Browse Source

+ initial implementation of SQLDB ODBC connection from Bram Kuijvenhoven

git-svn-id: trunk@1606 -
joost 20 years ago
parent
commit
65590e912a

+ 3 - 0
.gitattributes

@@ -717,6 +717,9 @@ fcl/db/sqldb/mysql/Makefile.fpc svneol=native#text/plain
 fcl/db/sqldb/mysql/fpmake.inc svneol=native#text/plain
 fcl/db/sqldb/mysql/fpmake.pp svneol=native#text/plain
 fcl/db/sqldb/mysql/mysql4conn.pas svneol=native#text/plain
+fcl/db/sqldb/odbc/Makefile svneol=native#text/plain
+fcl/db/sqldb/odbc/Makefile.fpc svneol=native#text/plain
+fcl/db/sqldb/odbc/odbcconn.pas svneol=native#text/plain
 fcl/db/sqldb/postgres/Makefile svneol=native#text/plain
 fcl/db/sqldb/postgres/Makefile.fpc svneol=native#text/plain
 fcl/db/sqldb/postgres/fpmake.inc svneol=native#text/plain

+ 126 - 19
fcl/db/sqldb/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/10/20]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/10/30]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-wince powerpc64-linux
@@ -233,58 +233,58 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/ext
 override PACKAGE_NAME=fcl
 PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl/Makefile.fpc,$(PACKAGESDIR))))))
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_DIRS+=interbase postgres mysql
+override TARGET_DIRS+=interbase postgres mysql odbc
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_UNITS+=sqldb
@@ -1385,6 +1385,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
 REQUIRE_PACKAGES_RTL=1
@@ -1394,6 +1395,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-os2)
 REQUIRE_PACKAGES_RTL=1
@@ -1403,6 +1405,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-beos)
 REQUIRE_PACKAGES_RTL=1
@@ -1412,6 +1415,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
 REQUIRE_PACKAGES_RTL=1
@@ -1427,6 +1431,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
 REQUIRE_PACKAGES_RTL=1
@@ -1448,18 +1453,21 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
 REQUIRE_PACKAGES_RTL=1
@@ -1472,6 +1480,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
 REQUIRE_PACKAGES_RTL=1
@@ -1481,12 +1490,14 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 REQUIRE_PACKAGES_RTL=1
@@ -1496,6 +1507,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
 REQUIRE_PACKAGES_RTL=1
@@ -1505,12 +1517,14 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
 REQUIRE_PACKAGES_RTL=1
@@ -1520,12 +1534,14 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
 REQUIRE_PACKAGES_RTL=1
@@ -1535,6 +1551,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifeq ($(FULL_TARGET),arm-wince)
 REQUIRE_PACKAGES_RTL=1
@@ -1544,6 +1561,7 @@ REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_IBASE=1
 REQUIRE_PACKAGES_POSTGRES=1
 REQUIRE_PACKAGES_MYSQL=1
+REQUIRE_PACKAGES_ODBC=1
 endif
 ifdef REQUIRE_PACKAGES_RTL
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
@@ -1649,6 +1667,32 @@ ifdef UNITDIR_MYSQL
 override COMPILER_UNITDIR+=$(UNITDIR_MYSQL)
 endif
 endif
+ifdef REQUIRE_PACKAGES_ODBC
+PACKAGEDIR_ODBC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /odbc/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_ODBC),)
+ifneq ($(wildcard $(PACKAGEDIR_ODBC)/units/$(TARGETSUFFIX)),)
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)/units/$(TARGETSUFFIX)
+else
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_ODBC)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_ODBC) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_ODBC)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_ODBC=
+UNITDIR_ODBC:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /odbc/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_ODBC),)
+UNITDIR_ODBC:=$(firstword $(UNITDIR_ODBC))
+else
+UNITDIR_ODBC=
+endif
+endif
+ifdef UNITDIR_ODBC
+override COMPILER_UNITDIR+=$(UNITDIR_ODBC)
+endif
+endif
 ifndef NOCPUDEF
 override FPCOPTDEF=$(CPU_TARGET)
 endif
