[SCM] shapelib branch, upstream, updated. upstream/1.2.10-1-g796f930
Arto Jantunen
viiru at debian.org
Sat Nov 9 12:36:42 UTC 2013
The following commit has been merged in the upstream branch:
commit 796f930ea312f1ab4ff627ad15f0bd9c39d71d45
Author: Arto Jantunen <viiru at debian.org>
Date: Fri May 18 10:33:11 2012 +0300
Imported Upstream version 1.3.0
diff --git a/.cvsignore b/.cvsignore
index fead322..6fbd556 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,10 +1,15 @@
-shpcreate
-shpadd
-shpdump
-dbfcreate
dbfadd
+dbfcreate
dbfdump
-shptest
-shptreedump
-shputils
+shpadd
+shpcreate
+shpdump
shprewind
+shptreedump
+shptest
+*.dll
+*.lib
+*.exp
+*.la
+*.lo
+.libs
diff --git a/ChangeLog b/ChangeLog
index 0675b70..d0227a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,249 @@
+2012-01-27 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shptree.c: optimize quadtree generation (gdal #4472)
+
+2012-01-24 Frank Warmerdam <warmerdam at google.com>
+
+ * shpopen.c: fix memory leaks on failure to open .shp file.
+
+2011-12-11 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shptree.c,h: Use SAHooks for .qix access (gdal #3365)
+
+2011-09-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: fix missing cast (#2344)
+
+2011-07-24 <warmerdam at pobox.com>
+
+ * shpopen.c, dbfopen.c, shptree.c, shapefil.h: Minimize use of
+ CPL services in favor of SAHooks.Error().
+
+ * Makefile: Remove all the shared library building stuff, it is just
+ too half assed, and results in all sorts of bug reports and complaints.
+ Instead just install a static libshp.a.
+
+2011-07-23 <warmerdam at pobox.com>
+
+ * Makefile: build shpdumptree as part of all target (#1648).
+
+ * shpopen.c: fix memory leaks in error cases (#2061)
+
+ * contrib/*.c: Include stdlib.h and strings.h (#2146)
+
+ * shpdump.c: change to use %.15g for coordinate reporting. (#2277)
+
+2011-05-13 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c, shapelib.h: Add functions to reorder and alter
+ field definitions. DBFReorderFields() and DBFAlterFields().
+
+2011-05-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Ensure pending record is flushed when adding a native
+ field (gdal #4073).
+
+2011-04-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shapefil.h: avoid warnings with SHP_CVSID on gcc.
+
+2010-12-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: fix read past end of init data fetching code page
+ http://bugzilla.maptools.org/show_bug.cgi?id=2276
+
+2010-07-01 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: do not error out on a shape with zero vertices.
+
+ * shpdump.c: do not crash if null shape returned by read object.
+
+2010-06-29 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shptree.c: fix sign of Z and M comparisons in SHPCheckObjectContained.
+ (http://bugzilla.maptools.org/show_bug.cgi?id=2223)
+
+2010-01-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c/shapefil.h: Handle the .shp file length limits more
+ gracefully. (http://trac.osgeo.org/gdal/ticket/3236)
+
+ * shpopen.c: Improve the numerical accurancy of algorithms in
+ SHPRewind() (http://trac.osgeo.org/gdal/ticket/3363).
+
+2010-01-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: support passing in zero/nulls to create an empty
+ SHPObject: http://bugzilla.maptools.org/show_bug.cgi?id=2148
+
+2009-10-29 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: avoid crash risk for truncated files.
+ http://trac.osgeo.org/gdal/ticket/3093
+
+2009-09-17 Bram de Greve <bram.degreve at bramz.net>
+
+ * shpopen.c: on Win32, define snprintf as alias to _snprintf
+
+2008-11-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shptree.c: improve safety in face of buggy .shp file.
+ http://trac.osgeo.org/gdal/ticket/2610
+
+ * dbfopen.c: DBFCreateField() can now also operate on files with
+ records, c/o Martin Dobias.
+ https://trac.osgeo.org/gdal/ticket/2672
+
+2008-11-11 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Introduce DBFDeleteField() function from Martin Dobias.
+ http://trac.osgeo.org/gdal/ticket/2671
+
+2008-03-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Correct crash on buggy geometries (Even Rouault).
+ http://trac.osgeo.org/gdal/ticket/2218
+
+2008-01-16 Bram de Greve <bram.degreve at bramz.net>
+
+ * shapefil.h, safileio.c: add file hooks that accept UTF-8
+ encoded filenames on some platforms. Use SASetupUtf8Hooks
+ to setup the hooks and check SHPAPI_UTF8_HOOKS for its
+ availability. Currently, this is only available on the Windows
+ platform that decodes the UTF-8 filenames to wide character
+ strings and feed them to _wfopen and _wremove.
+
+2008-01-10 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shapefil.h: Avoid _ prefix on #defines.
+ http://bugzilla.maptools.org/show_bug.cgi?id=1840
+
+2008-01-03 Bram de Greve <bram.degreve at bramz.net>
+
+ * dbfopen.c: in DBFCreate, use default code page
+ LDID/87 (= 0x57, ANSI) instead of LDID/3. This seems
+ to be the same as what ESRI would be doing by default.
+
+2007-12-30 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpadd.c/shpcreate.c: Add support for z and m files.
+
+ * Massive overhaul to use hooks for file io, etc.
+
+2007-12-18 Bram de Greve <bram.degreve at bramz.net>
+
+ * dbfopen.c/shapefil.h/safileio.c: create hook for client
+ specific atof http://bugzilla.maptools.org/show_bug.cgi?id=1615
+
+ * dbfopen.c: check for NULL handle before closing cpCPG file,
+ and close after reading.
+
+2007-12-15 Bram de Greve <bram.degreve at bramz.net>
+
+ * dbfopen.c/shapefil.h/safileio.c: read the Code Page information
+ from the DBF file, and exports this information as a string through
+ the DBFGetCodePage function. This is either the number from the LDID
+ header field ("LDID/<number>") or as the content of an accompanying
+ .CPG file. When creating a DBF file, the code can be set using
+ DBFCreateEx.
+
+2007-12-12 Bram de Greve <bram.degreve at bramz.net>
+
+ * dbfopen.c: check for NULL handle in DBFClose.
+
+2007-11-21 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c/shapefil.h: Don't keep .shx file open in read-only mode.
+ http://trac.osgeo.org/gdal/ticket/1956
+
+2007-11-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: checks after mallocs to detect for corrupted/voluntary
+ broken shapefiles. http://trac.osgeo.org/gdal/ticket/1991
+
+2007-09-03 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpgeo.c: Fixed SHPDimension() (missing breaks) in shpgeo.c.
+ Fix contributed by Andrea Peri.
+
+ * dbfopen.c: Move the static dDoubleField return buffer into DBFInfo
+ structure to avoid multithreaded risks.
+
+ * dbfopen.c: Simplify DBFReadTuple() to avoid use of static tuple.
+ Note that this means DBFReadTuple() results are only valid till the
+ next record is read for any reason.
+
+2007-06-21 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: Fix for SHPRewind() for "contact at one vertex"
+ cases in rings. http://trac.osgeo.org/gdal/ticket/976
+
+2006-11-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * contrib/shpgeo.c: Modified SHPProject to use pj_transform() so
+ it works for datums and stuff. Submitted by Steffen Macke.
+
+2006-09-04 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpeopen.c: (MLoskot) Added stronger test of Shapefile reading
+ failures, e.g. truncated files. The problem was discovered by Tim
+ Sutton and reported here:
+ https://svn.qgis.org/trac/ticket/200
+
+2006-06-17 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: use calloc() for DBFInfo in DBFCreate() to ensure
+ all fields initialized to zero if not otherwise mentioned.
+
+ * dbfopen.c: Don't allow creation of string fields with width larger
+ than 255 per http://bugzilla.maptools.org/show_bug.cgi?id=1434
+
+2006-06-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Don't treat decimals value as high order field length
+ for strings, as it causes serious bugs in some cases such as
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1202
+
+ * dbfopen.c: Made static field buffer in DBFReadAttribute() into a
+ field in the DBFInfo structure to avoid multi-threading problems.
+
+2006-03-29 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Fixed bug in DBFCloneEmpty() (treating pachFieldType as
+ an array of int).
+
+2006-02-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: Changed to put spaces into string fields that are NULL
+ as per http://bugzilla.maptools.org/show_bug.cgi?id=316.
+
+2006-01-26 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c, shapefil.h, shpdump.c: Added bMeasureIsUsed support as
+ per http://bugzilla.maptools.org/show_bug.cgi?id=1249
+
+2006-01-04 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c/shapefil.h: Added functions to check if dbf record is
+ deleted, and to mark it as deleted.
+
+2005-02-11 Frank Warmerdam <warmerdam at pobox.com>
+
+ * shpopen.c: Check panPartStart[0] is 0 in SHPCreateObject().
+
+ * Fixed bug 305 in DBFCloneEmpty() - header length problem.
+
+ * Make the pszStringField buffer for DBFReadAttribute() static char
+ [256] as per bug 306.
+
+2004-09-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * dbfopen.c: treat all blanks as NULL in DBFIsAttributeNULL().
+
+2004-06-23 Frank Warmerdam <warmerdam at pobox.com>
+
+ * contrib/shpsort.c: added new contribute program from Eric Miller.
+
2003-04-07 Frank Warmerdam <warmerdam at pobox.com>
* Issue 1.2.10 Release.
diff --git a/HOWTO-RELEASE b/HOWTO-RELEASE
new file mode 100644
index 0000000..b86f349
--- /dev/null
+++ b/HOWTO-RELEASE
@@ -0,0 +1,16 @@
+ Producing Shapelib Releases
+ ===========================
+
+1) Update web/release.html with change notes on the new release and commit.
+
+2) Build the release files.
+
+ ./mkrelease.sh 1.3.0
+
+3) Upload:
+
+ scp shapelib-1.3.0{.tar.gz,.zip} warmerdam at upload.osgeo.org:/osgeo/download/shapelib
+ ... add upload notes to maptools.org ...
+
+4) Announce on shapelib mailing list.
+
diff --git a/Makefile b/Makefile
index 6d24091..0c41d8a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,16 @@
-#LINKOPT = /usr/local/lib/libdbmalloc.a
-CFLAGS = -g
+PREFIX = /usr/local
+CFLAGS = -g -Wall -fPIC
+#CFLAGS = -g -DUSE_CPL
+#CC = g++
+
+LIBOBJ = shpopen.o dbfopen.o safileio.o shptree.o
+SHPBIN = shpcreate shpadd shpdump shprewind dbfcreate dbfadd dbfdump \
+ shptreedump
default: all
-all: shpcreate shpadd shpdump shprewind dbfcreate dbfadd dbfdump shptest
+all: $(SHPBIN) shptest lib
shpopen.o: shpopen.c shapefil.h
$(CC) $(CFLAGS) -c shpopen.c
@@ -15,42 +21,42 @@ shptree.o: shptree.c shapefil.h
dbfopen.o: dbfopen.c shapefil.h
$(CC) $(CFLAGS) -c dbfopen.c
-shpcreate: shpcreate.c shpopen.o
- $(CC) $(CFLAGS) shpcreate.c shpopen.o $(LINKOPT) -o shpcreate
+safileio.o: safileio.c shapefil.h
+ $(CC) $(CFLAGS) -c safileio.c
+
+shpcreate: shpcreate.c shpopen.o safileio.o
+ $(CC) $(CFLAGS) shpcreate.c shpopen.o safileio.o $(LINKOPT) -o shpcreate
-shpadd: shpadd.c shpopen.o
- $(CC) $(CFLAGS) shpadd.c shpopen.o $(LINKOPT) -o shpadd
+shpadd: shpadd.c shpopen.o safileio.o
+ $(CC) $(CFLAGS) shpadd.c shpopen.o safileio.o $(LINKOPT) -o shpadd
-shpdump: shpdump.c shpopen.o
- $(CC) $(CFLAGS) shpdump.c shpopen.o $(LINKOPT) -o shpdump
+shpdump: shpdump.c shpopen.o safileio.o
+ $(CC) $(CFLAGS) shpdump.c shpopen.o safileio.o $(LINKOPT) -o shpdump
-shprewind: shprewind.c shpopen.o
- $(CC) $(CFLAGS) shprewind.c shpopen.o $(LINKOPT) -o shprewind
+shprewind: shprewind.c shpopen.o safileio.o
+ $(CC) $(CFLAGS) shprewind.c shpopen.o safileio.o $(LINKOPT) -o shprewind
-dbfcreate: dbfcreate.c dbfopen.o
- $(CC) $(CFLAGS) dbfcreate.c dbfopen.o $(LINKOPT) -o dbfcreate
+dbfcreate: dbfcreate.c dbfopen.o safileio.o
+ $(CC) $(CFLAGS) dbfcreate.c dbfopen.o safileio.o $(LINKOPT) -o dbfcreate
-dbfadd: dbfadd.c dbfopen.o
- $(CC) $(CFLAGS) dbfadd.c dbfopen.o $(LINKOPT) -o dbfadd
+dbfadd: dbfadd.c dbfopen.o safileio.o
+ $(CC) $(CFLAGS) dbfadd.c dbfopen.o safileio.o $(LINKOPT) -o dbfadd
-dbfdump: dbfdump.c dbfopen.o
- $(CC) $(CFLAGS) dbfdump.c dbfopen.o $(LINKOPT) -o dbfdump
+dbfdump: dbfdump.c dbfopen.o safileio.o
+ $(CC) $(CFLAGS) dbfdump.c dbfopen.o safileio.o $(LINKOPT) -o dbfdump
-shptest: shptest.c shpopen.o
- $(CC) $(CFLAGS) shptest.c shpopen.o $(LINKOPT) -o shptest
+shptest: shptest.c shpopen.o safileio.o
+ $(CC) $(CFLAGS) shptest.c shpopen.o safileio.o $(LINKOPT) -o shptest
-shputils: shputils.c shpopen.o dbfopen.o
- $(CC) $(CFLAGS) shputils.c shpopen.o dbfopen.o $(LINKOPT) -o shputils
+shputils: shputils.c shpopen.o safileio.o dbfopen.o
+ $(CC) $(CFLAGS) shputils.c shpopen.o safileio.o dbfopen.o $(LINKOPT) -o shputils
-shptreedump: shptreedump.c shptree.o shpopen.o
- $(CC) $(CFLAGS) shptreedump.c shptree.o shpopen.o $(LINKOPT) \
+shptreedump: shptreedump.c shptree.o shpopen.o safileio.o
+ $(CC) $(CFLAGS) shptreedump.c shptree.o shpopen.o safileio.o $(LINKOPT) \
-o shptreedump
clean:
- rm -f *.o dbfdump dbfcreate dbfadd shpdump shpcreate shpadd shputils
- rm -f shptreedump
- rm -rf *.lo *.la .libs
- rm -f shptest
+ rm -f *.o shptest $(SHPBIN) libshp.a
test: test2 test3
@@ -91,52 +97,17 @@ test3:
fi
-# -----------------------------------------------------------------------------
-# The following is contributed by Jan-Oliver Wagner, and should allow for
-# creating shared libraries on most platforms with gcc, and libtool installed.
-
-SHPLIB_VERSION=1.2.9
-LIBSHP_VERSION=1.0.1 # still once to be changed manually (see for 1:1:0), sorry
-
-lib:
- /bin/sh ./libtool --mode=compile gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c shpopen.c
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c -fPIC -DPIC shpopen.c -o .libs/shpopen.lo
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c shpopen.c -o shpopen.o >/dev/null 2>&1
- mv -f .libs/shpopen.lo shpopen.lo
- /bin/sh ./libtool --mode=compile gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c shptree.c
- rm -f .libs/shptree.lo
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c -fPIC -DPIC shptree.c -o .libs/shptree.lo
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c shptree.c -o shptree.o >/dev/null 2>&1
- mv -f .libs/shptree.lo shptree.lo
- /bin/sh ./libtool --mode=compile gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c dbfopen.c
- rm -f .libs/dbfopen.lo
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c -fPIC -DPIC dbfopen.c -o .libs/dbfopen.lo
- gcc -DPACKAGE=\"libshp\" -DVERSION=\"$(SHPLIB_VERSION)\" -DSTDC_HEADERS=1 -I. -I. -I/usr/local/include -g -O2 -c dbfopen.c -o dbfopen.o >/dev/null 2>&1
- mv -f .libs/dbfopen.lo dbfopen.lo
- /bin/sh ./libtool --mode=link gcc -g -O2 -o libshp.la -rpath /usr/local/lib -version-info 1:1:0 shpopen.lo shptree.lo dbfopen.lo
- rm -fr .libs/libshp.la .libs/libshp.* .libs/libshp.*
- rm -fr .libs/libshp.lax
- mkdir .libs/libshp.lax
- /usr/bin/ld -G -h libshp.so.1 -o .libs/libshp.so.$(LIBSHP_VERSION) shpopen.lo shptree.lo dbfopen.lo -lc
-
- (cd .libs && rm -f libshp.so.1 && ln -s libshp.so.$(LIBSHP_VERSION) libshp.so.1)
- (cd .libs && rm -f libshp.so && ln -s libshp.so.$(LIBSHP_VERSION) libshp.so)
- ar cru .libs/libshp.a shpopen.o shptree.o dbfopen.o
- ranlib .libs/libshp.a
- rm -fr .libs/libshp.lax
- (cd .libs && rm -f libshp.la && ln -s ../libshp.la libshp.la)
-
-lib_install:
- cp .libs/libshp.la .libs/libshp.lai
- /bin/sh ./mkinstalldirs /usr/local/lib
- /bin/sh ./libtool --mode=install /usr/bin/install -c libshp.la /usr/local/lib/libshp.la
- /usr/bin/install -c .libs/libshp.so.$(LIBSHP_VERSION) /usr/local/lib/libshp.so.$(LIBSHP_VERSION)
- (cd /usr/local/lib && rm -f libshp.so.1 && ln -s libshp.so.$(LIBSHP_VERSION) libshp.so.1)
- (cd /usr/local/lib && rm -f libshp.so && ln -s libshp.so.$(LIBSHP_VERSION) libshp.so)
- chmod +x /usr/local/lib/libshp.so.$(LIBSHP_VERSION)
- /usr/bin/install -c .libs/libshp.la /usr/local/lib/libshp.la
- /usr/bin/install -c .libs/libshp.a /usr/local/lib/libshp.a
- ranlib /usr/local/lib/libshp.a
- chmod 644 /usr/local/lib/libshp.a
- /bin/sh ./mkinstalldirs /usr/local/include/libshp
- /usr/bin/install -c -m 644 shapefil.h /usr/local/include/libshp/shapefil.h
+lib: libshp.a
+
+libshp.a: $(LIBOBJ)
+ ar r libshp.a $(LIBOBJ)
+
+lib_install: libshp.a
+ cp libshp.a $(PREFIX)/lib
+ cp shapefil.h $(PREFIX)/include
+
+bin_install: $(SHPBIN)
+ cp $(SHPBIN) $(PREFIX)/bin
+
+install: lib_install bin_install
+
diff --git a/README b/README
index ad5faa3..5ae71bb 100755
--- a/README
+++ b/README
@@ -7,20 +7,26 @@ Building on Unix
1) Edit Makefile, and set CFLAGS, and CC macros as required for the
target system. Often the defaults will work fine.
-2) "type make"
+2) type "make"
The result should be:
Core shapelib support.
shpopen.o
dbfopen.o
+ safileio.o
+ shptree.o
+ libshp.a
Utility/demonstration programs:
- shpcreate, shpdump, shpadd, dbfcreate, dbfdump, dbfadd
+ shpcreate, shpdump, shpadd, dbfcreate, dbfdump, dbfadd, shptreedump
-To test type:
+3) To test type:
make test
+4) To libshp.a and the test binaries in /usr/local:
+ make install
+
Building on Windows
-------------------
diff --git a/contrib/.cvsignore b/contrib/.cvsignore
index 5a4010b..81e44a9 100644
--- a/contrib/.cvsignore
+++ b/contrib/.cvsignore
@@ -7,3 +7,6 @@ dbfcat
shpinfo
shpfix
shpcat
+Shape_PointInPoly
+shpproj
+shpsort
diff --git a/contrib/Makefile b/contrib/Makefile
index ab0ab13..9ae82f2 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -5,17 +5,17 @@
# Endian: define either _LITTLE_ENDIAN or _BIG_ENDIAN
ENDIAN = -D_LITTLE_ENDIAN
-CFLAGS = -g -I.. -DPROJ4 $(ENDIAN) -DDEBUG -DDEBUG2
+CFLAGS = -g -I.. -I$(HOME)/bld/include -DPROJ4 $(ENDIAN) -DDEBUG -DDEBUG2
-SHPOBJ = ../shpopen.o ../dbfopen.o
+SHPOBJ = ../shpopen.o ../dbfopen.o ../safileio.o
-SHPGOBJ = ../shpopen.o ../dbfopen.o shpgeo.o
+SHPGOBJ = ../shpopen.o ../dbfopen.o ../safileio.o shpgeo.o
-GEOOBJ = ./shpgeo.o -lm -lproj
+GEOOBJ = ./shpgeo.o -lm -L$(HOME)/bld/lib -lproj
default: all
-all: shpdxf shpproj dbfinfo shpcentrd shpdata shpwkb dbfinfo dbfcat shpinfo shpfix shpcat
+all: shpdxf shpproj dbfinfo shpcentrd shpdata shpwkb dbfinfo dbfcat shpinfo shpfix shpcat Shape_PointInPoly shpsort
clean:
rm -f shpdxf shpproj dbfinfo shpcentrd shpdata shpwkb dbfcat dbfinfo shpinfo shpfix shpcat *.o
@@ -47,12 +47,19 @@ shpwkb: shpwkb.c $(SHPGOBJ)
shpproj: shpproj.c $(SHPGOBJ)
$(CC) $(CFLAGS) shpproj.c $(SHPOBJ) $(GEOOBJ) -lm -lproj $(LINKOPT) -o shpproj
+shpsort: shpsort.c $(SHPOBJ)
+ $(CC) $(CFLAGS) shpsort.c ${SHPOBJ} $(LINKOPT) -lm -o shpsort
+
dbfinfo: dbfinfo.c $(SHPOBJ)
$(CC) $(CFLAGS) dbfinfo.c $(SHPOBJ) $(LINKOPT) -o dbfinfo
dbfcat: dbfcat.c $(SHPOBJ)
$(CC) $(CFLAGS) dbfcat.c $(SHPOBJ) $(LINKOPT) -o dbfcat
+Shape_PointInPoly: Shape_PointInPoly.cpp $(SHPOBJ)
+ $(CXX) $(CFLAGS) Shape_PointInPoly.cpp $(SHPOBJ) $(LINKOPT) \
+ -o Shape_PointInPoly
+
check: testproj
testproj:
diff --git a/contrib/ShapeFileII.pas b/contrib/ShapeFileII.pas
index 4ddb26e..14dc0b1 100644
--- a/contrib/ShapeFileII.pas
+++ b/contrib/ShapeFileII.pas
@@ -1,6 +1,6 @@
{
/******************************************************************************
- * $Id: ShapeFileII.pas,v 1.2 2002/01/21 14:09:26 warmerda Exp $
+ * $Id: ShapeFileII.pas,v 1.3 2003-05-14 20:04:51 warmerda Exp $
*
* Project: Shapelib
* Purpose: Delphi Pascal interface to Shapelib.
@@ -35,6 +35,9 @@
******************************************************************************
*
* $Log: ShapeFileII.pas,v $
+ * Revision 1.3 2003-05-14 20:04:51 warmerda
+ * Changed fpSHP and fpSHX to integer at suggestion of Ivan Lucena.
+ *
* Revision 1.2 2002/01/21 14:09:26 warmerda
* Fixed name.
*
@@ -90,7 +93,7 @@ SHPBoundsArr = double;
SHPInfo = record
fpSHP,
- fpSHX : FILE;
+ fpSHX : integer;
nShapeType,
nFileSize,
diff --git a/contrib/Shape_PointInPoly.cpp b/contrib/Shape_PointInPoly.cpp
new file mode 100644
index 0000000..32fd240
--- /dev/null
+++ b/contrib/Shape_PointInPoly.cpp
@@ -0,0 +1,238 @@
+/******************************************************************************
+ * $Id: Shape_PointInPoly.cpp,v 1.1 2004-01-09 16:47:57 fwarmerdam Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Commandline program to generate points-in-polygons from a
+ * shapefile as a shapefile.
+ * Author: Marko Podgorsek, d-mon at siol.net
+ *
+ ******************************************************************************
+ * Copyright (c) 2004, Marko Podgorsek, d-mon at siol.net
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: Shape_PointInPoly.cpp,v $
+ * Revision 1.1 2004-01-09 16:47:57 fwarmerdam
+ * New
+ *
+ */
+
+static char rcsid[] =
+ "$Id: Shape_PointInPoly.cpp,v 1.1 2004-01-09 16:47:57 fwarmerdam Exp $";
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <shapefil.h>
+
+#define MAXINTERSECTIONPOINTS 255
+
+enum loopDir {
+ kExterior,
+ kInterior,
+ kError
+};
+
+struct DPoint2d
+{
+ DPoint2d()
+ {
+ x = y = 0.0;
+ };
+ DPoint2d(double x, double y)
+ {
+ this->x = x;
+ this->y = y;
+ };
+ double x,y;
+};
+
+struct IntersectPoint
+{
+ IntersectPoint(void)
+ {
+ x = y = 0.0;
+ boundry_nmb = 0;
+ loopdirection = kError;
+ };
+ double x,y;
+ int boundry_nmb;
+ loopDir loopdirection;
+};
+
+loopDir LoopDirection(DPoint2d *vertices, int vertsize)
+{
+ int i;
+ double sum = 0.0;
+ for(i=0;i<vertsize-1;i++)
+ {
+ sum += (vertices[i].x*vertices[i+1].y)-(vertices[i].y*vertices[i+1].x);
+ }
+
+ if(sum>0)
+ return kInterior;
+ else
+ return kExterior;
+}
+
+DPoint2d CreatePointInPoly(SHPObject *psShape, int quality)
+{
+ int i, j, k, end, vert, pointpos;
+ double part, dx, xmin, xmax, ymin, ymax, y, x3, x4, y3, y4, len, maxlen = 0;
+ DPoint2d *vertices;
+ loopDir direction;
+ IntersectPoint mp1, mp2, point1, point2, points[MAXINTERSECTIONPOINTS];
+
+ xmin = psShape->dfXMin;
+ ymin = psShape->dfYMin;
+ xmax = psShape->dfXMax;
+ ymax = psShape->dfYMax;
+ part = (ymax-ymin)/(quality+1);
+ dx = xmax-xmin;
+ for(i=0;i<quality;i++)
+ {
+ y = ymin+part*(i+1);
+ pointpos = 0;
+ for(j=0;j<psShape->nParts;j++)
+ {
+ if(j==psShape->nParts-1)
+ end = psShape->nVertices;
+ else
+ end = psShape->panPartStart[j+1];
+ vertices = new DPoint2d [end-psShape->panPartStart[j]];
+ for(k=psShape->panPartStart[j],vert=0;k<end;k++)
+ {
+ vertices[vert].x = psShape->padfX[k];
+ vertices[vert++].y = psShape->padfY[k];
+ }
+ direction = LoopDirection(vertices, vert);
+ for(k=0;k<vert-1;k++)
+ {
+ y3 = vertices[k].y;
+ y4 = vertices[k+1].y;
+ if((y3 >= y && y4 < y) || (y3 <= y && y4 > y)) //I check >= only once, because if it's not checked now (y3) it will be in the next iteration (which is y4 now)
+ {
+ point1.boundry_nmb = j;
+ point1.loopdirection = direction;
+ x3 = vertices[k].x;
+ x4 = vertices[k+1].x;
+ if(y3==y)
+ {
+ point1.y = y3;
+ point1.x = x3;
+ if(direction == kInterior) //add point 2 times if the direction is interior, so that the final count of points is even
+ {
+ points[pointpos++]=point1;
+ }
+ }
+ else
+ {
+ point1.x = xmin+(((((x4-x3)*(y-y3))-((y4-y3)*(xmin-x3)))/((y4-y3)*dx))*dx); //striped down calculation of intersection of 2 lines
+ point1.y = y;
+ }
+ points[pointpos++]=point1;
+ }
+ }
+ delete [] vertices;
+ }
+
+ for(j=1;j<pointpos;j++) //sort the found intersection points by x value
+ {
+ for(k=j;k>0;k--)
+ {
+ if(points[k].x < points[k-1].x)
+ {
+ point1 = points[k];
+ points[k] = points[k-1];
+ points[k-1] = point1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ for(j=0;j<pointpos-1;j++)
+ {
+ point1 = points[j];
+ point2 = points[j+1];
+ if((point1.loopdirection == kExterior && //some checkings for valid point
+ point2.loopdirection == kExterior &&
+ point1.boundry_nmb == point2.boundry_nmb &&
+ j%2==0) ||
+ (point1.loopdirection == kExterior &&
+ point2.loopdirection == kInterior) ||
+ (point1.loopdirection == kInterior &&
+ point2.loopdirection == kExterior))
+ {
+ len = sqrt(pow(point1.x-point2.x, 2)+pow(point1.y-point2.y, 2));
+ if(len >= maxlen)
+ {
+ maxlen = len;
+ mp1 = point1;
+ mp2 = point2;
+ }
+ }
+ }
+ }
+
+ return DPoint2d((mp1.x+mp2.x)*0.5, (mp1.y+mp2.y)*0.5);
+}
+
+int main(int argc, char* argv[])
+{
+ if(argc != 3)
+ {
+ printf("Usage: %s shpfile_path quality\n", argv[0]);
+ return 1;
+ }
+
+ int i, nEntities, quality;
+ SHPHandle hSHP;
+ SHPObject *psShape;
+ DPoint2d pt;
+ quality = atoi(argv[2]);
+ hSHP = SHPOpen(argv[1], "rb");
+ SHPGetInfo(hSHP, &nEntities, NULL, NULL, NULL);
+
+ printf("PointInPoly v1.0, by Marko Podgorsek\n----------------\n");
+ for( i = 0; i < nEntities; i++ )
+ {
+ psShape = SHPReadObject( hSHP, i );
+ if(psShape->nSHPType == SHPT_POLYGON)
+ {
+ pt = CreatePointInPoly(psShape, quality);
+ printf("%d: x=%f y=%f\n",i, pt.x,pt.y);
+ }
+ SHPDestroyObject( psShape );
+ }
+
+ SHPClose(hSHP);
+
+ return 0;
+}
+
diff --git a/contrib/Shape_PointInPoly_README.txt b/contrib/Shape_PointInPoly_README.txt
new file mode 100644
index 0000000..dffe2eb
--- /dev/null
+++ b/contrib/Shape_PointInPoly_README.txt
@@ -0,0 +1,59 @@
+===============================================================================
+Project: Shape_PoinInPoly
+Purpose: Sample and the function for calculatin a point in a polygon
+ (complex,compound - it doesn't matter). Can be used for labeling.
+Author: Copyright (c) 2004, Marko Podgorsek, d-mon at siol.net
+===============================================================================
+Requires: shapelib 1.2 (http://shapelib.maptools.org/)
+Tested and created on platform:
+ Windows 2000 Professional
+ Visual Studio .NET 7.0
+ P4 2.4 GHz
+ 1GB RAM
+
+I just found out about the ShapeLib, GDAL and OGR and I must say that they're
+all great projects.
+I belive I'll use some of those libraries in the future. Right now I'm using
+only shapelib.
+The thing that led me to the http://wwww.maptools.org was the need of finding
+the point in poly...but as I found out that even OGR didn't support it. So
+there I was. I was forced to make my own function. Well, it was fun. I learned
+a lot.
+I wrote this function for the Autodesk Autocad 2004 MPolygon, because there was
+no function to do this in the Object Arx SDK (the Acad programming SDK). Well,
+it will be in the 2005 release...but, still. There is a function in the
+Autodesk Map 2004 version...in the menu.
+Not usefull when you need the coordinates, not the point on the screen...
+So when the Acad version was done I was thinking of doing it on the Shape files,
+too. A little bit of changing the structures and variable
+types (so they're not using Object Arx) and I was done.
+And here it is....Contribution from me to the ShapeLib world :)...and maybe even
+OGR (a little bit of changing there).
+
+Some statistics:
+For about 69000 polygons in Autocad picture (.dwg files)
+Autodesk Map 2004 was creating centroids (the menu command) about 45s (1 scan
+line)
+My function, with 3 scan lines took about 5s. And I was drawing the dots on the
+picture...
+
+-------------------------------------------------------------------------------
+DPoint2d CreatePointInPoly(SHPObject *psShape, int quality)
+
+The second parameter quality tell the function just how many rays shall it use
+to get the point.
+quality = 3 works very well, but anything below 5 is good.
+This doesn't mean that the execution will slow down, but it just finds a good
+point. That's all.
+
+The qality shows on the compound objects (multiple poligons with more than one
+exterior loop) - if not enough rays, then there may be no centroid.
+Or the U shaped thin polygon, only the bootom (below the y center line) is fat.
+Autodesk Map with one scan line will create the centroid on one of the thin
+parts, because it only uses the y center line. If you have more rays, one will
+surely pass the fat area and centroid will be created there.
+
+-------------------------------------------------------------------------------
+Anyone using this function:
+Just send me an e-mail, so I'll see if I did anything good for the public.
+And you can send me e-mail with questions also.
diff --git a/contrib/csv2shp.c b/contrib/csv2shp.c
new file mode 100644
index 0000000..467eb68
--- /dev/null
+++ b/contrib/csv2shp.c
@@ -0,0 +1,558 @@
+/*
+csv2shp - converts a character delimited file to a ESRI shapefile
+Copyright (C) 2005 Springs Rescue Mission
+
+
+LICENSE
+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 2
+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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+The GNU General Public License is also available from the web
+site <http://www.gnu.org>.
+
+
+GRATITUDE
+Like this program? Donate at <http://springsrescuemission.org>.
+
+
+COMPILING INSTRUCTIONS
+This program was written and tested using Shapefile C Library version
+1.2.10 available at <http://shapelib.maptools.org>.
+
+To compile, copy csv2shp.c to the directory with Shapefile C Library.
+Then, compile Shapefile C library. Then, run something like this:
+
+ gcc -pedantic -Wall -o csv2shp csv2shp.c -I. *o
+
+
+USAGE NOTES
+This program operates on single points only (not polygons or lines).
+
+The input file may be a .csv file (comma separated values) or tab-separated
+values, or it may be separated by any other character. The first row must
+contain column names. There must be each a column named longitude and
+latitude in the input file.
+
+The .csv parser does not understand text delimiters (e.g. quotation mark).
+It parses fields only by the given field delimiter (e.g. comma or tab).
+The program has not been tested with null values, and in this case, the
+behavior is undefined. The program will not accept lines with a trailing
+delimiter character.
+
+All columns (including longitude and latitude) in the input file are exported
+to the .dbf file.
+
+The program attempts to find the best type (integer, decimal, string) and
+smallest size of the fields necessary for the .dbf file.
+
+
+SUPPORT
+Springs Rescue Mission does not offer any support for this program.
+
+
+CONTACT INFORMATION
+Springs Rescue Mission
+5 West Las Vegas St
+PO Box 2108
+Colorado Springs CO 80901
+Web: <http://springsrescuemission.org>
+Email: <http://springsrescuemission.org/email.php?recipient=webmaster>
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "shapefil.h"
+#include "regex.h"
+
+#define MAX_COLUMNS 30
+
+typedef struct column_t {
+ DBFFieldType eType;
+ int nWidth;
+ int nDecimals;
+} column;
+
+/* counts the number of occurances of the character in the string */
+int strnchr(const char *s, char c)
+{
+ int n = 0;
+ int x = 0;
+
+ for (; x < strlen(s); x++)
+ {
+ if (c == s[x])
+ {
+ n++;
+ }
+ }
+
+ return n;
+}
+
+/* Returns a field given by column n (0-based) in a character-
+ delimited string s */
+char * delimited_column(char *s, char delim, int n)
+{
+ static char szreturn[4096];
+ char szbuffer[4096]; /* a copy of s */
+ char * pchar;
+ int x;
+ char szdelimiter[2]; /* delim converted to string */
+
+ if (strnchr(s, delim) < n)
+ {
+ fprintf(stderr, "delimited_column: n is too large\n");
+ return NULL;
+ }
+
+ strcpy(szbuffer, s);
+ szdelimiter[0] = delim;
+ szdelimiter[1] = '\0';
+ x = 0;
+ pchar = strtok(szbuffer, szdelimiter);
+ while (x < n)
+ {
+ pchar = strtok(NULL, szdelimiter);
+ x++;
+ }
+
+ if (NULL == pchar)
+ {
+ return NULL;
+ }
+
+ strcpy(szreturn, pchar);
+ return szreturn;
+}
+
+/* Determines the most specific column type.
+ The most specific types from most to least are integer, float, string. */
+DBFFieldType str_to_fieldtype(const char *s)
+{
+ regex_t regex_i;
+ regex_t regex_d;
+
+ if (0 != regcomp(®ex_i, "^[0-9]+$", REG_NOSUB|REG_EXTENDED))
+ {
+ fprintf(stderr, "integer regex complication failed\n");
+ exit (EXIT_FAILURE);
+ }
+
+ if (0 == regexec(®ex_i, s, 0, NULL, 0))
+ {
+ regfree(®ex_i);
+ return FTInteger;
+ }
+
+ regfree(®ex_i);
+
+ if (0 != regcomp(®ex_d, "^-?[0-9]+\\.[0-9]+$", REG_NOSUB|REG_EXTENDED))
+ {
+ fprintf(stderr, "integer regex complication failed\n");
+ exit (EXIT_FAILURE);
+ }
+
+ if (0 == regexec(®ex_d, s, 0, NULL, 0))
+ {
+ regfree(®ex_d);
+ return FTDouble;
+ }
+
+ regfree(®ex_d);
+
+ return FTString;
+}
+
+int float_width(const char *s)
+{
+ regex_t regex_d;
+ regmatch_t pmatch[2];
+ char szbuffer[4096];
+
+ if (0 != regcomp(®ex_d, "^(-?[0-9]+)\\.[0-9]+$", REG_EXTENDED))
+ {
+ fprintf(stderr, "integer regex complication failed\n");
+ exit (EXIT_FAILURE);
+ }
+
+ if (0 != regexec(®ex_d, s, 2, &pmatch[0], 0))
+ {
+ return -1;
+ }
+
+ strncpy(szbuffer, &s[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+ szbuffer[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0';
+ regfree(®ex_d);
+
+ return strlen(szbuffer);
+}
+
+/* returns the field width */
+int str_to_nwidth(const char *s, DBFFieldType eType)
+{
+ switch (eType)
+ {
+ case FTString:
+ case FTInteger:
+ case FTDouble:
+ return strlen(s);
+
+ default:
+ fprintf(stderr, "str_to_nwidth: unexpected type\n");
+ exit (EXIT_FAILURE);
+ }
+}
+
+/* returns the number of decimals in a real number given as a string s */
+int str_to_ndecimals(const char *s)
+{
+ regex_t regex_d;
+ regmatch_t pmatch[2];
+ char szbuffer[4096];
+
+ if (0 != regcomp(®ex_d, "^-?[0-9]+\\.([0-9]+)$", REG_EXTENDED))
+ {
+ fprintf(stderr, "integer regex complication failed\n");
+ exit (EXIT_FAILURE);
+ }
+
+ if (0 != regexec(®ex_d, s, 2, &pmatch[0], 0))
+ {
+ return -1;
+ }
+
+ strncpy(szbuffer, &s[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+ szbuffer[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0';
+
+ regfree(®ex_d);
+
+ return strlen(szbuffer);
+}
+
+/* returns true if f1 is more general than f2, otherwise false */
+int more_general_field_type(DBFFieldType t1, DBFFieldType t2)
+{
+ if (FTInteger == t2 && t1 != FTInteger)
+ {
+ return 1;
+ }
+
+ if (FTDouble == t2 && FTString == t1)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+void strip_crlf (char *line)
+{
+ /* remove trailing CR/LF */
+
+ if (strchr (line, 0x0D))
+ {
+ char *pszline;
+ pszline = strchr (line, 0x0D);
+ pszline[0] = '\0';
+ }
+
+ if (strchr (line, 0x0A))
+ {
+ char *pszline;
+ pszline = strchr (line, 0x0A);
+ pszline[0] = '\0';
+ }
+}
+
+int main( int argc, char ** argv )
+{
+ FILE *csv_f;
+ char sbuffer[4096];
+ char delimiter;
+ int n_columns; /* 1-based */
+ int n_line;
+ int n_longitude = -1; /* column with x, 0 based */
+ int n_latitude = -1; /* column with y, 0 based */
+ int x;
+ DBFHandle dbf_h;
+ SHPHandle shp_h;
+ column columns[MAX_COLUMNS + 1];
+
+ printf("csv2shp version 1, Copyright (C) 2005 Springs Rescue Mission\n");
+
+ if (4 != argc)
+ {
+ fprintf(stderr, "csv2shp comes with ABSOLUTELY NO WARRANTY; for details\n");
+ fprintf(stderr, "see csv2shp.c. This is free software, and you are welcome\n");
+ fprintf(stderr, "to redistribute it under certain conditions; see csv2shp.c\n");
+ fprintf(stderr, "for details\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "USAGE\n");
+ fprintf(stderr, "csv2shp csv_filename delimiter_character shp_filename\n");
+ fprintf(stderr, " csv_filename\n");
+ fprintf(stderr, " columns named longitude and latitude must exist\n");
+ fprintf(stderr, " delimiter_character\n");
+ fprintf(stderr, " one character only\n");
+ fprintf(stderr, " shp_filename\n");
+ fprintf(stderr, " base name, do not give the extension\n");
+ return EXIT_FAILURE;
+ }
+
+ if (strlen(argv[2]) > 1)
+ {
+ fprintf(stderr, "delimiter must be one character in length\n");
+ return EXIT_FAILURE;
+ }
+
+ delimiter = argv[2][0];
+
+ csv_f = fopen(argv[1], "r");
+
+ if (NULL == csv_f)
+ {
+ perror("could not open csv file");
+ exit (EXIT_FAILURE);
+ }
+
+ fgets(sbuffer, 4000, csv_f);
+
+ /* check first row */
+
+ strip_crlf(sbuffer);
+
+ if (delimiter == sbuffer[strlen(sbuffer)- 1])
+ {
+ fprintf(stderr, "lines must not end with the delimiter character\n");
+ return EXIT_FAILURE;
+
+ }
+
+ /* count columns and verify consistency*/
+
+ n_columns = strnchr(sbuffer, delimiter);
+
+ if (n_columns > MAX_COLUMNS)
+ {
+ fprintf(stderr, "too many columns, maximum is %i\n", MAX_COLUMNS);
+ return EXIT_FAILURE;
+ }
+
+ n_line = 1;
+
+ while (!feof(csv_f))
+ {
+ n_line++;
+ fgets(sbuffer, 4000, csv_f);
+ if (n_columns != strnchr(sbuffer, delimiter))
+ {
+ fprintf(stderr, "Number of columns on row %i does not match number of columns on row 1\n", n_columns);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* identify longitude and latitude columns */
+
+ fseek(csv_f, 0, SEEK_SET);
+ fgets(sbuffer, 4000, csv_f);
+ strip_crlf(sbuffer);
+
+ for (x = 0; x <= n_columns; x++)
+ {
+ if (0 == strcasecmp("Longitude", delimited_column(sbuffer, delimiter, x)))
+ {
+ n_longitude = x;
+ }
+
+ if (0 == strcasecmp("Latitude", delimited_column(sbuffer, delimiter, x)))
+ {
+ n_latitude = x;
+ }
+ }
+
+#ifdef DEBUG
+ printf("debug lat/long = %i/%i\n", n_latitude, n_longitude);
+#endif
+
+ if (-1 == n_longitude || -1 == n_latitude)
+ {
+ fprintf(stderr, "The header row must define one each a column named longitude and latitude\n");
+ return EXIT_FAILURE;
+ }
+
+ /* determine best fit for each column */
+
+ printf ("Anaylzing column types...\n");
+
+#ifdef DEBUG
+ printf("debug: string type = %i\n", FTString);
+ printf("debug: int type = %i\n", FTInteger);
+ printf("debug: double type = %i\n", FTDouble);
+#endif
+ for (x = 0; x <= n_columns; x++)
+ {
+#ifdef DEBUG
+ printf("debug: examining column %i\n", x);
+#endif
+ columns[x].eType = FTInteger;
+ columns[x].nWidth = 2;
+ columns[x].nDecimals = 0;
+
+ fseek(csv_f, 0, SEEK_SET);
+ fgets(sbuffer, 4000, csv_f);
+
+ while (!feof(csv_f))
+ {
+ char szfield[4096];
+#ifdef DEBUG
+ printf ("column %i, type = %i, w = %i, d = %i\n", x, columns[x].eType, columns[x].nWidth, columns[x].nDecimals);
+#endif
+ if (NULL == fgets(sbuffer, 4000, csv_f))
+ {
+ if (!feof(csv_f))
+ {
+ fprintf(stderr, "error during fgets()\n");
+ }
+ continue;
+ }
+ strcpy(szfield, delimited_column(sbuffer, delimiter, x));
+ if (more_general_field_type(str_to_fieldtype(szfield), columns[x].eType))
+ {
+ columns[x].eType = str_to_fieldtype(szfield);
+ columns[x].nWidth = 2;
+ columns[x].nDecimals = 0;
+ fseek(csv_f, 0, SEEK_SET);
+ fgets(sbuffer, 4000, csv_f);
+ continue;
+ }
+ if (columns[x].nWidth < str_to_nwidth(szfield, columns[x].eType))
+ {
+ columns[x].nWidth = str_to_nwidth(szfield, columns[x].eType);
+ }
+ if (FTDouble == columns[x].eType && columns[x].nDecimals < str_to_ndecimals(szfield))
+ {
+ columns[x].nDecimals = str_to_ndecimals(szfield);
+ }
+
+ }
+ }
+
+
+ /* initilize output files */
+
+ printf ("Initializing output files...\n");
+
+ shp_h = SHPCreate(argv[3], SHPT_POINT);
+
+ dbf_h = DBFCreate(argv[3]);
+
+ if (NULL == dbf_h)
+ {
+ fprintf(stderr, "DBFCreate failed\n");
+ exit (EXIT_FAILURE);
+ }
+
+ fseek(csv_f, 0, SEEK_SET);
+ fgets(sbuffer, 4000, csv_f);
+ strip_crlf(sbuffer);
+
+ for (x = 0; x <= n_columns; x++)
+ {
+#ifdef DEBUG
+ printf ("debug: final: column %i, type = %i, w = %i, d = %i, name=|%s|\n", x, columns[x].eType, columns[x].nWidth, columns[x].nDecimals, delimited_column(sbuffer, delimiter, x));
+#endif
+ if (-1 == DBFAddField(dbf_h, delimited_column(sbuffer, delimiter, x), columns[x].eType, columns[x].nWidth, columns[x].nDecimals))
+ {
+ fprintf(stderr, "DBFFieldAdd failed column %i\n", x + 1);
+ exit (EXIT_FAILURE);
+ }
+
+ }
+
+ /* write data */
+
+ printf ("Writing data...\n");
+
+ fseek(csv_f, 0, SEEK_SET);
+ fgets(sbuffer, 4000, csv_f); /* skip header */
+
+ n_columns = strnchr(sbuffer, delimiter);
+ n_line = 1;
+
+ while (!feof(csv_f))
+ {
+ SHPObject * shp;
+ double x_pt;
+ double y_pt;
+ int shp_i;
+
+ n_line++;
+ fgets(sbuffer, 4000, csv_f);
+
+ /* write to shape file */
+ x_pt = atof(delimited_column(sbuffer, delimiter, n_longitude));
+ y_pt = atof(delimited_column(sbuffer, delimiter, n_latitude));
+
+#ifdef DEBUG
+ printf("debug: sbuffer=%s", sbuffer);
+ printf("debug: x,y = %f, %f\n", x_pt, y_pt);
+#endif
+
+ shp = SHPCreateSimpleObject(SHPT_POINT, 1, &x_pt, &y_pt, NULL);
+ shp_i = SHPWriteObject(shp_h, -1, shp);
+ SHPDestroyObject(shp);
+
+ /* write to dbf */
+
+ for (x = 0; x <= n_columns; x++)
+ {
+ char szfield[4096];
+ int b;
+
+ strcpy(szfield, delimited_column(sbuffer, delimiter, x));
+
+ switch (columns[x].eType)
+ {
+ case FTInteger:
+ b = DBFWriteIntegerAttribute(dbf_h, shp_i, x, atoi(szfield));
+ break;
+ case FTDouble:
+ b = DBFWriteDoubleAttribute(dbf_h, shp_i, x, atof(szfield));
+ break;
+ case FTString:
+ b = DBFWriteStringAttribute(dbf_h, shp_i, x, szfield);
+ break;
+ default:
+ fprintf(stderr, "unexpected column type %i in column %i\n", columns[x].eType, x);
+ }
+
+ if (!b)
+ {
+ fprintf(stderr, "DBFWrite*Attribute failed\n");
+ exit (EXIT_FAILURE);
+ }
+ }
+ }
+
+ /* finish up */
+
+ SHPClose(shp_h);
+
+ DBFClose(dbf_h);
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/dbfcat.c b/contrib/dbfcat.c
index c03046d..2c4eb9f 100644
--- a/contrib/dbfcat.c
+++ b/contrib/dbfcat.c
@@ -4,7 +4,10 @@
* This code is in the public domain.
*
* $Log: dbfcat.c,v $
- * Revision 1.1 1999/05/26 02:56:31 candrsn
+ * Revision 1.2 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.1 1999-05-26 02:56:31 candrsn
* updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
*
* Revision 1.3 1995/10/21 03:15:01 warmerda
@@ -16,8 +19,10 @@
*/
static char rcsid[] =
- "$Id: dbfcat.c,v 1.1 1999/05/26 02:56:31 candrsn Exp $";
+ "$Id: dbfcat.c,v 1.2 2011-07-24 03:17:46 fwarmerdam Exp $";
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
diff --git a/contrib/dbfinfo.c b/contrib/dbfinfo.c
index a251d61..07efb82 100644
--- a/contrib/dbfinfo.c
+++ b/contrib/dbfinfo.c
@@ -10,13 +10,17 @@
*
*
* $Log: dbfinfo.c,v $
- * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * Revision 1.3 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.2 1999-05-26 02:56:31 candrsn
* updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
*
*
*/
-
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
diff --git a/contrib/makefile.vc b/contrib/makefile.vc
index ff3ce16..f376f64 100644
--- a/contrib/makefile.vc
+++ b/contrib/makefile.vc
@@ -1,9 +1,8 @@
-PROJ_DIR = D:\warmerda\proj
-CFLAGS = /I.. /I$(PROJ_DIR)\src /D_LITTLE_ENDIAN -DPROJ4
+CFLAGS = /Ox /MD /nologo /I.. /IC:\OSGeo4W\include \
+ /D_LITTLE_ENDIAN -DPROJ4
-LINKARGS = shpgeo.obj ..\shpopen.obj ..\dbfopen.obj \
- D:\warmerda\proj\src\proj_i.lib
+LINKARGS = ..\shapelib_i.lib C:\OSGeo4W\lib\proj_i.lib
default: all
@@ -11,19 +10,25 @@ all: shpcat.exe shpcentrd.exe shpdxf.exe shpinfo.exe shpproj.exe
shpcat.exe: shpcat.obj shpgeo.obj
$(CC) $(CFLAGS) shpcat.obj $(LINKARGS)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
shpcentrd.exe: shpcentrd.obj shpgeo.obj
- $(CC) $(CFLAGS) shpcentrd.obj $(LINKARGS)
+ $(CC) $(CFLAGS) shpcentrd.obj shpgeo.obj $(LINKARGS)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
shpproj.exe: shpproj.obj shpgeo.obj
- $(CC) $(CFLAGS) shpproj.obj $(LINKARGS)
+ $(CC) $(CFLAGS) shpproj.obj shpgeo.obj $(LINKARGS)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
shpdxf.exe: shpdxf.obj shpgeo.obj
$(CC) $(CFLAGS) shpdxf.obj $(LINKARGS)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
shpinfo.exe: shpinfo.obj shpgeo.obj
$(CC) $(CFLAGS) shpinfo.obj $(LINKARGS)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
clean:
- del *.obj *.exe
-
+ -del *.obj
+ -del *.exe
+ -del *.manifest
diff --git a/contrib/shpcat.c b/contrib/shpcat.c
index b105fd5..d4c32df 100644
--- a/contrib/shpcat.c
+++ b/contrib/shpcat.c
@@ -31,7 +31,10 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
+
int dbfcat_main( int argc, char ** argv );
int main( int argc, char ** argv )
diff --git a/contrib/shpcentrd.c b/contrib/shpcentrd.c
index d008603..8156b9e 100644
--- a/contrib/shpcentrd.c
+++ b/contrib/shpcentrd.c
@@ -28,7 +28,10 @@
*
*
* $Log: shpcentrd.c,v $
- * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * Revision 1.3 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.2 1999-05-26 02:56:31 candrsn
* updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
*
*
@@ -43,6 +46,8 @@
* Cy = sum (y dArea ) / Total Area
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
#include "shpgeo.h"
diff --git a/contrib/shpdata.c b/contrib/shpdata.c
index ba10337..e401b6e 100644
--- a/contrib/shpdata.c
+++ b/contrib/shpdata.c
@@ -26,7 +26,7 @@
*
*
* $Log: shpdata.c,v $
- * Revision 1.2 1999/05/26 02:56:31 candrsn
+ * Revision 1.2 1999-05-26 02:56:31 candrsn
* updates to shpdxf, dbfinfo, port from Shapelib 1.1.5 of dbfcat and shpinfo
*
*
diff --git a/contrib/shpdxf.c b/contrib/shpdxf.c
index 4a76b8f..2377809 100644
--- a/contrib/shpdxf.c
+++ b/contrib/shpdxf.c
@@ -37,9 +37,10 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
-
#define FLOAT_PREC "%16.5f\r\n"
void dxf_hdr (x1,y1,x2,y2,df)
diff --git a/contrib/shpfix.c b/contrib/shpfix.c
index 2c66ece..1ed73a3 100644
--- a/contrib/shpfix.c
+++ b/contrib/shpfix.c
@@ -34,6 +34,8 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
diff --git a/contrib/shpgeo.c b/contrib/shpgeo.c
index 9f1d59d..09d5ff6 100644
--- a/contrib/shpgeo.c
+++ b/contrib/shpgeo.c
@@ -32,6 +32,21 @@
* use -DPROJ4 to compile in Projection support
*
* $Log: shpgeo.c,v $
+ * Revision 1.13 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.12 2007-09-03 23:17:46 fwarmerdam
+ * fix SHPDimension() function
+ *
+ * Revision 1.11 2006/11/06 20:45:58 fwarmerdam
+ * Fixed SHPProject.
+ *
+ * Revision 1.10 2006/11/06 20:44:58 fwarmerdam
+ * SHPProject() uses pj_transform now
+ *
+ * Revision 1.9 2006/01/25 15:33:50 fwarmerdam
+ * fixed ppsC assignment maptools bug 1263
+ *
* Revision 1.8 2002/01/15 14:36:56 warmerda
* upgrade to use proj_api.h
*
@@ -55,6 +70,8 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
#ifndef NAN
@@ -147,41 +164,31 @@ static void * SfRealloc( void * pMem, int nNewSize )
* **************************************************************************/
int SHPProject ( SHPObject *psCShape, projPJ inproj, projPJ outproj ) {
#ifdef PROJ4
- int j;
- projUV p; /* struct { double u, double v } */
- /* for each vertex project it and stuff the projeted point back into */
- /* same SHPObject. Proj assumes data is in radians so convert it. */
- /* Proj will convert Geographic -> <proj> and <proj> -> Geographic */
- /* so <proj1> -> <proj2> requires bouncing though geographic */
-
- for ( j=0; j < psCShape->nVertices; j++ ) {
- p.u = psCShape->padfX[j];
- p.v = psCShape->padfY[j];
+ int j;
- if ( inproj )
- p = pj_inv ( p, inproj );
- else
- { p.u *= DEG_TO_RAD;
- p.v *= DEG_TO_RAD;
- }
+ if ( pj_is_latlong(inproj) ) {
+ for(j=0; j < psCShape->nVertices; j++) {
+ psCShape->padfX[j] *= DEG_TO_RAD;
+ psCShape->padfY[j] *= DEG_TO_RAD;
+ }
+ }
- if ( outproj )
- p = pj_fwd ( p, outproj );
- else
- { p.u *= RAD_TO_DEG;
- p.v *= RAD_TO_DEG;
- }
+ pj_transform(inproj, outproj, psCShape->nVertices, 0, psCShape->padfX,
+ psCShape->padfY, NULL);
- psCShape->padfX[j] = p.u;
- psCShape->padfY[j] = p.v;
- }
-
- /* Recompute new Extents of projected Object */
- SHPComputeExtents ( psCShape );
+ if ( pj_is_latlong(outproj) ) {
+ for(j=0; j < psCShape->nVertices; j++) {
+ psCShape->padfX[j] *= RAD_TO_DEG;
+ psCShape->padfY[j] *= RAD_TO_DEG;
+ }
+ }
+
+ /* Recompute new Extents of projected Object */
+ SHPComputeExtents ( psCShape );
#endif
- return ( 1 );
+ return ( 1 );
}
@@ -543,8 +550,8 @@ int SHPWriteOGisPolygon ( WKBStreamObj *stream_obj, SHPObject *psCShape ) {
nextring = 0;
cParts=0;
while ( nextring >= 0 ) {
- (SHPObject*) ppsC[cParts] = SHPUnCompound ( psCShape, &nextring );
- cParts++;
+ ppsC[cParts] = SHPUnCompound ( psCShape, &nextring );
+ cParts++;
}
#ifdef DEBUG2
@@ -828,22 +835,22 @@ int SHPDimension ( int SHPType ) {
dimension = 0;
switch ( SHPType ) {
- case SHPT_POINT : dimension = SHPD_POINT ;
- case SHPT_ARC : dimension = SHPD_LINE;
- case SHPT_POLYGON : dimension = SHPD_AREA;
- case SHPT_MULTIPOINT : dimension = SHPD_POINT;
- case SHPT_POINTZ : dimension = SHPD_POINT | SHPD_Z;
- case SHPT_ARCZ : dimension = SHPD_LINE | SHPD_Z;
- case SHPT_POLYGONZ : dimension = SHPD_AREA | SHPD_Z;
- case SHPT_MULTIPOINTZ : dimension = SHPD_POINT | SHPD_Z;
- case SHPT_POINTM : dimension = SHPD_POINT | SHPD_MEASURE;
- case SHPT_ARCM : dimension = SHPD_LINE | SHPD_MEASURE;
- case SHPT_POLYGONM : dimension = SHPD_AREA | SHPD_MEASURE;
- case SHPT_MULTIPOINTM : dimension = SHPD_POINT | SHPD_MEASURE;
- case SHPT_MULTIPATCH : dimension = SHPD_AREA;
+ case SHPT_POINT : dimension = SHPD_POINT; break;
+ case SHPT_ARC : dimension = SHPD_LINE; break;
+ case SHPT_POLYGON : dimension = SHPD_AREA; break;
+ case SHPT_MULTIPOINT : dimension = SHPD_POINT; break;
+ case SHPT_POINTZ : dimension = SHPD_POINT | SHPD_Z; break;
+ case SHPT_ARCZ : dimension = SHPD_LINE | SHPD_Z; break;
+ case SHPT_POLYGONZ : dimension = SHPD_AREA | SHPD_Z; break;
+ case SHPT_MULTIPOINTZ : dimension = SHPD_POINT | SHPD_Z; break;
+ case SHPT_POINTM : dimension = SHPD_POINT | SHPD_MEASURE; break;
+ case SHPT_ARCM : dimension = SHPD_LINE | SHPD_MEASURE; break;
+ case SHPT_POLYGONM : dimension = SHPD_AREA | SHPD_MEASURE; break;
+ case SHPT_MULTIPOINTM : dimension = SHPD_POINT | SHPD_MEASURE; break;
+ case SHPT_MULTIPATCH : dimension = SHPD_AREA; break;
}
- return ( dimension );
+ return ( dimension );
}
diff --git a/contrib/shpgeo.h b/contrib/shpgeo.h
index 02276b1..504812c 100644
--- a/contrib/shpgeo.h
+++ b/contrib/shpgeo.h
@@ -27,7 +27,7 @@
*
*
* $Log: shpgeo.h,v $
- * Revision 1.3 2002/01/15 14:36:56 warmerda
+ * Revision 1.3 2002-01-15 14:36:56 warmerda
* upgrade to use proj_api.h
*
* Revision 1.2 1999/05/26 02:56:31 candrsn
diff --git a/contrib/shpinfo.c b/contrib/shpinfo.c
index 4859e49..f1ae3e8 100644
--- a/contrib/shpinfo.c
+++ b/contrib/shpinfo.c
@@ -27,7 +27,10 @@
*
*
* $Log: shpinfo.c,v $
- * Revision 1.3 2002/04/15 21:33:03 warmerda
+ * Revision 1.4 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.3 2002-04-15 21:33:03 warmerda
* Avoid dereference arrays.
*
* Revision 1.2 2002/04/15 18:40:31 warmerda
@@ -39,6 +42,8 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
#include "shapefil.h"
int main( int argc, char ** argv )
diff --git a/contrib/shpproj.c b/contrib/shpproj.c
index 0759723..231c7f7 100644
--- a/contrib/shpproj.c
+++ b/contrib/shpproj.c
@@ -20,7 +20,7 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
- *******************************************************************************
+ ******************************************************************************
*
* requires shapelib 1.2
* gcc shpproj ../shpopen.o ../dbfopen.o shpgeo.o -lm -lproj -o shpproj
@@ -33,7 +33,10 @@
* SHPGeo must be compiled with -DPROJ4 support
*
* $Log: shpproj.c,v $
- * Revision 1.9 2002/01/15 14:37:08 warmerda
+ * Revision 1.10 2011-07-24 03:17:46 fwarmerdam
+ * include string.h and stdlib.h where needed in contrib (#2146)
+ *
+ * Revision 1.9 2002-01-15 14:37:08 warmerda
* upgrade to use proj_api.h
*
* Revision 1.8 2002/01/11 15:47:26 warmerda
@@ -52,9 +55,11 @@
*/
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
#include "shapefil.h"
#include "shpgeo.h"
-#include <stdarg.h>
int main( int argc, char ** argv )
{
diff --git a/contrib/shpsort.c b/contrib/shpsort.c
new file mode 100644
index 0000000..ae0bf6f
--- /dev/null
+++ b/contrib/shpsort.c
@@ -0,0 +1,605 @@
+/******************************************************************************
+ * Copyright (c) 2004, Eric G. Miller
+ *
+ * This code is based in part on the earlier work of Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ * shpsort
+ *
+ * Rewrite a shapefile sorted by a field or by the geometry. For polygons,
+ * sort by area, for lines sort by length and do nothing for all others.
+ *
+ * $Log: shpsort.c,v $
+ * Revision 1.3 2004-07-06 21:23:17 fwarmerdam
+ * minor const warning fix
+ *
+ * Revision 1.2 2004/07/06 21:20:49 fwarmerdam
+ * major upgrade .. sort on multiple fields
+ *
+ * Revision 1.4 2004/06/30 18:19:53 emiller
+ * handle POINTZ, POINTM
+ *
+ * Revision 1.3 2004/06/30 17:40:32 emiller
+ * major rewrite allows sorting on multiple fields.
+ *
+ * Revision 1.2 2004/06/23 23:19:58 emiller
+ * use tuple copy, misc changes
+ *
+ * Revision 1.1 2004/06/23 21:38:17 emiller
+ * Initial revision
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include "shapefil.h"
+
+enum FieldOrderEnum {DESCENDING, ASCENDING};
+enum FieldTypeEnum {
+ FIDType = -2,
+ SHPType = -1,
+ StringType = FTString,
+ LogicalType = FTLogical,
+ IntegerType = FTInteger,
+ DoubleType = FTDouble
+};
+
+struct DataUnion {
+ int null;
+ union {
+ int i;
+ double d;
+ char *s;
+ } u;
+};
+
+struct DataStruct {
+ int record;
+ struct DataUnion *value;
+};
+
+/*
+ globals used in sorting, each element could have a pointer to
+ a single data struct, but that's still nShapes pointers more
+ memory. Alternatively, write a custom sort rather than using
+ library qsort.
+*/
+int nFields;
+int *fldIdx;
+int *fldOrder;
+int *fldType;
+int shpType;
+int nShapes;
+
+static struct DataStruct * build_index (SHPHandle shp, DBFHandle dbf);
+static char * dupstr (const char *);
+static void copy_related (const char *inName, const char *outName,
+ const char *old_ext, const char *new_ext);
+static char ** split(const char *arg, const char *delim);
+static int compare(const void *, const void *);
+static double area2d_polygon (int n, double *x, double *y);
+static double shp_area (SHPObject *feat);
+static double length2d_polyline (int n, double *x, double *y);
+static double shp_length (SHPObject *feat);
+
+int main (int argc, char *argv[]) {
+
+ SHPHandle inSHP, outSHP;
+ DBFHandle inDBF, outDBF;
+ int len;
+ int i;
+ char **fieldNames;
+ char **strOrder = 0;
+ struct DataStruct *index;
+ int width;
+ int decimals;
+ SHPObject *feat;
+ void *tuple;
+
+ if (argc < 4) {
+ printf("USAGE: shpsort <infile> <outfile> <field[;...]> [<(ASCENDING|DESCENDING)[;...]>]\n");
+ exit(EXIT_FAILURE);
+ }
+
+ inSHP = SHPOpen (argv[1], "rb");
+ if (!inSHP) {
+ fputs("Couldn't open shapefile for reading!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ SHPGetInfo(inSHP, &nShapes, &shpType, NULL, NULL);
+
+ /* If we can open the inSHP, open its DBF */
+ inDBF = DBFOpen (argv[1], "rb");
+ if (!inDBF) {
+ fputs("Couldn't open dbf file for reading!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Parse fields and validate existence */
+ fieldNames = split(argv[3], ";");
+ if (!fieldNames) {
+ fputs("ERROR: parsing field names!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ for (nFields = 0; fieldNames[nFields] ; nFields++) {
+ continue;
+ }
+
+ fldIdx = malloc(sizeof *fldIdx * nFields);
+ if (!fldIdx) {
+ fputs("malloc failed!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < nFields; i++) {
+ len = (int)strlen(fieldNames[i]);
+ while(len > 0) {
+ --len;
+ fieldNames[i][len] = (char)toupper((unsigned char)fieldNames[i][len]);
+ }
+ fldIdx[i] = DBFGetFieldIndex(inDBF, fieldNames[i]);
+ if (fldIdx[i] < 0) {
+ /* try "SHAPE" */
+ if (strcmp(fieldNames[i], "SHAPE") == 0) {
+ fldIdx[i] = -1;
+ }
+ else if (strcmp(fieldNames[i], "FID") == 0) {
+ fldIdx[i] = -2;
+ }
+ else {
+ fprintf(stderr, "ERROR: field '%s' not found!\n", fieldNames[i]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+
+ /* set up field type array */
+ fldType = malloc(sizeof *fldType * nFields);
+ if (!fldType) {
+ fputs("malloc failed!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < nFields; i++) {
+ if (fldIdx[i] < 0) {
+ fldType[i] = fldIdx[i];
+ }
+ else {
+ fldType[i] = DBFGetFieldInfo(inDBF, fldIdx[i], NULL, &width, &decimals);
+ if (fldType[i] == FTInvalid) {
+ fputs("Unrecognized field type in dBASE file!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+
+ /* set up field order array */
+ fldOrder = malloc(sizeof *fldOrder * nFields);
+ if (!fldOrder) {
+ fputs("malloc failed!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < nFields; i++) {
+ /* default to ascending order */
+ fldOrder[i] = ASCENDING;
+ }
+ if (argc > 4) {
+ strOrder = split(argv[4], ";");
+ if (!strOrder) {
+ fputs("ERROR: parsing fields ordering!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i < nFields && strOrder[i]; i++) {
+ if (strcmp(strOrder[i], "DESCENDING") == 0) {
+ fldOrder[i] = DESCENDING;
+ }
+ }
+ }
+
+ /* build the index */
+ index = build_index (inSHP, inDBF);
+
+ /* Create output shapefile */
+ outSHP = SHPCreate(argv[2], shpType);
+ if (!outSHP) {
+ fprintf(stderr, "%s:%d: couldn't create output shapefile!\n",
+ __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create output dbf */
+ outDBF = DBFCloneEmpty(inDBF, argv[2]);
+ if (!outDBF) {
+ fprintf(stderr, "%s:%d: couldn't create output dBASE file!\n",
+ __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Copy projection file, if any */
+ copy_related(argv[1], argv[2], ".shp", ".prj");
+
+ /* Copy metadata file, if any */
+ copy_related(argv[1], argv[2], ".shp", ".shp.xml");
+
+ /* Write out sorted results */
+ for (i = 0; i < nShapes; i++) {
+ feat = SHPReadObject(inSHP, index[i].record);
+ if (SHPWriteObject(outSHP, -1, feat) < 0) {
+ fprintf(stderr, "%s:%d: error writing shapefile!\n", __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+ tuple = (void *) DBFReadTuple(inDBF, index[i].record);
+ if (DBFWriteTuple(outDBF, i, tuple) < 0) {
+ fprintf(stderr, "%s:%d: error writing dBASE file!\n", __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+ }
+ SHPClose(inSHP);
+ SHPClose(outSHP);
+ DBFClose(inDBF);
+ DBFClose(outDBF);
+
+ return EXIT_SUCCESS;
+
+}
+
+static char ** split(const char *arg, const char *delim)
+{
+ char *copy = dupstr(arg);
+ char *cptr = copy;
+ char **result = NULL;
+ char **tmp;
+ int i = 0;
+
+ for (cptr = strtok(copy, delim); cptr; cptr = strtok(NULL, delim)) {
+ tmp = realloc (result, sizeof *result * (i + 1));
+ if (!tmp && result) {
+ while (i > 0) {
+ free(result[--i]);
+ }
+ free(result);
+ free(copy);
+ return NULL;
+ }
+ result = tmp;
+ result[i++] = dupstr(cptr);
+ }
+
+ free(copy);
+
+ if (i) {
+ tmp = realloc(result, sizeof *result * (i + 1));
+ if (!tmp) {
+ while (i > 0) {
+ free(result[--i]);
+ }
+ free(result);
+ free(copy);
+ return NULL;
+ }
+ result = tmp;
+ result[i++] = NULL;
+ }
+
+ return result;
+}
+
+
+static void copy_related (const char *inName, const char *outName,
+ const char *old_ext, const char *new_ext)
+{
+ char *in;
+ char *out;
+ FILE *inFile;
+ FILE *outFile;
+ int c;
+ size_t name_len = strlen(inName);
+ size_t old_len = strlen(old_ext);
+ size_t new_len = strlen(new_ext);
+
+ in = malloc(name_len - old_len + new_len + 1);
+ strncpy(in, inName, (name_len - old_len));
+ strcpy(&in[(name_len - old_len)], new_ext);
+ inFile = fopen(in, "rb");
+ if (!inFile) {
+ free(in);
+ return;
+ }
+ name_len = strlen(outName);
+ out = malloc(name_len - old_len + new_len + 1);
+ strncpy(out, outName, (name_len - old_len));
+ strcpy(&out[(name_len - old_len)], new_ext);
+ outFile = fopen(out, "wb");
+ if (!out) {
+ fprintf(stderr, "%s:%d: couldn't copy related file!\n",
+ __FILE__, __LINE__);
+ free(in);
+ free(out);
+ return;
+ }
+ while ((c = fgetc(inFile)) != EOF) {
+ fputc(c, outFile);
+ }
+ fclose(inFile);
+ fclose(outFile);
+ free(in);
+ free(out);
+}
+
+static char * dupstr (const char *src)
+{
+ char *dst = malloc(strlen(src) + 1);
+ char *cptr;
+ if (!dst) {
+ fprintf(stderr, "%s:%d: malloc failed!\n", __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+ cptr = dst;
+ while ((*cptr++ = *src++))
+ ;
+ return dst;
+}
+
+#ifdef DEBUG
+static void PrintDataStruct (struct DataStruct *data) {
+ int i, j;
+ for (i = 0; i < nShapes; i++) {
+ printf("data[%d] {\n", i);
+ printf("\t.record = %d\n", data[i].record);
+ for (j = 0; j < nFields; j++) {
+ printf("\t.value[%d].null = %d\n", j, data[i].value[j].null);
+ if (!data[i].value[j].null) {
+ switch(fldType[j]) {
+ case FIDType:
+ case IntegerType:
+ case LogicalType:
+ printf("\t.value[%d].u.i = %d\n", j, data[i].value[j].u.i);
+ break;
+ case DoubleType:
+ case SHPType:
+ printf("\t.value[%d].u.d = %f\n", j, data[i].value[j].u.d);
+ break;
+ case StringType:
+ printf("\t.value[%d].u.s = %s\n", j, data[i].value[j].u.s);
+ break;
+ }
+ }
+ }
+ puts("}");
+ }
+}
+#endif
+
+static struct DataStruct * build_index (SHPHandle shp, DBFHandle dbf) {
+ struct DataStruct *data;
+ SHPObject *feat;
+ int i;
+ int j;
+
+ /* make array */
+ data = malloc (sizeof *data * nShapes);
+ if (!data) {
+ fputs("malloc failed!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* populate array */
+ for (i = 0; i < nShapes; i++) {
+ data[i].value = malloc(sizeof data[0].value[0] * nFields);
+ if (0 == data[i].value) {
+ fputs("malloc failed!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ data[i].record = i;
+ for (j = 0; j < nFields; j++) {
+ data[i].value[j].null = 0;
+ switch (fldType[j]) {
+ case FIDType:
+ data[i].value[j].u.i = i;
+ break;
+ case SHPType:
+ feat = SHPReadObject(shp, i);
+ switch (feat->nSHPType) {
+ case SHPT_NULL:
+ fprintf(stderr, "Shape %d is a null feature!\n", i);
+ data[i].value[j].null = 1;
+ break;
+ case SHPT_POINT:
+ case SHPT_POINTZ:
+ case SHPT_POINTM:
+ case SHPT_MULTIPOINT:
+ case SHPT_MULTIPOINTZ:
+ case SHPT_MULTIPOINTM:
+ case SHPT_MULTIPATCH:
+ /* Y-sort bounds */
+ data[i].value[j].u.d = feat->dfYMax;
+ break;
+ case SHPT_ARC:
+ case SHPT_ARCZ:
+ case SHPT_ARCM:
+ data[i].value[j].u.d = shp_length(feat);
+ break;
+ case SHPT_POLYGON:
+ case SHPT_POLYGONZ:
+ case SHPT_POLYGONM:
+ data[i].value[j].u.d = shp_area(feat);
+ break;
+ default:
+ fputs("Can't sort on Shapefile feature type!\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ SHPDestroyObject(feat);
+ break;
+ case FTString:
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
+ if (!data[i].value[j].null) {
+ data[i].value[j].u.s = dupstr(DBFReadStringAttribute(dbf, i, fldIdx[j]));
+ }
+ break;
+ case FTInteger:
+ case FTLogical:
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
+ if (!data[i].value[j].null) {
+ data[i].value[j].u.i = DBFReadIntegerAttribute(dbf, i, fldIdx[j]);
+ }
+ break;
+ case FTDouble:
+ data[i].value[j].null = DBFIsAttributeNULL(dbf, i, fldIdx[j]);
+ if (!data[i].value[j].null) {
+ data[i].value[j].u.d = DBFReadDoubleAttribute(dbf, i, fldIdx[j]);
+ }
+ break;
+ }
+ }
+ }
+
+#ifdef DEBUG
+ PrintDataStruct(data);
+ fputs("build_index: sorting array\n", stdout);
+#endif
+
+ qsort (data, nShapes, sizeof data[0], compare);
+
+#ifdef DEBUG
+ PrintDataStruct(data);
+ fputs("build_index: returning array\n", stdout);
+#endif
+
+ return data;
+}
+
+static int compare(const void *A, const void *B) {
+ const struct DataStruct *a = A;
+ const struct DataStruct *b = B;
+ int i;
+ int result = 0;
+
+ for (i = 0; i < nFields; i++) {
+ if (a->value[i].null && b->value[i].null) {
+ continue;
+ }
+ if (a->value[i].null && !b->value[i].null) {
+ return (fldOrder[i]) ? 1 : -1;
+ }
+ if (!a->value[i].null && b->value[i].null) {
+ return (fldOrder[i]) ? -1 : 1;
+ }
+ switch (fldType[i]) {
+ case FIDType:
+ case IntegerType:
+ case LogicalType:
+ if (a->value[i].u.i < b->value[i].u.i) {
+ return (fldOrder[i]) ? -1 : 1;
+ }
+ if (a->value[i].u.i > b->value[i].u.i) {
+ return (fldOrder[i]) ? 1 : -1;
+ }
+ break;
+ case DoubleType:
+ case SHPType:
+ if (a->value[i].u.d < b->value[i].u.d) {
+ return (fldOrder[i]) ? -1 : 1;
+ }
+ if (a->value[i].u.d > b->value[i].u.d) {
+ return (fldOrder[i]) ? 1 : -1;
+ }
+ break;
+ case StringType:
+ result = strcmp(a->value[i].u.s, b->value[i].u.s);
+ if (result) {
+ return (fldOrder[i]) ? result : -result;
+ }
+ break;
+ default:
+ fprintf(stderr, "compare: Program Error! Unhandled field type! fldType[%d] = %d\n", i, fldType[i]);
+ break;
+ }
+ }
+ return 0;
+}
+
+static double area2d_polygon (int n, double *x, double *y) {
+ double area = 0;
+ int i;
+ for (i = 1; i < n; i++) {
+ area += (x[i-1] + x[i]) * (y[i] - y[i-1]);
+ }
+ return area / 2.0;
+}
+
+static double shp_area (SHPObject *feat) {
+ double area = 0.0;
+ if (feat->nParts == 0) {
+ area = area2d_polygon (feat->nVertices, feat->padfX, feat->padfY);
+ }
+ else {
+ int part, n;
+ for (part = 0; part < feat->nParts; part++) {
+ if (part < feat->nParts - 1) {
+ n = feat->panPartStart[part+1] - feat->panPartStart[part];
+ }
+ else {
+ n = feat->nVertices - feat->panPartStart[part];
+ }
+ area += area2d_polygon (n, &(feat->padfX[feat->panPartStart[part]]),
+ &(feat->padfY[feat->panPartStart[part]]));
+ }
+ }
+ /* our area function computes in opposite direction */
+ return -area;
+}
+
+static double length2d_polyline (int n, double *x, double *y) {
+ double length = 0.0;
+ int i;
+ for (i = 1; i < n; i++) {
+ length += sqrt((x[i] - x[i-1])*(x[i] - x[i-1])
+ +
+ (y[i] - y[i-1])*(y[i] - y[i-1]));
+ }
+ return length;
+}
+
+static double shp_length (SHPObject *feat) {
+ double length = 0.0;
+ if (feat->nParts == 0) {
+ length = length2d_polyline(feat->nVertices, feat->padfX, feat->padfY);
+ }
+ else {
+ int part, n;
+ for (part = 0; part < feat->nParts; part++) {
+ if (part < feat->nParts - 1) {
+ n = feat->panPartStart[part+1] - feat->panPartStart[part];
+ }
+ else {
+ n = feat->nVertices - feat->panPartStart[part];
+ }
+ length += length2d_polyline (n,
+ &(feat->padfX[feat->panPartStart[part]]),
+ &(feat->padfY[feat->panPartStart[part]]));
+ }
+ }
+ return length;
+}
+
diff --git a/contrib/shpsort.txt b/contrib/shpsort.txt
new file mode 100644
index 0000000..7e40348
--- /dev/null
+++ b/contrib/shpsort.txt
@@ -0,0 +1,44 @@
+============================= ABOUT ===========================================
+
+The program "shpsort" is a standalone program for sorting shapefiles
+on one or more fields (including the pseudofield "SHAPE") and outputing
+the results. People may find it useful for forcing drawing order.
+
+============================= AUTHOR ==========================================
+
+Eric G. Miller
+California Department of Fish and Game
+2004-06-30
+
+============================= USAGE ===========================================
+
+shpsort <INFILE> <OUTFILE> <SORT_FIELD;SORT_FIELD...> {SORT_ORDER;SORT_ORDER...}
+
+============================= DETAILS =========================================
+
+INFILE The input shapefile
+
+OUTFILE The output shapefile
+
+SORT_FIELD Any attribute field of the shapefile, including "SHAPE"
+
+SORT_ORDER Specify "ASCENDING" or "DESCENDING" for each SORT_FIELD.
+ This field is optional, and is assumed to be ASCENDING
+ unless the exact word "DESCENDING" is specified (case
+ matters).
+
+ When sorting on the "SHAPE" the records are sorted as follows:
+
+ * Null shapes are treated as any other null field and will
+ sort to the top in ASCENDING mode. A warning is issued
+ for each null shape encountered.
+ * POINT, POINTM, POINTZ, MULTIPOINT, MULTIPOINTM, MULTIPOINTZ
+ and MULTIPATCH are all sorted by the maximum "Y" value of
+ their envelopes (not particularly useful).
+ * POLYLINE, POLYLINEZ and POLYLINEM are sorted by total 2d
+ shape length.
+ * POLYGON, POLYGONZ and POLYGONM are sorted by the 2d shape
+ area. Shapes are assumed to be in canonical ordering, so that
+ the area of interior rings (if any) is subtracted from the
+ area of exterior rings.
+
diff --git a/contrib/shpwkb.c b/contrib/shpwkb.c
index b11fb80..7c2725b 100644
--- a/contrib/shpwkb.c
+++ b/contrib/shpwkb.c
@@ -26,7 +26,7 @@
*
*
* $Log: shpwkb.c,v $
- * Revision 1.1 1999/05/26 02:29:36 candrsn
+ * Revision 1.1 1999-05-26 02:29:36 candrsn
* OGis Well Known Binary test program (output only)
*
*
diff --git a/contrib/tests/shpproj.sh b/contrib/tests/shpproj.sh
index 3520929..4996791 100755
--- a/contrib/tests/shpproj.sh
+++ b/contrib/tests/shpproj.sh
@@ -11,7 +11,7 @@ shpadd test -84.01681518 34.67275985
shpadd test -84.15596023 34.64862437
shpadd test -83.61951463 34.54927047
-dbfcreate test -s 30 fd
+dbfcreate test -s fd 30
dbfadd test "1"
dbfadd test "2"
dbfadd test "3"
@@ -35,4 +35,4 @@ fi
rm test*
-cd ..
\ No newline at end of file
+cd ..
diff --git a/dbfadd.c b/dbfadd.c
index f978208..3d323ec 100644
--- a/dbfadd.c
+++ b/dbfadd.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: dbfadd.c,v 1.7 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: dbfadd.c,v 1.9 2004-09-26 20:09:35 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for adding a record to an existing .dbf file.
@@ -34,6 +34,12 @@
******************************************************************************
*
* $Log: dbfadd.c,v $
+ * Revision 1.9 2004-09-26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.8 2004/01/09 16:39:49 fwarmerdam
+ * include standard include files
+ *
* Revision 1.7 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -54,13 +60,14 @@
*
*/
-static char rcsid[] =
- "$Id: dbfadd.c,v 1.7 2002/01/15 14:36:07 warmerda Exp $";
-
-#include "shapefil.h"
+#include <string.h>
#include <math.h>
#include <stdlib.h>
+#include "shapefil.h"
+
+SHP_CVSID("$Id: dbfadd.c,v 1.9 2004-09-26 20:09:35 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
diff --git a/dbfcreate.c b/dbfcreate.c
index f1e22ab..eb5ddfc 100644
--- a/dbfcreate.c
+++ b/dbfcreate.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: dbfcreate.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: dbfcreate.c,v 1.7 2004-09-26 20:09:35 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for creating a new .dbf file.
@@ -34,6 +34,9 @@
******************************************************************************
*
* $Log: dbfcreate.c,v $
+ * Revision 1.7 2004-09-26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
* Revision 1.6 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -51,13 +54,12 @@
*
*/
-static char rcsid[] =
- "$Id: dbfcreate.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $";
-
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
+SHP_CVSID("$Id: dbfcreate.c,v 1.7 2004-09-26 20:09:35 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
diff --git a/dbfdump.c b/dbfdump.c
index 9fe44fa..8c3e65e 100644
--- a/dbfdump.c
+++ b/dbfdump.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: dbfdump.c,v 1.9 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: dbfdump.c,v 1.12 2006-06-17 00:15:08 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for dumping .dbf files to the terminal.
@@ -34,6 +34,15 @@
******************************************************************************
*
* $Log: dbfdump.c,v $
+ * Revision 1.12 2006-06-17 00:15:08 fwarmerdam
+ * Free panWidth for better memory testing.
+ *
+ * Revision 1.11 2006/02/15 01:11:27 fwarmerdam
+ * added reporting of native type
+ *
+ * Revision 1.10 2004/09/26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
* Revision 1.9 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -60,13 +69,12 @@
*
*/
-static char rcsid[] =
- "$Id: dbfdump.c,v 1.9 2002/01/15 14:36:07 warmerda Exp $";
-
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
+SHP_CVSID("$Id: dbfdump.c,v 1.12 2006-06-17 00:15:08 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
@@ -134,6 +142,9 @@ int main( int argc, char ** argv )
{
DBFFieldType eType;
const char *pszTypeName;
+ char chNativeType;
+
+ chNativeType = DBFGetNativeFieldType( hDBF, i );
eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
if( eType == FTString )
@@ -145,8 +156,8 @@ int main( int argc, char ** argv )
else if( eType == FTInvalid )
pszTypeName = "Invalid";
- printf( "Field %d: Type=%s, Title=`%s', Width=%d, Decimals=%d\n",
- i, pszTypeName, szTitle, nWidth, nDecimals );
+ printf( "Field %d: Type=%c/%s, Title=`%s', Width=%d, Decimals=%d\n",
+ i, chNativeType, pszTypeName, szTitle, nWidth, nDecimals );
}
}
@@ -162,7 +173,7 @@ int main( int argc, char ** argv )
DBFFieldType eType;
eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals );
- if( strlen(szTitle) > nWidth )
+ if( (int) strlen(szTitle) > nWidth )
panWidth[i] = strlen(szTitle);
else
panWidth[i] = nWidth;
@@ -266,6 +277,7 @@ int main( int argc, char ** argv )
}
DBFClose( hDBF );
+ free( panWidth );
return( 0 );
}
diff --git a/dbfopen.c b/dbfopen.c
index 43b25ac..fbe7b06 100644
--- a/dbfopen.c
+++ b/dbfopen.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: dbfopen.c,v 1.48 2003/03/10 14:51:27 warmerda Exp $
+ * $Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Implementation of .dbf access API documented in dbf_api.html.
@@ -34,157 +34,128 @@
******************************************************************************
*
* $Log: dbfopen.c,v $
- * Revision 1.48 2003/03/10 14:51:27 warmerda
- * DBFWrite* calls now return FALSE if they have to truncate
+ * Revision 1.89 2011-07-24 05:59:25 fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
*
- * Revision 1.47 2002/11/20 03:32:22 warmerda
- * Ensure field name in DBFGetFieldIndex() is properly terminated.
+ * Revision 1.88 2011-05-13 17:35:17 fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
*
- * Revision 1.46 2002/10/09 13:10:21 warmerda
- * Added check that width is positive.
+ * Revision 1.87 2011-05-07 22:41:02 fwarmerdam
+ * ensure pending record is flushed when adding a native field (GDAL #4073)
*
- * Revision 1.45 2002/09/29 00:00:08 warmerda
- * added FTLogical and logical attribute read/write calls
+ * Revision 1.86 2011-04-17 15:15:29 fwarmerdam
+ * Removed unused variable.
*
- * Revision 1.44 2002/05/07 13:46:11 warmerda
- * Added DBFWriteAttributeDirectly().
+ * Revision 1.85 2010-12-06 16:09:34 fwarmerdam
+ * fix buffer read overrun fetching code page (bug 2276)
*
- * Revision 1.43 2002/02/13 19:39:21 warmerda
- * Fix casting issues in DBFCloneEmpty().
+ * Revision 1.84 2009-10-29 19:59:48 fwarmerdam
+ * avoid crash on truncated header (gdal #3093)
*
- * Revision 1.42 2002/01/15 14:36:07 warmerda
- * updated email address
+ * Revision 1.83 2008/11/12 14:28:15 fwarmerdam
+ * DBFCreateField() now works on files with records
*
- * Revision 1.41 2002/01/15 14:31:49 warmerda
- * compute rather than copying nHeaderLength in DBFCloneEmpty()
+ * Revision 1.82 2008/11/11 17:47:09 fwarmerdam
+ * added DBFDeleteField() function
*
- * Revision 1.40 2002/01/09 04:32:35 warmerda
- * fixed to read correct amount of header
+ * Revision 1.81 2008/01/03 17:48:13 bram
+ * in DBFCreate, use default code page LDID/87 (= 0x57, ANSI)
+ * instead of LDID/3. This seems to be the same as what ESRI
+ * would be doing by default.
*
- * Revision 1.39 2001/12/11 22:41:03 warmerda
- * improve io related error checking when reading header
+ * Revision 1.80 2007/12/30 14:36:39 fwarmerdam
+ * avoid syntax issue with last comment.
*
- * Revision 1.38 2001/11/28 16:07:31 warmerda
- * Cleanup to avoid compiler warnings as suggested by Richard Hash.
+ * Revision 1.79 2007/12/30 14:35:48 fwarmerdam
+ * Avoid char* / unsigned char* warnings.
*
- * Revision 1.37 2001/07/04 05:18:09 warmerda
- * do last fix properly
+ * Revision 1.78 2007/12/18 18:28:07 bram
+ * - create hook for client specific atof (bugzilla ticket 1615)
+ * - check for NULL handle before closing cpCPG file, and close after reading.
*
- * Revision 1.36 2001/07/04 05:16:09 warmerda
- * fixed fieldname comparison in DBFGetFieldIndex
+ * Revision 1.77 2007/12/15 20:25:21 bram
+ * dbfopen.c now reads the Code Page information from the DBF file, and exports
+ * this information as a string through the DBFGetCodePage function. This is
+ * either the number from the LDID header field ("LDID/<number>") or as the
+ * content of an accompanying .CPG file. When creating a DBF file, the code can
+ * be set using DBFCreateEx.
*
- * Revision 1.35 2001/06/22 02:10:06 warmerda
- * fixed NULL shape support with help from Jim Matthews
+ * Revision 1.76 2007/12/12 22:21:32 bram
+ * DBFClose: check for NULL psDBF handle before trying to close it.
*
- * Revision 1.33 2001/05/31 19:20:13 warmerda
- * added DBFGetFieldIndex()
+ * Revision 1.75 2007/12/06 13:58:19 fwarmerdam
+ * make sure file offset calculations are done in as SAOffset
*
- * Revision 1.32 2001/05/31 18:15:40 warmerda
- * Added support for NULL fields in DBF files
+ * Revision 1.74 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
*
- * Revision 1.31 2001/05/23 13:36:52 warmerda
- * added use of SHPAPI_CALL
+ * Revision 1.73 2007/09/03 19:48:11 fwarmerdam
+ * move DBFReadAttribute() static dDoubleField into dbfinfo
*
- * Revision 1.30 2000/12/05 14:43:38 warmerda
- * DBReadAttribute() white space trimming bug fix
+ * Revision 1.72 2007/09/03 19:34:06 fwarmerdam
+ * Avoid use of static tuple buffer in DBFReadTuple()
*
- * Revision 1.29 2000/10/05 14:36:44 warmerda
- * fix bug with writing very wide numeric fields
+ * Revision 1.71 2006/06/22 14:37:18 fwarmerdam
+ * avoid memory leak if dbfopen fread fails
*
- * Revision 1.28 2000/09/25 14:18:07 warmerda
- * Added some casts of strlen() return result to fix warnings on some
- * systems, as submitted by Daniel.
+ * Revision 1.70 2006/06/17 17:47:05 fwarmerdam
+ * use calloc() for dbfinfo in DBFCreate
*
- * Revision 1.27 2000/09/25 14:15:51 warmerda
- * added DBFGetNativeFieldType()
+ * Revision 1.69 2006/06/17 15:34:32 fwarmerdam
+ * disallow creating fields wider than 255
*
- * Revision 1.26 2000/07/07 13:39:45 warmerda
- * removed unused variables, and added system include files
+ * Revision 1.68 2006/06/17 15:12:40 fwarmerdam
+ * Fixed C++ style comments.
*
- * Revision 1.25 2000/05/29 18:19:13 warmerda
- * avoid use of uchar, and adding casting fix
+ * Revision 1.67 2006/06/17 00:24:53 fwarmerdam
+ * Don't treat non-zero decimals values as high order byte for length
+ * for strings. It causes serious corruption for some files.
+ * http://bugzilla.remotesensing.org/show_bug.cgi?id=1202
*
- * Revision 1.24 2000/05/23 13:38:27 warmerda
- * Added error checks on return results of fread() and fseek().
+ * Revision 1.66 2006/03/29 18:26:20 fwarmerdam
+ * fixed bug with size of pachfieldtype in dbfcloneempty
*
- * Revision 1.23 2000/05/23 13:25:49 warmerda
- * Avoid crashing if field or record are out of range in dbfread*attribute().
+ * Revision 1.65 2006/02/15 01:14:30 fwarmerdam
+ * added DBFAddNativeFieldType
*
- * Revision 1.22 1999/12/15 13:47:24 warmerda
- * Added stdlib.h to ensure that atof() is prototyped.
+ * Revision 1.64 2006/02/09 00:29:04 fwarmerdam
+ * Changed to put spaces into string fields that are NULL as
+ * per http://bugzilla.maptools.org/show_bug.cgi?id=316.
*
- * Revision 1.21 1999/12/13 17:25:46 warmerda
- * Added support for upper case .DBF extention.
+ * Revision 1.63 2006/01/25 15:35:43 fwarmerdam
+ * check success on DBFFlushRecord
*
- * Revision 1.20 1999/11/30 16:32:11 warmerda
- * Use atof() instead of sscanf().
+ * Revision 1.62 2006/01/10 16:28:03 fwarmerdam
+ * Fixed typo in CPLError.
*
- * Revision 1.19 1999/11/05 14:12:04 warmerda
- * updated license terms
+ * Revision 1.61 2006/01/10 16:26:29 fwarmerdam
+ * Push loading record buffer into DBFLoadRecord.
+ * Implement CPL error reporting if USE_CPL defined.
*
- * Revision 1.18 1999/07/27 00:53:28 warmerda
- * ensure that whole old field value clear on write of string
+ * Revision 1.60 2006/01/05 01:27:27 fwarmerdam
+ * added dbf deletion mark/fetch
*
- * Revision 1.1 1999/07/05 18:58:07 warmerda
- * New
+ * Revision 1.59 2005/03/14 15:20:28 fwarmerdam
+ * Fixed last change.
*
- * Revision 1.17 1999/06/11 19:14:12 warmerda
- * Fixed some memory leaks.
+ * Revision 1.58 2005/03/14 15:18:54 fwarmerdam
+ * Treat very wide fields with no decimals as double. This is
+ * more than 32bit integer fields.
*
- * Revision 1.16 1999/06/11 19:04:11 warmerda
- * Remoted some unused variables.
+ * Revision 1.57 2005/02/10 20:16:54 fwarmerdam
+ * Make the pszStringField buffer for DBFReadAttribute() static char [256]
+ * as per bug 306.
*
- * Revision 1.15 1999/05/11 03:19:28 warmerda
- * added new Tuple api, and improved extension handling - add from candrsn
+ * Revision 1.56 2005/02/10 20:07:56 fwarmerdam
+ * Fixed bug 305 in DBFCloneEmpty() - header length problem.
*
- * Revision 1.14 1999/05/04 15:01:48 warmerda
- * Added 'F' support.
+ * Revision 1.55 2004/09/26 20:23:46 fwarmerdam
+ * avoid warnings with rcsid and signed/unsigned stuff
*
- * Revision 1.13 1999/03/23 17:38:59 warmerda
- * DBFAddField() now actually does return the new field number, or -1 if
- * it fails.
- *
- * Revision 1.12 1999/03/06 02:54:46 warmerda
- * Added logic to convert shapefile name to dbf filename in DBFOpen()
- * for convenience.
- *
- * Revision 1.11 1998/12/31 15:30:34 warmerda
- * Improved the interchangability of numeric and string attributes. Add
- * white space trimming option for attributes.
- *
- * Revision 1.10 1998/12/03 16:36:44 warmerda
- * Use r+b instead of rb+ for binary access.
- *
- * Revision 1.9 1998/12/03 15:34:23 warmerda
- * Updated copyright message.
- *
- * Revision 1.8 1997/12/04 15:40:15 warmerda
- * Added newline character after field definitions.
- *
- * Revision 1.7 1997/03/06 14:02:10 warmerda
- * Ensure bUpdated is initialized.
- *
- * Revision 1.6 1996/02/12 04:54:41 warmerda
- * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
- *
- * Revision 1.5 1995/10/21 03:15:12 warmerda
- * Changed to use binary file access, and ensure that the
- * field name field is zero filled, and limited to 10 chars.
- *
- * Revision 1.4 1995/08/24 18:10:42 warmerda
- * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
- * as on the Sun.
- *
- * Revision 1.3 1995/08/04 03:15:16 warmerda
- * Fixed up header.
- *
- * Revision 1.2 1995/08/04 03:14:43 warmerda
- * Added header.
+ * Revision 1.54 2004/09/15 16:26:10 fwarmerdam
+ * Treat all blank numeric fields as null too.
*/
-static char rcsid[] =
- "$Id: dbfopen.c,v 1.48 2003/03/10 14:51:27 warmerda Exp $";
-
#include "shapefil.h"
#include <math.h>
@@ -192,14 +163,13 @@ static char rcsid[] =
#include <ctype.h>
#include <string.h>
+SHP_CVSID("$Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $")
+
#ifndef FALSE
# define FALSE 0
# define TRUE 1
#endif
-static int nStringFieldLen = 0;
-static char * pszStringField = NULL;
-
/************************************************************************/
/* SfRealloc() */
/* */
@@ -244,21 +214,29 @@ static void DBFWriteHeader(DBFHandle psDBF)
abyHeader[0] = 0x03; /* memo field? - just copying */
- /* date updated on close, record count preset at zero */
+ /* write out a dummy date */
+ abyHeader[1] = 95; /* YY */
+ abyHeader[2] = 7; /* MM */
+ abyHeader[3] = 26; /* DD */
- abyHeader[8] = psDBF->nHeaderLength % 256;
- abyHeader[9] = psDBF->nHeaderLength / 256;
+ /* record count preset at zero */
+
+ abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256);
+ abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256);
- abyHeader[10] = psDBF->nRecordLength % 256;
- abyHeader[11] = psDBF->nRecordLength / 256;
+ abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
+ abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
+
+ abyHeader[29] = (unsigned char) (psDBF->iLanguageDriver);
/* -------------------------------------------------------------------- */
/* Write the initial 32 byte file header, and all the field */
/* descriptions. */
/* -------------------------------------------------------------------- */
- fseek( psDBF->fp, 0, 0 );
- fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
- fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FWrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+ psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
+ psDBF->fp );
/* -------------------------------------------------------------------- */
/* Write out the newline character if there is room for it. */
@@ -268,7 +246,7 @@ static void DBFWriteHeader(DBFHandle psDBF)
char cNewline;
cNewline = 0x0d;
- fwrite( &cNewline, 1, 1, psDBF->fp );
+ psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
}
}
@@ -278,21 +256,104 @@ static void DBFWriteHeader(DBFHandle psDBF)
/* Write out the current record if there is one. */
/************************************************************************/
-static void DBFFlushRecord( DBFHandle psDBF )
+static int DBFFlushRecord( DBFHandle psDBF )
{
- int nRecordOffset;
+ SAOffset nRecordOffset;
if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
{
psDBF->bCurrentRecordModified = FALSE;
- nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
- + psDBF->nHeaderLength;
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord
+ + psDBF->nHeaderLength;
+
+ if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
+ || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
+ psDBF->nRecordLength,
+ 1, psDBF->fp ) != 1 )
+ {
+ char szMessage[128];
+ sprintf( szMessage, "Failure writing DBF record %d.",
+ psDBF->nCurrentRecord );
+ psDBF->sHooks.Error( szMessage );
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* DBFLoadRecord() */
+/************************************************************************/
+
+static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
+
+{
+ if( psDBF->nCurrentRecord != iRecord )
+ {
+ SAOffset nRecordOffset;
+
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
+
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
+ {
+ char szMessage[128];
+ sprintf( szMessage, "fseek(%ld) failed on DBF file.\n",
+ (long) nRecordOffset );
+ psDBF->sHooks.Error( szMessage );
+ return FALSE;
+ }
+
+ if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
+ psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
+ {
+ char szMessage[128];
+ sprintf( szMessage, "fread(%d) failed on DBF file.\n",
+ psDBF->nRecordLength );
+ psDBF->sHooks.Error( szMessage );
+ return FALSE;
+ }
- fseek( psDBF->fp, nRecordOffset, 0 );
- fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->nCurrentRecord = iRecord;
}
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* DBFUpdateHeader() */
+/************************************************************************/
+
+void SHPAPI_CALL
+DBFUpdateHeader( DBFHandle psDBF )
+
+{
+ unsigned char abyFileHeader[32];
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader( psDBF );
+
+ DBFFlushRecord( psDBF );
+
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FRead( abyFileHeader, 32, 1, psDBF->fp );
+
+ abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
+ abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
+ abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
+ abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
+
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FWrite( abyFileHeader, 32, 1, psDBF->fp );
+
+ psDBF->sHooks.FFlush( psDBF->fp );
}
/************************************************************************/
@@ -305,10 +366,29 @@ DBFHandle SHPAPI_CALL
DBFOpen( const char * pszFilename, const char * pszAccess )
{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return DBFOpenLL( pszFilename, pszAccess, &sHooks );
+}
+
+/************************************************************************/
+/* DBFOpen() */
+/* */
+/* Open a .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
+
+{
DBFHandle psDBF;
- unsigned char *pabyBuf;
- int nFields, nHeadLen, nRecLen, iField, i;
+ SAFile pfCPG;
+ unsigned char *pabyBuf;
+ int nFields, nHeadLen, iField, i;
char *pszBasename, *pszFullname;
+ int nBufSize = 500;
/* -------------------------------------------------------------------- */
/* We only allow the access strings "rb" and "r+". */
@@ -342,20 +422,30 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
sprintf( pszFullname, "%s.dbf", pszBasename );
psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
- psDBF->fp = fopen( pszFullname, pszAccess );
+ psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
+ memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
if( psDBF->fp == NULL )
{
sprintf( pszFullname, "%s.DBF", pszBasename );
- psDBF->fp = fopen(pszFullname, pszAccess );
+ psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
}
-
+
+ sprintf( pszFullname, "%s.cpg", pszBasename );
+ pfCPG = psHooks->FOpen( pszFullname, "r" );
+ if( pfCPG == NULL )
+ {
+ sprintf( pszFullname, "%s.CPG", pszBasename );
+ pfCPG = psHooks->FOpen( pszFullname, "r" );
+ }
+
free( pszBasename );
free( pszFullname );
if( psDBF->fp == NULL )
{
free( psDBF );
+ if( pfCPG ) psHooks->FClose( pfCPG );
return( NULL );
}
@@ -366,10 +456,11 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
/* -------------------------------------------------------------------- */
/* Read Table Header info */
/* -------------------------------------------------------------------- */
- pabyBuf = (unsigned char *) malloc(500);
- if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+ pabyBuf = (unsigned char *) malloc(nBufSize);
+ if( psDBF->sHooks.FRead( pabyBuf, 32, 1, psDBF->fp ) != 1 )
{
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
+ if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
free( pabyBuf );
free( psDBF );
return NULL;
@@ -379,11 +470,47 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
- psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
-
+ psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
+ psDBF->iLanguageDriver = pabyBuf[29];
+
+ if (nHeadLen < 32)
+ {
+ psDBF->sHooks.FClose( psDBF->fp );
+ if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
+ free( pabyBuf );
+ free( psDBF );
+ return NULL;
+ }
+
psDBF->nFields = nFields = (nHeadLen - 32) / 32;
- psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
+ psDBF->pszCurrentRecord = (char *) malloc(psDBF->nRecordLength);
+
+/* -------------------------------------------------------------------- */
+/* Figure out the code page from the LDID and CPG */
+/* -------------------------------------------------------------------- */
+
+ psDBF->pszCodePage = NULL;
+ if( pfCPG )
+ {
+ size_t n;
+ memset( pabyBuf, 0, nBufSize);
+ psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
+ n = strcspn( (char *) pabyBuf, "\n\r" );
+ if( n > 0 )
+ {
+ pabyBuf[n] = '\0';
+ psDBF->pszCodePage = (char *) malloc(n + 1);
+ memcpy( psDBF->pszCodePage, pabyBuf, n + 1 );
+ }
+ psDBF->sHooks.FClose( pfCPG );
+ }
+ if( psDBF->pszCodePage == NULL && pabyBuf[29] != 0 )
+ {
+ sprintf( (char *) pabyBuf, "LDID/%d", psDBF->iLanguageDriver );
+ psDBF->pszCodePage = (char *) malloc(strlen((char*)pabyBuf) + 1);
+ strcpy( psDBF->pszCodePage, (char *) pabyBuf );
+ }
/* -------------------------------------------------------------------- */
/* Read in Field Definitions */
@@ -392,11 +519,12 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
psDBF->pszHeader = (char *) pabyBuf;
- fseek( psDBF->fp, 32, 0 );
- if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+ psDBF->sHooks.FSeek( psDBF->fp, 32, 0 );
+ if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
{
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
free( pabyBuf );
+ free( psDBF->pszCurrentRecord );
free( psDBF );
return NULL;
}
@@ -419,8 +547,17 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
}
else
{
+ psDBF->panFieldSize[iField] = pabyFInfo[16];
+ psDBF->panFieldDecimals[iField] = 0;
+
+/*
+** The following seemed to be used sometimes to handle files with long
+** string fields, but in other cases (such as bug 1202) the decimals field
+** just seems to indicate some sort of preferred formatting, not very
+** wide fields. So I have disabled this code. FrankW.
psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
psDBF->panFieldDecimals[iField] = 0;
+*/
}
psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
@@ -441,6 +578,9 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
void SHPAPI_CALL
DBFClose(DBFHandle psDBF)
{
+ if( psDBF == NULL )
+ return;
+
/* -------------------------------------------------------------------- */
/* Write out header if not already written. */
/* -------------------------------------------------------------------- */
@@ -454,29 +594,12 @@ DBFClose(DBFHandle psDBF)
/* write access. */
/* -------------------------------------------------------------------- */
if( psDBF->bUpdated )
- {
- unsigned char abyFileHeader[32];
-
- fseek( psDBF->fp, 0, 0 );
- fread( abyFileHeader, 32, 1, psDBF->fp );
-
- abyFileHeader[1] = 95; /* YY */
- abyFileHeader[2] = 7; /* MM */
- abyFileHeader[3] = 26; /* DD */
-
- abyFileHeader[4] = psDBF->nRecords % 256;
- abyFileHeader[5] = (psDBF->nRecords/256) % 256;
- abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
- abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
-
- fseek( psDBF->fp, 0, 0 );
- fwrite( abyFileHeader, 32, 1, psDBF->fp );
- }
+ DBFUpdateHeader( psDBF );
/* -------------------------------------------------------------------- */
/* Close, and free resources. */
/* -------------------------------------------------------------------- */
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
if( psDBF->panFieldOffset != NULL )
{
@@ -486,17 +609,44 @@ DBFClose(DBFHandle psDBF)
free( psDBF->pachFieldType );
}
+ if( psDBF->pszWorkField != NULL )
+ free( psDBF->pszWorkField );
+
free( psDBF->pszHeader );
free( psDBF->pszCurrentRecord );
+ free( psDBF->pszCodePage );
free( psDBF );
+}
- if( pszStringField != NULL )
- {
- free( pszStringField );
- pszStringField = NULL;
- nStringFieldLen = 0;
- }
+/************************************************************************/
+/* DBFCreate() */
+/* */
+/* Create a new .dbf file with default code page LDID/87 (0x57) */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreate( const char * pszFilename )
+
+{
+ return DBFCreateEx( pszFilename, "LDID/87" ); // 0x57
+}
+
+/************************************************************************/
+/* DBFCreateEx() */
+/* */
+/* Create a new .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreateEx( const char * pszFilename, const char* pszCodePage )
+
+{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
}
/************************************************************************/
@@ -506,13 +656,14 @@ DBFClose(DBFHandle psDBF)
/************************************************************************/
DBFHandle SHPAPI_CALL
-DBFCreate( const char * pszFilename )
+DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHooks )
{
DBFHandle psDBF;
- FILE *fp;
+ SAFile fp;
char *pszFullname, *pszBasename;
- int i;
+ int i, ldid = -1;
+ char chZero = '\0';
/* -------------------------------------------------------------------- */
/* Compute the base (layer) name. If there is any extension */
@@ -530,29 +681,52 @@ DBFCreate( const char * pszFilename )
pszFullname = (char *) malloc(strlen(pszBasename) + 5);
sprintf( pszFullname, "%s.dbf", pszBasename );
- free( pszBasename );
/* -------------------------------------------------------------------- */
/* Create the file. */
/* -------------------------------------------------------------------- */
- fp = fopen( pszFullname, "wb" );
+ fp = psHooks->FOpen( pszFullname, "wb" );
if( fp == NULL )
return( NULL );
+
+ psHooks->FWrite( &chZero, 1, 1, fp );
+ psHooks->FClose( fp );
- fputc( 0, fp );
- fclose( fp );
-
- fp = fopen( pszFullname, "rb+" );
+ fp = psHooks->FOpen( pszFullname, "rb+" );
if( fp == NULL )
return( NULL );
+
+ sprintf( pszFullname, "%s.cpg", pszBasename );
+ if( pszCodePage != NULL )
+ {
+ if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
+ {
+ ldid = atoi( pszCodePage + 5 );
+ if( ldid > 255 )
+ ldid = -1; // don't use 0 to indicate out of range as LDID/0 is a valid one
+ }
+ if( ldid < 0 )
+ {
+ SAFile fpCPG = psHooks->FOpen( pszFullname, "w" );
+ psHooks->FWrite( (char*) pszCodePage, strlen(pszCodePage), 1, fpCPG );
+ psHooks->FClose( fpCPG );
+ }
+ }
+ if( pszCodePage == NULL || ldid >= 0 )
+ {
+ psHooks->Remove( pszFullname );
+ }
+
+ free( pszBasename );
free( pszFullname );
/* -------------------------------------------------------------------- */
/* Create the info structure. */
/* -------------------------------------------------------------------- */
- psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
+ psDBF = (DBFHandle) calloc(1,sizeof(DBFInfo));
+ memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
psDBF->fp = fp;
psDBF->nRecords = 0;
psDBF->nFields = 0;
@@ -571,14 +745,21 @@ DBFCreate( const char * pszFilename )
psDBF->bNoHeader = TRUE;
+ psDBF->iLanguageDriver = ldid > 0 ? ldid : 0;
+ psDBF->pszCodePage = NULL;
+ if( pszCodePage )
+ {
+ psDBF->pszCodePage = (char * ) malloc( strlen(pszCodePage) + 1 );
+ strcpy( psDBF->pszCodePage, pszCodePage );
+ }
+
return( psDBF );
}
/************************************************************************/
/* DBFAddField() */
/* */
-/* Add a field to a newly created .dbf file before any records */
-/* are written. */
+/* Add a field to a newly created .dbf or to an existing one */
/************************************************************************/
int SHPAPI_CALL
@@ -586,24 +767,74 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals )
{
+ char chNativeType = 'C';
+
+ if( eType == FTLogical )
+ chNativeType = 'L';
+ else if( eType == FTString )
+ chNativeType = 'C';
+ else
+ chNativeType = 'N';
+
+ return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType,
+ nWidth, nDecimals );
+}
+
+/************************************************************************/
+/* DBFGetNullCharacter() */
+/************************************************************************/
+
+static char DBFGetNullCharacter(char chType)
+{
+ switch (chType)
+ {
+ case 'N':
+ case 'F':
+ return '*';
+ case 'D':
+ return '0';
+ case 'L':
+ return '?';
+ default:
+ return ' ';
+ }
+}
+
+/************************************************************************/
+/* DBFAddField() */
+/* */
+/* Add a field to a newly created .dbf file before any records */
+/* are written. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
+ char chType, int nWidth, int nDecimals )
+
+{
char *pszFInfo;
int i;
+ int nOldRecordLength, nOldHeaderLength;
+ char *pszRecord;
+ char chFieldFill;
+ SAOffset nRecordOffset;
+
+ /* make sure that everything is written in .dbf */
+ if( !DBFFlushRecord( psDBF ) )
+ return -1;
/* -------------------------------------------------------------------- */
/* Do some checking to ensure we can add records to this file. */
/* -------------------------------------------------------------------- */
- if( psDBF->nRecords > 0 )
- return( -1 );
-
- if( !psDBF->bNoHeader )
- return( -1 );
-
- if( eType != FTDouble && nDecimals != 0 )
- return( -1 );
-
if( nWidth < 1 )
return -1;
+ if( nWidth > 255 )
+ nWidth = 255;
+
+ nOldRecordLength = psDBF->nRecordLength;
+ nOldHeaderLength = psDBF->nHeaderLength;
+
/* -------------------------------------------------------------------- */
/* SfRealloc all the arrays larger to hold the additional field */
/* information. */
@@ -611,16 +842,16 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
psDBF->nFields++;
psDBF->panFieldOffset = (int *)
- SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+ SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
psDBF->panFieldSize = (int *)
- SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+ SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
psDBF->panFieldDecimals = (int *)
- SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+ SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
psDBF->pachFieldType = (char *)
- SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+ SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
/* -------------------------------------------------------------------- */
/* Assign the new field information fields. */
@@ -629,13 +860,7 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
psDBF->nRecordLength += nWidth;
psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
-
- if( eType == FTLogical )
- psDBF->pachFieldType[psDBF->nFields-1] = 'L';
- else if( eType == FTString )
- psDBF->pachFieldType[psDBF->nFields-1] = 'C';
- else
- psDBF->pachFieldType[psDBF->nFields-1] = 'N';
+ psDBF->pachFieldType[psDBF->nFields-1] = chType;
/* -------------------------------------------------------------------- */
/* Extend the required header information. */
@@ -657,22 +882,63 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
- if( eType == FTString )
+ if( chType == 'C' )
{
- pszFInfo[16] = nWidth % 256;
- pszFInfo[17] = nWidth / 256;
+ pszFInfo[16] = (unsigned char) (nWidth % 256);
+ pszFInfo[17] = (unsigned char) (nWidth / 256);
}
else
{
- pszFInfo[16] = nWidth;
- pszFInfo[17] = nDecimals;
+ pszFInfo[16] = (unsigned char) nWidth;
+ pszFInfo[17] = (unsigned char) nDecimals;
}
/* -------------------------------------------------------------------- */
/* Make the current record buffer appropriately larger. */
/* -------------------------------------------------------------------- */
psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength);
+ psDBF->nRecordLength);
+
+ /* we're done if dealing with new .dbf */
+ if( psDBF->bNoHeader )
+ return( psDBF->nFields - 1 );
+
+/* -------------------------------------------------------------------- */
+/* For existing .dbf file, shift records */
+/* -------------------------------------------------------------------- */
+
+ /* alloc record */
+ pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+
+ chFieldFill = DBFGetNullCharacter(chType);
+
+ for (i = psDBF->nRecords-1; i >= 0; --i)
+ {
+ nRecordOffset = nOldRecordLength * (SAOffset) i + nOldHeaderLength;
+
+ /* load record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+ /* set new field's value to NULL */
+ memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
+
+ nRecordOffset = psDBF->nRecordLength * (SAOffset) i + psDBF->nHeaderLength;
+
+ /* move record to the new place*/
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+
+ /* free record */
+ free(pszRecord);
+
+ /* force update of header with new header, record length and new field */
+ psDBF->bNoHeader = TRUE;
+ DBFUpdateHeader( psDBF );
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
return( psDBF->nFields-1 );
}
@@ -687,12 +953,9 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
char chReqType )
{
- int nRecordOffset;
unsigned char *pabyRec;
void *pReturnField = NULL;
- static double dDoubleField;
-
/* -------------------------------------------------------------------- */
/* Verify selection. */
/* -------------------------------------------------------------------- */
@@ -705,59 +968,42 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
/* -------------------------------------------------------------------- */
/* Have we read the record? */
/* -------------------------------------------------------------------- */
- if( psDBF->nCurrentRecord != hEntity )
- {
- DBFFlushRecord( psDBF );
-
- nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
- if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
- {
- fprintf( stderr, "fseek(%d) failed on DBF file.\n",
- nRecordOffset );
- return NULL;
- }
-
- if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
- 1, psDBF->fp ) != 1 )
- {
- fprintf( stderr, "fread(%d) failed on DBF file.\n",
- psDBF->nRecordLength );
- return NULL;
- }
-
- psDBF->nCurrentRecord = hEntity;
- }
+ if( !DBFLoadRecord( psDBF, hEntity ) )
+ return NULL;
pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
/* -------------------------------------------------------------------- */
-/* Ensure our field buffer is large enough to hold this buffer. */
+/* Ensure we have room to extract the target field. */
/* -------------------------------------------------------------------- */
- if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
+ if( psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength )
{
- nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
- pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
+ psDBF->nWorkFieldLength = psDBF->panFieldSize[iField] + 100;
+ if( psDBF->pszWorkField == NULL )
+ psDBF->pszWorkField = (char *) malloc(psDBF->nWorkFieldLength);
+ else
+ psDBF->pszWorkField = (char *) realloc(psDBF->pszWorkField,
+ psDBF->nWorkFieldLength);
}
/* -------------------------------------------------------------------- */
/* Extract the requested field. */
/* -------------------------------------------------------------------- */
- strncpy( pszStringField,
+ strncpy( psDBF->pszWorkField,
((const char *) pabyRec) + psDBF->panFieldOffset[iField],
psDBF->panFieldSize[iField] );
- pszStringField[psDBF->panFieldSize[iField]] = '\0';
+ psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
- pReturnField = pszStringField;
+ pReturnField = psDBF->pszWorkField;
/* -------------------------------------------------------------------- */
/* Decode the field. */
/* -------------------------------------------------------------------- */
if( chReqType == 'N' )
{
- dDoubleField = atof(pszStringField);
+ psDBF->dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
- pReturnField = &dDoubleField;
+ pReturnField = &(psDBF->dfDoubleField);
}
/* -------------------------------------------------------------------- */
@@ -768,7 +1014,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
{
char *pchSrc, *pchDst;
- pchDst = pchSrc = pszStringField;
+ pchDst = pchSrc = psDBF->pszWorkField;
while( *pchSrc == ' ' )
pchSrc++;
@@ -776,7 +1022,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
*(pchDst++) = *(pchSrc++);
*pchDst = '\0';
- while( pchDst != pszStringField && *(--pchDst) == ' ' )
+ while( pchDst != psDBF->pszWorkField && *(--pchDst) == ' ' )
*pchDst = '\0';
}
#endif
@@ -850,35 +1096,45 @@ DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
}
+
/************************************************************************/
-/* DBFIsAttributeNULL() */
-/* */
-/* Return TRUE if value for field is NULL. */
+/* DBFIsValueNULL() */
/* */
-/* Contributed by Jim Matthews. */
+/* Return TRUE if the passed string is NULL. */
/************************************************************************/
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
+static int DBFIsValueNULL( char chType, const char* pszValue )
{
- const char *pszValue;
+ int i;
- pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+ if( pszValue == NULL )
+ return TRUE;
- switch(psDBF->pachFieldType[iField])
+ switch(chType)
{
case 'N':
case 'F':
- /* NULL numeric fields have value "****************" */
- return pszValue[0] == '*';
+ /*
+ ** We accept all asterisks or all blanks as NULL
+ ** though according to the spec I think it should be all
+ ** asterisks.
+ */
+ if( pszValue[0] == '*' )
+ return TRUE;
+
+ for( i = 0; pszValue[i] != '\0'; i++ )
+ {
+ if( pszValue[i] != ' ' )
+ return FALSE;
+ }
+ return TRUE;
case 'D':
/* NULL date fields have value "00000000" */
return strncmp(pszValue,"00000000",8) == 0;
case 'L':
- /* NULL boolean fields have value "?" */
+ /* NULL boolean fields have value "?" */
return pszValue[0] == '?';
default:
@@ -888,20 +1144,42 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
}
/************************************************************************/
-/* DBFGetFieldCount() */
+/* DBFIsAttributeNULL() */
/* */
-/* Return the number of fields in this table. */
+/* Return TRUE if value for field is NULL. */
+/* */
+/* Contributed by Jim Matthews. */
/************************************************************************/
int SHPAPI_CALL
-DBFGetFieldCount( DBFHandle psDBF )
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
{
- return( psDBF->nFields );
+ const char *pszValue;
+
+ pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+ if( pszValue == NULL )
+ return TRUE;
+
+ return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
}
/************************************************************************/
-/* DBFGetRecordCount() */
+/* DBFGetFieldCount() */
+/* */
+/* Return the number of fields in this table. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldCount( DBFHandle psDBF )
+
+{
+ return( psDBF->nFields );
+}
+
+/************************************************************************/
+/* DBFGetRecordCount() */
/* */
/* Return the number of records in this table. */
/************************************************************************/
@@ -947,10 +1225,10 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
return( FTLogical);
else if( psDBF->pachFieldType[iField] == 'N'
- || psDBF->pachFieldType[iField] == 'F'
- || psDBF->pachFieldType[iField] == 'D' )
+ || psDBF->pachFieldType[iField] == 'F' )
{
- if( psDBF->panFieldDecimals[iField] > 0 )
+ if( psDBF->panFieldDecimals[iField] > 0
+ || psDBF->panFieldSize[iField] > 10 )
return( FTDouble );
else
return( FTInteger );
@@ -971,7 +1249,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
void * pValue )
{
- int nRecordOffset, i, j, nRetResult = TRUE;
+ int i, j, nRetResult = TRUE;
unsigned char *pabyRec;
char szSField[400], szFormat[20];
@@ -989,7 +1267,8 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
/* -------------------------------------------------------------------- */
if( hEntity == psDBF->nRecords )
{
- DBFFlushRecord( psDBF );
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
psDBF->nRecords++;
for( i = 0; i < psDBF->nRecordLength; i++ )
@@ -1002,17 +1281,8 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
/* Is this an existing record, but different than the last one */
/* we accessed? */
/* -------------------------------------------------------------------- */
- if( psDBF->nCurrentRecord != hEntity )
- {
- DBFFlushRecord( psDBF );
-
- nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
- fseek( psDBF->fp, nRecordOffset, 0 );
- fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
-
- psDBF->nCurrentRecord = hEntity;
- }
+ if( !DBFLoadRecord( psDBF, hEntity ) )
+ return FALSE;
pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
@@ -1026,33 +1296,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
/* -------------------------------------------------------------------- */
if( pValue == NULL )
{
- switch(psDBF->pachFieldType[iField])
- {
- case 'N':
- case 'F':
- /* NULL numeric fields have value "****************" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
- psDBF->panFieldSize[iField] );
- break;
-
- case 'D':
- /* NULL date fields have value "00000000" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
- psDBF->panFieldSize[iField] );
- break;
-
- case 'L':
- /* NULL boolean fields have value "?" */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
- psDBF->panFieldSize[iField] );
- break;
-
- default:
- /* empty string fields are considered NULL */
- memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
- psDBF->panFieldSize[iField] );
- break;
- }
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ DBFGetNullCharacter(psDBF->pachFieldType[iField]),
+ psDBF->panFieldSize[iField] );
return TRUE;
}
@@ -1068,7 +1314,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
{
int nWidth = psDBF->panFieldSize[iField];
- if( sizeof(szSField)-2 < nWidth )
+ if( (int) sizeof(szSField)-2 < nWidth )
nWidth = sizeof(szSField)-2;
sprintf( szFormat, "%%%dd", nWidth );
@@ -1086,7 +1332,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
{
int nWidth = psDBF->panFieldSize[iField];
- if( sizeof(szSField)-2 < nWidth )
+ if( (int) sizeof(szSField)-2 < nWidth )
nWidth = sizeof(szSField)-2;
sprintf( szFormat, "%%%d.%df",
@@ -1137,11 +1383,12 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
/* as is to the field position in the record. */
/************************************************************************/
-int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+int SHPAPI_CALL
+DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
void * pValue )
{
- int nRecordOffset, i, j;
+ int i, j;
unsigned char *pabyRec;
/* -------------------------------------------------------------------- */
@@ -1158,7 +1405,8 @@ int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
/* -------------------------------------------------------------------- */
if( hEntity == psDBF->nRecords )
{
- DBFFlushRecord( psDBF );
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
psDBF->nRecords++;
for( i = 0; i < psDBF->nRecordLength; i++ )
@@ -1171,17 +1419,8 @@ int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
/* Is this an existing record, but different than the last one */
/* we accessed? */
/* -------------------------------------------------------------------- */
- if( psDBF->nCurrentRecord != hEntity )
- {
- DBFFlushRecord( psDBF );
-
- nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
- fseek( psDBF->fp, nRecordOffset, 0 );
- fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
-
- psDBF->nCurrentRecord = hEntity;
- }
+ if( !DBFLoadRecord( psDBF, hEntity ) )
+ return FALSE;
pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
@@ -1287,7 +1526,7 @@ int SHPAPI_CALL
DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
{
- int nRecordOffset, i;
+ int i;
unsigned char *pabyRec;
/* -------------------------------------------------------------------- */
@@ -1304,7 +1543,8 @@ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
/* -------------------------------------------------------------------- */
if( hEntity == psDBF->nRecords )
{
- DBFFlushRecord( psDBF );
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
psDBF->nRecords++;
for( i = 0; i < psDBF->nRecordLength; i++ )
@@ -1317,17 +1557,8 @@ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
/* Is this an existing record, but different than the last one */
/* we accessed? */
/* -------------------------------------------------------------------- */
- if( psDBF->nCurrentRecord != hEntity )
- {
- DBFFlushRecord( psDBF );
-
- nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
- fseek( psDBF->fp, nRecordOffset, 0 );
- fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
-
- psDBF->nCurrentRecord = hEntity;
- }
+ if( !DBFLoadRecord( psDBF, hEntity ) )
+ return FALSE;
pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
@@ -1340,49 +1571,23 @@ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
}
/************************************************************************/
-/* DBFReadTuple() */
+/* DBFReadTuple() */
/* */
-/* Read one of the attribute fields of a record. */
+/* Read a complete record. Note that the result is only valid */
+/* till the next record read for any reason. */
/************************************************************************/
const char SHPAPI_CALL1(*)
DBFReadTuple(DBFHandle psDBF, int hEntity )
{
- int nRecordOffset;
- unsigned char *pabyRec;
- static char *pReturnTuple = NULL;
-
- static int nTupleLen = 0;
-
-/* -------------------------------------------------------------------- */
-/* Have we read the record? */
-/* -------------------------------------------------------------------- */
if( hEntity < 0 || hEntity >= psDBF->nRecords )
return( NULL );
- if( psDBF->nCurrentRecord != hEntity )
- {
- DBFFlushRecord( psDBF );
-
- nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
- fseek( psDBF->fp, nRecordOffset, 0 );
- fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
-
- psDBF->nCurrentRecord = hEntity;
- }
-
- pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+ if( !DBFLoadRecord( psDBF, hEntity ) )
+ return NULL;
- if ( nTupleLen < psDBF->nRecordLength) {
- nTupleLen = psDBF->nRecordLength;
- pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
- }
-
- memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
-
- return( pReturnTuple );
+ return (const char *) psDBF->pszCurrentRecord;
}
/************************************************************************/
@@ -1396,24 +1601,24 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
{
DBFHandle newDBF;
- newDBF = DBFCreate ( pszFilename );
+ newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
if ( newDBF == NULL ) return ( NULL );
- newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
- memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
-
newDBF->nFields = psDBF->nFields;
newDBF->nRecordLength = psDBF->nRecordLength;
- newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
+ newDBF->nHeaderLength = psDBF->nHeaderLength;
+ newDBF->pszHeader = (char *) malloc ( newDBF->nHeaderLength );
+ memcpy ( newDBF->pszHeader, psDBF->pszHeader, newDBF->nHeaderLength );
+
newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
- newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
- memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
+ newDBF->pachFieldType = (char *) malloc ( sizeof(char) * psDBF->nFields );
+ memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(char)*psDBF->nFields );
newDBF->bNoHeader = TRUE;
newDBF->bUpdated = TRUE;
@@ -1460,7 +1665,7 @@ static void str_to_upper (char *string)
while (++i < len)
if (isalpha(string[i]) && islower(string[i]))
- string[i] = toupper ((int)string[i]);
+ string[i] = (char) toupper ((int)string[i]);
}
/************************************************************************/
@@ -1493,3 +1698,524 @@ DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
}
return(-1);
}
+
+/************************************************************************/
+/* DBFIsRecordDeleted() */
+/* */
+/* Returns TRUE if the indicated record is deleted, otherwise */
+/* it returns FALSE. */
+/************************************************************************/
+
+int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
+
+{
+/* -------------------------------------------------------------------- */
+/* Verify selection. */
+/* -------------------------------------------------------------------- */
+ if( iShape < 0 || iShape >= psDBF->nRecords )
+ return TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Have we read the record? */
+/* -------------------------------------------------------------------- */
+ if( !DBFLoadRecord( psDBF, iShape ) )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* '*' means deleted. */
+/* -------------------------------------------------------------------- */
+ return psDBF->pszCurrentRecord[0] == '*';
+}
+
+/************************************************************************/
+/* DBFMarkRecordDeleted() */
+/************************************************************************/
+
+int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
+ int bIsDeleted )
+
+{
+ char chNewFlag;
+
+/* -------------------------------------------------------------------- */
+/* Verify selection. */
+/* -------------------------------------------------------------------- */
+ if( iShape < 0 || iShape >= psDBF->nRecords )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( !DBFLoadRecord( psDBF, iShape ) )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Assign value, marking record as dirty if it changes. */
+/* -------------------------------------------------------------------- */
+ if( bIsDeleted )
+ chNewFlag = '*';
+ else
+ chNewFlag = ' ';
+
+ if( psDBF->pszCurrentRecord[0] != chNewFlag )
+ {
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+ psDBF->pszCurrentRecord[0] = chNewFlag;
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* DBFGetCodePage */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFGetCodePage(DBFHandle psDBF )
+{
+ if( psDBF == NULL )
+ return NULL;
+ return psDBF->pszCodePage;
+}
+
+/************************************************************************/
+/* DBFDeleteField() */
+/* */
+/* Remove a field from a .dbf file */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFDeleteField(DBFHandle psDBF, int iField)
+{
+ int nOldRecordLength, nOldHeaderLength;
+ int nDeletedFieldOffset, nDeletedFieldSize;
+ SAOffset nRecordOffset;
+ char* pszRecord;
+ int i, iRecord;
+
+ if (iField < 0 || iField >= psDBF->nFields)
+ return FALSE;
+
+ /* make sure that everything is written in .dbf */
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
+
+ /* get information about field to be deleted */
+ nOldRecordLength = psDBF->nRecordLength;
+ nOldHeaderLength = psDBF->nHeaderLength;
+ nDeletedFieldOffset = psDBF->panFieldOffset[iField];
+ nDeletedFieldSize = psDBF->panFieldSize[iField];
+
+ /* update fields info */
+ for (i = iField + 1; i < psDBF->nFields; i++)
+ {
+ psDBF->panFieldOffset[i-1] = psDBF->panFieldOffset[i] - nDeletedFieldSize;
+ psDBF->panFieldSize[i-1] = psDBF->panFieldSize[i];
+ psDBF->panFieldDecimals[i-1] = psDBF->panFieldDecimals[i];
+ psDBF->pachFieldType[i-1] = psDBF->pachFieldType[i];
+ }
+
+ /* resize fields arrays */
+ psDBF->nFields--;
+
+ psDBF->panFieldOffset = (int *)
+ SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldSize = (int *)
+ SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldDecimals = (int *)
+ SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+
+ psDBF->pachFieldType = (char *)
+ SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+
+ /* update header information */
+ psDBF->nHeaderLength -= 32;
+ psDBF->nRecordLength -= nDeletedFieldSize;
+
+ /* overwrite field information in header */
+ memmove(psDBF->pszHeader + iField*32,
+ psDBF->pszHeader + (iField+1)*32,
+ sizeof(char) * (psDBF->nFields - iField)*32);
+
+ psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+
+ /* update size of current record appropriately */
+ psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength);
+
+ /* we're done if we're dealing with not yet created .dbf */
+ if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+ return TRUE;
+
+ /* force update of header with new header and record length */
+ psDBF->bNoHeader = TRUE;
+ DBFUpdateHeader( psDBF );
+
+ /* alloc record */
+ pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+
+ /* shift records to their new positions */
+ for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ {
+ nRecordOffset =
+ nOldRecordLength * (SAOffset) iRecord + nOldHeaderLength;
+
+ /* load record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* move record in two steps */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->fp );
+ psDBF->sHooks.FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
+ nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
+ 1, psDBF->fp );
+
+ }
+
+ /* TODO: truncate file */
+
+ /* free record */
+ free(pszRecord);
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* DBFReorderFields() */
+/* */
+/* Reorder the fields of a .dbf file */
+/* */
+/* panMap must be exactly psDBF->nFields long and be a permutation */
+/* of [0, psDBF->nFields-1]. This assumption will not be asserted in the*/
+/* code of DBFReorderFields. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReorderFields( DBFHandle psDBF, int* panMap )
+{
+ SAOffset nRecordOffset;
+ int i, iRecord;
+ int *panFieldOffsetNew;
+ int *panFieldSizeNew;
+ int *panFieldDecimalsNew;
+ char *pachFieldTypeNew;
+ char *pszHeaderNew;
+ char *pszRecord;
+ char *pszRecordNew;
+
+ if ( psDBF->nFields == 0 )
+ return TRUE;
+
+ /* make sure that everything is written in .dbf */
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
+
+ panFieldOffsetNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+ panFieldSizeNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+ panFieldDecimalsNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+ pachFieldTypeNew = (char *) malloc(sizeof(char) * psDBF->nFields);
+ pszHeaderNew = (char*) malloc(sizeof(char) * 32 * psDBF->nFields);
+
+ /* shuffle fields definitions */
+ for(i=0; i < psDBF->nFields; i++)
+ {
+ panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
+ panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
+ pachFieldTypeNew[i] = psDBF->pachFieldType[panMap[i]];
+ memcpy(pszHeaderNew + i * 32,
+ psDBF->pszHeader + panMap[i] * 32, 32);
+ }
+ panFieldOffsetNew[0] = 1;
+ for(i=1; i < psDBF->nFields; i++)
+ {
+ panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
+ }
+
+ free(psDBF->pszHeader);
+ psDBF->pszHeader = pszHeaderNew;
+
+ /* we're done if we're dealing with not yet created .dbf */
+ if ( !(psDBF->bNoHeader && psDBF->nRecords == 0) )
+ {
+ /* force update of header with new header and record length */
+ psDBF->bNoHeader = TRUE;
+ DBFUpdateHeader( psDBF );
+
+ /* alloc record */
+ pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+ pszRecordNew = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+
+ /* shuffle fields in records */
+ for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ {
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* load record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FRead( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ pszRecordNew[0] = pszRecord[0];
+
+ for(i=0; i < psDBF->nFields; i++)
+ {
+ memcpy(pszRecordNew + panFieldOffsetNew[i],
+ pszRecord + psDBF->panFieldOffset[panMap[i]],
+ psDBF->panFieldSize[panMap[i]]);
+ }
+
+ /* write record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FWrite( pszRecordNew, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+
+ /* free record */
+ free(pszRecord);
+ free(pszRecordNew);
+ }
+
+ free(psDBF->panFieldOffset);
+ free(psDBF->panFieldSize);
+ free(psDBF->panFieldDecimals);
+ free(psDBF->pachFieldType);
+
+ psDBF->panFieldOffset = panFieldOffsetNew;
+ psDBF->panFieldSize = panFieldSizeNew;
+ psDBF->panFieldDecimals =panFieldDecimalsNew;
+ psDBF->pachFieldType = pachFieldTypeNew;
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+
+ return TRUE;
+}
+
+
+/************************************************************************/
+/* DBFAlterFieldDefn() */
+/* */
+/* Alter a field definition in a .dbf file */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+ char chType, int nWidth, int nDecimals )
+{
+ int i;
+ int iRecord;
+ int nOffset;
+ int nOldWidth;
+ int nOldRecordLength;
+ int nRecordOffset;
+ char* pszFInfo;
+ char chOldType;
+ int bIsNULL;
+ char chFieldFill;
+
+ if (iField < 0 || iField >= psDBF->nFields)
+ return FALSE;
+
+ /* make sure that everything is written in .dbf */
+ if( !DBFFlushRecord( psDBF ) )
+ return FALSE;
+
+ chFieldFill = DBFGetNullCharacter(chType);
+
+ chOldType = psDBF->pachFieldType[iField];
+ nOffset = psDBF->panFieldOffset[iField];
+ nOldWidth = psDBF->panFieldSize[iField];
+ nOldRecordLength = psDBF->nRecordLength;
+
+/* -------------------------------------------------------------------- */
+/* Do some checking to ensure we can add records to this file. */
+/* -------------------------------------------------------------------- */
+ if( nWidth < 1 )
+ return -1;
+
+ if( nWidth > 255 )
+ nWidth = 255;
+
+/* -------------------------------------------------------------------- */
+/* Assign the new field information fields. */
+/* -------------------------------------------------------------------- */
+ psDBF->panFieldSize[iField] = nWidth;
+ psDBF->panFieldDecimals[iField] = nDecimals;
+ psDBF->pachFieldType[iField] = chType;
+
+/* -------------------------------------------------------------------- */
+/* Update the header information. */
+/* -------------------------------------------------------------------- */
+ pszFInfo = psDBF->pszHeader + 32 * iField;
+
+ for( i = 0; i < 32; i++ )
+ pszFInfo[i] = '\0';
+
+ if( (int) strlen(pszFieldName) < 10 )
+ strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
+ else
+ strncpy( pszFInfo, pszFieldName, 10);
+
+ pszFInfo[11] = psDBF->pachFieldType[iField];
+
+ if( chType == 'C' )
+ {
+ pszFInfo[16] = (unsigned char) (nWidth % 256);
+ pszFInfo[17] = (unsigned char) (nWidth / 256);
+ }
+ else
+ {
+ pszFInfo[16] = (unsigned char) nWidth;
+ pszFInfo[17] = (unsigned char) nDecimals;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Update offsets */
+/* -------------------------------------------------------------------- */
+ if (nWidth != nOldWidth)
+ {
+ for (i = iField + 1; i < psDBF->nFields; i++)
+ psDBF->panFieldOffset[i] += nWidth - nOldWidth;
+ psDBF->nRecordLength += nWidth - nOldWidth;
+
+ psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength);
+ }
+
+ /* we're done if we're dealing with not yet created .dbf */
+ if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+ return TRUE;
+
+ /* force update of header with new header and record length */
+ psDBF->bNoHeader = TRUE;
+ DBFUpdateHeader( psDBF );
+
+ if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
+ {
+ char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+ char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+ pszOldField[nOldWidth] = 0;
+
+ /* move records to their new positions */
+ for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ {
+ nRecordOffset =
+ nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* load record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+ memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+ bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+ if (nWidth != nOldWidth)
+ {
+ if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
+ {
+ /* Strip leading spaces when truncating a numeric field */
+ memmove( pszRecord + nOffset,
+ pszRecord + nOffset + nOldWidth - nWidth,
+ nWidth );
+ }
+ if (nOffset + nOldWidth < nOldRecordLength)
+ {
+ memmove( pszRecord + nOffset + nWidth,
+ pszRecord + nOffset + nOldWidth,
+ nOldRecordLength - (nOffset + nOldWidth));
+ }
+ }
+
+ /* Convert null value to the appropriate value of the new type */
+ if (bIsNULL)
+ {
+ memset( pszRecord + nOffset, chFieldFill, nWidth);
+ }
+
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* write record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+
+ free(pszRecord);
+ free(pszOldField);
+ }
+ else if (nWidth > nOldWidth)
+ {
+ char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+ char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+ pszOldField[nOldWidth] = 0;
+
+ /* move records to their new positions */
+ for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
+ {
+ nRecordOffset =
+ nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* load record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+ memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+ bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+ if (nOffset + nOldWidth < nOldRecordLength)
+ {
+ memmove( pszRecord + nOffset + nWidth,
+ pszRecord + nOffset + nOldWidth,
+ nOldRecordLength - (nOffset + nOldWidth));
+ }
+
+ /* Convert null value to the appropriate value of the new type */
+ if (bIsNULL)
+ {
+ memset( pszRecord + nOffset, chFieldFill, nWidth);
+ }
+ else
+ {
+ if ((chOldType == 'N' || chOldType == 'F'))
+ {
+ /* Add leading spaces when expanding a numeric field */
+ memmove( pszRecord + nOffset + nWidth - nOldWidth,
+ pszRecord + nOffset, nOldWidth );
+ memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
+ }
+ else
+ {
+ /* Add trailing spaces */
+ memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
+ }
+ }
+
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+ /* write record */
+ psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+ psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+
+ free(pszRecord);
+ free(pszOldField);
+ }
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+
+ return TRUE;
+}
diff --git a/libtool b/libtool
deleted file mode 100755
index 7706a8c..0000000
--- a/libtool
+++ /dev/null
@@ -1,4149 +0,0 @@
-#! /bin/sh
-
-# libtool - Provide generalized library-building support services.
-# Generated automatically by ltconfig (GNU libtool 1.3 (1.385.2.117 1999/04/29 13:07:13))
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
-#
-# 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-# Libtool was configured as follows, on host cs46980-c:
-#
-# CC="gcc" CFLAGS="-g -O2" CPPFLAGS="" \
-# LD="/usr/bin/ld" LDFLAGS="" LIBS="" \
-# NM="/usr/bin/nm -B" RANLIB="ranlib" LN_S="ln -s" \
-# DLLTOOL="" OBJDUMP="" AS="" \
-# ./ltconfig --cache-file=./config.cache --with-gcc --with-gnu-ld --no-verify ./ltmain.sh i586-pc-linux-gnu
-#
-# Compiler and other test output produced by ltconfig, useful for
-# debugging ltconfig, is in ./config.log if it exists.
-
-# The version of ltconfig that generated this script.
-LTCONFIG_VERSION="1.3"
-
-# Shell to use when invoking shell scripts.
-SHELL="/bin/sh"
-
-# Whether or not to build shared libraries.
-build_libtool_libs=yes
-
-# Whether or not to build static libraries.
-build_old_libs=yes
-
-# Whether or not to optimize for fast installation.
-fast_install=yes
-
-# The host system.
-host_alias=i586-pc-linux-gnu
-host=i586-pc-linux-gnu
-
-# An echo program that does not interpret backslashes.
-echo="echo"
-
-# The archiver.
-AR="ar"
-
-# The default C compiler.
-CC="gcc"
-
-# The linker used to build libraries.
-LD="/usr/bin/ld"
-
-# Whether we need hard or soft links.
-LN_S="ln -s"
-
-# A BSD-compatible nm program.
-NM="/usr/bin/nm -B"
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="dlltool"
-
-# Used on cygwin: object dumper.
-OBJDUMP="objdump"
-
-# Used on cygwin: assembler.
-AS="as"
-
-# The name of the directory that contains temporary libtool files.
-objdir=.libs
-
-# How to create reloadable object files.
-reload_flag=" -r"
-reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
-
-# How to pass a linker flag through the compiler.
-wl="-Wl,"
-
-# Object file suffix (normally "o").
-objext="o"
-
-# Old archive suffix (normally "a").
-libext="a"
-
-# Additional compiler flags for building library objects.
-pic_flag=" -fPIC"
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o="yes"
-
-# Can we write directly to a .lo ?
-compiler_o_lo="yes"
-
-# Must we lock files when doing compilation ?
-need_locks="no"
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=no
-
-# Do we need a version for libraries?
-need_version=no
-
-# Whether dlopen is supported.
-dlopen=unknown
-
-# Whether dlopen of programs is supported.
-dlopen_self=unknown
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=unknown
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=" -fno-builtin -fno-rtti -fno-exceptions"
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec="\${wl}--export-dynamic"
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=""
-
-# Library versioning type.
-version_type=linux
-
-# Format of library name prefix.
-libname_spec="lib\$name"
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec="\${libname}\${release}.so\$versuffix \${libname}\${release}.so\$major \$libname.so"
-
-# The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}.so\$major"
-
-# Commands used to build and install an old-style archive.
-RANLIB="ranlib"
-old_archive_cmds="\$AR cru \$oldlib\$oldobjs~\$RANLIB \$oldlib"
-old_postinstall_cmds="\$RANLIB \$oldlib~chmod 644 \$oldlib"
-old_postuninstall_cmds=""
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=""
-
-# Commands used to build and install a shared archive.
-archive_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname -o \$lib"
-archive_expsym_cmds="\$CC -shared \$libobjs \$deplibs \$linkopts \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib"
-postinstall_cmds=""
-postuninstall_cmds=""
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )"
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd="/usr/bin/file"
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=""
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=""
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=""
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGISTW]\\)[ ][ ]*\\(\\)\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2\\3 \\3/p'"
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern char \\1;/p'"
-
-# This is the shared library runtime path variable.
-runpath_var=LD_RUN_PATH
-
-# This is the shared library path variable.
-shlibpath_var=LD_LIBRARY_PATH
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=no
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=immediate
-
-# Flag to hardcode $libdir into a binary during linking.
-# This must work even if $libdir does not exist.
-hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=""
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=no
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=no
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=unsupported
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-
-# Fix the shell variable $srcfile for the compiler.
-fix_srcfile_path=""
-
-# Set to yes if exported symbols are required.
-always_export_symbols=no
-
-# The commands to list exported symbols.
-export_symbols_cmds="\$NM \$libobjs | \$global_symbol_pipe | sed 's/.* //' | sort | uniq > \$export_symbols"
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-
-# Symbols that must always be exported.
-include_expsyms=""
-
-### END LIBTOOL CONFIG
-
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun ltconfig.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
-#
-# 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell, and then maybe $echo will work.
- exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit 0
-fi
-
-# The name of this program.
-progname=`$echo "$0" | sed 's%^.*/%%'`
-modename="$progname"
-
-# Constants.
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=1.3
-TIMESTAMP=" (1.385.2.117 1999/04/29 13:07:13)"
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-SP2NL='tr \040 \012'
-NL2SP='tr \012 \040'
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
- save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
- save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-if test "$LTCONFIG_VERSION" != "$VERSION"; then
- echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
-fi
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
- echo "$modename: not configured to build any kind of library" 1>&2
- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-# Parse our command line options once, thoroughly.
-while test $# -gt 0
-do
- arg="$1"
- shift
-
- case "$arg" in
- -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case "$prev" in
- execute_dlfiles)
- eval "$prev=\"\$$prev \$arg\""
- ;;
- *)
- eval "$prev=\$arg"
- ;;
- esac
-
- prev=
- prevopt=
- continue
- fi
-
- # Have we seen a non-optional argument yet?
- case "$arg" in
- --help)
- show_help=yes
- ;;
-
- --version)
- echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
- exit 0
- ;;
-
- --config)
- sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
- exit 0
- ;;
-
- --debug)
- echo "$progname: enabling shell trace mode"
- set -x
- ;;
-
- --dry-run | -n)
- run=:
- ;;
-
- --features)
- echo "host: $host"
- if test "$build_libtool_libs" = yes; then
- echo "enable shared libraries"
- else
- echo "disable shared libraries"
- fi
- if test "$build_old_libs" = yes; then
- echo "enable static libraries"
- else
- echo "disable static libraries"
- fi
- exit 0
- ;;
-
- --finish) mode="finish" ;;
-
- --mode) prevopt="--mode" prev=mode ;;
- --mode=*) mode="$optarg" ;;
-
- --quiet | --silent)
- show=:
- ;;
-
- -dlopen)
- prevopt="-dlopen"
- prev=execute_dlfiles
- ;;
-
- -*)
- $echo "$modename: unrecognized option \`$arg'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
-
- *)
- nonopt="$arg"
- break
- ;;
- esac
-done
-
-if test -n "$prevopt"; then
- $echo "$modename: option \`$prevopt' requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
-fi
-
-if test -z "$show_help"; then
-
- # Infer the operation mode.
- if test -z "$mode"; then
- case "$nonopt" in
- *cc | *++ | gcc* | *-gcc*)
- mode=link
- for arg
- do
- case "$arg" in
- -c)
- mode=compile
- break
- ;;
- esac
- done
- ;;
- *db | *dbx | *strace | *truss)
- mode=execute
- ;;
- *install*|cp|mv)
- mode=install
- ;;
- *rm)
- mode=uninstall
- ;;
- *)
- # If we have no mode, but dlfiles were specified, then do execute mode.
- test -n "$execute_dlfiles" && mode=execute
-
- # Just use the default operation mode.
- if test -z "$mode"; then
- if test -n "$nonopt"; then
- $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
- else
- $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
- fi
- fi
- ;;
- esac
- fi
-
- # Only execute mode is allowed to have -dlopen flags.
- if test -n "$execute_dlfiles" && test "$mode" != execute; then
- $echo "$modename: unrecognized option \`-dlopen'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Change the help message to a mode-specific one.
- generic_help="$help"
- help="Try \`$modename --help --mode=$mode' for more information."
-
- # These modes are in order of execution frequency so that they run quickly.
- case "$mode" in
- # libtool compile mode
- compile)
- modename="$modename: compile"
- # Get the compilation command and the source file.
- base_compile=
- lastarg=
- srcfile="$nonopt"
- suppress_output=
-
- user_target=no
- for arg
- do
- # Accept any command-line options.
- case "$arg" in
- -o)
- if test "$user_target" != "no"; then
- $echo "$modename: you cannot specify \`-o' more than once" 1>&2
- exit 1
- fi
- user_target=next
- ;;
-
- -static)
- build_old_libs=yes
- continue
- ;;
- esac
-
- case "$user_target" in
- next)
- # The next one is the -o target name
- user_target=yes
- continue
- ;;
- yes)
- # We got the output file
- user_target=set
- libobj="$arg"
- continue
- ;;
- esac
-
- # Accept the current argument as the source file.
- lastarg="$srcfile"
- srcfile="$arg"
-
- # Aesthetically quote the previous argument.
-
- # Backslashify any backslashes, double quotes, and dollar signs.
- # These are the only characters that are still specially
- # interpreted inside of double-quoted scrings.
- lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly in scan
- # sets, so we specify it separately.
- case "$lastarg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- lastarg="\"$lastarg\""
- ;;
- esac
-
- # Add the previous argument to base_compile.
- if test -z "$base_compile"; then
- base_compile="$lastarg"
- else
- base_compile="$base_compile $lastarg"
- fi
- done
-
- case "$user_target" in
- set)
- ;;
- no)
- # Get the name of the library object.
- libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
- ;;
- *)
- $echo "$modename: you must specify a target with \`-o'" 1>&2
- exit 1
- ;;
- esac
-
- # Recognize several different file suffixes.
- # If the user specifies -o file.o, it is replaced with file.lo
- xform='[cCFSfmso]'
- case "$libobj" in
- *.ada) xform=ada ;;
- *.adb) xform=adb ;;
- *.ads) xform=ads ;;
- *.asm) xform=asm ;;
- *.c++) xform=c++ ;;
- *.cc) xform=cc ;;
- *.cpp) xform=cpp ;;
- *.cxx) xform=cxx ;;
- *.f90) xform=f90 ;;
- *.for) xform=for ;;
- esac
-
- libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
- case "$libobj" in
- *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
- *)
- $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
- exit 1
- ;;
- esac
-
- if test -z "$base_compile"; then
- $echo "$modename: you must specify a compilation command" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Delete any leftover library objects.
- if test "$build_old_libs" = yes; then
- removelist="$obj $libobj"
- else
- removelist="$libobj"
- fi
-
- $run $rm $removelist
- trap "$run $rm $removelist; exit 1" 1 2 15
-
- # Calculate the filename of the output object if compiler does
- # not support -o with -c
- if test "$compiler_c_o" = no; then
- output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
- lockfile="$output_obj.lock"
- removelist="$removelist $output_obj $lockfile"
- trap "$run $rm $removelist; exit 1" 1 2 15
- else
- need_locks=no
- lockfile=
- fi
-
- # Lock this critical section if it is needed
- # We use this script file to make the link, it avoids creating a new file
- if test "$need_locks" = yes; then
- until ln "$0" "$lockfile" 2>/dev/null; do
- $show "Waiting for $lockfile to be removed"
- sleep 2
- done
- elif test "$need_locks" = warn; then
- if test -f "$lockfile"; then
- echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
- echo $srcfile > "$lockfile"
- fi
-
- if test -n "$fix_srcfile_path"; then
- eval srcfile=\"$fix_srcfile_path\"
- fi
-
- # Only build a PIC object if we are building libtool libraries.
- if test "$build_libtool_libs" = yes; then
- # Without this assignment, base_compile gets emptied.
- fbsd_hideous_sh_bug=$base_compile
-
- # All platforms use -DPIC, to notify preprocessed assembler code.
- command="$base_compile $pic_flag -DPIC $srcfile"
- if test "$build_old_libs" = yes; then
- lo_libobj="$libobj"
- dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$libobj"; then
- dir="$objdir"
- else
- dir="$dir/$objdir"
- fi
- libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-
- if test -d "$dir"; then
- $show "$rm $libobj"
- $run $rm $libobj
- else
- $show "$mkdir $dir"
- $run $mkdir $dir
- status=$?
- if test $status -ne 0 && test ! -d $dir; then
- exit $status
- fi
- fi
- fi
- if test "$compiler_o_lo" = yes; then
- output_obj="$libobj"
- command="$command -o $output_obj"
- elif test "$compiler_c_o" = yes; then
- output_obj="$obj"
- command="$command -o $output_obj"
- fi
-
- $show "$command"
- if $run eval "$command"; then :
- else
- test -n "$output_obj" && $run $rm $removelist
- exit 1
- fi
-
- if test "$need_locks" = warn &&
- test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
- echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
-
- # Just move the object if needed, then go on to compile the next one
- if test x"$output_obj" != x"$libobj"; then
- $show "$mv $output_obj $libobj"
- if $run $mv $output_obj $libobj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # If we have no pic_flag, then copy the object into place and finish.
- if test -z "$pic_flag" && test "$build_old_libs" = yes; then
- # Rename the .lo from within objdir to obj
- if test -f $obj; then
- $show $rm $obj
- $run $rm $obj
- fi
-
- $show "$mv $libobj $obj"
- if $run $mv $libobj $obj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
-
- # Now arrange that obj and lo_libobj become the same file
- $show "$LN_S $obj $lo_libobj"
- if $run $LN_S $obj $lo_libobj; then
- exit 0
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Allow error messages only from the first compilation.
- suppress_output=' >/dev/null 2>&1'
- fi
-
- # Only build a position-dependent object if we build old libraries.
- if test "$build_old_libs" = yes; then
- command="$base_compile $srcfile"
- if test "$compiler_c_o" = yes; then
- command="$command -o $obj"
- output_obj="$obj"
- fi
-
- # Suppress compiler output if we already did a PIC compilation.
- command="$command$suppress_output"
- $show "$command"
- if $run eval "$command"; then :
- else
- $run $rm $removelist
- exit 1
- fi
-
- if test "$need_locks" = warn &&
- test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
- echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit 1
- fi
-
- # Just move the object if needed
- if test x"$output_obj" != x"$obj"; then
- $show "$mv $output_obj $obj"
- if $run $mv $output_obj $obj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Create an invalid libtool object if no PIC, so that we do not
- # accidentally link it into a program.
- if test "$build_libtool_libs" != yes; then
- $show "echo timestamp > $libobj"
- $run eval "echo timestamp > \$libobj" || exit $?
- else
- # Move the .lo from within objdir
- $show "$mv $libobj $lo_libobj"
- if $run $mv $libobj $lo_libobj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
- fi
-
- # Unlock the critical section if it was locked
- if test "$need_locks" != no; then
- $rm "$lockfile"
- fi
-
- exit 0
- ;;
-
- # libtool link mode
- link)
- modename="$modename: link"
- C_compiler="$CC" # save it, to compile generated C sources
- CC="$nonopt"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
- # It is impossible to link a dll without this setting, and
- # we shouldn't force the makefile maintainer to figure out
- # which system we are compiling for in order to pass an extra
- # flag for every libtool invokation.
- # allow_undefined=no
-
- # FIXME: Unfortunately, there are problems with the above when trying
- # to make a dll which has undefined symbols, in which case not
- # even a static library is built. For now, we need to specify
- # -no-undefined on the libtool link line when we can be certain
- # that all symbols are satisfied, otherwise we get a static library.
- allow_undefined=yes
-
- # This is a source program that is used to create dlls on Windows
- # Don't remove nor modify the starting and closing comments
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-# __hDllInstance_base = hInst;
-# return TRUE;
-# }
-# /* ltdll.c ends here */
- # This is a source program that is used to create import libraries
- # on Windows for dlls which lack them. Don't remove nor modify the
- # starting and closing comments
-# /* impgen.c starts here */
-# /* Copyright (C) 1999 Free Software Foundation, Inc.
-#
-# This file is part of GNU libtool.
-#
-# 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# */
-#
-# #include <stdio.h> /* for printf() */
-# #include <unistd.h> /* for open(), lseek(), read() */
-# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
-# #include <string.h> /* for strdup() */
-#
-# static unsigned int
-# pe_get16 (fd, offset)
-# int fd;
-# int offset;
-# {
-# unsigned char b[2];
-# lseek (fd, offset, SEEK_SET);
-# read (fd, b, 2);
-# return b[0] + (b[1]<<8);
-# }
-#
-# static unsigned int
-# pe_get32 (fd, offset)
-# int fd;
-# int offset;
-# {
-# unsigned char b[4];
-# lseek (fd, offset, SEEK_SET);
-# read (fd, b, 4);
-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# static unsigned int
-# pe_as32 (ptr)
-# void *ptr;
-# {
-# unsigned char *b = ptr;
-# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-# }
-#
-# int
-# main (argc, argv)
-# int argc;
-# char *argv[];
-# {
-# int dll;
-# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
-# unsigned long export_rva, export_size, nsections, secptr, expptr;
-# unsigned long name_rvas, nexp;
-# unsigned char *expdata, *erva;
-# char *filename, *dll_name;
-#
-# filename = argv[1];
-#
-# dll = open(filename, O_RDONLY|O_BINARY);
-# if (!dll)
-# return 1;
-#
-# dll_name = filename;
-#
-# for (i=0; filename[i]; i++)
-# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
-# dll_name = filename + i +1;
-#
-# pe_header_offset = pe_get32 (dll, 0x3c);
-# opthdr_ofs = pe_header_offset + 4 + 20;
-# num_entries = pe_get32 (dll, opthdr_ofs + 92);
-#
-# if (num_entries < 1) /* no exports */
-# return 1;
-#
-# export_rva = pe_get32 (dll, opthdr_ofs + 96);
-# export_size = pe_get32 (dll, opthdr_ofs + 100);
-# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
-# secptr = (pe_header_offset + 4 + 20 +
-# pe_get16 (dll, pe_header_offset + 4 + 16));
-#
-# expptr = 0;
-# for (i = 0; i < nsections; i++)
-# {
-# char sname[8];
-# unsigned long secptr1 = secptr + 40 * i;
-# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
-# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
-# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
-# lseek(dll, secptr1, SEEK_SET);
-# read(dll, sname, 8);
-# if (vaddr <= export_rva && vaddr+vsize > export_rva)
-# {
-# expptr = fptr + (export_rva - vaddr);
-# if (export_rva + export_size > vaddr + vsize)
-# export_size = vsize - (export_rva - vaddr);
-# break;
-# }
-# }
-#
-# expdata = (unsigned char*)malloc(export_size);
-# lseek (dll, expptr, SEEK_SET);
-# read (dll, expdata, export_size);
-# erva = expdata - export_rva;
-#
-# nexp = pe_as32 (expdata+24);
-# name_rvas = pe_as32 (expdata+32);
-#
-# printf ("EXPORTS\n");
-# for (i = 0; i<nexp; i++)
-# {
-# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
-# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
-# }
-#
-# return 0;
-# }
-# /* impgen.c ends here */
- ;;
- *)
- allow_undefined=yes
- ;;
- esac
- compile_command="$CC"
- finalize_command="$CC"
-
- compile_rpath=
- finalize_rpath=
- compile_shlibpath=
- finalize_shlibpath=
- convenience=
- old_convenience=
- deplibs=
- linkopts=
-
- if test -n "$shlibpath_var"; then
- # get the directories listed in $shlibpath_var
- eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
- else
- lib_search_path=
- fi
- # now prepend the system-specific ones
- eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
- eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
- avoid_version=no
- dlfiles=
- dlprefiles=
- dlself=no
- export_dynamic=no
- export_symbols=
- export_symbols_regex=
- generated=
- libobjs=
- link_against_libtool_libs=
- ltlibs=
- module=no
- objs=
- prefer_static_libs=no
- preload=no
- prev=
- prevarg=
- release=
- rpath=
- xrpath=
- perm_rpath=
- temp_rpath=
- thread_safe=no
- vinfo=
-
- # We need to know -static, to get the right output filenames.
- for arg
- do
- case "$arg" in
- -all-static | -static)
- if test "X$arg" = "X-all-static"; then
- if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
- $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
- fi
- if test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- else
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- fi
- build_libtool_libs=no
- build_old_libs=yes
- prefer_static_libs=yes
- break
- ;;
- esac
- done
-
- # See if our shared archives depend on static archives.
- test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
- # Go through the arguments, transforming them on the way.
- while test $# -gt 0; do
- arg="$1"
- shift
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case "$prev" in
- output)
- compile_command="$compile_command @OUTPUT@"
- finalize_command="$finalize_command @OUTPUT@"
- ;;
- esac
-
- case "$prev" in
- dlfiles|dlprefiles)
- if test "$preload" = no; then
- # Add the symbol object into the linking commands.
- compile_command="$compile_command @SYMFILE@"
- finalize_command="$finalize_command @SYMFILE@"
- preload=yes
- fi
- case "$arg" in
- *.la | *.lo) ;; # We handle these cases below.
- self)
- if test "$prev" = dlprefiles; then
- dlself=yes
- elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
- dlself=yes
- else
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- *)
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- else
- dlprefiles="$dlprefiles $arg"
- fi
- prev=
- ;;
- esac
- ;;
- expsyms)
- export_symbols="$arg"
- if test ! -f "$arg"; then
- $echo "$modename: symbol file \`$arg' does not exist"
- exit 1
- fi
- prev=
- continue
- ;;
- expsyms_regex)
- export_symbols_regex="$arg"
- prev=
- continue
- ;;
- release)
- release="-$arg"
- prev=
- continue
- ;;
- rpath | xrpath)
- # We need an absolute path.
- case "$arg" in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit 1
- ;;
- esac
- if test "$prev" = rpath; then
- case "$rpath " in
- *" $arg "*) ;;
- *) rpath="$rpath $arg" ;;
- esac
- else
- case "$xrpath " in
- *" $arg "*) ;;
- *) xrpath="$xrpath $arg" ;;
- esac
- fi
- prev=
- continue
- ;;
- *)
- eval "$prev=\"\$arg\""
- prev=
- continue
- ;;
- esac
- fi
-
- prevarg="$arg"
-
- case "$arg" in
- -all-static)
- if test -n "$link_static_flag"; then
- compile_command="$compile_command $link_static_flag"
- finalize_command="$finalize_command $link_static_flag"
- fi
- continue
- ;;
-
- -allow-undefined)
- # FIXME: remove this flag sometime in the future.
- $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
- continue
- ;;
-
- -avoid-version)
- avoid_version=yes
- continue
- ;;
-
- -dlopen)
- prev=dlfiles
- continue
- ;;
-
- -dlpreopen)
- prev=dlprefiles
- continue
- ;;
-
- -export-dynamic)
- export_dynamic=yes
- continue
- ;;
-
- -export-symbols | -export-symbols-regex)
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: not more than one -exported-symbols argument allowed"
- exit 1
- fi
- if test "X$arg" = "X-export-symbols"; then
- prev=expsyms
- else
- prev=expsyms_regex
- fi
- continue
- ;;
-
- -L*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
- # We need an absolute path.
- case "$dir" in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
- exit 1
- fi
- dir="$absdir"
- ;;
- esac
- case " $deplibs " in
- *" $arg "*) ;;
- *) deplibs="$deplibs $arg";;
- esac
- case " $lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir";;
- esac
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
- dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
- case ":$dllsearchpath:" in
- ::) dllsearchpath="$dllsearchdir";;
- *":$dllsearchdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
- esac
- ;;
- esac
- ;;
-
- -l*)
- if test "$arg" = "-lc"; then
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
- # These systems don't actually have c library (as such)
- continue
- ;;
- esac
- elif test "$arg" = "-lm"; then
- case "$host" in
- *-*-cygwin* | *-*-beos*)
- # These systems don't actually have math library (as such)
- continue
- ;;
- esac
- fi
- deplibs="$deplibs $arg"
- ;;
-
- -module)
- module=yes
- continue
- ;;
-
- -no-undefined)
- allow_undefined=no
- continue
- ;;
-
- -o) prev=output ;;
-
- -release)
- prev=release
- continue
- ;;
-
- -rpath)
- prev=rpath
- continue
- ;;
-
- -R)
- prev=xrpath
- continue
- ;;
-
- -R*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
- # We need an absolute path.
- case "$dir" in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit 1
- ;;
- esac
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- continue
- ;;
-
- -static)
- # If we have no pic_flag, then this is the same as -all-static.
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- compile_command="$compile_command $link_static_flag"
- finalize_command="$finalize_command $link_static_flag"
- fi
- continue
- ;;
-
- -thread-safe)
- thread_safe=yes
- continue
- ;;
-
- -version-info)
- prev=vinfo
- continue
- ;;
-
- # Some other compiler flag.
- -* | +*)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- ;;
-
- *.o | *.obj | *.a | *.lib)
- # A standard object.
- objs="$objs $arg"
- ;;
-
- *.lo)
- # A library object.
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
- prev=
- fi
- libobjs="$libobjs $arg"
- ;;
-
- *.la)
- # A libtool-controlled library.
-
- dlname=
- libdir=
- library_names=
- old_library=
-
- # Check to see that this really is a libtool archive.
- if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
- exit 1
- fi
-
- # If the library was installed with an old release of libtool,
- # it will not redefine variable installed.
- installed=yes
-
- # Read the .la file
- # If there is no directory component, then add one.
- case "$arg" in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
- esac
-
- # Get the name of the library we link against.
- linklib=
- for l in $old_library $library_names; do
- linklib="$l"
- done
-
- if test -z "$linklib"; then
- $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
- exit 1
- fi
-
- # Find the relevant object directory and library name.
- name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
-
- if test "X$installed" = Xyes; then
- dir="$libdir"
- else
- dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$arg"; then
- dir="$objdir"
- else
- dir="$dir/$objdir"
- fi
- fi
-
- if test -n "$dependency_libs"; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for deplib in $dependency_libs; do
- case "$deplib" in
- -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
- case " $rpath $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- -L*) case "$compile_command $temp_deplibs " in
- *" $deplib "*) ;;
- *) temp_deplibs="$temp_deplibs $deplib";;
- esac;;
- *) temp_deplibs="$temp_deplibs $deplib";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- if test -z "$libdir"; then
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $dir/$old_library"
- old_convenience="$old_convenience $dir/$old_library"
- deplibs="$deplibs$dependency_libs"
- compile_command="$compile_command $dir/$old_library$dependency_libs"
- finalize_command="$finalize_command $dir/$old_library$dependency_libs"
- continue
- fi
-
- # This library was specified with -dlopen.
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking statically,
- # we need to preload.
- prev=dlprefiles
- else
- # We should not create a dependency on this library, but we
- # may need any libraries it requires.
- compile_command="$compile_command$dependency_libs"
- finalize_command="$finalize_command$dependency_libs"
- prev=
- continue
- fi
- fi
-
- # The library was specified with -dlpreopen.
- if test "$prev" = dlprefiles; then
- # Prefer using a static library (so that no silly _DYNAMIC symbols
- # are required to link).
- if test -n "$old_library"; then
- dlprefiles="$dlprefiles $dir/$old_library"
- else
- dlprefiles="$dlprefiles $dir/$linklib"
- fi
- prev=
- fi
-
- if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
- link_against_libtool_libs="$link_against_libtool_libs $arg"
- if test -n "$shlibpath_var"; then
- # Make sure the rpath contains only unique directories.
- case "$temp_rpath " in
- *" $dir "*) ;;
- *) temp_rpath="$temp_rpath $dir" ;;
- esac
- fi
-
- # We need an absolute path.
- case "$dir" in
- [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
- exit 1
- fi
- ;;
- esac
-
- # This is the magic to use -rpath.
- # Skip directories that are in the system default run-time
- # search path, unless they have been requested with -R.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
-
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
-
- lib_linked=yes
- case "$hardcode_action" in
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- compile_command="$compile_command $dir/$linklib"
- deplibs="$deplibs $dir/$linklib"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2*)
- dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
- if test -n "$dllsearchpath"; then
- dllsearchpath="$dllsearchpath:$dllsearchdir"
- else
- dllsearchpath="$dllsearchdir"
- fi
- ;;
- esac
- elif test "$hardcode_minus_L" = no; then
- case "$host" in
- *-*-sunos*)
- compile_shlibpath="$compile_shlibpath$dir:"
- ;;
- esac
- case "$compile_command " in
- *" -L$dir "*) ;;
- *) compile_command="$compile_command -L$dir";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -L$dir -l$name"
- elif test "$hardcode_shlibpath_var" = no; then
- case ":$compile_shlibpath:" in
- *":$dir:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$dir:";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -l$name"
- else
- lib_linked=no
- fi
- ;;
-
- relink)
- if test "$hardcode_direct" = yes; then
- compile_command="$compile_command $absdir/$linklib"
- deplibs="$deplibs $absdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- case "$compile_command " in
- *" -L$absdir "*) ;;
- *) compile_command="$compile_command -L$absdir";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -L$absdir -l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case ":$compile_shlibpath:" in
- *":$absdir:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$absdir:";;
- esac
- compile_command="$compile_command -l$name"
- deplibs="$deplibs -l$name"
- else
- lib_linked=no
- fi
- ;;
-
- *)
- lib_linked=no
- ;;
- esac
-
- if test "$lib_linked" != yes; then
- $echo "$modename: configuration error: unsupported hardcode properties"
- exit 1
- fi
-
- # Finalize command for both is simple: just hardcode it.
- if test "$hardcode_direct" = yes; then
- finalize_command="$finalize_command $libdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- case "$finalize_command " in
- *" -L$libdir "*) ;;
- *) finalize_command="$finalize_command -L$libdir";;
- esac
- finalize_command="$finalize_command -l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case ":$finalize_shlibpath:" in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
- esac
- finalize_command="$finalize_command -l$name"
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- case "$finalize_command " in
- *" -L$dir "*) ;;
- *) finalize_command="$finalize_command -L$libdir";;
- esac
- finalize_command="$finalize_command -l$name"
- fi
- else
- # Transform directly to old archives if we don't build new libraries.
- if test -n "$pic_flag" && test -z "$old_library"; then
- $echo "$modename: cannot find static library for \`$arg'" 1>&2
- exit 1
- fi
-
- # Here we assume that one of hardcode_direct or hardcode_minus_L
- # is not unsupported. This is valid on all known static and
- # shared platforms.
- if test "$hardcode_direct" != unsupported; then
- test -n "$old_library" && linklib="$old_library"
- compile_command="$compile_command $dir/$linklib"
- finalize_command="$finalize_command $dir/$linklib"
- else
- case "$compile_command " in
- *" -L$dir "*) ;;
- *) compile_command="$compile_command -L$dir";;
- esac
- compile_command="$compile_command -l$name"
- case "$finalize_command " in
- *" -L$dir "*) ;;
- *) finalize_command="$finalize_command -L$dir";;
- esac
- finalize_command="$finalize_command -l$name"
- fi
- fi
-
- # Add in any libraries that this one depends upon.
- compile_command="$compile_command$dependency_libs"
- finalize_command="$finalize_command$dependency_libs"
- continue
- ;;
-
- # Some other compiler argument.
- *)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- ;;
- esac
-
- # Now actually substitute the argument into the commands.
- if test -n "$arg"; then
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
- done
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
- eval arg=\"$export_dynamic_flag_spec\"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
-
- oldlibs=
- # calculate the name of the file, without its directory
- outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
- libobjs_save="$libobjs"
-
- case "$output" in
- "")
- $echo "$modename: you must specify an output file" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
-
- *.a | *.lib)
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
- exit 1
- fi
-
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
- fi
-
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
- fi
-
- # Now set the variables for building old libraries.
- build_libtool_libs=no
- oldlibs="$output"
- ;;
-
- *.la)
- # Make sure we only generate libraries of the form `libNAME.la'.
- case "$outputname" in
- lib*)
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
- eval libname=\"$libname_spec\"
- ;;
- *)
- if test "$module" = no; then
- $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- eval libname=\"$libname_spec\"
- else
- libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- fi
- ;;
- esac
-
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
-
- if test -n "$objs"; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
- exit 1
- fi
-
- # How the heck are we supposed to write a wrapper for a shared library?
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
- exit 1
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
- fi
-
- set dummy $rpath
- if test $# -gt 2; then
- $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
- fi
- install_libdir="$2"
-
- oldlibs=
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
- libext=al
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
- dependency_libs="$deplibs"
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
- fi
- else
-
- # Parse the version information argument.
- IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
- set dummy $vinfo 0 0 0
- IFS="$save_ifs"
-
- if test -n "$8"; then
- $echo "$modename: too many parameters to \`-version-info'" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- current="$2"
- revision="$3"
- age="$4"
-
- # Check that each of the things are valid numbers.
- case "$current" in
- 0 | [1-9] | [1-9][0-9]*) ;;
- *)
- $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- case "$revision" in
- 0 | [1-9] | [1-9][0-9]*) ;;
- *)
- $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- case "$age" in
- 0 | [1-9] | [1-9][0-9]*) ;;
- *)
- $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- ;;
- esac
-
- if test $age -gt $current; then
- $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit 1
- fi
-
- # Calculate the version variables.
- major=
- versuffix=
- verstring=
- case "$version_type" in
- none) ;;
-
- irix)
- major=`expr $current - $age + 1`
- versuffix="$major.$revision"
- verstring="sgi$major.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
- while test $loop != 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
- verstring="sgi$major.$iface:$verstring"
- done
- ;;
-
- linux)
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- ;;
-
- osf)
- major=`expr $current - $age`
- versuffix=".$current.$age.$revision"
- verstring="$current.$age.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
- while test $loop != 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring:${iface}.0"
- done
-
- # Make executables depend on our current version.
- verstring="$verstring:${current}.0"
- ;;
-
- sunos)
- major=".$current"
- versuffix=".$current.$revision"
- ;;
-
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current";
- ;;
-
- windows)
- # Like Linux, but with '-' rather than '.', since we only
- # want one extension on Windows 95.
- major=`expr $current - $age`
- versuffix="-$major-$age-$revision"
- ;;
-
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
- echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit 1
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
- verstring="0.0"
- if test "$need_version" = no; then
- versuffix=
- else
- versuffix=".0.0"
- fi
- fi
-
- # Remove version info from name if versioning should be avoided
- if test "$avoid_version" = yes && test "$need_version" = no; then
- major=
- versuffix=
- verstring=""
- fi
-
- # Check to see if the archive will have undefined symbols.
- if test "$allow_undefined" = yes; then
- if test "$allow_undefined_flag" = unsupported; then
- $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
- build_libtool_libs=no
- build_old_libs=yes
- fi
- else
- # Don't allow undefined symbols.
- allow_undefined_flag="$no_undefined_flag"
- fi
-
- dependency_libs="$deplibs"
- case "$host" in
- *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
- # these systems don't actually have a c library (as such)!
- ;;
- *)
- # Add libc to deplibs on all other systems.
- deplibs="$deplibs -lc"
- ;;
- esac
- fi
-
- # Create the output directory, or remove our outputs if we need to.
- if test -d $output_objdir; then
- $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
- $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
- else
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- status=$?
- if test $status -ne 0 && test ! -d $output_objdir; then
- exit $status
- fi
- fi
-
- # Now set the variables for building old libraries.
- if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
- oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
- # Transform .lo files to .o files.
- oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
- fi
-
- if test "$build_libtool_libs" = yes; then
- # Transform deplibs into only deplibs that can be linked in shared.
- name_save=$name
- libname_save=$libname
- release_save=$release
- versuffix_save=$versuffix
- major_save=$major
- # I'm not sure if I'm treating the release correctly. I think
- # release should show up in the -l (ie -lgmp5) so we don't want to
- # add it in twice. Is that correct?
- release=""
- versuffix=""
- major=""
- newdeplibs=
- droppeddeps=no
- case "$deplibs_check_method" in
- pass_all)
- # Don't check for shared/static. Everything works.
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
- # implementing what was already the behaviour.
- newdeplibs=$deplibs
- ;;
- test_compile)
- # This code stresses the "libraries are programs" paradigm to its
- # limits. Maybe even breaks it. We compile a program, linking it
- # against the deplibs as a proxy for the library. Then we can check
- # whether they linked in statically or dynamically with ldd.
- $rm conftest.c
- cat > conftest.c <<EOF
- int main() { return 0; }
-EOF
- $rm conftest
- $C_compiler -o conftest conftest.c $deplibs
- if test $? -eq 0 ; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- echo
- echo "*** Warning: This library needs some functionality provided by $i."
- echo "*** I have the capability to make that library automatically link in when"
- echo "*** you link to this library. But I can only do this if you have a"
- echo "*** shared version of the library, which you do not appear to have."
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- else
- # Error occured in the first compile. Let's try to salvage the situation:
- # Compile a seperate program for each library.
- for i in $deplibs; do
- name="`expr $i : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
- $rm conftest
- $C_compiler -o conftest conftest.c $i
- # Did it work?
- if test $? -eq 0 ; then
- ldd_output=`ldd conftest`
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- echo
- echo "*** Warning: This library needs some functionality provided by $i."
- echo "*** I have the capability to make that library automatically link in when"
- echo "*** you link to this library. But I can only do this if you have a"
- echo "*** shared version of the library, which you do not appear to have."
- fi
- else
- droppeddeps=yes
- echo
- echo "*** Warning! Library $i is needed by this library but I was not able to"
- echo "*** make it link in! You will probably need to install it or some"
- echo "*** library that it depends on before this library will be fully"
- echo "*** functional. Installing it before continuing would be even better."
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- fi
- ;;
- file_magic*)
- set dummy $deplibs_check_method
- file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
- for a_deplib in $deplibs; do
- name="`expr $a_deplib : '-l\(.*\)'`"
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potlib" 2>/dev/null \
- | grep " -> " >/dev/null; then
- continue
- fi
- # The statement above tries to avoid entering an
- # endless loop below, in case of cyclic links.
- # We might still enter an endless loop, since a link
- # loop can be closed while we follow links,
- # but so what?
- potlib="$potent_lib"
- while test -h "$potlib" 2>/dev/null; do
- potliblink=`ls -ld $potlib | sed 's/.* -> //'`
- case "$potliblink" in
- [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
- *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
- esac
- done
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
- | sed 10q \
- | egrep "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- echo
- echo "*** Warning: This library needs some functionality provided by $a_deplib."
- echo "*** I have the capability to make that library automatically link in when"
- echo "*** you link to this library. But I can only do this if you have a"
- echo "*** shared version of the library, which you do not appear to have."
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- none | unknown | *)
- newdeplibs=""
- if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
- -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
- grep . >/dev/null; then
- echo
- if test "X$deplibs_check_method" = "Xnone"; then
- echo "*** Warning: inter-library dependencies are not supported in this platform."
- else
- echo "*** Warning: inter-library dependencies are not known to be supported."
- fi
- echo "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
- esac
- versuffix=$versuffix_save
- major=$major_save
- release=$release_save
- libname=$libname_save
- name=$name_save
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
- echo
- echo "*** Warning: libtool could not satisfy all declared inter-library"
- echo "*** dependencies of module $libname. Therefore, libtool will create"
- echo "*** a static module, that should work as long as the dlopening"
- echo "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
- echo
- echo "*** However, this would only work if libtool was able to extract symbol"
- echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- echo "*** not find such a program. So, this module is probably useless."
- echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- else
- echo "*** The inter-library dependencies that have been dropped here will be"
- echo "*** automatically added whenever a program is linked with this library"
- echo "*** or is declared to -dlopen it."
- fi
- fi
- # Done checking deplibs!
- deplibs=$newdeplibs
- fi
-
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
- dlname=
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
- # Get the real and link names of the library.
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- realname="$2"
- shift; shift
-
- if test -n "$soname_spec"; then
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
-
- lib="$output_objdir/$realname"
- for link
- do
- linknames="$linknames $link"
- done
-
- # Ensure that we have .o objects for linkers which dislike .lo
- # (e.g. aix) incase we are running --disable-static
- for obj in $libobjs; do
- oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"`
- if test ! -f $oldobj; then
- $show "${LN_S} $obj $oldobj"
- $run ${LN_S} $obj $oldobj || exit $?
- fi
- done
-
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
- if test -n "$whole_archive_flag_spec"; then
- if test -n "$convenience"; then
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- fi
- else
- gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "mkdir $gentop"
- $run mkdir "$gentop"
- status=$?
- if test $status -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
- generated="$generated $gentop"
-
- for xlib in $convenience; do
- # Extract the objects.
- case "$xlib" in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "mkdir $xdir"
- $run mkdir "$xdir"
- status=$?
- if test $status -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
- libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
- done
- fi
-
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linkopts="$linkopts $flag"
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- eval cmds=\"$export_symbols_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex"; then
- $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
- $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- $show "$mv \"${export_symbols}T\" \"$export_symbols\""
- $run eval '$mv "${export_symbols}T" "$export_symbols"'
- fi
- fi
- fi
-
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
- fi
-
- # Do each of the archive commands.
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval cmds=\"$archive_expsym_cmds\"
- else
- eval cmds=\"$archive_cmds\"
- fi
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Create links to the real library.
- for linkname in $linknames; do
- if test "$realname" != "$linkname"; then
- $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
- fi
- done
-
- # If -module or -export-dynamic was specified, set the dlname.
- if test "$module" = yes || test "$export_dynamic" = yes; then
- # On all known operating systems, these are identical.
- dlname="$soname"
- fi
- fi
- ;;
-
- *.lo | *.o | *.obj)
- if test -n "$link_against_libtool_libs"; then
- $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
- exit 1
- fi
-
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
- fi
-
- case "$output" in
- *.lo)
- if test -n "$objs"; then
- $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
- exit 1
- fi
- libobj="$output"
- obj=`$echo "X$output" | $Xsed -e "$lo2o"`
- ;;
- *)
- libobj=
- obj="$output"
- ;;
- esac
-
- # Delete the old objects.
- $run $rm $obj $libobj
-
- # Create the old-style object.
- reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
-
- output="$obj"
- eval cmds=\"$reload_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Exit if we aren't doing a library object file.
- test -z "$libobj" && exit 0
-
- if test "$build_libtool_libs" != yes; then
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
- $show "echo timestamp > $libobj"
- $run eval "echo timestamp > $libobj" || exit $?
- exit 0
- fi
-
- if test -n "$pic_flag"; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs"
- output="$libobj"
- eval cmds=\"$reload_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- else
- # Just create a symlink.
- $show $rm $libobj
- $run $rm $libobj
- $show "$LN_S $obj $libobj"
- $run $LN_S $obj $libobj || exit $?
- fi
-
- exit 0
- ;;
-
- # Anything else should be a program.
- *)
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
- fi
-
- if test "$preload" = yes; then
- if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
- test "$dlopen_self_static" = unknown; then
- $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
- fi
- fi
-
- if test -n "$rpath$xrpath"; then
- # If the user specified any rpath flags, then add them.
- for libdir in $rpath $xrpath; do
- # This is the magic to use -rpath.
- case "$compile_rpath " in
- *" $libdir "*) ;;
- *) compile_rpath="$compile_rpath $libdir" ;;
- esac
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- fi
-
- # Now hardcode the library paths
- rpath=
- hardcode_libdirs=
- for libdir in $compile_rpath $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- compile_rpath="$rpath"
-
- rpath=
- hardcode_libdirs=
- for libdir in $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$finalize_perm_rpath " in
- *" $libdir "*) ;;
- *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- finalize_rpath="$rpath"
-
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
-
- # Create the binary in the object directory, then wrap it.
- if test ! -d $output_objdir; then
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- status=$?
- if test $status -ne 0 && test ! -d $output_objdir; then
- exit $status
- fi
- fi
-
- if test -n "$libobjs" && test "$build_old_libs" = yes; then
- # Transform all the library objects into standard objects.
- compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- fi
-
- dlsyms=
- if test -n "$dlfiles$dlprefiles" || test "$dlself" = yes; then
- if test -n "$NM" && test -n "$global_symbol_pipe"; then
- dlsyms="${outputname}S.c"
- else
- $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
- fi
- fi
-
- if test -n "$dlsyms"; then
- case "$dlsyms" in
- "") ;;
- *.c)
- # Discover the nlist of each of the dlfiles.
- nlist="$output_objdir/${outputname}.nm"
-
- $show "$rm $nlist ${nlist}S ${nlist}T"
- $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
- # Parse the name list into a source file.
- $show "creating $output_objdir/$dlsyms"
-
- test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
- if test "$dlself" = yes; then
- $show "generating symbol list for \`$output'"
-
- test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
- # Add our own program objects to the symbol list.
- progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- for arg in $progfiles; do
- $show "extracting global C symbols from \`$arg'"
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -n "$exclude_expsyms"; then
- $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- if test -n "$export_symbols_regex"; then
- $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$output.exp"
- $run $rm $export_symbols
- $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
- else
- $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
- $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
- $run eval 'mv "$nlist"T "$nlist"'
- fi
- fi
-
- for arg in $dlprefiles; do
- $show "extracting global C symbols from \`$arg'"
- name=`echo "$arg" | sed -e 's%^.*/%%'`
- $run eval 'echo ": $name " >> "$nlist"'
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -z "$run"; then
- # Make sure we have at least an empty file.
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
- egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $mv "$nlist"T "$nlist"
- fi
-
- # Try sorting and uniquifying the output.
- if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
- :
- else
- grep -v "^: " < "$nlist" > "$nlist"S
- fi
-
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
- else
- echo '/* NONE */' >> "$output_objdir/$dlsyms"
- fi
-
- $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
- sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
- -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
- < "$nlist" >> "$output_objdir/$dlsyms"
-
- $echo >> "$output_objdir/$dlsyms" "\
- {0, (lt_ptr_t) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
- fi
-
- pic_flag_for_symtable=
- case "$host" in
- # compiling the symbol table file with pic_flag works around
- # a FreeBSD bug that causes programs to crash when -lm is
- # linked before any other PIC object. But we must not use
- # pic_flag when linking with -static. The problem exists in
- # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
- *-*-freebsd2*|*-*-freebsd3.0*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
- esac
- esac
-
- # Now compile the dynamic symbol file.
- $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
- $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
- # Clean up the generated files.
- $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
- $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
- # Transform the symbol file into the correct name.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- ;;
- *)
- $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
- exit 1
- ;;
- esac
- else
- # We keep going just in case the user didn't refer to
- # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
- # really was required.
-
- # Nullify the symbol file.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-
- if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
- # Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-
- # We have no uninstalled library dependencies, so finalize right now.
- $show "$link_command"
- $run eval "$link_command"
- status=$?
-
- # Delete the generated files.
- if test -n "$dlsyms"; then
- $show "$rm $output_objdir/${outputname}S.${objext}"
- $run $rm "$output_objdir/${outputname}S.${objext}"
- fi
-
- exit $status
- fi
-
- if test -n "$shlibpath_var"; then
- # We should set the shlibpath_var
- rpath=
- for dir in $temp_rpath; do
- case "$dir" in
- [\\/]* | [A-Za-z]:[\\/]*)
- # Absolute path.
- rpath="$rpath$dir:"
- ;;
- *)
- # Relative path: add a thisdir entry.
- rpath="$rpath\$thisdir/$dir:"
- ;;
- esac
- done
- temp_rpath="$rpath"
- fi
-
- if test -n "$compile_shlibpath$finalize_shlibpath"; then
- compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
- fi
- if test -n "$finalize_shlibpath"; then
- finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
- fi
-
- compile_var=
- finalize_var=
- if test -n "$runpath_var"; then
- if test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- if test -n "$finalize_perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $finalize_perm_rpath; do
- rpath="$rpath$dir:"
- done
- finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- fi
-
- if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
-
- $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
- $echo "$modename: \`$output' will be relinked during installation" 1>&2
- else
- if test "$fast_install" != no; then
- link_command="$finalize_var$compile_command$finalize_rpath"
- if test "$fast_install" = yes; then
- relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
- else
- # fast_install is set to needless
- relink_command=
- fi
- else
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
- fi
- fi
-
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
- # Delete the old output files.
- $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
- $show "$link_command"
- $run eval "$link_command" || exit $?
-
- # Now create the wrapper script.
- $show "creating $output"
-
- # Quote the relink command for shipping.
- if test -n "$relink_command"; then
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Quote $echo for shipping.
- if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
- case "$0" in
- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
- *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
- esac
- qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
- qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Only actually do things if our run command is non-null.
- if test -z "$run"; then
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
- *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
- esac
- $rm $output
- trap "$rm $output; exit 1" 1 2 15
-
- $echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
- # install mode needs the following variable:
- link_against_libtool_libs='$link_against_libtool_libs'
-else
- # When we are sourced in execute mode, \$file and \$echo are already set.
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- echo=\"$qecho\"
- file=\"\$0\"
- # Make sure echo works.
- if test \"X\$1\" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
- # Yippee, \$echo works!
- :
- else
- # Restart under the correct shell, and then maybe \$echo will work.
- exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
- fi
- fi\
-"
- $echo >> $output "\
-
- # Find the directory that this script lives in.
- thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
- test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
- while test -n \"\$file\"; do
- destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
- # If there was a directory component, then change thisdir.
- if test \"x\$destdir\" != \"x\$file\"; then
- case \"\$destdir\" in
- [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
- *) thisdir=\"\$thisdir/\$destdir\" ;;
- esac
- fi
-
- file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
- file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
- done
-
- # Try to get the absolute directory name.
- absdir=\`cd \"\$thisdir\" && pwd\`
- test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
- if test "$fast_install" = yes; then
- echo >> $output "\
- program=lt-'$outputname'
- progdir=\"\$thisdir/$objdir\"
-
- if test ! -f \"\$progdir/\$program\" || \\
- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
- test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
- file=\"\$\$-\$program\"
-
- if test ! -d \"\$progdir\"; then
- $mkdir \"\$progdir\"
- else
- $rm \"\$progdir/\$file\"
- fi"
-
- echo >> $output "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
- if (cd \"\$thisdir\" && eval \$relink_command); then :
- else
- $rm \"\$progdir/\$file\"
- exit 1
- fi
- fi
-
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
- { $rm \"\$progdir/\$program\";
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
- $rm \"\$progdir/\$file\"
- fi"
- else
- echo >> $output "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
-"
- fi
-
- echo >> $output "\
-
- if test -f \"\$progdir/\$program\"; then"
-
- # Export our shlibpath_var if we have one.
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- $echo >> $output "\
- # Add our own library path to $shlibpath_var
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
- # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-"
- fi
-
- # fixup the dll searchpath if we need to.
- if test -n "$dllsearchpath"; then
- $echo >> $output "\
- # Add the dll search path components to the executable PATH
- PATH=$dllsearchpath:\$PATH
-"
- fi
-
- $echo >> $output "\
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- # Run the actual program with our arguments.
-"
- case $host in
- *-*-cygwin* | *-*-mingw | *-*-os2*)
- # win32 systems need to use the prog path for dll
- # lookup to work
- $echo >> $output "\
- exec \$progdir\\\\\$program \${1+\"\$@\"}
-"
- ;;
- *)
- $echo >> $output "\
- # Export the path to the program.
- PATH=\"\$progdir:\$PATH\"
- export PATH
-
- exec \$program \${1+\"\$@\"}
-"
- ;;
- esac
- $echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
- exit 1
- fi
- else
- # The program doesn't exist.
- \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
- \$echo \"This script is just a wrapper for \$program.\" 1>&2
- echo \"See the $PACKAGE documentation for more information.\" 1>&2
- exit 1
- fi
-fi\
-"
- chmod +x $output
- fi
- exit 0
- ;;
- esac
-
- # See if we need to build an old-fashioned archive.
- for oldlib in $oldlibs; do
-
- if test "$build_libtool_libs" = convenience; then
- oldobjs="$libobjs_save"
- addlibs="$convenience"
- build_libtool_libs=no
- else
- if test "$build_libtool_libs" = module; then
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
- oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "mkdir $gentop"
- $run mkdir "$gentop"
- status=$?
- if test $status -ne 0 && test ! -d "$gentop"; then
- exit $status
- fi
- generated="$generated $gentop"
-
- # Add in members from convenience archives.
- for xlib in $addlibs; do
- # Extract the objects.
- case "$xlib" in
- [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
- *) xabs=`pwd`"/$xlib" ;;
- esac
- xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
- xdir="$gentop/$xlib"
-
- $show "${rm}r $xdir"
- $run ${rm}r "$xdir"
- $show "mkdir $xdir"
- $run mkdir "$xdir"
- status=$?
- if test $status -ne 0 && test ! -d "$xdir"; then
- exit $status
- fi
- $show "(cd $xdir && $AR x $xabs)"
- $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
- oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
- done
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
- eval cmds=\"$old_archive_from_new_cmds\"
- else
- # Ensure that we have .o objects in place incase we decided
- # not to build a shared library, and have fallen back to building
- # static libs even though --disable-static was passed!
- for oldobj in $oldobjs; do
- if test ! -f $oldobj; then
- obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"`
- $show "${LN_S} $obj $oldobj"
- $run ${LN_S} $obj $oldobj || exit $?
- fi
- done
-
- eval cmds=\"$old_archive_cmds\"
- fi
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$generated"; then
- $show "${rm}r$generated"
- $run ${rm}r$generated
- fi
-
- # Now create the libtool archive.
- case "$output" in
- *.la)
- old_library=
- test "$build_old_libs" = yes && old_library="$libname.$libext"
- $show "creating $output"
-
- if test -n "$xrpath"; then
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- done
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
-
- # Only create the output if not a dry run.
- if test -z "$run"; then
- for installed in no yes; do
- if test "$installed" = yes; then
- if test -z "$install_libdir"; then
- break
- fi
- output="$output_objdir/$outputname"i
- fi
- $rm $output
- $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$dlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'\
-"
- done
- fi
-
- # Do a symbolic link so that the libtool archive can be found in
- # LD_LIBRARY_PATH before the program is installed.
- $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
- $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
- ;;
- esac
- exit 0
- ;;
-
- # libtool install mode
- install)
- modename="$modename: install"
-
- # There may be an optional sh(1) argument at the beginning of
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
- # Aesthetically quote it.
- arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$arg "
- arg="$1"
- shift
- else
- install_prog=
- arg="$nonopt"
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog$arg"
-
- # We need to accept at least all the BSD install flags.
- dest=
- files=
- opts=
- prev=
- install_type=
- isdir=no
- stripme=
- for arg
- do
- if test -n "$dest"; then
- files="$files $dest"
- dest="$arg"
- continue
- fi
-
- case "$arg" in
- -d) isdir=yes ;;
- -f) prev="-f" ;;
- -g) prev="-g" ;;
- -m) prev="-m" ;;
- -o) prev="-o" ;;
- -s)
- stripme=" -s"
- continue
- ;;
- -*) ;;
-
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
- dest="$arg"
- continue
- fi
- ;;
- esac
-
- # Aesthetically quote the argument.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case "$arg" in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog $arg"
- done
-
- if test -z "$install_prog"; then
- $echo "$modename: you must specify an install program" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prev' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- if test -z "$files"; then
- if test -z "$dest"; then
- $echo "$modename: no file or destination specified" 1>&2
- else
- $echo "$modename: you must specify a destination" 1>&2
- fi
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Strip any trailing slash from the destination.
- dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
- # Check to see that the destination is a directory.
- test -d "$dest" && isdir=yes
- if test "$isdir" = yes; then
- destdir="$dest"
- destname=
- else
- destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
- test "X$destdir" = "X$dest" && destdir=.
- destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files
- if test $# -gt 2; then
- $echo "$modename: \`$dest' is not a directory" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
- fi
- case "$destdir" in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- for file in $files; do
- case "$file" in
- *.lo) ;;
- *)
- $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
- esac
- done
- ;;
- esac
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- staticlibs=
- future_libdirs=
- current_libdirs=
- for file in $files; do
-
- # Do each installation.
- case "$file" in
- *.a | *.lib)
- # Do the static libraries later.
- staticlibs="$staticlibs $file"
- ;;
-
- *.la)
- # Check to see that this really is a libtool archive.
- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- library_names=
- old_library=
- # If there is no directory component, then add one.
- case "$file" in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Add the libdir to current_libdirs if it is the destination.
- if test "X$destdir" = "X$libdir"; then
- case "$current_libdirs " in
- *" $libdir "*) ;;
- *) current_libdirs="$current_libdirs $libdir" ;;
- esac
- else
- # Note the libdir as a future libdir.
- case "$future_libdirs " in
- *" $libdir "*) ;;
- *) future_libdirs="$future_libdirs $libdir" ;;
- esac
- fi
-
- dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
- test "X$dir" = "X$file/" && dir=
- dir="$dir$objdir"
-
- # See the names of the shared library.
- set dummy $library_names
- if test -n "$2"; then
- realname="$2"
- shift
- shift
-
- # Install the shared library and build the symlinks.
- $show "$install_prog $dir/$realname $destdir/$realname"
- $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
- test "X$dlname" = "X$realname" && dlname=
-
- if test $# -gt 0; then
- # Delete the old symlinks, and create new ones.
- for linkname
- do
- test "X$dlname" = "X$linkname" && dlname=
- if test "$linkname" != "$realname"; then
- $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
- fi
- done
- fi
-
- if test -n "$dlname"; then
- # Install the dynamically-loadable library.
- $show "$install_prog $dir/$dlname $destdir/$dlname"
- $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $?
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
- eval cmds=\"$postinstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- # Install the pseudo-library for information purposes.
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- instname="$dir/$name"i
- $show "$install_prog $instname $destdir/$name"
- $run eval "$install_prog $instname $destdir/$name" || exit $?
-
- # Maybe install the static library, too.
- test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
- ;;
-
- *.lo)
- # Install (i.e. copy) a libtool object.
-
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # Deduce the name of the destination old-style object file.
- case "$destfile" in
- *.lo)
- staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
- ;;
- *.o | *.obj)
- staticdest="$destfile"
- destfile=
- ;;
- *)
- $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
- esac
-
- # Install the libtool object if requested.
- if test -n "$destfile"; then
- $show "$install_prog $file $destfile"
- $run eval "$install_prog $file $destfile" || exit $?
- fi
-
- # Install the old object if enabled.
- if test "$build_old_libs" = yes; then
- # Deduce the name of the old-style object file.
- staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
- $show "$install_prog $staticobj $staticdest"
- $run eval "$install_prog \$staticobj \$staticdest" || exit $?
- fi
- exit 0
- ;;
-
- *)
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # Do a test to see if this is really a libtool program.
- if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- link_against_libtool_libs=
- relink_command=
-
- # If there is no directory component, then add one.
- case "$file" in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Check the variables that should have been set.
- if test -z "$link_against_libtool_libs"; then
- $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
- exit 1
- fi
-
- finalize=yes
- for lib in $link_against_libtool_libs; do
- # Check to see that each library is installed.
- libdir=
- if test -f "$lib"; then
- # If there is no directory component, then add one.
- case "$lib" in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- fi
- libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
- if test -n "$libdir" && test ! -f "$libfile"; then
- $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
- finalize=no
- fi
- done
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- if test "$finalize" = yes && test -z "$run"; then
- tmpdir="/tmp"
- test -n "$TMPDIR" && tmpdir="$TMPDIR"
- tmpdir="$tmpdir/libtool-$$"
- if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
- else
- $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
- continue
- fi
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- ${rm}r "$tmpdir"
- continue
- fi
- file="$outputname"
- else
- $echo "$modename: warning: cannot relink \`$file'" 1>&2
- fi
- else
- # Install the binary that we compiled earlier.
- file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- $show "$install_prog$stripme $file $destfile"
- $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
- test -n "$outputname" && ${rm}r "$tmpdir"
- ;;
- esac
- done
-
- for file in $staticlibs; do
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
- # Set up the ranlib parameters.
- oldlib="$destdir/$name"
-
- $show "$install_prog $file $oldlib"
- $run eval "$install_prog \$file \$oldlib" || exit $?
-
- # Do each command in the postinstall commands.
- eval cmds=\"$old_postinstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$future_libdirs"; then
- $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
- fi
-
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- test -n "$run" && current_libdirs=" -n$current_libdirs"
- exec $SHELL $0 --finish$current_libdirs
- exit 1
- fi
-
- exit 0
- ;;
-
- # libtool finish mode
- finish)
- modename="$modename: finish"
- libdirs="$nonopt"
- admincmds=
-
- if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
- for dir
- do
- libdirs="$libdirs $dir"
- done
-
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
- eval cmds=\"$finish_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || admincmds="$admincmds
- $cmd"
- done
- IFS="$save_ifs"
- fi
- if test -n "$finish_eval"; then
- # Do the single finish_eval.
- eval cmds=\"$finish_eval\"
- $run eval "$cmds" || admincmds="$admincmds
- $cmds"
- fi
- done
- fi
-
- # Exit here if they wanted silent mode.
- test "$show" = : && exit 0
-
- echo "----------------------------------------------------------------------"
- echo "Libraries have been installed in:"
- for libdir in $libdirs; do
- echo " $libdir"
- done
- echo
- echo "If you ever happen to want to link against installed libraries"
- echo "in a given directory, LIBDIR, you must either use libtool, and"
- echo "specify the full pathname of the library, or use \`-LLIBDIR'"
- echo "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
- echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
- echo " during execution"
- fi
- if test -n "$runpath_var"; then
- echo " - add LIBDIR to the \`$runpath_var' environment variable"
- echo " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
- echo " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
- echo " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
- echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
- echo
- echo "See any operating system documentation about shared libraries for"
- echo "more information, such as the ld(1) and ld.so(8) manual pages."
- echo "----------------------------------------------------------------------"
- exit 0
- ;;
-
- # libtool execute mode
- execute)
- modename="$modename: execute"
-
- # The first argument is the command name.
- cmd="$nonopt"
- if test -z "$cmd"; then
- $echo "$modename: you must specify a COMMAND" 1>&2
- $echo "$help"
- exit 1
- fi
-
- # Handle -dlopen flags immediately.
- for file in $execute_dlfiles; do
- if test ! -f "$file"; then
- $echo "$modename: \`$file' is not a file" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- dir=
- case "$file" in
- *.la)
- # Check to see that this really is a libtool archive.
- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- # Read the libtool library.
- dlname=
- library_names=
-
- # If there is no directory component, then add one.
- case "$file" in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Skip this library if it cannot be dlopened.
- if test -z "$dlname"; then
- # Warn if it was a shared library.
- test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
- continue
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
-
- if test -f "$dir/$objdir/$dlname"; then
- dir="$dir/$objdir"
- else
- $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
- exit 1
- fi
- ;;
-
- *.lo)
- # Just add the directory containing the .lo file.
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
- ;;
-
- *)
- $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
- continue
- ;;
- esac
-
- # Get the absolute pathname.
- absdir=`cd "$dir" && pwd`
- test -n "$absdir" && dir="$absdir"
-
- # Now add the directory to shlibpath_var.
- if eval "test -z \"\$$shlibpath_var\""; then
- eval "$shlibpath_var=\"\$dir\""
- else
- eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
- fi
- done
-
- # This variable tells wrapper scripts just to set shlibpath_var
- # rather than running their programs.
- libtool_execute_magic="$magic"
-
- # Check if any of the arguments is a wrapper script.
- args=
- for file
- do
- case "$file" in
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
- if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- # If there is no directory component, then add one.
- case "$file" in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Transform arg to wrapped name.
- file="$progdir/$program"
- fi
- ;;
- esac
- # Quote arguments (to preserve shell metacharacters).
- file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
- args="$args \"$file\""
- done
-
- if test -z "$run"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
-
- # Restore saved enviroment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
- if test "${save_LANG+set}" = set; then
- LANG="$save_LANG"; export LANG
- fi
-
- # Now actually exec the command.
- eval "exec \$cmd$args"
-
- $echo "$modename: cannot exec \$cmd$args"
- exit 1
- else
- # Display what would be done.
- eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
- $echo "export $shlibpath_var"
- $echo "$cmd$args"
- exit 0
- fi
- ;;
-
- # libtool uninstall mode
- uninstall)
- modename="$modename: uninstall"
- rm="$nonopt"
- files=
-
- for arg
- do
- case "$arg" in
- -*) rm="$rm $arg" ;;
- *) files="$files $arg" ;;
- esac
- done
-
- if test -z "$rm"; then
- $echo "$modename: you must specify an RM program" 1>&2
- $echo "$help" 1>&2
- exit 1
- fi
-
- for file in $files; do
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
- rmfiles="$file"
-
- case "$name" in
- *.la)
- # Possibly a libtool archive, so verify it.
- if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- . $dir/$name
-
- # Delete the libtool libraries and symlinks.
- for n in $library_names; do
- rmfiles="$rmfiles $dir/$n"
- test "X$n" = "X$dlname" && dlname=
- done
- test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname"
- test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
-
- $show "$rm $rmfiles"
- $run $rm $rmfiles
-
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- eval cmds=\"$postuninstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- eval cmds=\"$old_postuninstall_cmds\"
- IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd"
- done
- IFS="$save_ifs"
- fi
-
- # FIXME: should reinstall the best remaining shared library.
- fi
- ;;
-
- *.lo)
- if test "$build_old_libs" = yes; then
- oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
- rmfiles="$rmfiles $dir/$oldobj"
- fi
- $show "$rm $rmfiles"
- $run $rm $rmfiles
- ;;
-
- *)
- $show "$rm $rmfiles"
- $run $rm $rmfiles
- ;;
- esac
- done
- exit 0
- ;;
-
- "")
- $echo "$modename: you must specify a MODE" 1>&2
- $echo "$generic_help" 1>&2
- exit 1
- ;;
- esac
-
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
- exit 1
-fi # test -z "$show_help"
-
-# We need to display help for each of the modes.
-case "$mode" in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
- --config show all configuration variables
- --debug enable verbose shell tracing
--n, --dry-run display commands without modifying any files
- --features display basic configuration information and exit
- --finish same as \`--mode=finish'
- --help display this help message and exit
- --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
- --quiet same as \`--silent'
- --silent don't print informational messages
- --version print version information
-
-MODE must be one of the following:
-
- compile compile a source file into a libtool object
- execute automatically set library path, then run a program
- finish complete the installation of libtool libraries
- install install libraries or executables
- link create a library or an executable
- uninstall remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE."
- exit 0
- ;;
-
-compile)
- $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
- -o OUTPUT-FILE set the output file name to OUTPUT-FILE
- -static always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
- ;;
-
-execute)
- $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
- -dlopen FILE add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
- ;;
-
-finish)
- $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges. Use
-the \`--dry-run' option if you just want to see what would be executed."
- ;;
-
-install)
- $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command. The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
- ;;
-
-link)
- $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
- -all-static do not do any dynamic linking at all
- -avoid-version do not add a version suffix if possible
- -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
- -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
- -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
- -export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
- -export-symbols-regex REGEX
- try to export only the symbols matching REGEX
- -LLIBDIR search LIBDIR for required installed libraries
- -lNAME OUTPUT-FILE requires the installed library libNAME
- -module build a library that can dlopened
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -static do not do any dynamic linking of libtool libraries
- -version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename. Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
- ;;
-
-uninstall)
- $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
- ;;
-
-*)
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$help" 1>&2
- exit 1
- ;;
-esac
-
-echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/makefile.vc b/makefile.vc
index 0819a21..cc5dc74 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -1,10 +1,17 @@
#CFLAGS = /DSHPAPI_CALL=__stdcall
+CFLAGS = /nologo /Ox /MD /DSHAPELIB_DLLEXPORT
-default: all
+IMPORT_LIB = shapelib_i.lib
+STATIC_LIB = shapelib.lib
+DLLNAME = shapelib.dll
+LINK_LIB = $(IMPORT_LIB)
-all: shpcreate.exe shpadd.exe shpdump.exe shprewind.exe dbfcreate.exe \
- dbfadd.exe dbfdump.exe shptest.exe shptreedump.exe shapelib.dll
+OBJ = shpopen.obj dbfopen.obj shptree.obj safileio.obj
+
+all: $(STATIC_LIB) $(DLLNAME) \
+ shpcreate.exe shpadd.exe shpdump.exe shprewind.exe dbfcreate.exe \
+ dbfadd.exe dbfdump.exe shptest.exe shptreedump.exe
shpopen.obj: shpopen.c shapefil.h
$(CC) $(CFLAGS) -c shpopen.c
@@ -15,41 +22,65 @@ shptree.obj: shptree.c shapefil.h
dbfopen.obj: dbfopen.c shapefil.h
$(CC) $(CFLAGS) -c dbfopen.c
-shpcreate.exe: shpcreate.c shpopen.obj
- $(CC) $(CFLAGS) shpcreate.c shpopen.obj $(LINKOPT) -o shpcreate
+safileio.obj: safileio.c shapefil.h
+ $(CC) $(CFLAGS) -c safileio.c
+
+shpcreate.exe: shpcreate.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shpcreate.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
+
+shpadd.exe: shpadd.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shpadd.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shpadd.exe: shpadd.c shpopen.obj
- $(CC) $(CFLAGS) shpadd.c shpopen.obj $(LINKOPT)
+shpdump.exe: shpdump.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shpdump.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shpdump.exe: shpdump.c shpopen.obj
- $(CC) $(CFLAGS) shpdump.c shpopen.obj $(LINKOPT)
+shprewind.exe: shprewind.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shprewind.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shprewind.exe: shprewind.c shpopen.obj
- $(CC) $(CFLAGS) shprewind.c shpopen.obj $(LINKOPT)
+dbfcreate.exe: dbfcreate.c $(LINK_LIB)
+ $(CC) $(CFLAGS) dbfcreate.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-dbfcreate.exe: dbfcreate.c dbfopen.obj
- $(CC) $(CFLAGS) dbfcreate.c dbfopen.obj $(LINKOPT)
+dbfadd.exe: dbfadd.c $(LINK_LIB)
+ $(CC) $(CFLAGS) dbfadd.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-dbfadd.exe: dbfadd.c dbfopen.obj
- $(CC) $(CFLAGS) dbfadd.c dbfopen.obj $(LINKOPT)
+dbfdump.exe: dbfdump.c $(LINK_LIB)
+ $(CC) $(CFLAGS) dbfdump.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-dbfdump.exe: dbfdump.c dbfopen.obj
- $(CC) $(CFLAGS) dbfdump.c dbfopen.obj $(LINKOPT)
+shptest.exe: shptest.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shptest.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shptest.exe: shptest.c shpopen.obj
- $(CC) $(CFLAGS) shptest.c shpopen.obj $(LINKOPT)
+shputils.exe: shputils.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shputils.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shputils.exe: shputils.c shpopen.obj dbfopen.obj
- $(CC) $(CFLAGS) shputils.c shpopen.obj dbfopen.obj $(LINKOPT)
+shptreedump.exe: shptreedump.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shptreedump.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-shptreedump.exe: shptreedump.c shptree.obj shpopen.obj
- $(CC) $(CFLAGS) shptreedump.c shptree.obj shpopen.obj $(LINKOPT)
+shpdiff.exe: shpdiff.c $(LINK_LIB)
+ $(CC) $(CFLAGS) shpdiff.c $(LINK_LIB) $(LINKOPT)
+ if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
clean:
- -del *.obj dbfdump dbfcreate dbfadd shpdump shpcreate shpadd shputils
+ -del *.obj
+ -del *.exe
-del *.lib
-del *.dll
+ -del *.manifest
+
+$(STATIC_LIB): $(OBJ)
+ lib /nologo /out:$(STATIC_LIB) $(OBJ)
+
+$(IMPORT_LIB): $(DLLNAME)
-shapelib.dll: shpopen.obj dbfopen.obj shptree.obj shapelib.def
- link /dll /def:shapelib.def /out:shapelib.dll /implib:shapelib.lib \
- shpopen.obj dbfopen.obj shptree.obj
+$(DLLNAME): $(OBJ)
+ link /nologo /dll /out:$(DLLNAME) /implib:$(IMPORT_LIB) $(OBJ)
+ if exist $(DLLNAME).manifest mt /nologo -manifest $(DLLNAME).manifest -outputresource:$(DLLNAME);2
diff --git a/makeshape.sh b/makeshape.sh
index 6e5f271..7eb088a 100755
--- a/makeshape.sh
+++ b/makeshape.sh
@@ -5,17 +5,17 @@
# should display in ARCView II.
#
-shpcreate test polygon
-dbfcreate test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5
+./shpcreate test polygon
+./dbfcreate test.dbf -s Description 30 -n TestInt 6 0 -n TestDouble 16 5
-shpadd test 0 0 100 0 100 100 0 100 0 0 + 20 20 20 30 30 30 20 20
-dbfadd test.dbf "Square with triangle missing" 1.5 2.5
+./shpadd test 0 0 100 0 100 100 0 100 0 0 + 20 20 20 30 30 30 20 20
+./dbfadd test.dbf "Square with triangle missing" 1.5 2.5
-shpadd test 150 150 160 150 180 170 150 150
-dbfadd test.dbf "Smaller triangle" 100 1000.25
+./shpadd test 150 150 160 150 180 170 150 150
+./dbfadd test.dbf "Smaller triangle" 100 1000.25
-shpadd test 150 150 160 150 180 170 150 150
-dbfadd test.dbf "" "" ""
+./shpadd test 150 150 160 150 180 170 150 150
+./dbfadd test.dbf "" "" ""
-shpdump test.shp
-dbfdump test.dbf
+./shpdump test.shp
+./dbfdump test.dbf
diff --git a/mkdist.sh b/mkdist.sh
new file mode 100755
index 0000000..829325d
--- /dev/null
+++ b/mkdist.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+if [ $# -lt 1 ] ; then
+ echo "Usage: mkdist.sh <version>"
+ echo " <version> - version number used in name of generated archive."
+ echo "Example: mkdist.sh 1.1.4"
+ exit
+fi
+
+VERSION=$1
+
+rm -rf dist_wrk
+mkdir dist_wrk
+cd dist_wrk
+
+REP=:pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot
+if cvs -d $REP co shapelib ; then
+ echo checkout succeeds.
+else
+ cvs -d $REP login
+ cvs -d $REP co shapelib
+fi
+
+if [ ! -d shapelib ] ; then
+ exit 1
+fi
+
+mv shapelib shapelib-$VERSION
+
+find . -name CVS -type d -exec echo rm -rf {} \;
+
+tar czvf ../shapelib-$VERSION.tar.gz shapelib-$VERSION
+zip -r ../shapelib-$VERSION.zip shapelib-$VERSION
+cd ..
+rm -rf dist_wrk
+
+
diff --git a/mkrelease.sh b/mkrelease.sh
new file mode 100755
index 0000000..a25f9aa
--- /dev/null
+++ b/mkrelease.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# mkrelease.sh - prepares Shapelib source distribution package
+#
+if [ $# -lt 1 ] ; then
+ echo "Usage: mkrelease.sh <version>"
+ echo " <version> - version number used in name of generated archive."
+ echo
+ echo "Example: mkrelease 1.3.0beta1"
+ exit
+fi
+
+#
+# Processing script input arguments
+#
+VERSION=$1
+
+#
+# Checkout Shapelib sources from the repository
+#
+echo "* Downloading Shapelib sources from CVS..."
+rm -rf dist_wrk
+mkdir dist_wrk
+cd dist_wrk
+
+cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot export -D now shapelib
+
+if [ \! -d shapelib ] ; then
+ echo "checkout reported an error ..."
+ echo "perhaps you need to do:"
+ echo "cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot login"
+ cd ..
+ rm -rf dist_wrk
+ exit
+fi
+
+#
+# Make distribution packages
+#
+echo "* Making distribution packages..."
+
+mv shapelib shapelib-${VERSION}
+
+rm -f ../shapelib-${VERSION}.tar.gz ../shapelib-${VERSION}.zip
+
+tar cf ../shapelib-${VERSION}.tar shapelib-${VERSION}
+gzip -9 ../shapelib-${VERSION}.tar
+zip -r ../shapelib-${VERSION}.zip shapelib-${VERSION}
+
+echo "* Cleaning..."
+cd ..
+rm -rf dist_wrk
+
+echo "*** The End ***"
+
diff --git a/safileio.c b/safileio.c
new file mode 100644
index 0000000..f3affe2
--- /dev/null
+++ b/safileio.c
@@ -0,0 +1,286 @@
+/******************************************************************************
+ * $Id: safileio.c,v 1.4 2008-01-16 20:05:14 bram Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Default implementation of file io based on stdio.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: safileio.c,v $
+ * Revision 1.4 2008-01-16 20:05:14 bram
+ * Add file hooks that accept UTF-8 encoded filenames on some platforms. Use SASetupUtf8Hooks
+ * tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability. Currently, this
+ * is only available on the Windows platform that decodes the UTF-8 filenames to wide
+ * character strings and feeds them to _wfopen and _wremove.
+ *
+ * Revision 1.3 2007/12/18 18:28:11 bram
+ * - create hook for client specific atof (bugzilla ticket 1615)
+ * - check for NULL handle before closing cpCPG file, and close after reading.
+ *
+ * Revision 1.2 2007/12/15 20:25:30 bram
+ * dbfopen.c now reads the Code Page information from the DBF file, and exports
+ * this information as a string through the DBFGetCodePage function. This is
+ * either the number from the LDID header field ("LDID/<number>") or as the
+ * content of an accompanying .CPG file. When creating a DBF file, the code can
+ * be set using DBFCreateEx.
+ *
+ * Revision 1.1 2007/12/06 06:56:41 fwarmerdam
+ * new
+ *
+ */
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+SHP_CVSID("$Id: safileio.c,v 1.4 2008-01-16 20:05:14 bram Exp $");
+
+#ifdef SHPAPI_UTF8_HOOKS
+# ifdef SHPAPI_WINDOWS
+# define WIN32_LEAN_AND_MEAN
+# define NOMINMAX
+# include <windows.h>
+# pragma comment(lib, "kernel32.lib")
+# endif
+#endif
+
+/************************************************************************/
+/* SADFOpen() */
+/************************************************************************/
+
+SAFile SADFOpen( const char *pszFilename, const char *pszAccess )
+
+{
+ return (SAFile) fopen( pszFilename, pszAccess );
+}
+
+/************************************************************************/
+/* SADFRead() */
+/************************************************************************/
+
+SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+ return (SAOffset) fread( p, (size_t) size, (size_t) nmemb,
+ (FILE *) file );
+}
+
+/************************************************************************/
+/* SADFWrite() */
+/************************************************************************/
+
+SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+ return (SAOffset) fwrite( p, (size_t) size, (size_t) nmemb,
+ (FILE *) file );
+}
+
+/************************************************************************/
+/* SADFSeek() */
+/************************************************************************/
+
+SAOffset SADFSeek( SAFile file, SAOffset offset, int whence )
+
+{
+ return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+}
+
+/************************************************************************/
+/* SADFTell() */
+/************************************************************************/
+
+SAOffset SADFTell( SAFile file )
+
+{
+ return (SAOffset) ftell( (FILE *) file );
+}
+
+/************************************************************************/
+/* SADFFlush() */
+/************************************************************************/
+
+int SADFFlush( SAFile file )
+
+{
+ return fflush( (FILE *) file );
+}
+
+/************************************************************************/
+/* SADFClose() */
+/************************************************************************/
+
+int SADFClose( SAFile file )
+
+{
+ return fclose( (FILE *) file );
+}
+
+/************************************************************************/
+/* SADFClose() */
+/************************************************************************/
+
+int SADRemove( const char *filename )
+
+{
+ return remove( filename );
+}
+
+/************************************************************************/
+/* SADError() */
+/************************************************************************/
+
+void SADError( const char *message )
+
+{
+ fprintf( stderr, "%s\n", message );
+}
+
+/************************************************************************/
+/* SASetupDefaultHooks() */
+/************************************************************************/
+
+void SASetupDefaultHooks( SAHooks *psHooks )
+
+{
+ psHooks->FOpen = SADFOpen;
+ psHooks->FRead = SADFRead;
+ psHooks->FWrite = SADFWrite;
+ psHooks->FSeek = SADFSeek;
+ psHooks->FTell = SADFTell;
+ psHooks->FFlush = SADFFlush;
+ psHooks->FClose = SADFClose;
+ psHooks->Remove = SADRemove;
+
+ psHooks->Error = SADError;
+ psHooks->Atof = atof;
+}
+
+
+
+
+#ifdef SHPAPI_WINDOWS
+
+/************************************************************************/
+/* Utf8ToWideChar */
+/************************************************************************/
+
+const wchar_t* Utf8ToWideChar( const char *pszFilename )
+{
+ int nMulti, nWide;
+ wchar_t *pwszFileName;
+
+ nMulti = strlen(pszFilename) + 1;
+ nWide = MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, 0, 0);
+ if( nWide == 0 )
+ {
+ return NULL;
+ }
+ pwszFileName = (wchar_t*) malloc(nWide * sizeof(wchar_t));
+ if ( pwszFileName == NULL )
+ {
+ return NULL;
+ }
+ if( MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, pwszFileName, nWide ) == 0 )
+ {
+ free( pwszFileName );
+ return NULL;
+ }
+ return pwszFileName;
+}
+
+/************************************************************************/
+/* SAUtf8WFOpen */
+/************************************************************************/
+
+SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
+{
+ SAFile file = NULL;
+ const wchar_t *pwszFileName, *pwszAccess;
+ pwszFileName = Utf8ToWideChar( pszFilename );
+ pwszAccess = Utf8ToWideChar( pszAccess );
+ if( pwszFileName != NULL && pwszFileName != NULL)
+ {
+ file = (SAFile) _wfopen( pwszFileName, pwszAccess );
+ }
+ free ((wchar_t*) pwszFileName);
+ free ((wchar_t*) pwszAccess);
+ return file;
+}
+
+/************************************************************************/
+/* SAUtf8WRemove() */
+/************************************************************************/
+
+int SAUtf8WRemove( const char *pszFilename )
+{
+ const wchar_t *pwszFileName = Utf8ToWideChar( pszFilename );
+ int rc = -1;
+ if( pwszFileName != NULL )
+ {
+ rc = _wremove( pwszFileName );
+ }
+ free ((wchar_t*) pwszFileName);
+ return rc;
+}
+
+#endif
+
+#ifdef SHPAPI_UTF8_HOOKS
+
+/************************************************************************/
+/* SASetupUtf8Hooks() */
+/************************************************************************/
+
+void SASetupUtf8Hooks( SAHooks *psHooks )
+{
+#ifdef SHPAPI_WINDOWS
+ psHooks->FOpen = SAUtf8WFOpen;
+ psHooks->Remove = SAUtf8WRemove;
+#else
+# error "no implementations of UTF-8 hooks available for this platform"
+#endif
+ psHooks->FRead = SADFRead;
+ psHooks->FWrite = SADFWrite;
+ psHooks->FSeek = SADFSeek;
+ psHooks->FTell = SADFTell;
+ psHooks->FFlush = SADFFlush;
+ psHooks->FClose = SADFClose;
+
+ psHooks->Error = SADError;
+ psHooks->Atof = atof;
+}
+
+#endif
diff --git a/shapefil.h b/shapefil.h
index 19ba921..e90b1cc 100644
--- a/shapefil.h
+++ b/shapefil.h
@@ -1,8 +1,8 @@
-#ifndef _SHAPEFILE_H_INCLUDED
-#define _SHAPEFILE_H_INCLUDED
+#ifndef SHAPEFILE_H_INCLUDED
+#define SHAPEFILE_H_INCLUDED
/******************************************************************************
- * $Id: shapefil.h,v 1.26 2002/09/29 00:00:08 warmerda Exp $
+ * $Id: shapefil.h,v 1.52 2011-12-11 22:26:46 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Primary include file for Shapelib.
@@ -37,81 +37,107 @@
******************************************************************************
*
* $Log: shapefil.h,v $
- * Revision 1.26 2002/09/29 00:00:08 warmerda
- * added FTLogical and logical attribute read/write calls
+ * Revision 1.52 2011-12-11 22:26:46 fwarmerdam
+ * upgrade .qix access code to use SAHooks (gdal #3365)
*
- * Revision 1.25 2002/05/07 13:46:30 warmerda
- * added DBFWriteAttributeDirectly().
+ * Revision 1.51 2011-07-24 05:59:25 fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
*
- * Revision 1.24 2002/04/10 16:59:54 warmerda
- * added SHPRewindObject
+ * Revision 1.50 2011-05-13 17:35:17 fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
*
- * Revision 1.23 2002/01/15 14:36:07 warmerda
- * updated email address
+ * Revision 1.49 2011-04-16 14:38:21 fwarmerdam
+ * avoid warnings with gcc on SHP_CVSID
*
- * Revision 1.22 2002/01/15 14:32:00 warmerda
- * try to improve SHPAPI_CALL docs
+ * Revision 1.48 2010-08-27 23:42:52 fwarmerdam
+ * add SHPAPI_CALL attribute in code
*
- * Revision 1.21 2001/11/01 16:29:55 warmerda
- * move pabyRec into SHPInfo for thread safety
+ * Revision 1.47 2010-01-28 11:34:34 fwarmerdam
+ * handle the shape file length limits more gracefully (#3236)
*
- * Revision 1.20 2001/07/20 13:06:02 warmerda
- * fixed SHPAPI attribute for SHPTreeFindLikelyShapes
+ * Revision 1.46 2008-11-12 14:28:15 fwarmerdam
+ * DBFCreateField() now works on files with records
*
- * Revision 1.19 2001/05/31 19:20:13 warmerda
- * added DBFGetFieldIndex()
+ * Revision 1.45 2008/11/11 17:47:10 fwarmerdam
+ * added DBFDeleteField() function
*
- * Revision 1.18 2001/05/31 18:15:40 warmerda
- * Added support for NULL fields in DBF files
+ * Revision 1.44 2008/01/16 20:05:19 bram
+ * Add file hooks that accept UTF-8 encoded filenames on some platforms. Use SASetupUtf8Hooks
+ * tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability. Currently, this
+ * is only available on the Windows platform that decodes the UTF-8 filenames to wide
+ * character strings and feeds them to _wfopen and _wremove.
*
- * Revision 1.17 2001/05/23 13:36:52 warmerda
- * added use of SHPAPI_CALL
+ * Revision 1.43 2008/01/10 16:35:30 fwarmerdam
+ * avoid _ prefix on #defined symbols (bug 1840)
*
- * Revision 1.16 2000/09/25 14:15:59 warmerda
- * added DBFGetNativeFieldType()
+ * Revision 1.42 2007/12/18 18:28:14 bram
+ * - create hook for client specific atof (bugzilla ticket 1615)
+ * - check for NULL handle before closing cpCPG file, and close after reading.
*
- * Revision 1.15 2000/02/16 16:03:51 warmerda
- * added null shape support
+ * Revision 1.41 2007/12/15 20:25:32 bram
+ * dbfopen.c now reads the Code Page information from the DBF file, and exports
+ * this information as a string through the DBFGetCodePage function. This is
+ * either the number from the LDID header field ("LDID/<number>") or as the
+ * content of an accompanying .CPG file. When creating a DBF file, the code can
+ * be set using DBFCreateEx.
*
- * Revision 1.14 1999/11/05 14:12:05 warmerda
- * updated license terms
+ * Revision 1.40 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
*
- * Revision 1.13 1999/06/02 18:24:21 warmerda
- * added trimming code
+ * Revision 1.39 2007/12/04 20:37:56 fwarmerdam
+ * preliminary implementation of hooks api for io and errors
*
- * Revision 1.12 1999/06/02 17:56:12 warmerda
- * added quad'' subnode support for trees
+ * Revision 1.38 2007/11/21 22:39:56 fwarmerdam
+ * close shx file in readonly mode (GDAL #1956)
*
- * Revision 1.11 1999/05/18 19:11:11 warmerda
- * Added example searching capability
+ * Revision 1.37 2007/10/27 03:31:14 fwarmerdam
+ * limit default depth of tree to 12 levels (gdal ticket #1594)
*
- * Revision 1.10 1999/05/18 17:49:38 warmerda
- * added initial quadtree support
+ * Revision 1.36 2007/09/10 23:33:15 fwarmerdam
+ * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
+ * of GDAL (gdal ticket #1810).
*
- * Revision 1.9 1999/05/11 03:19:28 warmerda
- * added new Tuple api, and improved extension handling - add from candrsn
+ * Revision 1.35 2007/09/03 19:48:10 fwarmerdam
+ * move DBFReadAttribute() static dDoubleField into dbfinfo
*
- * Revision 1.8 1999/03/23 17:22:27 warmerda
- * Added extern "C" protection for C++ users of shapefil.h.
+ * Revision 1.34 2006/06/17 15:33:32 fwarmerdam
+ * added pszWorkField - bug 1202 (rso)
*
- * Revision 1.7 1998/12/31 15:31:07 warmerda
- * Added the TRIM_DBF_WHITESPACE and DISABLE_MULTIPATCH_MEASURE options.
+ * Revision 1.33 2006/02/15 01:14:30 fwarmerdam
+ * added DBFAddNativeFieldType
*
- * Revision 1.6 1998/12/03 15:48:15 warmerda
- * Added SHPCalculateExtents().
+ * Revision 1.32 2006/01/26 15:07:32 fwarmerdam
+ * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
*
- * Revision 1.5 1998/11/09 20:57:16 warmerda
- * Altered SHPGetInfo() call.
+ * Revision 1.31 2006/01/05 01:27:27 fwarmerdam
+ * added dbf deletion mark/fetch
*
- * Revision 1.4 1998/11/09 20:19:33 warmerda
- * Added 3D support, and use of SHPObject.
+ * Revision 1.30 2005/01/03 22:30:13 fwarmerdam
+ * added support for saved quadtrees
*
- * Revision 1.3 1995/08/23 02:24:05 warmerda
- * Added support for reading bounds.
+ * Revision 1.29 2004/09/26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.28 2003/12/29 06:02:18 fwarmerdam
+ * added cpl_error.h option
+ *
+ * Revision 1.27 2003/04/21 18:30:37 warmerda
+ * added header write/update public methods
+ *
+ * Revision 1.26 2002/09/29 00:00:08 warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.25 2002/05/07 13:46:30 warmerda
+ * added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.24 2002/04/10 16:59:54 warmerda
+ * added SHPRewindObject
*
- * Revision 1.2 1995/08/04 03:17:39 warmerda
- * Added header.
+ * Revision 1.23 2002/01/15 14:36:07 warmerda
+ * updated email address
*
+ * Revision 1.22 2002/01/15 14:32:00 warmerda
+ * try to improve SHPAPI_CALL docs
*/
#include <stdio.h>
@@ -140,7 +166,7 @@ extern "C" {
/* is disabled. */
/* -------------------------------------------------------------------- */
#define DISABLE_MULTIPATCH_MEASURE
-
+
/* -------------------------------------------------------------------- */
/* SHPAPI_CALL */
/* */
@@ -176,29 +202,88 @@ extern "C" {
#endif
#ifndef SHPAPI_CALL
-# define SHPAPI_CALL
+# if defined(USE_GCC_VISIBILITY_FLAG)
+# define SHPAPI_CALL __attribute__ ((visibility("default")))
+# define SHPAPI_CALL1(x) __attribute__ ((visibility("default"))) x
+# else
+# define SHPAPI_CALL
+# endif
#endif
#ifndef SHPAPI_CALL1
# define SHPAPI_CALL1(x) x SHPAPI_CALL
#endif
+/* -------------------------------------------------------------------- */
+/* Macros for controlling CVSID and ensuring they don't appear */
+/* as unreferenced variables resulting in lots of warnings. */
+/* -------------------------------------------------------------------- */
+#ifndef DISABLE_CVSID
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define SHP_CVSID(string) static char cpl_cvsid[] __attribute__((used)) = string;
+# else
+# define SHP_CVSID(string) static char cpl_cvsid[] = string; \
+static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+# endif
+#else
+# define SHP_CVSID(string)
+#endif
+
+/* -------------------------------------------------------------------- */
+/* On some platforms, additional file IO hooks are defined that */
+/* UTF-8 encoded filenames Unicode filenames */
+/* -------------------------------------------------------------------- */
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define SHPAPI_WINDOWS
+# define SHPAPI_UTF8_HOOKS
+#endif
+
+/* -------------------------------------------------------------------- */
+/* IO/Error hook functions. */
+/* -------------------------------------------------------------------- */
+typedef int *SAFile;
+
+#ifndef SAOffset
+typedef unsigned long SAOffset;
+#endif
+
+typedef struct {
+ SAFile (*FOpen) ( const char *filename, const char *access);
+ SAOffset (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+ SAOffset (*FWrite)( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+ SAOffset (*FSeek) ( SAFile file, SAOffset offset, int whence );
+ SAOffset (*FTell) ( SAFile file );
+ int (*FFlush)( SAFile file );
+ int (*FClose)( SAFile file );
+ int (*Remove) ( const char *filename );
+
+ void (*Error) ( const char *message );
+ double (*Atof) ( const char *str );
+} SAHooks;
+
+void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
+#ifdef SHPAPI_UTF8_HOOKS
+void SHPAPI_CALL SASetupUtf8Hooks( SAHooks *psHooks );
+#endif
+
/************************************************************************/
/* SHP Support. */
/************************************************************************/
typedef struct
{
- FILE *fpSHP;
- FILE *fpSHX;
+ SAHooks sHooks;
+
+ SAFile fpSHP;
+ SAFile fpSHX;
int nShapeType; /* SHPT_* */
- int nFileSize; /* SHP file */
+ unsigned int nFileSize; /* SHP file */
int nRecords;
int nMaxRecords;
- int *panRecOffset;
- int *panRecSize;
+ unsigned int *panRecOffset;
+ unsigned int *panRecSize;
double adBoundsMin[4];
double adBoundsMax[4];
@@ -271,15 +356,26 @@ typedef struct
double dfYMax;
double dfZMax;
double dfMMax;
+
+ int bMeasureIsUsed;
} SHPObject;
/* -------------------------------------------------------------------- */
/* SHP API Prototypes */
/* -------------------------------------------------------------------- */
+
+/* If pszAccess is read-only, the fpSHX field of the returned structure */
+/* will be NULL as it is not necessary to keep the SHX file open */
SHPHandle SHPAPI_CALL
SHPOpen( const char * pszShapeFile, const char * pszAccess );
SHPHandle SHPAPI_CALL
+ SHPOpenLL( const char *pszShapeFile, const char *pszAccess,
+ SAHooks *psHooks );
+SHPHandle SHPAPI_CALL
SHPCreate( const char * pszShapeFile, int nShapeType );
+SHPHandle SHPAPI_CALL
+ SHPCreateLL( const char * pszShapeFile, int nShapeType,
+ SAHooks *psHooks );
void SHPAPI_CALL
SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
double * padfMinBound, double * padfMaxBound );
@@ -294,19 +390,22 @@ void SHPAPI_CALL
void SHPAPI_CALL
SHPComputeExtents( SHPObject * psObject );
SHPObject SHPAPI_CALL1(*)
- SHPCreateObject( int nSHPType, int nShapeId,
- int nParts, int * panPartStart, int * panPartType,
- int nVertices, double * padfX, double * padfY,
- double * padfZ, double * padfM );
+ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
+ const int * panPartStart, const int * panPartType,
+ int nVertices,
+ const double * padfX, const double * padfY,
+ const double * padfZ, const double * padfM );
SHPObject SHPAPI_CALL1(*)
SHPCreateSimpleObject( int nSHPType, int nVertices,
- double * padfX, double * padfY, double * padfZ );
+ const double * padfX,
+ const double * padfY,
+ const double * padfZ );
int SHPAPI_CALL
SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
-void SHPAPI_CALL
- SHPClose( SHPHandle hSHP );
+void SHPAPI_CALL SHPClose( SHPHandle hSHP );
+void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
const char SHPAPI_CALL1(*)
SHPTypeName( int nSHPType );
@@ -320,6 +419,9 @@ const char SHPAPI_CALL1(*)
/* this can be two or four for binary or quad tree */
#define MAX_SUBNODE 4
+/* upper limit of tree levels for automatic estimation */
+#define MAX_DEFAULT_TREE_DEPTH 12
+
typedef struct shape_tree_node
{
/* region covered by this node */
@@ -343,6 +445,7 @@ typedef struct
int nMaxDepth;
int nDimension;
+ int nTotalCount;
SHPTreeNode *psRoot;
} SHPTree;
@@ -355,12 +458,8 @@ void SHPAPI_CALL
int SHPAPI_CALL
SHPWriteTree( SHPTree *hTree, const char * pszFilename );
-SHPTree SHPAPI_CALL
- SHPReadTree( const char * pszFilename );
int SHPAPI_CALL
- SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
-int SHPAPI_CALL
SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
int SHPAPI_CALL
SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
@@ -376,12 +475,37 @@ int SHPAPI_CALL1(*)
int SHPAPI_CALL
SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+int SHPAPI_CALL1(*)
+SHPSearchDiskTree( FILE *fp,
+ double *padfBoundsMin, double *padfBoundsMax,
+ int *pnShapeCount );
+
+
+typedef struct SHPDiskTreeInfo* SHPTreeDiskHandle;
+
+SHPTreeDiskHandle SHPAPI_CALL
+ SHPOpenDiskTree( const char* pszQIXFilename,
+ SAHooks *psHooks );
+
+void SHPAPI_CALL
+ SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree );
+
+int SHPAPI_CALL1(*)
+SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
+ double *padfBoundsMin, double *padfBoundsMax,
+ int *pnShapeCount );
+
+int SHPAPI_CALL
+ SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, SAHooks *psHooks );
+
/************************************************************************/
/* DBF Support. */
/************************************************************************/
typedef struct
{
- FILE *fp;
+ SAHooks sHooks;
+
+ SAFile fp;
int nRecords;
@@ -398,9 +522,17 @@ typedef struct
int nCurrentRecord;
int bCurrentRecordModified;
char *pszCurrentRecord;
+
+ int nWorkFieldLength;
+ char *pszWorkField;
int bNoHeader;
int bUpdated;
+
+ double dfDoubleField;
+
+ int iLanguageDriver;
+ char *pszCodePage;
} DBFInfo;
typedef DBFInfo * DBFHandle;
@@ -415,10 +547,18 @@ typedef enum {
#define XBASE_FLDHDR_SZ 32
+
DBFHandle SHPAPI_CALL
DBFOpen( const char * pszDBFFile, const char * pszAccess );
DBFHandle SHPAPI_CALL
+ DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
+ SAHooks *psHooks );
+DBFHandle SHPAPI_CALL
DBFCreate( const char * pszDBFFile );
+DBFHandle SHPAPI_CALL
+ DBFCreateEx( const char * pszDBFFile, const char * pszCodePage );
+DBFHandle SHPAPI_CALL
+ DBFCreateLL( const char * pszDBFFile, const char * pszCodePage, SAHooks *psHooks );
int SHPAPI_CALL
DBFGetFieldCount( DBFHandle psDBF );
@@ -428,6 +568,20 @@ int SHPAPI_CALL
DBFAddField( DBFHandle hDBF, const char * pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals );
+int SHPAPI_CALL
+ DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
+ char chType, int nWidth, int nDecimals );
+
+int SHPAPI_CALL
+ DBFDeleteField( DBFHandle hDBF, int iField );
+
+int SHPAPI_CALL
+ DBFReorderFields( DBFHandle psDBF, int* panMap );
+
+int SHPAPI_CALL
+ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+ char chType, int nWidth, int nDecimals );
+
DBFFieldType SHPAPI_CALL
DBFGetFieldInfo( DBFHandle psDBF, int iField,
char * pszFieldName, int * pnWidth, int * pnDecimals );
@@ -469,16 +623,25 @@ const char SHPAPI_CALL1(*)
int SHPAPI_CALL
DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
+int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
+ int bIsDeleted );
+
DBFHandle SHPAPI_CALL
DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
void SHPAPI_CALL
DBFClose( DBFHandle hDBF );
+void SHPAPI_CALL
+ DBFUpdateHeader( DBFHandle hDBF );
char SHPAPI_CALL
DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+const char SHPAPI_CALL1(*)
+ DBFGetCodePage(DBFHandle psDBF );
+
#ifdef __cplusplus
}
#endif
-#endif /* ndef _SHAPEFILE_H_INCLUDED */
+#endif /* ndef SHAPEFILE_H_INCLUDED */
diff --git a/shapelib.def b/shapelib.def
index 01964c4..354c8f0 100644
--- a/shapelib.def
+++ b/shapelib.def
@@ -9,6 +9,7 @@ EXPORTS SHPOpen
SHPCreateObject
SHPCreateSimpleObject
SHPClose
+ SHPWriteHeader
SHPTypeName
SHPPartTypeName
SHPCreateTree
@@ -38,5 +39,8 @@ EXPORTS SHPOpen
DBFIsAttributeNULL
DBFWriteLogicalAttribute
DBFReadLogicalAttribute
-
-
+ DBFUpdateHeader
+ DBFGetNativeFieldType
+ SHPRewindObject
+ DBFIsRecordDeleted
+ DBFMarkRecordDeleted
diff --git a/shapelib.html b/shapelib.html
deleted file mode 100644
index 4372d1d..0000000
--- a/shapelib.html
+++ /dev/null
@@ -1,334 +0,0 @@
-<html>
-<head>
-<title>Shapefile C Library V1.2</title>
-</head>
-
-<body>
-<h1>Shapefile C Library V1.2</h1>
-
-<h2>Purpose</h2>
-
-The Shapefile C Library provides the ability to write simple C programs
-for reading, writing and updating (to a limited extent) ESRI Shapefiles,
-and the associated attribute file (.dbf).<p>
-
-<h2>Manifest</h2>
-
-<ul>
-<li> <b>shapelib.html</b>: This file - general documentation on the
-Shapefile C Library.<p>
-
-<li> <b><a href="shp_api.html">shp_api.html</a></b>: Documentation
-for the API for accessing the .shp/.shx files. <p>
-
-<li> <b><a href="dbf_api.html">dbf_api.html</a></b>: Documentation
-for the API for accessing the .dbf attribute files. <p>
-
-<li> <b>shpopen.c</b>: C code for access to .shp/.shx vertex files.<p>
-
-<li> <b>dbfopen.c</b>: C code for access to .dbf attribute file.<p>
-
-<li> <b>shapefil.h</b>: Include file defining all the services of dbfopen.c
-and shpopen.c.<p>
-
-<li> <b>contrib/</b>: A directory of "in progress" contributed programs
-from Carl Anderson.<p>
-
-<li> <b>dbfcreate.c</b>: Simple example program for creating a new .dbf file.
- <p>
-
-<li> <b>dbfadd.c</b>:
- Simple example program for adding a record to a .dbf file.<p>
-
-<li> <b>dbfdump.c</b>: Simple example program for displaying the contents of
- a .dbf file.<p>
-
-<li> <b>shpcreate.c</b>: Simple example program for creating a new .shp and
-.shx file.<p>
-
-<li> <b>shpadd.c</b>: Simple example program for adding a shape to an existing
- shape file.<p>
-
-<li> <b>shpdump.c</b>: Simple program for dumping all the vertices in a
- shapefile with an indicating of the parts.<p>
-
-<li> <b>shputils.c</b>: Complex contributed program capable of clipping and
- appending
- shapefiles as well as a few other things. Type shputils
- after building to get a full usage message.<p>
-
-<li> <b>Makefile</b>: A simple makefile to compile the library and example
- programs.<p>
-
-<li> <b>makeshape.sh</b>: A simple script for running some of the example
-programs.<p>
-
-<li> <b>shptest.c</b>: A simple test harnass to generate each of the supported
- types of shapefiles. <p>
-
-
-<li> <b>shptree.c</b>: Implements a simple quadtree algorithm for fast
-spatial searches of shapefiles.<p>
-
-<li> <b>shptreedump.c</b>: A simple mainly showing information on quad
-trees build using the quad tree api.<p>
-
-<li> <b>stream1.sh</b> - A test script, which should produce stream1.out.
-Note this will only work if you have the example data downloaded.<p>
-
-<li> <b>stream1.out</b>: Expected output of stream1.sh test script.<p>
-
-<li> <b>stream2.sh</b>: A test script, which should produce stream2.out.<p>
-
-<li> <b>stream2.out</b>: Expected output of stream2.sh test script.<p>
-
-<li> <b>pyshapelib-0.1</b>: Prototype contributed Python bindings.<p>
-
-</ul>
-
-<h2>What is a Shapefile?</h2>
-
-If you don't know, you probably don't need this library. The Shapefile
-format is a new working and interchange format promulagated by ESRI
-(http://www.esri.com/) for simple vector data with attributes. It is
-apparently the only file format that can be edited in ARCView 2/3, and can
-also be exported and imported in Arc/Info. <p>
-
-An excellent white paper on the shapefile format is available from ESRI,
-but it is .pdf format, so you will need Adobe Acrobat to browse it.<p>
-
-The file format actually consists of three files.<p>
-
-<pre>
-XXX.shp - holds the actual vertices.
-XXX.shx - hold index data pointing to the structures in the .shp file.
-XXX.dbf - holds the attributes in xBase (dBase) format.
-</pre>
-
-<h2>Release Notes</h2>
-
-To get notification of new releases of Shapelib <i>subscribe</i> to
-the project at www.freshmeat.net. This is currently the only reliable
-way of finding out about new releases since there is no shapelib specific
-mailing list.<p>
-
-<b>Release 1.2.10</b>: Added SHPRewindObject() function, and shprewind utility
-program. Added FTLogical, DBFReadLogicalAttribute() and
-DBFWriteLogicalAttribute() (thanks to Olek Neyman). <p>
-
-<b>Release 1.2.9</b>: Good support for reading and writing NULL fields
-in .dbf files, good support for NULL shapes and addition of the
-DBFGetFieldIndex() functions (all contributed by Jim Matthews).<p>
-
-An upgraded shputils.c has been contributed by Bill Miller. Daniel
-Morissette contributed DBFGetNativeFieldType(). Better error checking
-for disk errors in dbfopen.c. Various other bug fixes and safety improvements.
-<p>
-
-<b>Release 1.2.8</b>: Added hacked libtool support (supplied by Jan)
-and "rpm ready" install logic.<p>
-
-<b>Release 1.2.7</b>: Fix record size (was 4 bytes too long). Modify
-SHPReadObject() to handle null shapes properly. Use atof() instead of
-sscanf(). Support .DBF as well as .dbf.<p>
-
-<b>Release 1.2.6</b>: Now available under old MIT style license, or at the
-users option, LGPL. Added the contrib directory of stuff from Carl Anderson
-and the shptree.c API for quadtree based spatial searches.<p>
-
-<b>Release 1.2.5</b>: SHPOpen() now forcably uses "rb" or "r+b" access string
-to avoid common mistakes on Windows. Also fixed a serious bug with .dbf
-files with a 'F' field type.<p>
-
-<b>Release 1.2.4</b>: DBFOpen() will now automatically translate a .shp
-extension to .dbf for convenience. SHPOpen() will try datasets with lower
-and uppercase extension. DBFAddField() now returns the field number,
-not TRUE/FALSE.<p>
-
-<b>Release 1.2.3</b>: Disable writing measures to multi-patches as ArcView
-seems to puke on them (as reported by Monika Sester). Add white space
-trimming, and string/numeric attribute interchangability in DBF API
-as suggested by Steve Lime. Dbfdump was updated to include several
-reporting options.<p>
-
-<b>Release 1.2.2</b>: Added proper support for multipatch (reading and
-writing) - this release just for testing purposes.<p>
-
-<b>Release 1.2</b> is mostly a rewrite of the .shp/.shx access API to account
-for ArcView 3.x 3D shapes, and to encapsulate the shapes in a structure.
-Existing code using the shapefile library will require substantial changes
-to use release 1.2.<p>
-
-<b>Release V1.1</b> has been built on a number of platforms, and used by a
-number of people successfully. V1.1 is the first release with the xBase API
-documentation.<p>
-
-
-<h2>Maintainer</h2>
-
-This library is maintained by me (Frank Warmerdam) on my own time. Please
-send me bug patches and suggestions for the library. Email can be sent to
-warmerdam at pobox.com.<p>
-
-The current status of the Shapelib code can be found at
-<a href="http://pobox.com/~warmerdam/root/projects/shapelib/">
-http://pobox.com/~warmerdam/root/projects/shapelib/</a>. To find out about
-new releases of Shapelib, select the "Subscribe to new releases" option
-from the link at
-<a href="http://freshmeat.net/projects/shapelib/">Freshmeat</a>.<p>
-
-The shputils.c module was contributed by Bill Miller (NC-DOT) who can be
-reached at bmiller at doh.dot.state.nc.us. I had to modify it substantially
-to work with the 1.2 API, and I am not sure that it works as well as it
-did when it was originally provided by Bill.<p>
-
-<h2>Credits</h2>
-
-I didn't start this section anywhere near soon enough, so alot of earlier
-contributors to Shapelib are lost in pre-history.
-
-<ul>
-<li> Bill Miller (NY-DOT) for shputils.c
-<li> Carl Anderson for the contents of the contrib directory, and
-the "tuple" additions to dbfopen.c.
-<li> Andrea Giacomelli for patches for dbfopen.c.
-<li> Doug Matthews for portability improvements.
-<li> Jan-Oliver Wagner for convincing me to make it available under LGPL,
-shared library support, and various other patches.
-<li> Dennis Christopher (of Avenza) for testing and bug fixes.
-<li> Miko Syrjä (of 3D-system Oy) for a record size bug fix.
-<li> Steven Lime and Curtis Hill for help with NULL shapes.
-<li> Jim Matthews for support of NULL attributes in dbf files.
-<li> <a href="http://www.pcigeomatics.com/">PCI Geomatics</a> who let me
-release a modified version of their shapefile code in the beginning and
-who hosted shapelib for years.
-</ul>
-
-<h2>In Memorium</h2>
-
-I would like to dedicate Shapelib to the memory of Sol Katz. While I never
-met him in person, his generous contributions to the GIS community took
-many forms, including free distribution of a variety of GIS translators
-with source. The fact that he used this Shapelib in some of his utilities,
-and thanked me was a great encouragement to me. I hope I can do his memory
-honour by trying to contribute in a similar fashion.<p>
-
-<h2>Portability</h2>
-
-The Shapefile C Library should port easily to 32bit systems with ANSI C
-compilers. It should work on 64 bit architectures (such as the DEC AXP).<p>
-
-Care should also be taken to pass the binary access flag into SHPOpen()
-and DBFOpen() when operating on systems with special text file translation
-such as MSDOS.<p>
-
-The shputils.c module is contributed, and may not take the same approach
-to portability as the rest of the package.<p>
-
-On Linux, and most unix systems it should be possible to build and
-install shapefile support as a shared library using the "lib" and "lib_install"
-targets of the Makefile. Note that this Makefile doesn't use autoconf
-mechanisms and will generally require some hand tailoring for your environment.
-
-<h2>Limitations</h2>
-
-<ul>
-
-<li> You can't modify the vertices of existing structures (though you
- can update the attributes of existing structures, and create new
- structures).<p>
-
-<li> Not written in such a way as to be particularly fast. This is
-particularly true of the 1.2 API. For applications more concerned with
-speed it may be worth using the V1.1 API.<p>
-
-<li> Doesn't set the last access time properly in the .dbf files.<p>
-
-<li> There is no way to synchronize information to the file except to close it.
-<p>
-
-<li> Poor error checking and reporting.<p>
-
-<li> Not professionally supported (well it can be, if you want to pay).<p>
-
-<li> Some aspects of xBase files not supported, though I believe they are
-not used by ESRI.<p>
-
-<li> The application must keep the .dbf file in sync with the .shp/.shx
-files through appropriate use of the DBF and SHP APIs.<p>
-
-<li> No support for the undocumented .sbn/.sbx spatial index files.<p>
-
-</ul>
-
-<h2>Copyright</h2>
-
-The source for the Shapefile C Library is (c) 1998 Frank Warmerdam,
-and released under the following conditions. The intent is that anyone
-can do anything with the code, but that I do not assume any liability, nor
-express any warranty for this code. <p>
-
-As of Shapelib 1.2.6 the core portions of the library are made available
-under two possible licenses. The licensee can choose to use the code
-under either the Library GNU Public License (LGPL) described in
-LICENSE.LGPL or under the following MIT style license. Any files in
-the Shapelib distribution without explicit copyright license terms
-(such as this documentation, the Makefile and so forth) should be
-considered to have the following licensing terms. Some auxilary portions
-of Shapelib, notably some of the components in the contrib directory
-come under slightly different license restrictions. Check the source
-files that you are actually using for conditions.<p>
-
-<h3>Default License Terms</h3>
-
-<quote>
-Copyright (c) 1999, Frank Warmerdam<p>
-
-This software is available under the following "MIT Style" license,
-or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
-option is discussed in more detail in shapelib.html.<p>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:<p>
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.<p>
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.<p>
-</quote>
-
-<h3>Shapelib Modifications</h3>
-
-I am pleased to receive bug fixes, and improvements for Shapelib. Unless
-the submissions indicate otherwise I will assume that changes submitted to
-me remain under the the above "dual license" terms. If changes are made
-to the library with the intention that those changes should be protected by
-the LGPL then I should be informed upon submission. Note that I will not
-generally incorporate changes into the core of Shapelib that are protected
-under the LGPL as this would effectively limit the whole file and
-distribution to LGPL terms.<p>
-
-<h3>Opting for LGPL</h3>
-
-For licensee's opting to use Shapelib under LGPL as opposed to the MIT
-Style license above, and wishing to redistribute the software based on
-Shapelib, I would ask that all "dual license" modules be updated to
-indicate that only the LGPL (and not the MIT Style license) applies. This
-action represents opting for the LGPL, and thereafter LGPL terms apply to
-any redistribution and modification of the affected modules.<p>
-
-</body>
-</html>
-
-
-
diff --git a/shpadd.c b/shpadd.c
index 68b0c9d..7b20b8a 100644
--- a/shpadd.c
+++ b/shpadd.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shpadd.c,v 1.13 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: shpadd.c,v 1.16 2010-06-21 20:41:52 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for adding a shape to a shapefile.
@@ -34,6 +34,15 @@
******************************************************************************
*
* $Log: shpadd.c,v $
+ * Revision 1.16 2010-06-21 20:41:52 fwarmerdam
+ * reformat white space
+ *
+ * Revision 1.15 2007-12-30 16:57:32 fwarmerdam
+ * add support for z and m
+ *
+ * Revision 1.14 2004/09/26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
* Revision 1.13 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -72,44 +81,68 @@
*
*/
-static char rcsid[] =
- "$Id: shpadd.c,v 1.13 2002/01/15 14:36:07 warmerda Exp $";
-
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
+SHP_CVSID("$Id: shpadd.c,v 1.16 2010-06-21 20:41:52 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType, nVertices, nParts, *panParts, i, nVMax;
- double *padfX, *padfY;
+ double *padfX, *padfY, *padfZ = NULL, *padfM = NULL;
SHPObject *psObject;
+ const char *tuple = "";
+ const char *filename;
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc < 2 )
{
- printf( "shpadd shp_file [[x y] [+]]*\n" );
- exit( 1 );
+ printf( "shpadd shp_file [[x y] [+]]*\n" );
+ printf( " or\n" );
+ printf( "shpadd shp_file -m [[x y m] [+]]*\n" );
+ printf( " or\n" );
+ printf( "shpadd shp_file -z [[x y z] [+]]*\n" );
+ printf( " or\n" );
+ printf( "shpadd shp_file -zm [[x y z m] [+]]*\n" );
+ exit( 1 );
+ }
+
+ filename = argv[1];
+ argv++;
+ argc--;
+
+/* -------------------------------------------------------------------- */
+/* Check for tuple description options. */
+/* -------------------------------------------------------------------- */
+ if( argc > 1
+ && (strcmp(argv[1],"-z") == 0
+ || strcmp(argv[1],"-m") == 0
+ || strcmp(argv[1],"-zm") == 0) )
+ {
+ tuple = argv[1] + 1;
+ argv++;
+ argc--;
}
/* -------------------------------------------------------------------- */
/* Open the passed shapefile. */
/* -------------------------------------------------------------------- */
- hSHP = SHPOpen( argv[1], "r+b" );
+ hSHP = SHPOpen( filename, "r+b" );
if( hSHP == NULL )
{
- printf( "Unable to open:%s\n", argv[1] );
- exit( 1 );
+ printf( "Unable to open:%s\n", filename );
+ exit( 1 );
}
SHPGetInfo( hSHP, NULL, &nShapeType, NULL, NULL );
- if( argc == 2 )
+ if( argc == 1 )
nShapeType = SHPT_NULL;
/* -------------------------------------------------------------------- */
@@ -118,6 +151,11 @@ int main( int argc, char ** argv )
nVMax = 1000;
padfX = (double *) malloc(sizeof(double) * nVMax);
padfY = (double *) malloc(sizeof(double) * nVMax);
+
+ if( strchr(tuple,'z') )
+ padfZ = (double *) malloc(sizeof(double) * nVMax);
+ if( strchr(tuple,'m') )
+ padfM = (double *) malloc(sizeof(double) * nVMax);
nVertices = 0;
@@ -130,34 +168,42 @@ int main( int argc, char ** argv )
nParts = 1;
panParts[0] = 0;
- for( i = 2; i < argc; )
+ for( i = 1; i < argc; )
{
- if( argv[i][0] == '+' )
- {
- panParts[nParts++] = nVertices;
- i++;
- }
- else if( i < argc-1 )
- {
+ if( argv[i][0] == '+' )
+ {
+ panParts[nParts++] = nVertices;
+ i++;
+ }
+ else if( i < argc-1-strlen(tuple) )
+ {
if( nVertices == nVMax )
{
nVMax = nVMax * 2;
padfX = (double *) realloc(padfX,sizeof(double)*nVMax);
padfY = (double *) realloc(padfY,sizeof(double)*nVMax);
+ if( padfZ )
+ padfZ = (double *) realloc(padfZ,sizeof(double)*nVMax);
+ if( padfM )
+ padfM = (double *) realloc(padfM,sizeof(double)*nVMax);
}
- sscanf( argv[i], "%lg", padfX+nVertices );
- sscanf( argv[i+1], "%lg", padfY+nVertices );
- nVertices += 1;
- i += 2;
- }
+ sscanf( argv[i++], "%lg", padfX+nVertices );
+ sscanf( argv[i++], "%lg", padfY+nVertices );
+ if( padfZ )
+ sscanf( argv[i++], "%lg", padfZ+nVertices );
+ if( padfM )
+ sscanf( argv[i++], "%lg", padfM+nVertices );
+
+ nVertices += 1;
+ }
}
/* -------------------------------------------------------------------- */
/* Write the new entity to the shape file. */
/* -------------------------------------------------------------------- */
psObject = SHPCreateObject( nShapeType, -1, nParts, panParts, NULL,
- nVertices, padfX, padfY, NULL, NULL );
+ nVertices, padfX, padfY, padfZ, padfM );
SHPWriteObject( hSHP, -1, psObject );
SHPDestroyObject( psObject );
@@ -166,6 +212,8 @@ int main( int argc, char ** argv )
free( panParts );
free( padfX );
free( padfY );
+ free( padfZ );
+ free( padfM );
return 0;
}
diff --git a/shpcreate.c b/shpcreate.c
index c33dd25..5e170b7 100644
--- a/shpcreate.c
+++ b/shpcreate.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shpcreate.c,v 1.5 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: shpcreate.c,v 1.8 2007-12-30 16:57:33 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for creating a new shapefile.
@@ -34,6 +34,15 @@
******************************************************************************
*
* $Log: shpcreate.c,v $
+ * Revision 1.8 2007-12-30 16:57:33 fwarmerdam
+ * add support for z and m
+ *
+ * Revision 1.7 2004/09/26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.6 2004/01/09 16:39:49 fwarmerdam
+ * include standard include files
+ *
* Revision 1.5 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -48,11 +57,12 @@
*
*/
-static char rcsid[] =
- "$Id: shpcreate.c,v 1.5 2002/01/15 14:36:07 warmerda Exp $";
-
+#include <string.h>
+#include <stdlib.h>
#include "shapefil.h"
+SHP_CVSID("$Id: shpcreate.c,v 1.8 2007-12-30 16:57:33 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
@@ -64,7 +74,7 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
if( argc != 3 )
{
- printf( "shpcreate shp_file [point/arc/polygon/multipoint]\n" );
+ printf( "shpcreate shp_file [point/arc/polygon/multipoint][/m/z]\n" );
exit( 1 );
}
@@ -79,6 +89,24 @@ int main( int argc, char ** argv )
nShapeType = SHPT_POLYGON;
else if( strcmp(argv[2],"MULTIPOINT")==0 ||strcmp(argv[2],"multipoint")==0)
nShapeType = SHPT_MULTIPOINT;
+ else if( strcmp(argv[2],"POINTZ") == 0 || strcmp(argv[2],"pointz") == 0 )
+ nShapeType = SHPT_POINTZ;
+ else if( strcmp(argv[2],"ARCZ") == 0 || strcmp(argv[2],"arcz") == 0 )
+ nShapeType = SHPT_ARCZ;
+ else if( strcmp(argv[2],"POLYGONZ") == 0 || strcmp(argv[2],"polygonz") == 0)
+ nShapeType = SHPT_POLYGONZ;
+ else if( strcmp(argv[2],"MULTIPOINTZ") == 0
+ || strcmp(argv[2],"multipointz") == 0)
+ nShapeType = SHPT_MULTIPOINTZ;
+ else if( strcmp(argv[2],"POINTM") == 0 || strcmp(argv[2],"pointm") == 0 )
+ nShapeType = SHPT_POINTM;
+ else if( strcmp(argv[2],"ARCM") == 0 || strcmp(argv[2],"arcm") == 0 )
+ nShapeType = SHPT_ARCM;
+ else if( strcmp(argv[2],"POLYGONM") == 0 || strcmp(argv[2],"polygonm") == 0)
+ nShapeType = SHPT_POLYGONM;
+ else if( strcmp(argv[2],"MULTIPOINTM") == 0
+ || strcmp(argv[2],"multipointm") == 0 )
+ nShapeType = SHPT_MULTIPOINTM;
else
{
printf( "Shape Type `%s' not recognised.\n", argv[2] );
diff --git a/shpdump.c b/shpdump.c
index 5dc1cfa..87dfa49 100644
--- a/shpdump.c
+++ b/shpdump.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shpdump.c,v 1.10 2002/04/10 16:59:29 warmerda Exp $
+ * $Id: shpdump.c,v 1.18 2011-07-24 03:05:14 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Sample application for dumping contents of a shapefile to
@@ -35,6 +35,30 @@
******************************************************************************
*
* $Log: shpdump.c,v $
+ * Revision 1.18 2011-07-24 03:05:14 fwarmerdam
+ * use %.15g for formatting coordiantes in shpdump
+ *
+ * Revision 1.17 2010-07-01 07:33:04 fwarmerdam
+ * do not crash in shpdump if null object returned
+ *
+ * Revision 1.16 2010-07-01 07:27:13 fwarmerdam
+ * white space formatting adjustments
+ *
+ * Revision 1.15 2006-01-26 15:07:32 fwarmerdam
+ * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
+ *
+ * Revision 1.14 2005/02/11 17:17:46 fwarmerdam
+ * added panPartStart[0] validation
+ *
+ * Revision 1.13 2004/09/26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.12 2004/01/27 18:05:35 fwarmerdam
+ * Added the -ho (header only) switch.
+ *
+ * Revision 1.11 2004/01/09 16:39:49 fwarmerdam
+ * include standard include files
+ *
* Revision 1.10 2002/04/10 16:59:29 warmerda
* added -validate switch
*
@@ -64,16 +88,18 @@
*
*/
-static char rcsid[] =
- "$Id: shpdump.c,v 1.10 2002/04/10 16:59:29 warmerda Exp $";
-
+#include <string.h>
+#include <stdlib.h>
#include "shapefil.h"
+SHP_CVSID("$Id: shpdump.c,v 1.18 2011-07-24 03:05:14 fwarmerdam Exp $")
+
int main( int argc, char ** argv )
{
SHPHandle hSHP;
int nShapeType, nEntities, i, iPart, bValidate = 0,nInvalidCount=0;
+ int bHeaderOnly = 0;
const char *pszPlus;
double adfMinBound[4], adfMaxBound[4];
@@ -84,13 +110,20 @@ int main( int argc, char ** argv )
argc--;
}
+ if( argc > 1 && strcmp(argv[1],"-ho") == 0 )
+ {
+ bHeaderOnly = 1;
+ argv++;
+ argc--;
+ }
+
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
if( argc != 2 )
{
- printf( "shpdump [-validate] shp_file\n" );
- exit( 1 );
+ printf( "shpdump [-validate] [-ho] shp_file\n" );
+ exit( 1 );
}
/* -------------------------------------------------------------------- */
@@ -100,8 +133,8 @@ int main( int argc, char ** argv )
if( hSHP == NULL )
{
- printf( "Unable to open:%s\n", argv[1] );
- exit( 1 );
+ printf( "Unable to open:%s\n", argv[1] );
+ exit( 1 );
}
/* -------------------------------------------------------------------- */
@@ -112,8 +145,8 @@ int main( int argc, char ** argv )
printf( "Shapefile Type: %s # of Shapes: %d\n\n",
SHPTypeName( nShapeType ), nEntities );
- printf( "File Bounds: (%12.3f,%12.3f,%g,%g)\n"
- " to (%12.3f,%12.3f,%g,%g)\n",
+ printf( "File Bounds: (%.15g,%.15g,%.15g,%.15g)\n"
+ " to (%.15g,%.15g,%.15g,%.15g)\n",
adfMinBound[0],
adfMinBound[1],
adfMinBound[2],
@@ -122,52 +155,85 @@ int main( int argc, char ** argv )
adfMaxBound[1],
adfMaxBound[2],
adfMaxBound[3] );
-
+
/* -------------------------------------------------------------------- */
/* Skim over the list of shapes, printing all the vertices. */
/* -------------------------------------------------------------------- */
- for( i = 0; i < nEntities; i++ )
+ for( i = 0; i < nEntities && !bHeaderOnly; i++ )
{
- int j;
+ int j;
SHPObject *psShape;
- psShape = SHPReadObject( hSHP, i );
+ psShape = SHPReadObject( hSHP, i );
+
+ if( psShape == NULL )
+ {
+ fprintf( stderr,
+ "Unable to read shape %d, terminating object reading.\n",
+ i );
+ break;
+ }
+
+ if( psShape->bMeasureIsUsed )
+ printf( "\nShape:%d (%s) nVertices=%d, nParts=%d\n"
+ " Bounds:(%.15g,%.15g, %.15g, %.15g)\n"
+ " to (%.15g,%.15g, %.15g, %.15g)\n",
+ i, SHPTypeName(psShape->nSHPType),
+ psShape->nVertices, psShape->nParts,
+ psShape->dfXMin, psShape->dfYMin,
+ psShape->dfZMin, psShape->dfMMin,
+ psShape->dfXMax, psShape->dfYMax,
+ psShape->dfZMax, psShape->dfMMax );
+ else
+ printf( "\nShape:%d (%s) nVertices=%d, nParts=%d\n"
+ " Bounds:(%.15g,%.15g, %.15g)\n"
+ " to (%.15g,%.15g, %.15g)\n",
+ i, SHPTypeName(psShape->nSHPType),
+ psShape->nVertices, psShape->nParts,
+ psShape->dfXMin, psShape->dfYMin,
+ psShape->dfZMin,
+ psShape->dfXMax, psShape->dfYMax,
+ psShape->dfZMax );
- printf( "\nShape:%d (%s) nVertices=%d, nParts=%d\n"
- " Bounds:(%12.3f,%12.3f, %g, %g)\n"
- " to (%12.3f,%12.3f, %g, %g)\n",
- i, SHPTypeName(psShape->nSHPType),
- psShape->nVertices, psShape->nParts,
- psShape->dfXMin, psShape->dfYMin,
- psShape->dfZMin, psShape->dfMMin,
- psShape->dfXMax, psShape->dfYMax,
- psShape->dfZMax, psShape->dfMMax );
+ if( psShape->nParts > 0 && psShape->panPartStart[0] != 0 )
+ {
+ fprintf( stderr, "panPartStart[0] = %d, not zero as expected.\n",
+ psShape->panPartStart[0] );
+ }
- for( j = 0, iPart = 1; j < psShape->nVertices; j++ )
- {
+ for( j = 0, iPart = 1; j < psShape->nVertices; j++ )
+ {
const char *pszPartType = "";
if( j == 0 && psShape->nParts > 0 )
pszPartType = SHPPartTypeName( psShape->panPartType[0] );
- if( iPart < psShape->nParts
+ if( iPart < psShape->nParts
&& psShape->panPartStart[iPart] == j )
- {
+ {
pszPartType = SHPPartTypeName( psShape->panPartType[iPart] );
- iPart++;
- pszPlus = "+";
- }
- else
- pszPlus = " ";
-
- printf(" %s (%12.3f,%12.3f, %g, %g) %s \n",
- pszPlus,
- psShape->padfX[j],
- psShape->padfY[j],
- psShape->padfZ[j],
- psShape->padfM[j],
- pszPartType );
- }
+ iPart++;
+ pszPlus = "+";
+ }
+ else
+ pszPlus = " ";
+
+ if( psShape->bMeasureIsUsed )
+ printf(" %s (%.15g,%.15g, %.15g, %.15g) %s \n",
+ pszPlus,
+ psShape->padfX[j],
+ psShape->padfY[j],
+ psShape->padfZ[j],
+ psShape->padfM[j],
+ pszPartType );
+ else
+ printf(" %s (%.15g,%.15g, %.15g) %s \n",
+ pszPlus,
+ psShape->padfX[j],
+ psShape->padfY[j],
+ psShape->padfZ[j],
+ pszPartType );
+ }
if( bValidate )
{
diff --git a/shpopen.c b/shpopen.c
index 6e1d626..ee9fce5 100644
--- a/shpopen.c
+++ b/shpopen.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shpopen.c,v 1.39 2002/08/26 06:46:56 warmerda Exp $
+ * $Id: shpopen.c,v 1.73 2012-01-24 22:33:01 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Implementation of core Shapefile read/write functions.
@@ -34,6 +34,112 @@
******************************************************************************
*
* $Log: shpopen.c,v $
+ * Revision 1.73 2012-01-24 22:33:01 fwarmerdam
+ * fix memory leak on failure to open .shp (gdal #4410)
+ *
+ * Revision 1.72 2011-12-11 22:45:28 fwarmerdam
+ * fix failure return from SHPOpenLL.
+ *
+ * Revision 1.71 2011-09-15 03:33:58 fwarmerdam
+ * fix missing cast (#2344)
+ *
+ * Revision 1.70 2011-07-24 05:59:25 fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.69 2011-07-24 03:24:22 fwarmerdam
+ * fix memory leaks in error cases creating shapefiles (#2061)
+ *
+ * Revision 1.68 2010-08-27 23:42:52 fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
+ * Revision 1.67 2010-07-01 08:15:48 fwarmerdam
+ * do not error out on an object with zero vertices
+ *
+ * Revision 1.66 2010-07-01 07:58:57 fwarmerdam
+ * minor cleanup of error handling
+ *
+ * Revision 1.65 2010-07-01 07:27:13 fwarmerdam
+ * white space formatting adjustments
+ *
+ * Revision 1.64 2010-01-28 11:34:34 fwarmerdam
+ * handle the shape file length limits more gracefully (#3236)
+ *
+ * Revision 1.63 2010-01-28 04:04:40 fwarmerdam
+ * improve numerical accuracy of SHPRewind() algs (gdal #3363)
+ *
+ * Revision 1.62 2010-01-17 05:34:13 fwarmerdam
+ * Remove asserts on x/y being null (#2148).
+ *
+ * Revision 1.61 2010-01-16 05:07:42 fwarmerdam
+ * allow 0/nulls in shpcreateobject (#2148)
+ *
+ * Revision 1.60 2009-09-17 20:50:02 bram
+ * on Win32, define snprintf as alias to _snprintf
+ *
+ * Revision 1.59 2008-03-14 05:25:31 fwarmerdam
+ * Correct crash on buggy geometries (gdal #2218)
+ *
+ * Revision 1.58 2008/01/08 23:28:26 bram
+ * on line 2095, use a float instead of a double to avoid a compiler warning
+ *
+ * Revision 1.57 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
+ *
+ * Revision 1.56 2007/12/04 20:37:56 fwarmerdam
+ * preliminary implementation of hooks api for io and errors
+ *
+ * Revision 1.55 2007/11/21 22:39:56 fwarmerdam
+ * close shx file in readonly mode (GDAL #1956)
+ *
+ * Revision 1.54 2007/11/15 00:12:47 mloskot
+ * Backported recent changes from GDAL (Ticket #1415) to Shapelib.
+ *
+ * Revision 1.53 2007/11/14 22:31:08 fwarmerdam
+ * checks after mallocs to detect for corrupted/voluntary broken shapefiles.
+ * http://trac.osgeo.org/gdal/ticket/1991
+ *
+ * Revision 1.52 2007/06/21 15:58:33 fwarmerdam
+ * fix for SHPRewindObject when rings touch at one vertex (gdal #976)
+ *
+ * Revision 1.51 2006/09/04 15:24:01 fwarmerdam
+ * Fixed up log message for 1.49.
+ *
+ * Revision 1.50 2006/09/04 15:21:39 fwarmerdam
+ * fix of last fix
+ *
+ * Revision 1.49 2006/09/04 15:21:00 fwarmerdam
+ * MLoskot: Added stronger test of Shapefile reading failures, e.g. truncated
+ * files. The problem was discovered by Tim Sutton and reported here
+ * https://svn.qgis.org/trac/ticket/200
+ *
+ * Revision 1.48 2006/01/26 15:07:32 fwarmerdam
+ * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
+ *
+ * Revision 1.47 2006/01/04 20:07:23 fwarmerdam
+ * In SHPWriteObject() make sure that the record length is updated
+ * when rewriting an existing record.
+ *
+ * Revision 1.46 2005/02/11 17:17:46 fwarmerdam
+ * added panPartStart[0] validation
+ *
+ * Revision 1.45 2004/09/26 20:09:48 fwarmerdam
+ * const correctness changes
+ *
+ * Revision 1.44 2003/12/29 00:18:39 fwarmerdam
+ * added error checking for failed IO and optional CPL error reporting
+ *
+ * Revision 1.43 2003/12/01 16:20:08 warmerda
+ * be careful of zero vertex shapes
+ *
+ * Revision 1.42 2003/12/01 14:58:27 warmerda
+ * added degenerate object check in SHPRewindObject()
+ *
+ * Revision 1.41 2003/07/08 15:22:43 warmerda
+ * avoid warning
+ *
+ * Revision 1.40 2003/04/21 18:30:37 warmerda
+ * added header write/update public methods
+ *
* Revision 1.39 2002/08/26 06:46:56 warmerda
* avoid c++ comments
*
@@ -158,9 +264,6 @@
*
*/
-static char rcsid[] =
- "$Id: shpopen.c,v 1.39 2002/08/26 06:46:56 warmerda Exp $";
-
#include "shapefil.h"
#include <math.h>
@@ -168,13 +271,16 @@ static char rcsid[] =
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
+
+SHP_CVSID("$Id: shpopen.c,v 1.73 2012-01-24 22:33:01 fwarmerdam Exp $")
typedef unsigned char uchar;
#if UINT_MAX == 65535
-typedef long int32;
+typedef unsigned long int32;
#else
-typedef int int32;
+typedef unsigned int int32;
#endif
#ifndef FALSE
@@ -188,6 +294,12 @@ typedef int int32;
# define MAX(a,b) ((a>b) ? a : b)
#endif
+#if defined(WIN32) || defined(_WIN32)
+# ifndef snprintf
+# define snprintf _snprintf
+# endif
+#endif
+
static int bBigEndian;
@@ -234,7 +346,7 @@ static void * SfRealloc( void * pMem, int nNewSize )
/* contents of the index (.shx) file. */
/************************************************************************/
-static void SHPWriteHeader( SHPHandle psSHP )
+void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
{
uchar abyHeader[100];
@@ -242,12 +354,18 @@ static void SHPWriteHeader( SHPHandle psSHP )
int32 i32;
double dValue;
int32 *panSHX;
+
+ if (psSHP->fpSHX == NULL)
+ {
+ psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
+ return;
+ }
/* -------------------------------------------------------------------- */
/* Prepare header block for .shp file. */
/* -------------------------------------------------------------------- */
for( i = 0; i < 100; i++ )
- abyHeader[i] = 0;
+ abyHeader[i] = 0;
abyHeader[2] = 0x27; /* magic cookie */
abyHeader[3] = 0x0a;
@@ -299,8 +417,12 @@ static void SHPWriteHeader( SHPHandle psSHP )
/* -------------------------------------------------------------------- */
/* Write .shp file header. */
/* -------------------------------------------------------------------- */
- fseek( psSHP->fpSHP, 0, 0 );
- fwrite( abyHeader, 100, 1, psSHP->fpSHP );
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
+ || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
+ {
+ psSHP->sHooks.Error( "Failure writing .shp header" );
+ return;
+ }
/* -------------------------------------------------------------------- */
/* Prepare, and write .shx file header. */
@@ -309,8 +431,12 @@ static void SHPWriteHeader( SHPHandle psSHP )
ByteCopy( &i32, abyHeader+24, 4 );
if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
- fseek( psSHP->fpSHX, 0, 0 );
- fwrite( abyHeader, 100, 1, psSHP->fpSHX );
+ if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
+ || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
+ {
+ psSHP->sHooks.Error( "Failure writing .shx header" );
+ return;
+ }
/* -------------------------------------------------------------------- */
/* Write out the .shx contents. */
@@ -319,15 +445,40 @@ static void SHPWriteHeader( SHPHandle psSHP )
for( i = 0; i < psSHP->nRecords; i++ )
{
- panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
- panSHX[i*2+1] = psSHP->panRecSize[i]/2;
- if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
- if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+ panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
+ panSHX[i*2+1] = psSHP->panRecSize[i]/2;
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
}
- fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX );
+ if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
+ != psSHP->nRecords )
+ {
+ psSHP->sHooks.Error( "Failure writing .shx contents" );
+ }
free( panSHX );
+
+/* -------------------------------------------------------------------- */
+/* Flush to disk. */
+/* -------------------------------------------------------------------- */
+ psSHP->sHooks.FFlush( psSHP->fpSHP );
+ psSHP->sHooks.FFlush( psSHP->fpSHX );
+}
+
+/************************************************************************/
+/* SHPOpen() */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
+
+{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return SHPOpenLL( pszLayer, pszAccess, &sHooks );
}
/************************************************************************/
@@ -338,7 +489,7 @@ static void SHPWriteHeader( SHPHandle psSHP )
/************************************************************************/
SHPHandle SHPAPI_CALL
-SHPOpen( const char * pszLayer, const char * pszAccess )
+SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
{
char *pszFullname, *pszBasename;
@@ -374,6 +525,7 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
psSHP->bUpdated = FALSE;
+ memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
/* -------------------------------------------------------------------- */
/* Compute the base (layer) name. If there is any extension */
@@ -382,9 +534,9 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
pszBasename = (char *) malloc(strlen(pszLayer)+5);
strcpy( pszBasename, pszLayer );
for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
if( pszBasename[i] == '.' )
pszBasename[i] = '\0';
@@ -394,33 +546,46 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
/* a PC to Unix with upper case filenames won't work! */
/* -------------------------------------------------------------------- */
pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.shp", pszBasename );
- psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ sprintf( pszFullname, "%s.shp", pszBasename ) ;
+ psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
if( psSHP->fpSHP == NULL )
{
sprintf( pszFullname, "%s.SHP", pszBasename );
- psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
}
if( psSHP->fpSHP == NULL )
{
+ char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+ sprintf( pszMessage, "Unable to open %s.shp or %s.SHP.",
+ pszBasename, pszBasename );
+ psHooks->Error( pszMessage );
+ free( pszMessage );
+
free( psSHP );
free( pszBasename );
free( pszFullname );
- return( NULL );
+
+ return NULL;
}
sprintf( pszFullname, "%s.shx", pszBasename );
- psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
if( psSHP->fpSHX == NULL )
{
sprintf( pszFullname, "%s.SHX", pszBasename );
- psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
}
if( psSHP->fpSHX == NULL )
{
- fclose( psSHP->fpSHP );
+ char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+ sprintf( pszMessage, "Unable to open %s.shx or %s.SHX.",
+ pszBasename, pszBasename );
+ psHooks->Error( pszMessage );
+ free( pszMessage );
+
+ psSHP->sHooks.FClose( psSHP->fpSHP );
free( psSHP );
free( pszBasename );
free( pszFullname );
@@ -434,44 +599,51 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
/* Read the file size from the SHP file. */
/* -------------------------------------------------------------------- */
pabyBuf = (uchar *) malloc(100);
- fread( pabyBuf, 100, 1, psSHP->fpSHP );
+ psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
- psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
- + pabyBuf[25] * 256 * 256
- + pabyBuf[26] * 256
- + pabyBuf[27]) * 2;
+ psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
+ + (unsigned int)pabyBuf[25] * 256 * 256
+ + (unsigned int)pabyBuf[26] * 256
+ + (unsigned int)pabyBuf[27]) * 2;
/* -------------------------------------------------------------------- */
/* Read SHX file Header info */
/* -------------------------------------------------------------------- */
- fread( pabyBuf, 100, 1, psSHP->fpSHX );
-
- if( pabyBuf[0] != 0
+ if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
+ || pabyBuf[0] != 0
|| pabyBuf[1] != 0
|| pabyBuf[2] != 0x27
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
{
- fclose( psSHP->fpSHP );
- fclose( psSHP->fpSHX );
- free( psSHP );
+ psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ free( psSHP );
- return( NULL );
+ return( NULL );
}
psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
- + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
+ + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
psSHP->nShapeType = pabyBuf[32];
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
{
- /* this header appears to be corrupt. Give up. */
- fclose( psSHP->fpSHP );
- fclose( psSHP->fpSHX );
- free( psSHP );
+ char szError[200];
+
+ sprintf( szError,
+ "Record count in .shp header is %d, which seems\n"
+ "unreasonable. Assuming header is corrupt.",
+ psSHP->nRecords );
+ psSHP->sHooks.Error( szError );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ free( psSHP );
+ free(pabyBuf);
- return( NULL );
+ return( NULL );
}
/* -------------------------------------------------------------------- */
@@ -517,26 +689,72 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
/* -------------------------------------------------------------------- */
psSHP->nMaxRecords = psSHP->nRecords;
- psSHP->panRecOffset =
- (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
- psSHP->panRecSize =
- (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
-
+ psSHP->panRecOffset = (unsigned int *)
+ malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
+ psSHP->panRecSize = (unsigned int *)
+ malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
- fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
+
+ if (psSHP->panRecOffset == NULL ||
+ psSHP->panRecSize == NULL ||
+ pabyBuf == NULL)
+ {
+ char szError[200];
+
+ sprintf(szError,
+ "Not enough memory to allocate requested memory (nRecords=%d).\n"
+ "Probably broken SHP file",
+ psSHP->nRecords );
+ psSHP->sHooks.Error( szError );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ if (psSHP->panRecOffset) free( psSHP->panRecOffset );
+ if (psSHP->panRecSize) free( psSHP->panRecSize );
+ if (pabyBuf) free( pabyBuf );
+ free( psSHP );
+ return( NULL );
+ }
+
+ if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
+ != psSHP->nRecords )
+ {
+ char szError[200];
+
+ sprintf( szError,
+ "Failed to read all values for %d records in .shx file.",
+ psSHP->nRecords );
+ psSHP->sHooks.Error( szError );
+
+ /* SHX is short or unreadable for some reason. */
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ free( psSHP->panRecOffset );
+ free( psSHP->panRecSize );
+ free( pabyBuf );
+ free( psSHP );
+
+ return( NULL );
+ }
+
+ /* In read-only mode, we can close the SHX now */
+ if (strcmp(pszAccess, "rb") == 0)
+ {
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ psSHP->fpSHX = NULL;
+ }
for( i = 0; i < psSHP->nRecords; i++ )
{
- int32 nOffset, nLength;
+ int32 nOffset, nLength;
- memcpy( &nOffset, pabyBuf + i * 8, 4 );
- if( !bBigEndian ) SwapWord( 4, &nOffset );
+ memcpy( &nOffset, pabyBuf + i * 8, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nOffset );
- memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
- if( !bBigEndian ) SwapWord( 4, &nLength );
+ memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nLength );
- psSHP->panRecOffset[i] = nOffset*2;
- psSHP->panRecSize[i] = nLength*2;
+ psSHP->panRecOffset[i] = nOffset*2;
+ psSHP->panRecSize[i] = nLength*2;
}
free( pabyBuf );
@@ -553,13 +771,14 @@ void SHPAPI_CALL
SHPClose(SHPHandle psSHP )
{
+ if( psSHP == NULL )
+ return;
+
/* -------------------------------------------------------------------- */
/* Update the header if we have modified anything. */
/* -------------------------------------------------------------------- */
if( psSHP->bUpdated )
- {
SHPWriteHeader( psSHP );
- }
/* -------------------------------------------------------------------- */
/* Free all resources, and close files. */
@@ -567,8 +786,9 @@ SHPClose(SHPHandle psSHP )
free( psSHP->panRecOffset );
free( psSHP->panRecSize );
- fclose( psSHP->fpSHX );
- fclose( psSHP->fpSHP );
+ if ( psSHP->fpSHX != NULL)
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
if( psSHP->pabyRec != NULL )
{
@@ -590,6 +810,9 @@ SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
{
int i;
+
+ if( psSHP == NULL )
+ return;
if( pnEntities != NULL )
*pnEntities = psSHP->nRecords;
@@ -617,9 +840,27 @@ SHPHandle SHPAPI_CALL
SHPCreate( const char * pszLayer, int nShapeType )
{
- char *pszBasename, *pszFullname;
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return SHPCreateLL( pszLayer, nShapeType, &sHooks );
+}
+
+/************************************************************************/
+/* SHPCreate() */
+/* */
+/* Create a new shape file and return a handle to the open */
+/* shape file with read/write access. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
+
+{
+ char *pszBasename = NULL, *pszFullname = NULL;
int i;
- FILE *fpSHP, *fpSHX;
+ SAFile fpSHP = NULL, fpSHX = NULL;
uchar abyHeader[100];
int32 i32;
double dValue;
@@ -640,9 +881,9 @@ SHPCreate( const char * pszLayer, int nShapeType )
pszBasename = (char *) malloc(strlen(pszLayer)+5);
strcpy( pszBasename, pszLayer );
for( i = strlen(pszBasename)-1;
- i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
- && pszBasename[i] != '\\';
- i-- ) {}
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
if( pszBasename[i] == '.' )
pszBasename[i] = '\0';
@@ -652,23 +893,29 @@ SHPCreate( const char * pszLayer, int nShapeType )
/* -------------------------------------------------------------------- */
pszFullname = (char *) malloc(strlen(pszBasename) + 5);
sprintf( pszFullname, "%s.shp", pszBasename );
- fpSHP = fopen(pszFullname, "wb" );
+ fpSHP = psHooks->FOpen(pszFullname, "wb" );
if( fpSHP == NULL )
- return( NULL );
+ {
+ psHooks->Error( "Failed to create file .shp file." );
+ goto error;
+ }
sprintf( pszFullname, "%s.shx", pszBasename );
- fpSHX = fopen(pszFullname, "wb" );
+ fpSHX = psHooks->FOpen(pszFullname, "wb" );
if( fpSHX == NULL )
- return( NULL );
+ {
+ psHooks->Error( "Failed to create file .shx file." );
+ goto error;
+ }
- free( pszFullname );
- free( pszBasename );
+ free( pszFullname ); pszFullname = NULL;
+ free( pszBasename ); pszBasename = NULL;
/* -------------------------------------------------------------------- */
/* Prepare header block for .shp file. */
/* -------------------------------------------------------------------- */
for( i = 0; i < 100; i++ )
- abyHeader[i] = 0;
+ abyHeader[i] = 0;
abyHeader[2] = 0x27; /* magic cookie */
abyHeader[3] = 0x0a;
@@ -694,7 +941,11 @@ SHPCreate( const char * pszLayer, int nShapeType )
/* -------------------------------------------------------------------- */
/* Write .shp file header. */
/* -------------------------------------------------------------------- */
- fwrite( abyHeader, 100, 1, fpSHP );
+ if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
+ {
+ psHooks->Error( "Failed to write .shp header." );
+ goto error;
+ }
/* -------------------------------------------------------------------- */
/* Prepare, and write .shx file header. */
@@ -703,15 +954,26 @@ SHPCreate( const char * pszLayer, int nShapeType )
ByteCopy( &i32, abyHeader+24, 4 );
if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
- fwrite( abyHeader, 100, 1, fpSHX );
+ if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
+ {
+ psHooks->Error( "Failed to write .shx header." );
+ goto error;
+ }
/* -------------------------------------------------------------------- */
/* Close the files, and then open them as regular existing files. */
/* -------------------------------------------------------------------- */
- fclose( fpSHP );
- fclose( fpSHX );
+ psHooks->FClose( fpSHP );
+ psHooks->FClose( fpSHX );
- return( SHPOpen( pszLayer, "r+b" ) );
+ return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
+
+error:
+ if (pszFullname) free(pszFullname);
+ if (pszBasename) free(pszBasename);
+ if (fpSHP) psHooks->FClose( fpSHP );
+ if (fpSHX) psHooks->FClose( fpSHX );
+ return NULL;
}
/************************************************************************/
@@ -785,9 +1047,9 @@ SHPComputeExtents( SHPObject * psObject )
SHPObject SHPAPI_CALL1(*)
SHPCreateObject( int nSHPType, int nShapeId, int nParts,
- int * panPartStart, int * panPartType,
- int nVertices, double * padfX, double * padfY,
- double * padfZ, double * padfM )
+ const int * panPartStart, const int * panPartType,
+ int nVertices, const double *padfX, const double *padfY,
+ const double * padfZ, const double * padfM )
{
SHPObject *psObject;
@@ -796,6 +1058,7 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
psObject->nSHPType = nSHPType;
psObject->nShapeId = nShapeId;
+ psObject->bMeasureIsUsed = FALSE;
/* -------------------------------------------------------------------- */
/* Establish whether this shape type has M, and Z values. */
@@ -835,7 +1098,7 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
psObject->nParts = MAX(1,nParts);
psObject->panPartStart = (int *)
- malloc(sizeof(int) * psObject->nParts);
+ calloc(sizeof(int), psObject->nParts);
psObject->panPartType = (int *)
malloc(sizeof(int) * psObject->nParts);
@@ -844,17 +1107,21 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
for( i = 0; i < nParts; i++ )
{
- psObject->panPartStart[i] = panPartStart[i];
+ if( psObject->panPartStart != NULL )
+ psObject->panPartStart[i] = panPartStart[i];
+
if( panPartType != NULL )
psObject->panPartType[i] = panPartType[i];
else
psObject->panPartType[i] = SHPP_RING;
}
+
+ if( psObject->panPartStart[0] != 0 )
+ psObject->panPartStart[0] = 0;
}
/* -------------------------------------------------------------------- */
-/* Capture vertices. Note that Z and M are optional, but X and */
-/* Y are not. */
+/* Capture vertices. Note that X, Y, Z and M are optional. */
/* -------------------------------------------------------------------- */
if( nVertices > 0 )
{
@@ -863,18 +1130,19 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
psObject->padfM = (double *) calloc(sizeof(double),nVertices);
- assert( padfX != NULL );
- assert( padfY != NULL );
-
for( i = 0; i < nVertices; i++ )
{
- psObject->padfX[i] = padfX[i];
- psObject->padfY[i] = padfY[i];
+ if( padfX != NULL )
+ psObject->padfX[i] = padfX[i];
+ if( padfY != NULL )
+ psObject->padfY[i] = padfY[i];
if( padfZ != NULL && bHasZ )
psObject->padfZ[i] = padfZ[i];
if( padfM != NULL && bHasM )
psObject->padfM[i] = padfM[i];
}
+ if( padfM != NULL && bHasM )
+ psObject->bMeasureIsUsed = TRUE;
}
/* -------------------------------------------------------------------- */
@@ -895,8 +1163,8 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
SHPObject SHPAPI_CALL1(*)
SHPCreateSimpleObject( int nSHPType, int nVertices,
- double * padfX, double * padfY,
- double * padfZ )
+ const double * padfX, const double * padfY,
+ const double * padfZ )
{
return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
@@ -914,7 +1182,8 @@ int SHPAPI_CALL
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
{
- int nRecordOffset, i, nRecordSize;
+ unsigned int nRecordOffset, nRecordSize=0;
+ int i;
uchar *pabyRec;
int32 i32;
@@ -943,19 +1212,19 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
/* -------------------------------------------------------------------- */
if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
{
- psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+ psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
- psSHP->panRecOffset = (int *)
- SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
- psSHP->panRecSize = (int *)
- SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
+ psSHP->panRecOffset = (unsigned int *)
+ SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * psSHP->nMaxRecords );
+ psSHP->panRecSize = (unsigned int *)
+ SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * psSHP->nMaxRecords );
}
/* -------------------------------------------------------------------- */
/* Initialize record. */
/* -------------------------------------------------------------------- */
pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
- + psObject->nParts * 8 + 128);
+ + psObject->nParts * 8 + 128);
/* -------------------------------------------------------------------- */
/* Extract vertices for a Polygon or Arc. */
@@ -968,32 +1237,32 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
|| psObject->nSHPType == SHPT_ARCM
|| psObject->nSHPType == SHPT_MULTIPATCH )
{
- int32 nPoints, nParts;
- int i;
+ int32 nPoints, nParts;
+ int i;
- nPoints = psObject->nVertices;
- nParts = psObject->nParts;
+ nPoints = psObject->nVertices;
+ nParts = psObject->nParts;
- _SHPSetBounds( pabyRec + 12, psObject );
+ _SHPSetBounds( pabyRec + 12, psObject );
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
- ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
- ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+ ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
+ ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
nRecordSize = 52;
/*
* Write part start positions.
*/
- ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
+ ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
4 * psObject->nParts );
- for( i = 0; i < psObject->nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+ for( i = 0; i < psObject->nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
nRecordSize += 4;
- }
+ }
/*
* Write multipatch part types if needed.
@@ -1012,19 +1281,19 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
/*
* Write the (x,y) vertex values.
*/
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
- ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
- if( bBigEndian )
+ if( bBigEndian )
SwapWord( 8, pabyRec + nRecordSize );
- if( bBigEndian )
+ if( bBigEndian )
SwapWord( 8, pabyRec + nRecordSize + 8 );
nRecordSize += 2 * 8;
- }
+ }
/*
* Write the Z coordinates (if any).
@@ -1052,13 +1321,14 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
/*
* Write the M values, if any.
*/
- if( psObject->nSHPType == SHPT_POLYGONM
- || psObject->nSHPType == SHPT_ARCM
+ if( psObject->bMeasureIsUsed
+ && (psObject->nSHPType == SHPT_POLYGONM
+ || psObject->nSHPType == SHPT_ARCM
#ifndef DISABLE_MULTIPATCH_MEASURE
- || psObject->nSHPType == SHPT_MULTIPATCH
+ || psObject->nSHPType == SHPT_MULTIPATCH
#endif
- || psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_ARCZ )
+ || psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_ARCZ) )
{
ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1084,26 +1354,26 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
|| psObject->nSHPType == SHPT_MULTIPOINTZ
|| psObject->nSHPType == SHPT_MULTIPOINTM )
{
- int32 nPoints;
- int i;
+ int32 nPoints;
+ int i;
- nPoints = psObject->nVertices;
+ nPoints = psObject->nVertices;
_SHPSetBounds( pabyRec + 12, psObject );
- if( bBigEndian ) SwapWord( 4, &nPoints );
- ByteCopy( &nPoints, pabyRec + 44, 4 );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ ByteCopy( &nPoints, pabyRec + 44, 4 );
- for( i = 0; i < psObject->nVertices; i++ )
- {
- ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
- ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
- }
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+ }
- nRecordSize = 48 + 16 * psObject->nVertices;
+ nRecordSize = 48 + 16 * psObject->nVertices;
if( psObject->nSHPType == SHPT_MULTIPOINTZ )
{
@@ -1123,8 +1393,9 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
}
}
- if( psObject->nSHPType == SHPT_MULTIPOINTZ
- || psObject->nSHPType == SHPT_MULTIPOINTM )
+ if( psObject->bMeasureIsUsed
+ && (psObject->nSHPType == SHPT_MULTIPOINTZ
+ || psObject->nSHPType == SHPT_MULTIPOINTM) )
{
ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1150,11 +1421,11 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
|| psObject->nSHPType == SHPT_POINTZ
|| psObject->nSHPType == SHPT_POINTM )
{
- ByteCopy( psObject->padfX, pabyRec + 12, 8 );
- ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+ ByteCopy( psObject->padfX, pabyRec + 12, 8 );
+ ByteCopy( psObject->padfY, pabyRec + 20, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
nRecordSize = 28;
@@ -1165,8 +1436,9 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
nRecordSize += 8;
}
- if( psObject->nSHPType == SHPT_POINTZ
- || psObject->nSHPType == SHPT_POINTM )
+ if( psObject->bMeasureIsUsed
+ && (psObject->nSHPType == SHPT_POINTZ
+ || psObject->nSHPType == SHPT_POINTM) )
{
ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1195,6 +1467,18 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
/* -------------------------------------------------------------------- */
if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
{
+ unsigned int nExpectedSize = psSHP->nFileSize + nRecordSize;
+ if( nExpectedSize < psSHP->nFileSize ) // due to unsigned int overflow
+ {
+ char str[128];
+ sprintf( str, "Failed to write shape object. "
+ "File size cannot reach %u + %u.",
+ psSHP->nFileSize, nRecordSize );
+ psSHP->sHooks.Error( str );
+ free( pabyRec );
+ return -1;
+ }
+
if( nShapeId == -1 )
nShapeId = psSHP->nRecords++;
@@ -1205,6 +1489,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
else
{
nRecordOffset = psSHP->panRecOffset[nShapeId];
+ psSHP->panRecSize[nShapeId] = nRecordSize-8;
}
/* -------------------------------------------------------------------- */
@@ -1225,10 +1510,15 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
/* -------------------------------------------------------------------- */
/* Write out record. */
/* -------------------------------------------------------------------- */
- if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
- || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 )
+ {
+ psSHP->sHooks.Error( "Error in psSHP->sHooks.FSeek() while writing object to .shp file." );
+ free( pabyRec );
+ return -1;
+ }
+ if( psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
{
- printf( "Error in fseek() or fwrite().\n" );
+ psSHP->sHooks.Error( "Error in psSHP->sHooks.Fwrite() while writing object to .shp file." );
free( pabyRec );
return -1;
}
@@ -1241,25 +1531,34 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
if( psSHP->adBoundsMin[0] == 0.0
&& psSHP->adBoundsMax[0] == 0.0
&& psSHP->adBoundsMin[1] == 0.0
- && psSHP->adBoundsMax[1] == 0.0
- && psObject->nSHPType != SHPT_NULL )
+ && psSHP->adBoundsMax[1] == 0.0 )
{
- psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
- psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
- psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
- psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+ if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
+ {
+ psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
+ psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
+ psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0;
+ psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0;
+ }
+ else
+ {
+ psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
+ psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
+ psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
+ psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+ }
}
for( i = 0; i < psObject->nVertices; i++ )
{
- psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
- psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
- psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
- psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
- psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
- psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
- psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
- psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+ psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
+ psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
+ psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
+ psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
+ psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
+ psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
+ psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+ psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
}
return( nShapeId );
@@ -1276,7 +1575,9 @@ SHPObject SHPAPI_CALL1(*)
SHPReadObject( SHPHandle psSHP, int hEntity )
{
- SHPObject *psShape;
+ int nEntitySize, nRequiredSize;
+ SHPObject *psShape;
+ char szErrorMsg[128];
/* -------------------------------------------------------------------- */
/* Validate the record/entity number. */
@@ -1287,25 +1588,85 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* -------------------------------------------------------------------- */
/* Ensure our record buffer is large enough. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+ nEntitySize = psSHP->panRecSize[hEntity]+8;
+ if( nEntitySize > psSHP->nBufSize )
+ {
+ psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
+ if (psSHP->pabyRec == NULL)
+ {
+ char szError[200];
+
+ /* Reallocate previous successfull size for following features */
+ psSHP->pabyRec = (uchar *) malloc(psSHP->nBufSize);
+
+ sprintf( szError,
+ "Not enough memory to allocate requested memory (nBufSize=%d). "
+ "Probably broken SHP file", psSHP->nBufSize );
+ psSHP->sHooks.Error( szError );
+ return NULL;
+ }
+
+ /* Only set new buffer size after successfull alloc */
+ psSHP->nBufSize = nEntitySize;
+ }
+
+ /* In case we were not able to reallocate the buffer on a previous step */
+ if (psSHP->pabyRec == NULL)
{
- psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
- psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+ return NULL;
}
/* -------------------------------------------------------------------- */
/* Read the record. */
/* -------------------------------------------------------------------- */
- fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
- fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
+ {
+ /*
+ * TODO - mloskot: Consider detailed diagnostics of shape file,
+ * for example to detect if file is truncated.
+ */
+ char str[128];
+ sprintf( str,
+ "Error in fseek() reading object from .shp file at offset %u",
+ psSHP->panRecOffset[hEntity]);
+
+ psSHP->sHooks.Error( str );
+ return NULL;
+ }
+
+ if( psSHP->sHooks.FRead( psSHP->pabyRec, nEntitySize, 1, psSHP->fpSHP ) != 1 )
+ {
+ /*
+ * TODO - mloskot: Consider detailed diagnostics of shape file,
+ * for example to detect if file is truncated.
+ */
+ char str[128];
+ sprintf( str,
+ "Error in fread() reading object of size %u at offset %u from .shp file",
+ nEntitySize, psSHP->panRecOffset[hEntity] );
+
+ psSHP->sHooks.Error( str );
+ return NULL;
+ }
/* -------------------------------------------------------------------- */
/* Allocate and minimally initialize the object. */
/* -------------------------------------------------------------------- */
psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
psShape->nShapeId = hEntity;
+ psShape->bMeasureIsUsed = FALSE;
+ if ( 8 + 4 > nEntitySize )
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
/* ==================================================================== */
@@ -1318,9 +1679,18 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
|| psShape->nSHPType == SHPT_ARCM
|| psShape->nSHPType == SHPT_MULTIPATCH )
{
- int32 nPoints, nParts;
- int i, nOffset;
+ int32 nPoints, nParts;
+ int i, nOffset;
+ if ( 40 + 8 + 4 > nEntitySize )
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
/* -------------------------------------------------------------------- */
/* Get the X/Y bounds. */
/* -------------------------------------------------------------------- */
@@ -1329,30 +1699,80 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
/* -------------------------------------------------------------------- */
/* Extract part/point count, and build vertex and part arrays */
/* to proper size. */
/* -------------------------------------------------------------------- */
- memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
- memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
+ memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
+ memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
+
+ if (nPoints < 0 || nParts < 0 ||
+ nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
+ hEntity, nPoints, nParts);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
+ /* With the previous checks on nPoints and nParts, */
+ /* we should not overflow here and after */
+ /* since 50 M * (16 + 8 + 8) = 1 600 MB */
+ nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
+ if ( psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ nRequiredSize += 16 + 8 * nPoints;
+ }
+ if( psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ nRequiredSize += 4 * nParts;
+ }
+ if (nRequiredSize > nEntitySize)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
+ hEntity, nPoints, nParts, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
- psShape->nVertices = nPoints;
+ psShape->nVertices = nPoints;
psShape->padfX = (double *) calloc(nPoints,sizeof(double));
psShape->padfY = (double *) calloc(nPoints,sizeof(double));
psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
psShape->padfM = (double *) calloc(nPoints,sizeof(double));
- psShape->nParts = nParts;
+ psShape->nParts = nParts;
psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
psShape->panPartType = (int *) calloc(nParts,sizeof(int));
+
+ if (psShape->padfX == NULL ||
+ psShape->padfY == NULL ||
+ psShape->padfZ == NULL ||
+ psShape->padfM == NULL ||
+ psShape->panPartStart == NULL ||
+ psShape->panPartType == NULL)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
+ "Probably broken SHP file", hEntity, nPoints, nParts );
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
for( i = 0; i < nParts; i++ )
psShape->panPartType[i] = SHPP_RING;
@@ -1360,13 +1780,35 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* -------------------------------------------------------------------- */
/* Copy out the part array from the record. */
/* -------------------------------------------------------------------- */
- memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
- for( i = 0; i < nParts; i++ )
- {
- if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
- }
+ memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
+ for( i = 0; i < nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+
+ /* We check that the offset is inside the vertex array */
+ if (psShape->panPartStart[i] < 0
+ || (psShape->panPartStart[i] >= psShape->nVertices
+ && psShape->nVertices > 0) )
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
+ hEntity, i, psShape->panPartStart[i], psShape->nVertices);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+ if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
+ hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+ }
- nOffset = 44 + 8 + 4*nParts;
+ nOffset = 44 + 8 + 4*nParts;
/* -------------------------------------------------------------------- */
/* If this is a multipatch, we will also have parts types. */
@@ -1385,19 +1827,19 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* -------------------------------------------------------------------- */
/* Copy out the vertices from the record. */
/* -------------------------------------------------------------------- */
- for( i = 0; i < nPoints; i++ )
- {
- memcpy(psShape->padfX + i,
- psSHP->pabyRec + nOffset + i * 16,
- 8 );
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX + i,
+ psSHP->pabyRec + nOffset + i * 16,
+ 8 );
- memcpy(psShape->padfY + i,
- psSHP->pabyRec + nOffset + i * 16 + 8,
- 8 );
+ memcpy(psShape->padfY + i,
+ psSHP->pabyRec + nOffset + i * 16 + 8,
+ 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
- if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
- }
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
nOffset += 16*nPoints;
@@ -1430,7 +1872,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ if( nEntitySize >= nOffset + 16 + 8*nPoints )
{
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1444,8 +1886,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
psSHP->pabyRec + nOffset + 16 + i*8, 8 );
if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
}
+ psShape->bMeasureIsUsed = TRUE;
}
-
}
/* ==================================================================== */
@@ -1455,26 +1897,74 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
|| psShape->nSHPType == SHPT_MULTIPOINTM
|| psShape->nSHPType == SHPT_MULTIPOINTZ )
{
- int32 nPoints;
- int i, nOffset;
+ int32 nPoints;
+ int i, nOffset;
+
+ if ( 44 + 4 > nEntitySize )
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+ memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
- memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
- if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+
+ if (nPoints < 0 || nPoints > 50 * 1000 * 1000)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nPoints = %d",
+ hEntity, nPoints);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
- psShape->nVertices = nPoints;
+ nRequiredSize = 48 + nPoints * 16;
+ if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ nRequiredSize += 16 + nPoints * 8;
+ }
+ if (nRequiredSize > nEntitySize)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
+ hEntity, nPoints, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
+ psShape->nVertices = nPoints;
psShape->padfX = (double *) calloc(nPoints,sizeof(double));
psShape->padfY = (double *) calloc(nPoints,sizeof(double));
psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
psShape->padfM = (double *) calloc(nPoints,sizeof(double));
- for( i = 0; i < nPoints; i++ )
- {
- memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
- memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+ if (psShape->padfX == NULL ||
+ psShape->padfY == NULL ||
+ psShape->padfZ == NULL ||
+ psShape->padfM == NULL)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
+ "Probably broken SHP file", hEntity, nPoints );
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
+ memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
- if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
- }
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
nOffset = 48 + 16*nPoints;
@@ -1486,10 +1976,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
/* -------------------------------------------------------------------- */
/* If we have a Z coordinate, collect that now. */
@@ -1518,7 +2008,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ if( nEntitySize >= nOffset + 16 + 8*nPoints )
{
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1532,6 +2022,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
psSHP->pabyRec + nOffset + 16 + i*8, 8 );
if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
}
+ psShape->bMeasureIsUsed = TRUE;
}
}
@@ -1544,17 +2035,26 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
{
int nOffset;
- psShape->nVertices = 1;
+ psShape->nVertices = 1;
psShape->padfX = (double *) calloc(1,sizeof(double));
psShape->padfY = (double *) calloc(1,sizeof(double));
psShape->padfZ = (double *) calloc(1,sizeof(double));
psShape->padfM = (double *) calloc(1,sizeof(double));
- memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
- memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+ if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
+ {
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( szErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+ memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
+ memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfX );
- if( bBigEndian ) SwapWord( 8, psShape->padfY );
+ if( bBigEndian ) SwapWord( 8, psShape->padfX );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY );
nOffset = 20 + 8;
@@ -1576,11 +2076,12 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
+ if( nEntitySize >= nOffset + 8 )
{
memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
if( bBigEndian ) SwapWord( 8, psShape->padfM );
+ psShape->bMeasureIsUsed = TRUE;
}
/* -------------------------------------------------------------------- */
@@ -1735,6 +2236,9 @@ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
&& psObject->nSHPType != SHPT_POLYGONM )
return 0;
+ if( psObject->nVertices == 0 || psObject->nParts == 0 )
+ return 0;
+
/* -------------------------------------------------------------------- */
/* Process each of the rings. */
/* -------------------------------------------------------------------- */
@@ -1749,9 +2253,16 @@ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
/* first ring is outer and all others are inner, but eventually */
/* we need to fix this to handle multiple island polygons and */
/* unordered sets of rings. */
+/* */
/* -------------------------------------------------------------------- */
- dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]];
- dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]];
+
+ /* Use point in the middle of segment to avoid testing
+ * common points of rings.
+ */
+ dfTestX = ( psObject->padfX[psObject->panPartStart[iOpRing]]
+ + psObject->padfX[psObject->panPartStart[iOpRing] + 1] ) / 2;
+ dfTestY = ( psObject->padfY[psObject->panPartStart[iOpRing]]
+ + psObject->padfY[psObject->panPartStart[iOpRing] + 1] ) / 2;
bInner = FALSE;
for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
@@ -1779,21 +2290,31 @@ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
else
iNext = 0;
- if( (psObject->padfY[iEdge+nVertStart] < dfTestY
- && psObject->padfY[iNext+nVertStart] >= dfTestY)
- || (psObject->padfY[iNext+nVertStart] < dfTestY
- && psObject->padfY[iEdge+nVertStart] >= dfTestY) )
+ /* Rule #1:
+ * Test whether the edge 'straddles' the horizontal ray from the test point (dfTestY,dfTestY)
+ * The rule #1 also excludes edges collinear with the ray.
+ */
+ if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
+ && dfTestY <= psObject->padfY[iNext+nVertStart] )
+ || ( psObject->padfY[iNext+nVertStart] < dfTestY
+ && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
{
- if( psObject->padfX[iEdge+nVertStart]
- + (dfTestY - psObject->padfY[iEdge+nVertStart])
- / (psObject->padfY[iNext+nVertStart]
- - psObject->padfY[iEdge+nVertStart])
- * (psObject->padfX[iNext+nVertStart]
- - psObject->padfX[iEdge+nVertStart]) < dfTestX )
+ /* Rule #2:
+ * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
+ */
+ double const intersect =
+ ( psObject->padfX[iEdge+nVertStart]
+ + ( dfTestY - psObject->padfY[iEdge+nVertStart] )
+ / ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
+ * ( psObject->padfX[iNext+nVertStart] - psObject->padfX[iEdge+nVertStart] ) );
+
+ if (intersect < dfTestX)
+ {
bInner = !bInner;
- }
+ }
+ }
}
- }
+ } /* for iCheckRing */
/* -------------------------------------------------------------------- */
/* Determine the current order of this ring so we will know if */
@@ -1807,15 +2328,16 @@ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
nVertCount = psObject->panPartStart[iOpRing+1]
- psObject->panPartStart[iOpRing];
- dfSum = 0.0;
- for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
+ if (nVertCount < 2)
+ continue;
+
+ dfSum = psObject->padfX[nVertStart] * (psObject->padfY[nVertStart+1] - psObject->padfY[nVertStart+nVertCount-1]);
+ for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
{
- dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
- - psObject->padfY[iVert] * psObject->padfX[iVert+1];
+ dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] - psObject->padfY[iVert-1]);
}
- dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
- - psObject->padfY[iVert] * psObject->padfX[nVertStart];
+ dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] - psObject->padfY[iVert-1]);
/* -------------------------------------------------------------------- */
/* Reverse if necessary. */
diff --git a/shprewind b/shprewind
deleted file mode 100755
index c1f6f8c..0000000
Binary files a/shprewind and /dev/null differ
diff --git a/shprewind.c b/shprewind.c
index 503ee51..0b2f66d 100644
--- a/shprewind.c
+++ b/shprewind.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shprewind.c,v 1.2 2002/04/10 17:23:11 warmerda Exp $
+ * $Id: shprewind.c,v 1.4 2004-09-26 20:09:35 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Utility to validate and reset the winding order of rings in
@@ -35,6 +35,12 @@
******************************************************************************
*
* $Log: shprewind.c,v $
+ * Revision 1.4 2004-09-26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
+ * Revision 1.3 2004/01/09 16:39:49 fwarmerdam
+ * include standard include files
+ *
* Revision 1.2 2002/04/10 17:23:11 warmerda
* copy from source to destination now
*
@@ -43,6 +49,8 @@
*
*/
+#include <string.h>
+#include <stdlib.h>
#include "shapefil.h"
int main( int argc, char ** argv )
@@ -90,7 +98,6 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
for( i = 0; i < nEntities; i++ )
{
- int j;
SHPObject *psShape;
psShape = SHPReadObject( hSHP, i );
diff --git a/shptest.c b/shptest.c
index 83b471a..4336eea 100644
--- a/shptest.c
+++ b/shptest.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shptest.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $
+ * $Id: shptest.c,v 1.7 2004-09-26 20:09:35 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Application for generating sample Shapefiles of various types.
@@ -35,6 +35,9 @@
******************************************************************************
*
* $Log: shptest.c,v $
+ * Revision 1.7 2004-09-26 20:09:35 fwarmerdam
+ * avoid rcsid warnings
+ *
* Revision 1.6 2002/01/15 14:36:07 warmerda
* updated email address
*
@@ -55,13 +58,12 @@
*
*/
-static char rcsid[] =
- "$Id: shptest.c,v 1.6 2002/01/15 14:36:07 warmerda Exp $";
-
#include <stdlib.h>
#include <string.h>
#include "shapefil.h"
+SHP_CVSID("$Id: shptest.c,v 1.7 2004-09-26 20:09:35 fwarmerdam Exp $")
+
/************************************************************************/
/* Test_WritePoints() */
/* */
diff --git a/shptree.c b/shptree.c
index 98d5ce0..409134e 100644
--- a/shptree.c
+++ b/shptree.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shptree.c,v 1.9 2003/01/28 15:53:41 warmerda Exp $
+ * $Id: shptree.c,v 1.17 2012-01-27 21:09:26 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Implementation of quadtree building and searching functions.
@@ -34,6 +34,30 @@
******************************************************************************
*
* $Log: shptree.c,v $
+ * Revision 1.17 2012-01-27 21:09:26 fwarmerdam
+ * optimize .qix output (gdal #4472)
+ *
+ * Revision 1.16 2011-12-11 22:26:46 fwarmerdam
+ * upgrade .qix access code to use SAHooks (gdal #3365)
+ *
+ * Revision 1.15 2011-07-24 05:59:25 fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.14 2010-08-27 23:43:27 fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
+ * Revision 1.13 2010-06-29 05:50:15 fwarmerdam
+ * fix sign of Z/M comparisons in SHPCheckObjectContained (#2223)
+ *
+ * Revision 1.12 2008-11-12 15:39:50 fwarmerdam
+ * improve safety in face of buggy .shp file.
+ *
+ * Revision 1.11 2007/10/27 03:31:14 fwarmerdam
+ * limit default depth of tree to 12 levels (gdal ticket #1594)
+ *
+ * Revision 1.10 2005/01/03 22:30:13 fwarmerdam
+ * added support for saved quadtrees
+ *
* Revision 1.9 2003/01/28 15:53:41 warmerda
* Avoid build warnings.
*
@@ -63,9 +87,6 @@
*
*/
-static char rcsid[] =
- "$Id: shptree.c,v 1.9 2003/01/28 15:53:41 warmerda Exp $";
-
#include "shapefil.h"
#include <math.h>
@@ -73,11 +94,19 @@ static char rcsid[] =
#include <stdlib.h>
#include <string.h>
+#ifdef USE_CPL
+#include "cpl_error.h"
+#endif
+
+SHP_CVSID("$Id: shptree.c,v 1.17 2012-01-27 21:09:26 fwarmerdam Exp $")
+
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
+static int bBigEndian = 0;
+
/* -------------------------------------------------------------------- */
/* If the following is 0.5, nodes will be split in half. If it */
@@ -118,6 +147,8 @@ static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
SHPTreeNode *psTreeNode;
psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
+ if( NULL == psTreeNode )
+ return NULL;
psTreeNode->nShapeCount = 0;
psTreeNode->panShapeIds = NULL;
@@ -140,8 +171,8 @@ static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
/************************************************************************/
SHPTree SHPAPI_CALL1(*)
-SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
- double *padfBoundsMin, double *padfBoundsMax )
+ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+ double *padfBoundsMin, double *padfBoundsMax )
{
SHPTree *psTree;
@@ -153,10 +184,15 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
/* Allocate the tree object */
/* -------------------------------------------------------------------- */
psTree = (SHPTree *) malloc(sizeof(SHPTree));
+ if( NULL == psTree )
+ {
+ return NULL;
+ }
psTree->hSHP = hSHP;
psTree->nMaxDepth = nMaxDepth;
psTree->nDimension = nDimension;
+ psTree->nTotalCount = 0;
/* -------------------------------------------------------------------- */
/* If no max depth was defined, try to select a reasonable one */
@@ -173,18 +209,46 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
psTree->nMaxDepth += 1;
nMaxNodeCount = nMaxNodeCount * 2;
}
+
+#ifdef USE_CPL
+ CPLDebug( "Shape",
+ "Estimated spatial index tree depth: %d",
+ psTree->nMaxDepth );
+#endif
+
+ /* NOTE: Due to problems with memory allocation for deep trees,
+ * automatically estimated depth is limited up to 12 levels.
+ * See Ticket #1594 for detailed discussion.
+ */
+ if( psTree->nMaxDepth > MAX_DEFAULT_TREE_DEPTH )
+ {
+ psTree->nMaxDepth = MAX_DEFAULT_TREE_DEPTH;
+
+#ifdef USE_CPL
+ CPLDebug( "Shape",
+ "Falling back to max number of allowed index tree levels (%d).",
+ MAX_DEFAULT_TREE_DEPTH );
+#endif
+ }
}
/* -------------------------------------------------------------------- */
/* Allocate the root node. */
/* -------------------------------------------------------------------- */
psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
+ if( NULL == psTree->psRoot )
+ {
+ return NULL;
+ }
/* -------------------------------------------------------------------- */
/* Assign the bounds to the root node. If none are passed in, */
/* use the bounds of the provided file otherwise the create */
/* function will have already set the bounds. */
/* -------------------------------------------------------------------- */
+ assert( NULL != psTree );
+ assert( NULL != psTree->psRoot );
+
if( padfBoundsMin == NULL )
{
SHPGetInfo( hSHP, NULL, NULL,
@@ -206,8 +270,11 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
SHPObject *psShape;
psShape = SHPReadObject( hSHP, iShape );
- SHPTreeAddShapeId( psTree, psShape );
- SHPDestroyObject( psShape );
+ if( psShape != NULL )
+ {
+ SHPTreeAddShapeId( psTree, psShape );
+ SHPDestroyObject( psShape );
+ }
}
}
@@ -223,6 +290,8 @@ static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
{
int i;
+ assert( NULL != psTreeNode );
+
for( i = 0; i < psTreeNode->nSubNodes; i++ )
{
if( psTreeNode->apsSubNode[i] != NULL )
@@ -306,14 +375,14 @@ static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
return TRUE;
if( psObject->dfZMin < padfBoundsMin[2]
- || psObject->dfZMax < padfBoundsMax[2] )
+ || psObject->dfZMax > padfBoundsMax[2] )
return FALSE;
if( nDimension == 3 )
return TRUE;
if( psObject->dfMMin < padfBoundsMin[3]
- || psObject->dfMMax < padfBoundsMax[3] )
+ || psObject->dfMMax > padfBoundsMax[3] )
return FALSE;
return TRUE;
@@ -494,14 +563,14 @@ SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
/* -------------------------------------------------------------------- */
psTreeNode->nShapeCount++;
- psTreeNode->panShapeIds =
+ psTreeNode->panShapeIds = (int *)
SfRealloc( psTreeNode->panShapeIds,
sizeof(int) * psTreeNode->nShapeCount );
psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
if( psTreeNode->papsShapeObj != NULL )
{
- psTreeNode->papsShapeObj =
+ psTreeNode->papsShapeObj = (SHPObject **)
SfRealloc( psTreeNode->papsShapeObj,
sizeof(void *) * psTreeNode->nShapeCount );
psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
@@ -521,6 +590,8 @@ int SHPAPI_CALL
SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
{
+ psTree->nTotalCount++;
+
return( SHPTreeNodeAddShapeId( psTree->psRoot, psObject,
psTree->nMaxDepth, psTree->nDimension ) );
}
@@ -658,6 +729,29 @@ static int SHPTreeNodeTrim( SHPTreeNode * psTreeNode )
}
/* -------------------------------------------------------------------- */
+/* If the current node has 1 subnode and no shapes, promote that */
+/* subnode to the current node position. */
+/* -------------------------------------------------------------------- */
+ if( psTreeNode->nSubNodes == 1 && psTreeNode->nShapeCount == 0)
+ {
+ SHPTreeNode* psSubNode = psTreeNode->apsSubNode[0];
+
+ memcpy(psTreeNode->adfBoundsMin, psSubNode->adfBoundsMin,
+ sizeof(psSubNode->adfBoundsMin));
+ memcpy(psTreeNode->adfBoundsMax, psSubNode->adfBoundsMax,
+ sizeof(psSubNode->adfBoundsMax));
+ psTreeNode->nShapeCount = psSubNode->nShapeCount;
+ assert(psTreeNode->panShapeIds == NULL);
+ psTreeNode->panShapeIds = psSubNode->panShapeIds;
+ assert(psTreeNode->papsShapeObj == NULL);
+ psTreeNode->papsShapeObj = psSubNode->papsShapeObj;
+ psTreeNode->nSubNodes = psSubNode->nSubNodes;
+ for( i = 0; i < psSubNode->nSubNodes; i++ )
+ psTreeNode->apsSubNode[i] = psSubNode->apsSubNode[i];
+ free(psSubNode);
+ }
+
+/* -------------------------------------------------------------------- */
/* We should be trimmed if we have no subnodes, and no shapes. */
/* -------------------------------------------------------------------- */
return( psTreeNode->nSubNodes == 0 && psTreeNode->nShapeCount == 0 );
@@ -677,3 +771,417 @@ SHPTreeTrimExtraNodes( SHPTree * hTree )
SHPTreeNodeTrim( hTree->psRoot );
}
+/************************************************************************/
+/* SwapWord() */
+/* */
+/* Swap a 2, 4 or 8 byte word. */
+/************************************************************************/
+
+static void SwapWord( int length, void * wordP )
+
+{
+ int i;
+ unsigned char temp;
+
+ for( i=0; i < length/2; i++ )
+ {
+ temp = ((unsigned char *) wordP)[i];
+ ((unsigned char *)wordP)[i] = ((unsigned char *) wordP)[length-i-1];
+ ((unsigned char *) wordP)[length-i-1] = temp;
+ }
+}
+
+
+struct SHPDiskTreeInfo
+{
+ SAHooks sHooks;
+ SAFile fpQIX;
+};
+
+/************************************************************************/
+/* SHPOpenDiskTree() */
+/************************************************************************/
+
+SHPTreeDiskHandle SHPOpenDiskTree( const char* pszQIXFilename,
+ SAHooks *psHooks )
+{
+ SHPTreeDiskHandle hDiskTree;
+
+ hDiskTree = (SHPTreeDiskHandle) calloc(sizeof(struct SHPDiskTreeInfo),1);
+
+ if (psHooks == NULL)
+ SASetupDefaultHooks( &(hDiskTree->sHooks) );
+ else
+ memcpy( &(hDiskTree->sHooks), psHooks, sizeof(SAHooks) );
+
+ hDiskTree->fpQIX = hDiskTree->sHooks.FOpen(pszQIXFilename, "rb");
+ if (hDiskTree->fpQIX == NULL)
+ {
+ free(hDiskTree);
+ return NULL;
+ }
+
+ return hDiskTree;
+}
+
+/***********************************************************************/
+/* SHPCloseDiskTree() */
+/************************************************************************/
+
+void SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree )
+{
+ if (hDiskTree == NULL)
+ return;
+
+ hDiskTree->sHooks.FClose(hDiskTree->fpQIX);
+ free(hDiskTree);
+}
+
+/************************************************************************/
+/* SHPSearchDiskTreeNode() */
+/************************************************************************/
+
+static int
+SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax,
+ int **ppanResultBuffer, int *pnBufferMax,
+ int *pnResultCount, int bNeedSwap )
+
+{
+ int i;
+ int offset;
+ int numshapes, numsubnodes;
+ double adfNodeBoundsMin[2], adfNodeBoundsMax[2];
+
+/* -------------------------------------------------------------------- */
+/* Read and unswap first part of node info. */
+/* -------------------------------------------------------------------- */
+ hDiskTree->sHooks.FRead( &offset, 4, 1, hDiskTree->fpQIX );
+ if ( bNeedSwap ) SwapWord ( 4, &offset );
+
+ hDiskTree->sHooks.FRead( adfNodeBoundsMin, sizeof(double), 2, hDiskTree->fpQIX );
+ hDiskTree->sHooks.FRead( adfNodeBoundsMax, sizeof(double), 2, hDiskTree->fpQIX );
+ if ( bNeedSwap )
+ {
+ SwapWord( 8, adfNodeBoundsMin + 0 );
+ SwapWord( 8, adfNodeBoundsMin + 1 );
+ SwapWord( 8, adfNodeBoundsMax + 0 );
+ SwapWord( 8, adfNodeBoundsMax + 1 );
+ }
+
+ hDiskTree->sHooks.FRead( &numshapes, 4, 1, hDiskTree->fpQIX );
+ if ( bNeedSwap ) SwapWord ( 4, &numshapes );
+
+/* -------------------------------------------------------------------- */
+/* If we don't overlap this node at all, we can just fseek() */
+/* pass this node info and all subnodes. */
+/* -------------------------------------------------------------------- */
+ if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax,
+ padfBoundsMin, padfBoundsMax, 2 ) )
+ {
+ offset += numshapes*sizeof(int) + sizeof(int);
+ hDiskTree->sHooks.FSeek(hDiskTree->fpQIX, offset, SEEK_CUR);
+ return TRUE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add all the shapeids at this node to our list. */
+/* -------------------------------------------------------------------- */
+ if(numshapes > 0)
+ {
+ if( *pnResultCount + numshapes > *pnBufferMax )
+ {
+ *pnBufferMax = (int) ((*pnResultCount + numshapes + 100) * 1.25);
+ *ppanResultBuffer = (int *)
+ SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) );
+ }
+
+ hDiskTree->sHooks.FRead( *ppanResultBuffer + *pnResultCount,
+ sizeof(int), numshapes, hDiskTree->fpQIX );
+
+ if (bNeedSwap )
+ {
+ for( i=0; i<numshapes; i++ )
+ SwapWord( 4, *ppanResultBuffer + *pnResultCount + i );
+ }
+
+ *pnResultCount += numshapes;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Process the subnodes. */
+/* -------------------------------------------------------------------- */
+ hDiskTree->sHooks.FRead( &numsubnodes, 4, 1, hDiskTree->fpQIX );
+ if ( bNeedSwap ) SwapWord ( 4, &numsubnodes );
+
+ for(i=0; i<numsubnodes; i++)
+ {
+ if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax,
+ ppanResultBuffer, pnBufferMax,
+ pnResultCount, bNeedSwap ) )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* SHPTreeReadLibc() */
+/************************************************************************/
+
+static
+SAOffset SHPTreeReadLibc( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+ return (SAOffset) fread( p, (size_t) size, (size_t) nmemb,
+ (FILE *) file );
+}
+
+/************************************************************************/
+/* SHPTreeSeekLibc() */
+/************************************************************************/
+
+static
+SAOffset SHPTreeSeekLibc( SAFile file, SAOffset offset, int whence )
+
+{
+ return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+}
+
+/************************************************************************/
+/* SHPSearchDiskTree() */
+/************************************************************************/
+
+int SHPAPI_CALL1(*)
+SHPSearchDiskTree( FILE *fp,
+ double *padfBoundsMin, double *padfBoundsMax,
+ int *pnShapeCount )
+{
+ struct SHPDiskTreeInfo sDiskTree;
+ memset(&sDiskTree.sHooks, 0, sizeof(sDiskTree.sHooks));
+
+ /* We do not use SASetupDefaultHooks() because the FILE* */
+ /* is a libc FILE* */
+ sDiskTree.sHooks.FSeek = SHPTreeSeekLibc;
+ sDiskTree.sHooks.FRead = SHPTreeReadLibc;
+
+ sDiskTree.fpQIX = (SAFile)fp;
+
+ return SHPSearchDiskTreeEx( &sDiskTree, padfBoundsMin, padfBoundsMax,
+ pnShapeCount );
+}
+
+/***********************************************************************/
+/* SHPSearchDiskTreeEx() */
+/************************************************************************/
+
+int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
+ double *padfBoundsMin, double *padfBoundsMax,
+ int *pnShapeCount )
+
+{
+ int i, bNeedSwap, nBufferMax = 0;
+ unsigned char abyBuf[16];
+ int *panResultBuffer = NULL;
+
+ *pnShapeCount = 0;
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this machine. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((unsigned char *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Read the header. */
+/* -------------------------------------------------------------------- */
+ hDiskTree->sHooks.FSeek( hDiskTree->fpQIX, 0, SEEK_SET );
+ hDiskTree->sHooks.FRead( abyBuf, 16, 1, hDiskTree->fpQIX );
+
+ if( memcmp( abyBuf, "SQT", 3 ) != 0 )
+ return NULL;
+
+ if( (abyBuf[3] == 2 && bBigEndian)
+ || (abyBuf[3] == 1 && !bBigEndian) )
+ bNeedSwap = FALSE;
+ else
+ bNeedSwap = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Search through root node and it's decendents. */
+/* -------------------------------------------------------------------- */
+ if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax,
+ &panResultBuffer, &nBufferMax,
+ pnShapeCount, bNeedSwap ) )
+ {
+ if( panResultBuffer != NULL )
+ free( panResultBuffer );
+ *pnShapeCount = 0;
+ return NULL;
+ }
+/* -------------------------------------------------------------------- */
+/* Sort the id array */
+/* -------------------------------------------------------------------- */
+ qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints);
+
+ return panResultBuffer;
+}
+
+/************************************************************************/
+/* SHPGetSubNodeOffset() */
+/* */
+/* Determine how big all the subnodes of this node (and their */
+/* children) will be. This will allow disk based searchers to */
+/* seek past them all efficiently. */
+/************************************************************************/
+
+static int SHPGetSubNodeOffset( SHPTreeNode *node)
+{
+ int i;
+ long offset=0;
+
+ for(i=0; i<node->nSubNodes; i++ )
+ {
+ if(node->apsSubNode[i])
+ {
+ offset += 4*sizeof(double)
+ + (node->apsSubNode[i]->nShapeCount+3)*sizeof(int);
+ offset += SHPGetSubNodeOffset(node->apsSubNode[i]);
+ }
+ }
+
+ return(offset);
+}
+
+/************************************************************************/
+/* SHPWriteTreeNode() */
+/************************************************************************/
+
+static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks)
+{
+ int i,j;
+ int offset;
+ unsigned char *pabyRec = NULL;
+ assert( NULL != node );
+
+ offset = SHPGetSubNodeOffset(node);
+
+ pabyRec = (unsigned char *)
+ malloc(sizeof(double) * 4
+ + (3 * sizeof(int)) + (node->nShapeCount * sizeof(int)) );
+ if( NULL == pabyRec )
+ {
+#ifdef USE_CPL
+ CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
+#endif
+ assert( 0 );
+ return;
+ }
+
+ memcpy( pabyRec, &offset, 4);
+
+ /* minx, miny, maxx, maxy */
+ memcpy( pabyRec+ 4, node->adfBoundsMin+0, sizeof(double) );
+ memcpy( pabyRec+12, node->adfBoundsMin+1, sizeof(double) );
+ memcpy( pabyRec+20, node->adfBoundsMax+0, sizeof(double) );
+ memcpy( pabyRec+28, node->adfBoundsMax+1, sizeof(double) );
+
+ memcpy( pabyRec+36, &node->nShapeCount, 4);
+ j = node->nShapeCount * sizeof(int);
+ memcpy( pabyRec+40, node->panShapeIds, j);
+ memcpy( pabyRec+j+40, &node->nSubNodes, 4);
+
+ psHooks->FWrite( pabyRec, 44+j, 1, fp );
+ free (pabyRec);
+
+ for(i=0; i<node->nSubNodes; i++ )
+ {
+ if(node->apsSubNode[i])
+ SHPWriteTreeNode( fp, node->apsSubNode[i], psHooks);
+ }
+}
+
+/************************************************************************/
+/* SHPWriteTree() */
+/************************************************************************/
+
+int SHPAPI_CALL SHPWriteTree(SHPTree *tree, const char *filename )
+{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return SHPWriteTreeLL(tree, filename, &sHooks);
+}
+
+/************************************************************************/
+/* SHPWriteTreeLL() */
+/************************************************************************/
+
+int SHPWriteTreeLL(SHPTree *tree, const char *filename, SAHooks* psHooks )
+{
+ char signature[4] = "SQT";
+ int i;
+ char abyBuf[32];
+ SAFile fp;
+
+ SAHooks sHooks;
+ if (psHooks == NULL)
+ {
+ SASetupDefaultHooks( &sHooks );
+ psHooks = &sHooks;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Open the output file. */
+/* -------------------------------------------------------------------- */
+ fp = psHooks->FOpen(filename, "wb");
+ if( fp == NULL )
+ {
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this machine. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((unsigned char *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Write the header. */
+/* -------------------------------------------------------------------- */
+ memcpy( abyBuf+0, signature, 3 );
+
+ if( bBigEndian )
+ abyBuf[3] = 2; /* New MSB */
+ else
+ abyBuf[3] = 1; /* New LSB */
+
+ abyBuf[4] = 1; /* version */
+ abyBuf[5] = 0; /* next 3 reserved */
+ abyBuf[6] = 0;
+ abyBuf[7] = 0;
+
+ psHooks->FWrite( abyBuf, 8, 1, fp );
+
+ psHooks->FWrite( &(tree->nTotalCount), 4, 1, fp );
+
+ /* write maxdepth */
+
+ psHooks->FWrite( &(tree->nMaxDepth), 4, 1, fp );
+
+/* -------------------------------------------------------------------- */
+/* Write all the nodes "in order". */
+/* -------------------------------------------------------------------- */
+
+ SHPWriteTreeNode( fp, tree->psRoot, psHooks );
+
+ psHooks->FClose( fp );
+
+ return TRUE;
+}
diff --git a/shptreedump.c b/shptreedump.c
index caa3c7d..d5c1e3f 100644
--- a/shptreedump.c
+++ b/shptreedump.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shptreedump.c,v 1.7 2002/04/10 16:59:12 warmerda Exp $
+ * $Id: shptreedump.c,v 1.8 2005-01-03 22:30:13 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose: Mainline for creating and dumping an ASCII representation of
@@ -35,6 +35,9 @@
******************************************************************************
*
* $Log: shptreedump.c,v $
+ * Revision 1.8 2005-01-03 22:30:13 fwarmerdam
+ * added support for saved quadtrees
+ *
* Revision 1.7 2002/04/10 16:59:12 warmerda
* fixed email
*
@@ -58,14 +61,14 @@
*
*/
-static char rcsid[] =
- "$Id: shptreedump.c,v 1.7 2002/04/10 16:59:12 warmerda Exp $";
-
#include "shapefil.h"
#include <assert.h>
#include <stdlib.h>
#include <math.h>
+#include <string.h>
+
+SHP_CVSID("$Id: shptreedump.c,v 1.8 2005-01-03 22:30:13 fwarmerdam Exp $")
static void SHPTreeNodeDump( SHPTree *, SHPTreeNode *, const char *, int );
static void SHPTreeNodeSearchAndDump( SHPTree *, double *, double * );
@@ -78,7 +81,8 @@ static void Usage()
{
printf( "shptreedump [-maxdepth n] [-search xmin ymin xmax ymax]\n"
- " [-v] shp_file\n" );
+ " [-v] [-o indexfilename] [-i indexfilename]\n"
+ " shp_file\n" );
exit( 1 );
}
@@ -94,9 +98,11 @@ int main( int argc, char ** argv )
SHPTree *psTree;
int nExpandShapes = 0;
int nMaxDepth = 0;
- int nDoSearch = 0;
+ int bDoSearch = 0;
double adfSearchMin[4], adfSearchMax[4];
-
+ const char *pszOutputIndexFilename = NULL;
+ const char *pszInputIndexFilename = NULL;
+ const char *pszTargetFile = NULL;
/* -------------------------------------------------------------------- */
/* Consume flags. */
@@ -115,9 +121,21 @@ int main( int argc, char ** argv )
argv += 2;
argc -= 2;
}
+ else if( strcmp(argv[1],"-o") == 0 && argc > 2 )
+ {
+ pszOutputIndexFilename = argv[2];
+ argv += 2;
+ argc -= 2;
+ }
+ else if( strcmp(argv[1],"-i") == 0 && argc > 2 )
+ {
+ pszInputIndexFilename = argv[2];
+ argv += 2;
+ argc -= 2;
+ }
else if( strcmp(argv[1],"-search") == 0 && argc > 5 )
{
- nDoSearch = 1;
+ bDoSearch = 1;
adfSearchMin[0] = atof(argv[2]);
adfSearchMin[1] = atof(argv[3]);
@@ -137,14 +155,51 @@ int main( int argc, char ** argv )
argv += 5;
argc -= 5;
}
+ else if( pszTargetFile == NULL )
+ {
+ pszTargetFile = argv[1];
+ argv++;
+ argc--;
+ }
else
- break;
+ {
+ printf( "Unrecognised argument: %s\n", argv[1] );
+ Usage();
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Do a search with an existing index file? */
+/* -------------------------------------------------------------------- */
+ if( bDoSearch && pszInputIndexFilename != NULL )
+ {
+ FILE *fp = fopen( pszInputIndexFilename, "rb" );
+ int *panResult, nResultCount = 0, iResult;
+
+ if( fp == NULL )
+ {
+ perror( pszInputIndexFilename );
+ exit( 1 );
+ }
+
+ panResult = SHPSearchDiskTree( fp, adfSearchMin, adfSearchMax,
+ &nResultCount );
+
+ printf( "Result: " );
+ for( iResult = 0; iResult < nResultCount; iResult++ )
+ printf( "%d ", panResult[iResult] );
+ printf( "\n" );
+ free( panResult );
+
+ fclose( fp );
+
+ exit( 0 );
}
/* -------------------------------------------------------------------- */
/* Display a usage message. */
/* -------------------------------------------------------------------- */
- if( argc < 2 )
+ if( pszTargetFile == NULL )
{
Usage();
}
@@ -152,11 +207,11 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
/* Open the passed shapefile. */
/* -------------------------------------------------------------------- */
- hSHP = SHPOpen( argv[1], "rb" );
+ hSHP = SHPOpen( pszTargetFile, "rb" );
if( hSHP == NULL )
{
- printf( "Unable to open:%s\n", argv[1] );
+ printf( "Unable to open:%s\n", pszTargetFile );
exit( 1 );
}
@@ -169,11 +224,19 @@ int main( int argc, char ** argv )
/* Trim unused nodes from the tree. */
/* -------------------------------------------------------------------- */
SHPTreeTrimExtraNodes( psTree );
-
+
+/* -------------------------------------------------------------------- */
+/* Dump tree to .qix file. */
+/* -------------------------------------------------------------------- */
+ if( pszOutputIndexFilename != NULL )
+ {
+ SHPWriteTree( psTree, pszOutputIndexFilename );
+ }
+
/* -------------------------------------------------------------------- */
/* Dump tree by recursive descent. */
/* -------------------------------------------------------------------- */
- if( !nDoSearch )
+ else if( !bDoSearch )
SHPTreeNodeDump( psTree, psTree->psRoot, "", nExpandShapes );
/* -------------------------------------------------------------------- */
diff --git a/shputils.c b/shputils.c
index 2a04f5e..b2c7f06 100644
--- a/shputils.c
+++ b/shputils.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id: shputils.c,v 1.7 2003/02/25 17:20:22 warmerda Exp $
+ * $Id: shputils.c,v 1.10 2007-12-13 19:59:23 fwarmerdam Exp $
*
* Project: Shapelib
* Purpose:
@@ -53,6 +53,15 @@
******************************************************************************
*
* $Log: shputils.c,v $
+ * Revision 1.10 2007-12-13 19:59:23 fwarmerdam
+ * reindent code, avoid some warnings.
+ *
+ * Revision 1.9 2004/01/14 14:56:00 fwarmerdam
+ * Some cleanlyness improvements.
+ *
+ * Revision 1.8 2004/01/14 14:40:22 fwarmerdam
+ * Fixed exit() call to include code.
+ *
* Revision 1.7 2003/02/25 17:20:22 warmerda
* Set psCShape to NULL after SHPDestroyObject() to avoid multi-frees of
* the same memory ... as submitted by Fred Fox.
@@ -76,11 +85,12 @@
* Initial revision
*/
-static char rcsid[] =
- "$Id: shputils.c,v 1.7 2003/02/25 17:20:22 warmerda Exp $";
-
#include "shapefil.h"
#include "string.h"
+#include <stdlib.h>
+
+SHP_CVSID("$Id: shputils.c,v 1.10 2007-12-13 19:59:23 fwarmerdam Exp $")
+
#ifndef FALSE
# define FALSE 0
# define TRUE 1
@@ -112,9 +122,10 @@ char iszFormat[32], iszField[1024];
char jszFormat[32], jszField[1024];
int i, ti, iWidth, iDecimals, iRecord;
int j, tj, jWidth, jDecimals, jRecord;
-int found, newdbf;
+int clip_boundary();
+double findunit(char *unit);
void openfiles(void);
void setext(char *pt, char *ext);
int strncasecmp2(char *s1, char *s2, int n);
@@ -122,7 +133,7 @@ void mergefields(void);
void findselect(void);
void showitems(void);
int selectrec();
-int check_theme_bnd();
+void check_theme_bnd();
int clip_boundary();
void error();
@@ -257,7 +268,7 @@ int main( int argc, char ** argv )
iclip=TRUE;
} /*** End CLIP & ERASE ***/
else if (strncasecmp2(argv[i], "FACTOR",0) == 0)
- {
+ {
i++;
if (i >= argc) error();
infactor=findunit(argv[i]);
@@ -268,20 +279,20 @@ int main( int argc, char ** argv )
outfactor=findunit(argv[i]);
if (outfactor == 0)
{
- sscanf(argv[i],"%lf",&factor);
- if (factor == 0) error();
+ sscanf(argv[i],"%lf",&factor);
+ if (factor == 0) error();
}
if (factor == 0)
{
- if (infactor ==0)
- { puts("ERROR: Input unit must be defined before output unit"); exit(); }
- factor=infactor/outfactor;
+ if (infactor ==0)
+ { puts("ERROR: Input unit must be defined before output unit"); exit(1); }
+ factor=infactor/outfactor;
}
printf("Output file coordinate values will be factored by %lg\n",factor);
ifactor=(factor != 1); /* True if a valid factor */
- } /*** End FACTOR ***/
- else if (strncasecmp2(argv[i],"SHIFT",5) == 0)
- {
+ } /*** End FACTOR ***/
+ else if (strncasecmp2(argv[i],"SHIFT",5) == 0)
+ {
i++;
if (i >= argc) error();
sscanf(argv[i],"%lf",&xshift);
@@ -290,10 +301,10 @@ int main( int argc, char ** argv )
sscanf(argv[i],"%lf",&yshift);
iunit=TRUE;
printf("X Shift: %lg Y Shift: %lg\n",xshift,yshift);
- } /*** End SHIFT ***/
- else {
+ } /*** End SHIFT ***/
+ else {
printf("ERROR: Unknown function %s\n",argv[i]); error();
- }
+ }
}
/* -------------------------------------------------------------------- */
/* If there is no data in this file let the user know. */
@@ -380,6 +391,7 @@ int main( int argc, char ** argv )
switch( DBFGetFieldInfo( hDBF, i, NULL, &iWidth, &iDecimals ) )
{
case FTString:
+ case FTLogical:
DBFWriteStringAttribute(hDBFappend, jRecord, pt[i],
(DBFReadStringAttribute( hDBF, iRecord, i )) );
break;
@@ -393,6 +405,9 @@ int main( int argc, char ** argv )
DBFWriteDoubleAttribute(hDBFappend, jRecord, pt[i],
(DBFReadDoubleAttribute( hDBF, iRecord, i )) );
break;
+
+ case FTInvalid:
+ break;
}
}
}
@@ -400,7 +415,7 @@ int main( int argc, char ** argv )
/* -------------------------------------------------------------------- */
/* Change FACTOR and SHIFT coordinates of shapes if needed. */
/* -------------------------------------------------------------------- */
- if (iunit)
+ if (iunit)
{
for( j = 0; j < psCShape->nVertices; j++ )
{
@@ -441,13 +456,13 @@ int main( int argc, char ** argv )
DBFClose( hDBF );
DBFClose( hDBFappend );
if (nEntitiesAppend == 0) {
- puts("Remove the output files.");
- setext(outfile, "dbf");
- remove(outfile);
- setext(outfile, "shp");
- remove(outfile);
- setext(outfile, "shx");
- remove(outfile);
+ puts("Remove the output files.");
+ setext(outfile, "dbf");
+ remove(outfile);
+ setext(outfile, "shp");
+ remove(outfile);
+ setext(outfile, "shx");
+ remove(outfile);
}
return( 0 );
}
@@ -562,7 +577,7 @@ void mergefields()
for( i = 0; i < ti; i++ )
{
- pt[i]= -1; /* Initial pt values to -1 */
+ pt[i]= -1; /* Initial pt values to -1 */
}
/* DBF must be empty before adding items */
jRecord = DBFGetRecordCount( hDBFappend );
@@ -607,7 +622,7 @@ void mergefields()
== -1 )
{
printf( "Warning: DBFAddField(%s, TYPE:%d, WIDTH:%d DEC:%d, ITEM#:%d of %d) failed.\n",
- iszTitle, iType, iWidth, iDecimals, (i+1), (ti+1) );
+ iszTitle, iType, iWidth, iDecimals, (i+1), (ti+1) );
pt[i]=-1;
}
}
@@ -638,92 +653,96 @@ void findselect()
void showitems()
{
-char stmp[40],slow[40],shigh[40];
-double dtmp,dlow,dhigh,dsum,mean;
-long int itmp,ilow,ihigh,isum;
-long int maxrec;
-char *pt;
-
- printf("Available Items: (%d)",ti);
- maxrec = DBFGetRecordCount(hDBF);
- if (maxrec > 5000 && ! iall)
- { maxrec=5000; printf(" ** ESTIMATED RANGES (MEAN) For more records use \"All\""); }
- else { printf(" RANGES (MEAN)"); }
+ char stmp[40],slow[40],shigh[40];
+ double dtmp,dlow,dhigh,dsum,mean;
+ long int itmp,ilow,ihigh,isum;
+ long int maxrec;
+ char *pt;
+
+ printf("Available Items: (%d)",ti);
+ maxrec = DBFGetRecordCount(hDBF);
+ if (maxrec > 5000 && ! iall)
+ { maxrec=5000; printf(" ** ESTIMATED RANGES (MEAN) For more records use \"All\""); }
+ else { printf(" RANGES (MEAN)"); }
- for( i = 0; i < ti; i++ )
+ for( i = 0; i < ti; i++ )
+ {
+ switch( DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals ) )
{
- switch( DBFGetFieldInfo( hDBF, i, iszTitle, &iWidth, &iDecimals ) )
- {
- case FTString:
- strcpy(slow, "~");
- strcpy(shigh,"\0");
- printf("\n String %3d %-16s",iWidth,iszTitle);
- for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
- strncpy(stmp,DBFReadStringAttribute( hDBF, iRecord, i ),39);
- if (strcmp(stmp,"!!") > 0) {
- if (strncasecmp2(stmp,slow,0) < 0) strncpy(slow, stmp,39);
- if (strncasecmp2(stmp,shigh,0) > 0) strncpy(shigh,stmp,39);
- }
- }
- pt=slow+strlen(slow)-1;
- while(*pt == ' ') { *pt='\0'; pt--; }
- pt=shigh+strlen(shigh)-1;
- while(*pt == ' ') { *pt='\0'; pt--; }
- if (strncasecmp2(slow,shigh,0) < 0) printf("%s to %s",slow,shigh);
- else if (strncasecmp2(slow,shigh,0) == 0) printf("= %s",slow);
- else printf("No Values");
- break;
- case FTInteger:
- printf("\n Integer %3d %-16s",iWidth,iszTitle);
- ilow = 1999999999;
- ihigh= -1999999999;
- isum = 0;
- for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
- itmp = DBFReadIntegerAttribute( hDBF, iRecord, i );
- if (ilow > itmp) ilow = itmp;
- if (ihigh < itmp) ihigh = itmp;
- isum = isum + itmp;
- }
- mean=isum/maxrec;
- if (ilow < ihigh) printf("%d to %d \t(%.1f)",ilow,ihigh,mean);
- else if (ilow == ihigh) printf("= %d",ilow);
- else printf("No Values");
- break;
-
- case FTDouble:
- printf("\n Real %3d,%d %-16s",iWidth,iDecimals,iszTitle);
- dlow = 999999999999999.0;
- dhigh= -999999999999999.0;
- dsum = 0;
- for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
- dtmp = DBFReadDoubleAttribute( hDBF, iRecord, i );
- if (dlow > dtmp) dlow = dtmp;
- if (dhigh < dtmp) dhigh = dtmp;
- dsum = dsum + dtmp;
- }
- mean=dsum/maxrec;
- sprintf(stmp,"%%.%df to %%.%df \t(%%.%df)",iDecimals,iDecimals,iDecimals);
- if (dlow < dhigh) printf(stmp,dlow,dhigh,mean);
- else if (dlow == dhigh) {
- sprintf(stmp,"= %%.%df",iDecimals);
- printf(stmp,dlow);
- }
- else printf("No Values");
- break;
+ case FTString:
+ case FTLogical:
+ strcpy(slow, "~");
+ strcpy(shigh,"\0");
+ printf("\n String %3d %-16s",iWidth,iszTitle);
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ strncpy(stmp,DBFReadStringAttribute( hDBF, iRecord, i ),39);
+ if (strcmp(stmp,"!!") > 0) {
+ if (strncasecmp2(stmp,slow,0) < 0) strncpy(slow, stmp,39);
+ if (strncasecmp2(stmp,shigh,0) > 0) strncpy(shigh,stmp,39);
+ }
+ }
+ pt=slow+strlen(slow)-1;
+ while(*pt == ' ') { *pt='\0'; pt--; }
+ pt=shigh+strlen(shigh)-1;
+ while(*pt == ' ') { *pt='\0'; pt--; }
+ if (strncasecmp2(slow,shigh,0) < 0) printf("%s to %s",slow,shigh);
+ else if (strncasecmp2(slow,shigh,0) == 0) printf("= %s",slow);
+ else printf("No Values");
+ break;
+ case FTInteger:
+ printf("\n Integer %3d %-16s",iWidth,iszTitle);
+ ilow = 1999999999;
+ ihigh= -1999999999;
+ isum = 0;
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ itmp = DBFReadIntegerAttribute( hDBF, iRecord, i );
+ if (ilow > itmp) ilow = itmp;
+ if (ihigh < itmp) ihigh = itmp;
+ isum = isum + itmp;
+ }
+ mean=isum/maxrec;
+ if (ilow < ihigh) printf("%ld to %ld \t(%.1f)",ilow,ihigh,mean);
+ else if (ilow == ihigh) printf("= %ld",ilow);
+ else printf("No Values");
+ break;
- }
+ case FTDouble:
+ printf("\n Real %3d,%d %-16s",iWidth,iDecimals,iszTitle);
+ dlow = 999999999999999.0;
+ dhigh= -999999999999999.0;
+ dsum = 0;
+ for( iRecord = 0; iRecord < maxrec; iRecord++ ) {
+ dtmp = DBFReadDoubleAttribute( hDBF, iRecord, i );
+ if (dlow > dtmp) dlow = dtmp;
+ if (dhigh < dtmp) dhigh = dtmp;
+ dsum = dsum + dtmp;
+ }
+ mean=dsum/maxrec;
+ sprintf(stmp,"%%.%df to %%.%df \t(%%.%df)",iDecimals,iDecimals,iDecimals);
+ if (dlow < dhigh) printf(stmp,dlow,dhigh,mean);
+ else if (dlow == dhigh) {
+ sprintf(stmp,"= %%.%df",iDecimals);
+ printf(stmp,dlow);
+ }
+ else printf("No Values");
+ break;
+
+ case FTInvalid:
+ break;
}
- printf("\n");
+
+ }
+ printf("\n");
}
int selectrec()
{
-long int value, ty;
+ long int value, ty;
- ty = DBFGetFieldInfo( hDBF, iselectitem, NULL, &iWidth, &iDecimals);
- switch(ty)
- {
+ ty = DBFGetFieldInfo( hDBF, iselectitem, NULL, &iWidth, &iDecimals);
+ switch(ty)
+ {
case FTString:
puts("Invalid Item");
iselect=FALSE;
@@ -731,23 +750,25 @@ long int value, ty;
case FTInteger:
value = DBFReadIntegerAttribute( hDBF, iRecord, iselectitem );
for (j = 0; j<selcount; j++)
- {
- if (selectvalues[j] == value)
- if (iunselect) return(0); /* Keep this record */
- else return(1); /* Skip this record */
- }
+ {
+ if (selectvalues[j] == value)
+ {
+ if (iunselect) return(0); /* Keep this record */
+ else return(1); /* Skip this record */
+ }
+ }
break;
case FTDouble:
puts("Invalid Item");
iselect=FALSE;
break;
- }
- if (iunselect) return(1); /* Skip this record */
- else return(0); /* Keep this record */
+ }
+ if (iunselect) return(1); /* Skip this record */
+ else return(0); /* Keep this record */
}
-int check_theme_bnd()
+void check_theme_bnd()
{
if ( (adfBoundsMin[0] >= cxmin) && (adfBoundsMax[0] <= cxmax) &&
(adfBoundsMin[1] >= cymin) && (adfBoundsMax[1] <= cymax) )
@@ -769,111 +790,113 @@ int check_theme_bnd()
puts("WARNING: Theme is outside the clip area."); /** SKIP THEME **/
}
-clip_boundary()
+int clip_boundary()
{
int inside;
int prev_outside;
int i2;
int j2;
- /*** FIRST check the boundary of the feature ***/
- if ( ( (psCShape->dfXMin < cxmin) && (psCShape->dfXMax < cxmin) ) ||
- ( (psCShape->dfYMin < cymin) && (psCShape->dfYMax < cymin) ) ||
- ( (psCShape->dfXMin > cxmax) && (psCShape->dfXMax > cxmax) ) ||
- ( (psCShape->dfYMin > cymax) && (psCShape->dfYMax > cymax) ) )
- { /** Feature is totally outside clip area **/
- if (ierase) return(1); /** WRITE RECORD **/
- else return(0); /** SKIP RECORD **/
- }
+ /*** FIRST check the boundary of the feature ***/
+ if ( ( (psCShape->dfXMin < cxmin) && (psCShape->dfXMax < cxmin) ) ||
+ ( (psCShape->dfYMin < cymin) && (psCShape->dfYMax < cymin) ) ||
+ ( (psCShape->dfXMin > cxmax) && (psCShape->dfXMax > cxmax) ) ||
+ ( (psCShape->dfYMin > cymax) && (psCShape->dfYMax > cymax) ) )
+ { /** Feature is totally outside clip area **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ }
- if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
- (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
- { /** Feature is totally inside clip area **/
- if (ierase) return(0); /** SKIP RECORD **/
- else return(1); /** WRITE RECORD **/
- }
+ if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
+ (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
+ { /** Feature is totally inside clip area **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
- if (iinside)
- { /** INSIDE * Feature might touch the boundary or could be outside **/
- if (ierase) return(1); /** WRITE RECORD **/
- else return(0); /** SKIP RECORD **/
- }
+ if (iinside)
+ { /** INSIDE * Feature might touch the boundary or could be outside **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ }
- if (itouch)
- { /** TOUCH **/
- if ( ( (psCShape->dfXMin <= cxmin) || (psCShape->dfXMax >= cxmax) ) &&
- (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
- { /** Feature intersects the clip boundary only on the X axis **/
- if (ierase) return(0); /** SKIP RECORD **/
- else return(1); /** WRITE RECORD **/
- }
-
- if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
+ if (itouch)
+ { /** TOUCH **/
+ if ( ( (psCShape->dfXMin <= cxmin) || (psCShape->dfXMax >= cxmax) ) &&
+ (psCShape->dfYMin >= cymin) && (psCShape->dfYMax <= cymax) )
+ { /** Feature intersects the clip boundary only on the X axis **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+
+ if ( (psCShape->dfXMin >= cxmin) && (psCShape->dfXMax <= cxmax) &&
( (psCShape->dfYMin <= cymin) || (psCShape->dfYMax >= cymax) ) )
- { /** Feature intersects the clip boundary only on the Y axis **/
- if (ierase) return(0); /** SKIP RECORD **/
- else return(1); /** WRITE RECORD **/
- }
+ { /** Feature intersects the clip boundary only on the Y axis **/
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
- for( j2 = 0; j2 < psCShape->nVertices; j2++ )
- { /** At least one vertex must be inside the clip boundary **/
- if ( (psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax) ||
- (psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax) )
- if (ierase) return(0); /** SKIP RECORD **/
- else return(1); /** WRITE RECORD **/
- }
+ for( j2 = 0; j2 < psCShape->nVertices; j2++ )
+ { /** At least one vertex must be inside the clip boundary **/
+ if ( (psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax) ||
+ (psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax) )
+ {
+ if (ierase) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ }
+ }
- /** All vertices are outside the clip boundary **/
- if (ierase) return(1); /** WRITE RECORD **/
- else return(0); /** SKIP RECORD **/
- } /** End TOUCH **/
+ /** All vertices are outside the clip boundary **/
+ if (ierase) return(1); /** WRITE RECORD **/
+ else return(0); /** SKIP RECORD **/
+ } /** End TOUCH **/
- if (icut)
- { /** CUT **/
- /*** Check each vertex in the feature with the Boundary and "CUT" ***/
- /*** THIS CODE WAS NOT COMPLETED! READ NOTE AT THE BOTTOM ***/
- i2=0;
- prev_outside=FALSE;
- for( j2 = 0; j2 < psCShape->nVertices; j2++ )
- {
- inside = psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax &&
- psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax ;
+ if (icut)
+ { /** CUT **/
+ /*** Check each vertex in the feature with the Boundary and "CUT" ***/
+ /*** THIS CODE WAS NOT COMPLETED! READ NOTE AT THE BOTTOM ***/
+ i2=0;
+ prev_outside=FALSE;
+ for( j2 = 0; j2 < psCShape->nVertices; j2++ )
+ {
+ inside = psCShape->padfX[j2] >= cxmin && psCShape->padfX[j2] <= cxmax &&
+ psCShape->padfY[j2] >= cymin && psCShape->padfY[j2] <= cymax ;
- if (ierase) inside=(! inside);
- if (inside)
- {
- if (i2 != j2)
- {
- if (prev_outside)
- {
- /*** AddIntersection(i2); /*** Add intersection ***/
- prev_outside=FALSE;
- }
- psCShape->padfX[i2]=psCShape->padfX[j2]; /** move vertex **/
- psCShape->padfY[i2]=psCShape->padfY[j2];
- }
- i2++;
- } else {
- if ( (! prev_outside) && (j2 > 0) )
- {
- /*** AddIntersection(i2); /*** Add intersection (Watch out for j2==i2-1) ***/
- /*** Also a polygon may overlap twice and will split into a several parts ***/
- prev_outside=TRUE;
- }
- }
- }
+ if (ierase) inside=(! inside);
+ if (inside)
+ {
+ if (i2 != j2)
+ {
+ if (prev_outside)
+ {
+ /*** AddIntersection(i2); ***/ /*** Add intersection ***/
+ prev_outside=FALSE;
+ }
+ psCShape->padfX[i2]=psCShape->padfX[j2]; /** move vertex **/
+ psCShape->padfY[i2]=psCShape->padfY[j2];
+ }
+ i2++;
+ } else {
+ if ( (! prev_outside) && (j2 > 0) )
+ {
+ /*** AddIntersection(i2); ***//*** Add intersection (Watch out for j2==i2-1) ***/
+ /*** Also a polygon may overlap twice and will split into a several parts ***/
+ prev_outside=TRUE;
+ }
+ }
+ }
printf("Vertices:%d OUT:%d Number of Parts:%d\n",
- psCShape->nVertices,i2, psCShape->nParts );
+ psCShape->nVertices,i2, psCShape->nParts );
- psCShape->nVertices = i2;
+ psCShape->nVertices = i2;
- if (i2 < 2) return(0); /** SKIP RECORD **/
- /*** (WE ARE NOT CREATING INTERESECTIONS and some lines could be reduced to one point) **/
+ if (i2 < 2) return(0); /** SKIP RECORD **/
+ /*** (WE ARE NOT CREATING INTERESECTIONS and some lines could be reduced to one point) **/
- if (i2 == 0) return(0); /** SKIP RECORD **/
- else return(1); /** WRITE RECORD **/
- } /** End CUT **/
+ if (i2 == 0) return(0); /** SKIP RECORD **/
+ else return(1); /** WRITE RECORD **/
+ } /** End CUT **/
}
@@ -910,8 +933,7 @@ int j,i;
#define NKEYS (sizeof(unitkeytab) / sizeof(struct unitkey))
-findunit(unit)
- char *unit;
+double findunit(char *unit)
{
struct unitkey {
char *name;
@@ -946,65 +968,65 @@ findunit(unit)
/* Display a usage message. */
/* -------------------------------------------------------------------- */
void error()
- {
- puts( "The program will append to an existing shape file or it will" );
- puts( "create a new file if needed." );
- puts( "Only the items in the first output file will be preserved." );
- puts( "When an item does not match with the append theme then the item");
- puts( "might be placed to an existing item at the same position and type." );
- puts( " OTHER FUNCTIONS:" );
- puts( " - Describe all items in the dbase file (Use ALL for more than 5000 recs.)");
- puts( " - Select a group of shapes from a comma separated selection list.");
- puts( " - UnSelect a group of shapes from a comma separated selection list.");
- puts( " - Clip boundary extent or by theme boundary." );
- puts( " Touch writes all the shapes that touch the boundary.");
- puts( " Inside writes all the shapes that are completely within the boundary.");
- puts( " Boundary clips are only the min and max of a theme boundary." );
- puts( " - Erase boundary extent or by theme boundary." );
- puts( " Erase is the direct opposite of the Clip function." );
- puts( " - Change coordinate value units between meters and feet.");
- puts( " There is no way to determine the input unit of a shape file.");
- puts( " Skip this function if the shape file is already in the correct unit.");
- puts( " Clip and Erase will be done before the unit is changed.");
- puts( " A shift will be done after the unit is changed.");
- puts( " - Shift X and Y coordinates.\n" );
- puts( "Finally, There can only be one select or unselect in the command line.");
- puts( " There can only be one clip or erase in the command line.");
- puts( " There can only be one unit and only one shift in the command line.\n");
- puts( "Ex: shputils in.shp out.shp SELECT countycode 3,5,9,13,17,27");
- puts( " shputils in.shp out.shp CLIP 10 10 90 90 Touch FACTOR Meter Feet");
- puts( " shputils in.shp out.shp FACTOR Meter 3.0");
- puts( " shputils in.shp out.shp CLIP clip.shp Boundary Touch SHIFT 40 40");
- puts( " shputils in.shp out.shp SELECT co 112 CLIP clip.shp Boundary Touch\n");
- puts( "USAGE: shputils <DescribeShape> {ALL}");
- puts( "USAGE: shputils <InputShape> <OutShape|AppendShape>" );
- puts( " { <FACTOR> <FEET|MILES|METERS|KM> <FEET|MILES|METERS|KM|factor> }" );
- puts( " { <SHIFT> <xshift> <yshift> }" );
- puts( " { <SELECT|UNSEL> <Item> <valuelist> }" );
- puts( " { <CLIP|ERASE> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
- puts( " { <CLIP|ERASE> <theme> <BOUNDARY> <TOUCH|INSIDE|CUT> }" );
- puts( " Note: CUT is not complete and does not create intersections.");
- puts( " For more information read programmer comment.");
+{
+ puts( "The program will append to an existing shape file or it will" );
+ puts( "create a new file if needed." );
+ puts( "Only the items in the first output file will be preserved." );
+ puts( "When an item does not match with the append theme then the item");
+ puts( "might be placed to an existing item at the same position and type." );
+ puts( " OTHER FUNCTIONS:" );
+ puts( " - Describe all items in the dbase file (Use ALL for more than 5000 recs.)");
+ puts( " - Select a group of shapes from a comma separated selection list.");
+ puts( " - UnSelect a group of shapes from a comma separated selection list.");
+ puts( " - Clip boundary extent or by theme boundary." );
+ puts( " Touch writes all the shapes that touch the boundary.");
+ puts( " Inside writes all the shapes that are completely within the boundary.");
+ puts( " Boundary clips are only the min and max of a theme boundary." );
+ puts( " - Erase boundary extent or by theme boundary." );
+ puts( " Erase is the direct opposite of the Clip function." );
+ puts( " - Change coordinate value units between meters and feet.");
+ puts( " There is no way to determine the input unit of a shape file.");
+ puts( " Skip this function if the shape file is already in the correct unit.");
+ puts( " Clip and Erase will be done before the unit is changed.");
+ puts( " A shift will be done after the unit is changed.");
+ puts( " - Shift X and Y coordinates.\n" );
+ puts( "Finally, There can only be one select or unselect in the command line.");
+ puts( " There can only be one clip or erase in the command line.");
+ puts( " There can only be one unit and only one shift in the command line.\n");
+ puts( "Ex: shputils in.shp out.shp SELECT countycode 3,5,9,13,17,27");
+ puts( " shputils in.shp out.shp CLIP 10 10 90 90 Touch FACTOR Meter Feet");
+ puts( " shputils in.shp out.shp FACTOR Meter 3.0");
+ puts( " shputils in.shp out.shp CLIP clip.shp Boundary Touch SHIFT 40 40");
+ puts( " shputils in.shp out.shp SELECT co 112 CLIP clip.shp Boundary Touch\n");
+ puts( "USAGE: shputils <DescribeShape> {ALL}");
+ puts( "USAGE: shputils <InputShape> <OutShape|AppendShape>" );
+ puts( " { <FACTOR> <FEET|MILES|METERS|KM> <FEET|MILES|METERS|KM|factor> }" );
+ puts( " { <SHIFT> <xshift> <yshift> }" );
+ puts( " { <SELECT|UNSEL> <Item> <valuelist> }" );
+ puts( " { <CLIP|ERASE> <xmin> <ymin> <xmax> <ymax> <TOUCH|INSIDE|CUT> }" );
+ puts( " { <CLIP|ERASE> <theme> <BOUNDARY> <TOUCH|INSIDE|CUT> }" );
+ puts( " Note: CUT is not complete and does not create intersections.");
+ puts( " For more information read programmer comment.");
- /**** Clip functions for Polygon and Cut is not supported
- There are several web pages that describe methods of doing this function.
- It seem easy to impliment until you start writting code. I don't have the
- time to add these functions but a did leave a simple cut routine in the
- program that can be called by using CUT instead of TOUCH in the
- CLIP or ERASE functions. It does not add the intersection of the line and
- the clip box, so polygons could look incomplete and lines will come up short.
+ /**** Clip functions for Polygon and Cut is not supported
+ There are several web pages that describe methods of doing this function.
+ It seem easy to impliment until you start writting code. I don't have the
+ time to add these functions but a did leave a simple cut routine in the
+ program that can be called by using CUT instead of TOUCH in the
+ CLIP or ERASE functions. It does not add the intersection of the line and
+ the clip box, so polygons could look incomplete and lines will come up short.
- Information about clipping lines with a box:
- http://www.csclub.uwaterloo.ca/u/mpslager/articles/sutherland/wr.html
- Information about finding the intersection of two lines:
- http://www.whisqu.se/per/docs/math28.htm
+ Information about clipping lines with a box:
+ http://www.csclub.uwaterloo.ca/u/mpslager/articles/sutherland/wr.html
+ Information about finding the intersection of two lines:
+ http://www.whisqu.se/per/docs/math28.htm
-THE CODE LOOKS LIKE THIS:
- ********************************************************
-void Intersect_Lines(float x0,float y0,float x1,float y1,
- float x2,float y2,float x3,float y3,
- float *xi,float *yi)
- {
+ THE CODE LOOKS LIKE THIS:
+ ********************************************************
+ void Intersect_Lines(float x0,float y0,float x1,float y1,
+ float x2,float y2,float x3,float y3,
+ float *xi,float *yi)
+ {
// this function computes the intersection of the sent lines
// and returns the intersection point, note that the function assumes
// the lines intersect. the function can handle vertical as well
@@ -1014,22 +1036,22 @@ void Intersect_Lines(float x0,float y0,float x1,float y1,
// The Intersect_lines program came from (http://www.whisqu.se/per/docs/math28.htm)
float a1,b1,c1, // constants of linear equations
- a2,b2,c2,
- det_inv, // the inverse of the determinant of the coefficientmatrix
- m1,m2; // the slopes of each line
+a2,b2,c2,
+det_inv, // the inverse of the determinant of the coefficientmatrix
+m1,m2; // the slopes of each line
// compute slopes, note the cludge for infinity, however, this will
// be close enough
if ((x1-x0)!=0)
- m1 = (y1-y0)/(x1-x0);
+m1 = (y1-y0)/(x1-x0);
else
- m1 = (float)1e+10; // close enough to infinity
+m1 = (float)1e+10; // close enough to infinity
if ((x3-x2)!=0)
- m2 = (y3-y2)/(x3-x2);
+m2 = (y3-y2)/(x3-x2);
else
- m2 = (float)1e+10; // close enough to infinity
+m2 = (float)1e+10; // close enough to infinity
// compute constants
a1 = m1;
@@ -1044,7 +1066,7 @@ det_inv = 1/(a1*b2 - a2*b1);
*xi=((b1*c2 - b2*c1)*det_inv);
*yi=((a2*c1 - a1*c2)*det_inv);
} // end Intersect_Lines
- **********************************************************/
+ **********************************************************/
- exit( 1 );
- }
+ exit( 1 );
+}
diff --git a/stream2.out b/stream2.out
index 424a9e6..249f8b8 100644
--- a/stream2.out
+++ b/stream2.out
@@ -3,528 +3,528 @@ Test 2/0
-----------------------------------------------------------------------
Shapefile Type: NullShape # of Shapes: 2
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 10.000, 20.000,0,0)
+File Bounds: (0,0,0,0)
+ to (10,20,0,0)
Shape:0 (NullShape) nVertices=0, nParts=0
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 0.000, 0.000, 0, 0)
+ Bounds:(0,0, 0)
+ to (0,0, 0)
Shape:1 (NullShape) nVertices=0, nParts=0
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 0.000, 0.000, 0, 0)
+ Bounds:(0,0, 0)
+ to (0,0, 0)
-----------------------------------------------------------------------
Test 2/1
-----------------------------------------------------------------------
Shapefile Type: Point # of Shapes: 2
-File Bounds: ( 1.000, 2.000,0,0)
- to ( 10.000, 20.000,0,0)
+File Bounds: (1,2,0,0)
+ to (10,20,0,0)
Shape:0 (Point) nVertices=1, nParts=0
- Bounds:( 1.000, 2.000, 0, 0)
- to ( 1.000, 2.000, 0, 0)
- ( 1.000, 2.000, 0, 0)
+ Bounds:(1,2, 0)
+ to (1,2, 0)
+ (1,2, 0)
Shape:1 (Point) nVertices=1, nParts=0
- Bounds:( 10.000, 20.000, 0, 0)
- to ( 10.000, 20.000, 0, 0)
- ( 10.000, 20.000, 0, 0)
+ Bounds:(10,20, 0)
+ to (10,20, 0)
+ (10,20, 0)
-----------------------------------------------------------------------
Test 2/2
-----------------------------------------------------------------------
Shapefile Type: PointZ # of Shapes: 2
-File Bounds: ( 1.000, 2.000,3,4)
- to ( 10.000, 20.000,30,40)
+File Bounds: (1,2,3,4)
+ to (10,20,30,40)
Shape:0 (PointZ) nVertices=1, nParts=0
- Bounds:( 1.000, 2.000, 3, 4)
- to ( 1.000, 2.000, 3, 4)
- ( 1.000, 2.000, 3, 4)
+ Bounds:(1,2, 3, 4)
+ to (1,2, 3, 4)
+ (1,2, 3, 4)
Shape:1 (PointZ) nVertices=1, nParts=0
- Bounds:( 10.000, 20.000, 30, 40)
- to ( 10.000, 20.000, 30, 40)
- ( 10.000, 20.000, 30, 40)
+ Bounds:(10,20, 30, 40)
+ to (10,20, 30, 40)
+ (10,20, 30, 40)
-----------------------------------------------------------------------
Test 2/3
-----------------------------------------------------------------------
Shapefile Type: PointM # of Shapes: 2
-File Bounds: ( 1.000, 2.000,0,4)
- to ( 10.000, 20.000,0,40)
+File Bounds: (1,2,0,4)
+ to (10,20,0,40)
Shape:0 (PointM) nVertices=1, nParts=0
- Bounds:( 1.000, 2.000, 0, 4)
- to ( 1.000, 2.000, 0, 4)
- ( 1.000, 2.000, 0, 4)
+ Bounds:(1,2, 0, 4)
+ to (1,2, 0, 4)
+ (1,2, 0, 4)
Shape:1 (PointM) nVertices=1, nParts=0
- Bounds:( 10.000, 20.000, 0, 40)
- to ( 10.000, 20.000, 0, 40)
- ( 10.000, 20.000, 0, 40)
+ Bounds:(10,20, 0, 40)
+ to (10,20, 0, 40)
+ (10,20, 0, 40)
-----------------------------------------------------------------------
Test 2/4
-----------------------------------------------------------------------
Shapefile Type: MultiPoint # of Shapes: 3
-File Bounds: ( 1.150, 2.250,0,0)
- to ( 24.150, 25.250,0,0)
+File Bounds: (1.15,2.25,0,0)
+ to (24.15,25.25,0,0)
Shape:0 (MultiPoint) nVertices=4, nParts=0
- Bounds:( 1.150, 2.250, 0, 0)
- to ( 4.150, 5.250, 0, 0)
- ( 1.150, 2.250, 0, 0)
- ( 2.150, 3.250, 0, 0)
- ( 3.150, 4.250, 0, 0)
- ( 4.150, 5.250, 0, 0)
+ Bounds:(1.15,2.25, 0)
+ to (4.15,5.25, 0)
+ (1.15,2.25, 0)
+ (2.15,3.25, 0)
+ (3.15,4.25, 0)
+ (4.15,5.25, 0)
Shape:1 (MultiPoint) nVertices=4, nParts=0
- Bounds:( 11.150, 12.250, 0, 0)
- to ( 14.150, 15.250, 0, 0)
- ( 11.150, 12.250, 0, 0)
- ( 12.150, 13.250, 0, 0)
- ( 13.150, 14.250, 0, 0)
- ( 14.150, 15.250, 0, 0)
+ Bounds:(11.15,12.25, 0)
+ to (14.15,15.25, 0)
+ (11.15,12.25, 0)
+ (12.15,13.25, 0)
+ (13.15,14.25, 0)
+ (14.15,15.25, 0)
Shape:2 (MultiPoint) nVertices=4, nParts=0
- Bounds:( 21.150, 22.250, 0, 0)
- to ( 24.150, 25.250, 0, 0)
- ( 21.150, 22.250, 0, 0)
- ( 22.150, 23.250, 0, 0)
- ( 23.150, 24.250, 0, 0)
- ( 24.150, 25.250, 0, 0)
+ Bounds:(21.15,22.25, 0)
+ to (24.15,25.25, 0)
+ (21.15,22.25, 0)
+ (22.15,23.25, 0)
+ (23.15,24.25, 0)
+ (24.15,25.25, 0)
-----------------------------------------------------------------------
Test 2/5
-----------------------------------------------------------------------
Shapefile Type: MultiPointZ # of Shapes: 3
-File Bounds: ( 1.150, 2.250,3.35,4.45)
- to ( 24.150, 25.250,26.35,27.45)
+File Bounds: (1.15,2.25,3.35,4.45)
+ to (24.15,25.25,26.35,27.45)
Shape:0 (MultiPointZ) nVertices=4, nParts=0
- Bounds:( 1.150, 2.250, 3.35, 4.45)
- to ( 4.150, 5.250, 6.35, 7.45)
- ( 1.150, 2.250, 3.35, 4.45)
- ( 2.150, 3.250, 4.35, 5.45)
- ( 3.150, 4.250, 5.35, 6.45)
- ( 4.150, 5.250, 6.35, 7.45)
+ Bounds:(1.15,2.25, 3.35, 4.45)
+ to (4.15,5.25, 6.35, 7.45)
+ (1.15,2.25, 3.35, 4.45)
+ (2.15,3.25, 4.35, 5.45)
+ (3.15,4.25, 5.35, 6.45)
+ (4.15,5.25, 6.35, 7.45)
Shape:1 (MultiPointZ) nVertices=4, nParts=0
- Bounds:( 11.150, 12.250, 13.35, 14.45)
- to ( 14.150, 15.250, 16.35, 17.45)
- ( 11.150, 12.250, 13.35, 14.45)
- ( 12.150, 13.250, 14.35, 15.45)
- ( 13.150, 14.250, 15.35, 16.45)
- ( 14.150, 15.250, 16.35, 17.45)
+ Bounds:(11.15,12.25, 13.35, 14.45)
+ to (14.15,15.25, 16.35, 17.45)
+ (11.15,12.25, 13.35, 14.45)
+ (12.15,13.25, 14.35, 15.45)
+ (13.15,14.25, 15.35, 16.45)
+ (14.15,15.25, 16.35, 17.45)
Shape:2 (MultiPointZ) nVertices=4, nParts=0
- Bounds:( 21.150, 22.250, 23.35, 24.45)
- to ( 24.150, 25.250, 26.35, 27.45)
- ( 21.150, 22.250, 23.35, 24.45)
- ( 22.150, 23.250, 24.35, 25.45)
- ( 23.150, 24.250, 25.35, 26.45)
- ( 24.150, 25.250, 26.35, 27.45)
+ Bounds:(21.15,22.25, 23.35, 24.45)
+ to (24.15,25.25, 26.35, 27.45)
+ (21.15,22.25, 23.35, 24.45)
+ (22.15,23.25, 24.35, 25.45)
+ (23.15,24.25, 25.35, 26.45)
+ (24.15,25.25, 26.35, 27.45)
-----------------------------------------------------------------------
Test 2/6
-----------------------------------------------------------------------
Shapefile Type: MultiPointM # of Shapes: 3
-File Bounds: ( 1.150, 2.250,0,4.45)
- to ( 24.150, 25.250,0,27.45)
+File Bounds: (1.15,2.25,0,4.45)
+ to (24.15,25.25,0,27.45)
Shape:0 (MultiPointM) nVertices=4, nParts=0
- Bounds:( 1.150, 2.250, 0, 4.45)
- to ( 4.150, 5.250, 0, 7.45)
- ( 1.150, 2.250, 0, 4.45)
- ( 2.150, 3.250, 0, 5.45)
- ( 3.150, 4.250, 0, 6.45)
- ( 4.150, 5.250, 0, 7.45)
+ Bounds:(1.15,2.25, 0, 4.45)
+ to (4.15,5.25, 0, 7.45)
+ (1.15,2.25, 0, 4.45)
+ (2.15,3.25, 0, 5.45)
+ (3.15,4.25, 0, 6.45)
+ (4.15,5.25, 0, 7.45)
Shape:1 (MultiPointM) nVertices=4, nParts=0
- Bounds:( 11.150, 12.250, 0, 14.45)
- to ( 14.150, 15.250, 0, 17.45)
- ( 11.150, 12.250, 0, 14.45)
- ( 12.150, 13.250, 0, 15.45)
- ( 13.150, 14.250, 0, 16.45)
- ( 14.150, 15.250, 0, 17.45)
+ Bounds:(11.15,12.25, 0, 14.45)
+ to (14.15,15.25, 0, 17.45)
+ (11.15,12.25, 0, 14.45)
+ (12.15,13.25, 0, 15.45)
+ (13.15,14.25, 0, 16.45)
+ (14.15,15.25, 0, 17.45)
Shape:2 (MultiPointM) nVertices=4, nParts=0
- Bounds:( 21.150, 22.250, 0, 24.45)
- to ( 24.150, 25.250, 0, 27.45)
- ( 21.150, 22.250, 0, 24.45)
- ( 22.150, 23.250, 0, 25.45)
- ( 23.150, 24.250, 0, 26.45)
- ( 24.150, 25.250, 0, 27.45)
+ Bounds:(21.15,22.25, 0, 24.45)
+ to (24.15,25.25, 0, 27.45)
+ (21.15,22.25, 0, 24.45)
+ (22.15,23.25, 0, 25.45)
+ (23.15,24.25, 0, 26.45)
+ (24.15,25.25, 0, 27.45)
-----------------------------------------------------------------------
Test 2/7
-----------------------------------------------------------------------
Shapefile Type: Arc # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,0,0)
+File Bounds: (0,0,0,0)
+ to (100,100,0,0)
Shape:0 (Arc) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 0, 0)
- to ( 2.000, 2.000, 0, 0)
- ( 1.000, 1.000, 0, 0) Ring
- ( 2.000, 1.000, 0, 0)
- ( 2.000, 2.000, 0, 0)
- ( 1.000, 2.000, 0, 0)
- ( 1.000, 1.000, 0, 0)
+ Bounds:(1,1, 0)
+ to (2,2, 0)
+ (1,1, 0) Ring
+ (2,1, 0)
+ (2,2, 0)
+ (1,2, 0)
+ (1,1, 0)
Shape:1 (Arc) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 0, 0)
- to ( 2.000, 5.000, 0, 0)
- ( 1.000, 4.000, 0, 0) Ring
- ( 2.000, 4.000, 0, 0)
- ( 2.000, 5.000, 0, 0)
- ( 1.000, 5.000, 0, 0)
- ( 1.000, 4.000, 0, 0)
+ Bounds:(1,4, 0)
+ to (2,5, 0)
+ (1,4, 0) Ring
+ (2,4, 0)
+ (2,5, 0)
+ (1,5, 0)
+ (1,4, 0)
Shape:2 (Arc) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 0, 0)
- to ( 2.000, 8.000, 0, 0)
- ( 1.000, 7.000, 0, 0) Ring
- ( 2.000, 7.000, 0, 0)
- ( 2.000, 8.000, 0, 0)
- ( 1.000, 8.000, 0, 0)
- ( 1.000, 7.000, 0, 0)
+ Bounds:(1,7, 0)
+ to (2,8, 0)
+ (1,7, 0) Ring
+ (2,7, 0)
+ (2,8, 0)
+ (1,8, 0)
+ (1,7, 0)
Shape:3 (Arc) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 0, 0)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 0, 0)
- ( 100.000, 100.000, 0, 0)
- ( 100.000, 0.000, 0, 0)
- ( 0.000, 0.000, 0, 0)
- + ( 10.000, 20.000, 0, 0) Ring
- ( 30.000, 20.000, 0, 0)
- ( 30.000, 40.000, 0, 0)
- ( 10.000, 40.000, 0, 0)
- ( 10.000, 20.000, 0, 0)
- + ( 60.000, 20.000, 0, 0) Ring
- ( 90.000, 20.000, 0, 0)
- ( 90.000, 40.000, 0, 0)
- ( 60.000, 40.000, 0, 0)
- ( 60.000, 20.000, 0, 0)
+ Bounds:(0,0, 0)
+ to (100,100, 0)
+ (0,0, 0) Ring
+ (0,100, 0)
+ (100,100, 0)
+ (100,0, 0)
+ (0,0, 0)
+ + (10,20, 0) Ring
+ (30,20, 0)
+ (30,40, 0)
+ (10,40, 0)
+ (10,20, 0)
+ + (60,20, 0) Ring
+ (90,20, 0)
+ (90,40, 0)
+ (60,40, 0)
+ (60,20, 0)
-----------------------------------------------------------------------
Test 2/8
-----------------------------------------------------------------------
Shapefile Type: ArcZ # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,27.35,28.45)
+File Bounds: (0,0,0,0)
+ to (100,100,27.35,28.45)
Shape:0 (ArcZ) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 3.35, 4.45)
- to ( 2.000, 2.000, 7.35, 8.45)
- ( 1.000, 1.000, 3.35, 4.45) Ring
- ( 2.000, 1.000, 4.35, 5.45)
- ( 2.000, 2.000, 5.35, 6.45)
- ( 1.000, 2.000, 6.35, 7.45)
- ( 1.000, 1.000, 7.35, 8.45)
+ Bounds:(1,1, 3.35, 4.45)
+ to (2,2, 7.35, 8.45)
+ (1,1, 3.35, 4.45) Ring
+ (2,1, 4.35, 5.45)
+ (2,2, 5.35, 6.45)
+ (1,2, 6.35, 7.45)
+ (1,1, 7.35, 8.45)
Shape:1 (ArcZ) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 13.35, 14.45)
- to ( 2.000, 5.000, 17.35, 18.45)
- ( 1.000, 4.000, 13.35, 14.45) Ring
- ( 2.000, 4.000, 14.35, 15.45)
- ( 2.000, 5.000, 15.35, 16.45)
- ( 1.000, 5.000, 16.35, 17.45)
- ( 1.000, 4.000, 17.35, 18.45)
+ Bounds:(1,4, 13.35, 14.45)
+ to (2,5, 17.35, 18.45)
+ (1,4, 13.35, 14.45) Ring
+ (2,4, 14.35, 15.45)
+ (2,5, 15.35, 16.45)
+ (1,5, 16.35, 17.45)
+ (1,4, 17.35, 18.45)
Shape:2 (ArcZ) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 23.35, 24.45)
- to ( 2.000, 8.000, 27.35, 28.45)
- ( 1.000, 7.000, 23.35, 24.45) Ring
- ( 2.000, 7.000, 24.35, 25.45)
- ( 2.000, 8.000, 25.35, 26.45)
- ( 1.000, 8.000, 26.35, 27.45)
- ( 1.000, 7.000, 27.35, 28.45)
+ Bounds:(1,7, 23.35, 24.45)
+ to (2,8, 27.35, 28.45)
+ (1,7, 23.35, 24.45) Ring
+ (2,7, 24.35, 25.45)
+ (2,8, 25.35, 26.45)
+ (1,8, 26.35, 27.45)
+ (1,7, 27.35, 28.45)
Shape:3 (ArcZ) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 14, 28)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 1, 2)
- ( 100.000, 100.000, 2, 4)
- ( 100.000, 0.000, 3, 6)
- ( 0.000, 0.000, 4, 8)
- + ( 10.000, 20.000, 5, 10) Ring
- ( 30.000, 20.000, 6, 12)
- ( 30.000, 40.000, 7, 14)
- ( 10.000, 40.000, 8, 16)
- ( 10.000, 20.000, 9, 18)
- + ( 60.000, 20.000, 10, 20) Ring
- ( 90.000, 20.000, 11, 22)
- ( 90.000, 40.000, 12, 24)
- ( 60.000, 40.000, 13, 26)
- ( 60.000, 20.000, 14, 28)
+ Bounds:(0,0, 0, 0)
+ to (100,100, 14, 28)
+ (0,0, 0, 0) Ring
+ (0,100, 1, 2)
+ (100,100, 2, 4)
+ (100,0, 3, 6)
+ (0,0, 4, 8)
+ + (10,20, 5, 10) Ring
+ (30,20, 6, 12)
+ (30,40, 7, 14)
+ (10,40, 8, 16)
+ (10,20, 9, 18)
+ + (60,20, 10, 20) Ring
+ (90,20, 11, 22)
+ (90,40, 12, 24)
+ (60,40, 13, 26)
+ (60,20, 14, 28)
-----------------------------------------------------------------------
Test 2/9
-----------------------------------------------------------------------
Shapefile Type: ArcM # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,0,28.45)
+File Bounds: (0,0,0,0)
+ to (100,100,0,28.45)
Shape:0 (ArcM) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 0, 4.45)
- to ( 2.000, 2.000, 0, 8.45)
- ( 1.000, 1.000, 0, 4.45) Ring
- ( 2.000, 1.000, 0, 5.45)
- ( 2.000, 2.000, 0, 6.45)
- ( 1.000, 2.000, 0, 7.45)
- ( 1.000, 1.000, 0, 8.45)
+ Bounds:(1,1, 0, 4.45)
+ to (2,2, 0, 8.45)
+ (1,1, 0, 4.45) Ring
+ (2,1, 0, 5.45)
+ (2,2, 0, 6.45)
+ (1,2, 0, 7.45)
+ (1,1, 0, 8.45)
Shape:1 (ArcM) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 0, 14.45)
- to ( 2.000, 5.000, 0, 18.45)
- ( 1.000, 4.000, 0, 14.45) Ring
- ( 2.000, 4.000, 0, 15.45)
- ( 2.000, 5.000, 0, 16.45)
- ( 1.000, 5.000, 0, 17.45)
- ( 1.000, 4.000, 0, 18.45)
+ Bounds:(1,4, 0, 14.45)
+ to (2,5, 0, 18.45)
+ (1,4, 0, 14.45) Ring
+ (2,4, 0, 15.45)
+ (2,5, 0, 16.45)
+ (1,5, 0, 17.45)
+ (1,4, 0, 18.45)
Shape:2 (ArcM) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 0, 24.45)
- to ( 2.000, 8.000, 0, 28.45)
- ( 1.000, 7.000, 0, 24.45) Ring
- ( 2.000, 7.000, 0, 25.45)
- ( 2.000, 8.000, 0, 26.45)
- ( 1.000, 8.000, 0, 27.45)
- ( 1.000, 7.000, 0, 28.45)
+ Bounds:(1,7, 0, 24.45)
+ to (2,8, 0, 28.45)
+ (1,7, 0, 24.45) Ring
+ (2,7, 0, 25.45)
+ (2,8, 0, 26.45)
+ (1,8, 0, 27.45)
+ (1,7, 0, 28.45)
Shape:3 (ArcM) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 0, 28)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 0, 2)
- ( 100.000, 100.000, 0, 4)
- ( 100.000, 0.000, 0, 6)
- ( 0.000, 0.000, 0, 8)
- + ( 10.000, 20.000, 0, 10) Ring
- ( 30.000, 20.000, 0, 12)
- ( 30.000, 40.000, 0, 14)
- ( 10.000, 40.000, 0, 16)
- ( 10.000, 20.000, 0, 18)
- + ( 60.000, 20.000, 0, 20) Ring
- ( 90.000, 20.000, 0, 22)
- ( 90.000, 40.000, 0, 24)
- ( 60.000, 40.000, 0, 26)
- ( 60.000, 20.000, 0, 28)
+ Bounds:(0,0, 0, 0)
+ to (100,100, 0, 28)
+ (0,0, 0, 0) Ring
+ (0,100, 0, 2)
+ (100,100, 0, 4)
+ (100,0, 0, 6)
+ (0,0, 0, 8)
+ + (10,20, 0, 10) Ring
+ (30,20, 0, 12)
+ (30,40, 0, 14)
+ (10,40, 0, 16)
+ (10,20, 0, 18)
+ + (60,20, 0, 20) Ring
+ (90,20, 0, 22)
+ (90,40, 0, 24)
+ (60,40, 0, 26)
+ (60,20, 0, 28)
-----------------------------------------------------------------------
Test 2/10
-----------------------------------------------------------------------
Shapefile Type: Polygon # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,0,0)
+File Bounds: (0,0,0,0)
+ to (100,100,0,0)
Shape:0 (Polygon) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 0, 0)
- to ( 2.000, 2.000, 0, 0)
- ( 1.000, 1.000, 0, 0) Ring
- ( 2.000, 1.000, 0, 0)
- ( 2.000, 2.000, 0, 0)
- ( 1.000, 2.000, 0, 0)
- ( 1.000, 1.000, 0, 0)
+ Bounds:(1,1, 0)
+ to (2,2, 0)
+ (1,1, 0) Ring
+ (2,1, 0)
+ (2,2, 0)
+ (1,2, 0)
+ (1,1, 0)
Shape:1 (Polygon) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 0, 0)
- to ( 2.000, 5.000, 0, 0)
- ( 1.000, 4.000, 0, 0) Ring
- ( 2.000, 4.000, 0, 0)
- ( 2.000, 5.000, 0, 0)
- ( 1.000, 5.000, 0, 0)
- ( 1.000, 4.000, 0, 0)
+ Bounds:(1,4, 0)
+ to (2,5, 0)
+ (1,4, 0) Ring
+ (2,4, 0)
+ (2,5, 0)
+ (1,5, 0)
+ (1,4, 0)
Shape:2 (Polygon) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 0, 0)
- to ( 2.000, 8.000, 0, 0)
- ( 1.000, 7.000, 0, 0) Ring
- ( 2.000, 7.000, 0, 0)
- ( 2.000, 8.000, 0, 0)
- ( 1.000, 8.000, 0, 0)
- ( 1.000, 7.000, 0, 0)
+ Bounds:(1,7, 0)
+ to (2,8, 0)
+ (1,7, 0) Ring
+ (2,7, 0)
+ (2,8, 0)
+ (1,8, 0)
+ (1,7, 0)
Shape:3 (Polygon) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 0, 0)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 0, 0)
- ( 100.000, 100.000, 0, 0)
- ( 100.000, 0.000, 0, 0)
- ( 0.000, 0.000, 0, 0)
- + ( 10.000, 20.000, 0, 0) Ring
- ( 30.000, 20.000, 0, 0)
- ( 30.000, 40.000, 0, 0)
- ( 10.000, 40.000, 0, 0)
- ( 10.000, 20.000, 0, 0)
- + ( 60.000, 20.000, 0, 0) Ring
- ( 90.000, 20.000, 0, 0)
- ( 90.000, 40.000, 0, 0)
- ( 60.000, 40.000, 0, 0)
- ( 60.000, 20.000, 0, 0)
+ Bounds:(0,0, 0)
+ to (100,100, 0)
+ (0,0, 0) Ring
+ (0,100, 0)
+ (100,100, 0)
+ (100,0, 0)
+ (0,0, 0)
+ + (10,20, 0) Ring
+ (30,20, 0)
+ (30,40, 0)
+ (10,40, 0)
+ (10,20, 0)
+ + (60,20, 0) Ring
+ (90,20, 0)
+ (90,40, 0)
+ (60,40, 0)
+ (60,20, 0)
-----------------------------------------------------------------------
Test 2/11
-----------------------------------------------------------------------
Shapefile Type: PolygonZ # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,27.35,28.45)
+File Bounds: (0,0,0,0)
+ to (100,100,27.35,28.45)
Shape:0 (PolygonZ) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 3.35, 4.45)
- to ( 2.000, 2.000, 7.35, 8.45)
- ( 1.000, 1.000, 3.35, 4.45) Ring
- ( 2.000, 1.000, 4.35, 5.45)
- ( 2.000, 2.000, 5.35, 6.45)
- ( 1.000, 2.000, 6.35, 7.45)
- ( 1.000, 1.000, 7.35, 8.45)
+ Bounds:(1,1, 3.35, 4.45)
+ to (2,2, 7.35, 8.45)
+ (1,1, 3.35, 4.45) Ring
+ (2,1, 4.35, 5.45)
+ (2,2, 5.35, 6.45)
+ (1,2, 6.35, 7.45)
+ (1,1, 7.35, 8.45)
Shape:1 (PolygonZ) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 13.35, 14.45)
- to ( 2.000, 5.000, 17.35, 18.45)
- ( 1.000, 4.000, 13.35, 14.45) Ring
- ( 2.000, 4.000, 14.35, 15.45)
- ( 2.000, 5.000, 15.35, 16.45)
- ( 1.000, 5.000, 16.35, 17.45)
- ( 1.000, 4.000, 17.35, 18.45)
+ Bounds:(1,4, 13.35, 14.45)
+ to (2,5, 17.35, 18.45)
+ (1,4, 13.35, 14.45) Ring
+ (2,4, 14.35, 15.45)
+ (2,5, 15.35, 16.45)
+ (1,5, 16.35, 17.45)
+ (1,4, 17.35, 18.45)
Shape:2 (PolygonZ) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 23.35, 24.45)
- to ( 2.000, 8.000, 27.35, 28.45)
- ( 1.000, 7.000, 23.35, 24.45) Ring
- ( 2.000, 7.000, 24.35, 25.45)
- ( 2.000, 8.000, 25.35, 26.45)
- ( 1.000, 8.000, 26.35, 27.45)
- ( 1.000, 7.000, 27.35, 28.45)
+ Bounds:(1,7, 23.35, 24.45)
+ to (2,8, 27.35, 28.45)
+ (1,7, 23.35, 24.45) Ring
+ (2,7, 24.35, 25.45)
+ (2,8, 25.35, 26.45)
+ (1,8, 26.35, 27.45)
+ (1,7, 27.35, 28.45)
Shape:3 (PolygonZ) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 14, 28)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 1, 2)
- ( 100.000, 100.000, 2, 4)
- ( 100.000, 0.000, 3, 6)
- ( 0.000, 0.000, 4, 8)
- + ( 10.000, 20.000, 5, 10) Ring
- ( 30.000, 20.000, 6, 12)
- ( 30.000, 40.000, 7, 14)
- ( 10.000, 40.000, 8, 16)
- ( 10.000, 20.000, 9, 18)
- + ( 60.000, 20.000, 10, 20) Ring
- ( 90.000, 20.000, 11, 22)
- ( 90.000, 40.000, 12, 24)
- ( 60.000, 40.000, 13, 26)
- ( 60.000, 20.000, 14, 28)
+ Bounds:(0,0, 0, 0)
+ to (100,100, 14, 28)
+ (0,0, 0, 0) Ring
+ (0,100, 1, 2)
+ (100,100, 2, 4)
+ (100,0, 3, 6)
+ (0,0, 4, 8)
+ + (10,20, 5, 10) Ring
+ (30,20, 6, 12)
+ (30,40, 7, 14)
+ (10,40, 8, 16)
+ (10,20, 9, 18)
+ + (60,20, 10, 20) Ring
+ (90,20, 11, 22)
+ (90,40, 12, 24)
+ (60,40, 13, 26)
+ (60,20, 14, 28)
-----------------------------------------------------------------------
Test 2/12
-----------------------------------------------------------------------
Shapefile Type: PolygonM # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,0,28.45)
+File Bounds: (0,0,0,0)
+ to (100,100,0,28.45)
Shape:0 (PolygonM) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 0, 4.45)
- to ( 2.000, 2.000, 0, 8.45)
- ( 1.000, 1.000, 0, 4.45) Ring
- ( 2.000, 1.000, 0, 5.45)
- ( 2.000, 2.000, 0, 6.45)
- ( 1.000, 2.000, 0, 7.45)
- ( 1.000, 1.000, 0, 8.45)
+ Bounds:(1,1, 0, 4.45)
+ to (2,2, 0, 8.45)
+ (1,1, 0, 4.45) Ring
+ (2,1, 0, 5.45)
+ (2,2, 0, 6.45)
+ (1,2, 0, 7.45)
+ (1,1, 0, 8.45)
Shape:1 (PolygonM) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 0, 14.45)
- to ( 2.000, 5.000, 0, 18.45)
- ( 1.000, 4.000, 0, 14.45) Ring
- ( 2.000, 4.000, 0, 15.45)
- ( 2.000, 5.000, 0, 16.45)
- ( 1.000, 5.000, 0, 17.45)
- ( 1.000, 4.000, 0, 18.45)
+ Bounds:(1,4, 0, 14.45)
+ to (2,5, 0, 18.45)
+ (1,4, 0, 14.45) Ring
+ (2,4, 0, 15.45)
+ (2,5, 0, 16.45)
+ (1,5, 0, 17.45)
+ (1,4, 0, 18.45)
Shape:2 (PolygonM) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 0, 24.45)
- to ( 2.000, 8.000, 0, 28.45)
- ( 1.000, 7.000, 0, 24.45) Ring
- ( 2.000, 7.000, 0, 25.45)
- ( 2.000, 8.000, 0, 26.45)
- ( 1.000, 8.000, 0, 27.45)
- ( 1.000, 7.000, 0, 28.45)
+ Bounds:(1,7, 0, 24.45)
+ to (2,8, 0, 28.45)
+ (1,7, 0, 24.45) Ring
+ (2,7, 0, 25.45)
+ (2,8, 0, 26.45)
+ (1,8, 0, 27.45)
+ (1,7, 0, 28.45)
Shape:3 (PolygonM) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 0, 28)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 0, 2)
- ( 100.000, 100.000, 0, 4)
- ( 100.000, 0.000, 0, 6)
- ( 0.000, 0.000, 0, 8)
- + ( 10.000, 20.000, 0, 10) Ring
- ( 30.000, 20.000, 0, 12)
- ( 30.000, 40.000, 0, 14)
- ( 10.000, 40.000, 0, 16)
- ( 10.000, 20.000, 0, 18)
- + ( 60.000, 20.000, 0, 20) Ring
- ( 90.000, 20.000, 0, 22)
- ( 90.000, 40.000, 0, 24)
- ( 60.000, 40.000, 0, 26)
- ( 60.000, 20.000, 0, 28)
+ Bounds:(0,0, 0, 0)
+ to (100,100, 0, 28)
+ (0,0, 0, 0) Ring
+ (0,100, 0, 2)
+ (100,100, 0, 4)
+ (100,0, 0, 6)
+ (0,0, 0, 8)
+ + (10,20, 0, 10) Ring
+ (30,20, 0, 12)
+ (30,40, 0, 14)
+ (10,40, 0, 16)
+ (10,20, 0, 18)
+ + (60,20, 0, 20) Ring
+ (90,20, 0, 22)
+ (90,40, 0, 24)
+ (60,40, 0, 26)
+ (60,20, 0, 28)
-----------------------------------------------------------------------
Test 2/13
-----------------------------------------------------------------------
Shapefile Type: MultiPatch # of Shapes: 4
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 100.000, 100.000,27.35,28.45)
+File Bounds: (0,0,0,0)
+ to (100,100,27.35,28.45)
Shape:0 (MultiPatch) nVertices=5, nParts=1
- Bounds:( 1.000, 1.000, 3.35, 0)
- to ( 2.000, 2.000, 7.35, 0)
- ( 1.000, 1.000, 3.35, 0) Ring
- ( 2.000, 1.000, 4.35, 0)
- ( 2.000, 2.000, 5.35, 0)
- ( 1.000, 2.000, 6.35, 0)
- ( 1.000, 1.000, 7.35, 0)
+ Bounds:(1,1, 3.35)
+ to (2,2, 7.35)
+ (1,1, 3.35) Ring
+ (2,1, 4.35)
+ (2,2, 5.35)
+ (1,2, 6.35)
+ (1,1, 7.35)
Shape:1 (MultiPatch) nVertices=5, nParts=1
- Bounds:( 1.000, 4.000, 13.35, 0)
- to ( 2.000, 5.000, 17.35, 0)
- ( 1.000, 4.000, 13.35, 0) Ring
- ( 2.000, 4.000, 14.35, 0)
- ( 2.000, 5.000, 15.35, 0)
- ( 1.000, 5.000, 16.35, 0)
- ( 1.000, 4.000, 17.35, 0)
+ Bounds:(1,4, 13.35)
+ to (2,5, 17.35)
+ (1,4, 13.35) Ring
+ (2,4, 14.35)
+ (2,5, 15.35)
+ (1,5, 16.35)
+ (1,4, 17.35)
Shape:2 (MultiPatch) nVertices=5, nParts=1
- Bounds:( 1.000, 7.000, 23.35, 0)
- to ( 2.000, 8.000, 27.35, 0)
- ( 1.000, 7.000, 23.35, 0) Ring
- ( 2.000, 7.000, 24.35, 0)
- ( 2.000, 8.000, 25.35, 0)
- ( 1.000, 8.000, 26.35, 0)
- ( 1.000, 7.000, 27.35, 0)
+ Bounds:(1,7, 23.35)
+ to (2,8, 27.35)
+ (1,7, 23.35) Ring
+ (2,7, 24.35)
+ (2,8, 25.35)
+ (1,8, 26.35)
+ (1,7, 27.35)
Shape:3 (MultiPatch) nVertices=15, nParts=3
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 14, 0)
- ( 0.000, 0.000, 0, 0) Ring
- ( 0.000, 100.000, 1, 0)
- ( 100.000, 100.000, 2, 0)
- ( 100.000, 0.000, 3, 0)
- ( 0.000, 0.000, 4, 0)
- + ( 10.000, 20.000, 5, 0) InnerRing
- ( 30.000, 20.000, 6, 0)
- ( 30.000, 40.000, 7, 0)
- ( 10.000, 40.000, 8, 0)
- ( 10.000, 20.000, 9, 0)
- + ( 60.000, 20.000, 10, 0) InnerRing
- ( 90.000, 20.000, 11, 0)
- ( 90.000, 40.000, 12, 0)
- ( 60.000, 40.000, 13, 0)
- ( 60.000, 20.000, 14, 0)
+ Bounds:(0,0, 0)
+ to (100,100, 14)
+ (0,0, 0) Ring
+ (0,100, 1)
+ (100,100, 2)
+ (100,0, 3)
+ (0,0, 4)
+ + (10,20, 5) InnerRing
+ (30,20, 6)
+ (30,40, 7)
+ (10,40, 8)
+ (10,20, 9)
+ + (60,20, 10) InnerRing
+ (90,20, 11)
+ (90,40, 12)
+ (60,40, 13)
+ (60,20, 14)
diff --git a/stream3.out b/stream3.out
index b668233..1ab8af4 100644
--- a/stream3.out
+++ b/stream3.out
@@ -1,36 +1,36 @@
Shapefile Type: Polygon # of Shapes: 3
-File Bounds: ( 0.000, 0.000,0,0)
- to ( 180.000, 170.000,0,0)
+File Bounds: (0,0,0,0)
+ to (180,170,0,0)
Shape:0 (Polygon) nVertices=9, nParts=2
- Bounds:( 0.000, 0.000, 0, 0)
- to ( 100.000, 100.000, 0, 0)
- ( 0.000, 0.000, 0, 0) Ring
- ( 100.000, 0.000, 0, 0)
- ( 100.000, 100.000, 0, 0)
- ( 0.000, 100.000, 0, 0)
- ( 0.000, 0.000, 0, 0)
- + ( 20.000, 20.000, 0, 0) Ring
- ( 20.000, 30.000, 0, 0)
- ( 30.000, 30.000, 0, 0)
- ( 20.000, 20.000, 0, 0)
+ Bounds:(0,0, 0)
+ to (100,100, 0)
+ (0,0, 0) Ring
+ (100,0, 0)
+ (100,100, 0)
+ (0,100, 0)
+ (0,0, 0)
+ + (20,20, 0) Ring
+ (20,30, 0)
+ (30,30, 0)
+ (20,20, 0)
Shape:1 (Polygon) nVertices=4, nParts=1
- Bounds:( 150.000, 150.000, 0, 0)
- to ( 180.000, 170.000, 0, 0)
- ( 150.000, 150.000, 0, 0) Ring
- ( 160.000, 150.000, 0, 0)
- ( 180.000, 170.000, 0, 0)
- ( 150.000, 150.000, 0, 0)
+ Bounds:(150,150, 0)
+ to (180,170, 0)
+ (150,150, 0) Ring
+ (160,150, 0)
+ (180,170, 0)
+ (150,150, 0)
Shape:2 (Polygon) nVertices=4, nParts=1
- Bounds:( 150.000, 150.000, 0, 0)
- to ( 180.000, 170.000, 0, 0)
- ( 150.000, 150.000, 0, 0) Ring
- ( 160.000, 150.000, 0, 0)
- ( 180.000, 170.000, 0, 0)
- ( 150.000, 150.000, 0, 0)
+ Bounds:(150,150, 0)
+ to (180,170, 0)
+ (150,150, 0) Ring
+ (160,150, 0)
+ (180,170, 0)
+ (150,150, 0)
Descriptio TestInt TestDouble
Square with triangle missing 1 2.50000
Smaller triangle 100 1000.25000
diff --git a/web/.cvsignore b/web/.cvsignore
new file mode 100644
index 0000000..d6ffe8d
--- /dev/null
+++ b/web/.cvsignore
@@ -0,0 +1,2 @@
+robots.txt
+dl
diff --git a/web/codepage.html b/web/codepage.html
new file mode 100644
index 0000000..23a9cfb
--- /dev/null
+++ b/web/codepage.html
@@ -0,0 +1,403 @@
+
+This table is derived from:<p>
+
+<a href="http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM">http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM</a><p>
+
+
+<table border="1" width="100%">
+ <tbody><tr>
+ <th colspan="2" align="left" bgcolor="#c0c0c0">ID</th>
+ <th align="left" bgcolor="#c0c0c0">Codepage</th>
+ <th align="left" bgcolor="#c0c0c0">Description</th>
+ </tr>
+ <tr>
+ <td>1</td>
+ <td>0x01</td>
+ <td>437</td>
+ <td>US MS-DOS</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>0x02</td>
+ <td>850</td>
+ <td>International MS-DOS</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td>0x03</td>
+ <td>1252</td>
+ <td>Windows ANSI Latin I</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td>0x04</td>
+ <td>10000</td>
+ <td>Standard Macintosh</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>0x08</td>
+ <td>865</td>
+ <td>Danish OEM</td>
+ </tr>
+ <tr>
+ <td>9</td>
+ <td>0x09</td>
+ <td>437</td>
+ <td>Dutch OEM</td>
+ </tr>
+ <tr>
+ <td>10</td>
+ <td>0x0A</td>
+ <td>850</td>
+ <td>Dutch OEM*</td>
+ </tr>
+ <tr>
+ <td>11</td>
+ <td>0x0B</td>
+ <td>437</td>
+ <td>Finnish OEM</td>
+ </tr>
+ <tr>
+ <td>13</td>
+ <td>0x0D</td>
+ <td>437</td>
+ <td>French OEM</td>
+ </tr>
+ <tr>
+ <td>14</td>
+ <td>0x0E</td>
+ <td>850</td>
+ <td>French OEM*</td>
+ </tr>
+ <tr>
+ <td>15</td>
+ <td>0x0F</td>
+ <td>437</td>
+ <td>German OEM</td>
+ </tr>
+ <tr>
+ <td>16</td>
+ <td>0x10</td>
+ <td>850</td>
+ <td>German OEM*</td>
+ </tr>
+ <tr>
+ <td>17</td>
+ <td>0x11</td>
+ <td>437</td>
+ <td>Italian OEM</td>
+ </tr>
+ <tr>
+ <td>18</td>
+ <td>0x12</td>
+ <td>850</td>
+ <td>Italian OEM*</td>
+ </tr>
+ <tr>
+ <td>19</td>
+ <td>0x13</td>
+ <td>932</td>
+ <td>Japanese Shift-JIS</td>
+ </tr>
+ <tr>
+ <td>20</td>
+ <td>0x14</td>
+ <td>850</td>
+ <td>Spanish OEM*</td>
+ </tr>
+ <tr>
+ <td>21</td>
+ <td>0x15</td>
+ <td>437</td>
+ <td>Swedish OEM</td>
+ </tr>
+ <tr>
+ <td>22</td>
+ <td>0x16</td>
+ <td>850</td>
+ <td>Swedish OEM*</td>
+ </tr>
+ <tr>
+ <td>23</td>
+ <td>0x17</td>
+ <td>865</td>
+ <td>Norwegian OEM</td>
+ </tr>
+ <tr>
+ <td>24</td>
+ <td>0x18</td>
+ <td>437</td>
+ <td>Spanish OEM</td>
+ </tr>
+ <tr>
+ <td>25</td>
+ <td>0x19</td>
+ <td>437</td>
+ <td>English OEM (Great Britain)</td>
+ </tr>
+ <tr>
+ <td>26</td>
+ <td>0x1A</td>
+ <td>850</td>
+ <td>English OEM (Great Britain)*</td>
+ </tr>
+ <tr>
+ <td>27</td>
+ <td>0x1B</td>
+ <td>437</td>
+ <td>English OEM (US)</td>
+ </tr>
+ <tr>
+ <td>28</td>
+ <td>0x1C</td>
+ <td>863</td>
+ <td>French OEM (Canada)</td>
+ </tr>
+ <tr>
+ <td>29</td>
+ <td>0x1D</td>
+ <td>850</td>
+ <td>French OEM*</td>
+ </tr>
+ <tr>
+ <td>31</td>
+ <td>0x1F</td>
+ <td>852</td>
+ <td>Czech OEM</td>
+ </tr>
+ <tr>
+ <td>34</td>
+ <td>0x22</td>
+ <td>852</td>
+ <td>Hungarian OEM</td>
+ </tr>
+ <tr>
+ <td>35</td>
+ <td>0x23</td>
+ <td>852</td>
+ <td>Polish OEM</td>
+ </tr>
+ <tr>
+ <td>36</td>
+ <td>0x24</td>
+ <td>860</td>
+ <td>Portuguese OEM</td>
+ </tr>
+ <tr>
+ <td>37</td>
+ <td>0x25</td>
+ <td>850</td>
+ <td>Portuguese OEM*</td>
+ </tr>
+ <tr>
+ <td>38</td>
+ <td>0x26</td>
+ <td>866</td>
+ <td>Russian OEM</td>
+ </tr>
+ <tr>
+ <td>55</td>
+ <td>0x37</td>
+ <td>850</td>
+ <td>English OEM (US)*</td>
+ </tr>
+ <tr>
+ <td>64</td>
+ <td>0x40</td>
+ <td>852</td>
+ <td>Romanian OEM</td>
+ </tr>
+ <tr>
+ <td>77</td>
+ <td>0x4D</td>
+ <td>936</td>
+ <td>Chinese GBK (PRC)</td>
+ </tr>
+ <tr>
+ <td>78</td>
+ <td>0x4E</td>
+ <td>949</td>
+ <td>Korean (ANSI/OEM)</td>
+ </tr>
+ <tr>
+ <td>79</td>
+ <td>0x4F</td>
+ <td>950</td>
+ <td>Chinese Big5 (Taiwan)</td>
+ </tr>
+ <tr>
+ <td>80</td>
+ <td>0x50</td>
+ <td>874</td>
+ <td>Thai (ANSI/OEM)</td>
+ </tr>
+ <tr>
+ <td>87</td>
+ <td>0x57</td>
+ <td>Current ANSI CP</td>
+ <td>ANSI</td>
+ </tr>
+ <tr>
+ <td>88</td>
+ <td>0x58</td>
+ <td>1252</td>
+ <td>Western European ANSI</td>
+ </tr>
+ <tr>
+ <td>89</td>
+ <td>0x59</td>
+ <td>1252</td>
+ <td>Spanish ANSI</td>
+ </tr>
+ <tr>
+ <td>100</td>
+ <td>0x64</td>
+ <td>852</td>
+ <td>Eastern European MS-DOS</td>
+ </tr>
+ <tr>
+ <td>101</td>
+ <td>0x65</td>
+ <td>866</td>
+ <td>Russian MS-DOS</td>
+ </tr>
+ <tr>
+ <td>102</td>
+ <td>0x66</td>
+ <td>865</td>
+ <td>Nordic MS-DOS</td>
+ </tr>
+ <tr>
+ <td>103</td>
+ <td>0x67</td>
+ <td>861</td>
+ <td>Icelandic MS-DOS</td>
+ </tr>
+ <tr>
+ <td>104</td>
+ <td>0x68</td>
+ <td>895</td>
+ <td>Kamenicky (Czech) MS-DOS</td>
+ </tr>
+ <tr>
+ <td>105</td>
+ <td>0x69</td>
+ <td>620</td>
+ <td>Mazovia (Polish) MS-DOS</td>
+ </tr>
+ <tr>
+ <td>106</td>
+ <td>0x6A</td>
+ <td>737</td>
+ <td>Greek MS-DOS (437G)</td>
+ </tr>
+ <tr>
+ <td>107</td>
+ <td>0x6B</td>
+ <td>857</td>
+ <td>Turkish MS-DOS</td>
+ </tr>
+ <tr>
+ <td>108</td>
+ <td>0x6C</td>
+ <td>863</td>
+ <td>French-Canadian MS-DOS</td>
+ </tr>
+ <tr>
+ <td>120</td>
+ <td>0x78</td>
+ <td>950</td>
+ <td>Taiwan Big 5</td>
+ </tr>
+ <tr>
+ <td>121</td>
+ <td>0x79</td>
+ <td>949</td>
+ <td>Hangul (Wansung)</td>
+ </tr>
+ <tr>
+ <td>122</td>
+ <td>0x7A</td>
+ <td>936</td>
+ <td>PRC GBK</td>
+ </tr>
+ <tr>
+ <td>123</td>
+ <td>0x7B</td>
+ <td>932</td>
+ <td>Japanese Shift-JIS</td>
+ </tr>
+ <tr>
+ <td>124</td>
+ <td>0x7C</td>
+ <td>874</td>
+ <td>Thai Windows/MSDOS</td>
+ </tr>
+ <tr>
+ <td>134</td>
+ <td>0x86</td>
+ <td>737</td>
+ <td>Greek OEM</td>
+ </tr>
+ <tr>
+ <td>135</td>
+ <td>0x87</td>
+ <td>852</td>
+ <td>Slovenian OEM</td>
+ </tr>
+ <tr>
+ <td>136</td>
+ <td>0x88</td>
+ <td>857</td>
+ <td>Turkish OEM</td>
+ </tr>
+ <tr>
+ <td>150</td>
+ <td>0x96</td>
+ <td>10007</td>
+ <td>Russian Macintosh</td>
+ </tr>
+ <tr>
+ <td>151</td>
+ <td>0x97</td>
+ <td>10029</td>
+ <td>Eastern European Macintosh</td>
+ </tr>
+ <tr>
+ <td>152</td>
+ <td>0x98</td>
+ <td>10006</td>
+ <td>Greek Macintosh</td>
+ </tr>
+ <tr>
+ <td>200</td>
+ <td>0xC8</td>
+ <td>1250</td>
+ <td>Eastern European Windows</td>
+ </tr>
+ <tr>
+ <td>201</td>
+ <td>0xC9</td>
+ <td>1251</td>
+ <td>Russian Windows</td>
+ </tr>
+ <tr>
+ <td>202</td>
+ <td>0xCA</td>
+ <td>1254</td>
+ <td>Turkish Windows</td>
+ </tr>
+ <tr>
+ <td>203</td>
+ <td>0xCB</td>
+ <td>1253</td>
+ <td>Greek Windows</td>
+ </tr>
+ <tr>
+ <td>204</td>
+ <td>0xCC</td>
+ <td>1257</td>
+ <td>Baltic Windows</td>
+ </tr>
+</tbody></table>
diff --git a/dbf_api.html b/web/dbf_api.html
similarity index 95%
rename from dbf_api.html
rename to web/dbf_api.html
index b0fa373..f7a311b 100644
--- a/dbf_api.html
+++ b/web/dbf_api.html
@@ -381,6 +381,34 @@ void DBFClose( DBFHandle hDBF );
<!-------------------------------------------------------------------------->
+<h2>DBFIsRecordDeleted()</h2>
+
+<pre>
+int DBFIsRecordDeleted( DBFHandle hDBF, int iShape );
+
+ hDBF: The access handle for the file to be checked.
+ iShape: The record index to check.
+</pre>
+
+ Returns TRUE (non-zero) if the record is marked for deletion, otherwise
+ it returns FALSE.<p>
+
+<!-------------------------------------------------------------------------->
+
+<h2>DBFMarkRecordDeleted()</h2>
+
+<pre>
+int DBFMarkRecordDeleted( DBFHandle hDBF, int iShape, int bIsDeleted );
+
+ hDBF: The access handle for the file.
+ iShape: The record index to update.
+ bIsDeleted: TRUE to mark record deleted, or FALSE to undelete it.
+</pre>
+
+ Returns TRUE on success, or FALSE on error.<p>
+
+<!-------------------------------------------------------------------------->
+
<h2>DBFGetNativeFieldType()</h2>
<pre>
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000..2015283
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,235 @@
+<html>
+<head>
+<title>Shapefile C Library V1.2</title>
+<link href="http://www.maptools.org/maptools.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>Shapefile C Library V1.2</h1>
+
+<h2>Purpose</h2>
+
+The Shapefile C Library provides the ability to write simple C programs
+for reading, writing and updating (to a limited extent) ESRI Shapefiles,
+and the associated attribute file (.dbf).<p>
+
+<h2>Supporting Information</h2>
+
+<ul>
+<li> <a href="shp_api.html">Shapefile API Docs</a>
+<li> <a href="dbf_api.html">DBF/xBase API Docs</a>
+<li> <a href="shapelib-tools.html">Shapefile Tools Docs</a>
+<li> <a href="release.html">Release Notes</a>
+<li> <a href="manifest.html">Shapelib File Manifest</a>
+<li> <a href="license.html">Shapelib Licensing Terms</a>
+</ul>
+
+<h2>What is a Shapefile?</h2>
+
+If you don't know, you probably don't need this library. The Shapefile
+format is a working and interchange format promulagated by
+<a href="http://www.esri.com/">ESRI</a> for simple vector data with attributes.
+<p>
+
+An excellent <a href="dl/shapefile.pdf">white paper</a> on the shapefile format
+is available from ESRI,
+but it is .pdf format, so you will need Adobe Acrobat to browse it.<p>
+
+The file format actually consists of three files.<p>
+
+<pre>
+XXX.shp - holds the actual vertices.
+XXX.shx - hold index data pointing to the structures in the .shp file.
+XXX.dbf - holds the attributes in xBase (dBase) format.
+</pre>
+
+<h2>Download</h2>
+
+Source code, and some other odds and ends can be downloaded from
+<a href="http://download.osgeo.org/shapelib">http://download.osgeo.org/shapelib</a> or <a href="http://shapelib.maptools.org/dl">http://shapelib.maptools.org/dl</a>.<p>
+
+Shapelib is available for anonymous CVS access:
+
+<pre>
+ cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot login
+ Password: (hit enter)
+ cvs -d :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot co shapelib
+</pre>
+
+<h2>Bugs, Maintainance and Support</h2>
+
+This library is maintained by <a href="http://pobox.com/~warmerdam">Frank
+Warmerdam</a>. Please send me bug reports, patches and suggestions for the
+library via the <a href="http://bugzilla.maptools.org/enter_bug.cgi?product=Shapelib">maptools.org Bugzilla</a>. Shapelib bugs can also be
+<a href="http://bugzilla.maptools.org/query.cgi?product=Shapelib">queried</a>.
+<p>
+
+Shapelib is hosted at
+<a href="http://shapelib.maptools.org">shapelib.maptools.org</a>. A mailing
+list for discussion of how to use shapelib, and announcing new releases
+<a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is
+available</a>. To only find out about new releases of Shapelib select the
+"<i>Subscribe to new releases</i>" option from the link at
+<a href="http://freshmeat.net/projects/shapelib/">Freshmeat</a>.<p>
+
+<h2>Credits</h2>
+
+I didn't start this section anywhere near soon enough, so alot of earlier
+contributors to Shapelib are lost in pre-history.
+
+<ul>
+<li> Bill Miller (NY-DOT) for shputils.c
+<li> Carl Anderson for the contents of the contrib directory, and
+the "tuple" additions to dbfopen.c.
+<li> Andrea Giacomelli for patches for dbfopen.c.
+<li> Doug Matthews for portability improvements.
+<li> Jan-Oliver Wagner for convincing me to make it available under LGPL,
+shared library support, and various other patches.
+<li> Dennis Christopher (of Avenza) for testing and bug fixes.
+<li> Miko Syrjä (of 3D-system Oy) for a record size bug fix.
+<li> Steven Lime and Curtis Hill for help with NULL shapes.
+<li> Jim Matthews for support of NULL attributes in dbf files.
+<li> <a href="http://www.pcigeomatics.com/">PCI Geomatics</a> who let me
+release a modified version of their shapefile code in the beginning and
+who hosted shapelib for years.
+</ul>
+
+<h2>In Memorium</h2>
+
+I would like to dedicate Shapelib to the memory of Sol Katz. While I never
+met him in person, his generous contributions to the GIS community took
+many forms, including free distribution of a variety of GIS translators
+with source. The fact that he used this Shapelib in some of his utilities,
+and thanked me was a great encouragement to me. I hope I can do his memory
+honour by trying to contribute in a similar fashion.<p>
+
+<h2>Portability</h2>
+
+The Shapefile C Library should port easily to 32bit systems with ANSI C
+compilers. It should work on 64 bit architectures (such as the DEC AXP).<p>
+
+Care should also be taken to pass the binary access flag into SHPOpen()
+and DBFOpen() when operating on systems with special text file translation
+such as MSDOS.<p>
+
+The shputils.c module is contributed, and may not take the same approach
+to portability as the rest of the package.<p>
+
+On Linux, and most unix systems it should be possible to build and
+install shapefile support as a shared library using the "lib" and "lib_install"
+targets of the Makefile. Note that this Makefile doesn't use autoconf
+mechanisms and will generally require some hand tailoring for your environment.
+
+<h2>Limitations</h2>
+
+<ul>
+
+<li> You can't modify the vertices of existing structures (though you
+ can update the attributes of existing structures, and create new
+ structures).<p>
+
+<li> Not written in such a way as to be particularly fast. This is
+particularly true of the 1.2 API. For applications more concerned with
+speed it may be worth using the V1.1 API.<p>
+
+<li> Doesn't set the last access time properly in the .dbf files.<p>
+
+<li> There is no way to synchronize information to the file except to close it.
+<p>
+
+<li> Poor error checking and reporting.<p>
+
+<li> Not professionally supported (well it can be, if you want to pay).<p>
+
+<li> Some aspects of xBase files not supported, though I believe they are
+not used by ESRI.<p>
+
+<li> The application must keep the .dbf file in sync with the .shp/.shx
+files through appropriate use of the DBF and SHP APIs.<p>
+
+<li> No support for the undocumented .sbn/.sbx spatial index files.<p>
+
+</ul>
+
+<h2>Other Shapefile Resources</h2>
+
+<ul>
+<li> <a href="dl/shapefile.pdf">Shapefile Format Specifications (pdf)</a><p>
+
+<li> <a href="http://www.clicketyclick.dk/databases/xbase/format/">Xbase (.dbf) File Format Description</a>. <p>
+
+<li> <a href="codepage.html">Language ID / Code Page mappings</a><p>
+
+<li> Shapelib is used within the multiformat
+<a href="http://ogr.maptools.org/">OGR</a> library. If you are looking for a
+high level C++ library with support for many geospatial vector formats you
+might want to check it out.<p>
+
+<li> Ari Jolma has produced an initial <b>perl</b> binding on top of shapelib,
+which can be found at CPAN as Geo::ShapeFile under the
+<a href="http://www.cpan.org/modules/by-module/Geo/">Geo</a> module.
+<p>
+
+<li> Bernhard Herzog has produced <b>python</b> bindings for Shapelib with
+SWIG, available at <a href="http://ftp.intevation.de/users/bh/pyshapelib/">http://ftp.intevation.de/users/bh/pyshapelib</a>. A new version not using swig is
+available as <a href="http://wald.intevation.org/plugins/scmsvn/viewcvs.php/trunk/thuban/libraries/pyshapelib/?root=thuban">part of Thuban</a>.<p>
+
+<li> <a href="http://www.triplexware.huckfinn.de/shpapi.html">Delphi</a>
+bindings for Shapelib courtesy of Alexander Weidauer.<p>
+
+<li> Miguel Filgueiras has implemented
+<a href="http://www.ncc.up.pt/gpsmanshp/">Tcl</a> bindings for Shapelib
+as part of <a href="http://www.ncc.up.pt/gpsman/">GPSMan</a>.<p>
+
+<li> David Gancarz has implemented a Microsoft
+<a href="dl/contrib/DotNetArchive.zip">.NET wrapper</a> for
+Shapelib. An example of using shapelib with VB6 is also icluded in the .NET wrapper project file.<p>
+
+<li> Andrey Hristov (php at hristov dot com) has developed a PHP extension
+based on Shapelib. It can be found in CVS at http://cvs.php.net/pecl/shp.<p>
+
+<li> Toyoda Eizi has developed Ruby bindings found at
+<a href="http://sourceforge.net/projects/ruby-shapelib">http://sourceforge.net/projects/ruby-shapelib</a>.<p>
+
+<li> Davide Cesari has developed FORTRAN bindings that can be found at
+<a href"http://www.webalice.it/o.drofa/davide/shapelib-fortran/">
+http://www.webalice.it/o.drofa/davide/shapelib-fortran</a>.
+
+<li> Jan-Oliver Wagner has implemented a commandline program
+(<b>gen2shp</b>) for producing shapefiles from Arc/Info Generate format ASCII
+files. He maintains a <a href="http://intevation.de/~jan/gen2shp">web page</a> for his work. <p>
+
+<li> Tom Russo has implemented a shpcs2cs program, which reprojects shapefiles
+using arguments similar to the PROJ.4 cs2cs program including datum conversion.
+Use as an alternate to the contrib/shpproj which doesn't do datums. It is
+available at the bottom of Tom's <a href="http://www.swcp.com/~russo/shape_web/">Xastir Shapefile Resources</a> page. <p>
+
+<li>
+Andrew Williamson's
+<a href="http://www.geocities.com/SiliconValley/Haven/2295/useful.html">Useful
+Scripts and Stuff</a> page for ArcView, which includes ShapeChecker.<p>
+
+<li> The University of Bonn <a href="http://katla.giub.uni-bonn.de/sfjava/">
+sf4java</a> project apparently includes Java classes for reading Shapefiles.<p>
+
+<li> The <a href="http://gis.esri.com/arcscripts/details.cfm?CFGRIDKEY=628102085">ShapeIO2</a> Visual Basic libraries may be of interest to those wanting
+VB access to Shapefiles. Also available <a href="http://shapelib.maptools.org/dl/contrib/ShapeIO2.zip">locally</a>.<p>
+
+<li> The <a href="http://arcscripts.esri.com/details.asp?dbid=11810">ShapeFile Read/Write OCX</a> is another option for Visual Basic programmers.<p>
+
+<li> <a href="http://www.casa.ucl.ac.uk/sanjay/software_isovistanalyst.htm">Isovist Analyst</a> is a sort-of-free isovist generating extension for
+ArcView using shapelib.<p>
+
+<li> <a href="http://www.obviously.com/gis/shpdiff/">shpdiff</a> utility
+by Bryce Nesbitt.<p>
+
+<li> <a href="http://www.aequometer.de/">Aequometer</a>: a program for
+MS Excel to calculate the area of polygons and export as shapefiles.<p>
+
+</ul>
+
+</body>
+</html>
+
+
+
diff --git a/web/license.html b/web/license.html
new file mode 100644
index 0000000..8580972
--- /dev/null
+++ b/web/license.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+<title>Shapelib License</title>
+<link href="http://www.maptools.org/maptools.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>License</h1>
+
+The source for the Shapefile C Library is (c) 1998 Frank Warmerdam,
+and released under the following conditions. The intent is that anyone
+can do anything with the code, but that I do not assume any liability, nor
+express any warranty for this code. <p>
+
+As of Shapelib 1.2.6 the core portions of the library are made available
+under two possible licenses. The licensee can choose to use the code
+under either the Library GNU Public License (LGPL) described in
+LICENSE.LGPL or under the following MIT style license. Any files in
+the Shapelib distribution without explicit copyright license terms
+(such as this documentation, the Makefile and so forth) should be
+considered to have the following licensing terms. Some auxilary portions
+of Shapelib, notably some of the components in the contrib directory
+come under slightly different license restrictions. Check the source
+files that you are actually using for conditions.<p>
+
+<h3>Default License Terms</h3>
+
+<quote>
+Copyright (c) 1999, Frank Warmerdam<p>
+
+This software is available under the following "MIT Style" license,
+or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+option is discussed in more detail in shapelib.html.<p>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:<p>
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.<p>
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.<p>
+</quote>
+
+<h3>Shapelib Modifications</h3>
+
+I am pleased to receive bug fixes, and improvements for Shapelib. Unless
+the submissions indicate otherwise I will assume that changes submitted to
+me remain under the the above "dual license" terms. If changes are made
+to the library with the intention that those changes should be protected by
+the LGPL then I should be informed upon submission. Note that I will not
+generally incorporate changes into the core of Shapelib that are protected
+under the LGPL as this would effectively limit the whole file and
+distribution to LGPL terms.<p>
+
+<h3>Opting for LGPL</h3>
+
+For licensee's opting to use Shapelib under LGPL as opposed to the MIT
+Style license above, and wishing to redistribute the software based on
+Shapelib, I would ask that all "dual license" modules be updated to
+indicate that only the LGPL (and not the MIT Style license) applies. This
+action represents opting for the LGPL, and thereafter LGPL terms apply to
+any redistribution and modification of the affected modules.<p>
+
+</body>
+</html>
+
+
+
diff --git a/web/manifest.html b/web/manifest.html
new file mode 100644
index 0000000..27aeb0f
--- /dev/null
+++ b/web/manifest.html
@@ -0,0 +1,87 @@
+<html>
+<head>
+<title>Shapefile C Library V1.2</title>
+<link href="http://www.maptools.org/maptools.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>Shapelib Manifest</h1>
+
+<ul>
+<li> <b>web/index.html</b>: This file - general documentation on the
+Shapefile C Library.<p>
+
+<li> <b><a href="shp_api.html">web/shp_api.html</a></b>: Documentation
+for the API for accessing the .shp/.shx files. <p>
+
+<li> <b><a href="dbf_api.html">web/dbf_api.html</a></b>: Documentation
+for the API for accessing the .dbf attribute files. <p>
+
+<li> <b>shpopen.c</b>: C code for access to .shp/.shx vertex files.<p>
+
+<li> <b>dbfopen.c</b>: C code for access to .dbf attribute file.<p>
+
+<li> <b>shapefil.h</b>: Include file defining all the services of dbfopen.c
+and shpopen.c.<p>
+
+<li> <b>contrib/</b>: A directory of "in progress" contributed programs
+from Carl Anderson.<p>
+
+<li> <b>dbfcreate.c</b>: Simple example program for creating a new .dbf file.
+ <p>
+
+<li> <b>dbfadd.c</b>:
+ Simple example program for adding a record to a .dbf file.<p>
+
+<li> <b>dbfdump.c</b>: Simple example program for displaying the contents of
+ a .dbf file.<p>
+
+<li> <b>shpcreate.c</b>: Simple example program for creating a new .shp and
+.shx file.<p>
+
+<li> <b>shpadd.c</b>: Simple example program for adding a shape to an existing
+ shape file.<p>
+
+<li> <b>shpdump.c</b>: Simple program for dumping all the vertices in a
+ shapefile with an indicating of the parts.<p>
+
+<li> <b>shputils.c</b>: Complex contributed program capable of clipping and
+ appending
+ shapefiles as well as a few other things. Type shputils
+ after building to get a full usage message.<p>
+
+<li> <b>Makefile</b>: A simple makefile to compile the library and example
+ programs.<p>
+
+<li> <b>makeshape.sh</b>: A simple script for running some of the example
+programs.<p>
+
+<li> <b>shptest.c</b>: A simple test harnass to generate each of the supported
+ types of shapefiles. <p>
+
+
+<li> <b>shptree.c</b>: Implements a simple quadtree algorithm for fast
+spatial searches of shapefiles.<p>
+
+<li> <b>shptreedump.c</b>: A simple mainly showing information on quad
+trees build using the quad tree api.<p>
+
+<li> <b>stream1.sh</b> - A test script, which should produce stream1.out.
+Note this will only work if you have the example data downloaded.<p>
+
+<li> <b>stream1.out</b>: Expected output of stream1.sh test script.<p>
+
+<li> <b>stream2.sh</b>: A test script, which should produce stream2.out.<p>
+
+<li> <b>stream2.out</b>: Expected output of stream2.sh test script.<p>
+
+<li> <b>pyshapelib-0.1</b>: Prototype contributed Python bindings.<p>
+
+</ul>
+
+
+</body>
+</html>
+
+
+
diff --git a/web/release.html b/web/release.html
new file mode 100644
index 0000000..00170da
--- /dev/null
+++ b/web/release.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+<title>Shapelib Release Notes</title>
+<link href="http://www.maptools.org/maptools.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>Shapelib Release Notes</h1>
+
+To get notification of new releases of Shapelib <i>subscribe</i> to
+the project at www.freshmeat.net. This is currently the only reliable
+way of finding out about new releases since there is no shapelib specific
+mailing list.<p>
+
+<b>Release 1.3.0</b>:
+<ul>
+<li> Major rework to us application provided hooks for file io, and error reporting (SAHooks).
+<li> Added contrib/Shape_PointInPoly.cpp from Marko Podgorsek.
+<li> Added shapelib tools documentation from Eduardo Patto Kanegae.
+<li> Added dbf deletion support.
+<li> Added DBFAddNativeFieldType().
+<li> Added DBFDeleteField(), DBFReorderFields() and DBFAlterFields() to
+rework DBF schema.
+<li> likely a variety of other changes - it has been eight years since 1.2.10!
+</ul>
+
+<b>Release 1.2.10</b>: Added SHPRewindObject() function, and shprewind utility
+program. Added FTLogical, DBFReadLogicalAttribute() and
+DBFWriteLogicalAttribute() (thanks to Olek Neyman). <p>
+
+<b>Release 1.2.9</b>: Good support for reading and writing NULL fields
+in .dbf files, good support for NULL shapes and addition of the
+DBFGetFieldIndex() functions (all contributed by Jim Matthews).<p>
+
+An upgraded shputils.c has been contributed by Bill Miller. Daniel
+Morissette contributed DBFGetNativeFieldType(). Better error checking
+for disk errors in dbfopen.c. Various other bug fixes and safety improvements.
+<p>
+
+<b>Release 1.2.8</b>: Added hacked libtool support (supplied by Jan)
+and "rpm ready" install logic.<p>
+
+<b>Release 1.2.7</b>: Fix record size (was 4 bytes too long). Modify
+SHPReadObject() to handle null shapes properly. Use atof() instead of
+sscanf(). Support .DBF as well as .dbf.<p>
+
+<b>Release 1.2.6</b>: Now available under old MIT style license, or at the
+users option, LGPL. Added the contrib directory of stuff from Carl Anderson
+and the shptree.c API for quadtree based spatial searches.<p>
+
+<b>Release 1.2.5</b>: SHPOpen() now forcably uses "rb" or "r+b" access string
+to avoid common mistakes on Windows. Also fixed a serious bug with .dbf
+files with a 'F' field type.<p>
+
+<b>Release 1.2.4</b>: DBFOpen() will now automatically translate a .shp
+extension to .dbf for convenience. SHPOpen() will try datasets with lower
+and uppercase extension. DBFAddField() now returns the field number,
+not TRUE/FALSE.<p>
+
+<b>Release 1.2.3</b>: Disable writing measures to multi-patches as ArcView
+seems to puke on them (as reported by Monika Sester). Add white space
+trimming, and string/numeric attribute interchangability in DBF API
+as suggested by Steve Lime. Dbfdump was updated to include several
+reporting options.<p>
+
+<b>Release 1.2.2</b>: Added proper support for multipatch (reading and
+writing) - this release just for testing purposes.<p>
+
+<b>Release 1.2</b> is mostly a rewrite of the .shp/.shx access API to account
+for ArcView 3.x 3D shapes, and to encapsulate the shapes in a structure.
+Existing code using the shapefile library will require substantial changes
+to use release 1.2.<p>
+
+<b>Release V1.1</b> has been built on a number of platforms, and used by a
+number of people successfully. V1.1 is the first release with the xBase API
+documentation.<p>
+
+
+</body>
+</html>
diff --git a/web/shapelib-tools.html b/web/shapelib-tools.html
new file mode 100644
index 0000000..19ad547
--- /dev/null
+++ b/web/shapelib-tools.html
@@ -0,0 +1,352 @@
+<html>
+<head>
+<title>ShapeLib Tools - User Guide</title>
+<link href="http://www.maptools.org/maptools.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>ShapeLib Tools - User Guide</h1>
+ShapeLib is maintained by Frank Warmerdam<br>
+This guide was created by <a href="http://www.consultoria.eti.br" target="_show">Eduardo Patto Kanegae</a> < eduardo<i>~at~</i>consultoria<i>~dot~</i>eti<i>~dot~</i>br >
+<ul>
+ <li><a href="#dbfcreate">dbfcreate</a></li>
+ <li><a href="#dbfadd">dbfadd</a></li>
+ <li><a href="#dbfdump">dbfdump</a></li>
+ <li><a href="#shpcreate">shpcreate</a></li>
+ <li><a href="#shpadd">shpadd</a></li>
+ <li><a href="#shpdump">shpdump</a></li>
+ <li><a href="#shprewind">shprewind</a></li>
+ <li><i>Tools from ShapeLib 'contrib' directory</i>
+ <ul>
+ <li><a href="#dbfinfo">dbfinfo</a></li>
+ <li><a href="#dbfcat">dbfcat</a></li>
+ <li><a href="#shpinfo">shpinfo</a></li>
+ <li><a href="#shpcat">shpcat</a></li>
+ <li><a href="#shpcentrd">shpcentrd</a></li>
+ <li><a href="#shpdxf">shpdxf</a></li>
+ <li><a href="#shpfix">shpfix</a></li>
+ <li><a href="#shpproj">shpproj</a></li>
+ </ul>
+ </li>
+
+</ul>
+
+<h2><a name="dbfcreate">dbfcreate</a></h2>
+<b>Purpose</b>: creates a new and empty .dbf file.
+<br>
+<b>Usage</b>: <font face="courier">dbfcreate xbase_file [[-s field_name width],[-n field_name width decimals]]...</font>
+<br>
+<ul>
+ <li><b>xbase_file</b>: the name of xBase file to be created. Doesn't need the extension.</li>
+ <li><b>-s field_name width</b>: creates a string field with name <u>field_name</u> and size <u>width</u>.</li>
+ <li><b>-n field_name width decimals</b>: creates a numeric field with name <u>field_name</u>, width of <u>width</u> and with decimals places sized by <u>decimals</u>.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ dbfcreate testbase -s NAME 20, -n AREA 9 3, -n VALUE 9 2</font>
+<br># this will create a file named testbase.dbf with 3 fields: NAME ( string (20)),
+AREA ( float (9,3)) and VALUE ( float (9,2))
+<br>
+<hr>
+
+<h2><a name="dbfadd">dbfadd</a></h2>
+<b>Purpose</b>: adds a record into an existing .dbf file.
+<br>
+<b>Usage</b>: <font face="courier">dbfadd xbase_file field_values</font>
+<br>
+<ul>
+ <li><b>xbase_file</b>: the name of an existing xBase file.</li>
+ <li><b>field_values</b>: list of values to be inserted into the xBase file.
+ You must specify a number of values equal to the number of fields the xBase file has.
+ The order of values must also reflect the order of fields inside xBase file.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ dbfadd testbase.dbf REGION1 25.656 150.22</font>
+<br># assuming that testbase.dbf has 3 fields( NAME, AREA and VALUE), this command line
+will insert a new record into testbase.dbf with the value "REGION1" for NAME,
+'25.656' for AREA and '150.22' for VALUE field.
+<br>
+<hr>
+
+<h2><a name="dbfdump">dbfdump</a></h2>
+<b>Purpose</b>: dumps the content of a xBase file to the terminal.
+<br>
+<b>Usage</b>: <font face="courier">dbfdump [-h] [-r] [-m] xbase_file</font>
+<br>
+<ul>
+ <li><b>-h</b>: output header info( field descriptions).</li>
+ <li><b>-r</b>: output raw field info, numeric values not reformatted.</li>
+ <li><b>-m</b>: output one line per field.</li>
+ <li><b>xbase_file</b>: the name of an existing xBase file.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ dbfdump -h testbase.dbf</font>
+<br># assuming that testbase.dbf has 1 record( inserted by previous example using 'dbfadd'),
+this command line will produce the following output:<br>
+<font face="courier">
+Field 0: Type=String, Title=`NAME', Width=20, Decimals=0<br>
+Field 1: Type=Double, Title=`AREA', Width=9, Decimals=3<br>
+Field 2: Type=Double, Title=`VALUE', Width=9, Decimals=2<br>
+NAME AREA VALUE<br>
+REGION1 25.656 150.22
+</font>
+<br>
+<hr>
+
+<h2><a name="shpcreate">shpcreate</a></h2>
+<b>Purpose</b>: creates a new and empty shapefile.
+<br>
+<b>Usage</b>: <font face="courier">shpcreate shp_file [point|arc|polygon|multipoint]</font>
+<br>
+<ul>
+ <li><b>shp_file</b>: the name of shapefile to be created. Doesn't need the extension.</li>
+ <li><b>point/arc/polygon/multipoint</b>: the type of shapefile that you wish to create. You must specify a valid option.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpcreate testpolygon polygon</font>
+<br># this will create a point shapefile named testpolygon( in fact testpolygon.shp and testpolygon.shx will be created).
+<br>
+<hr>
+
+<h2><a name="shpadd">shpadd</a></h2>
+<b>Purpose</b>: adds a shape into an existing shapefile.
+<br>
+<b>Usage</b>: <font face="courier">shpadd shp_file [[x y] [+]]*</font>
+<br>
+<ul>
+ <li><b>shp_file</b>: the name of an existing shapefile.</li>
+ <li><b>x<sub><i>1</i></sub> y<sub><i>1</i></sub> x<sub><i>2</i></sub> y<sub><i>2</i></sub> ... x<sub><i>n</i></sub> y<sub><i>n</i></sub></b>: the set of x,y coordinates that describes the shape that you wish to add. Note that you must specify the correct number of parameters for a given type of shapefile. e.g.: for point shapefiles you have to pass 1 pair of XY coordinates and for a polygon shapefile you should pass at least 4 pairs of XY coordinates( where the first and the last point must have the same coordinates).</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpadd testpolygon 100000 7000000 250000 6500000 200000 6000000 100000 7000000</font>
+<br># assuming that testpolygon is a polygon shapefile, this command line will insert a new shape( a triangle) into testpolygon with the following XY coordinates:<br>
+vertice 0: 100000 7000000 ( this will also be the vertice where the shape starts and ends)<br>
+vertice 1: 250000 6500000<br>
+vertice 2: 200000 6000000<br>
+vertice 3: 100000 7000000<br>
+<hr>
+
+<h2><a name="shpdump">shpdump</a></h2>
+<b>Purpose</b>: dumps content of shapefile showing information like shape type, file extents, total of objects and vertices coordinates.
+<br>
+<b>Usage</b>: <font face="courier">shpdump [-validate] shp_file</font>
+<br>
+<ul>
+ <li><b>-validate</b>: count the number of objects that has invalid ring orderings.</li>
+ <li><b>shp_file</b>: the name of an existing shapefile.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpdump testpolygon</font>
+<br># assuming that testpolygon is an existing shapefile previously created, this command line will output the following result:
+<pre>Shapefile Type: Polygon # of Shapes: 1
+
+File Bounds: ( 100000.000, 6000000.000,0,0)
+ to ( 250000.000, 7000000.000,0,0)
+
+Shape:0 (Polygon) nVertices=4, nParts=1
+ Bounds:( 100000.000, 6000000.000, 0, 0)
+ to ( 250000.000, 7000000.000, 0, 0)
+ ( 100000.000, 7000000.000, 0, 0) Ring
+ ( 250000.000, 6500000.000, 0, 0)
+ ( 200000.000, 6000000.000, 0, 0)
+ ( 100000.000, 7000000.000, 0, 0)</pre>
+<hr>
+
+<h2><a name="shprewind">shprewind</a></h2>
+<b>Purpose</b>: validates and resets the winding order of rings in polygon geometries to match the ordering required by shapefile specification. This is usefull for shapefiles having troubles when checked with a 'shpdump -validate'.
+<br>
+<b>Usage</b>: <font face="courier">shprewind in_shp_file out_shp_file</font>
+<br>
+<ul>
+ <li><b>in_shp_file</b>: the name of an existing shapefile.</li>
+ <li><b>out_shp_file</b>: the name of the new fixed shapefile that will be created.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shprewind badshapefile newshapefile</font>
+<br>
+<hr>
+
+<h2><a name="dbfinfo">dbfinfo</a></h2>
+<b>Purpose</b>: displays basic information for a given xBase file, like number of columns, number of records and type of each column.
+<br>
+<b>Usage</b>: <font face="courier">dbfinfo xbase_file</font>
+<br>
+<ul>
+ <li><b>xbase_file</b>: the name of an existing xBase file.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ dbfinfo testbase</font>
+<br>
+<pre>Info for testbase.dbf
+3 Columns, 1 Records in file
+ NAME string (20,0)
+ AREA float (9,3)
+ VALUE float (9,2)
+</pre>
+<br>
+<hr>
+
+<h2><a name="dbfcat">dbfcat</a></h2>
+<b>Purpose</b>: appends the records of a source xBase file into a destiny xBase file. Both files must have the same number of fields.
+<br>
+<b>Usage</b>: <font face="courier">dbfcat [-v] [-f] from_DBFfile to_DBFfile</font>
+<br>
+<ul>
+ <li><b>-v</b>: verbose mode.</li>
+ <li><b>-f</b>: forces data convertion if data field types is not the same at both files or if is there any null value into <u>from_DBFfile</u>.</li>
+ <li><b>from_DBFfile</b>: source xBase file.</li>
+ <li><b>to_DBFfile</b>: destiny xBase file.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ dbfcat -v testbase1 testbase2</font>
+<br>
+<hr>
+
+<h2><a name="shpinfo">shpinfo</a></h2>
+<b>Purpose</b>: displays basic information for a given shapefile, like shapefile type, number of objects and its extents.
+<br>
+<b>Usage</b>: <font face="courier">shpinfo shp_file</font>
+<br>
+<ul>
+ <li><b>shp_file</b>: the name of an existing shapefile.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpinfo testpolygon</font>
+<br>
+<pre>Info for testpolygon
+Polygon(5), 1 Records in file
+File Bounds: ( 100000, 6000000)
+ ( 250000, 7000000)</pre>
+<hr>
+
+<h2><a name="shpcat">shpcat</a></h2>
+<b>Purpose</b>: appends the content of a source shapefile into a destiny shapefile. Both files must be the same shapefile type.
+<br>
+<b>Usage</b>: <font face="courier">shpcat from_shpfile to_shpfile</font>
+<br>
+<ul>
+ <li><b>from_shpfile</b>: source shapefile</li>
+ <li><b>to_shpfile</b>: destiny shapefile</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpcat shapefile1 shapefile2</font>
+<br>
+<hr>
+
+<h2><a name="shpcentrd">shpcentrd</a></h2>
+<b>Purpose</b>: computes XY centroid for polygon shapefiles.
+<br>
+<b>Usage</b>: <font face="courier">shpcentrd shp_file new_shp_file</font>
+<br>
+<ul>
+ <li><b>shp_file</b>: the name of an existing polygon shapefile.</li>
+ <li><b>new_shp_file</b>: the name of the point shapefile that will created.</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpcentrd apolygonfile pointcentrd</font>
+<br>
+<hr>
+
+<h2><a name="shpdxf">shpdxf</a></h2>
+<b>Purpose</b>: creates a DXF file from an existing shapefile.
+<br>
+<b>Usage</b>: <font face="courier">shpdxf shapefile {idfield}</font>
+<br>
+<ul>
+ <li><b>shapefile</b>: the name of an existing shapefile.</li>
+ <li><b>idfield</b>: explain</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpdxf testshapefile IDFIELD</font>
+<br># explain the command
+<br>
+<hr>
+
+<h2><a name="shpfix">shpfix</a></h2>
+<b>Purpose</b>: Utility program to fix nulls and inconsistencies in Shapefiles
+as happens from time to time.
+<br>
+<b>Usage</b>: <font face="courier">shpfix shpfile new_file <Record# to Blank></font>
+<br>
+<ul>
+ <li><b>shpfile</b>: input file</li>
+ <li><b>new_file</b>: output file</li>
+</ul>
+<b>Example</b>
+<br>
+<font face="courier">$ shpfix broken fixed</font>
+<br>
+<hr>
+
+<h2><a name="shpproj">shpproj</a></h2>
+<b>Purpose</b>: Reproject Shapefiles using PROJ.4
+<br>
+<b>Usage</b>: <font face="courier">shpproj shp_file new_shp ( -i=in_proj_file | -i="in_params" | -i=geographic ) ( -o=out_info_file | -o="out_params" | -o=geographic ) </font>
+<br>
+<ul>
+ <li><b>param1</b>: explain</li>
+ <li><b>param2</b>: explain</li>
+</ul>
+<p>
+
+<b>INPUT</b><br>
+ Input can come from one of three sources. A projection parameter file,
+ directly through parameters or geographic. If the shapefile has an associated
+ prj file, name the same as the shapefile but ending in ".prj" it will be used
+ by default ignoring all other parameters. If input is omitted it defaults to
+ geographic, unless the default prj file exists.<p>
+
+<b>OUTPUT</b><br>
+ Output can come from one of three sources. A projection parameter file,
+ directly through parameters or geographic. If output is omitted it defaults
+ to geographic.<p>
+
+<b>PROJECTION PARAMETER FILE</b><br>
+ This file MUST end with the extension ".prj". It has the form of one
+ projection parameter per line. Parameters can be in any order. The
+ projection parameters are those used to define a PROJ.4 projection.<p>
+
+<b>PROJECTION PARAMETERS</b><br>
+ Are the same as used by proj and invproj.<p>
+<pre>
+ use proj -lP to see available projections
+ proj -lu to see available units
+ proj -le to see available ellipsoid
+</pre>
+
+Or visit the PROJ.4 web page at <a href="http://www.remotesensing.org/proj">http://www.remotesensing.org/proj</a> for more details.<p>
+
+<p>
+
+<b>Example</b></br>
+
+the following example projects file rowtest to row3, moving data from Stateplane NAD83 zone 1002 to utm zone 16 in meters<p>
+
+<pre>
+
+shpproj rowtest row -i="init=nad83:1002 units=us-ft" -o="proj=utm zone=16 units=m"
+
+shpproj rowtest row3 -o="proj=utm zone=18 units=m" -i="zone=16 proj=utm units=us-ft"
+
+shpproj rowtest row3 -o="proj=utm zone=18 units=m"
+
+shpproj rowtest row3 -i=myfile.prj -o=geographic
+shpproj rowtest row3 -is=myfile.prj
+</pre>
+
+<hr>
+
+</body>
+</html>
diff --git a/shp_api.html b/web/shp_api.html
similarity index 100%
rename from shp_api.html
rename to web/shp_api.html
--
Library for reading and writing ArcView Shapefiles
More information about the Pkg-grass-devel
mailing list