[spatialite-tools] 01/08: Imported Upstream version 4.4.0~rc1

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat May 7 13:34:43 UTC 2016


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

sebastic pushed a commit to branch experimental
in repository spatialite-tools.

commit 58e2179a513a1b01dbf1e8236cf45c4cd5202213
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat May 7 14:37:29 2016 +0200

    Imported Upstream version 4.4.0~rc1
---
 Makefile-static-MinGW |   53 +-
 Makefile.am           |    5 +-
 Makefile.in           |   22 +-
 configure             |   20 +-
 configure.ac          |    2 +-
 makefile.vc           |   10 +-
 shp_sanitize.c        | 4321 +++++++++++++++++++++++++++++++++++++++++++++++++
 spatialite_osm_map.c  |   99 +-
 8 files changed, 4440 insertions(+), 92 deletions(-)

diff --git a/Makefile-static-MinGW b/Makefile-static-MinGW
index d278685..f5b74f4 100644
--- a/Makefile-static-MinGW
+++ b/Makefile-static-MinGW
@@ -11,7 +11,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/spatialite_osm_map.exe ./static_bin/spatialite_gml.exe \
 	./static_bin/spatialite_osm_raw.exe ./static_bin/spatialite_osm_filter.exe \
 	./static_bin/spatialite_convert.exe ./static_bin/spatialite_dxf.exe \
-	./static_bin/spatialite_osm_overpass.exe \
+	./static_bin/spatialite_osm_overpass.exe ./static_bin/shp_sanitize.exe \
 	./static_bin/spatialite_xml_collapse.exe \
 	./static_bin/spatialite_xml_validator.exe \
 	./static_bin/spatialite_xml_load.exe \
@@ -21,7 +21,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) shell.o -o ./static_bin/spatialite.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -38,7 +38,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/spatialite_tool.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -55,7 +55,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/spatialite_convert.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -72,7 +72,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/spatialite_dxf.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -88,7 +88,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_network.o -o ./static_bin/spatialite_network.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -104,7 +104,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) shp_doctor.o -o ./static_bin/shp_doctor.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -116,11 +116,27 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc
 	strip --strip-all ./static_bin/shp_doctor.exe
 	
+./static_bin/shp_sanitize.exe: shp_sanitize.o
+	$(GG) shp_sanitize.o -o ./static_bin/shp_sanitize.exe \
+	/usr/local/lib/libspatialite.a \
+	/usr/local/lib/libsqlite3.a \
+	/usr/local/lib/librttopo.a \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libproj.a \
+	/usr/local/lib/libgeos_c.a \
+	/usr/local/lib/libgeos.a \
+	/usr/local/lib/libfreexl.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc
+	strip --strip-all ./static_bin/shp_sanitize.exe
+	
 ./static_bin/exif_loader.exe: exif_loader.o
 	$(GG) exif_loader.o -o ./static_bin/exif_loader.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -136,7 +152,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_osm_net.o -o ./static_bin/spatialite_osm_net.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -154,7 +170,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_osm_map.o -o ./static_bin/spatialite_osm_map.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -172,7 +188,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_gml.o -o ./static_bin/spatialite_gml.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -189,7 +205,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_osm_raw.o -o ./static_bin/spatialite_osm_raw.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -207,7 +223,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_osm_filter.o -o ./static_bin/spatialite_osm_filter.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -223,7 +239,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_osm_overpass.o -o ./static_bin/spatialite_osm_overpass.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -239,7 +255,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_xml_collapse.o -o ./static_bin/spatialite_xml_collapse.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -264,7 +280,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_xml_load.o -o ./static_bin/spatialite_xml_load.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -281,7 +297,7 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	$(GG) spatialite_xml_print.o -o ./static_bin/spatialite_xml_print.exe \
 	/usr/local/lib/libspatialite.a \
 	/usr/local/lib/libsqlite3.a \
-	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/librttopo.a \
 	/usr/local/lib/libxml2.a \
 	/usr/local/lib/liblzma.a \
 	/usr/local/lib/libproj.a \
@@ -304,6 +320,9 @@ spatialite_network.o:
 
 shp_doctor.o:
 	$(CC) $(CFLAGS) shp_doctor.c -c
+
+shp_sanitize.o:
+	$(CC) $(CFLAGS) shp_sanitize.c -c
 	
 exif_loader.o:
 	$(CC) $(CFLAGS) exif_loader.c -c
diff --git a/Makefile.am b/Makefile.am
index 1bc4c7e..eb4ce16 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,7 @@ if NO_READOSM
 bin_PROGRAMS = spatialite \
 	spatialite_tool \
 	spatialite_network \
-	shp_doctor \
+	shp_doctor shp_sanitize \
 	exif_loader \
 	spatialite_osm_filter \
 	spatialite_gml \
@@ -19,7 +19,7 @@ else
 bin_PROGRAMS = spatialite \
 	spatialite_tool \
 	spatialite_network \
-	shp_doctor \
+	shp_doctor shp_sanitize \
 	exif_loader \
 	spatialite_osm_net \
 	spatialite_osm_map \
@@ -42,6 +42,7 @@ spatialite_SOURCES = shell.c
 spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
+shp_sanitize_SOURCES = shp_sanitize.c
 exif_loader_SOURCES = exif_loader.c
 spatialite_xml_validator_SOURCES = spatialite_xml_validator.c
 spatialite_xml_load_SOURCES = spatialite_xml_load.c
diff --git a/Makefile.in b/Makefile.in
index 13d46a6..4f30813 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -91,7 +91,8 @@ host_triplet = @host@
 @NO_READOSM_FALSE at bin_PROGRAMS = spatialite$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_tool$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_network$(EXEEXT) \
- at NO_READOSM_FALSE@	shp_doctor$(EXEEXT) exif_loader$(EXEEXT) \
+ at NO_READOSM_FALSE@	shp_doctor$(EXEEXT) shp_sanitize$(EXEEXT) \
+ at NO_READOSM_FALSE@	exif_loader$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_osm_net$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_osm_map$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_osm_raw$(EXEEXT) \
@@ -107,7 +108,8 @@ host_triplet = @host@
 @NO_READOSM_TRUE at bin_PROGRAMS = spatialite$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_tool$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_network$(EXEEXT) \
- at NO_READOSM_TRUE@	shp_doctor$(EXEEXT) exif_loader$(EXEEXT) \
+ at NO_READOSM_TRUE@	shp_doctor$(EXEEXT) shp_sanitize$(EXEEXT) \
+ at NO_READOSM_TRUE@	exif_loader$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_osm_filter$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_gml$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_convert$(EXEEXT) \
@@ -147,6 +149,10 @@ am_shp_doctor_OBJECTS = shp_doctor.$(OBJEXT)
 shp_doctor_OBJECTS = $(am_shp_doctor_OBJECTS)
 shp_doctor_LDADD = $(LDADD)
 shp_doctor_DEPENDENCIES =
+am_shp_sanitize_OBJECTS = shp_sanitize.$(OBJEXT)
+shp_sanitize_OBJECTS = $(am_shp_sanitize_OBJECTS)
+shp_sanitize_LDADD = $(LDADD)
+shp_sanitize_DEPENDENCIES =
 am_spatialite_OBJECTS = shell.$(OBJEXT)
 spatialite_OBJECTS = $(am_spatialite_OBJECTS)
 spatialite_DEPENDENCIES =
@@ -245,7 +251,8 @@ am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
-	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
+	$(shp_sanitize_SOURCES) $(spatialite_SOURCES) \
+	spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
 	$(spatialite_osm_filter_SOURCES) $(spatialite_osm_map_SOURCES) \
 	$(spatialite_osm_net_SOURCES) \
@@ -255,7 +262,8 @@ SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES) \
 	$(spatialite_xml_validator_SOURCES)
 DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
-	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
+	$(shp_sanitize_SOURCES) $(spatialite_SOURCES) \
+	spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
 	$(spatialite_osm_filter_SOURCES) \
 	$(am__spatialite_osm_map_SOURCES_DIST) \
@@ -454,6 +462,7 @@ spatialite_SOURCES = shell.c
 spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
+shp_sanitize_SOURCES = shp_sanitize.c
 exif_loader_SOURCES = exif_loader.c
 spatialite_xml_validator_SOURCES = spatialite_xml_validator.c
 spatialite_xml_load_SOURCES = spatialite_xml_load.c