@@ -2085,91 +2129,109 @@ ifeq ($(FULL_TARGET),i386-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 TARGET_DIRS_INTERBASE=1
 TARGET_DIRS_POSTGRES=1
 TARGET_DIRS_MYSQL=1
+TARGET_DIRS_ODBC=1
 endif
 ifdef TARGET_DIRS_INTERBASE
 interbase_all:
@@ -2306,6 +2368,51 @@ mysql:
 	$(MAKE) -C mysql all
 .PHONY: mysql_all mysql_debug mysql_smart mysql_release mysql_units mysql_examples mysql_shared mysql_install mysql_sourceinstall mysql_exampleinstall mysql_distinstall mysql_zipinstall mysql_zipsourceinstall mysql_zipexampleinstall mysql_zipdistinstall mysql_clean mysql_distclean mysql_cleanall mysql_info mysql_makefiles mysql
 endif
+ifdef TARGET_DIRS_ODBC
+odbc_all:
+	$(MAKE) -C odbc all
+odbc_debug:
+	$(MAKE) -C odbc debug
+odbc_smart:
+	$(MAKE) -C odbc smart
+odbc_release:
+	$(MAKE) -C odbc release
+odbc_units:
+	$(MAKE) -C odbc units
+odbc_examples:
+	$(MAKE) -C odbc examples
+odbc_shared:
+	$(MAKE) -C odbc shared
+odbc_install:
+	$(MAKE) -C odbc install
+odbc_sourceinstall:
+	$(MAKE) -C odbc sourceinstall
+odbc_exampleinstall:
+	$(MAKE) -C odbc exampleinstall
+odbc_distinstall:
+	$(MAKE) -C odbc distinstall
+odbc_zipinstall:
+	$(MAKE) -C odbc zipinstall
+odbc_zipsourceinstall:
+	$(MAKE) -C odbc zipsourceinstall
+odbc_zipexampleinstall:
+	$(MAKE) -C odbc zipexampleinstall
+odbc_zipdistinstall:
+	$(MAKE) -C odbc zipdistinstall
+odbc_clean:
+	$(MAKE) -C odbc clean
+odbc_distclean:
+	$(MAKE) -C odbc distclean
+odbc_cleanall:
+	$(MAKE) -C odbc cleanall
+odbc_info:
+	$(MAKE) -C odbc info
+odbc_makefiles:
+	$(MAKE) -C odbc makefiles
+odbc:
+	$(MAKE) -C odbc all
+.PHONY: odbc_all odbc_debug odbc_smart odbc_release odbc_units odbc_examples odbc_shared odbc_install odbc_sourceinstall odbc_exampleinstall odbc_distinstall odbc_zipinstall odbc_zipsourceinstall odbc_zipexampleinstall odbc_zipdistinstall odbc_clean odbc_distclean odbc_cleanall odbc_info odbc_makefiles odbc
+endif
 all: fpc_all $(addsuffix _all,$(TARGET_DIRS))
 debug: fpc_debug
 smart: fpc_smart

+ 6 - 6
fcl/db/sqldb/Makefile.fpc

@@ -6,12 +6,12 @@
 main=fcl
 
 [target]
-dirs_linux=interbase postgres mysql
-dirs_freebsd=interbase postgres mysql
-dirs_darwin=interbase postgres mysql
-dirs_netbsd=interbase postgres mysql
-dirs_openbsd=interbase postgres mysql
-dirs_win32=interbase postgres mysql
+dirs_linux=interbase postgres mysql odbc
+dirs_freebsd=interbase postgres mysql odbc
+dirs_darwin=interbase postgres mysql odbc
+dirs_netbsd=interbase postgres mysql odbc
+dirs_openbsd=interbase postgres mysql odbc
+dirs_win32=interbase postgres mysql odbc
 units=sqldb
 rsts=sqldb
 

+ 2 - 1
fcl/db/sqldb/examples/alisttables.pp

@@ -15,7 +15,7 @@ program aListTables;
 
 uses
   Classes,
-  sqldb, pqconnection, mysql4conn, IBConnection,
+  sqldb, pqconnection, mysql4conn, IBConnection, ODBCConn,
   SqldbExampleUnit;
 
 var Tables : TStringList;
@@ -28,6 +28,7 @@ begin
   if dbtype = 'mysql' then Fconnection := tMySQLConnection.Create(nil);
   if dbtype = 'postgresql' then Fconnection := tpqConnection.Create(nil);
   if dbtype = 'interbase' then Fconnection := tIBConnection.Create(nil);
+  if dbtype = 'odbc' then Fconnection := tODBCConnection.Create(nil);
 
   if not assigned(Fconnection) then ExitWithError('Invalid database-type, check if a valid database-type was provided in the file ''database.ini''');
 

+ 2 - 1
fcl/db/sqldb/examples/sqldbexampleunit.pp

@@ -16,7 +16,7 @@ interface
 
 uses
   Classes,
-  sqldb, pqconnection, mysql4conn, IBConnection;
+  sqldb, pqconnection, mysql4conn, IBConnection, ODBCConn;
 
 var dbtype,
     dbname,
@@ -82,6 +82,7 @@ begin
   if dbtype = 'mysql' then Fconnection := tMySQLConnection.Create(nil);
   if dbtype = 'postgresql' then Fconnection := tpqConnection.Create(nil);
   if dbtype = 'interbase' then Fconnection := tIBConnection.Create(nil);
+  if dbtype = 'odbc' then Fconnection := tODBCConnection.Create(nil);
 
   if not assigned(Fconnection) then ExitWithError('Invalid database-type, check if a valid database-type was provided in the file ''database.ini''');
 

+ 1873 - 0
fcl/db/sqldb/odbc/Makefile

@@ -0,0 +1,1873 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/10/30]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-wince powerpc64-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx
+LIMIT83fs = go32v2 os2 emx watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../../../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPC:=$(shell $(FPCPROG) -PB)
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=fcl
+PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl/Makefile.fpc,$(PACKAGESDIR))))))
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=odbcconn
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=odbcconn
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_OPTIONS+=-S2
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_OPTIONS+=-S2
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+ifeq ($(OS_SOURCE),linux)
+ifndef GCCLIBDIR
+ifeq ($(CPU_TARGET),i386)
+ifneq ($(findstring x86_64,$(shell uname -a)),)
+ifeq ($(BINUTILSPREFIX),)
+GCCLIBDIR:=$(shell dirname `gcc -m32 -print-libgcc-file-name`)
+endif
+endif
+endif
+ifeq ($(CPU_TARGET),powerpc64)
+ifeq ($(BINUTILSPREFIX),)
+GCCLIBDIR:=$(shell dirname `gcc -m64 -print-libgcc-file-name`)
+endif
+endif
+endif
+ifndef GCCLIBDIR
+CROSSGCC=$(strip $(wildcard $(addsuffix /$(BINUTILSPREFIX)gcc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(CROSSGCC),)
+GCCLIBDIR:=$(shell dirname `$(CROSSGCC) -print-libgcc-file-name`)
+endif
+endif
+ifndef OTHERLIBDIR
+OTHERLIBDIR:=$(shell grep -v "^\#" /etc/ld.so.conf | awk '{ ORS=" "; print $1 }')
+endif
+endif
+ifdef inUnix
+ifeq ($(OS_SOURCE),netbsd)
+OTHERLIBDIR+=/usr/pkg/lib
+endif
+export GCCLIBDIR OTHERLIB
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+STATICLIBPREFIX=libp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.asm
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl odbc
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_ODBC=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_ODBC
+PACKAGEDIR_ODBC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /odbc/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_ODBC),)
+ifneq ($(wildcard $(PACKAGEDIR_ODBC)/units/$(TARGETSUFFIX)),)
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)/units/$(TARGETSUFFIX)
+else
+UNITDIR_ODBC=$(PACKAGEDIR_ODBC)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_ODBC)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_ODBC) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_ODBC)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_ODBC=
+UNITDIR_ODBC:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /odbc/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_ODBC),)
+UNITDIR_ODBC:=$(firstword $(UNITDIR_ODBC))
+else
+UNITDIR_ODBC=
+endif
+endif
+ifdef UNITDIR_ODBC
+override COMPILER_UNITDIR+=$(UNITDIR_ODBC)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(CPU_TARGET)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX) -Xc
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+else
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+else
+FPCCPUOPT:=
+endif
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-OG2p3
+endif
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+ifeq ($(FPC_VERSION),1.0.6)
+override FPCOPTDEF+=HASUNIX
+endif
+endif
+ifdef GCCLIBDIR
+override FPCOPT+=-Fl$(GCCLIBDIR)
+endif
+ifdef OTHERLIBDIR
+override FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR))
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+EXECPPAS:=@$(PPAS)
+endif
+endif
+.PHONY: fpc_units
+ifneq ($(TARGET_UNITS),)
+override ALLTARGET+=fpc_units
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))
+override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS))
+override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+endif
+fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+	@$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+	$(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+	$(MAKE) all DEBUG=1
+fpc_release:
+	$(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+	$(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+	$(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(PPUEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pp
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.pas
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.lpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%$(EXEEXT): %.dpr
+	$(COMPILER) $<
+	$(EXECPPAS)
+%.res: %.rc
+	windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+	-$(UPXPROG) $(INSTALLEXEFILES)
+endif
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+	-$(DELTREE) units
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+	-$(DEL) *.o *.ppu *.a
+endif
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+	-$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+	@$(ECHO)
+	@$(ECHO)  == Package info ==
+	@$(ECHO)  Package Name..... $(PACKAGE_NAME)
+	@$(ECHO)  Package Version.. $(PACKAGE_VERSION)
+	@$(ECHO)
+	@$(ECHO)  == Configuration info ==
+	@$(ECHO)
+	@$(ECHO)  FPC.......... $(FPC)
+	@$(ECHO)  FPC Version.. $(FPC_VERSION)
+	@$(ECHO)  Source CPU... $(CPU_SOURCE)
+	@$(ECHO)  Target CPU... $(CPU_TARGET)
+	@$(ECHO)  Source OS.... $(OS_SOURCE)
+	@$(ECHO)  Target OS.... $(OS_TARGET)
+	@$(ECHO)  Full Source.. $(FULL_SOURCE)
+	@$(ECHO)  Full Target.. $(FULL_TARGET)
+	@$(ECHO)  SourceSuffix. $(SOURCESUFFIX)
+	@$(ECHO)  TargetSuffix. $(TARGETSUFFIX)
+	@$(ECHO)
+	@$(ECHO)  == Directory info ==
+	@$(ECHO)
+	@$(ECHO)  Required pkgs... $(REQUIRE_PACKAGES)
+	@$(ECHO)
+	@$(ECHO)  Basedir......... $(BASEDIR)
+	@$(ECHO)  FPCDir.......... $(FPCDIR)
+	@$(ECHO)  CrossBinDir..... $(CROSSBINDIR)
+	@$(ECHO)  UnitsDir........ $(UNITSDIR)
+	@$(ECHO)  PackagesDir..... $(PACKAGESDIR)
+	@$(ECHO)
+	@$(ECHO)  GCC library..... $(GCCLIBDIR)
+	@$(ECHO)  Other library... $(OTHERLIBDIR)
+	@$(ECHO)
+	@$(ECHO)  == Tools info ==
+	@$(ECHO)
+	@$(ECHO)  As........ $(AS)
+	@$(ECHO)  Ld........ $(LD)
+	@$(ECHO)  Ar........ $(AR)
+	@$(ECHO)  Rc........ $(RC)
+	@$(ECHO)
+	@$(ECHO)  Mv........ $(MVPROG)
+	@$(ECHO)  Cp........ $(CPPROG)
+	@$(ECHO)  Rm........ $(RMPROG)
+	@$(ECHO)  GInstall.. $(GINSTALL)
+	@$(ECHO)  Echo...... $(ECHO)
+	@$(ECHO)  Shell..... $(SHELL)
+	@$(ECHO)  Date...... $(DATE)
+	@$(ECHO)  FPCMake... $(FPCMAKE)
+	@$(ECHO)  PPUMove... $(PPUMOVE)
+	@$(ECHO)  Upx....... $(UPXPROG)
+	@$(ECHO)  Zip....... $(ZIPPROG)
+	@$(ECHO)
+	@$(ECHO)  == Object info ==
+	@$(ECHO)
+	@$(ECHO)  Target Loaders........ $(TARGET_LOADERS)
+	@$(ECHO)  Target Units.......... $(TARGET_UNITS)
+	@$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)
+	@$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)
+	@$(ECHO)  Target Dirs........... $(TARGET_DIRS)
+	@$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)
+	@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+	@$(ECHO)
+	@$(ECHO)  Clean Units......... $(CLEAN_UNITS)
+	@$(ECHO)  Clean Files......... $(CLEAN_FILES)
+	@$(ECHO)
+	@$(ECHO)  Install Units....... $(INSTALL_UNITS)
+	@$(ECHO)  Install Files....... $(INSTALL_FILES)
+	@$(ECHO)
+	@$(ECHO)  == Install info ==
+	@$(ECHO)
+	@$(ECHO)  DateStr.............. $(DATESTR)
+	@$(ECHO)  ZipName.............. $(ZIPNAME)
+	@$(ECHO)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(ECHO)  FullZipName.......... $(FULLZIPNAME)
+	@$(ECHO)  Install FPC Package.. $(INSTALL_FPCPACKAGE)
+	@$(ECHO)
+	@$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)
+	@$(ECHO)  Install binary dir... $(INSTALL_BINDIR)
+	@$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)
+	@$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)
+	@$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)
+	@$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)
+	@$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)
+	@$(ECHO)  Install data dir..... $(INSTALL_DATADIR)
+	@$(ECHO)
+	@$(ECHO)  Dist destination dir. $(DIST_DESTDIR)
+	@$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)
+	@$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+	fpc_makefile_dirs
+fpc_makefile:
+	$(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples:
+shared:
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif

+ 21 - 0
fcl/db/sqldb/odbc/Makefile.fpc

@@ -0,0 +1,21 @@
+#
+# Makefile.fpc for SQL ODBCConn
+#
+
+[package]
+main=fcl
+
+[target]
+units=odbcconn
+
+[require]
+packages=odbc
+
+[compiler]
+options=-S2
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../../../..

+ 872 - 0
fcl/db/sqldb/odbc/odbcconn.pas

@@ -0,0 +1,872 @@
+(******************************************************************************
+ *                                                                            *
+ *  (c) 2005 Hexis BV                                                         *
+ *                                                                            *
+ *  File:        odbcconn.pas                                                 *
+ *  Author:      Bram Kuijvenhoven ([email protected])                 *
+ *  Description: ODBC SQLDB unit                                              *
+ *  License:     (modified) LGPL                                              *
+ *                                                                            *
+ ******************************************************************************)
+
+unit odbcconn;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, sqldb, db, odbcsql;
+  
+type
+
+  // forward declarations
+  TODBCConnection = class;
+
+  { TODBCCursor }
+
+  TODBCCursor = class(TSQLCursor)
+  protected
+    FSTMTHandle:SQLHSTMT; // ODBC Statement Handle
+    FQuery:string;        // last prepared query, with :ParamName converted to ?
+    FParamIndex:array of integer; // maps the i-th parameter in the query to the TParams passed to PrepareStatement
+    FParamBuf:array of pointer; // buffers that can be used to bind the i-th parameter in the query
+  public
+    constructor Create(Connection:TODBCConnection);
+    destructor Destroy; override;
+  end;
+  
+  { TODBCHandle } // this name is a bit confusing, but follows the standards for naming classes in sqldb
+
+  TODBCHandle = class(TSQLHandle)
+  protected
+  end;
+  
+  { TODBCEnvironment }
+
+  TODBCEnvironment = class
+  protected
+    FENVHandle:SQLHENV; // ODBC Environment Handle
+  public
+    constructor Create;
+    destructor Destroy; override;
+  end;
+
+  { TODBCConnection }
+
+  TODBCConnection = class(TSQLConnection)
+  private
+    FDataSourceName: string;
+    FDriver: string;
+    FEnvironment:TODBCEnvironment;
+    FDBCHandle:SQLHDBC; // ODBC Connection Handle
+    FFileDSN: string;
+    
+    procedure SetParameters(ODBCCursor:TODBCCursor; AParams:TParams);
+    procedure FreeParamBuffers(ODBCCursor:TODBCCursor);
+  protected
+    // Overrides from TSQLConnection
+    function GetHandle:pointer; override;
+    // - Connect/disconnect
+    procedure DoInternalConnect; override;
+    procedure DoInternalDisconnect; override;
+    // - Handle (de)allocation
+    function AllocateCursorHandle:TSQLCursor; override;
+    procedure DeAllocateCursorHandle(var cursor:TSQLCursor); override;
+    function AllocateTransactionHandle:TSQLHandle; override;
+    // - Statement handling
+    procedure PrepareStatement(cursor:TSQLCursor; ATransaction:TSQLTransaction; buf:string; AParams:TParams); override;
+    procedure UnPrepareStatement(cursor:TSQLCursor); override;
+    // - Transaction handling
+    function GetTransactionHandle(trans:TSQLHandle):pointer; override;
+    function StartDBTransaction(trans:TSQLHandle; AParams:string):boolean; override;
+    function Commit(trans:TSQLHandle):boolean; override;
+    function Rollback(trans:TSQLHandle):boolean; override;
+    procedure CommitRetaining(trans:TSQLHandle); override;
+    procedure RollbackRetaining(trans:TSQLHandle); override;
+    // - Statement execution
+    procedure Execute(cursor:TSQLCursor; ATransaction:TSQLTransaction; AParams:TParams); override;
+    // - Result retrieving
+    procedure AddFieldDefs(cursor:TSQLCursor; FieldDefs:TFieldDefs); override;
+    function Fetch(cursor:TSQLCursor):boolean; override;
+    function LoadField(cursor:TSQLCursor; FieldDef:TFieldDef; buffer:pointer):boolean; override;
+    function CreateBlobStream(Field:TField; Mode:TBlobStreamMode):TStream; override;
+    procedure FreeFldBuffers(cursor:TSQLCursor); override;
+    // - UpdateIndexDefs
+    procedure UpdateIndexDefs(var IndexDefs:TIndexDefs; TableName:string); override;
+    // - Schema info
+    function GetSchemaInfoSQL(SchemaType:TSchemaType; SchemaObjectName, SchemaObjectPattern:string):string; override;
+    
+    // Internal utility functions
+    function CreateConnectionString:string;
+  public
+    property Environment:TODBCEnvironment read FEnvironment;
+  published
+    property Driver:string read FDriver write FDriver;                         // will be passed as DRIVER connection parameter
+    property FileDSN:string read FFileDSN write FFileDSN;                      // will be passed as FILEDSN parameter
+    // Redeclare properties from TSQLConnection
+    property Password;     // will be passed as PWD connection parameter
+    property Transaction;
+    property UserName;     // will be passed as UID connection parameter
+    property CharSet;
+    property HostName;     // ignored
+    // Redeclare properties from TDatabase
+    property Connected;
+    property Role;
+    property DatabaseName; // will be passed as DSN connection parameter
+    property KeepConnection;
+    property LoginPrompt;  // if true, ODBC drivers might prompt for more details that are not in the connection string
+    property Params;       // will be added to connection string
+    property OnLogin;
+  end;
+  
+  EODBCException = class(Exception)
+    // currently empty; perhaps we can add fields here later that describe the error instead of one simple message string
+  end;
+
+implementation
+
+uses
+  Math; // for the Min proc
+
+const
+  DefaultEnvironment:TODBCEnvironment = nil;
+  ODBCLoadCount:integer = 0; // ODBC is loaded when > 0; modified by TODBCEnvironment.Create/Destroy
+  
+{ Generic ODBC helper functions }
+
+function ODBCSucces(const Res:SQLRETURN):boolean;
+begin
+  Result:=(Res=SQL_SUCCESS) or (Res=SQL_SUCCESS_WITH_INFO);
+end;
+
+procedure ODBCCheckResult(HandleType:SQLSMALLINT; AHandle: SQLHANDLE; ErrorMsg: string);
+
+  // check return value from SQLGetDiagField/Rec function itself
+  procedure CheckSQLGetDiagResult(const Res:SQLRETURN);
+  begin
+    case Res of
+      SQL_INVALID_HANDLE:
+        raise EODBCException.Create('Invalid handle passed to SQLGetDiagRec/Field');
+      SQL_ERROR:
+        raise EODBCException.Create('An invalid parameter was passed to SQLGetDiagRec/Field');
+      SQL_NO_DATA:
+        raise EODBCException.Create('A too large RecNumber was passed to SQLGetDiagRec/Field');
+    end;
+  end;
+
+var
+  NativeError:SQLINTEGER;
+  TextLength:SQLSMALLINT;
+  Res,LastReturnCode:SQLRETURN;
+  SqlState,MessageText,TotalMessage:string;
+  RecNumber:SQLSMALLINT;
+begin
+  // check result
+  Res:=SQLGetDiagField(HandleType,AHandle,0,SQL_DIAG_RETURNCODE,@LastReturnCode,0,TextLength);
+  CheckSQLGetDiagResult(Res);
+  if ODBCSucces(LastReturnCode) then
+    Exit; // no error; all is ok
+    
+  // build TotalMessage for exception to throw
+  TotalMessage:=Format('%s ODBC error details:',[ErrorMsg]);
+  // retrieve status records
+  SetLength(SqlState,5); // SqlState buffer
+  RecNumber:=1;
+  repeat
+    // dummy call to get correct TextLength
+    Res:=SQLGetDiagRec(HandleType,AHandle,RecNumber,@(SqlState[1]),NativeError,@(SqlState[1]),0,TextLength);
+    if Res=SQL_NO_DATA then
+      Break; // no more status records
+    CheckSQLGetDiagResult(Res);
+    if TextLength>0 then // if TextLength=0 we don't need another call; also our string buffer would not point to a #0, but be a nil pointer
+    begin
+      // allocate large enough buffer
+      SetLength(MessageText,TextLength); // note: ansistrings of Length>0 are always terminated by a #0 character, so this is safe
+      // actual call
+      Res:=SQLGetDiagRec(HandleType,AHandle,RecNumber,@(SqlState[1]),NativeError,@(MessageText[1]),Length(MessageText)+1,TextLength);
+      CheckSQLGetDiagResult(Res);
+    end;
+    // add to TotalMessage
+    TotalMessage:=TotalMessage + Format(' Record %d: SqlState: %s; NativeError: %d; Message: %s;',[RecNumber,SqlState,NativeError,MessageText]);
+    // incement counter
+    Inc(RecNumber);
+  until false;
+  // raise error
+  raise EODBCException.Create(TotalMessage);
+end;
+
+{ TODBCConnection }
+
+// Creates a connection string using the current value of the fields
+function TODBCConnection.CreateConnectionString: string;
+
+  // encloses a param value with braces if necessary, i.e. when any of the characters []{}(),;?*=!@ is in the value
+  function EscapeParamValue(const s:string):string;
+  var
+    NeedEscape:boolean;
+    i:integer;
+  begin
+    NeedEscape:=false;
+    for i:=1 to Length(s) do
+      if s[i] in ['[',']','{','}','(',')',',','*','=','!','@'] then
+      begin
+        NeedEscape:=true;
+        Break;
+      end;
+    if NeedEscape then
+      Result:='{'+s+'}'
+    else
+      Result:=s;
+  end;
+  
+var
+  i: Integer;
+  Param: string;
+  EqualSignPos:integer;
+begin
+  Result:='';
+  if DatabaseName<>'' then Result:=Result + 'DSN='+EscapeParamValue(DatabaseName)+';';
+  if Driver      <>'' then Result:=Result + 'DRIVER='+EscapeParamValue(Driver)+';';
+  if UserName    <>'' then Result:=Result + 'UID='+EscapeParamValue(UserName)+';PWD='+EscapeParamValue(Password)+';';
+  if FileDSN     <>'' then Result:=Result + 'FILEDSN='+EscapeParamValue(FileDSN)+'';
+  for i:=0 to Params.Count-1 do
+  begin
+    Param:=Params[i];
+    EqualSignPos:=Pos('=',Param);
+    if EqualSignPos=0 then
+      raise EODBCException.CreateFmt('Invalid parameter in Params[%d]; can''t find a ''='' in ''%s''',[i, Param])
+    else if EqualSignPos=1 then
+      raise EODBCException.CreateFmt('Invalid parameter in Params[%d]; no identifier before the ''='' in ''%s''',[i, Param])
+    else
+      Result:=Result + EscapeParamValue(Copy(Param,1,EqualSignPos-1))+'='+EscapeParamValue(Copy(Param,EqualSignPos+1,MaxInt));
+  end;
+end;
+
+procedure TODBCConnection.SetParameters(ODBCCursor: TODBCCursor; AParams: TParams);
+var
+  ParamIndex:integer;
+  Buf:pointer;
+  I:integer;
+  IntVal:longint;
+  StrVal:string;
+  StrLen:SQLINTEGER;
+begin
+  // Note: it is assumed that AParams is the same as the one passed to PrepareStatement, in the sense that
+  //       the parameters have the same order and names
+
+  if Length(ODBCCursor.FParamIndex)>0 then
+    if not Assigned(AParams) then
+      raise EODBCException.CreateFmt('The query has parameter markers in it, but no actual parameters were passed',[]);
+
+  SetLength(ODBCCursor.FParamBuf, Length(ODBCCursor.FParamIndex));
+  for i:=0 to High(ODBCCursor.FParamIndex) do
+  begin
+    ParamIndex:=ODBCCursor.FParamIndex[i];
+    if (ParamIndex<0) or (ParamIndex>=AParams.Count) then
+      raise EODBCException.CreateFmt('Parameter %d in query does not have a matching parameter set',[i]);
+    case AParams[ParamIndex].DataType of
+      ftInteger:
+        begin
+          Buf:=GetMem(4);
+          IntVal:=AParams[ParamIndex].AsInteger;
+          Move(IntVal,Buf^,4);
+          ODBCCursor.FParamBuf[i]:=Buf;
+          SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
+                           i+1,                    // ParameterNumber
+                           SQL_PARAM_INPUT,        // InputOutputType
+                           SQL_C_LONG,             // ValueType
+                           SQL_INTEGER,            // ParameterType
+                           10,                     // ColumnSize
+                           0,                      // DecimalDigits
+                           Buf,                    // ParameterValuePtr
+                           0,                      // BufferLength
+                           nil);                   // StrLen_or_IndPtr
+          ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i]));
+        end;
+      ftString:
+        begin
+          StrVal:=AParams[ParamIndex].AsString;
+          StrLen:=Length(StrVal);
+          Buf:=GetMem(SizeOf(SQLINTEGER)+StrLen);
+          Move(StrLen,    buf^,                    SizeOf(SQLINTEGER));
+          Move(StrVal[1],(buf+SizeOf(SQLINTEGER))^,StrLen);
+          ODBCCursor.FParamBuf[i]:=Buf;
+          SQLBindParameter(ODBCCursor.FSTMTHandle, // StatementHandle
+                           i+1,                    // ParameterNumber
+                           SQL_PARAM_INPUT,        // InputOutputType
+                           SQL_C_CHAR,             // ValueType
+                           SQL_CHAR,               // ParameterType
+                           StrLen,                 // ColumnSize
+                           0,                      // DecimalDigits
+                           buf+SizeOf(SQLINTEGER), // ParameterValuePtr
+                           StrLen,                 // BufferLength
+                           Buf);                   // StrLen_or_IndPtr
+          ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not bind parameter %d',[i]));
+        end;
+    else
+      raise EDataBaseError.CreateFmt('Parameter %d is of type %s, which not supported yet',[ParamIndex, Fieldtypenames[AParams[ParamIndex].DataType]]);
+    end;
+  end;
+end;
+
+procedure TODBCConnection.FreeParamBuffers(ODBCCursor: TODBCCursor);
+var
+  i:integer;
+begin
+  for i:=0 to High(ODBCCursor.FParamBuf) do
+    FreeMem(ODBCCursor.FParamBuf[i]);
+end;
+
+function TODBCConnection.GetHandle: pointer;
+begin
+  // I'm not sure whether this is correct; perhaps we should return nil
+  Result:=pointer(FDBCHandle); // note that FDBHandle is a LongInt, because ODBC handles are integers, not pointers
+end;
+
+procedure TODBCConnection.DoInternalConnect;
+const
+  BufferLength = 1024; // should be at least 1024 according to the ODBC specification
+var
+  ConnectionString:string;
+  OutConnectionString:string;
+  ActualLength:SQLSMALLINT;
+begin
+  inherited DoInternalConnect;
+  
+  // make sure we have an environment
+  if not Assigned(FEnvironment) then
+  begin
+    if not Assigned(DefaultEnvironment) then
+      DefaultEnvironment:=TODBCEnvironment.Create;
+    FEnvironment:=DefaultEnvironment;
+  end;
+    
+  // allocate connection handle
+  SQLAllocHandle(SQL_HANDLE_DBC,Environment.FENVHandle,FDBCHandle);
+  ODBCCheckResult(SQL_HANDLE_ENV,Environment.FENVHandle,'Could not allocate ODBC Connection handle.');
+
+  // connect
+  ConnectionString:=CreateConnectionString;
+  SetLength(OutConnectionString,BufferLength-1); // allocate completed connection string buffer (using the ansistring #0 trick)
+  SQLDriverConnect(FDBCHandle,               // the ODBC connection handle
+                   0,                        // no parent window (would be required for prompts)
+                   PChar(ConnectionString),  // the connection string
+                   Length(ConnectionString), // connection string length
+                   @(OutConnectionString[1]),// buffer for storing the completed connection string
+                   BufferLength,             // length of the buffer
+                   ActualLength,             // the actual length of the completed connection string
+                   SQL_DRIVER_NOPROMPT);     // don't prompt for password etc.
+  ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,Format('Could not connect with connection string "%s".',[ConnectionString]));
+  if ActualLength<BufferLength-1 then
+    SetLength(OutConnectionString,ActualLength); // fix completed connection string length
+
+  // set connection attributes (none yet)
+end;
+
+procedure TODBCConnection.DoInternalDisconnect;
+begin
+  inherited DoInternalDisconnect;
+  
+  // disconnect
+  SQLDisconnect(FDBCHandle);
+  ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,'Could not disconnect.');
+  
+  // deallocate connection handle
+  if SQLFreeHandle(SQL_HANDLE_DBC, FDBCHandle)=SQL_ERROR then
+    ODBCCheckResult(SQL_HANDLE_DBC,FDBCHandle,'Could not free connection handle.');
+end;
+
+function TODBCConnection.AllocateCursorHandle: TSQLCursor;
+begin
+  Result:=TODBCCursor.Create(self);
+end;
+
+procedure TODBCConnection.DeAllocateCursorHandle(var cursor: TSQLCursor);
+begin
+  FreeAndNil(cursor); // the destructor of TODBCCursor frees the ODBC Statement handle
+end;
+
+function TODBCConnection.AllocateTransactionHandle: TSQLHandle;
+begin
+  Result:=nil; // not yet supported; will move connection handles to transaction handles later
+end;
+
+procedure TODBCConnection.PrepareStatement(cursor: TSQLCursor; ATransaction: TSQLTransaction; buf: string; AParams: TParams);
+type
+  // used for ParamPart
+  TStringPart = record
+    Start,Stop:integer;
+  end;
+const
+  ParamAllocStepSize = 8;
+var
+  ODBCCursor:TODBCCursor;
+  p,ParamNameStart,BufStart:PChar;
+  ParamName:string;
+  QuestionMarkParamCount,ParameterIndex,NewLength:integer;
+  ParamCount:integer; // actual number of parameters encountered so far;
+                      // always <= Length(ParamPart) = Length(ODBCCursor.FParamIndex)
+                      // ODBCCursor.FParamIndex will have length ParamCount in the end
+  ParamPart:array of TStringPart; // describe which parts of buf are parameters
+  NewQueryLength:integer;
+  NewQuery:string;
+  NewQueryIndex,BufIndex,CopyLen,i:integer;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+  
+  // Parameter handling
+  // Note: We can only pass ? parameters to ODBC, so we should convert named parameters like :MyID
+  //       ODBCCursor.FParamIndex will map th i-th ? token in the (modified) query to an index for AParams
+
+  // Parse the SQL and build FParamIndex
+  ParamCount:=0;
+  NewQueryLength:=Length(buf);
+  SetLength(ParamPart,ParamAllocStepSize);
+  SetLength(ODBCCursor.FParamIndex,ParamAllocStepSize);
+  QuestionMarkParamCount:=0; // number of ? params found in query so far
+  p:=PChar(buf);
+  BufStart:=p; // used to calculate ParamPart.Start values
+  repeat
+    case p^ of
+      '''': // single quote delimited string (not obligatory in ODBC, but let's handle it anyway)
+        begin
+          Inc(p);
+          while not (p^ in [#0, '''']) do
+          begin
+            if p^='\' then Inc(p,2) // make sure we handle \' and \\ correct
+            else Inc(p);
+          end;
+          if p^='''' then Inc(p); // skip final '
+        end;
+      '"':  // double quote delimited string
+        begin
+          Inc(p);
+          while not (p^ in [#0, '"']) do
+          begin
+            if p^='\'  then Inc(p,2) // make sure we handle \" and \\ correct
+            else Inc(p);
+          end;
+          if p^='"' then Inc(p); // skip final "
+        end;
+      '-': // possible start of -- comment
+        begin
+          Inc(p);
+          if p='-' then // -- comment
+          begin
+            repeat // skip until at end of line
+              Inc(p);
+            until p^ in [#10, #0];
+          end
+        end;
+      '/': // possible start of /* */ comment
+        begin
+          Inc(p);
+          if p^='*' then // /* */ comment
+          begin
+            repeat
+              Inc(p);
+              if p^='*' then // possible end of comment
+              begin
+                Inc(p);
+                if p^='/' then Break; // end of comment
+              end;
+            until p^=#0;
+            if p^='/' then Inc(p); // skip final /
+          end;
+        end;
+      ':','?': // parameter
+        begin
+          Inc(ParamCount);
+          if ParamCount>Length(ParamPart) then
+          begin
+            NewLength:=Length(ParamPart)+ParamAllocStepSize;
+            SetLength(ParamPart,NewLength);
+            SetLength(ODBCCursor.FParamIndex,NewLength);
+          end;
+        
+          if p^=':' then
+          begin // find parameter name
+            Inc(p);
+            ParamNameStart:=p;
+            while not (p^ in (SQLDelimiterCharacters+[#0])) do
+              Inc(p);
+            ParamName:=Copy(ParamNameStart,1,p-ParamNameStart);
+          end
+          else
+          begin
+            Inc(p);
+            ParamNameStart:=p;
+            ParamName:='';
+          end;
+          
+          // find ParameterIndex
+          if ParamName<>'' then
+          begin
+            if AParams=nil then
+              raise EDataBaseError.CreateFmt('Found parameter marker with name %s in the query, but no actual parameters are given at all',[ParamName]);
+            ParameterIndex:=AParams.ParamByName(ParamName).Index // lookup parameter in AParams
+          end
+          else
+          begin
+            ParameterIndex:=QuestionMarkParamCount;
+            Inc(QuestionMarkParamCount);
+          end;
+          
+          // store ParameterIndex in FParamIndex, ParamPart data
+          ODBCCursor.FParamIndex[ParamCount-1]:=ParameterIndex;
+          ParamPart[ParamCount-1].Start:=ParamNameStart-BufStart;
+          ParamPart[ParamCount-1].Stop:=p-BufStart+1;
+          
+          // update NewQueryLength
+          Dec(NewQueryLength,p-ParamNameStart);
+        end;
+      #0:Break;
+    else
+      Inc(p);
+    end;
+  until false;
+
+  SetLength(ParamPart,ParamCount);
+  SetLength(ODBCCursor.FParamIndex,ParamCount);
+  
+  if ParamCount>0 then
+  begin
+    // replace :ParamName by ? (using ParamPart array and NewQueryLength)
+    SetLength(NewQuery,NewQueryLength);
+    NewQueryIndex:=1;
+    BufIndex:=1;
+    for i:=0 to High(ParamPart) do
+    begin
+      CopyLen:=ParamPart[i].Start-BufIndex;
+      Move(buf[BufIndex],NewQuery[NewQueryIndex],CopyLen);
+      Inc(NewQueryIndex,CopyLen);
+      NewQuery[NewQueryIndex]:='?';
+      Inc(NewQueryIndex);
+      BufIndex:=ParamPart[i].Stop;
+    end;
+    CopyLen:=Length(Buf)+1-BufIndex;
+    Move(buf[BufIndex],NewQuery[NewQueryIndex],CopyLen);
+  end
+  else
+    NewQuery:=buf;
+    
+  // prepare statement
+  SQLPrepare(ODBCCursor.FSTMTHandle, PChar(NewQuery), Length(NewQuery));
+  ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not prepare statement.');
+  
+  ODBCCursor.FQuery:=NewQuery;
+end;
+
+procedure TODBCConnection.UnPrepareStatement(cursor: TSQLCursor);
+begin
+  // not necessary in ODBC
+end;
+
+function TODBCConnection.GetTransactionHandle(trans: TSQLHandle): pointer;
+begin
+  // Tranactions not implemented yet
+end;
+
+function TODBCConnection.StartDBTransaction(trans: TSQLHandle; AParams:string): boolean;
+begin
+  // Tranactions not implemented yet
+end;
+
+function TODBCConnection.Commit(trans: TSQLHandle): boolean;
+begin
+  // Tranactions not implemented yet
+end;
+
+function TODBCConnection.Rollback(trans: TSQLHandle): boolean;
+begin
+  // Tranactions not implemented yet
+end;
+
+procedure TODBCConnection.CommitRetaining(trans: TSQLHandle);
+begin
+  // Tranactions not implemented yet
+end;
+
+procedure TODBCConnection.RollbackRetaining(trans: TSQLHandle);
+begin
+  // Tranactions not implemented yet
+end;
+
+procedure TODBCConnection.Execute(cursor: TSQLCursor; ATransaction: TSQLTransaction; AParams: TParams);
+var
+  ODBCCursor:TODBCCursor;
+  Res:SQLRETURN;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+  
+  // set parameters
+  SetParameters(ODBCCursor, AParams);
+
+  // execute the statement
+  Res:=SQLExecute(ODBCCursor.FSTMTHandle);
+  ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not execute statement.');
+  
+  // free parameter buffers
+  FreeParamBuffers(ODBCCursor);
+end;
+
+function TODBCConnection.Fetch(cursor: TSQLCursor): boolean;
+var
+  ODBCCursor:TODBCCursor;
+  Res:SQLRETURN;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+  
+  // fetch new row
+  Res:=SQLFetch(ODBCCursor.FSTMTHandle);
+  if Res<>SQL_NO_DATA then
+    ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not fetch new row from result set');
+  
+  // result is true iff a new row was available
+  Result:=Res<>SQL_NO_DATA;
+end;
+
+function TODBCConnection.LoadField(cursor: TSQLCursor; FieldDef: TFieldDef; buffer: pointer): boolean;
+var
+  ODBCCursor:TODBCCursor;
+  StrLenOrInd:SQLINTEGER;
+  ODBCDateStruct:SQL_DATE_STRUCT;
+  ODBCTimeStruct:SQL_TIME_STRUCT;
+  ODBCTimeStampStruct:SQL_TIMESTAMP_STRUCT;
+  DateTime:TDateTime;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+  
+  // load the field using SQLGetData
+  // Note: optionally we can implement the use of SQLBindCol later for even more speed
+  // TODO: finish this
+  case FieldDef.DataType of
+    ftFixedChar,ftString: // are both mapped to TStringField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_CHAR, buffer, FieldDef.Size, @StrLenOrInd);
+    ftSmallint:           // mapped to TSmallintField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SSHORT, buffer, SizeOf(Smallint), @StrLenOrInd);
+    ftInteger,ftWord:     // mapped to TLongintField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SLONG, buffer, SizeOf(Longint), @StrLenOrInd);
+    ftLargeint:           // mapped to TLargeintField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_SBIGINT, buffer, SizeOf(Largeint), @StrLenOrInd);
+    ftFloat:              // mapped to TFloatField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_DOUBLE, buffer, SizeOf(Double), @StrLenOrInd);
+    ftTime:               // mapped to TTimeField
+    begin
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIME, @ODBCTimeStruct, SizeOf(SQL_TIME_STRUCT), @StrLenOrInd);
+      DateTime:=TimeStructToDateTime(@ODBCTimeStruct);
+      Move(DateTime, buffer^, SizeOf(TDateTime));
+    end;
+    ftDate:               // mapped to TDateField
+    begin
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_DATE, @ODBCDateStruct, SizeOf(SQL_DATE_STRUCT), @StrLenOrInd);
+      DateTime:=DateStructToDateTime(@ODBCDateStruct);
+      Move(DateTime, buffer^, SizeOf(TDateTime));
+    end;
+    ftDateTime:           // mapped to TDateTimeField
+    begin
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_TYPE_TIMESTAMP, @ODBCTimeStampStruct, SizeOf(SQL_TIMESTAMP_STRUCT), @StrLenOrInd);
+      DateTime:=TimeStampStructToDateTime(@ODBCTimeStampStruct);
+      Move(DateTime, buffer^, SizeOf(TDateTime));
+    end;
+    ftBoolean:            // mapped to TBooleanField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BIT, buffer, SizeOf(Wordbool), @StrLenOrInd);
+    ftBytes:              // mapped to TBytesField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
+    ftVarBytes:           // mapped to TVarBytesField
+      SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
+    // TODO: Loading of other field types
+  else
+    raise EODBCException.CreateFmt('Tried to load field of unsupported field type %s',[Fieldtypenames[FieldDef.DataType]]);
+  end;
+  ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get field data for field ''%s'' (index %d).',[FieldDef.Name, FieldDef.Index+1]));
+  Result:=StrLenOrInd<>SQL_NULL_DATA; // Result indicates whether the value is non-null
+
+//  writeln(Format('Field.Size: %d; StrLenOrInd: %d',[FieldDef.Size, StrLenOrInd]));
+end;
+
+function TODBCConnection.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
+begin
+  // TODO: implement TODBCConnection.CreateBlobStream
+  Result:=nil;
+end;
+
+procedure TODBCConnection.FreeFldBuffers(cursor: TSQLCursor);
+var
+  ODBCCursor:TODBCCursor;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+
+  SQLFreeStmt(ODBCCursor.FSTMTHandle, SQL_CLOSE);
+  ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not close ODBC statement cursor.');
+end;
+
+procedure TODBCConnection.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TFieldDefs);
+const
+  ColNameDefaultLength = 40; // should be > 0, because an ansistring of length 0 is a nil pointer instead of a pointer to a #0
+var
+  ODBCCursor:TODBCCursor;
+  ColumnCount:SQLSMALLINT;
+  i:integer;
+  ColNameLength,DataType,DecimalDigits,Nullable:SQLSMALLINT;
+  ColumnSize:SQLUINTEGER;
+  ColName:string;
+  FieldType:TFieldType;
+  FieldSize:word;
+begin
+  ODBCCursor:=cursor as TODBCCursor;
+  
+  // get number of columns in result set
+  SQLNumResultCols(ODBCCursor.FSTMTHandle, ColumnCount);
+  ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could not determine number of columns in result set.');
+
+  for i:=1 to ColumnCount do
+  begin
+    SetLength(ColName,ColNameDefaultLength); // also garantuees uniqueness
+
+    // call with default column name buffer
+    SQLDescribeCol(ODBCCursor.FSTMTHandle, // statement handle
+                   i,                      // column number, is 1-based (Note: column 0 is the bookmark column in ODBC)
+                   @(ColName[1]),          // default buffer
+                   ColNameDefaultLength+1, // and its length; we include the #0 terminating any ansistring of Length > 0 in the buffer
+                   ColNameLength,          // actual column name length
+                   DataType,               // the SQL datatype for the column
+                   ColumnSize,             // column size
+                   DecimalDigits,          // number of decimal digits
+                   Nullable);              // SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN
+    ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column properties for column %d.',[i]));
+
+    // truncate buffer or make buffer long enough for entire column name (note: the call is the same for both cases!)
+    SetLength(ColName,ColNameLength);
+    // check whether entire column name was returned
+    if ColNameLength>ColNameDefaultLength then
+    begin
+      // request column name with buffer that is long enough
+      SQLColAttribute(ODBCCursor.FSTMTHandle, // statement handle
+                      i,                      // column number
+                      SQL_DESC_NAME,          // the column name or alias
+                      @(ColName[1]),          // buffer
+                      ColNameLength+1,        // buffer size
+                      @ColNameLength,         // actual length
+                      nil);                   // no numerical output
+      ODBCCheckResult(SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, Format('Could not get column name for column %d.',[i]));
+    end;
+      
+    // convert type
+    // NOTE: I made some guesses here after I found only limited information about TFieldType; please report any problems
+    case DataType of
+      SQL_CHAR:          begin FieldType:=ftFixedChar;  FieldSize:=ColumnSize+1; end;
+      SQL_VARCHAR:       begin FieldType:=ftString;     FieldSize:=ColumnSize+1; end;
+      SQL_LONGVARCHAR:   begin FieldType:=ftString;     FieldSize:=ColumnSize+1; end; // no fixed maximum length; make ftMemo when blobs are supported
+      SQL_WCHAR:         begin FieldType:=ftWideString; FieldSize:=ColumnSize+1; end;
+      SQL_WVARCHAR:      begin FieldType:=ftWideString; FieldSize:=ColumnSize+1; end;
+      SQL_WLONGVARCHAR:  begin FieldType:=ftWideString; FieldSize:=ColumnSize+1; end; // no fixed maximum length; make ftMemo when blobs are supported
+      SQL_DECIMAL:       begin FieldType:=ftFloat;      FieldSize:=0; end;
+      SQL_NUMERIC:       begin FieldType:=ftFloat;      FieldSize:=0; end;
+      SQL_SMALLINT:      begin FieldType:=ftSmallint;   FieldSize:=0; end;
+      SQL_INTEGER:       begin FieldType:=ftInteger;    FieldSize:=0; end;
+      SQL_REAL:          begin FieldType:=ftFloat;      FieldSize:=0; end;
+      SQL_FLOAT:         begin FieldType:=ftFloat;      FieldSize:=0; end;
+      SQL_DOUBLE:        begin FieldType:=ftFloat;      FieldSize:=0; end;
+      SQL_BIT:           begin FieldType:=ftBoolean;    FieldSize:=0; end;
+      SQL_TINYINT:       begin FieldType:=ftSmallint;   FieldSize:=0; end;
+      SQL_BIGINT:        begin FieldType:=ftLargeint;   FieldSize:=0; end;
+      SQL_BINARY:        begin FieldType:=ftBytes;      FieldSize:=ColumnSize; end;
+      SQL_VARBINARY:     begin FieldType:=ftVarBytes;   FieldSize:=ColumnSize; end;
+      SQL_LONGVARBINARY: begin FieldType:=ftBlob;       FieldSize:=ColumnSize; end;
+      SQL_TYPE_DATE:     begin FieldType:=ftDate;       FieldSize:=0; end;
+      SQL_TYPE_TIME:     begin FieldType:=ftTime;       FieldSize:=0; end;
+      SQL_TYPE_TIMESTAMP:begin FieldType:=ftTimeStamp;  FieldSize:=0; end;
+{      SQL_TYPE_UTCDATETIME:FieldType:=ftUnknown;}
+{      SQL_TYPE_UTCTIME:   FieldType:=ftUnknown; }
+{      SQL_INTERVAL_MONTH:           FieldType:=ftUnknown;}
+{      SQL_INTERVAL_YEAR:            FieldType:=ftUnknown;}
+{      SQL_INTERVAL_YEAR_TO_MONTH:   FieldType:=ftUnknown;}
+{      SQL_INTERVAL_DAY:             FieldType:=ftUnknown;}
+{      SQL_INTERVAL_HOUR:            FieldType:=ftUnknown;}
+{      SQL_INTERVAL_MINUTE:          FieldType:=ftUnknown;}
+{      SQL_INTERVAL_SECOND:          FieldType:=ftUnknown;}
+{      SQL_INTERVAL_DAY_TO_HOUR:     FieldType:=ftUnknown;}
+{      SQL_INTERVAL_DAY_TO_MINUTE:   FieldType:=ftUnknown;}
+{      SQL_INTERVAL_DAY_TO_SECOND:   FieldType:=ftUnknown;}
+{      SQL_INTERVAL_HOUR_TO_MINUTE:  FieldType:=ftUnknown;}
+{      SQL_INTERVAL_HOUR_TO_SECOND:  FieldType:=ftUnknown;}
+{      SQL_INTERVAL_MINUTE_TO_SECOND:FieldType:=ftUnknown;}
+{      SQL_GUID:          begin FieldType:=ftGuid;       FieldSize:=ColumnSize; end; } // no TGuidField exists yet in the db unit
+    else
+      begin FieldType:=ftUnknown; FieldSize:=ColumnSize; end
+    end;
+
+    // add FieldDef
+    TFieldDef.Create(FieldDefs, ColName, FieldType, FieldSize, False, i);
+  end;
+end;
+
+procedure TODBCConnection.UpdateIndexDefs(var IndexDefs: TIndexDefs; TableName: string);
+begin
+  inherited UpdateIndexDefs(IndexDefs, TableName);
+  // TODO: implement this
+end;
+
+function TODBCConnection.GetSchemaInfoSQL(SchemaType: TSchemaType; SchemaObjectName, SchemaObjectPattern: string): string;
+begin
+  Result:=inherited GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaObjectPattern);
+  // TODO: implement this
+end;
+
+{ TODBCEnvironment }
+
+constructor TODBCEnvironment.Create;
+begin
+  // make sure odbc is loaded
+  if ODBCLoadCount=0 then LoadOdbc;
+  Inc(ODBCLoadCount);
+
+  // allocate environment handle
+  if SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, FENVHandle)=SQL_Error then
+    raise EODBCException.Create('Could not allocate ODBC Environment handle'); // we can't retrieve any more information, because we don't have a handle for the SQLGetDiag* functions
+  
+  // set odbc version
+  SQLSetEnvAttr(FENVHandle, SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0);
+  ODBCCheckResult(SQL_HANDLE_ENV, FENVHandle,'Could not set ODBC version to 3.');
+end;
+
+destructor TODBCEnvironment.Destroy;
+begin
+  // free environment handle
+  if SQLFreeHandle(SQL_HANDLE_ENV, FENVHandle)=SQL_ERROR then
+    ODBCCheckResult(SQL_HANDLE_ENV, FENVHandle, 'Could not free ODBC Environment handle.');
+
+  // free odbc if not used by any TODBCEnvironment object anymore
+  Dec(ODBCLoadCount);
+  if ODBCLoadCount=0 then UnLoadOdbc;
+end;
+
+{ TODBCCursor }
+
+constructor TODBCCursor.Create(Connection:TODBCConnection);
+begin
+  // allocate statement handle
+  SQLAllocHandle(SQL_HANDLE_STMT, Connection.FDBCHandle, FSTMTHandle);
+  ODBCCheckResult(SQL_HANDLE_DBC, Connection.FDBCHandle, 'Could not allocate ODBC Statement handle.');
+end;
+
+destructor TODBCCursor.Destroy;
+begin
+  inherited Destroy;
+  
+  // deallocate statement handle
+  if SQLFreeHandle(SQL_HANDLE_STMT, FSTMTHandle)=SQL_ERROR then
+    ODBCCheckResult(SQL_HANDLE_STMT, FSTMTHandle, 'Could not free ODBC Statement handle.');
+end;
+
+{ finalization }
+
+finalization
+
+  if Assigned(DefaultEnvironment) then
+    DefaultEnvironment.Free;
+
+end.
+