diff --git a/.gitattributes b/.gitattributes
index 733f2d6e50..6a33465fec 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7091,6 +7091,35 @@ packages/rtl-extra/src/win/winsock.pp svneol=native#text/plain
packages/rtl-extra/src/win/winsock2.pp svneol=native#text/plain
packages/rtl-extra/src/wince/winsock.pp svneol=native#text/plain
packages/rtl-extra/src/wince/winsock2.pp svneol=native#text/plain
+packages/rtl-generics/Makefile svneol=native#text/plain
+packages/rtl-generics/Makefile.fpc svneol=native#text/plain
+packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/tcomparer/tcomparerproject.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tcomparer/tcomparerproject.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/thashmap/thashmapproject.lpi svneol=native#text/xml
+packages/rtl-generics/examples/thashmap/thashmapproject.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpi svneol=native#text/xml
+packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpi svneol=native#text/xml
+packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/tqueue/tqueueproject.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tqueue/tqueueproject.lpr svneol=native#text/pascal
+packages/rtl-generics/examples/tstack/tstackproject.lpi svneol=native#text/xml
+packages/rtl-generics/examples/tstack/tstackproject.lpr svneol=native#text/pascal
+packages/rtl-generics/fpmake.pp svneol=native#text/pascal
+packages/rtl-generics/src/generics.collections.pas svneol=native#text/pascal
+packages/rtl-generics/src/generics.defaults.pas svneol=native#text/pascal
+packages/rtl-generics/src/generics.hashes.pas svneol=native#text/pascal
+packages/rtl-generics/src/generics.helpers.pas svneol=native#text/pascal
+packages/rtl-generics/src/generics.memoryexpanders.pas svneol=native#text/pascal
+packages/rtl-generics/src/generics.strings.pas svneol=native#text/pascal
+packages/rtl-generics/src/inc/generics.dictionaries.inc svneol=native#text/pascal
+packages/rtl-generics/src/inc/generics.dictionariesh.inc svneol=native#text/pascal
packages/rtl-objpas/Makefile svneol=native#text/plain
packages/rtl-objpas/Makefile.fpc svneol=native#text/plain
packages/rtl-objpas/Makefile.fpc.fpcmake svneol=native#text/plain
diff --git a/packages/fpmake_add.inc b/packages/fpmake_add.inc
index 3157934b5e..d99ae8d436 100644
--- a/packages/fpmake_add.inc
+++ b/packages/fpmake_add.inc
@@ -104,6 +104,7 @@
add_rexx(ADirectory+IncludeTrailingPathDelimiter('rexx'));
add_rtl_console(ADirectory+IncludeTrailingPathDelimiter('rtl-console'));
add_rtl_extra(ADirectory+IncludeTrailingPathDelimiter('rtl-extra'));
+ add_rtl_generics(ADirectory+IncludeTrailingPathDelimiter('rtl-generics'));
add_rtl_objpas(ADirectory+IncludeTrailingPathDelimiter('rtl-objpas'));
add_rtl_unicode(ADirectory+IncludeTrailingPathDelimiter('rtl-unicode'));
add_sdl(ADirectory+IncludeTrailingPathDelimiter('sdl'));
diff --git a/packages/fpmake_proc.inc b/packages/fpmake_proc.inc
index 354455fe59..328bcdab63 100644
--- a/packages/fpmake_proc.inc
+++ b/packages/fpmake_proc.inc
@@ -605,6 +605,8 @@ end;
{$include rtl-extra/fpmake.pp}
+{$include rtl-generics/fpmake.pp}
+
{$include rtl-objpas/fpmake.pp}
{$include rtl-unicode/fpmake.pp}
diff --git a/packages/rtl-generics/Makefile b/packages/rtl-generics/Makefile
new file mode 100644
index 0000000000..369046a9ac
--- /dev/null
+++ b/packages/rtl-generics/Makefile
@@ -0,0 +1,2486 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2016-06-18 rev 34006]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-embedded i8086-msdos i8086-win16 aarch64-linux aarch64-darwin
+BSDs = freebsd netbsd openbsd darwin dragonfly
+UNIXs = linux $(BSDs) solaris qnx haiku aix
+LIMIT83fs = go32v2 os2 emx watcom msdos win16
+OSNeedsComspecToRunBatch = go32v2 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 COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+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))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+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
+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)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for avr-embedded, a sub-architecture (e.g. SUBARCH=avr25 or SUBARCH=avr35) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+ifneq ($(findstring $(OS_TARGET),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+endif
+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
+ifndef CROSSCOMPILE
+BUILDFULLNATIVE=1
+export BUILDFULLNATIVE
+endif
+ifdef BUILDFULLNATIVE
+BUILDNATIVE=1
+export BUILDNATIVE
+endif
+export OS_TARGET OS_SOURCE ARCH 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
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifneq ($(OS_TARGET),msdos)
+ifndef DARWIN2DARWIN
+ifneq ($(CPU_TARGET),jvm)
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+ifeq ($(OS_TARGET),android)
+ifeq ($(CPU_TARGET),arm)
+BINUTILSPREFIX=arm-linux-androideabi-
+else
+ifeq ($(CPU_TARGET),i386)
+BINUTILSPREFIX=i686-linux-android-
+else
+ifeq ($(CPU_TARGET),mipsel)
+BINUTILSPREFIX=mipsel-linux-android-
+endif
+endif
+endif
+endif
+endif
+endif
+else
+BINUTILSPREFIX=$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifndef FPCFPMAKE
+ifdef CROSSCOMPILE
+ifeq ($(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR)))),)
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPCFPMAKE:=$(shell $(FPCPROG) -PB)
+ifeq ($(strip $(wildcard $(FPCFPMAKE))),)
+FPCFPMAKE:=$(firstword $(FPCPROG))
+endif
+else
+override FPCFPMAKE=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+FPCFPMAKE=$(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR))))
+FPMAKE_SKIP_CONFIG=-n
+export FPCFPMAKE
+export FPMAKE_SKIP_CONFIG
+endif
+else
+FPMAKE_SKIP_CONFIG=-n
+FPCFPMAKE=$(FPC)
+endif
+endif
+override PACKAGE_NAME=googleapi
+override PACKAGE_VERSION=3.1.1
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+override INSTALL_FPCPACKAGE=y
+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
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+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
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+EXEDBGEXT=.dbg
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifneq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),dragonfly)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=df
+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
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),aros)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=aros
+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),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+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
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+EXEDBGEXT=.dSYM
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+ifeq ($(OS_TARGET),wii)
+EXEEXT=.dol
+SHAREDLIBEXT=.so
+SHORTSUFFIX=wii
+endif
+ifeq ($(OS_TARGET),aix)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=aix
+endif
+ifeq ($(OS_TARGET),java)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=java
+endif
+ifeq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=android
+endif
+endif
+ifeq ($(OS_TARGET),msdos)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHORTSUFFIX=d16
+endif
+ifeq ($(OS_TARGET),embedded)
+ifeq ($(CPU_TARGET),i8086)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+else
+EXEEXT=.bin
+endif
+SHORTSUFFIX=emb
+endif
+ifeq ($(OS_TARGET),win16)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w16
+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 /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+NASMNAME=$(BINUTILSPREFIX)nasm
+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
+ifndef NASMPROG
+ifdef CROSSBINDIR
+NASMPROG=$(CROSSBINDIR)/$(NASMNAME)$(SRCEXEEXT)
+else
+NASMPROG=$(NASMNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+NASM=$(NASMPROG)
+ifdef inUnix
+PPAS=./ppas$(SRCBATCHEXT)
+else
+PPAS=ppas$(SRCBATCHEXT)
+endif
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl fpmkunit
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i386-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),arm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),mips-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),jvm-java)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i8086-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i8086-msdos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),i8086-win16)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=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
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(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
+ifdef UNITDIR_FPMAKE_RTL
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_PASZLIB
+PACKAGEDIR_PASZLIB:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_PASZLIB),)
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)),)
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)
+else
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_PASZLIB)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_PASZLIB) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_PASZLIB)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_PASZLIB=
+UNITDIR_PASZLIB:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_PASZLIB),)
+UNITDIR_PASZLIB:=$(firstword $(UNITDIR_PASZLIB))
+else
+UNITDIR_PASZLIB=
+endif
+endif
+ifdef UNITDIR_PASZLIB
+override COMPILER_UNITDIR+=$(UNITDIR_PASZLIB)
+endif
+ifdef UNITDIR_FPMAKE_PASZLIB
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_PASZLIB)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-PROCESS
+PACKAGEDIR_FCL-PROCESS:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-PROCESS),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_FCL-PROCESS) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-PROCESS=
+UNITDIR_FCL-PROCESS:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-PROCESS),)
+UNITDIR_FCL-PROCESS:=$(firstword $(UNITDIR_FCL-PROCESS))
+else
+UNITDIR_FCL-PROCESS=
+endif
+endif
+ifdef UNITDIR_FCL-PROCESS
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-PROCESS)
+endif
+ifdef UNITDIR_FPMAKE_FCL-PROCESS
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FCL-PROCESS)
+endif
+endif
+ifdef REQUIRE_PACKAGES_HASH
+PACKAGEDIR_HASH:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /hash/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_HASH),)
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)),)
+UNITDIR_HASH=$(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)
+else
+UNITDIR_HASH=$(PACKAGEDIR_HASH)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_HASH)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_HASH) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_HASH)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_HASH=
+UNITDIR_HASH:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /hash/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_HASH),)
+UNITDIR_HASH:=$(firstword $(UNITDIR_HASH))
+else
+UNITDIR_HASH=
+endif
+endif
+ifdef UNITDIR_HASH
+override COMPILER_UNITDIR+=$(UNITDIR_HASH)
+endif
+ifdef UNITDIR_FPMAKE_HASH
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_HASH)
+endif
+endif
+ifdef REQUIRE_PACKAGES_LIBTAR
+PACKAGEDIR_LIBTAR:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libtar/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_LIBTAR),)
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)),)
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)
+else
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_LIBTAR)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_LIBTAR) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_LIBTAR)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_LIBTAR=
+UNITDIR_LIBTAR:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /libtar/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_LIBTAR),)
+UNITDIR_LIBTAR:=$(firstword $(UNITDIR_LIBTAR))
+else
+UNITDIR_LIBTAR=
+endif
+endif
+ifdef UNITDIR_LIBTAR
+override COMPILER_UNITDIR+=$(UNITDIR_LIBTAR)
+endif
+ifdef UNITDIR_FPMAKE_LIBTAR
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_LIBTAR)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FPMKUNIT
+PACKAGEDIR_FPMKUNIT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FPMKUNIT),)
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)),)
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_FPMKUNIT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FPMKUNIT=
+UNITDIR_FPMKUNIT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FPMKUNIT),)
+UNITDIR_FPMKUNIT:=$(firstword $(UNITDIR_FPMKUNIT))
+else
+UNITDIR_FPMKUNIT=
+endif
+endif
+ifdef UNITDIR_FPMKUNIT
+override COMPILER_UNITDIR+=$(UNITDIR_FPMKUNIT)
+endif
+ifdef UNITDIR_FPMAKE_FPMKUNIT
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FPMKUNIT)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPMAKE_BUILD_OPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+override FPMAKE_BUILD_OPT+=-XP$(BINUTILSPREFIX)
+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
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+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
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+endif
+ifneq ($(findstring $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
+ifneq ($(findstring $(CPU_TARGET),x86_64 mips mipsel),)
+override FPCOPT+=-Cg
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPMAKEBUILDOPT
+override FPMAKE_BUILD_OPT+=$(FPMAKEBUILDOPT)
+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 AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(strip $(FPC) $(FPCOPT))
+ifneq (,$(findstring -sh ,$(COMPILER)))
+UseEXECPPAS=1
+endif
+ifneq (,$(findstring -s ,$(COMPILER)))
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+UseEXECPPAS=1
+endif
+endif
+ifneq ($(UseEXECPPAS),1)
+EXECPPAS=
+else
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.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))) $(addprefix $(IMPORTLIBPREFIX),$(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)
+ $(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: $(EXAMPLEINSTALLTARGET) $(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_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+ $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+ $(MKDIR) $(DIST_DESTDIR)
+ $(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+ echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+ echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+ echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+ /bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+ $(RUNBATCH) $(ZIPWRAPPER)
+else
+ $(ZIPWRAPPER)
+endif
+endif
+ $(DEL) $(ZIPWRAPPER)
+else
+ $(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+ $(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+ $(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=distinstall
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+override CLEANEXEDBGFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEDBGFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEDBGEXT), $(CLEAN_PROGRAMS)))
+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))) $(addprefix $(IMPORTLIBPREFIX),$(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 CLEANEXEDBGFILES
+ -$(DELTREE) $(CLEANEXEDBGFILES)
+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
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+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
+ifdef LOCALFPMAKEBIN
+ -$(DEL) $(LOCALFPMAKEBIN)
+ -$(DEL) $(FPMAKEBINOBJ)
+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) FPC fpmake... $(FPCFPMAKE)
+ @$(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) 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
+units:
+examples:
+shared:
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+zipexampleinstall: fpc_zipexampleinstall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: units examples shared sourceinstall exampleinstall zipexampleinstall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+fpmake$(SRCEXEEXT): fpmake.pp
+ $(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+ $(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean: $(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+ { $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi; }
+else
+ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+ -$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+distinstall: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+ $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif
diff --git a/packages/rtl-generics/Makefile.fpc b/packages/rtl-generics/Makefile.fpc
new file mode 100644
index 0000000000..06cdbe473d
--- /dev/null
+++ b/packages/rtl-generics/Makefile.fpc
@@ -0,0 +1,102 @@
+#
+# Makefile.fpc for running fpmake
+#
+
+[package]
+name=googleapi
+version=3.1.1
+
+[require]
+packages=rtl fpmkunit
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+[prerules]
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+
+[rules]
+# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own.
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+
+fpmake$(SRCEXEEXT): fpmake.pp
+ $(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
+# most often fail because the dependencies are cleared.
+# In case of a clean, simply do nothing
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+ $(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
+# when the package is compiled using fpcmake prior to running this clean using fpmake
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean: $(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+ { $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi; }
+else
+ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+ -$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+# distinstall also installs the example-sources and omits the location of the source-
+# files from the fpunits.cfg files.
+distinstall: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+ $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall: fpmake$(SRCEXEEXT)
+ $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall: fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+ $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+ $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif
diff --git a/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpi b/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpi
new file mode 100644
index 0000000000..45b6b1eea4
--- /dev/null
+++ b/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpr b/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpr
new file mode 100644
index 0000000000..8ed5c2bf4a
--- /dev/null
+++ b/packages/rtl-generics/examples/tarraydouble/tarrayprojectdouble.lpr
@@ -0,0 +1,91 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+
+program TArrayProjectDouble;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Math, Types, Generics.Collections, Generics.Defaults;
+
+type
+ TDoubleIntegerArray = array of TIntegerDynArray;
+
+procedure PrintMatrix(A: TDoubleIntegerArray);
+var
+ i, j: Integer;
+begin
+ for i := Low(A) to High(A) do
+ begin
+ for j := Low(A[0]) to High(A[0]) do
+ Write(A[i, j]: 3, ' ');
+ Writeln;
+ end;
+ Writeln; Writeln;
+end;
+
+function CustomCompare_1(constref Left, Right: TIntegerDynArray): Integer;
+begin
+ Result := TCompare.Integer(Right[0], Left[0]);
+end;
+
+function CustomCompare_2(constref Left, Right: TIntegerDynArray): Integer;
+var
+ i: Integer;
+begin
+ i := 0;
+ repeat
+ Result := TCompare.Integer(Right[i], Left[i]);
+ Inc(i);
+ until ((Result <> 0) or (i = Length(Left)));
+end;
+
+var
+ A: TDoubleIntegerArray;
+ FoundIndex: Integer;
+ i, j: Integer;
+
+begin
+ WriteLn('Working with TArray - a two-dimensional integer array');
+ WriteLn;
+
+ // Fill integer array with random numbers [1 .. 50]
+ SetLength(A, 4, 7);
+ Randomize;
+ for i := Low(A) to High(A) do
+ for j := Low(A[0]) to High(A[0]) do
+ A[i, j] := Math.RandomRange(1, 50);
+
+ // Equate some of the elements for further "cascade" sorting
+ A[1, 0] := A[0, 0];
+ A[2, 0] := A[0, 0];
+ A[1, 1] := A[0, 1];
+
+ // Print out what happened
+ Writeln('The original array:');
+ PrintMatrix(A);
+
+ // ! FPC don't support anonymous methods yet
+ //TArray.Sort(A, TComparer.Construct(
+ // function (const Left, Right: TIntegerDynArray): Integer
+ // begin
+ // Result := Right[0] - Left[0];
+ // end));
+ // Sort descending 1st column, with cutom comparer_1
+ TArrayHelper.Sort(A, TComparer.Construct(
+ CustomCompare_1));
+ Writeln('Descending in column 1:');
+ PrintMatrix(A);
+
+ // Sort descending 1st column "cascade" -
+ // If the line items are equal, compare neighboring
+ TArrayHelper.Sort(A, TComparer.Construct(
+ CustomCompare_2));
+ Writeln('Cascade sorting, starting from the 1st column:');
+ PrintMatrix(A);
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpi b/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpi
new file mode 100644
index 0000000000..6d2ee412de
--- /dev/null
+++ b/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpi
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpr b/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpr
new file mode 100644
index 0000000000..49bec2cfca
--- /dev/null
+++ b/packages/rtl-generics/examples/tarraysingle/tarrayprojectsingle.lpr
@@ -0,0 +1,111 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+
+program TArrayProjectSingle;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Math, Types, Generics.Collections, Generics.Defaults;
+
+function CompareIntReverse(constref Left, Right: Integer): Integer;
+begin
+ Result := TCompare.Integer(Right, Left);
+end;
+
+type
+ TForCompare = class
+ public
+ function CompareIntReverseMethod(constref Left, Right: Integer): Integer;
+ end;
+
+function TForCompare.CompareIntReverseMethod(constref Left, Right: Integer): Integer;
+begin
+ Result := TCompare.Integer(Right, Left);
+end;
+
+procedure PrintMatrix(A: TIntegerDynArray);
+var
+ item: Integer;
+begin
+ for item in A do
+ Write(item, ' ');
+ Writeln; Writeln;
+end;
+
+var
+ A: TIntegerDynArray;
+ FoundIndex: PtrInt;
+ ForCompareObj: TForCompare;
+begin
+ WriteLn('Working with TArray - one-dimensional integer array');
+ WriteLn;
+
+ // Fill a one-dimensional array of integers by random numbers [1 .. 10]
+ A := TIntegerDynArray.Create(1, 6, 3, 2, 9);
+
+ // Print out what happened
+ Writeln('The original array:');
+ PrintMatrix(A);
+
+ // Sort ascending without comparator
+ TArrayHelper.Sort(A);
+ Writeln('Ascending Sort without parameters:');
+ PrintMatrix(A);
+
+ // ! FPC don't support anonymous methods yet
+ // Sort descending, the comparator is constructed
+ // using an anonymous method
+ //TArray.Sort(A, TComparer.Construct(
+ // function (const Left, Right: Integer): Integer
+ // begin
+ // Result := Math.CompareValue(Right, Left)
+ // end));
+
+ // Sort descending, the comparator is constructed
+ // using an method
+ TArrayHelper.Sort(A, TComparer.Construct(
+ ForCompareObj.CompareIntReverseMethod));
+ Writeln('Descending by TComparer.Construct(ForCompareObj.Method):');
+ PrintMatrix(A);
+
+ // Again sort ascending by using defaul
+ TArrayHelper.Sort(A, TComparer.Default);
+ Writeln('Ascending by TComparer.Default:');
+ PrintMatrix(A);
+
+ // Again descending using own comparator function
+ TArrayHelper.Sort(A, TComparer.Construct(CompareIntReverse));
+ Writeln('Descending by TComparer.Construct(CompareIntReverse):');
+ PrintMatrix(A);
+
+ // Searches for a nonexistent element
+ Writeln('BinarySearch nonexistent element');
+ if TArrayHelper.BinarySearch(A, 5, FoundIndex) then
+ Writeln('5 is found, its index ', FoundIndex)
+ else
+ Writeln('5 not found!');
+ Writeln;
+
+ // Search for an existing item with default comparer
+ Writeln('BinarySearch for an existing item ');
+ if TArrayHelper.BinarySearch(A, 6, FoundIndex) then
+ Writeln('6 is found, its index ', FoundIndex)
+ else
+ Writeln('6 not found!');
+ Writeln;
+
+ // Search for an existing item with custom comparer
+ Writeln('BinarySearch for an existing item with custom comparer');
+ if TArrayHelper.BinarySearch(A, 6, FoundIndex,
+ TComparer.Construct(CompareIntReverse)) then
+ Writeln('6 is found, its index ', FoundIndex)
+ else
+ Writeln('6 not found!');
+ Writeln;
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpi b/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpi
new file mode 100644
index 0000000000..66e8d8be35
--- /dev/null
+++ b/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpr b/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpr
new file mode 100644
index 0000000000..b7c12823a0
--- /dev/null
+++ b/packages/rtl-generics/examples/tcomparer/tcomparerproject.lpr
@@ -0,0 +1,124 @@
+// Generic types for FreeSparta.com and FreePascal!
+// by Maciej Izak (hnb), 2014
+
+program TComparerProject;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Generics.Collections, Generics.Defaults;
+
+type
+
+ { TCustomer }
+
+ TCustomer = record
+ private
+ FName: string;
+ FMoney: Currency;
+ public
+ constructor Create(const Name: string; Money: Currency);
+ property Name: string read FName write FName;
+ property Money: Currency read FMoney write FMoney;
+ function ToString: string;
+ end;
+
+ TCustomerComparer = class(TComparer)
+ function Compare(constref Left, Right: TCustomer): Integer; override;
+ end;
+
+{ TCustomer }
+
+constructor TCustomer.Create(const Name: string; Money: Currency);
+begin
+ FName := Name;
+ FMoney := Money;
+end;
+
+function TCustomer.ToString: string;
+begin
+ Result := Format('Name: %s >>> Money: %m', [Name, Money]);
+end;
+
+// Ascending
+function TCustomerComparer.Compare(constref Left, Right: TCustomer): Integer;
+begin
+ Result := TCompare.&String(Left.Name, Right.Name);
+ if Result = 0 then
+ Result := TCompare.Currency(Left.Money, Right.Money);
+end;
+
+// Descending
+function CustomerCompare(constref Left, Right: TCustomer): Integer;
+begin
+ Result := TCompare.&String(Right.Name, Left.Name);
+ if Result = 0 then
+ Result := TCompare.Currency(Right.Money, Left.Money);
+end;
+
+var
+ CustomersArray: TArray;
+ CustomersList: TList;
+ Comparer: TCustomerComparer;
+ Customer: TCustomer;
+begin
+ CustomersArray := TArray.Create(
+ TCustomer.Create('Derp', 2000),
+ TCustomer.Create('Sheikh', 2000000000),
+ TCustomer.Create('Derp', 1000),
+ TCustomer.Create('Bill Gates', 1000000000));
+
+ Comparer := TCustomerComparer.Create;
+ Comparer._AddRef;
+
+ // create TList with custom comparer
+ CustomersList := TList.Create(Comparer);
+ CustomersList.AddRange(CustomersArray);
+
+ WriteLn('CustomersList before sort:');
+ for Customer in CustomersList do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ // default sort
+ CustomersList.Sort; // will use TCustomerComparer (passed in the constructor)
+ WriteLn('CustomersList after ascending sort (default with interface from constructor):');
+ for Customer in CustomersList do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ // construct with simple function
+ CustomersList.Sort(TComparer.Construct(CustomerCompare));
+ WriteLn('CustomersList after descending sort (by using construct with function)');
+ WriteLn('CustomersList.Sort(TComparer.Construct(CustomerCompare)):');
+ for Customer in CustomersList do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ // construct with method
+ CustomersList.Sort(TComparer.Construct(Comparer.Compare));
+ WriteLn('CustomersList after ascending sort (by using construct with method)');
+ WriteLn('CustomersList.Sort(TComparer.Construct(Comparer.Compare)):');
+ for Customer in CustomersList do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ WriteLn('CustomersArray before sort:');
+ for Customer in CustomersArray do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ // sort with interface
+ TArrayHelper.Sort(CustomersArray, TCustomerComparer.Create);
+ WriteLn('CustomersArray after ascending sort (by using interfese - no construct)');
+ WriteLn('TArrayHelper.Sort(CustomersArray, TCustomerComparer.Create):');
+ for Customer in CustomersArray do
+ WriteLn(Customer.ToString);
+ WriteLn;
+
+ CustomersList.Free;
+ Comparer._Release;
+ ReadLn;
+end.
+
diff --git a/packages/rtl-generics/examples/thashmap/thashmapproject.lpi b/packages/rtl-generics/examples/thashmap/thashmapproject.lpi
new file mode 100644
index 0000000000..61bd73c661
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmap/thashmapproject.lpi
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/thashmap/thashmapproject.lpr b/packages/rtl-generics/examples/thashmap/thashmapproject.lpr
new file mode 100644
index 0000000000..d9598cab9d
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmap/thashmapproject.lpr
@@ -0,0 +1,218 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+
+program THashMapProject;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Generics.Collections, Generics.Defaults;
+
+type
+ TSubscriberInfo = record
+ Name, SName: string;
+ class function Create(const Name, SName: string): TSubscriberInfo; static;
+ function ToString: string;
+ end;
+
+ // Class containing handlers add / remove items in the dictionary
+ THashMapEventsHandler = class
+ public
+ class procedure OnKeyNotify(Sender: TObject; constref Item: string;
+ Action: TCollectionNotification);
+ class procedure OnValueNotify(Sender: TObject; constref Item: TSubscriberInfo;
+ Action: TCollectionNotification);
+ end;
+
+class function TSubscriberInfo.Create(const Name,
+ SName: string): TSubscriberInfo;
+begin
+ Result.Name := Name;
+ Result.SName := SName;
+end;
+
+function TSubscriberInfo.ToString: string;
+begin
+ Result := Format('%s %s', [Name, SName]);
+end;
+
+// Function to generate the dictionary contents into a string
+function PrintTelephoneDirectory(
+ TelephoneDirectory: THashMap): string;
+var
+ PhoneNumber: string;
+begin
+ Result := Format('Content directory (%d):', [TelephoneDirectory.Count]);
+
+ for PhoneNumber in TelephoneDirectory.Keys do
+ Result := Result + Format(LineEnding + '%s: %s',
+ [PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]);
+end;
+
+// Handlers add / remove items dictionary
+class procedure THashMapEventsHandler.OnKeyNotify(Sender: TObject;
+ constref Item: string; Action: TCollectionNotification);
+begin
+ case Action of
+ cnAdded:
+ Writeln(Format('OnKeyNotify! Phone %s added!', [Item]));
+ cnRemoved:
+ Writeln(Format('OnKeyNotify! Number %s deleted!', [Item]));
+ end;
+end;
+
+class procedure THashMapEventsHandler.OnValueNotify(Sender: TObject;
+ constref Item: TSubscriberInfo; Action: TCollectionNotification);
+begin
+ case Action of
+ cnAdded:
+ Writeln(Format('OnValueNotify! Subscriber %s added!', [Item.ToString]));
+ cnRemoved:
+ Writeln(Format('OnValueNotify! Subscriber %s deleted!', [Item.ToString]));
+ end;
+end;
+
+function CustomCompare(constref Left, Right: TPair): Integer;
+begin
+ // Comparable full first names, and then phones if necessary
+ Result := TCompare.&String(Left.Value.ToString, Right.Value.ToString);
+ if Result = 0 then
+ Result := TCompare.&String(Left.Key, Right.Key);
+end;
+
+var
+ // Declare the "dictionary"
+ // key is the telephone number which will be possible
+ // to determine information about the owner
+ TelephoneDirectory: THashMap;
+ TTelephoneArray: array of TPair;
+ TTelephoneArrayItem: TPair;
+ PhoneNumber: string;
+ Subscriber: TSubscriberInfo;
+begin
+ WriteLn('Working with THashMap - phonebook');
+ WriteLn;
+
+ // create a directory
+ // Constructor has several overloaded options which will
+ // enable the capacity of the container, a comparator for values
+ // or the initial data - we use the easiest option
+ TelephoneDirectory := THashMap.Create;
+
+ // ---------------------------------------------------
+ // 1) Adding items to dictionary
+
+ // Add new users to the phonebook
+ TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
+ TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
+ TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Brad', 'Pitt'));
+ TelephoneDirectory.Add('9204444444', TSubscriberInfo.Create('Brad', 'Pitt'));
+ TelephoneDirectory.Add('9205555555', TSubscriberInfo.Create('Sandra', 'Bullock'));
+ // Adding a new subscriber if number already exist
+ TelephoneDirectory.AddOrSetValue('9204444444',
+ TSubscriberInfo.Create('Angelina', 'Jolie'));
+ // Print list
+ Writeln(PrintTelephoneDirectory(TelephoneDirectory));
+
+ // ---------------------------------------------------
+ // 2) Working with the elements
+
+ // Set the "capacity" of the dictionary according to the current number of elements
+ TelephoneDirectory.TrimExcess;
+ // Is there a key? - ContainsKey
+ if TelephoneDirectory.ContainsKey('9205555555') then
+ Writeln('Phone 9205555555 registered!');
+ // Is there a subscriber? - ContainsValue
+ Subscriber := TSubscriberInfo.Create('Sandra', 'Bullock');
+ if TelephoneDirectory.ContainsValue(Subscriber) then
+ Writeln(Format('%s is in the directory!', [Subscriber.ToString]));
+ // Try to get information via telephone. TryGetValue
+ if TelephoneDirectory.TryGetValue('9204444444', Subscriber) then
+ Writeln(Format('Number 9204444444 belongs to %s', [Subscriber.ToString]));
+ // Directly access by phone number
+ Writeln(Format('Phone 9201111111 subscribers: %s', [TelephoneDirectory['9201111111'].ToString]));
+ // Number of people in the directory
+ Writeln(Format('Total subscribers in the directory: %d', [TelephoneDirectory.Count]));
+
+ // ---------------------------------------------------
+ // 3) Delete items
+
+ // Schwarzenegger now will not be listed
+ TelephoneDirectory.Remove('9201111111');
+ // Completely clear the list
+ TelephoneDirectory.Clear;
+
+ // ---------------------------------------------------
+ // 4) Events add / remove values
+ //
+ // Events OnKeyNotify OnValueNotify are designed for "tracking"
+ // for adding / removing keys and values ​​respectively
+ TelephoneDirectory.OnKeyNotify := THashMapEventsHandler.OnKeyNotify;
+ TelephoneDirectory.OnValueNotify := THashMapEventsHandler.OnValueNotify;
+
+ Writeln;
+ // Try events
+ TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
+ TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
+ TelephoneDirectory['9202222222'] := TSubscriberInfo.Create('Monica', 'Bellucci');
+ TelephoneDirectory.Clear;
+ WriteLn;
+
+ TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Monica', 'Bellucci'));
+ TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Sylvester', 'Stallone'));
+ TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Bruce', 'Willis'));
+ WriteLn;
+
+ // Show keys (phones)
+ Writeln('Keys (phones):');
+ for PhoneNumber in TelephoneDirectory.Keys do
+ Writeln(PhoneNumber);
+ Writeln;
+
+ // Show values ​​(subscribers)
+ Writeln('Values (subscribers):');
+ for Subscriber in TelephoneDirectory.Values do
+ Writeln(Subscriber.ToString);
+ Writeln;
+
+ // All together now
+ Writeln('Subscribers list with phones:');
+ for PhoneNumber in TelephoneDirectory.Keys do
+ Writeln(Format('%s: %s',
+ [PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]));
+ Writeln;
+
+ // In addition, we can "export" from the dictionary
+ // to TArray
+ // Sort the resulting array and display
+ TTelephoneArray := TelephoneDirectory.ToArray;
+
+ // partial specializations not allowed
+ // same for anonymous methods
+ //TArray.Sort>(
+ // TTelephoneArray, TComparer>.Construct(
+ // function (const Left, Right: TPair): Integer
+ // begin
+ // // Comparable full first names, and then phones if necessary
+ // Result := CompareStr(Left.Value.ToString, Right.Value.ToString);
+ // if Result = 0 then
+ // Result := CompareStr(Left.Key, Right.Key);
+ // end));
+
+ TArrayHelper.Sort(
+ TTelephoneArray, TComparer.Construct(
+ CustomCompare));
+ // Print
+ Writeln('Sorted list of subscribers into TArray (by name, and eventually by phone):');
+ for TTelephoneArrayItem in TTelephoneArray do
+ Writeln(Format('%s: %s',
+ [TTelephoneArrayItem.Value.ToString, TTelephoneArrayItem.Key]));
+
+ Writeln;
+ FreeAndNil(TelephoneDirectory);
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpi b/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpi
new file mode 100644
index 0000000000..0c2d179d7d
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpr b/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpr
new file mode 100644
index 0000000000..377bd69c19
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmapcaseinsensitive/thashmapcaseinsensitive.lpr
@@ -0,0 +1,55 @@
+// Generic types for FreeSparta.com and FreePascal!
+// by Maciej Izak (hnb), 2014
+
+program THashMapCaseInsensitive;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ Generics.Collections, Generics.Defaults;
+
+var
+ StringMap: THashMap;
+ AnsiStringMap: THashMap;
+ UnicodeStringMap: THashMap;
+ AdvancedHashMapWithBigLoadFactor: TCuckooD6;
+ k: String;
+begin
+ WriteLn('Working with case insensitive THashMap');
+ WriteLn;
+ // example constructors for different string types
+ StringMap := THashMap.Create(TIStringComparer.Ordinal);
+ StringMap.Free;
+ AnsiStringMap := THashMap.Create(TIAnsiStringComparer.Ordinal);
+ AnsiStringMap.Free;
+ UnicodeStringMap := THashMap.Create(TIUnicodeStringComparer.Ordinal);
+ UnicodeStringMap.Free;
+
+ // standard TI*Comparer is dedicated for MAX_HASHLIST_COUNT = 4 and lower. For example DArrayCuckoo where D = 6
+ // we need to create extra specialized TGIStringComparer type
+ AdvancedHashMapWithBigLoadFactor := TCuckooD6.Create(
+ TGIStringComparer.Ordinal);
+ AdvancedHashMapWithBigLoadFactor.Free;
+
+ // ok lets start
+ // another way to create case insensitive hash map
+ StringMap := THashMap.Create(TGIStringComparer.Ordinal);
+
+ WriteLn('Add Cat and Dog');
+ StringMap.Add('Cat', EmptyRecord);
+ StringMap.Add('Dog', EmptyRecord);
+
+ //
+ WriteLn('Contains CAT = ', StringMap.ContainsKey('CAT'));
+ WriteLn('Contains dOG = ', StringMap.ContainsKey('dOG'));
+ WriteLn('Contains Fox = ', StringMap.ContainsKey('Fox'));
+
+ WriteLn('Enumerate all keys :');
+ for k in StringMap.Keys do
+ WriteLn(' > ', k);
+
+ ReadLn;
+ StringMap.Free;
+end.
+
diff --git a/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpi b/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpi
new file mode 100644
index 0000000000..b32ad72067
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpr b/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpr
new file mode 100644
index 0000000000..d3c9116c77
--- /dev/null
+++ b/packages/rtl-generics/examples/thashmapextendedequalitycomparer/thashmapextendedequalitycomparer.lpr
@@ -0,0 +1,108 @@
+// Generic types for FreeSparta.com and FreePascal!
+// by Maciej Izak (hnb), 2014
+
+program THashMapExtendedEqualityComparer;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Generics.Collections, Generics.Defaults;
+
+type
+
+ { TTaxPayer }
+
+ TTaxPayer = record
+ TaxID: Integer;
+ Name: string;
+
+ constructor Create(ATaxID: Integer; const AName: string);
+ function ToString: string;
+ end;
+
+constructor TTaxPayer.Create(ATaxID: Integer; const AName: string);
+begin
+ TaxID := ATaxID;
+ Name := AName;
+end;
+
+function TTaxPayer.ToString: string;
+begin
+ Result := Format('TaxID = %-10d Name = %-17s', [TaxID, Name]);
+end;
+
+function EqualityComparison(constref ALeft, ARight: TTaxPayer): Boolean;
+begin
+ Result := ALeft.TaxID = ARight.TaxID;
+end;
+
+procedure ExtendedHasher(constref AValue: TTaxPayer; AHashList: PUInt32);
+begin
+ // don't work with TCuckooD6 map because default TCuckooD6 needs TDelphiSixfoldHashFactory
+ // and TDefaultHashFactory = TDelphiQuadrupleHashFactory
+ // (TDelphiQuadrupleHashFactory is compatible with TDelphiDoubleHashFactory and TDelphiHashFactory)
+ TDefaultHashFactory.GetHashList(@AValue.TaxID, SizeOf(Integer), AHashList);
+end;
+
+var
+ map: THashMap; // THashMap = TCuckooD4
+ LTaxPayer: TTaxPayer;
+ LSansa: TTaxPayer;
+ LPair: TPair;
+begin
+ WriteLn('program of tax office - ExtendedEqualityComparer for THashMap');
+ WriteLn;
+
+ // to identify the taxpayer need only nip
+ map := THashMap.Create(
+ TExtendedEqualityComparer.Construct(EqualityComparison, ExtendedHasher));
+
+ map.Add(TTaxPayer.Create(1234567890, 'Joffrey Baratheon'), 'guilty');
+ map.Add(TTaxPayer.Create(90, 'Little Finger'), 'swindler');
+ map.Add(TTaxPayer.Create(667, 'John Snow'), 'delinquent tax');
+
+ // useless in this place but we can convert Keys to TArray :)
+ WriteLn(Format('All taxpayers (count = %d)', [Length(map.Keys.ToArray)]));
+ for LTaxPayer in map.Keys do
+ WriteLn(' > ', LTaxPayer.ToString);
+
+ LSansa := TTaxPayer.Create(667, 'Sansa Stark');
+
+ // exist because custom EqualityComparison and ExtendedHasher
+ WriteLn;
+ WriteLn(LSansa.Name, ' exist in map = ', map.ContainsKey(LSansa));
+ WriteLn;
+
+ //
+ WriteLn('All taxpayers');
+ for LPair in map do
+ WriteLn(' > ', LPair.Key.ToString, ' is ', LPair.Value);
+
+ // Add or set sansa? :)
+ WriteLn;
+ WriteLn(Format('AddOrSet(%s, ''innocent'')', [LSansa.ToString]));
+ map.AddOrSetValue(LSansa, 'innocent');
+ WriteLn;
+
+ //
+ WriteLn('All taxpayers');
+ for LPair in map do
+ WriteLn(' > ', LPair.Key.ToString, ' is ', LPair.Value);
+
+ // Add or set sansa? :)
+ WriteLn;
+ LSansa.TaxID := 668;
+ WriteLn(Format('AddOrSet(%s, ''innocent'')', [LSansa.ToString]));
+ map.AddOrSetValue(LSansa, 'innocent');
+ WriteLn;
+
+ //
+ WriteLn('All taxpayers');
+ for LPair in map do
+ WriteLn(' > ', LPair.Key.ToString, ' is ', LPair.Value);
+
+ ReadLn;
+ map.Free;
+end.
+
diff --git a/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpi b/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpi
new file mode 100644
index 0000000000..63511b3e9c
--- /dev/null
+++ b/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpr b/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpr
new file mode 100644
index 0000000000..179d88595e
--- /dev/null
+++ b/packages/rtl-generics/examples/tobjectlist/tobjectlistproject.lpr
@@ -0,0 +1,194 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+
+program TObjectListProject;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Generics.Collections, Generics.Defaults, DateUtils;
+
+type
+ TPlayer = class
+ public
+ Name, Team: string;
+ BirthDay: TDateTime;
+ NTeamGoals: Byte; // Number of goals for the national team
+ constructor Create(const Name: string; BirthDay: TDateTime;
+ const Team: string; NTeamGoals: Byte = 0);
+ function ToString: string;
+ end;
+
+ // Class containing handlers add / remove list items
+ TListEventsHandler = class
+ public
+ class procedure OnListChanged(Sender: TObject; constref Item: TPlayer;
+ Action: TCollectionNotification);
+ end;
+
+
+constructor TPlayer.Create(const Name: string; BirthDay: TDateTime;
+ const Team: string; NTeamGoals: Byte);
+begin
+ Self.Name := Name;
+ Self.BirthDay := BirthDay;
+ Self.Team := Team;
+ Self.NTeamGoals := NTeamGoals;
+end;
+
+function TPlayer.ToString: string;
+begin
+ Result := Format('%s - Age: %d Team: %s Goals: %d',
+ [Name,
+ DateUtils.YearsBetween(Date, BirthDay),
+ Team, NTeamGoals])
+end;
+
+// Function sort descending goals for the national team
+function ComparePlayersByGoalsDecs(constref Player1, Player2: TPlayer): Integer;
+begin
+ Result := TCompare.UInt8(Player2.NTeamGoals, Player1.NTeamGoals);
+end;
+
+class procedure TListEventsHandler.OnListChanged(Sender: TObject; constref Item: TPlayer;
+ Action: TCollectionNotification);
+var
+ Mes: string;
+begin
+ // Unlike TDictionary we added Action = cnExtracted
+ case Action of
+ cnAdded:
+ Mes := 'added to the list!';
+ cnRemoved:
+ Mes := 'removed from the list!';
+ cnExtracted:
+ Mes := 'extracted from the list!';
+ end;
+ Writeln(Format('Football player %s %s ', [Item.ToString, Mes]));
+end;
+
+var
+ // Declare TObjectList as storage for TPlayer
+ PlayersList: TObjectList;
+ Player: TPlayer;
+ FoundIndex: PtrInt;
+begin
+ WriteLn('Working with TObjectList - football manager');
+ WriteLn;
+
+ PlayersList := TObjectList.Create;
+
+ // ---------------------------------------------------
+ // 1) Adding items
+
+ PlayersList.Add(
+ TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
+ PlayersList.Add(
+ TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
+ PlayersList.Add(
+ TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
+ // Adding the specified position
+ PlayersList.Insert(0,
+ TPlayer.Create('Luis Figo', EncodeDate(1972, 11, 4), 'Portugal', 33));
+ // Add a few players through InsertRange (AddRange works similarly)
+ PlayersList.InsertRange(0,
+ [TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
+ TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
+ TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
+ Player := TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44);
+ PlayersList.Add(Player);
+
+
+ // ---------------------------------------------------
+ // 2) Access and check the items
+
+ // Is there a player in the list - Contains
+ if PlayersList.Contains(Player) then
+ Writeln('Raul is in the list!');
+ // Player index and count of items in the list
+ Writeln(Format('Raul is %d-th on the list of %d players.',
+ [PlayersList.IndexOf(Player) + 1, PlayersList.Count]));
+ // Index access
+ Writeln(Format('1st in the list: %s', [PlayersList[0].ToString]));
+ // The first player
+ Writeln(Format('1st in the list: %s', [PlayersList.First.ToString]));
+ // The last player
+ Writeln(Format('Last in the list: %s', [PlayersList.Last.ToString]));
+ // "Reverse" elements
+ PlayersList.Reverse;
+ Writeln('List items have been "reversed"');
+ Writeln;
+
+
+ // ---------------------------------------------------
+ // 3) Moving and removing items
+
+ // Changing places players in the list
+ PlayersList.Exchange(0, 1);
+ // Move back 1 player
+ PlayersList.Move(1, 0);
+
+ // Removes the element at index
+ PlayersList.Delete(5);
+ // Or a number of elements starting at index
+ PlayersList.DeleteRange(5, 2);
+ // Remove the item from the list, if the item
+ // exists returns its index in the list
+ Writeln(Format('Removed %d-st player', [PlayersList.Remove(Player) + 1]));
+
+ // Extract and return the item, if there is no Player in the list then
+ // Extract will return = nil, (anyway Raul is already removed via Remove)
+ Player := PlayersList.Extract(Player);
+ if Assigned(Player) then
+ Writeln(Format('Extracted: %s', [Player.ToString]));
+
+ // Clear the list completely
+ PlayersList.Clear;
+ Writeln;
+
+ // ---------------------------------------------------
+ // 4) Event OnNotify, sorting and searching
+
+ PlayersList.OnNotify := TListEventsHandler.OnListChanged;
+
+ PlayersList.Add(
+ TPlayer.Create('Zinedine Zidane', EncodeDate(1972, 06, 23), 'France', 31));
+ PlayersList.Add(
+ TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44));
+ PlayersList.Add(
+ TPlayer.Create('Ronaldo', EncodeDate(1976, 09, 22), 'Brazil', 62));
+ PlayersList.AddRange(
+ [TPlayer.Create('David Beckham', EncodeDate(1975, 05, 2), 'England', 17),
+ TPlayer.Create('Alessandro Del Piero', EncodeDate(1974, 11, 9), 'Italy ', 27),
+ TPlayer.Create('Raul', EncodeDate(1977, 06, 27), 'Spain', 44)]);
+
+ PlayersList.Remove(PlayersList.Last);
+ Player := PlayersList.Extract(PlayersList[0]);
+
+ PlayersList.Sort(TComparer.Construct(ComparePlayersByGoalsDecs));
+ Writeln;
+ Writeln('Sorted list of players:');
+ for Player in PlayersList do
+ Writeln(Player.ToString);
+ Writeln;
+
+ // Find Ronaldo!
+ // TArray BinarySearch requires sorted list
+ // IndexOf does not require sorted list
+ // but BinarySearch is usually faster
+ Player := PlayersList[0];
+ if PlayersList.BinarySearch(Player, FoundIndex,
+ TComparer.Construct(ComparePlayersByGoalsDecs)) then
+ Writeln(Format('Ronaldo is in the sorted list at position %d', [FoundIndex + 1]));
+
+ Writeln;
+
+ // With the destruction of the list remove all elements
+ // OnNotify show it
+ FreeAndNil(PlayersList);
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/examples/tqueue/tqueueproject.lpi b/packages/rtl-generics/examples/tqueue/tqueueproject.lpi
new file mode 100644
index 0000000000..5eec3b87fd
--- /dev/null
+++ b/packages/rtl-generics/examples/tqueue/tqueueproject.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tqueue/tqueueproject.lpr b/packages/rtl-generics/examples/tqueue/tqueueproject.lpr
new file mode 100644
index 0000000000..87e51cd101
--- /dev/null
+++ b/packages/rtl-generics/examples/tqueue/tqueueproject.lpr
@@ -0,0 +1,89 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+
+program TQueueProject;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils, Generics.Collections;
+
+type
+ // This is FreeSpaaarta! versions =)
+ TSpartaVersion = (svFreeSparta, svBasic, svStarter, svProfessional);
+
+ TCustomer = record
+ strict private
+ const
+ SV_NAMES: array [TSpartaVersion] of string =
+ ('FreeSparta', 'Basic', 'Starter', 'Professional');
+ public
+ var
+ SpartaVersion: TSpartaVersion;
+ class function Create(SpartaVersion: TSpartaVersion): TCustomer; static;
+ function ToString: string;
+ end;
+
+class function TCustomer.Create(SpartaVersion: TSpartaVersion): TCustomer;
+begin
+ Result.SpartaVersion := SpartaVersion;
+end;
+
+function TCustomer.ToString: string;
+begin
+ Result := Format('Sparta %s', [SV_NAMES[SpartaVersion]])
+end;
+
+var
+ CustomerQueue: TQueue;
+ Customer: TCustomer;
+begin
+ WriteLn('Working with TQueue - buy FreeSparta.com');
+ WriteLn;
+
+ // "Create" turn in sales
+ CustomerQueue := TQueue.Create;
+
+ // Add a few people in the queue
+ // Enqueue - puts the item in the queue
+ CustomerQueue.Enqueue(TCustomer.Create(svFreeSparta));
+ CustomerQueue.Enqueue(TCustomer.Create(svBasic));
+ CustomerQueue.Enqueue(TCustomer.Create(svBasic));
+ CustomerQueue.Enqueue(TCustomer.Create(svBasic));
+ CustomerQueue.Enqueue(TCustomer.Create(svStarter));
+ CustomerQueue.Enqueue(TCustomer.Create(svStarter));
+ CustomerQueue.Enqueue(TCustomer.Create(svProfessional));
+ CustomerQueue.Enqueue(TCustomer.Create(svProfessional));
+
+ // Part of customers served
+ // Dequeue - remove an element from the queue
+ // btw if TQueue is TObjectQueue also call Free for object
+ Customer := CustomerQueue.Dequeue;
+ Writeln(Format('Sold (Dequeue): %s', [Customer.ToString]));
+ // Extract - similar to Dequeue, but causes in OnNotify
+ // Action = cnExtracted instead cnRemoved
+ Customer := CustomerQueue.Extract;
+ Writeln(Format('Sold (Extract): %s', [Customer.ToString]));
+
+ // For what came next buyer?
+ // Peek - returns the first element, but does not remove it from the queue
+ Writeln(Format('Serves customers come for %s',
+ [CustomerQueue.Peek.ToString]));
+
+ // The remaining buyers
+ Writeln;
+ Writeln(Format('Buyers left: %d', [CustomerQueue.Count]));
+ for Customer in CustomerQueue do
+ Writeln(Customer.ToString);
+
+ // We serve all
+ // Clear - clears the queue
+ CustomerQueue.Clear;
+
+ FreeAndNil(CustomerQueue);
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/examples/tstack/tstackproject.lpi b/packages/rtl-generics/examples/tstack/tstackproject.lpi
new file mode 100644
index 0000000000..ccc9bd6793
--- /dev/null
+++ b/packages/rtl-generics/examples/tstack/tstackproject.lpi
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/rtl-generics/examples/tstack/tstackproject.lpr b/packages/rtl-generics/examples/tstack/tstackproject.lpr
new file mode 100644
index 0000000000..1a53e1872a
--- /dev/null
+++ b/packages/rtl-generics/examples/tstack/tstackproject.lpr
@@ -0,0 +1,86 @@
+// Generic types for FreeSparta.com and FreePascal!
+// Original version by keeper89.blogspot.com, 2011
+// FPC version by Maciej Izak (hnb), 2014
+program TStackProject;
+
+{$MODE DELPHI}
+{$APPTYPE CONSOLE}
+
+uses
+ SysUtils,
+ Windows,
+ Generics.Collections;
+
+type
+ // We will cook pancakes, put them on a plate and take the last
+ TPancakeType = (ptMeat, ptCherry, ptCurds);
+
+ TPancake = record
+ strict private
+ const
+ PANCAKE_TYPE_NAMES: array [TPancakeType] of string =
+ ('meat', 'cherry', 'curds');
+ public
+ var
+ PancakeType: TPancakeType;
+ class function Create(PancakeType: TPancakeType): TPancake; static;
+ function ToString: string;
+ end;
+
+class function TPancake.Create(PancakeType: TPancakeType): TPancake;
+begin
+ Result.PancakeType := PancakeType;
+end;
+
+function TPancake.ToString: string;
+begin
+ Result := Format('Pancake with %s', [PANCAKE_TYPE_NAMES[PancakeType]])
+end;
+
+var
+ PancakesPlate: TStack;
+ Pancake: TPancake;
+
+begin
+ WriteLn('Working with TStack - pancakes');
+ WriteLn;
+
+ // "Create" a plate of pancakes
+ PancakesPlate := TStack.Create;
+
+ // Bake some pancakes
+ // Push - puts items on the stack
+ PancakesPlate.Push(TPancake.Create(ptMeat));
+ PancakesPlate.Push(TPancake.Create(ptCherry));
+ PancakesPlate.Push(TPancake.Create(ptCherry));
+ PancakesPlate.Push(TPancake.Create(ptCurds));
+ PancakesPlate.Push(TPancake.Create(ptMeat));
+
+ // Eating some pancakes
+ // Pop - removes an item from the stack
+ Pancake := PancakesPlate.Pop;
+ Writeln(Format('Ate a pancake (Pop): %s', [Pancake.ToString]));
+ // Extract - similar to Pop, but causes in OnNotify
+ // Action = cnExtracted instead of cnRemoved
+ Pancake := PancakesPlate.Extract;
+ Writeln(Format('Ate a pancake (Extract): %s', [Pancake.ToString]));
+
+ // What is the last pancake?
+ // Peek - returns the last item, but does not remove it from the stack
+ Writeln(Format('Last pancake: %s', [PancakesPlate.Peek.ToString]));
+
+ // Show the remaining pancakes
+ Writeln;
+ Writeln(Format('Total pancakes: %d', [PancakesPlate.Count]));
+ for Pancake in PancakesPlate do
+ Writeln(Pancake.ToString);
+
+ // Eat up all
+ // Clear - clears the stack
+ PancakesPlate.Clear;
+
+ FreeAndNil(PancakesPlate);
+
+ Readln;
+end.
+
diff --git a/packages/rtl-generics/fpmake.pp b/packages/rtl-generics/fpmake.pp
new file mode 100644
index 0000000000..dbd04bdcac
--- /dev/null
+++ b/packages/rtl-generics/fpmake.pp
@@ -0,0 +1,78 @@
+{$ifndef ALLPACKAGES}
+program fpmake;
+
+{$mode objfpc}{$h+}
+
+uses fpmkunit;
+{$endif}
+
+Procedure add_rtl_generics(ADirectory : string);
+
+Var
+ P : TPackage;
+ T : TTarget;
+
+begin
+ With Installer do
+ begin
+ P:=AddPackage('rtl-generics');
+ P.ShortName:='rtlgen';
+ P.Author := 'Maciej Izak';
+ P.License := 'LGPL with modification, ';
+ P.HomepageURL := 'www.freepascal.org';
+ P.Email := '';
+ P.Description := 'Generic collection library.';
+ P.NeedLibC:= false;
+ P.OSes := AllOSes;
+ P.Directory:=ADirectory;
+ P.Version:='3.1.1';
+ P.Dependencies.Add('rtl-objpas');
+ P.SourcePath.Add('src');
+ P.IncludePath.Add('src/inc');
+ T:=P.Targets.AddUnit('generics.collections.pas');
+ with T.Dependencies do
+ begin
+ AddUnit('generics.memoryexpanders');
+ AddUnit('generics.defaults');
+ AddUnit('generics.helpers');
+ AddUnit('generics.strings');
+ end;
+ T:=P.Targets.AddUnit('generics.defaults.pas');
+ with T.Dependencies do
+ begin
+ AddUnit('generics.hashes');
+ AddUnit('generics.strings');
+ AddUnit('generics.helpers');
+ end;
+ T:=P.Targets.AddUnit('generics.hashes.pas');
+ T:=P.Targets.AddUnit('generics.helpers.pas');
+ T:=P.Targets.AddUnit('generics.memoryexpanders.pas');
+ T:=P.Targets.AddUnit('generics.strings.pas');
+ // Examples
+ P.ExamplePath.Add('examples/tarraydouble');
+ T:=P.Targets.AddExampleProgram('tarrayprojectdouble.lpr');
+ P.ExamplePath.Add('examples/tarraysingle');
+ T:=P.Targets.AddExampleProgram('tarrayprojectsingle.lpr');
+ P.ExamplePath.Add('examples/tcomparer');
+ T:=P.Targets.AddExampleProgram('tcomparerproject.lpr');
+ P.ExamplePath.Add('examples/thashmap');
+ T:=P.Targets.AddExampleProgram('thashmapproject.lpr');
+ P.ExamplePath.Add('examples/thashmapcaseinsensitive');
+ T:=P.Targets.AddExampleProgram('thashmapcaseinsensitive.lpr');
+ P.ExamplePath.Add('examples/thashmapextendedequalitycomparer');
+ T:=P.Targets.AddExampleProgram('thashmapextendedequalitycomparer.lpr');
+ P.ExamplePath.Add('examples/tobjectlist');
+ T:=P.Targets.AddExampleProgram('tobjectlistproject.lpr');
+ P.ExamplePath.Add('examples/tqueue');
+ T:=P.Targets.AddExampleProgram('tqueueproject.lpr');
+ P.ExamplePath.Add('examples/tstack');
+ T:=P.Targets.AddExampleProgram('tstackproject.lpr');
+ end;
+end;
+
+{$ifndef ALLPACKAGES}
+begin
+ add_rtl_generics('');
+ Installer.Run;
+end.
+{$endif ALLPACKAGES}
diff --git a/packages/rtl-generics/src/generics.collections.pas b/packages/rtl-generics/src/generics.collections.pas
new file mode 100644
index 0000000000..0643f88a15
--- /dev/null
+++ b/packages/rtl-generics/src/generics.collections.pas
@@ -0,0 +1,1265 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2014 by Maciej Izak (hnb)
+ member of the Free Sparta development team (http://freesparta.com)
+
+ Copyright(c) 2004-2014 DaThoX
+
+ It contains the Free Pascal generics library
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit Generics.Collections;
+
+{$MODE DELPHI}{$H+}
+{$MACRO ON}
+{$COPERATORS ON}
+{$DEFINE CUSTOM_DICTIONARY_CONSTRAINTS := TKey, TValue, THashFactory}
+{$DEFINE OPEN_ADDRESSING_CONSTRAINTS := TKey, TValue, THashFactory, TProbeSequence}
+{$DEFINE CUCKOO_CONSTRAINTS := TKey, TValue, THashFactory, TCuckooCfg}
+{$WARNINGS OFF}
+{$HINTS OFF}
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+
+interface
+
+uses
+ Classes, SysUtils, Generics.MemoryExpanders, Generics.Defaults,
+ Generics.Helpers, Generics.Strings;
+
+{ FPC BUGS related to Generics.* (54 bugs, 19 fixed)
+ REGRESSION: 26483, 26481
+ FIXED REGRESSION: 26480, 26482
+
+ CRITICAL: 24848(!!!), 24872(!), 25607(!), 26030, 25917, 25918, 25620, 24283, 24254, 24287 (Related to? 24872)
+ IMPORTANT: 23862(!), 24097, 24285, 24286 (Similar to? 24285), 24098, 24609 (RTL inconsistency), 24534,
+ 25606, 25614, 26177, 26195
+ OTHER: 26484, 24073, 24463, 25593, 25596, 25597, 25602, 26181 (or MYBAD?)
+ CLOSED BUT IMO STILL TO FIX: 25601(!), 25594
+ FIXED: 25610(!), 24064, 24071, 24282, 24458, 24867, 24871, 25604, 25600, 25605, 25598, 25603, 25929, 26176, 26180,
+ 26193, 24072
+ MYBAD: 24963, 25599
+}
+
+{ LAZARUS BUGS related to Generics.* (7 bugs, 0 fixed)
+ CRITICAL: 25613
+ OTHER: 25595, 25612, 25615, 25617, 25618, 25619
+}
+
+type
+ TArray = array of T; // for name TArray conflict with TArray record implementation (bug #26030)
+
+ // bug #24254 workaround
+ // should be TArray = record class procedure Sort(...) etc.
+ TCustomArrayHelper = class abstract
+ private
+ type
+ // bug #24282
+ TComparerBugHack = TComparer;
+ protected
+ // modified QuickSort from classes\lists.inc
+ class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt; const AComparer: IComparer);
+ virtual; abstract;
+ public
+ class procedure Sort(var AValues: array of T); overload;
+ class procedure Sort(var AValues: array of T;
+ const AComparer: IComparer); overload;
+ class procedure Sort(var AValues: array of T;
+ const AComparer: IComparer; AIndex, ACount: SizeInt); overload;
+
+ class function BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt; const AComparer: IComparer;
+ AIndex, ACount: SizeInt): Boolean; virtual; abstract; overload;
+ class function BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt; const AComparer: IComparer): Boolean; overload;
+ class function BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt): Boolean; overload;
+ end experimental; // will be renamed to TCustomArray (bug #24254)
+
+ TArrayHelper = class(TCustomArrayHelper)
+ protected
+ // modified QuickSort from classes\lists.inc
+ class procedure QuickSort(var AValues: array of T; ALeft, ARight: SizeInt; const AComparer: IComparer); override;
+ public
+ class function BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt; const AComparer: IComparer;
+ AIndex, ACount: SizeInt): Boolean; override; overload;
+ end experimental; // will be renamed to TArray (bug #24254)
+
+ TCollectionNotification = (cnAdded, cnRemoved, cnExtracted);
+ TCollectionNotifyEvent = procedure(ASender: TObject; constref AItem: T; AAction: TCollectionNotification)
+ of object;
+
+ { TEnumerator }
+
+ TEnumerator = class abstract
+ protected
+ function DoGetCurrent: T; virtual; abstract;
+ function DoMoveNext: boolean; virtual; abstract;
+ public
+ property Current: T read DoGetCurrent;
+ function MoveNext: boolean;
+ end;
+
+ { TEnumerable }
+
+ TEnumerable = class abstract
+ protected
+ function ToArrayImpl(ACount: SizeInt): TArray; overload; // used by descendants
+ protected
+ function DoGetEnumerator: TEnumerator; virtual; abstract;
+ public
+ function GetEnumerator: TEnumerator; inline;
+ function ToArray: TArray; virtual; overload;
+ end;
+
+ // More info: http://stackoverflow.com/questions/5232198/about-vectors-growth
+ // TODO: custom memory managers (as constraints)
+ {$DEFINE CUSTOM_LIST_CAPACITY_INC := Result + Result div 2} // ~approximation to golden ratio: n = n * 1.5 }
+ // {$DEFINE CUSTOM_LIST_CAPACITY_INC := Result * 2} // standard inc
+ TCustomList = class abstract(TEnumerable)
+ protected
+ type // bug #24282
+ TArrayHelperBugHack = TArrayHelper;
+ private
+ FOnNotify: TCollectionNotifyEvent;
+ function GetCapacity: SizeInt; inline;
+ protected
+ FItemsLength: SizeInt;
+ FItems: array of T;
+
+ function PrepareAddingItem: SizeInt; virtual;
+ function PrepareAddingRange(ACount: SizeInt): SizeInt; virtual;
+ procedure Notify(constref AValue: T; ACollectionNotification: TCollectionNotification); virtual;
+ function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; virtual;
+ procedure SetCapacity(AValue: SizeInt); virtual; abstract;
+ function GetCount: SizeInt; virtual;
+ public
+ function ToArray: TArray; override; final;
+
+ property Count: SizeInt read GetCount;
+ property Capacity: SizeInt read GetCapacity write SetCapacity;
+ property OnNotify: TCollectionNotifyEvent read FOnNotify write FOnNotify;
+ end;
+
+ TCustomListEnumerator = class abstract(TEnumerator< T >)
+ private
+ FList: TCustomList;
+ FIndex: SizeInt;
+ protected
+ function DoMoveNext: boolean; override;
+ function DoGetCurrent: T; override;
+ function GetCurrent: T; virtual;
+ public
+ constructor Create(AList: TCustomList);
+ end;
+
+ TList = class(TCustomList)
+ private var
+ FComparer: IComparer;
+ protected
+ // bug #24287 - workaround for generics type name conflict (Identifier not found)
+ // next bug workaround - for another error related to previous workaround
+ // change order (method must be declared before TEnumerator declaration)
+ function DoGetEnumerator: {Generics.Collections.}TEnumerator; override;
+ public
+ // with this type declaration i found #24285, #24285
+ type
+ // bug workaround
+ TEnumerator = class(TCustomListEnumerator);
+
+ function GetEnumerator: TEnumerator; reintroduce;
+ protected
+ procedure SetCapacity(AValue: SizeInt); override;
+ procedure SetCount(AValue: SizeInt);
+ private
+ function GetItem(AIndex: SizeInt): T;
+ procedure SetItem(AIndex: SizeInt; const AValue: T);
+ public
+ constructor Create; overload;
+ constructor Create(const AComparer: IComparer); overload;
+ constructor Create(ACollection: TEnumerable); overload;
+ destructor Destroy; override;
+
+ function Add(constref AValue: T): SizeInt;
+ procedure AddRange(constref AValues: array of T); overload;
+ procedure AddRange(const AEnumerable: IEnumerable); overload;
+ procedure AddRange(AEnumerable: TEnumerable); overload;
+
+ procedure Insert(AIndex: SizeInt; constref AValue: T);
+ procedure InsertRange(AIndex: SizeInt; constref AValues: array of T); overload;
+ procedure InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable); overload;
+ procedure InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable); overload;
+
+ function Remove(constref AValue: T): SizeInt;
+ procedure Delete(AIndex: SizeInt); inline;
+ procedure DeleteRange(AIndex, ACount: SizeInt);
+ function ExtractIndex(const AIndex: SizeInt): T; overload;
+ function Extract(constref AValue: T): T; overload;
+
+ procedure Exchange(AIndex1, AIndex2: SizeInt);
+ procedure Move(AIndex, ANewIndex: SizeInt);
+
+ function First: T; inline;
+ function Last: T; inline;
+
+ procedure Clear;
+
+ function Contains(constref AValue: T): Boolean; inline;
+ function IndexOf(constref AValue: T): SizeInt; virtual;
+ function LastIndexOf(constref AValue: T): SizeInt; virtual;
+
+ procedure Reverse;
+
+ procedure TrimExcess;
+
+ procedure Sort; overload;
+ procedure Sort(const AComparer: IComparer); overload;
+ function BinarySearch(constref AItem: T; out AIndex: SizeInt): Boolean; overload;
+ function BinarySearch(constref AItem: T; out AIndex: SizeInt; const AComparer: IComparer): Boolean; overload;
+
+ property Count: SizeInt read FItemsLength write SetCount;
+ property Items[Index: SizeInt]: T read GetItem write SetItem; default;
+ end;
+
+ TQueue = class(TCustomList)
+ protected
+ // bug #24287 - workaround for generics type name conflict (Identifier not found)
+ // next bug workaround - for another error related to previous workaround
+ // change order (function must be declared before TEnumerator declaration}
+ function DoGetEnumerator: {Generics.Collections.}TEnumerator; override;
+ public
+ type
+ TEnumerator = class(TCustomListEnumerator)
+ public
+ constructor Create(AQueue: TQueue);
+ end;
+
+ function GetEnumerator: TEnumerator; reintroduce;
+ private
+ FLow: SizeInt;
+ protected
+ procedure SetCapacity(AValue: SizeInt); override;
+ function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
+ function GetCount: SizeInt; override;
+ public
+ constructor Create(ACollection: TEnumerable); overload;
+ destructor Destroy; override;
+ procedure Enqueue(constref AValue: T);
+ function Dequeue: T;
+ function Extract: T;
+ function Peek: T;
+ procedure Clear;
+ procedure TrimExcess;
+ end;
+
+ TStack = class(TCustomList)
+ protected
+ // bug #24287 - workaround for generics type name conflict (Identifier not found)
+ // next bug workaround - for another error related to previous workaround
+ // change order (function must be declared before TEnumerator declaration}
+ function DoGetEnumerator: {Generics.Collections.}TEnumerator; override;
+ public
+ type
+ TEnumerator = class(TCustomListEnumerator);
+
+ function GetEnumerator: TEnumerator; reintroduce;
+ protected
+ function DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T; override;
+ procedure SetCapacity(AValue: SizeInt); override;
+ public
+ constructor Create(ACollection: TEnumerable); overload;
+ destructor Destroy; override;
+ procedure Clear;
+ procedure Push(constref AValue: T);
+ function Pop: T; inline;
+ function Peek: T;
+ function Extract: T; inline;
+ procedure TrimExcess;
+ end;
+
+ TObjectList = class(TList)
+ private
+ FObjectsOwner: Boolean;
+ protected
+ procedure Notify(constref AValue: T; ACollectionNotification: TCollectionNotification); override;
+ public
+ constructor Create(AOwnsObjects: Boolean = True); overload;
+ constructor Create(const AComparer: IComparer; AOwnsObjects: Boolean = True); overload;
+ constructor Create(ACollection: TEnumerable; AOwnsObjects: Boolean = True); overload;
+ property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
+ end;
+
+ TObjectQueue = class(TQueue)
+ private
+ FObjectsOwner: Boolean;
+ protected
+ procedure Notify(constref AValue: T; ACollectionNotification: TCollectionNotification); override;
+ public
+ constructor Create(AOwnsObjects: Boolean = True); overload;
+ constructor Create(ACollection: TEnumerable; AOwnsObjects: Boolean = True); overload;
+ procedure Dequeue;
+ property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
+ end;
+
+ TObjectStack = class(TStack)
+ private
+ FObjectsOwner: Boolean;
+ protected
+ procedure Notify(constref AValue: T; ACollectionNotification: TCollectionNotification); override;
+ public
+ constructor Create(AOwnsObjects: Boolean = True); overload;
+ constructor Create(ACollection: TEnumerable; AOwnsObjects: Boolean = True); overload;
+ function Pop: T;
+ property OwnsObjects: Boolean read FObjectsOwner write FObjectsOwner;
+ end;
+
+ PObject = ^TObject;
+
+{$I inc\generics.dictionariesh.inc}
+
+function InCircularRange(ABottom, AItem, ATop: SizeInt): Boolean;
+
+implementation
+
+function InCircularRange(ABottom, AItem, ATop: SizeInt): Boolean;
+begin
+ Result :=
+ (ABottom < AItem) and (AItem <= ATop )
+ or (ATop < ABottom) and (AItem > ABottom)
+ or (ATop < ABottom ) and (AItem <= ATop );
+end;
+
+{ TCustomArrayHelper }
+
+class function TCustomArrayHelper.BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt; const AComparer: IComparer): Boolean;
+begin
+ Result := BinarySearch(AValues, AItem, AFoundIndex, AComparer, Low(AValues), Length(AValues));
+end;
+
+class function TCustomArrayHelper.BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt): Boolean;
+begin
+ Result := BinarySearch(AValues, AItem, AFoundIndex, TComparerBugHack.Default, Low(AValues), Length(AValues));
+end;
+
+class procedure TCustomArrayHelper.Sort(var AValues: array of T);
+begin
+ QuickSort(AValues, Low(AValues), High(AValues), TComparerBugHack.Default);
+end;
+
+class procedure TCustomArrayHelper.Sort(var AValues: array of T;
+ const AComparer: IComparer);
+begin
+ QuickSort(AValues, Low(AValues), High(AValues), AComparer);
+end;
+
+class procedure TCustomArrayHelper.Sort(var AValues: array of T;
+ const AComparer: IComparer; AIndex, ACount: SizeInt);
+begin
+ if ACount <= 1 then
+ Exit;
+ QuickSort(AValues, AIndex, Pred(AIndex + ACount), AComparer);
+end;
+
+{ TArrayHelper }
+
+class procedure TArrayHelper.QuickSort(var AValues: array of T; ALeft, ARight: SizeInt;
+ const AComparer: IComparer);
+var
+ I, J: SizeInt;
+ P, Q: T;
+begin
+ if ((ARight - ALeft) <= 0) or (Length(AValues) = 0) then
+ Exit;
+ repeat
+ I := ALeft;
+ J := ARight;
+ P := AValues[ALeft + (ARight - ALeft) shr 1];
+ repeat
+ while AComparer.Compare(AValues[I], P) < 0 do
+ I += 1;
+ while AComparer.Compare(AValues[J], P) > 0 do
+ J -= 1;
+ if I <= J then
+ begin
+ if I <> J then
+ begin
+ Q := AValues[I];
+ AValues[I] := AValues[J];
+ AValues[J] := Q;
+ end;
+ I += 1;
+ J -= 1;
+ end;
+ until I > J;
+ // sort the smaller range recursively
+ // sort the bigger range via the loop
+ // Reasons: memory usage is O(log(n)) instead of O(n) and loop is faster than recursion
+ if J - ALeft < ARight - I then
+ begin
+ if ALeft < J then
+ QuickSort(AValues, ALeft, J, AComparer);
+ ALeft := I;
+ end
+ else
+ begin
+ if I < ARight then
+ QuickSort(AValues, I, ARight, AComparer);
+ ARight := J;
+ end;
+ until ALeft >= ARight;
+end;
+
+class function TArrayHelper.BinarySearch(constref AValues: array of T; constref AItem: T;
+ out AFoundIndex: SizeInt; const AComparer: IComparer;
+ AIndex, ACount: SizeInt): Boolean;
+var
+ imin, imax, imid: Int32;
+ LCompare: SizeInt;
+begin
+ // continually narrow search until just one element remains
+ imin := AIndex;
+ imax := Pred(AIndex + ACount);
+
+ // http://en.wikipedia.org/wiki/Binary_search_algorithm
+ while (imin < imax) do
+ begin
+ imid := imin + ((imax - imin) shr 1);
+
+ // code must guarantee the interval is reduced at each iteration
+ // assert(imid < imax);
+ // note: 0 <= imin < imax implies imid will always be less than imax
+
+ LCompare := AComparer.Compare(AValues[imid], AItem);
+ // reduce the search
+ if (LCompare < 0) then
+ imin := imid + 1
+ else
+ begin
+ imax := imid;
+ if LCompare = 0 then
+ begin
+ AFoundIndex := imid;
+ Exit(True);
+ end;
+ end;
+ end;
+ // At exit of while:
+ // if A[] is empty, then imax < imin
+ // otherwise imax == imin
+
+ // deferred test for equality
+
+ LCompare := AComparer.Compare(AValues[imin], AItem);
+ if (imax = imin) and (LCompare = 0) then
+ begin
+ AFoundIndex := imin;
+ Exit(True);
+ end
+ else
+ begin
+ AFoundIndex := -1;
+ Exit(False);
+ end;
+end;
+
+{ TEnumerator }
+
+function TEnumerator.MoveNext: boolean;
+begin
+ Exit(DoMoveNext);
+end;
+
+{ TEnumerable }
+
+function TEnumerable.ToArrayImpl(ACount: SizeInt): TArray;
+var
+ i: SizeInt;
+ LEnumerator: TEnumerator;
+begin
+ SetLength(Result, ACount);
+
+ try
+ LEnumerator := GetEnumerator;
+
+ i := 0;
+ while LEnumerator.MoveNext do
+ begin
+ Result[i] := LEnumerator.Current;
+ Inc(i);
+ end;
+ finally
+ LEnumerator.Free;
+ end;
+end;
+
+function TEnumerable.GetEnumerator: TEnumerator;
+begin
+ Exit(DoGetEnumerator);
+end;
+
+function TEnumerable.ToArray: TArray;
+var
+ LEnumerator: TEnumerator;
+ LBuffer: TList;
+begin
+ LBuffer := TList.Create;
+ try
+ LEnumerator := GetEnumerator;
+
+ while LEnumerator.MoveNext do
+ LBuffer.Add(LEnumerator.Current);
+
+ Result := LBuffer.ToArray;
+ finally
+ LBuffer.Free;
+ LEnumerator.Free;
+ end;
+end;
+
+{ TCustomList }
+
+function TCustomList.PrepareAddingItem: SizeInt;
+begin
+ Result := Length(FItems);
+
+ if (FItemsLength < 4) and (Result < 4) then
+ SetLength(FItems, 4)
+ else if FItemsLength = High(FItemsLength) then
+ OutOfMemoryError
+ else if FItemsLength = Result then
+ SetLength(FItems, CUSTOM_LIST_CAPACITY_INC);
+
+ Result := FItemsLength;
+ Inc(FItemsLength);
+end;
+
+function TCustomList.PrepareAddingRange(ACount: SizeInt): SizeInt;
+begin
+ if ACount < 0 then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+ if ACount = 0 then
+ Exit(FItemsLength - 1);
+
+ if (FItemsLength = 0) and (Length(FItems) = 0) then
+ SetLength(FItems, 4)
+ else if FItemsLength = High(FItemsLength) then
+ OutOfMemoryError;
+
+ Result := Length(FItems);
+ while Pred(FItemsLength + ACount) >= Result do
+ begin
+ SetLength(FItems, CUSTOM_LIST_CAPACITY_INC);
+ Result := Length(FItems);
+ end;
+
+ Result := FItemsLength;
+ Inc(FItemsLength, ACount);
+end;
+
+function TCustomList.ToArray: TArray;
+begin
+ Result := ToArrayImpl(Count);
+end;
+
+function TCustomList.GetCount: SizeInt;
+begin
+ Result := FItemsLength;
+end;
+
+procedure TCustomList.Notify(constref AValue: T; ACollectionNotification: TCollectionNotification);
+begin
+ if Assigned(FOnNotify) then
+ FOnNotify(Self, AValue, ACollectionNotification);
+end;
+
+function TCustomList.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
+begin
+ if (AIndex < 0) or (AIndex >= FItemsLength) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ Result := FItems[AIndex];
+ Dec(FItemsLength);
+
+ FItems[AIndex] := Default(T);
+ if AIndex <> FItemsLength then
+ begin
+ System.Move(FItems[AIndex + 1], FItems[AIndex], (FItemsLength - AIndex) * SizeOf(T));
+ FillChar(FItems[FItemsLength], SizeOf(T), 0);
+ end;
+
+ Notify(Result, ACollectionNotification);
+end;
+
+function TCustomList.GetCapacity: SizeInt;
+begin
+ Result := Length(FItems);
+end;
+
+{ TCustomListEnumerator }
+
+function TCustomListEnumerator.DoMoveNext: boolean;
+begin
+ Inc(FIndex);
+ Result := (FList.FItemsLength <> 0) and (FIndex < FList.FItemsLength)
+end;
+
+function TCustomListEnumerator.DoGetCurrent: T;
+begin
+ Result := GetCurrent;
+end;
+
+function TCustomListEnumerator.GetCurrent: T;
+begin
+ Result := FList.FItems[FIndex];
+end;
+
+constructor TCustomListEnumerator.Create(AList: TCustomList);
+begin
+ inherited Create;
+ FIndex := -1;
+ FList := AList;
+end;
+
+{ TList }
+
+constructor TList.Create;
+begin
+ FComparer := TComparer.Default;
+end;
+
+constructor TList.Create(const AComparer: IComparer);
+begin
+ FComparer := AComparer;
+end;
+
+constructor TList.Create(ACollection: TEnumerable);
+var
+ LItem: T;
+begin
+ Create;
+ for LItem in ACollection do
+ Add(LItem);
+end;
+
+destructor TList.Destroy;
+begin
+ SetCapacity(0);
+end;
+
+procedure TList.SetCapacity(AValue: SizeInt);
+begin
+ if AValue < Count then
+ Count := AValue;
+
+ SetLength(FItems, AValue);
+end;
+
+procedure TList.SetCount(AValue: SizeInt);
+begin
+ if AValue < 0 then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ if AValue > Capacity then
+ Capacity := AValue;
+ if AValue < Count then
+ DeleteRange(AValue, Count - AValue);
+
+ FItemsLength := AValue;
+end;
+
+function TList.GetItem(AIndex: SizeInt): T;
+begin
+ if (AIndex < 0) or (AIndex >= Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ Result := FItems[AIndex];
+end;
+
+procedure TList.SetItem(AIndex: SizeInt; const AValue: T);
+begin
+ if (AIndex < 0) or (AIndex >= Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ FItems[AIndex] := AValue;
+end;
+
+function TList.GetEnumerator: TEnumerator;
+begin
+ Result := TEnumerator.Create(Self);
+end;
+
+function TList.DoGetEnumerator: {Generics.Collections.}TEnumerator;
+begin
+ Result := GetEnumerator;
+end;
+
+function TList.Add(constref AValue: T): SizeInt;
+begin
+ Result := PrepareAddingItem;
+ FItems[Result] := AValue;
+ Notify(AValue, cnAdded);
+end;
+
+procedure TList.AddRange(constref AValues: array of T);
+begin
+ InsertRange(Count, AValues);
+end;
+
+procedure TList.AddRange(const AEnumerable: IEnumerable);
+var
+ LValue: T;
+begin
+ for LValue in AEnumerable do
+ Add(LValue);
+end;
+
+procedure TList.AddRange(AEnumerable: TEnumerable);
+var
+ LValue: T;
+begin
+ for LValue in AEnumerable do
+ Add(LValue);
+end;
+
+procedure TList.Insert(AIndex: SizeInt; constref AValue: T);
+begin
+ if (AIndex < 0) or (AIndex > Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ if AIndex <> PrepareAddingItem then
+ begin
+ System.Move(FItems[AIndex], FItems[AIndex + 1], ((Count - AIndex) - 1) * SizeOf(T));
+ FillChar(FItems[AIndex], SizeOf(T), 0);
+ end;
+
+ FItems[AIndex] := AValue;
+ Notify(AValue, cnAdded);
+end;
+
+procedure TList.InsertRange(AIndex: SizeInt; constref AValues: array of T);
+var
+ i: SizeInt;
+ LLength: SizeInt;
+ LValue: ^T;
+begin
+ if (AIndex < 0) or (AIndex > Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ LLength := Length(AValues);
+ if LLength = 0 then
+ Exit;
+
+ if AIndex <> PrepareAddingRange(LLength) then
+ begin
+ System.Move(FItems[AIndex], FItems[AIndex + LLength], ((Count - AIndex) - LLength) * SizeOf(T));
+ FillChar(FItems[AIndex], SizeOf(T) * LLength, 0);
+ end;
+
+ LValue := @AValues[0];
+ for i := AIndex to Pred(AIndex + LLength) do
+ begin
+ FItems[i] := LValue^;
+ Notify(LValue^, cnAdded);
+ Inc(LValue);
+ end;
+end;
+
+procedure TList.InsertRange(AIndex: SizeInt; const AEnumerable: IEnumerable);
+var
+ LValue: T;
+ i: SizeInt;
+begin
+ if (AIndex < 0) or (AIndex > Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ i := 0;
+ for LValue in AEnumerable do
+ begin
+ Insert(Aindex + i, LValue);
+ Inc(i);
+ end;
+end;
+
+procedure TList.InsertRange(AIndex: SizeInt; const AEnumerable: TEnumerable);
+var
+ LValue: T;
+ i: SizeInt;
+begin
+ if (AIndex < 0) or (AIndex > Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ i := 0;
+ for LValue in AEnumerable do
+ begin
+ Insert(Aindex + i, LValue);
+ Inc(i);
+ end;
+end;
+
+function TList.Remove(constref AValue: T): SizeInt;
+begin
+ Result := IndexOf(AValue);
+ if Result >= 0 then
+ DoRemove(Result, cnRemoved);
+end;
+
+procedure TList.Delete(AIndex: SizeInt);
+begin
+ DoRemove(AIndex, cnRemoved);
+end;
+
+procedure TList.DeleteRange(AIndex, ACount: SizeInt);
+var
+ LDeleted: array of T;
+ i: SizeInt;
+ LMoveDelta: SizeInt;
+begin
+ if ACount = 0 then
+ Exit;
+
+ if (ACount < 0) or (AIndex < 0) or (AIndex + ACount > Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ SetLength(LDeleted, Count);
+ System.Move(FItems[AIndex], LDeleted[0], ACount * SizeOf(T));
+
+ LMoveDelta := Count - (AIndex + ACount);
+
+ if LMoveDelta = 0 then
+ FillChar(FItems[AIndex], ACount * SizeOf(T), #0)
+ else
+ begin
+ System.Move(FItems[AIndex + ACount], FItems[AIndex], LMoveDelta * SizeOf(T));
+ FillChar(FItems[Count - ACount], ACount * SizeOf(T), #0);
+ end;
+
+ FItemsLength -= ACount;
+
+ for i := 0 to High(LDeleted) do
+ Notify(LDeleted[i], cnRemoved);
+end;
+
+function TList.ExtractIndex(const AIndex: SizeInt): T;
+begin
+ Result := DoRemove(AIndex, cnExtracted);
+end;
+
+function TList.Extract(constref AValue: T): T;
+var
+ LIndex: SizeInt;
+begin
+ LIndex := IndexOf(AValue);
+ if LIndex < 0 then
+ Exit(Default(T));
+
+ Result := DoRemove(LIndex, cnExtracted);
+end;
+
+procedure TList.Exchange(AIndex1, AIndex2: SizeInt);
+var
+ LTemp: T;
+begin
+ LTemp := FItems[AIndex1];
+ FItems[AIndex1] := FItems[AIndex2];
+ FItems[AIndex2] := LTemp;
+end;
+
+procedure TList.Move(AIndex, ANewIndex: SizeInt);
+var
+ LTemp: T;
+begin
+ if ANewIndex = AIndex then
+ Exit;
+
+ if (ANewIndex < 0) or (ANewIndex >= Count) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ LTemp := FItems[AIndex];
+ FItems[AIndex] := Default(T);
+
+ if AIndex < ANewIndex then
+ System.Move(FItems[Succ(AIndex)], FItems[AIndex], (ANewIndex - AIndex) * SizeOf(T))
+ else
+ System.Move(FItems[ANewIndex], FItems[Succ(ANewIndex)], (AIndex - ANewIndex) * SizeOf(T));
+
+ FillChar(FItems[ANewIndex], SizeOf(T), #0);
+ FItems[ANewIndex] := LTemp;
+end;
+
+function TList.First: T;
+begin
+ Result := Items[0];
+end;
+
+function TList.Last: T;
+begin
+ Result := Items[Pred(Count)];
+end;
+
+procedure TList.Clear;
+begin
+ SetCount(0);
+ SetCapacity(0);
+end;
+
+procedure TList.TrimExcess;
+begin
+ SetCapacity(Count);
+end;
+
+function TList.Contains(constref AValue: T): Boolean;
+begin
+ Result := IndexOf(AValue) >= 0;
+end;
+
+function TList.IndexOf(constref AValue: T): SizeInt;
+var
+ i: SizeInt;
+begin
+ for i := 0 to Count - 1 do
+ if FComparer.Compare(AValue, FItems[i]) = 0 then
+ Exit(i);
+ Result := -1;
+end;
+
+function TList.LastIndexOf(constref AValue: T): SizeInt;
+var
+ i: SizeInt;
+begin
+ for i := Count - 1 downto 0 do
+ if FComparer.Compare(AValue, FItems[i]) = 0 then
+ Exit(i);
+ Result := -1;
+end;
+
+procedure TList.Reverse;
+var
+ a, b: SizeInt;
+ LTemp: T;
+begin
+ a := 0;
+ b := Count - 1;
+ while a < b do
+ begin
+ LTemp := FItems[a];
+ FItems[a] := FItems[b];
+ FItems[b] := LTemp;
+ Inc(a);
+ Dec(b);
+ end;
+end;
+
+procedure TList.Sort;
+begin
+ TArrayHelperBugHack.Sort(FItems, FComparer, 0, Count);
+end;
+
+procedure TList.Sort(const AComparer: IComparer);
+begin
+ TArrayHelperBugHack.Sort(FItems, AComparer, 0, Count);
+end;
+
+function TList.BinarySearch(constref AItem: T; out AIndex: SizeInt): Boolean;
+begin
+ Result := TArrayHelperBugHack.BinarySearch(FItems, AItem, AIndex);
+end;
+
+function TList.BinarySearch(constref AItem: T; out AIndex: SizeInt; const AComparer: IComparer): Boolean;
+begin
+ Result := TArrayHelperBugHack.BinarySearch(FItems, AItem, AIndex, AComparer);
+end;
+
+{ TQueue.TEnumerator }
+
+constructor TQueue.TEnumerator.Create(AQueue: TQueue);
+begin
+ inherited Create(AQueue);
+
+ FIndex := Pred(AQueue.FLow);
+end;
+
+{ TQueue }
+
+function TQueue.GetEnumerator: TEnumerator;
+begin
+ Result := TEnumerator.Create(Self);
+end;
+
+function TQueue.DoGetEnumerator: {Generics.Collections.}TEnumerator;
+begin
+ Result := GetEnumerator;
+end;
+
+function TQueue.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
+begin
+ Result := FItems[AIndex];
+ FItems[AIndex] := Default(T);
+ Notify(Result, ACollectionNotification);
+ FLow += 1;
+ if FLow = FItemsLength then
+ begin
+ FLow := 0;
+ FItemsLength := 0;
+ end;
+end;
+
+procedure TQueue.SetCapacity(AValue: SizeInt);
+begin
+ if AValue < Count then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ if AValue = FItemsLength then
+ Exit;
+
+ if (Count > 0) and (FLow > 0) then
+ begin
+ Move(FItems[FLow], FItems[0], Count * SizeOf(T));
+ FillChar(FItems[Count], (FItemsLength - Count) * SizeOf(T), #0);
+ end;
+
+ SetLength(FItems, AValue);
+ FItemsLength := Count;
+ FLow := 0;
+end;
+
+function TQueue.GetCount: SizeInt;
+begin
+ Result := FItemsLength - FLow;
+end;
+
+constructor TQueue.Create(ACollection: TEnumerable);
+var
+ LItem: T;
+begin
+ for LItem in ACollection do
+ Enqueue(LItem);
+end;
+
+destructor TQueue.Destroy;
+begin
+ Clear;
+end;
+
+procedure TQueue.Enqueue(constref AValue: T);
+var
+ LIndex: SizeInt;
+begin
+ LIndex := PrepareAddingItem;
+ FItems[LIndex] := AValue;
+ Notify(AValue, cnAdded);
+end;
+
+function TQueue.Dequeue: T;
+begin
+ Result := DoRemove(FLow, cnRemoved);
+end;
+
+function TQueue.Extract: T;
+begin
+ Result := DoRemove(FLow, cnExtracted);
+end;
+
+function TQueue.Peek: T;
+begin
+ if (Count = 0) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ Result := FItems[FLow];
+end;
+
+procedure TQueue.Clear;
+begin
+ while Count <> 0 do
+ Dequeue;
+ FLow := 0;
+ FItemsLength := 0;
+end;
+
+procedure TQueue.TrimExcess;
+begin
+ SetCapacity(Count);
+end;
+
+{ TStack }
+
+function TStack.GetEnumerator: TEnumerator;
+begin
+ Result := TEnumerator.Create(Self);
+end;
+
+function TStack.DoGetEnumerator: {Generics.Collections.}TEnumerator;
+begin
+ Result := GetEnumerator;
+end;
+
+constructor TStack.Create(ACollection: TEnumerable);
+var
+ LItem: T;
+begin
+ for LItem in ACollection do
+ Push(LItem);
+end;
+
+function TStack.DoRemove(AIndex: SizeInt; ACollectionNotification: TCollectionNotification): T;
+begin
+ if AIndex < 0 then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ Result := FItems[AIndex];
+ FItems[AIndex] := Default(T);
+ FItemsLength -= 1;
+ Notify(Result, ACollectionNotification);
+end;
+
+destructor TStack.Destroy;
+begin
+ Clear;
+end;
+
+procedure TStack.Clear;
+begin
+ while Count <> 0 do
+ Pop;
+end;
+
+procedure TStack.SetCapacity(AValue: SizeInt);
+begin
+ if AValue < Count then
+ AValue := Count;
+
+ SetLength(FItems, AValue);
+end;
+
+procedure TStack.Push(constref AValue: T);
+var
+ LIndex: SizeInt;
+begin
+ LIndex := PrepareAddingItem;
+ FItems[LIndex] := AValue;
+ Notify(AValue, cnAdded);
+end;
+
+function TStack.Pop: T;
+begin
+ Result := DoRemove(FItemsLength - 1, cnRemoved);
+end;
+
+function TStack.Peek: T;
+begin
+ if (Count = 0) then
+ raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
+
+ Result := FItems[FItemsLength - 1];
+end;
+
+function TStack.Extract: T;
+begin
+ Result := DoRemove(FItemsLength - 1, cnExtracted);
+end;
+
+procedure TStack