@@ -612,6 +621,10 @@ shp_doctor$(EXEEXT): $(shp_doctor_OBJECTS) $(shp_doctor_DEPENDENCIES) $(EXTRA_sh
 	@rm -f shp_doctor$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(shp_doctor_OBJECTS) $(shp_doctor_LDADD) $(LIBS)
 
+shp_sanitize$(EXEEXT): $(shp_sanitize_OBJECTS) $(shp_sanitize_DEPENDENCIES) $(EXTRA_shp_sanitize_DEPENDENCIES) 
+	@rm -f shp_sanitize$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(shp_sanitize_OBJECTS) $(shp_sanitize_LDADD) $(LIBS)
+
 spatialite$(EXEEXT): $(spatialite_OBJECTS) $(spatialite_DEPENDENCIES) $(EXTRA_spatialite_DEPENDENCIES) 
 	@rm -f spatialite$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(spatialite_OBJECTS) $(spatialite_LDADD) $(LIBS)
@@ -681,6 +694,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/exif_loader.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shell.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shp_doctor.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/shp_sanitize.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_convert.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_dxf.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_gml.Po at am__quote@
diff --git a/configure b/configure
index a8835b2..825df87 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for spatialite-tools 4.4.0-RC0.
+# Generated by GNU Autoconf 2.69 for spatialite-tools 4.4.0-RC1.
 #
 # Report bugs to <a.furieri at lqt.it>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='spatialite-tools'
 PACKAGE_TARNAME='spatialite-tools'
-PACKAGE_VERSION='4.4.0-RC0'
-PACKAGE_STRING='spatialite-tools 4.4.0-RC0'
+PACKAGE_VERSION='4.4.0-RC1'
+PACKAGE_STRING='spatialite-tools 4.4.0-RC1'
 PACKAGE_BUGREPORT='a.furieri at lqt.it'
 PACKAGE_URL=''
 
@@ -1358,7 +1358,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures spatialite-tools 4.4.0-RC0 to adapt to many kinds of systems.
+\`configure' configures spatialite-tools 4.4.0-RC1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1429,7 +1429,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of spatialite-tools 4.4.0-RC0:";;
+     short | recursive ) echo "Configuration of spatialite-tools 4.4.0-RC1:";;
    esac
   cat <<\_ACEOF
 
@@ -1566,7 +1566,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-spatialite-tools configure 4.4.0-RC0
+spatialite-tools configure 4.4.0-RC1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2156,7 +2156,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by spatialite-tools $as_me 4.4.0-RC0, which was
+It was created by spatialite-tools $as_me 4.4.0-RC1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3027,7 +3027,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='spatialite-tools'
- VERSION='4.4.0-RC0'
+ VERSION='4.4.0-RC1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -18871,7 +18871,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by spatialite-tools $as_me 4.4.0-RC0, which was
+This file was extended by spatialite-tools $as_me 4.4.0-RC1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -18937,7 +18937,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-spatialite-tools config.status 4.4.0-RC0
+spatialite-tools config.status 4.4.0-RC1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 7fff3ec..ed864ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(spatialite-tools, 4.4.0-RC0, a.furieri at lqt.it)
+AC_INIT(spatialite-tools, 4.4.0-RC1, a.furieri at lqt.it)
 AC_LANG(C)
 AC_CONFIG_MACRO_DIR([m4])
 
diff --git a/makefile.vc b/makefile.vc
index 33c85d2..53ef751 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -7,6 +7,7 @@
 SPATIALITE_EXE            = spatialite.exe
 EXIF_LOADER_EXE           = exif_loader.exe
 SHP_DOCTOR_EXE            = shp_doctor.exe
+SHP_SANITIZE_EXE            = shp_sanitize.exe
 SPATIALITE_NETWORK_EXE    = spatialite_network.exe
 SPATIALITE_TOOL_EXE       = spatialite_tool.exe
 SPATIALITE_OSM_NET_EXE    = spatialite_osm_net.exe
@@ -23,7 +24,7 @@ all: $(SPATIALITE_EXE) $(SHP_DOCTOR_EXE) $(SPATIALITE_TOOL_EXE) \
 	$(SPATIALITE_NETWORK_EXE) $(EXIF_LOADER_EXE) \
 	$(SPATIALITE_OSM_NET_EXE) $(SPATIALITE_OSM_MAP_EXE) \
 	$(SPATIALITE_GML_EXE) $(SPATIALITE_OSM_RAW_EXE) \
-	$(SPATIALITE_OSM_FILTER_EXE)
+	$(SPATIALITE_OSM_FILTER_EXE) $(SHP_SANITIZE_EXE)
 
 $(SPATIALITE_EXE): shell.obj
 	cl shell.obj C:\OSGeo4W\lib\proj_i.lib \
@@ -47,6 +48,13 @@ $(SHP_DOCTOR_EXE):	shp_doctor.obj
 	if exist $(SHP_DOCTOR_EXE).manifest mt -manifest \
 		$(SHP_DOCTOR_EXE).manifest -outputresource:$(SHP_DOCTOR_EXE);1
 
+$(SHP_SANITIZE_EXE):	shp_sanitize.obj
+	cl shp_sanitize.obj  C:\OSGeo4W\lib\proj_i.lib \
+		C:\OSGeo4W\lib\iconv.lib C:\OSGeo4W\lib\geos_c.lib \
+		C:\OSGeo4W\lib\spatialite_i.lib C:\OSGeo4W\lib\sqlite3_i.lib 
+	if exist $(SHP_SANITIZE_EXE).manifest mt -manifest \
+		$(SHP_SANITIZE_EXE).manifest -outputresource:$(SHP_SANITIZE_EXE);1
+
 $(SPATIALITE_NETWORK_EXE):	spatialite_network.obj
 	cl spatialite_network.obj C:\OSGeo4W\lib\proj_i.lib \
 		C:\OSGeo4W\lib\iconv.lib \
diff --git a/shp_sanitize.c b/shp_sanitize.c
new file mode 100644
index 0000000..f56105f
--- /dev/null
+++ b/shp_sanitize.c
@@ -0,0 +1,4321 @@
+/* 
+/ shp_sanitize
+/
+/ an analysis / sanitizing tool for  broken SHAPEFILES
+/
+/ version 1.0, 2016 April 25
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2016  Alessandro Furieri
+/
+/    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/>.
+/
+*/
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <sys/types.h>
+#if defined(_WIN32) && !defined(__MINGW32__)
+#include <io.h>
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#include "config-msvc.h"
+#else
+#include "config.h"
+#endif
+
+#ifdef SPATIALITE_AMALGAMATION
+#include <spatialite/sqlite3.h>
+#else
+#include <sqlite3.h>
+#endif
+
+#include <spatialite/gaiageo.h>
+#include <spatialite.h>
+
+#define ARG_NONE		0
+#define ARG_IN_DIR		1
+#define ARG_OUT_DIR		2
+
+#define SUFFIX_DISCARD	0
+#define SUFFIX_SHP		1
+#define SUFFIX_SHX		2
+#define SUFFIX_DBF		3
+
+#define SHAPEFILE_NO_DATA 1e-38
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define strcasecmp	_stricmp
+#endif /* not WIN32 */
+
+struct shp_entry
+{
+/* an item of the SHP list */
+    char *base_name;
+    char *file_name;
+    int has_shp;
+    int has_shx;
+    int has_dbf;
+    struct shp_entry *next;
+};
+
+struct shp_list
+{
+/* the SHP list */
+    struct shp_entry *first;
+    struct shp_entry *last;
+};
+
+static struct shp_list *
+alloc_shp_list (void)
+{
+/* allocating an empty SHP list */
+    struct shp_list *list = malloc (sizeof (struct shp_list));
+    list->first = NULL;
+    list->last = NULL;
+    return list;
+}
+
+static void
+free_shp_list (struct shp_list *list)
+{
+/* memory cleanup: freeing an SHP list */
+    struct shp_entry *pi;
+    struct shp_entry *pin;
+    if (list == NULL)
+	return;
+
+    pi = list->first;
+    while (pi != NULL)
+      {
+	  pin = pi->next;
+	  if (pi->base_name != NULL)
+	      sqlite3_free (pi->base_name);
+	  if (pi->file_name != NULL)
+	      sqlite3_free (pi->file_name);
+	  free (pi);
+	  pi = pin;
+      }
+    free (list);
+}
+
+static void
+do_add_shapefile (struct shp_list *list, char *base_name, char *file_name,
+		  int suffix)
+{
+/* adding a possible SHP to the list */
+    struct shp_entry *pi;
+    if (list == NULL)
+	return;
+
+    pi = list->first;
+    while (pi != NULL)
+      {
+	  /* searching if already defined */
+	  if (strcmp (pi->base_name, base_name) == 0)
+	    {
+		switch (suffix)
+		  {
+		  case SUFFIX_SHP:
+		      pi->has_shp = 1;
+		      break;
+		  case SUFFIX_SHX:
+		      pi->has_shx = 1;
+		      break;
+		  case SUFFIX_DBF:
+		      pi->has_dbf = 1;
+		      break;
+		  };
+		sqlite3_free (base_name);
+		sqlite3_free (file_name);
+		return;
+	    }
+	  pi = pi->next;
+      }
+
+/* adding a new SHP entry */
+    pi = malloc (sizeof (struct shp_entry));
+    pi->base_name = base_name;
+    pi->file_name = file_name;
+    pi->has_shp = 0;
+    pi->has_shx = 0;
+    pi->has_dbf = 0;
+    pi->next = NULL;
+
+    switch (suffix)
+      {
+      case SUFFIX_SHP:
+	  pi->has_shp = 1;
+	  break;
+      case SUFFIX_SHX:
+	  pi->has_shx = 1;
+	  break;
+      case SUFFIX_DBF:
+	  pi->has_dbf = 1;
+	  break;
+      };
+
+    if (list->first == NULL)
+	list->first = pi;
+    if (list->last != NULL)
+	list->last->next = pi;
+    list->last = pi;
+}
+
+static int
+test_valid_shp (struct shp_entry *p)
+{
+/* testing for a valid SHP candidate */
+    if (p == NULL)
+	return 0;
+    if (p->has_shp && p->has_shx && p->has_dbf)
+	return 1;
+    return 0;
+}
+
+static gaiaShapefilePtr
+allocShapefile ()
+{
+/* allocates and initializes the Shapefile object */
+    gaiaShapefilePtr shp = malloc (sizeof (gaiaShapefile));
+    shp->endian_arch = 1;
+    shp->Path = NULL;
+    shp->Shape = -1;
+    shp->EffectiveType = GAIA_UNKNOWN;
+    shp->EffectiveDims = GAIA_XY;
+    shp->flShp = NULL;
+    shp->flShx = NULL;
+    shp->flDbf = NULL;
+    shp->Dbf = NULL;
+    shp->ShpBfsz = 0;
+    shp->BufShp = NULL;
+    shp->BufDbf = NULL;
+    shp->DbfHdsz = 0;
+    shp->DbfReclen = 0;
+    shp->DbfSize = 0;
+    shp->DbfRecno = 0;
+    shp->ShpSize = 0;
+    shp->ShxSize = 0;
+    shp->MinX = DBL_MAX;
+    shp->MinY = DBL_MAX;
+    shp->MaxX = -DBL_MAX;
+    shp->MaxY = -DBL_MAX;
+    shp->Valid = 0;
+    shp->IconvObj = NULL;
+    shp->LastError = NULL;
+    return shp;
+}
+
+static void
+freeShapefile (gaiaShapefilePtr shp)
+{
+/* frees all memory allocations related to the Shapefile object */
+    if (shp->Path)
+	free (shp->Path);
+    if (shp->flShp)
+	fclose (shp->flShp);
+    if (shp->flShx)
+	fclose (shp->flShx);
+    if (shp->flDbf)
+	fclose (shp->flDbf);
+    if (shp->Dbf)
+	gaiaFreeDbfList (shp->Dbf);
+    if (shp->BufShp)
+	free (shp->BufShp);
+    if (shp->BufDbf)
+	free (shp->BufDbf);
+    if (shp->LastError)
+	free (shp->LastError);
+    free (shp);
+}
+
+static void
+openShpRead (gaiaShapefilePtr shp, const char *path, double *MinX, double *MinY,
+	     double *MaxX, double *MaxY, int *mismatching)
+{
+/* trying to open the shapefile and initial checkings */
+    FILE *fl_shx = NULL;
+    FILE *fl_shp = NULL;
+    FILE *fl_dbf = NULL;
+    char xpath[1024];
+    int rd;
+    unsigned char buf_shx[256];
+    unsigned char *buf_shp = NULL;
+    int buf_size = 1024;
+    int shape;
+    unsigned char bf[1024];
+    int dbf_size;
+    int dbf_reclen = 0;
+    int off_dbf;
+    int ind;
+    char field_name[2048];
+    char *sys_err;
+    char errMsg[1024];
+    double minx;
+    double miny;
+    double maxx;
+    double maxy;
+    int len;
+    int endian_arch = gaiaEndianArch ();
+    gaiaDbfListPtr dbf_list = NULL;
+    if (shp->flShp != NULL || shp->flShx != NULL || shp->flDbf != NULL)
+      {
+	  sprintf (errMsg,
+		   "attempting to reopen an already opened Shapefile\n");
+	  goto unsupported_conversion;
+      }
+    sprintf (xpath, "%s.shx", path);
+    fl_shx = fopen (xpath, "rb");
+    if (!fl_shx)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for reading: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+    sprintf (xpath, "%s.shp", path);
+    fl_shp = fopen (xpath, "rb");
+    if (!fl_shp)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for reading: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+    sprintf (xpath, "%s.dbf", path);
+    fl_dbf = fopen (xpath, "rb");
+    if (!fl_dbf)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for reading: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+/* reading SHX file header */
+    rd = fread (buf_shx, sizeof (unsigned char), 100, fl_shx);
+    if (rd != 100)
+	goto error;
+    if (gaiaImport32 (buf_shx + 0, GAIA_BIG_ENDIAN, endian_arch) != 9994)	/* checks the SHX magic number */
+	goto error;
+    *MinX = gaiaImport64 (buf_shx + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+    *MinY = gaiaImport64 (buf_shx + 44, GAIA_LITTLE_ENDIAN, endian_arch);
+    *MaxX = gaiaImport64 (buf_shx + 52, GAIA_LITTLE_ENDIAN, endian_arch);
+    *MaxY = gaiaImport64 (buf_shx + 60, GAIA_LITTLE_ENDIAN, endian_arch);
+/* reading SHP file header */
+    buf_shp = malloc (sizeof (unsigned char) * buf_size);
+    rd = fread (buf_shp, sizeof (unsigned char), 100, fl_shp);
+    if (rd != 100)
+	goto error;
+    if (gaiaImport32 (buf_shp + 0, GAIA_BIG_ENDIAN, endian_arch) != 9994)	/* checks the SHP magic number */
+	goto error;
+    minx = gaiaImport64 (buf_shp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+    miny = gaiaImport64 (buf_shp + 44, GAIA_LITTLE_ENDIAN, endian_arch);
+    maxx = gaiaImport64 (buf_shp + 52, GAIA_LITTLE_ENDIAN, endian_arch);
+    maxy = gaiaImport64 (buf_shp + 60, GAIA_LITTLE_ENDIAN, endian_arch);
+    *mismatching = 0;
+    if (*MinX != minx || *MinY != miny || *MaxX != maxx || *MaxY != maxy)
+      {
+	  fprintf (stderr,
+		   "\t\tHEADERS: found mismatching BBOX between .shx and .shp\n");
+	  *mismatching = 1;
+      }
+    shape = gaiaImport32 (buf_shp + 32, GAIA_LITTLE_ENDIAN, endian_arch);
+    if (shape == GAIA_SHP_POINT || shape == GAIA_SHP_POINTZ
+	|| shape == GAIA_SHP_POINTM || shape == GAIA_SHP_POLYLINE
+	|| shape == GAIA_SHP_POLYLINEZ || shape == GAIA_SHP_POLYLINEM
+	|| shape == GAIA_SHP_POLYGON || shape == GAIA_SHP_POLYGONZ
+	|| shape == GAIA_SHP_POLYGONM || shape == GAIA_SHP_MULTIPOINT
+	|| shape == GAIA_SHP_MULTIPOINTZ || shape == GAIA_SHP_MULTIPOINTM)
+	;
+    else
+	goto unsupported;
+/* reading DBF file header */
+    rd = fread (bf, sizeof (unsigned char), 32, fl_dbf);
+    if (rd != 32)
+	goto error;
+    switch (*bf)
+      {
+	  /* checks the DBF magic number */
+      case 0x03:
+      case 0x83:
+	  break;
+      case 0x02:
+      case 0xF8:
+	  sprintf (errMsg, "'%s'\ninvalid magic number %02x [FoxBASE format]",
+		   path, *bf);
+	  goto dbf_bad_magic;
+      case 0xF5:
+	  sprintf (errMsg,
+		   "'%s'\ninvalid magic number %02x [FoxPro 2.x (or earlier) format]",
+		   path, *bf);
+	  goto dbf_bad_magic;
+      case 0x30:
+      case 0x31:
+      case 0x32:
+	  sprintf (errMsg,
+		   "'%s'\ninvalid magic number %02x [Visual FoxPro format]",
+		   path, *bf);
+	  goto dbf_bad_magic;
+      case 0x43:
+      case 0x63:
+      case 0xBB:
+      case 0xCB:
+	  sprintf (errMsg, "'%s'\ninvalid magic number %02x [dBASE IV format]",
+		   path, *bf);
+	  goto dbf_bad_magic;
+      default:
+	  sprintf (errMsg, "'%s'\ninvalid magic number %02x [unknown format]",
+		   path, *bf);
+	  goto dbf_bad_magic;
+      };
+    dbf_size = gaiaImport16 (bf + 8, GAIA_LITTLE_ENDIAN, endian_arch);
+    dbf_reclen = gaiaImport16 (bf + 10, GAIA_LITTLE_ENDIAN, endian_arch);
+    dbf_size--;
+    off_dbf = 0;
+    dbf_list = gaiaAllocDbfList ();
+    for (ind = 32; ind < dbf_size; ind += 32)
+      {
+	  /* fetches DBF fields definitions */
+	  rd = fread (bf, sizeof (unsigned char), 32, fl_dbf);
+	  if (rd != 32)
+	      goto error;
+	  if (*(bf + 11) == 'M')
+	    {
+		/* skipping any MEMO field */
+		memcpy (field_name, bf, 11);
+		field_name[11] = '\0';
+		off_dbf += *(bf + 16);
+		fprintf (stderr,
+			 "WARNING: column \"%s\" is of the MEMO type and will be ignored\n",
+			 field_name);
+		continue;
+	    }
+	  memcpy (field_name, bf, 11);
+	  field_name[11] = '\0';
+	  gaiaAddDbfField (dbf_list, field_name, *(bf + 11), off_dbf,
+			   *(bf + 16), *(bf + 17));
+	  off_dbf += *(bf + 16);
+      }
+    if (!gaiaIsValidDbfList (dbf_list))
+      {
+	  /* invalid DBF */
+	  goto illegal_dbf;
+      }
+    len = strlen (path);
+    shp->Path = malloc (len + 1);
+    strcpy (shp->Path, path);
+    shp->ReadOnly = 1;
+    shp->Shape = shape;
+    switch (shape)
+      {
+	  /* setting up a prudential geometry type */
+      case GAIA_SHP_POINT:
+      case GAIA_SHP_POINTZ:
+      case GAIA_SHP_POINTM:
+	  shp->EffectiveType = GAIA_POINT;
+	  break;
+      case GAIA_SHP_POLYLINE:
+      case GAIA_SHP_POLYLINEZ:
+      case GAIA_SHP_POLYLINEM:
+	  shp->EffectiveType = GAIA_MULTILINESTRING;
+	  break;
+      case GAIA_SHP_POLYGON:
+      case GAIA_SHP_POLYGONZ:
+      case GAIA_SHP_POLYGONM:
+	  shp->EffectiveType = GAIA_MULTIPOLYGON;
+	  break;
+      case GAIA_SHP_MULTIPOINT:
+      case GAIA_SHP_MULTIPOINTZ:
+      case GAIA_SHP_MULTIPOINTM:
+	  shp->EffectiveType = GAIA_MULTIPOINT;
+	  break;
+      }
+    switch (shape)
+      {
+	  /* setting up a prudential dimension model */
+      case GAIA_SHP_POINTZ:
+      case GAIA_SHP_POLYLINEZ:
+      case GAIA_SHP_POLYGONZ:
+      case GAIA_SHP_MULTIPOINTZ:
+	  shp->EffectiveDims = GAIA_XY_Z_M;
+	  break;
+      case GAIA_SHP_POINTM:
+      case GAIA_SHP_POLYLINEM:
+      case GAIA_SHP_POLYGONM:
+      case GAIA_SHP_MULTIPOINTM:
+	  shp->EffectiveDims = GAIA_XY_M;
+	  break;
+      default:
+	  shp->EffectiveDims = GAIA_XY;
+	  break;
+      }
+    shp->flShp = fl_shp;
+    shp->flShx = fl_shx;
+    shp->flDbf = fl_dbf;
+    shp->Dbf = dbf_list;
+/* saving the SHP buffer */
+    shp->BufShp = buf_shp;
+    shp->ShpBfsz = buf_size;
+/* allocating DBF buffer */
+    shp->BufDbf = malloc (sizeof (unsigned char) * dbf_reclen);
+    shp->DbfHdsz = dbf_size + 1;
+    shp->DbfReclen = dbf_reclen;
+    shp->Valid = 1;
+    shp->endian_arch = endian_arch;
+    return;
+  unsupported_conversion:
+/* illegal charset */
+    if (shp->LastError)
+	free (shp->LastError);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    return;
+  no_file:
+/* one of shapefile's files can't be accessed */
+    if (shp->LastError)
+	free (shp->LastError);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    if (fl_shx)
+	fclose (fl_shx);
+    if (fl_shp)
+	fclose (fl_shp);
+    if (fl_dbf)
+	fclose (fl_dbf);
+    return;
+  dbf_bad_magic:
+/* the DBF has an invalid magin number */
+    if (shp->LastError)
+	free (shp->LastError);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    gaiaFreeDbfList (dbf_list);
+    if (buf_shp)
+	free (buf_shp);
+    fclose (fl_shx);
+    fclose (fl_shp);
+    fclose (fl_dbf);
+    return;
+  error:
+/* the shapefile is invalid or corrupted */
+    if (shp->LastError)
+	free (shp->LastError);
+    sprintf (errMsg, "'%s' is corrupted / has invalid format", path);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    gaiaFreeDbfList (dbf_list);
+    if (buf_shp)
+	free (buf_shp);
+    fclose (fl_shx);
+    fclose (fl_shp);
+    fclose (fl_dbf);
+    return;
+  unsupported:
+/* the shapefile has an unrecognized shape type */
+    if (shp->LastError)
+	free (shp->LastError);
+    sprintf (errMsg, "'%s' shape=%d is not supported", path, shape);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    gaiaFreeDbfList (dbf_list);
+    if (buf_shp)
+	free (buf_shp);
+    fclose (fl_shx);
+    fclose (fl_shp);
+    if (fl_dbf)
+	fclose (fl_dbf);
+    return;
+  illegal_dbf:
+/* the DBF-file contains unsupported data types */
+    if (shp->LastError)
+	free (shp->LastError);
+    sprintf (errMsg, "'%s.dbf' contains unsupported data types", path);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    gaiaFreeDbfList (dbf_list);
+    if (buf_shp)
+	free (buf_shp);
+    fclose (fl_shx);
+    fclose (fl_shp);
+    if (fl_dbf)
+	fclose (fl_dbf);
+    return;
+}
+
+static int
+readShpEntity (gaiaShapefilePtr shp, int current_row, int *shplen, double *minx,
+	       double *miny, double *maxx, double *maxy)
+{
+/* trying to read an entity from shapefile */
+    unsigned char buf[512];
+    int len;
+    int rd;
+    int skpos;
+    int offset;
+    int off_shp;
+    int sz;
+    char errMsg[1024];
+    int shape;
+    int endian_arch = gaiaEndianArch ();
+
+/* positioning and reading the SHX file */
+    offset = 100 + (current_row * 8);	/* 100 bytes for the header + current row displacement; each SHX row = 8 bytes */
+    skpos = fseek (shp->flShx, offset, SEEK_SET);
+    if (skpos != 0)
+	goto eof;
+    rd = fread (buf, sizeof (unsigned char), 8, shp->flShx);
+    if (rd != 8)
+	goto eof;
+    off_shp = gaiaImport32 (buf, GAIA_BIG_ENDIAN, shp->endian_arch);
+/* positioning and reading the DBF file */
+    offset = shp->DbfHdsz + (current_row * shp->DbfReclen);
+    skpos = fseek (shp->flDbf, offset, SEEK_SET);
+    if (skpos != 0)
+	goto error;
+    rd = fread (shp->BufDbf, sizeof (unsigned char), shp->DbfReclen,
+		shp->flDbf);
+    if (rd != shp->DbfReclen)
+	goto error;
+    if (*(shp->BufDbf) == '*')
+	goto dbf_deleted;
+/* positioning and reading corresponding SHP entity - geometry */
+    offset = off_shp * 2;
+    skpos = fseek (shp->flShp, offset, SEEK_SET);
+    if (skpos != 0)
+	goto error;
+    rd = fread (buf, sizeof (unsigned char), 8, shp->flShp);
+    if (rd != 8)
+	goto error;
+    sz = gaiaImport32 (buf + 4, GAIA_BIG_ENDIAN, shp->endian_arch);
+    if ((sz * 2) > shp->ShpBfsz)
+      {
+	  /* current buffer is too small; we need to allocate a bigger buffer */
+	  free (shp->BufShp);
+	  shp->ShpBfsz = sz * 2;
+	  shp->BufShp = malloc (sizeof (unsigned char) * shp->ShpBfsz);
+      }
+    /* reading the raw Geometry */
+    rd = fread (shp->BufShp, sizeof (unsigned char), sz * 2, shp->flShp);
+    if (rd != sz * 2)
+	goto error;
+    *shplen = rd;
+
+/* retrieving the feature's BBOX */
+    shape = gaiaImport32 (shp->BufShp + 0, GAIA_LITTLE_ENDIAN, endian_arch);
+    *minx = DBL_MAX;
+    *miny = DBL_MAX;
+    *maxx = DBL_MAX;
+    *maxy = DBL_MAX;
+    if (shape == GAIA_SHP_POINT || shape == GAIA_SHP_POINTZ
+	|| shape == GAIA_SHP_POINTM)
+      {
+	  *minx =
+	      gaiaImport64 (shp->BufShp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  *maxx = *minx;
+	  *miny =
+	      gaiaImport64 (shp->BufShp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  *maxy = *miny;
+      }
+    if (shape == GAIA_SHP_POLYLINE || shape == GAIA_SHP_POLYLINEZ
+	|| shape == GAIA_SHP_POLYLINEM || shape == GAIA_SHP_POLYGON
+	|| shape == GAIA_SHP_POLYGONZ || shape == GAIA_SHP_POLYGONM
+	|| shape == GAIA_SHP_MULTIPOINT || shape == GAIA_SHP_MULTIPOINTZ
+	|| shape == GAIA_SHP_MULTIPOINTM)
+      {
+	  *minx =
+	      gaiaImport64 (shp->BufShp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  *miny =
+	      gaiaImport64 (shp->BufShp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  *maxx =
+	      gaiaImport64 (shp->BufShp + 20, GAIA_LITTLE_ENDIAN, endian_arch);
+	  *maxy =
+	      gaiaImport64 (shp->BufShp + 28, GAIA_LITTLE_ENDIAN, endian_arch);
+      }
+    return 1;
+
+  eof:
+    if (shp->LastError)
+	free (shp->LastError);
+    shp->LastError = NULL;
+    return 0;
+  error:
+    if (shp->LastError)
+	free (shp->LastError);
+    sprintf (errMsg, "'%s' is corrupted / has invalid format", shp->Path);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    return 0;
+  dbf_deleted:
+    if (shp->LastError)
+	free (shp->LastError);
+    shp->LastError = NULL;
+    return -1;
+}
+
+struct shp_ring_item
+{
+/* a RING item [to be reassembled into a (Multi)Polygon] */
+    gaiaRingPtr Ring;
+    int IsExterior;
+    gaiaRingPtr Mother;
+    struct shp_ring_item *Next;
+};
+
+struct shp_ring_collection
+{
+/* a collection of RING items */
+    struct shp_ring_item *First;
+    struct shp_ring_item *Last;
+};
+
+static void
+shp_free_rings (struct shp_ring_collection *ringsColl)
+{
+/* memory cleanup: rings collection */
+    struct shp_ring_item *p;
+    struct shp_ring_item *pN;
+    p = ringsColl->First;
+    while (p)
+      {
+	  pN = p->Next;
+	  if (p->Ring)
+	      gaiaFreeRing (p->Ring);
+	  free (p);
+	  p = pN;
+      }
+}
+
+static void
+shp_add_ring (struct shp_ring_collection *ringsColl, gaiaRingPtr ring)
+{
+/* inserting a ring into the rings collection */
+    struct shp_ring_item *p = malloc (sizeof (struct shp_ring_item));
+    p->Ring = ring;
+    gaiaMbrRing (ring);
+    gaiaClockwise (ring);
+/* accordingly to SHP rules interior/exterior depends on direction */
+    p->IsExterior = ring->Clockwise;
+    p->Mother = NULL;
+    p->Next = NULL;
+/* updating the linked list */
+    if (ringsColl->First == NULL)
+	ringsColl->First = p;
+    if (ringsColl->Last != NULL)
+	ringsColl->Last->Next = p;
+    ringsColl->Last = p;
+}
+
+static int
+shp_check_rings (gaiaRingPtr exterior, gaiaRingPtr candidate)
+{
+/* 
+/ speditively checks if the candidate could be an interior Ring
+/ contained into the exterior Ring
+*/
+    double z;
+    double m;
+    double x0;
+    double y0;
+    double x1;
+    double y1;
+    int mid;
+    int ret0;
+    int ret1;
+    if (candidate->DimensionModel == GAIA_XY_Z)
+      {
+	  gaiaGetPointXYZ (candidate->Coords, 0, &x0, &y0, &z);
+      }
+    else if (candidate->DimensionModel == GAIA_XY_M)
+      {
+	  gaiaGetPointXYM (candidate->Coords, 0, &x0, &y0, &m);
+      }
+    else if (candidate->DimensionModel == GAIA_XY_Z_M)
+      {
+	  gaiaGetPointXYZM (candidate->Coords, 0, &x0, &y0, &z, &m);
+      }
+    else
+      {
+	  gaiaGetPoint (candidate->Coords, 0, &x0, &y0);
+      }
+    mid = candidate->Points / 2;
+    if (candidate->DimensionModel == GAIA_XY_Z)
+      {
+	  gaiaGetPointXYZ (candidate->Coords, mid, &x1, &y1, &z);
+      }
+    else if (candidate->DimensionModel == GAIA_XY_M)
+      {
+	  gaiaGetPointXYM (candidate->Coords, mid, &x1, &y1, &m);
+      }
+    else if (candidate->DimensionModel == GAIA_XY_Z_M)
+      {
+	  gaiaGetPointXYZM (candidate->Coords, mid, &x1, &y1, &z, &m);
+      }
+    else
+      {
+	  gaiaGetPoint (candidate->Coords, mid, &x1, &y1);
+      }
+
+/* testing if the first point falls on the exterior ring surface */
+    ret0 = gaiaIsPointOnRingSurface (exterior, x0, y0);
+/* testing if the second point falls on the exterior ring surface */
+    ret1 = gaiaIsPointOnRingSurface (exterior, x1, y1);
+    if (ret0 || ret1)
+	return 1;
+    return 0;
+}
+
+static int
+shp_mbr_contains (gaiaRingPtr r1, gaiaRingPtr r2)
+{
+/* checks if the first Ring contains the second one - MBR based */
+    int ok_1 = 0;
+    int ok_2 = 0;
+    int ok_3 = 0;
+    int ok_4 = 0;
+    if (r2->MinX >= r1->MinX && r2->MinX <= r1->MaxX)
+	ok_1 = 1;
+    if (r2->MaxX >= r1->MinX && r2->MaxX <= r1->MaxX)
+	ok_2 = 1;
+    if (r2->MinY >= r1->MinY && r2->MinY <= r1->MaxY)
+	ok_3 = 1;
+    if (r2->MaxY >= r1->MinY && r2->MaxY <= r1->MaxY)
+	ok_4 = 1;
+    if (ok_1 && ok_2 && ok_3 && ok_4)
+	return 1;
+    return 0;
+}
+
+static void
+shp_arrange_rings (struct shp_ring_collection *ringsColl)
+{
+/* 
+/ arranging Rings so to associate any interior ring
+/ to the containing exterior ring
+*/
+    struct shp_ring_item *pInt;
+    struct shp_ring_item *pExt;
+    pExt = ringsColl->First;
+    while (pExt != NULL)
+      {
+	  /* looping on Exterior Rings */
+	  if (pExt->IsExterior)
+	    {
+		pInt = ringsColl->First;
+		while (pInt != NULL)
+		  {
+		      /* looping on Interior Rings */
+		      if (pInt->IsExterior == 0 && pInt->Mother == NULL
+			  && shp_mbr_contains (pExt->Ring, pInt->Ring))
+			{
+			    /* ok, matches */
+			    if (shp_check_rings (pExt->Ring, pInt->Ring))
+				pInt->Mother = pExt->Ring;
+			}
+		      pInt = pInt->Next;
+		  }
+	    }
+	  pExt = pExt->Next;
+      }
+    pExt = ringsColl->First;
+    while (pExt != NULL)
+      {
+	  if (pExt->IsExterior == 0 && pExt->Mother == NULL)
+	    {
+		/* orphan ring: promoting to Exterior */
+		pExt->IsExterior = 1;
+	    }
+	  pExt = pExt->Next;
+      }
+}
+
+static void
+shp_build_area (struct shp_ring_collection *ringsColl, gaiaGeomCollPtr geom)
+{
+/* building the final (Multi)Polygon Geometry */
+    gaiaPolygonPtr polyg;
+    struct shp_ring_item *pExt;
+    struct shp_ring_item *pInt;
+    pExt = ringsColl->First;
+    while (pExt != NULL)
+      {
+	  if (pExt->IsExterior)
+	    {
+		/* creating a new Polygon */
+		polyg = gaiaInsertPolygonInGeomColl (geom, pExt->Ring);
+		pInt = ringsColl->First;
+		while (pInt != NULL)
+		  {
+		      if (pExt->Ring == pInt->Mother)
+			{
+			    /* adding an interior ring to current POLYGON */
+			    gaiaAddRingToPolyg (polyg, pInt->Ring);
+			    /* releasing Ring ownership */
+			    pInt->Ring = NULL;
+			}
+		      pInt = pInt->Next;
+		  }
+		/* releasing Ring ownership */
+		pExt->Ring = NULL;
+	    }
+	  pExt = pExt->Next;
+      }
+}
+
+static gaiaGeomCollPtr
+do_parse_geometry (const unsigned char *bufshp, int buflen, int eff_dims,
+		   int eff_type, int *nullshape)
+{
+/* attempting to parse a Geometry from the SHP */
+    gaiaGeomCollPtr geom = NULL;
+    int shape;
+    double x;
+    double y;
+    double z;
+    double m;
+    int points;
+    int n;
+    int n1;
+    int base;
+    int baseZ;
+    int baseM;
+    int start;
+    int end;
+    int iv;
+    int ind;
+    int max_size;
+    int min_size;
+    int hasM;
+    int sz;
+    gaiaLinestringPtr line = NULL;
+    gaiaRingPtr ring = NULL;
+    int endian_arch = gaiaEndianArch ();
+    struct shp_ring_collection ringsColl;
+/* initializing the RING collection */
+    ringsColl.First = NULL;
+    ringsColl.Last = NULL;
+
+    shape = gaiaImport32 (bufshp + 0, GAIA_LITTLE_ENDIAN, endian_arch);
+    if (shape == GAIA_SHP_NULL)
+      {
+	  *nullshape = 1;
+	  return NULL;
+      }
+    *nullshape = 0;
+
+    if (shape == GAIA_SHP_POINT)
+      {
+	  /* shape point */
+	  x = gaiaImport64 (bufshp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  y = gaiaImport64 (bufshp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (eff_dims == GAIA_XY_Z)
+	    {
+		geom = gaiaAllocGeomCollXYZ ();
+		gaiaAddPointToGeomCollXYZ (geom, x, y, 0.0);
+	    }
+	  else if (eff_dims == GAIA_XY_M)
+	    {
+		geom = gaiaAllocGeomCollXYM ();
+		gaiaAddPointToGeomCollXYM (geom, x, y, 0.0);
+	    }
+	  else if (eff_dims == GAIA_XY_Z_M)
+	    {
+		geom = gaiaAllocGeomCollXYZM ();
+		gaiaAddPointToGeomCollXYZM (geom, x, y, 0.0, 0.0);
+	    }
+	  else
+	    {
+		geom = gaiaAllocGeomColl ();
+		gaiaAddPointToGeomColl (geom, x, y);
+	    }
+	  geom->DeclaredType = GAIA_POINT;
+      }
+    if (shape == GAIA_SHP_POINTZ)
+      {
+	  /* shape point Z */
+	  x = gaiaImport64 (bufshp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  y = gaiaImport64 (bufshp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  z = gaiaImport64 (bufshp + 20, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (buflen == 28)
+	      m = 0.0;
+	  else
+	      m = gaiaImport64 (bufshp + 28, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (eff_dims == GAIA_XY_Z)
+	    {
+		geom = gaiaAllocGeomCollXYZ ();
+		gaiaAddPointToGeomCollXYZ (geom, x, y, z);
+	    }
+	  else if (eff_dims == GAIA_XY_M)
+	    {
+		geom = gaiaAllocGeomCollXYM ();
+		gaiaAddPointToGeomCollXYM (geom, x, y, m);
+	    }
+	  else if (eff_dims == GAIA_XY_Z_M)
+	    {
+		geom = gaiaAllocGeomCollXYZM ();
+		gaiaAddPointToGeomCollXYZM (geom, x, y, z, m);
+	    }
+	  else
+	    {
+		geom = gaiaAllocGeomColl ();
+		gaiaAddPointToGeomColl (geom, x, y);
+	    }
+	  geom->DeclaredType = GAIA_POINT;
+      }
+    if (shape == GAIA_SHP_POINTM)
+      {
+	  /* shape point M */
+	  x = gaiaImport64 (bufshp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  y = gaiaImport64 (bufshp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  m = gaiaImport64 (bufshp + 20, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (eff_dims == GAIA_XY_Z)
+	    {
+		geom = gaiaAllocGeomCollXYZ ();
+		gaiaAddPointToGeomCollXYZ (geom, x, y, 0.0);
+	    }
+	  else if (eff_dims == GAIA_XY_M)
+	    {
+		geom = gaiaAllocGeomCollXYM ();
+		gaiaAddPointToGeomCollXYM (geom, x, y, m);
+	    }
+	  else if (eff_dims == GAIA_XY_Z_M)
+	    {
+		geom = gaiaAllocGeomCollXYZM ();
+		gaiaAddPointToGeomCollXYZM (geom, x, y, 0.0, m);
+	    }
+	  else
+	    {
+		geom = gaiaAllocGeomColl ();
+		gaiaAddPointToGeomColl (geom, x, y);
+	    }
+	  geom->DeclaredType = GAIA_POINT;
+      }
+    if (shape == GAIA_SHP_POLYLINE)
+      {
+	  /* shape polyline */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  base = 44 + (n * 4);
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    line = gaiaAllocLinestringXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    line = gaiaAllocLinestringXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    line = gaiaAllocLinestringXYZM (points);
+		else
+		    line = gaiaAllocLinestring (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (line->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (line->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (line->Coords, points, x, y,
+					      0.0, 0.0);
+			}
+		      else
+			{
+			    gaiaSetPoint (line->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		if (!geom)
+		  {
+		      if (eff_dims == GAIA_XY_Z)
+			  geom = gaiaAllocGeomCollXYZ ();
+		      else if (eff_dims == GAIA_XY_M)
+			  geom = gaiaAllocGeomCollXYM ();
+		      else if (eff_dims == GAIA_XY_Z_M)
+			  geom = gaiaAllocGeomCollXYZM ();
+		      else
+			  geom = gaiaAllocGeomColl ();
+		      if (eff_type == GAIA_LINESTRING)
+			  geom->DeclaredType = GAIA_LINESTRING;
+		      else
+			  geom->DeclaredType = GAIA_MULTILINESTRING;
+		  }
+		gaiaInsertLinestringInGeomColl (geom, line);
+	    }
+      }
+    if (shape == GAIA_SHP_POLYLINEZ)
+      {
+	  /* shape polyline Z */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 38 + (2 * n) + (n1 * 16);	/* size [in 16 bits words !!!] ZM */
+	  min_size = 30 + (2 * n) + (n1 * 12);	/* size [in 16 bits words !!!] Z-only */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  base = 44 + (n * 4);
+	  baseZ = base + (n1 * 16) + 16;
+	  baseM = baseZ + (n1 * 8) + 16;
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    line = gaiaAllocLinestringXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    line = gaiaAllocLinestringXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    line = gaiaAllocLinestringXYZM (points);
+		else
+		    line = gaiaAllocLinestring (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      z = gaiaImport64 (bufshp + baseZ + (iv * 8),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (hasM)
+			  m = gaiaImport64 (bufshp + baseM +
+					    (iv * 8), GAIA_LITTLE_ENDIAN,
+					    endian_arch);
+		      else
+			  m = 0.0;
+		      if (m < SHAPEFILE_NO_DATA)
+			  m = 0.0;
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (line->Coords, points, x, y, z);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (line->Coords, points, x, y, m);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (line->Coords, points, x, y, z, m);
+			}
+		      else
+			{
+			    gaiaSetPoint (line->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		if (!geom)
+		  {
+		      if (eff_dims == GAIA_XY_Z)
+			  geom = gaiaAllocGeomCollXYZ ();
+		      else if (eff_dims == GAIA_XY_M)
+			  geom = gaiaAllocGeomCollXYM ();
+		      else if (eff_dims == GAIA_XY_Z_M)
+			  geom = gaiaAllocGeomCollXYZM ();
+		      else
+			  geom = gaiaAllocGeomColl ();
+		      if (eff_type == GAIA_LINESTRING)
+			  geom->DeclaredType = GAIA_LINESTRING;
+		      else
+			  geom->DeclaredType = GAIA_MULTILINESTRING;
+		  }
+		gaiaInsertLinestringInGeomColl (geom, line);
+	    }
+      }
+    if (shape == GAIA_SHP_POLYLINEM)
+      {
+	  /* shape polyline M */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 30 + (2 * n) + (n1 * 12);	/* size [in 16 bits words !!!] M */
+	  min_size = 22 + (2 * n) + (n1 * 8);	/* size [in 16 bits words !!!] no-M */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  base = 44 + (n * 4);
+	  baseM = base + (n1 * 16) + 16;
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    line = gaiaAllocLinestringXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    line = gaiaAllocLinestringXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    line = gaiaAllocLinestringXYZM (points);
+		else
+		    line = gaiaAllocLinestring (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (hasM)
+			  m = gaiaImport64 (bufshp + baseM +
+					    (iv * 8), GAIA_LITTLE_ENDIAN,
+					    endian_arch);
+		      else
+			  m = 0.0;
+		      if (m < SHAPEFILE_NO_DATA)
+			  m = 0.0;
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (line->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (line->Coords, points, x, y, m);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (line->Coords, points, x, y,
+					      0.0, m);
+			}
+		      else
+			{
+			    gaiaSetPoint (line->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		if (!geom)
+		  {
+		      if (eff_dims == GAIA_XY_Z)
+			  geom = gaiaAllocGeomCollXYZ ();
+		      else if (eff_dims == GAIA_XY_M)
+			  geom = gaiaAllocGeomCollXYM ();
+		      else if (eff_dims == GAIA_XY_Z_M)
+			  geom = gaiaAllocGeomCollXYZM ();
+		      else
+			  geom = gaiaAllocGeomColl ();
+		      if (eff_type == GAIA_LINESTRING)
+			  geom->DeclaredType = GAIA_LINESTRING;
+		      else
+			  geom->DeclaredType = GAIA_MULTILINESTRING;
+		  }
+		gaiaInsertLinestringInGeomColl (geom, line);
+	    }
+      }
+    if (shape == GAIA_SHP_POLYGON)
+      {
+	  /* shape polygon */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  base = 44 + (n * 4);
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    ring = gaiaAllocRingXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    ring = gaiaAllocRingXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    ring = gaiaAllocRingXYZM (points);
+		else
+		    ring = gaiaAllocRing (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (ring->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (ring->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (ring->Coords, points, x, y,
+					      0.0, 0.0);
+			}
+		      else
+			{
+			    gaiaSetPoint (ring->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		shp_add_ring (&ringsColl, ring);
+	    }
+	  shp_arrange_rings (&ringsColl);
+	  /* allocating the final geometry */
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  if (eff_type == GAIA_POLYGON)
+	      geom->DeclaredType = GAIA_POLYGON;
+	  else
+	      geom->DeclaredType = GAIA_MULTIPOLYGON;
+	  shp_build_area (&ringsColl, geom);
+      }
+    if (shape == GAIA_SHP_POLYGONZ)
+      {
+	  /* shape polygon Z */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 38 + (2 * n) + (n1 * 16);	/* size [in 16 bits words !!!] ZM */
+	  min_size = 30 + (2 * n) + (n1 * 12);	/* size [in 16 bits words !!!] Z-only */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  base = 44 + (n * 4);
+	  baseZ = base + (n1 * 16) + 16;
+	  baseM = baseZ + (n1 * 8) + 16;
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    ring = gaiaAllocRingXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    ring = gaiaAllocRingXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    ring = gaiaAllocRingXYZM (points);
+		else
+		    ring = gaiaAllocRing (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      z = gaiaImport64 (bufshp + baseZ + (iv * 8),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (hasM)
+			  m = gaiaImport64 (bufshp + baseM +
+					    (iv * 8), GAIA_LITTLE_ENDIAN,
+					    endian_arch);
+		      else
+			  m = 0.0;
+		      if (m < SHAPEFILE_NO_DATA)
+			  m = 0.0;
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (ring->Coords, points, x, y, z);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (ring->Coords, points, x, y, m);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (ring->Coords, points, x, y, z, m);
+			}
+		      else
+			{
+			    gaiaSetPoint (ring->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		shp_add_ring (&ringsColl, ring);
+	    }
+	  shp_arrange_rings (&ringsColl);
+	  /* allocating the final geometry */
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  if (eff_type == GAIA_POLYGON)
+	      geom->DeclaredType = GAIA_POLYGON;
+	  else
+	      geom->DeclaredType = GAIA_MULTIPOLYGON;
+	  shp_build_area (&ringsColl, geom);
+      }
+    if (shape == GAIA_SHP_POLYGONM)
+      {
+	  /* shape polygon M */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  n1 = gaiaImport32 (bufshp + 40, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 30 + (2 * n) + (n1 * 12);	/* size [in 16 bits words !!!] M */
+	  min_size = 22 + (2 * n) + (n1 * 8);	/* size [in 16 bits words !!!] no-M */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  base = 44 + (n * 4);
+	  baseM = base + (n1 * 16) + 16;
+	  start = 0;
+	  for (ind = 0; ind < n; ind++)
+	    {
+		if (ind < (n - 1))
+		    end =
+			gaiaImport32 (bufshp + 44 + ((ind + 1) * 4),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    end = n1;
+		points = end - start;
+		if (eff_dims == GAIA_XY_Z)
+		    ring = gaiaAllocRingXYZ (points);
+		else if (eff_dims == GAIA_XY_M)
+		    ring = gaiaAllocRingXYM (points);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    ring = gaiaAllocRingXYZM (points);
+		else
+		    ring = gaiaAllocRing (points);
+		points = 0;
+		for (iv = start; iv < end; iv++)
+		  {
+		      x = gaiaImport64 (bufshp + base + (iv * 16),
+					GAIA_LITTLE_ENDIAN, endian_arch);
+		      y = gaiaImport64 (bufshp + base + (iv * 16) +
+					8, GAIA_LITTLE_ENDIAN, endian_arch);
+		      if (hasM)
+			  m = gaiaImport64 (bufshp + baseM +
+					    (iv * 8), GAIA_LITTLE_ENDIAN,
+					    endian_arch);
+		      m = 0.0;
+		      if (m < SHAPEFILE_NO_DATA)
+			  m = 0.0;
+		      if (eff_dims == GAIA_XY_Z)
+			{
+			    gaiaSetPointXYZ (ring->Coords, points, x, y, 0.0);
+			}
+		      else if (eff_dims == GAIA_XY_M)
+			{
+			    gaiaSetPointXYM (ring->Coords, points, x, y, m);
+			}
+		      else if (eff_dims == GAIA_XY_Z_M)
+			{
+			    gaiaSetPointXYZM (ring->Coords, points, x, y,
+					      0.0, m);
+			}
+		      else
+			{
+			    gaiaSetPoint (ring->Coords, points, x, y);
+			}
+		      start++;
+		      points++;
+		  }
+		shp_add_ring (&ringsColl, ring);
+	    }
+	  shp_arrange_rings (&ringsColl);
+	  /* allocating the final geometry */
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  if (eff_type == GAIA_POLYGON)
+	      geom->DeclaredType = GAIA_POLYGON;
+	  else
+	      geom->DeclaredType = GAIA_MULTIPOLYGON;
+	  shp_build_area (&ringsColl, geom);
+      }
+    if (shape == GAIA_SHP_MULTIPOINT)
+      {
+	  /* shape multipoint */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  geom->DeclaredType = GAIA_MULTIPOINT;
+	  for (iv = 0; iv < n; iv++)
+	    {
+		x = gaiaImport64 (bufshp + 40 + (iv * 16),
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		y = gaiaImport64 (bufshp + 40 + (iv * 16) + 8,
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		if (eff_dims == GAIA_XY_Z)
+		    gaiaAddPointToGeomCollXYZ (geom, x, y, 0.0);
+		else if (eff_dims == GAIA_XY_M)
+		    gaiaAddPointToGeomCollXYM (geom, x, y, 0.0);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    gaiaAddPointToGeomCollXYZM (geom, x, y, 0.0, 0.0);
+		else
+		    gaiaAddPointToGeomColl (geom, x, y);
+	    }
+      }
+    if (shape == GAIA_SHP_MULTIPOINTZ)
+      {
+	  /* shape multipoint Z */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 36 + (n * 16);	/* size [in 16 bits words !!!] ZM */
+	  min_size = 28 + (n * 12);	/* size [in 16 bits words !!!] Z-only */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  baseZ = 40 + (n * 16) + 16;
+	  baseM = baseZ + (n * 8) + 16;
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  geom->DeclaredType = GAIA_MULTIPOINT;
+	  for (iv = 0; iv < n; iv++)
+	    {
+		x = gaiaImport64 (bufshp + 40 + (iv * 16),
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		y = gaiaImport64 (bufshp + 40 + (iv * 16) + 8,
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		z = gaiaImport64 (bufshp + baseZ + (iv * 8),
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		if (hasM)
+		    m = gaiaImport64 (bufshp + baseM + (iv * 8),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    m = 0.0;
+		if (m < SHAPEFILE_NO_DATA)
+		    m = 0.0;
+		if (eff_dims == GAIA_XY_Z)
+		    gaiaAddPointToGeomCollXYZ (geom, x, y, z);
+		else if (eff_dims == GAIA_XY_M)
+		    gaiaAddPointToGeomCollXYM (geom, x, y, m);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    gaiaAddPointToGeomCollXYZM (geom, x, y, z, m);
+		else
+		    gaiaAddPointToGeomColl (geom, x, y);
+	    }
+      }
+    if (shape == GAIA_SHP_MULTIPOINTM)
+      {
+	  /* shape multipoint M */
+	  n = gaiaImport32 (bufshp + 36, GAIA_LITTLE_ENDIAN, endian_arch);
+	  hasM = 0;
+	  max_size = 28 + (n * 12);	/* size [in 16 bits words !!!] M */
+	  min_size = 20 + (n * 8);	/* size [in 16 bits words !!!] no-M */
+	  sz = buflen / 2;
+	  if (sz < min_size)
+	      goto error;
+	  if (sz == max_size)
+	      hasM = 1;
+	  baseM = 40 + (n * 16) + 16;
+	  if (eff_dims == GAIA_XY_Z)
+	      geom = gaiaAllocGeomCollXYZ ();
+	  else if (eff_dims == GAIA_XY_M)
+	      geom = gaiaAllocGeomCollXYM ();
+	  else if (eff_dims == GAIA_XY_Z_M)
+	      geom = gaiaAllocGeomCollXYZM ();
+	  else
+	      geom = gaiaAllocGeomColl ();
+	  geom->DeclaredType = GAIA_MULTIPOINT;
+	  for (iv = 0; iv < n; iv++)
+	    {
+		x = gaiaImport64 (bufshp + 40 + (iv * 16),
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		y = gaiaImport64 (bufshp + 40 + (iv * 16) + 8,
+				  GAIA_LITTLE_ENDIAN, endian_arch);
+		if (hasM)
+		    m = gaiaImport64 (bufshp + baseM + (iv * 8),
+				      GAIA_LITTLE_ENDIAN, endian_arch);
+		else
+		    m = 0.0;
+		if (m < SHAPEFILE_NO_DATA)
+		    m = 0.0;
+		if (eff_dims == GAIA_XY_Z)
+		    gaiaAddPointToGeomCollXYZ (geom, x, y, 0.0);
+		else if (eff_dims == GAIA_XY_M)
+		    gaiaAddPointToGeomCollXYM (geom, x, y, m);
+		else if (eff_dims == GAIA_XY_Z_M)
+		    gaiaAddPointToGeomCollXYZM (geom, x, y, 0.0, m);
+		else
+		    gaiaAddPointToGeomColl (geom, x, y);
+	    }
+      }
+
+    if (geom != NULL)
+	gaiaMbrGeometry (geom);
+    shp_free_rings (&ringsColl);
+    return geom;
+
+  error:
+    fprintf (stderr, "\tcorrupted shapefile / invalid format");
+    shp_free_rings (&ringsColl);
+    return NULL;
+}
+
+static int
+do_read_shp (const void *cache, const char *shp_path, int validate, int esri,
+	     int *invalid)
+{
+/* reading some Shapefile and testing for validity */
+    int current_row;
+    gaiaShapefilePtr shp = NULL;
+    int ret;
+    double minx;
+    double miny;
+    double maxx;
+    double maxy;
+    double MinX = DBL_MAX;
+    double MinY = DBL_MAX;
+    double MaxX = 0.0 - DBL_MAX;
+    double MaxY = 0.0 - DBL_MAX;
+    double hMinX;
+    double hMinY;
+    double hMaxX;
+    double hMaxY;
+    int mismatching;
+
+    *invalid = 0;
+    shp = allocShapefile ();
+    openShpRead (shp, shp_path, &hMinX, &hMinY, &hMaxX, &hMaxY, &mismatching);
+    if (!(shp->Valid))
+      {
+	  char extra[512];
+	  *extra = '\0';
+	  if (shp->LastError)
+	      sprintf (extra, "\n\tcause: %s\n", shp->LastError);
+	  fprintf (stderr,
+		   "\terror: cannot open shapefile '%s'%s", shp_path, extra);
+	  freeShapefile (shp);
+	  return 0;
+      }
+    if (mismatching)
+	*invalid += 1;
+
+    current_row = 0;
+    while (1)
+      {
+	  /* reading rows from shapefile */
+	  int shplen;
+	  ret =
+	      readShpEntity (shp, current_row, &shplen, &minx, &miny, &maxx,
+			     &maxy);
+	  if (ret < 0)
+	    {
+		/* found a DBF deleted record */
+		fprintf (stderr, "\t\trow #%d: logical deletion found\n",
+			 current_row);
+		current_row++;
+		*invalid += 1;
+		continue;
+	    }
+	  if (!ret)
+	    {
+		if (!(shp->LastError))	/* normal SHP EOF */
+		    break;
+		fprintf (stderr, "\tERROR: %s\n", shp->LastError);
+		goto stop;
+	    }
+
+	  if (validate)
+	    {
+		int nullshape;
+		gaiaGeomCollPtr geom =
+		    do_parse_geometry (shp->BufShp, shplen, shp->EffectiveDims,
+				       shp->EffectiveType, &nullshape);
+		if (nullshape)
+		    ;
+		else
+		  {
+		      if (geom == NULL)
+			{
+			    fprintf (stderr,
+				     "\t\trow #%d: unable to get a Geometry\n",
+				     current_row);
+			    *invalid += 1;
+			}
+		      else
+			{
+			    if (geom->MinX != minx || geom->MinY != miny
+				|| geom->MaxX != maxx || geom->MaxY != maxy)
+			      {
+				  fprintf (stderr,
+					   "\t\trow #%d: mismatching BBOX\n",
+					   current_row);
+				  *invalid += 1;
+			      }
+			    if (esri)
+			      {
+				  /* checking invalid geometries in ESRI mode */
+				  gaiaGeomCollPtr detail;
+				  detail =
+				      gaiaIsValidDetailEx_r (cache, geom, 1);
+				  if (detail == NULL)
+				    {
+					/* extra checks */
+					int extra = 0;
+					if (gaiaIsToxic_r (cache, geom))
+					    extra = 1;
+					if (gaiaIsNotClosedGeomColl_r
+					    (cache, geom))
+					    extra = 1;
+					if (extra)
+					  {
+					      char *reason =
+						  gaiaIsValidReason_r (cache,
+								       geom);
+					      if (reason == NULL)
+						  fprintf (stderr,
+							   "\t\trow #%d: invalid Geometry (unknown reason)\n",
+							   current_row);
+					      else
+						{
+						    fprintf (stderr,
+							     "\t\trow #%d: %s\n",
+							     current_row,
+							     reason);
+						    free (reason);
+						}
+					      *invalid += 1;
+					  }
+				    }
+				  else
+				    {
+					char *reason =
+					    gaiaIsValidReason_r (cache, geom);
+					if (reason == NULL)
+					    fprintf (stderr,
+						     "\t\trow #%d: invalid Geometry (unknown reason)\n",
+						     current_row);
+					else
+					  {
+					      fprintf (stderr,
+						       "\t\trow #%d: %s\n",
+						       current_row, reason);
+					      free (reason);
+					  }
+					*invalid += 1;
+					gaiaFreeGeomColl (detail);
+				    }
+			      }
+			    else
+			      {
+				  /* checking invalid geometries in ISO/OGC mode */
+				  if (gaiaIsValid_r (cache, geom) != 1)
+				    {
+					char *reason =
+					    gaiaIsValidReason_r (cache, geom);
+					if (reason == NULL)
+					    fprintf (stderr,
+						     "\t\trow #%d: invalid Geometry (unknown reason)\n",
+						     current_row);
+					else
+					  {
+					      fprintf (stderr,
+						       "\t\trow #%d: %s\n",
+						       current_row, reason);
+					      free (reason);
+					  }
+					*invalid += 1;
+				    }
+			      }
+			    gaiaFreeGeomColl (geom);
+			}
+		  }
+	    }
+	  if (minx != DBL_MAX && miny != DBL_MAX && maxx != DBL_MAX
+	      && maxy != DBL_MAX)
+	    {
+		if (minx < MinX)
+		    MinX = minx;
+		if (miny < MinY)
+		    MinY = miny;
+		if (maxx > MaxX)
+		    MaxX = maxx;
+		if (maxy > MaxY)
+		    MaxY = maxy;
+	    }
+	  current_row++;
+      }
+    freeShapefile (shp);
+
+    if (MinX != hMinX || MinY != hMinY || MaxX != hMaxX || MaxY != hMaxY)
+      {
+	  fprintf (stderr, "\t\tHEADERS: found invalid BBOX\n");
+	  *invalid += 1;
+      }
+
+    return 1;
+
+  stop:
+    freeShapefile (shp);
+    fprintf (stderr, "\tMalformed shapefile: quitting\n");
+    return 0;
+}
+
+static void
+do_clen_files (const char *out_path, const char *name)
+{
+/* removing an invalid Shapefile (not properly repaired) */
+    char path[1024];
+
+    sprintf (path, "%s/%s.shx", out_path, name);
+#ifdef _WIN32
+    _unlink (path);
+#else
+    unlink (path);
+#endif
+
+    sprintf (path, "%s/%s.shp", out_path, name);
+#ifdef _WIN32
+    _unlink (path);
+#else
+    unlink (path);
+#endif
+
+    sprintf (path, "%s/%s.dbf", out_path, name);
+#ifdef _WIN32
+    _unlink (path);
+#else
+    unlink (path);
+#endif
+}
+
+static void
+openShpWrite (gaiaShapefilePtr shp, const char *path, int shape,
+	      gaiaDbfListPtr dbf_list)
+{
+/* trying to create the shapefile */
+    FILE *fl_shx = NULL;
+    FILE *fl_shp = NULL;
+    FILE *fl_dbf = NULL;
+    char xpath[1024];
+    unsigned char *buf_shp = NULL;
+    int buf_size = 1024;
+    unsigned char *dbf_buf = NULL;
+    gaiaDbfFieldPtr fld;
+    char *sys_err;
+    char errMsg[1024];
+    short dbf_reclen = 0;
+    int shp_size = 0;
+    int shx_size = 0;
+    unsigned short dbf_size = 0;
+    int len;
+    int endian_arch = gaiaEndianArch ();
+    char buf[2048];
+    if (shp->flShp != NULL || shp->flShx != NULL || shp->flDbf != NULL)
+      {
+	  sprintf (errMsg,
+		   "attempting to reopen an already opened Shapefile\n");
+	  goto unsupported_conversion;
+      }
+    buf_shp = malloc (buf_size);
+/* trying to open shapefile files */
+    sprintf (xpath, "%s.shx", path);
+    fl_shx = fopen (xpath, "wb");
+    if (!fl_shx)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for writing: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+    sprintf (xpath, "%s.shp", path);
+    fl_shp = fopen (xpath, "wb");
+    if (!fl_shp)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for writing: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+    sprintf (xpath, "%s.dbf", path);
+    fl_dbf = fopen (xpath, "wb");
+    if (!fl_dbf)
+      {
+	  sys_err = strerror (errno);
+	  sprintf (errMsg, "unable to open '%s' for writing: %s", xpath,
+		   sys_err);
+	  goto no_file;
+      }
+/* allocating DBF buffer */
+    dbf_reclen = 1;		/* an extra byte is needed because in DBF rows first byte is a marker for deletion */
+    fld = dbf_list->First;
+    while (fld)
+      {
+	  /* computing the DBF record length */
+	  dbf_reclen += fld->Length;
+	  fld = fld->Next;
+      }
+    dbf_buf = malloc (dbf_reclen);
+/* writing an empty SHP file header */
+    memset (buf_shp, 0, 100);
+    fwrite (buf_shp, 1, 100, fl_shp);
+    shp_size = 50;		/* note: shapefile [SHP and SHX] counts sizes in WORDS of 16 bits, not in bytes of 8 bits !!!! */
+/* writing an empty SHX file header */
+    memset (buf_shp, 0, 100);
+    fwrite (buf_shp, 1, 100, fl_shx);
+    shx_size = 50;
+/* writing the DBF file header */
+    memset (buf_shp, '\0', 32);
+    fwrite (buf_shp, 1, 32, fl_dbf);
+    dbf_size = 32;		/* note: DBF counts sizes in bytes */
+    fld = dbf_list->First;
+    while (fld)
+      {
+	  /* exporting DBF Fields specifications */
+	  memset (buf_shp, 0, 32);
+	  strcpy (buf, fld->Name);
+	  memcpy (buf_shp, buf, strlen (buf));
+	  *(buf_shp + 11) = fld->Type;
+	  *(buf_shp + 16) = fld->Length;
+	  *(buf_shp + 17) = fld->Decimals;
+	  fwrite (buf_shp, 1, 32, fl_dbf);
+	  dbf_size += 32;
+	  fld = fld->Next;
+      }
+    fwrite ("\r", 1, 1, fl_dbf);	/* this one is a special DBF delimiter that closes file header */
+    dbf_size++;
+/* setting up the SHP struct */
+    len = strlen (path);
+    shp->Path = malloc (len + 1);
+    strcpy (shp->Path, path);
+    shp->ReadOnly = 0;
+    shp->Shape = shape;
+    shp->flShp = fl_shp;
+    shp->flShx = fl_shx;
+    shp->flDbf = fl_dbf;
+    shp->Dbf = dbf_list;
+    shp->BufShp = buf_shp;
+    shp->ShpBfsz = buf_size;
+    shp->BufDbf = dbf_buf;
+    shp->DbfHdsz = dbf_size + 1;
+    shp->DbfReclen = dbf_reclen;
+    shp->DbfSize = dbf_size;
+    shp->DbfRecno = 0;
+    shp->ShpSize = shp_size;
+    shp->ShxSize = shx_size;
+    shp->MinX = DBL_MAX;
+    shp->MinY = DBL_MAX;
+    shp->MaxX = -DBL_MAX;
+    shp->MaxY = -DBL_MAX;
+    shp->Valid = 1;
+    shp->endian_arch = endian_arch;
+    return;
+  unsupported_conversion:
+/* illegal charset */
+    if (shp->LastError)
+	free (shp->LastError);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    return;
+  no_file:
+/* one of shapefile's files can't be created/opened */
+    if (shp->LastError)
+	free (shp->LastError);
+    len = strlen (errMsg);
+    shp->LastError = malloc (len + 1);
+    strcpy (shp->LastError, errMsg);
+    if (buf_shp)
+	free (buf_shp);
+    if (fl_shx)
+	fclose (fl_shx);
+    if (fl_shp)
+	fclose (fl_shp);
+    if (fl_dbf)
+	fclose (fl_dbf);
+    return;
+}
+
+static int
+writeShpEntity (gaiaShapefilePtr shp, const unsigned char *bufshp, int shplen,
+		const unsigned char *bufdbf, int dbflen)
+{
+/* trying to write an entity into shapefile */
+    unsigned char buf[64];
+    int endian_arch = shp->endian_arch;
+    int shape;
+    double minx;
+    double maxx;
+    double miny;
+    double maxy;
+
+/* inserting entity in SHX file */
+    gaiaExport32 (buf, shp->ShpSize, GAIA_BIG_ENDIAN, endian_arch);	/* exports current SHP file position */
+    gaiaExport32 (buf + 4, shplen / 2, GAIA_BIG_ENDIAN, endian_arch);	/* exports entitiy size [in 16 bits words !!!] */
+    fwrite (buf, 1, 8, shp->flShx);
+    (shp->ShxSize) += 4;	/* updating current SHX file position [in 16 bits words !!!] */
+
+/* inserting entity in SHP file */
+    gaiaExport32 (buf, shp->DbfRecno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+    gaiaExport32 (buf + 4, shplen / 2, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+    fwrite (buf, 1, 8, shp->flShp);
+    (shp->ShpSize) += 4;
+    fwrite (bufshp, 1, shplen, shp->flShp);
+    (shp->ShpSize) += shplen / 2;	/* updating current SHP file position [in 16 bits words !!!] */
+
+/* inserting entity in DBF file */
+    fwrite (bufdbf, 1, dbflen, shp->flDbf);
+    (shp->DbfRecno)++;
+
+/* updating the full extent BBOX */
+    shape = gaiaImport32 (bufshp + 0, GAIA_LITTLE_ENDIAN, endian_arch);
+    if (shape == GAIA_SHP_POINT || shape == GAIA_SHP_POINTZ
+	|| shape == GAIA_SHP_POINTM)
+      {
+	  minx = gaiaImport64 (bufshp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  maxx = minx;
+	  miny = gaiaImport64 (bufshp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  maxy = miny;
+	  if (minx < shp->MinX)
+	      shp->MinX = minx;
+	  if (maxx > shp->MaxX)
+	      shp->MaxX = maxx;
+	  if (miny < shp->MinY)
+	      shp->MinY = miny;
+	  if (maxy > shp->MaxY)
+	      shp->MaxY = maxy;
+      }
+    if (shape == GAIA_SHP_POLYLINE || shape == GAIA_SHP_POLYLINEZ
+	|| shape == GAIA_SHP_POLYLINEM || shape == GAIA_SHP_POLYGON
+	|| shape == GAIA_SHP_POLYGONZ || shape == GAIA_SHP_POLYGONM
+	|| shape == GAIA_SHP_MULTIPOINT || shape == GAIA_SHP_MULTIPOINTZ
+	|| shape == GAIA_SHP_MULTIPOINTM)
+      {
+	  minx = gaiaImport64 (bufshp + 4, GAIA_LITTLE_ENDIAN, endian_arch);
+	  miny = gaiaImport64 (bufshp + 12, GAIA_LITTLE_ENDIAN, endian_arch);
+	  maxx = gaiaImport64 (bufshp + 20, GAIA_LITTLE_ENDIAN, endian_arch);
+	  maxy = gaiaImport64 (bufshp + 28, GAIA_LITTLE_ENDIAN, endian_arch);
+	  if (minx < shp->MinX)
+	      shp->MinX = minx;
+	  if (maxx > shp->MaxX)
+	      shp->MaxX = maxx;
+	  if (miny < shp->MinY)
+	      shp->MinY = miny;
+	  if (maxy > shp->MaxY)
+	      shp->MaxY = maxy;
+      }
+    return 1;
+}
+
+static int
+check_geometry (gaiaGeomCollPtr geom, int shape)
+{
+/* cheching the geometry type and dims */
+    int pts = 0;
+    int lns = 0;
+    int pgs = 0;
+    gaiaPointPtr pt;
+    gaiaLinestringPtr ln;
+    gaiaPolygonPtr pg;
+
+    pt = geom->FirstPoint;
+    while (pt != NULL)
+      {
+	  pts++;
+	  pt = pt->Next;
+      }
+    ln = geom->FirstLinestring;
+    while (ln != NULL)
+      {
+	  lns++;
+	  ln = ln->Next;
+      }
+    pg = geom->FirstPolygon;
+    while (pg != NULL)
+      {
+	  pgs++;
+	  pg = pg->Next;
+      }
+
+    if (pts == 1 && lns == 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_POINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POINTM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTM
+	      && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts > 1 && lns == 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_MULTIPOINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTM
+	      && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts == 0 && lns > 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_POLYLINE && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POLYLINEZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POLYLINEM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts == 0 && lns == 0 && pgs > 0)
+      {
+	  if (shape == GAIA_SHP_POLYGON && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POLYGONZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POLYGONM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+
+    return 0;
+}
+
+static int
+check_geometry_verbose (gaiaGeomCollPtr geom, int shape, char **expected,
+			char **actual)
+{
+/* cheching the geometry type and dims - verbose */
+    int pts = 0;
+    int lns = 0;
+    int pgs = 0;
+    gaiaPointPtr pt;
+    gaiaLinestringPtr ln;
+    gaiaPolygonPtr pg;
+    const char *str;
+    int len;
+
+    *expected = NULL;
+    *actual = NULL;
+    pt = geom->FirstPoint;
+    while (pt != NULL)
+      {
+	  pts++;
+	  pt = pt->Next;
+      }
+    ln = geom->FirstLinestring;
+    while (ln != NULL)
+      {
+	  lns++;
+	  ln = ln->Next;
+      }
+    pg = geom->FirstPolygon;
+    while (pg != NULL)
+      {
+	  pgs++;
+	  pg = pg->Next;
+      }
+
+    if (pts == 1 && lns == 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_POINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POINTM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTM
+	      && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts > 1 && lns == 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_MULTIPOINT && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_MULTIPOINTM
+	      && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts == 0 && lns > 0 && pgs == 0)
+      {
+	  if (shape == GAIA_SHP_POLYLINE && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POLYLINEZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POLYLINEM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+    if (pts == 0 && lns == 0 && pgs > 0)
+      {
+	  if (shape == GAIA_SHP_POLYGON && geom->DimensionModel == GAIA_XY)
+	      return 1;
+	  if (shape == GAIA_SHP_POLYGONZ
+	      && (geom->DimensionModel == GAIA_XY_Z
+		  || geom->DimensionModel == GAIA_XY_Z_M))
+	      return 1;
+	  if (shape == GAIA_SHP_POLYGONM && geom->DimensionModel == GAIA_XY_M)
+	      return 1;
+      }
+
+    switch (shape)
+      {
+      case GAIA_SHP_POINT:
+	  str = "POINT";
+	  break;
+      case GAIA_SHP_POINTZ:
+	  str = "POINT-M";
+	  break;
+      case GAIA_SHP_POINTM:
+	  str = "POINT-Z";
+	  break;
+      case GAIA_SHP_POLYLINE:
+	  str = "POLYLINE";
+	  break;
+      case GAIA_SHP_POLYLINEZ:
+	  str = "POLYLINE-Z";
+	  break;
+      case GAIA_SHP_POLYLINEM:
+	  str = "POLYLINE-M";
+	  break;
+      case GAIA_SHP_POLYGON:
+	  str = "POLYGON";
+	  break;
+      case GAIA_SHP_POLYGONZ:
+	  str = "POLYGON-Z";
+	  break;
+      case GAIA_SHP_POLYGONM:
+	  str = "POLYGON-M";
+	  break;
+      case GAIA_SHP_MULTIPOINT:
+	  str = "MULTIPOINT";
+	  break;
+      case GAIA_SHP_MULTIPOINTZ:
+	  str = "MULTIPOINT-Z";
+	  break;
+      case GAIA_SHP_MULTIPOINTM:
+	  str = "MULTIPOINT-M";
+	  break;
+      default:
+	  str = "UNKNOWN";
+	  break;
+      };
+    len = strlen (str);
+    *expected = malloc (len + 1);
+    strcpy (*expected, str);
+
+    str = "UNKNOWN";
+    if (pts == 1 && lns == 0 && pgs == 0)
+      {
+	  if (geom->DimensionModel == GAIA_XY)
+	      str = "POINT";
+	  if (geom->DimensionModel == GAIA_XY_Z
+	      || geom->DimensionModel == GAIA_XY_Z_M)
+	      str = "POINT-Z";
+	  if (geom->DimensionModel == GAIA_XY_M)
+	      str = "POINT-M";
+      }
+    if (pts > 1 && lns == 0 && pgs == 0)
+      {
+	  if (geom->DimensionModel == GAIA_XY)
+	      str = "MULTIPOINT";
+	  if (geom->DimensionModel == GAIA_XY_Z
+	      || geom->DimensionModel == GAIA_XY_Z_M)
+	      str = "MULTIPOINT-Z";
+	  if (geom->DimensionModel == GAIA_XY_M)
+	      str = "MULTIPOINT-M";
+      }
+    if (pts == 0 && lns > 0 && pgs == 0)
+      {
+	  if (geom->DimensionModel == GAIA_XY)
+	      str = "POLYLINE";
+	  if (geom->DimensionModel == GAIA_XY_Z
+	      || geom->DimensionModel == GAIA_XY_Z_M)
+	      str = "POLYLINE-Z";
+	  if (geom->DimensionModel == GAIA_XY_M)
+	      str = "POLYLINE-M";
+      }
+    if (pts == 0 && lns == 0 && pgs > 0)
+      {
+	  if (geom->DimensionModel == GAIA_XY)
+	      str = "POLYGON";
+	  if (geom->DimensionModel == GAIA_XY_Z
+	      || geom->DimensionModel == GAIA_XY_Z_M)
+	      str = "POLYGON-Z";
+	  return 1;
+	  if (geom->DimensionModel == GAIA_XY_M)
+	      str = "POLYGON-M";
+	  return 1;
+      }
+    len = strlen (str);
+    *actual = malloc (len + 1);
+    strcpy (*actual, str);
+
+    return 0;
+}
+
+static void
+gaiaSaneClockwise (gaiaPolygonPtr polyg)
+{
+/*
+/ when exporting POLYGONs to SHAPEFILE, we must guarantee that:
+/ - all EXTERIOR RING must be clockwise
+/ - all INTERIOR RING must be anti-clockwise
+/
+/ this function checks for the above conditions,
+/ and if needed inverts the rings
+*/
+    int ib;
+    int iv;
+    int iv2;
+    double x;
+    double y;
+    double z;
+    double m;
+    gaiaRingPtr new_ring;
+    gaiaRingPtr ring = polyg->Exterior;
+    gaiaClockwise (ring);
+    if (!(ring->Clockwise))
+      {
+	  /* exterior ring needs inversion */
+	  if (ring->DimensionModel == GAIA_XY_Z)
+	      new_ring = gaiaAllocRingXYZ (ring->Points);
+	  else if (ring->DimensionModel == GAIA_XY_M)
+	      new_ring = gaiaAllocRingXYM (ring->Points);
+	  else if (ring->DimensionModel == GAIA_XY_Z_M)
+	      new_ring = gaiaAllocRingXYZM (ring->Points);
+	  else
+	      new_ring = gaiaAllocRing (ring->Points);
+	  iv2 = 0;
+	  for (iv = ring->Points - 1; iv >= 0; iv--)
+	    {
+		if (ring->DimensionModel == GAIA_XY_Z)
+		  {
+		      gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+		      gaiaSetPointXYZ (new_ring->Coords, iv2, x, y, z);
+		  }
+		else if (ring->DimensionModel == GAIA_XY_M)
+		  {
+		      gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+		      gaiaSetPointXYM (new_ring->Coords, iv2, x, y, m);
+		  }
+		else if (ring->DimensionModel == GAIA_XY_Z_M)
+		  {
+		      gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+		      gaiaSetPointXYZM (new_ring->Coords, iv2, x, y, z, m);
+		  }
+		else
+		  {
+		      gaiaGetPoint (ring->Coords, iv, &x, &y);
+		      gaiaSetPoint (new_ring->Coords, iv2, x, y);
+		  }
+		iv2++;
+	    }
+	  polyg->Exterior = new_ring;
+	  gaiaFreeRing (ring);
+      }
+    for (ib = 0; ib < polyg->NumInteriors; ib++)
+      {
+	  ring = polyg->Interiors + ib;
+	  gaiaClockwise (ring);
+	  if (ring->Clockwise)
+	    {
+		/* interior ring needs inversion */
+		if (ring->DimensionModel == GAIA_XY_Z)
+		    new_ring = gaiaAllocRingXYZ (ring->Points);
+		else if (ring->DimensionModel == GAIA_XY_M)
+		    new_ring = gaiaAllocRingXYM (ring->Points);
+		else if (ring->DimensionModel == GAIA_XY_Z_M)
+		    new_ring = gaiaAllocRingXYZM (ring->Points);
+		else
+		    new_ring = gaiaAllocRing (ring->Points);
+		iv2 = 0;
+		for (iv = ring->Points - 1; iv >= 0; iv--)
+		  {
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			    gaiaSetPointXYZ (new_ring->Coords, iv2, x, y, z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			    gaiaSetPointXYM (new_ring->Coords, iv2, x, y, m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			    gaiaSetPointXYZM (new_ring->Coords, iv2, x, y,
+					      z, m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			    gaiaSetPoint (new_ring->Coords, iv2, x, y);
+			}
+		      iv2++;
+		  }
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (new_ring->Coords, iv, &x, &y, &z);
+			    gaiaSetPointXYZ (ring->Coords, iv, x, y, z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (new_ring->Coords, iv, &x, &y, &m);
+			    gaiaSetPointXYM (ring->Coords, iv, x, y, m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (new_ring->Coords, iv, &x, &y,
+					      &z, &m);
+			    gaiaSetPointXYZM (ring->Coords, iv, x, y, z, m);
+			}
+		      else
+			{
+			    gaiaGetPoint (new_ring->Coords, iv, &x, &y);
+			    gaiaSetPoint (ring->Coords, iv, x, y);
+			}
+		  }
+		gaiaFreeRing (new_ring);
+	    }
+      }
+}
+
+static int
+do_export_geometry (gaiaGeomCollPtr geom, unsigned char **bufshp, int *buflen,
+		    int xshape, int recno, int rowno, int eff_dims)
+{
+/* attempting to encode a Geometry */
+    unsigned char *buf;
+    int iv;
+    int tot_ln;
+    int tot_v;
+    int tot_pts;
+    int this_size;
+    int ix;
+    double x;
+    double y;
+    double z;
+    double m;
+    int hasM;
+    double minZ;
+    double maxZ;
+    double minM;
+    double maxM;
+    int endian_arch = gaiaEndianArch ();
+
+    if (geom == NULL)
+      {
+	  /* exporting a NULL Shape */
+	  *buflen = 12;
+	  buf = malloc (12);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, 2, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_NULL, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = NULL */
+	  *bufshp = buf;
+	  return 1;
+      }
+
+    if (!check_geometry (geom, xshape))
+      {
+	  /* mismatching Geometry type */
+	  fprintf (stderr, "\tinput row #%d: mismatching Geometry type\n",
+		   rowno);
+	  return 0;
+      }
+
+    if (xshape == GAIA_SHP_POINT)
+      {
+	  /* this one is expected to be a POINT */
+	  gaiaPointPtr pt = geom->FirstPoint;
+	  *buflen = 28;
+	  buf = malloc (28);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, 10, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POINT, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POINT */
+	  gaiaExport64 (buf + 12, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports X coordinate */
+	  gaiaExport64 (buf + 20, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports Y coordinate */
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POINTZ)
+      {
+	  /* this one is expected to be a POINT Z */
+	  gaiaPointPtr pt = geom->FirstPoint;
+	  *buflen = 42;
+	  buf = malloc (42);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, 18, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POINTZ, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POINT Z */
+	  gaiaExport64 (buf + 12, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports X coordinate */
+	  gaiaExport64 (buf + 20, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports Y coordinate */
+	  gaiaExport64 (buf + 28, pt->Z, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports Z coordinate */
+	  gaiaExport64 (buf + 36, pt->M, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports M coordinate */
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POINTM)
+      {
+	  /* this one is expected to be a POINT M */
+	  gaiaPointPtr pt = geom->FirstPoint;
+	  *buflen = 36;
+	  buf = malloc (36);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, 14, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POINTM, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POINT M */
+	  gaiaExport64 (buf + 12, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports X coordinate */
+	  gaiaExport64 (buf + 20, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports Y coordinate */
+	  gaiaExport64 (buf + 28, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports M coordinate */
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYLINE)
+      {
+	  /* this one is expected to be a LINESTRING / MULTILINESTRING */
+	  gaiaLinestringPtr line;
+	  tot_ln = 0;
+	  tot_v = 0;
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* computes # lines and total # points */
+		tot_v += line->Points;
+		tot_ln++;
+		line = line->Next;
+	    }
+	  this_size = 26 + (2 * tot_ln) + (tot_v * 8);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYLINE, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYLINE */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # lines in this polyline */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports start point index for each line */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += line->Points;
+		ix += 4;
+		line = line->Next;
+	    }
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports points for each line */
+		for (iv = 0; iv < line->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] */
+		      if (line->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
+			}
+		      else if (line->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
+			}
+		      else if (line->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (line->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		line = line->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYLINEZ)
+      {
+	  /* this one is expected to be a LINESTRING / MULTILINESTRING Z */
+	  gaiaLinestringPtr line;
+	  gaiaZRangeGeometry (geom, &minZ, &maxZ);
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_ln = 0;
+	  tot_v = 0;
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* computes # lines and total # points */
+		tot_v += line->Points;
+		tot_ln++;
+		line = line->Next;
+	    }
+	  hasM = 0;
+	  if (eff_dims == GAIA_XY_M || eff_dims == GAIA_XY_Z_M)
+	      hasM = 1;
+	  if (hasM)
+	      this_size = 42 + (2 * tot_ln) + (tot_v * 16);	/* size [in 16 bits words !!!] ZM */
+	  else
+	      this_size = 34 + (2 * tot_ln) + (tot_v * 12);	/* size [in 16 bits words !!!] Z-only */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYLINEZ, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYLINE Z */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # lines in this polyline */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports start point index for each line */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += line->Points;
+		ix += 4;
+		line = line->Next;
+	    }
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports points for each line */
+		for (iv = 0; iv < line->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] */
+		      if (line->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
+			}
+		      else if (line->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
+			}
+		      else if (line->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (line->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		line = line->Next;
+	    }
+	  /* exporting the Z-range [min/max] */
+	  gaiaExport64 (buf + ix, minZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports Z-values for each line */
+		for (iv = 0; iv < line->Points; iv++)
+		  {
+		      /* exports Z-value */
+		      z = 0.0;
+		      if (line->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
+			}
+		      else if (line->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
+			}
+		      else if (line->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (line->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, z,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		line = line->Next;
+	    }
+	  if (hasM)
+	    {
+		/* exporting the M-range [min/max] */
+		gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		line = geom->FirstLinestring;
+		while (line)
+		  {
+		      /* exports M-values for each line */
+		      for (iv = 0; iv < line->Points; iv++)
+			{
+			    /* exports M-value */
+			    m = 0.0;
+			    if (line->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (line->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (line->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (line->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (line->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (line->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (line->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, m,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		      line = line->Next;
+		  }
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYLINEM)
+      {
+	  /* this one is expected to be a LINESTRING / MULTILINESTRING M */
+	  gaiaLinestringPtr line;
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_ln = 0;
+	  tot_v = 0;
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* computes # lines and total # points */
+		tot_v += line->Points;
+		tot_ln++;
+		line = line->Next;
+	    }
+	  this_size = 34 + (2 * tot_ln) + (tot_v * 12);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYLINEM, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYLINE M */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # lines in this polyline */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports start point index for each line */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += line->Points;
+		ix += 4;
+		line = line->Next;
+	    }
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports points for each line */
+		for (iv = 0; iv < line->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] */
+		      if (line->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
+			}
+		      else if (line->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
+			}
+		      else if (line->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (line->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		line = line->Next;
+	    }
+	  /* exporting the M-range [min/max] */
+	  gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  line = geom->FirstLinestring;
+	  while (line)
+	    {
+		/* exports M-values for each line */
+		for (iv = 0; iv < line->Points; iv++)
+		  {
+		      /* exports M-value */
+		      m = 0.0;
+		      if (line->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
+			}
+		      else if (line->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
+			}
+		      else if (line->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (line->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, m,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		line = line->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYGON)
+      {
+	  /* this one is expected to be a POLYGON or a MULTIPOLYGON */
+	  gaiaPolygonPtr polyg;
+	  gaiaRingPtr ring;
+	  int ib;
+	  tot_ln = 0;
+	  tot_v = 0;
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* computes # rings and total # points */
+		gaiaSaneClockwise (polyg);	/* we must assure that exterior ring is clockwise, and interior rings are anti-clockwise */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		tot_v += ring->Points;
+		tot_ln++;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      tot_v += ring->Points;
+		      tot_ln++;
+		  }
+		polyg = polyg->Next;
+	    }
+	  this_size = 26 + (2 * tot_ln) + (tot_v * 8);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYGON, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYGON */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # rings in this polygon */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports start point index for each line */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += ring->Points;
+		ix += 4;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      gaiaExport32 (buf + ix, tot_v,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      tot_v += ring->Points;
+		      ix += 4;
+		  }
+		polyg = polyg->Next;
+	    }
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports points for each ring */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] - exterior ring */
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports a POINT [x,y] - interior ring */
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, x,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			    gaiaExport64 (buf + ix, y,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		  }
+		polyg = polyg->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYGONZ)
+      {
+	  /* this one is expected to be a POLYGON or a MULTIPOLYGON Z */
+	  gaiaPolygonPtr polyg;
+	  gaiaRingPtr ring;
+	  int ib;
+	  gaiaZRangeGeometry (geom, &minZ, &maxZ);
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_ln = 0;
+	  tot_v = 0;
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* computes # rings and total # points */
+		gaiaSaneClockwise (polyg);	/* we must assure that exterior ring is clockwise, and interior rings are anti-clockwise */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		tot_v += ring->Points;
+		tot_ln++;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      tot_v += ring->Points;
+		      tot_ln++;
+		  }
+		polyg = polyg->Next;
+	    }
+	  hasM = 0;
+	  if (eff_dims == GAIA_XY_M || eff_dims == GAIA_XY_Z_M)
+	      hasM = 1;
+	  if (hasM)
+	      this_size = 42 + (2 * tot_ln) + (tot_v * 16);	/* size [in 16 bits words !!!] ZM */
+	  else
+	      this_size = 34 + (2 * tot_ln) + (tot_v * 12);	/* size [in 16 bits words !!!] Z-only */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYGONZ, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYGON Z */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # rings in this polygon */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports start point index for each line */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += ring->Points;
+		ix += 4;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      gaiaExport32 (buf + ix, tot_v,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      tot_v += ring->Points;
+		      ix += 4;
+		  }
+		polyg = polyg->Next;
+	    }
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports points for each ring */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] - exterior ring */
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports a POINT [x,y] - interior ring */
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, x,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			    gaiaExport64 (buf + ix, y,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		  }
+		polyg = polyg->Next;
+	    }
+	  /* exporting the Z-range [min/max] */
+	  gaiaExport64 (buf + ix, minZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports Z-values for each ring */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      /* exports Z-values - exterior ring */
+		      z = 0.0;
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, z,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports Z-values - interior ring */
+			    z = 0.0;
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, z,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		  }
+		polyg = polyg->Next;
+	    }
+	  if (hasM)
+	    {
+		/* exporting the M-range [min/max] */
+		gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		polyg = geom->FirstPolygon;
+		while (polyg)
+		  {
+		      /* exports M-values for each ring */
+		      ring = polyg->Exterior;	/* this one is the exterior ring */
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports M-values - exterior ring */
+			    m = 0.0;
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, m,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		      for (ib = 0; ib < polyg->NumInteriors; ib++)
+			{
+			    /* that ones are the interior rings */
+			    ring = polyg->Interiors + ib;
+			    for (iv = 0; iv < ring->Points; iv++)
+			      {
+				  /* exports M-values - interior ring */
+				  m = 0.0;
+				  if (ring->DimensionModel == GAIA_XY_Z)
+				    {
+					gaiaGetPointXYZ (ring->Coords,
+							 iv, &x, &y, &z);
+				    }
+				  else if (ring->DimensionModel == GAIA_XY_M)
+				    {
+					gaiaGetPointXYM (ring->Coords,
+							 iv, &x, &y, &m);
+				    }
+				  else if (ring->DimensionModel == GAIA_XY_Z_M)
+				    {
+					gaiaGetPointXYZM (ring->Coords,
+							  iv, &x, &y, &z, &m);
+				    }
+				  else
+				    {
+					gaiaGetPoint (ring->Coords, iv, &x, &y);
+				    }
+				  gaiaExport64 (buf + ix, m,
+						GAIA_LITTLE_ENDIAN,
+						endian_arch);
+				  ix += 8;
+			      }
+			}
+		      polyg = polyg->Next;
+		  }
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_POLYGONM)
+      {
+	  /* this one is expected to be a POLYGON or a MULTIPOLYGON M */
+	  gaiaPolygonPtr polyg;
+	  gaiaRingPtr ring;
+	  int ib;
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_ln = 0;
+	  tot_v = 0;
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* computes # rings and total # points */
+		gaiaSaneClockwise (polyg);	/* we must assure that exterior ring is clockwise, and interior rings are anti-clockwise */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		tot_v += ring->Points;
+		tot_ln++;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      tot_v += ring->Points;
+		      tot_ln++;
+		  }
+		polyg = polyg->Next;
+	    }
+	  this_size = 34 + (2 * tot_ln) + (tot_v * 12);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_POLYGONM, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = POLYGON M */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_ln, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports # rings in this polygon */
+	  gaiaExport32 (buf + 48, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  tot_v = 0;		/* resets points counter */
+	  ix = 52;		/* sets current buffer offset */
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports start point index for each line */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		gaiaExport32 (buf + ix, tot_v, GAIA_LITTLE_ENDIAN, endian_arch);
+		tot_v += ring->Points;
+		ix += 4;
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      gaiaExport32 (buf + ix, tot_v,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      tot_v += ring->Points;
+		      ix += 4;
+		  }
+		polyg = polyg->Next;
+	    }
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports points for each ring */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      /* exports a POINT [x,y] - exterior ring */
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, x,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      gaiaExport64 (buf + ix, y,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports a POINT [x,y] - interior ring */
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, x,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			    gaiaExport64 (buf + ix, y,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		  }
+		polyg = polyg->Next;
+	    }
+	  /* exporting the M-range [min/max] */
+	  gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  polyg = geom->FirstPolygon;
+	  while (polyg)
+	    {
+		/* exports M-values for each ring */
+		ring = polyg->Exterior;	/* this one is the exterior ring */
+		for (iv = 0; iv < ring->Points; iv++)
+		  {
+		      /* exports M-values - exterior ring */
+		      m = 0.0;
+		      if (ring->DimensionModel == GAIA_XY_Z)
+			{
+			    gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_M)
+			{
+			    gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
+			}
+		      else if (ring->DimensionModel == GAIA_XY_Z_M)
+			{
+			    gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
+			}
+		      else
+			{
+			    gaiaGetPoint (ring->Coords, iv, &x, &y);
+			}
+		      gaiaExport64 (buf + ix, m,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		  }
+		for (ib = 0; ib < polyg->NumInteriors; ib++)
+		  {
+		      /* that ones are the interior rings */
+		      ring = polyg->Interiors + ib;
+		      for (iv = 0; iv < ring->Points; iv++)
+			{
+			    /* exports M-values - interior ring */
+			    m = 0.0;
+			    if (ring->DimensionModel == GAIA_XY_Z)
+			      {
+				  gaiaGetPointXYZ (ring->Coords, iv,
+						   &x, &y, &z);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_M)
+			      {
+				  gaiaGetPointXYM (ring->Coords, iv,
+						   &x, &y, &m);
+			      }
+			    else if (ring->DimensionModel == GAIA_XY_Z_M)
+			      {
+				  gaiaGetPointXYZM (ring->Coords, iv,
+						    &x, &y, &z, &m);
+			      }
+			    else
+			      {
+				  gaiaGetPoint (ring->Coords, iv, &x, &y);
+			      }
+			    gaiaExport64 (buf + ix, m,
+					  GAIA_LITTLE_ENDIAN, endian_arch);
+			    ix += 8;
+			}
+		  }
+		polyg = polyg->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_MULTIPOINT)
+      {
+	  /* this one is expected to be a MULTIPOINT */
+	  gaiaPointPtr pt;
+	  tot_pts = 0;
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* computes # points */
+		tot_pts++;
+		pt = pt->Next;
+	    }
+	  this_size = 24 + (tot_pts * 8);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_MULTIPOINT, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = MULTIPOINT */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_pts, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  ix = 48;		/* sets current buffer offset */
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* exports each point */
+		gaiaExport64 (buf + ix, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = pt->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_MULTIPOINTZ)
+      {
+	  /* this one is expected to be a MULTIPOINT Z */
+	  gaiaPointPtr pt;
+	  gaiaZRangeGeometry (geom, &minZ, &maxZ);
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_pts = 0;
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* computes # points */
+		tot_pts++;
+		pt = pt->Next;
+	    }
+	  hasM = 0;
+	  if (eff_dims == GAIA_XY_M || eff_dims == GAIA_XY_Z_M)
+	      hasM = 1;
+	  if (hasM)
+	      this_size = 40 + (tot_pts * 16);	/* size [in 16 bits words !!!] ZM */
+	  else
+	      this_size = 32 + (tot_pts * 12);	/* size [in 16 bits words !!!] Z-only */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_MULTIPOINTZ, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = MULTIPOINT Z */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_pts, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  ix = 48;		/* sets current buffer offset */
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* exports each point */
+		gaiaExport64 (buf + ix, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = pt->Next;
+	    }
+	  /* exporting the Z-range [min/max] */
+	  gaiaExport64 (buf + ix, minZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxZ, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* exports Z-values */
+		gaiaExport64 (buf + ix, pt->Z, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = pt->Next;
+	    }
+	  if (hasM)
+	    {
+		/* exporting the M-range [min/max] */
+		gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = geom->FirstPoint;
+		while (pt)
+		  {
+		      /* exports M-values */
+		      gaiaExport64 (buf + ix, pt->M,
+				    GAIA_LITTLE_ENDIAN, endian_arch);
+		      ix += 8;
+		      pt = pt->Next;
+		  }
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+    if (xshape == GAIA_SHP_MULTIPOINTM)
+      {
+	  /* this one is expected to be a MULTIPOINT M */
+	  gaiaPointPtr pt;
+	  gaiaMRangeGeometry (geom, &minM, &maxM);
+	  tot_pts = 0;
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* computes # points */
+		tot_pts++;
+		pt = pt->Next;
+	    }
+	  this_size = 32 + (tot_pts * 12);	/* size [in 16 bits words !!!] for this SHP entity */
+	  *buflen = this_size * 2;
+	  buf = malloc (this_size * 2);
+	  gaiaExport32 (buf, recno + 1, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity ID */
+	  gaiaExport32 (buf + 4, this_size, GAIA_BIG_ENDIAN, endian_arch);	/* exports entity size [in 16 bits words !!!] */
+	  gaiaExport32 (buf + 8, GAIA_SHP_MULTIPOINTM, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports geometry type = MULTIPOINT M */
+	  gaiaExport64 (buf + 12, geom->MinX, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports the MBR for this geometry */
+	  gaiaExport64 (buf + 20, geom->MinY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 28, geom->MaxX, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport64 (buf + 36, geom->MaxY, GAIA_LITTLE_ENDIAN, endian_arch);
+	  gaiaExport32 (buf + 44, tot_pts, GAIA_LITTLE_ENDIAN, endian_arch);	/* exports total # points */
+	  ix = 48;		/* sets current buffer offset */
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* exports each point */
+		gaiaExport64 (buf + ix, pt->X, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		gaiaExport64 (buf + ix, pt->Y, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = pt->Next;
+	    }
+	  /* exporting the M-range [min/max] */
+	  gaiaExport64 (buf + ix, minM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  gaiaExport64 (buf + ix, maxM, GAIA_LITTLE_ENDIAN, endian_arch);
+	  ix += 8;
+	  pt = geom->FirstPoint;
+	  while (pt)
+	    {
+		/* exports M-values */
+		gaiaExport64 (buf + ix, pt->M, GAIA_LITTLE_ENDIAN, endian_arch);
+		ix += 8;
+		pt = pt->Next;
+	    }
+	  *bufshp = buf;
+	  return 1;
+      }
+
+    fprintf (stderr,
+	     "\tinput row #%d: unable to export a consistent Geometry\n",
+	     rowno);
+    return 0;
+}
+
+static int
+do_repair_shapefile (const void *cache, const char *shp_path,
+		     const char *out_path, int validate, int esri, int force,
+		     int *repair_failed)
+{
+/* repairing some Shapefile */
+    int current_row;
+    gaiaShapefilePtr shp_in = NULL;
+    gaiaShapefilePtr shp_out = NULL;
+    int ret;
+    gaiaDbfListPtr dbf_list = NULL;
+    gaiaDbfFieldPtr in_fld;
+    double minx;
+    double miny;
+    double maxx;
+    double maxy;
+    double hMinX;
+    double hMinY;
+    double hMaxX;
+    double hMaxY;
+    int mismatching;
+
+    *repair_failed = 0;
+
+/* opening the INPUT SHP */
+    shp_in = allocShapefile ();
+    openShpRead (shp_in, shp_path, &hMinX, &hMinY, &hMaxX, &hMaxY,
+		 &mismatching);
+    if (!(shp_in->Valid))
+      {
+	  char extra[512];
+	  *extra = '\0';
+	  if (shp_in->LastError)
+	      sprintf (extra, "\n\t\tcause: %s\n", shp_in->LastError);
+	  fprintf (stderr,
+		   "\t\terror: cannot open shapefile '%s'%s", shp_path, extra);
+	  freeShapefile (shp_in);
+	  return 0;
+      }
+
+/* preparing the DBF fields list - OUTPUT */
+    dbf_list = gaiaAllocDbfList ();
+    in_fld = shp_in->Dbf->First;
+    while (in_fld)
+      {
+	  /* adding a DBF field - OUTPUT */
+	  gaiaAddDbfField (dbf_list, in_fld->Name, in_fld->Type, in_fld->Offset,
+			   in_fld->Length, in_fld->Decimals);
+	  in_fld = in_fld->Next;
+      }
+
+/* creating the OUTPUT SHP */
+    shp_out = allocShapefile ();
+    openShpWrite (shp_out, out_path, shp_in->Shape, dbf_list);
+    if (!(shp_out->Valid))
+      {
+	  char extra[512];
+	  *extra = '\0';
+	  if (shp_out->LastError)
+	      sprintf (extra, "\n\t\tcause: %s\n", shp_out->LastError);
+	  fprintf (stderr,
+		   "\t\terror: cannot open shapefile '%s'%s", out_path, extra);
+	  freeShapefile (shp_in);
+	  freeShapefile (shp_out);
+	  gaiaFreeDbfList (dbf_list);
+	  return 0;
+      }
+
+    current_row = 0;
+    while (1)
+      {
+	  /* reading rows from shapefile */
+	  int shplen;
+	  ret =
+	      readShpEntity (shp_in, current_row, &shplen, &minx, &miny, &maxx,
+			     &maxy);
+	  if (ret < 0)
+	    {
+		/* found a DBF deleted record */
+		current_row++;
+		continue;
+	    }
+	  if (!ret)
+	    {
+		if (!(shp_in->LastError))	/* normal SHP EOF */
+		    break;
+		fprintf (stderr, "\t\tERROR: %s\n", shp_in->LastError);
+		goto stop;
+	    }
+	  if (validate || force)
+	    {
+		/* attempting to rearrange geometries */
+		unsigned char *bufshp;
+		int buflen;
+		int nullshape;
+		gaiaGeomCollPtr geom =
+		    do_parse_geometry (shp_in->BufShp, shplen,
+				       shp_in->EffectiveDims,
+				       shp_in->EffectiveType, &nullshape);
+		if (nullshape)
+		    goto default_null;
+		if (geom == NULL)
+		  {
+		      fprintf (stderr,
+			       "\t\tinput row #%d: unexpected NULL geometry\n",
+			       current_row);
+		      *repair_failed = 1;
+		      goto default_null;
+		  }
+
+		if (validate)
+		  {
+		      /* testing for invalid Geometries */
+		      int is_invalid = 0;
+		      if (esri)
+			{
+			    /* checking invalid geometries in ESRI mode */
+			    gaiaGeomCollPtr detail;
+			    detail = gaiaIsValidDetailEx_r (cache, geom, 1);
+			    if (detail == NULL)
+			      {
+				  /* extra checks */
+				  int extra = 0;
+				  if (gaiaIsToxic_r (cache, geom))
+				      extra = 1;
+				  if (gaiaIsNotClosedGeomColl_r (cache, geom))
+				      extra = 1;
+				  if (extra)
+				      is_invalid = 1;
+			      }
+			    else
+			      {
+				  is_invalid = 1;
+				  gaiaFreeGeomColl (detail);
+			      }
+			}
+		      else
+			{
+			    /* checking invalid geometries in ISO/OGC mode */
+			    if (gaiaIsValid_r (cache, geom) != 1)
+				is_invalid = 1;
+			}
+
+		      if (is_invalid)
+			{
+			    /* attempting to repair an invalid Geometry */
+			    char *expected;
+			    char *actual;
+			    gaiaGeomCollPtr discarded;
+			    gaiaGeomCollPtr result =
+				gaiaMakeValid (cache, geom);
+			    if (result == NULL)
+			      {
+				  fprintf (stderr,
+					   "\t\tinput row #%d: unexpected MakeValid failure\n",
+					   current_row);
+				  gaiaFreeGeomColl (geom);
+				  *repair_failed = 1;
+				  goto default_null;
+			      }
+			    discarded = gaiaMakeValidDiscarded (cache, geom);
+			    if (discarded != NULL)
+			      {
+				  fprintf (stderr,
+					   "\t\tinput row #%d: MakeValid reports discarded elements\n",
+					   current_row);
+				  gaiaFreeGeomColl (result);
+				  gaiaFreeGeomColl (discarded);
+				  gaiaFreeGeomColl (geom);
+				  *repair_failed = 1;
+				  goto default_null;
+			      }
+			    if (!check_geometry_verbose
+				(result, shp_in->Shape, &expected, &actual))
+			      {
+				  fprintf (stderr,
+					   "\t\tinput row #%d: MakeValid returned an invalid SHAPE (expected %s, got %s)\n",
+					   current_row, expected, actual);
+				  free (expected);
+				  free (actual);
+				  gaiaFreeGeomColl (result);
+				  gaiaFreeGeomColl (geom);
+				  *repair_failed = 1;
+				  goto default_null;
+			      }
+			    gaiaFreeGeomColl (geom);
+			    geom = result;
+			}
+
+		      if (!do_export_geometry
+			  (geom, &bufshp, &buflen, shp_in->Shape,
+			   shp_out->DbfRecno, current_row,
+			   shp_out->EffectiveDims))
+			{
+			    gaiaFreeGeomColl (geom);
+			    goto stop;
+			}
+		      gaiaFreeGeomColl (geom);
+		  }
+		  else
+		  {
+		      if (!do_export_geometry
+			  (geom, &bufshp, &buflen, shp_in->Shape,
+			   shp_out->DbfRecno, current_row,
+			   shp_out->EffectiveDims))
+			{
+			    gaiaFreeGeomColl (geom);
+			    goto stop;
+			}
+		      gaiaFreeGeomColl (geom);
+		  }
+		goto ok_geom;
+
+	      default_null:
+		/* exporting a NULL shape */
+		do_export_geometry
+		    (NULL, &bufshp, &buflen, shp_in->Shape,
+		     shp_out->DbfRecno, current_row, shp_out->EffectiveDims);
+
+	      ok_geom:
+		ret = writeShpEntity
+		    (shp_out, bufshp, buflen, shp_in->BufDbf,
+		     shp_in->DbfReclen);
+		free (bufshp);
+		if (!ret)
+		    goto stop;
+	    }
+	  else
+	    {
+		/* passing geometries exactly as they were */
+		if (!writeShpEntity
+		    (shp_out, shp_in->BufShp, shplen, shp_in->BufDbf,
+		     shp_in->DbfReclen))
+		    goto stop;
+	    }
+	  current_row++;
+      }
+    gaiaFlushShpHeaders (shp_out);
+    freeShapefile (shp_in);
+    freeShapefile (shp_out);
+    return 1;
+
+  stop:
+    freeShapefile (shp_in);
+    freeShapefile (shp_out);
+    fprintf (stderr,
+	     "\t\tMalformed shapefile, impossible to repair: quitting\n");
+    return 0;
+}
+
+static int
+do_test_shapefile (const void *cache, const char *shp_path, int validate,
+		   int esri, int *invalid)
+{
+/* testing a Shapefile for validity */
+    int n_invalid;
+
+    fprintf (stderr, "\nVerifying %s.shp\n", shp_path);
+    *invalid = 0;
+    if (!do_read_shp (cache, shp_path, validate, esri, &n_invalid))
+	return 0;
+    if (n_invalid)
+      {
+	  fprintf (stderr, "\tfound %d invalidit%s: cleaning required.\n",
+		   n_invalid, (n_invalid > 1) ? "ies" : "y");
+	  *invalid = 1;
+      }
+    else
+	fprintf (stderr, "\tfound to be already valid.\n");
+    return 1;
+}
+
+static int
+check_extension (const char *file_name)
+{
+/* checks the file extension */
+    const char *mark = NULL;
+    int len = strlen (file_name);
+    const char *p = file_name + len - 1;
+
+    while (p >= file_name)
+      {
+	  if (*p == '.')
+	      mark = p;
+	  p--;
+      }
+    if (mark == NULL)
+	return SUFFIX_DISCARD;
+    if (strcasecmp (mark, ".shp") == 0)
+	return SUFFIX_SHP;
+    if (strcasecmp (mark, ".shx") == 0)
+	return SUFFIX_SHX;
+    if (strcasecmp (mark, ".dbf") == 0)
+	return SUFFIX_DBF;
+    return SUFFIX_DISCARD;
+}
+
+static int
+do_scan_dir (const void *cache, const char *in_dir, const char *out_dir,
+	     int *n_shp, int *r_shp, int *x_shp, int validate, int esri,
+	     int force)
+{
+/* scanning a directory and searching for Shapefiles to be checked */
+    struct shp_entry *p_shp;
+    struct shp_list *list = alloc_shp_list ();
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* Visual Studio .NET */
+    struct _finddata_t c_file;
+    intptr_t hFile;
+    char *path;
+    char *name;
+    int len;
+    int ret;
+    if (_chdir (in_dir) < 0)
+	goto error;
+    if ((hFile = _findfirst ("*.shp", &c_file)) == -1L)
+	;
+    else
+      {
+	  while (1)
+	    {
+		if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
+		    || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
+		  {
+		      name = sqlite3_mprintf ("%s", c_file.name);
+		      len = strlen (name);
+		      name[len - 4] = '\0';
+		      path = sqlite3_mprintf ("%s/%s", in_dir, name);
+		      do_add_shapefile (list, path, name, SUFFIX_SHP);
+		  }
+		if (_findnext (hFile, &c_file) != 0)
+		    break;
+	    }
+	  _findclose (hFile);
+	  if ((hFile = _findfirst ("*.shx", &c_file)) == -1L)
+	      ;
+	  else
+	    {
+		while (1)
+		  {
+		      if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
+			  || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
+			{
+			    name = sqlite3_mprintf ("%s", c_file.name);
+			    len = strlen (name);
+			    name[len - 4] = '\0';
+			    path = sqlite3_mprintf ("%s/%s", in_dir, name);
+			    do_add_shapefile (list, path, name, SUFFIX_SHX);
+			}
+		      if (_findnext (hFile, &c_file) != 0)
+			  break;
+		  }
+		_findclose (hFile);
+		if ((hFile = _findfirst ("*.dbf", &c_file)) == -1L)
+		    ;
+		else
+		  {
+		      while (1)
+			{
+			    if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
+				|| (c_file.attrib & _A_NORMAL) == _A_NORMAL)
+			      {
+				  name = sqlite3_mprintf ("%s", c_file.name);
+				  len = strlen (name);
+				  name[len - 4] = '\0';
+				  path =
+				      sqlite3_mprintf ("%s/%s", in_dir, name);
+				  do_add_shapefile (list, path, name,
+						    SUFFIX_DBF);
+			      }
+			    if (_findnext (hFile, &c_file) != 0)
+				break;
+			}
+		      _findclose (hFile);
+		  }
+	    }
+      }
+#else
+/* not Visual Studio .NET */
+    char *path;
+    char *name;
+    struct dirent *entry;
+    int len;
+    int suffix;
+    DIR *dir = opendir (in_dir);
+    if (!dir)
+	goto error;
+    while (1)
+      {
+	  /* extracting the SHP candidates */
+	  entry = readdir (dir);
+	  if (!entry)
+	      break;
+	  suffix = check_extension (entry->d_name);
+	  if (suffix == SUFFIX_DISCARD)
+	      continue;
+	  path = sqlite3_mprintf ("%s/%s", in_dir, entry->d_name);
+	  len = strlen (path);
+	  path[len - 4] = '\0';
+	  name = sqlite3_mprintf ("%s", entry->d_name);
+	  len = strlen (name);
+	  name[len - 4] = '\0';
+	  do_add_shapefile (list, path, name, suffix);
+      }
+    closedir (dir);
+#endif
+
+    p_shp = list->first;
+    while (p_shp != NULL)
+      {
+	  if (test_valid_shp (p_shp))
+	    {
+		int invalid;
+		if (!do_test_shapefile
+		    (cache, p_shp->base_name, validate, esri, &invalid))
+		    goto error;
+		*n_shp += 1;
+		if (invalid)
+		    *x_shp += 1;
+		if ((invalid || force) && out_dir != NULL)
+		  {
+		      /* attempting to repair */
+		      int repair_failed;
+		      int ret;
+		      char *out_path = sqlite3_mprintf ("%s/%s", out_dir,
+							p_shp->file_name);
+		      fprintf (stderr, "\tAttempting to repair: %s.shp\n",
+			       out_path);
+		      ret =
+			  do_repair_shapefile (cache, p_shp->base_name,
+					       out_path, validate, esri, force,
+					       &repair_failed);
+		      sqlite3_free (out_path);
+		      if (!ret)
+			  goto error;
+		      if (repair_failed)
+			{
+			    do_clen_files (out_dir, p_shp->base_name);
+			    fprintf (stderr,
+				     "\tFAILURE: automatic repair is impossible, manual repair required.\n");
+			}
+		      else
+			{
+			    *r_shp += 1;
+			    fprintf (stderr, "\tOK, successfully repaired.\n");
+			}
+		  }
+	    }
+	  p_shp = p_shp->next;
+      }
+
+    free_shp_list (list);
+    return 1;
+
+  error:
+    free_shp_list (list);
+    fprintf (stderr, "Unable to access \"%s\"\n", in_dir);
+    return 0;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: shp_sanitize ARGLIST\n");
+    fprintf (stderr,
+	     "=================================================================\n");
+    fprintf (stderr,
+	     "-h or --help                      print this help message\n");
+    fprintf (stderr,
+	     "-idir or --in-dir   dir-path      directory expected to contain\n"
+	     "                                  all SHP to be checked\n");
+    fprintf (stderr,
+	     "-odir or --out-dir  dir-path      <optional> directory where to\n"
+	     "                                  store all repaired SHPs\n\n");
+    fprintf (stderr,
+	     "======================= optional args ===========================\n"
+	     "-geom or --invalid-geoms          checks for invalid Geometries\n"
+	     "-esri or --esri-flag              tolerates ESRI-like inner holes\n"
+	     "-force or --force-repair          unconditionally repair\n\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function simply perform arguments checking */
+    int i;
+    int error = 0;
+    int next_arg = ARG_NONE;
+    char *in_dir = NULL;
+    char *out_dir = NULL;
+    int validate = 0;
+    int esri = 0;
+    int force = 0;
+    int n_shp = 0;
+    int r_shp = 0;
+    int x_shp = 0;
+    const void *cache;
+
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_IN_DIR:
+		      in_dir = argv[i];
+		      break;
+		  case ARG_OUT_DIR:
+		      out_dir = argv[i];
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcasecmp (argv[i], "-idir") == 0
+	      || strcasecmp (argv[i], "--in-dir") == 0)
+	    {
+		next_arg = ARG_IN_DIR;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-odir") == 0
+	      || strcasecmp (argv[i], "--out-dir") == 0)
+	    {
+		next_arg = ARG_OUT_DIR;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-geom") == 0
+	      || strcasecmp (argv[i], "--invalid-geoms") == 0)
+	    {
+		validate = 1;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-esri") == 0
+	      || strcasecmp (argv[i], "--esri-flag") == 0)
+	    {
+		esri = 1;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-force") == 0
+	      || strcasecmp (argv[i], "--force-repair") == 0)
+	    {
+		force = 1;
+		continue;
+	    }
+	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+/* checking the arguments */
+    if (!in_dir)
+      {
+	  fprintf (stderr, "did you forget setting the --in-dir argument ?\n");
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+    if (out_dir != NULL)
+      {
+#ifdef _WIN32
+	  if (_mkdir (out_dir) != 0)
+#else
+	  if (mkdir (out_dir, 0777) != 0)
+#endif
+	    {
+		fprintf (stderr,
+			 "ERROR: unable to create the output directory\n%s\n%s\n\n",
+			 out_dir, strerror (errno));
+		return -1;
+	    }
+      }
+
+    cache = spatialite_alloc_connection ();
+    spatialite_set_silent_mode (cache);
+    fprintf (stderr, "\nInput dir: %s\n", in_dir);
+    if (out_dir != NULL)
+      {
+	  fprintf (stderr, "Output dir: %s\n", out_dir);
+	  if (force)
+	      fprintf (stderr, "Unconditionally repairing all Shapefiles\n");
+      }
+    else
+	fprintf (stderr, "Only a diagnostic report will be reported\n");
+    if (validate)
+      {
+	  fprintf (stderr, "Checking for invalid geometries (%s mode)\n",
+		   esri ? "ESRI" : "ISO/OGC");
+      }
+
+    if (!do_scan_dir
+	(cache, in_dir, out_dir, &n_shp, &r_shp, &x_shp, validate, esri, force))
+      {
+	  fprintf (stderr,
+		   "\n... quitting ... some unexpected error occurred\n");
+	  spatialite_cleanup_ex (cache);
+	  return -1;
+      }
+
+    fprintf (stderr, "\n===========================================\n");
+    fprintf (stderr, "%d Shapefil%s ha%s been inspected.\n", n_shp,
+	     (n_shp > 1) ? "es" : "e", (n_shp > 1) ? "ve" : "s");
+    fprintf (stderr, "%d malformed Shapefil%s ha%s been identified.\n", x_shp,
+	     (x_shp > 1) ? "es" : "e", (x_shp > 1) ? "ve" : "s");
+    fprintf (stderr, "%d Shapefil%s ha%s been repaired.\n\n", r_shp,
+	     (r_shp > 1) ? "es" : "e", (r_shp > 1) ? "ve" : "s");
+
+    spatialite_cleanup_ex (cache);
+    return 0;
+}
diff --git a/spatialite_osm_map.c b/spatialite_osm_map.c
index d75b0c2..9a23e12 100644
--- a/spatialite_osm_map.c
+++ b/spatialite_osm_map.c
@@ -367,11 +367,10 @@ point_layer_insert (struct aux_params *params, const char *layer_name,
 		      ret = sqlite3_step (layer->ins_point_stmt);
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
-		      fprintf (stderr, "sqlite3_step() error: INS_POINT %s\n",
-			       layer_name);
-		      sqlite3_finalize (layer->ins_point_stmt);
-		      layer->ins_point_stmt = NULL;
-		      return 0;
+		      fprintf (stderr,
+			       "sqlite3_step() error: INS_POINT %s (%s)\n",
+			       layer_name, sqlite3_errmsg (params->db_handle));
+		      return 1;
 		  }
 		return 1;
 	    }
@@ -406,10 +405,9 @@ point_generic_insert (struct aux_params *params, const readosm_node * node,
 	  ret = sqlite3_step (params->ins_generic_point_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
-	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_POINT\n");
-	  sqlite3_finalize (params->ins_generic_point_stmt);
-	  params->ins_generic_point_stmt = NULL;
-	  return 0;
+	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_POINT (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }
@@ -468,10 +466,9 @@ address_insert (struct aux_params *params, const readosm_node * node,
 	  ret = sqlite3_step (params->ins_addresses_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
-	  fprintf (stderr, "sqlite3_step() error: INS_ADDRESSES\n");
-	  sqlite3_finalize (params->ins_addresses_stmt);
-	  params->ins_addresses_stmt = NULL;
-	  return 0;
+	  fprintf (stderr, "sqlite3_step() error: INS_ADDRESSES (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }
@@ -490,10 +487,9 @@ tmp_nodes_insert (struct aux_params *params, const readosm_node * node)
     ret = sqlite3_step (params->ins_tmp_nodes_stmt);
     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	return 1;
-    fprintf (stderr, "sqlite3_step() error: INS_TMP_NODES\n");
-    sqlite3_finalize (params->ins_tmp_nodes_stmt);
-    params->ins_tmp_nodes_stmt = NULL;
-    return 0;
+    fprintf (stderr, "sqlite3_step() error: INS_TMP_NODES (%s)\n",
+	     sqlite3_errmsg (params->db_handle));
+    return 1;
 }
 
 static int
@@ -808,11 +804,9 @@ line_layer_insert (struct aux_params *params, const char *layer_name,
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
 		      fprintf (stderr,
-			       "sqlite3_step() error: INS_LINESTRING %s\n",
-			       layer_name);
-		      sqlite3_finalize (layer->ins_linestring_stmt);
-		      layer->ins_linestring_stmt = NULL;
-		      return 0;
+			       "sqlite3_step() error: INS_LINESTRING %s (%s)\n",
+			       layer_name, sqlite3_errmsg (params->db_handle));
+		      return 1;
 		  }
 		return 1;
 	    }
@@ -862,11 +856,9 @@ polygon_layer_insert (struct aux_params *params, const char *layer_name,
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
 		      fprintf (stderr,
-			       "sqlite3_step() error: INS_POLYGON %s\n",
-			       layer_name);
-		      sqlite3_finalize (layer->ins_polygon_stmt);
-		      layer->ins_polygon_stmt = NULL;
-		      return 0;
+			       "sqlite3_step() error: INS_POLYGON %s (%s)\n",
+			       layer_name, sqlite3_errmsg (params->db_handle));
+		      return 1;
 		  }
 		return 1;
 	    }
@@ -894,10 +886,10 @@ line_generic_insert (struct aux_params *params, sqlite3_int64 id,
 	  ret = sqlite3_step (params->ins_generic_linestring_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
-	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_LINESTRING\n");
-	  sqlite3_finalize (params->ins_generic_linestring_stmt);
-	  params->ins_generic_linestring_stmt = NULL;
-	  return 0;
+	  fprintf (stderr,
+		   "sqlite3_step() error: INS_GENERIC_LINESTRING (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }
@@ -922,10 +914,9 @@ polygon_generic_insert (struct aux_params *params, sqlite3_int64 id,
 	  ret = sqlite3_step (params->ins_generic_polygon_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
-	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_POLYGON\n");
-	  sqlite3_finalize (params->ins_generic_polygon_stmt);
-	  params->ins_generic_polygon_stmt = NULL;
-	  return 0;
+	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_POLYGON (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }
@@ -947,10 +938,9 @@ tmp_ways_insert (struct aux_params *params, sqlite3_int64 id, int area,
 
     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	return 1;
-    fprintf (stderr, "sqlite3_step() error: INS_TMP_WAYS\n");
-    sqlite3_finalize (params->ins_tmp_ways_stmt);
-    params->ins_tmp_ways_stmt = NULL;
-    return 0;
+    fprintf (stderr, "sqlite3_step() error: INS_TMP_WAYS (%s)\n",
+	     sqlite3_errmsg (params->db_handle));
+    return 1;
 }
 
 static int
@@ -1422,11 +1412,9 @@ multiline_layer_insert (struct aux_params *params, const char *layer_name,
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
 		      fprintf (stderr,
-			       "sqlite3_step() error: INS_MULTILINESTRING %s\n",
-			       layer_name);
-		      sqlite3_finalize (layer->ins_linestring_stmt);
-		      layer->ins_linestring_stmt = NULL;
-		      return 0;
+			       "sqlite3_step() error: INS_MULTILINESTRING %s (%s)\n",
+			       layer_name, sqlite3_errmsg (params->db_handle));
+		      return 1;
 		  }
 		return 1;
 	    }
@@ -1821,11 +1809,9 @@ multipolygon_layer_insert (struct aux_params *params, const char *layer_name,
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
 		      fprintf (stderr,
-			       "sqlite3_step() error: INS_MULTIPOLYGON %s\n",
-			       layer_name);
-		      sqlite3_finalize (layer->ins_polygon_stmt);
-		      layer->ins_polygon_stmt = NULL;
-		      return 0;
+			       "sqlite3_step() error: INS_MULTIPOLYGON %s (%s)\n",
+			       layer_name, sqlite3_errmsg (params->db_handle));
+		      return 1;
 		  }
 		return 1;
 	    }
@@ -1864,10 +1850,9 @@ multiline_generic_insert (struct aux_params *params,
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
 	  fprintf (stderr,
-		   "sqlite3_step() error: INS_GENERIC_MULTILINESTRING\n");
-	  sqlite3_finalize (params->ins_generic_linestring_stmt);
-	  params->ins_generic_linestring_stmt = NULL;
-	  return 0;
+		   "sqlite3_step() error: INS_GENERIC_MULTILINESTRING (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }
@@ -1903,10 +1888,10 @@ multipolygon_generic_insert (struct aux_params *params,
 	  ret = sqlite3_step (params->ins_generic_polygon_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
-	  fprintf (stderr, "sqlite3_step() error: INS_GENERIC_MULTIPOLYGON\n");
-	  sqlite3_finalize (params->ins_generic_polygon_stmt);
-	  params->ins_generic_polygon_stmt = NULL;
-	  return 0;
+	  fprintf (stderr,
+		   "sqlite3_step() error: INS_GENERIC_MULTIPOLYGON (%s)\n",
+		   sqlite3_errmsg (params->db_handle));
+	  return 1;
       }
     return 1;
 }

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



More information about the Pkg-grass-devel mailing list