2
0
Эх сурвалжийг харах

* Initial implementation

git-svn-id: trunk@8522 -
michael 18 жил өмнө
parent
commit
f83d92c9a0

+ 9 - 0
.gitattributes

@@ -4262,6 +4262,15 @@ packages/fcl-image/src/pixtools.pp svneol=native#text/plain
 packages/fcl-image/src/pngcomn.pp svneol=native#text/plain
 packages/fcl-image/src/pscanvas.pp svneol=native#text/plain
 packages/fcl-image/src/targacmn.pp svneol=native#text/plain
+packages/fcl-json/Makefile svneol=native#text/plain
+packages/fcl-json/Makefile.fpc svneol=native#text/plain
+packages/fcl-json/src/fpjson.pp svneol=native#text/plain
+packages/fcl-json/src/jsonparser.pp svneol=native#text/plain
+packages/fcl-json/src/jsonscanner.pp svneol=native#text/plain
+packages/fcl-json/tests/testjson.lpi svneol=native#text/plain
+packages/fcl-json/tests/testjson.pp svneol=native#text/plain
+packages/fcl-json/tests/testjsondata.pp svneol=native#text/plain
+packages/fcl-json/tests/testjsonparser.pp svneol=native#text/plain
 packages/fcl-net/Makefile svneol=native#text/plain
 packages/fcl-net/Makefile.fpc svneol=native#text/plain
 packages/fcl-net/src/fpmake.inc svneol=native#text/plain

+ 2783 - 0
packages/fcl-json/Makefile

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

+ 29 - 0
packages/fcl-json/Makefile.fpc

@@ -0,0 +1,29 @@
+#
+#   Makefile.fpc for XML for FCL
+#
+
+[package]
+name=fcl-json
+version=2.2.0
+
+[target]
+units=fpjson jsonscanner jsonparser
+rsts=fpjson jsonscanner jsonparser
+
+[require]
+packages=fcl-base
+
+[compiler]
+options=-S2h
+sourcedir=src
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+[rules]
+.NOTPARALLEL:
+
+jsonparser$(PPUEXT): jsonparser.pp fpjson$(PPUEXT) jsonscanner$(PPUEXT)

+ 1448 - 0
packages/fcl-json/src/fpjson.pp

@@ -0,0 +1,1448 @@
+{$mode objfpc}
+{$h+}
+unit fpjson;
+
+interface
+
+uses
+  variants,
+  SysUtils,
+  classes,
+  contnrs;
+
+type
+
+  TJSONtype = (jtUnknown, jtNumber, jtString, jtBoolean, jtNull, jtArray, jtObject);
+  TJSONFloat = Extended;
+  TJSONStringType = AnsiString;
+
+  { TJSONData }
+
+  TJSONData = class(TObject)
+  protected
+    function GetAsBoolean: Boolean; virtual; abstract;
+    function GetAsFloat: TJSONFloat; virtual; abstract;
+    function GetAsInteger: Integer; virtual; abstract;
+    function GetIsNull: Boolean; virtual;
+    procedure SetAsBoolean(const AValue: Boolean); virtual; abstract;
+    procedure SetAsFloat(const AValue: TJSONFloat); virtual; abstract;
+    procedure SetAsInteger(const AValue: Integer); virtual; abstract;
+    function GetAsJSON: TJSONStringType; virtual; abstract;
+    function GetAsString: TJSONStringType; virtual; abstract;
+    procedure SetAsString(const AValue: TJSONStringType); virtual; abstract;
+    function GetValue: variant; virtual; abstract;
+    procedure SetValue(const AValue: variant); virtual; abstract;
+    function GetItem(Index : Integer): TJSONData; virtual;
+    procedure SetItem(Index : Integer; const AValue: TJSONData); virtual;
+    function GetCount: Integer; virtual;
+  public
+    Class function JSONType: TJSONType; virtual;
+    property Count: Integer read GetCount;
+    property Items[Index: Integer]: TJSONData read GetItem write SetItem;
+    property Value: variant read GetValue write SetValue;
+    Property AsString : TJSONStringType Read GetAsString Write SetAsString;
+    Property AsFloat : TJSONFloat Read GetAsFloat Write SetAsFloat;
+    Property AsInteger : Integer Read GetAsInteger Write SetAsInteger;
+    Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean;
+    Property IsNull : Boolean Read GetIsNull;
+    Property AsJSON : String Read GetAsJSON;
+  end;
+
+  TJSONNumberType = (ntFloat,ntInteger);
+
+  TJSONNumber = class(TJSONData)
+  protected
+  public
+    class function JSONType: TJSONType; override;
+    class function NumberType : TJSONNumberType; virtual; abstract;
+  end;
+
+  { TJSONFloatNumber }
+
+  TJSONFloatNumber = class(TJSONNumber)
+  Private
+    FValue : TJSONFloat;
+  protected
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+    function GetValue: variant; override;
+    procedure SetValue(const AValue: variant); override;
+  public
+    Constructor Create(AValue : TJSONFloat);
+    class function NumberType : TJSONNumberType; override;
+  end;
+  
+  { TJSONIntegerNumber }
+
+  TJSONIntegerNumber = class(TJSONNumber)
+  Private
+    FValue : Integer;
+  protected
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+    function GetValue: variant; override;
+    procedure SetValue(const AValue: variant); override;
+  public
+    Constructor Create(AValue : Integer);
+    class function NumberType : TJSONNumberType; override;
+  end;
+
+  { TJSONString }
+
+  TJSONString = class(TJSONData)
+  Private
+    FValue: TJSONStringType;
+  protected
+    function GetValue: Variant; override;
+    procedure SetValue(const AValue: Variant); override;
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+  public
+    Constructor Create(AValue : TJSONStringType);
+    class function JSONType: TJSONType; override;
+  end;
+
+  { TJSONboolean }
+
+  TJSONBoolean = class(TJSONData)
+  Private
+    FValue: Boolean;
+  protected
+    function GetValue: Variant; override;
+    procedure SetValue(const AValue: Variant); override;
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+  public
+    Constructor Create(AValue : Boolean);
+    class function JSONType: TJSONType; override;
+  end;
+
+  { TJSONnull }
+
+  TJSONNull = class(TJSONData)
+  protected
+    Procedure Converterror(From : Boolean);
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    function GetIsNull: Boolean; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+    function GetValue: variant; override;
+    procedure SetValue(const AValue: variant); override;
+  public
+    class function JSONType: TJSONType; override;
+  end;
+
+  TJSONArrayIterator = procedure(Item: TJSONData; Data: TObject; var Continue: Boolean) of object;
+
+  { TJSONArray }
+  TJSONObject = Class;
+
+  TJSONArray = class(TJSONData)
+  Private
+    FList : TFPObjectList;
+    function GetArrays(Index : Integer): TJSONArray;
+    function GetBooleans(Index : Integer): Boolean;
+    function GetFloats(Index : Integer): TJSONFloat;
+    function GetIntegers(Index : Integer): Integer;
+    function GetNulls(Index : Integer): Boolean;
+    function GetObjects(Index : Integer): TJSONObject;
+    function GetStrings(Index : Integer): TJSONStringType;
+    function GetTypes(Index : Integer): TJSONType;
+    procedure SetArrays(Index : Integer; const AValue: TJSONArray);
+    procedure SetBooleans(Index : Integer; const AValue: Boolean);
+    procedure SetFloats(Index : Integer; const AValue: TJSONFloat);
+    procedure SetIntegers(Index : Integer; const AValue: Integer);
+    procedure SetObjects(Index : Integer; const AValue: TJSONObject);
+    procedure SetStrings(Index : Integer; const AValue: TJSONStringType);
+  protected
+    Procedure Converterror(From : Boolean);
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+    function GetValue: variant; override;
+    procedure SetValue(const AValue: variant); override;
+    function GetCount: Integer; override;
+    function GetItem(Index : Integer): TJSONData; override;
+    procedure SetItem(Index : Integer; const AValue: TJSONData); override;
+  public
+    Constructor Create; overload;
+    Constructor Create(const Elements : Array of Const); overload;
+    Destructor Destroy; override;
+    class function JSONType: TJSONType; override;
+    // Examine
+    procedure Iterate(Iterator : TJSONArrayIterator; Data: TObject);
+    function IndexOf(obj: TJSONData): Integer;
+    // Manipulate
+    function Add(Item : TJSONData): Integer;
+    function Add(I : Integer): Integer;
+    function Add(S : String): Integer;
+    function Add: Integer;
+    function Add(F : TJSONFloat): Integer;
+    function Add(B : Boolean): Integer;
+    function Add(AnArray : TJSONArray): Integer;
+    function Add(AnObject: TJSONObject): Integer;
+    Procedure Delete(Index : Integer);
+    Procedure Remove(Item : TJSONData);
+    // Easy Access Properties.
+    property Items;default;
+    Property Types[Index : Integer] : TJSONType Read GetTypes;
+    Property Nulls[Index : Integer] : Boolean Read GetNulls;
+    Property Integers[Index : Integer] : Integer Read GetIntegers Write SetIntegers;
+    Property Strings[Index : Integer] : TJSONStringType Read GetStrings Write SetStrings;
+    Property Floats[Index : Integer] : TJSONFloat Read GetFloats Write SetFloats;
+    Property Booleans[Index : Integer] : Boolean Read GetBooleans Write SetBooleans;
+    Property Arrays[Index : Integer] : TJSONArray Read GetArrays Write SetArrays;
+    Property Objects[Index : Integer] : TJSONObject Read GetObjects Write SetObjects;
+  end;
+
+  TJSONObjectIterator = procedure(Const AName : TJSONStringType; Item: TJSONData; Data: TObject; var Continue: Boolean) of object;
+
+  { TJSONObject }
+
+  TJSONObject = class(TJSONData)
+  private
+    FHash : TFPHashObjectList; // Careful : Names limited to 255 chars.
+    function GetArrays(AName : String): TJSONArray;
+    function GetBooleans(AName : String): Boolean;
+    function GetElements(AName: string): TJSONData;
+    function GetFloats(AName : String): TJSONFloat;
+    function GetIntegers(AName : String): Integer;
+    function GetIsNull(AName : String): Boolean;
+    function GetNameOf(Index : Integer): TJSONStringType;
+    function GetObjects(AName : String): TJSONObject;
+    function GetStrings(AName : String): TJSONStringType;
+    function GetTypes(AName : String): TJSONType;
+    procedure SetArrays(AName : String; const AValue: TJSONArray);
+    procedure SetBooleans(AName : String; const AValue: Boolean);
+    procedure SetElements(AName: string; const AValue: TJSONData);
+    procedure SetFloats(AName : String; const AValue: TJSONFloat);
+    procedure SetIntegers(AName : String; const AValue: Integer);
+    procedure SetIsNull(AName : String; const AValue: Boolean);
+    procedure SetObjects(AName : String; const AValue: TJSONObject);
+    procedure SetStrings(AName : String; const AValue: TJSONStringType);
+  protected
+    Procedure Converterror(From : Boolean);
+    function GetAsBoolean: Boolean; override;
+    function GetAsFloat: TJSONFloat; override;
+    function GetAsInteger: Integer; override;
+    procedure SetAsBoolean(const AValue: Boolean); override;
+    procedure SetAsFloat(const AValue: TJSONFloat); override;
+    procedure SetAsInteger(const AValue: Integer); override;
+    function GetAsJSON: TJSONStringType; override;
+    function GetAsString: TJSONStringType; override;
+    procedure SetAsString(const AValue: TJSONStringType); override;
+    function GetValue: variant; override;
+    procedure SetValue(const AValue: variant); override;
+    function GetCount: Integer; override;
+    function GetItem(Index : Integer): TJSONData; override;
+    procedure SetItem(Index : Integer; const AValue: TJSONData); override;
+  public
+    constructor Create;
+    Constructor Create(const Elements : Array of Const); overload;
+    destructor Destroy; override;
+    class function JSONType: TJSONType; override;
+    // Examine
+    procedure Iterate(Iterator : TJSONObjectIterator; Data: TObject);
+    function IndexOf(Item: TJSONData): Integer;
+    Function IndexOfName(const AName: TJSONStringType): Integer;
+    // Manipulate
+    function Add(const AName: TJSONStringType; AValue: TJSONData): Integer; overload;
+    function Add(const AName: TJSONStringType; AValue: Boolean): Integer; overload;
+    function Add(const AName: TJSONStringType; AValue: TJSONFloat): Integer; overload;
+    function Add(const AName: TJSONStringType; AValue: TJSONStringType): Integer; overload;
+    function Add(const AName: TJSONStringType; Avalue: Integer): Integer; overload;
+    function Add(const AName: TJSONStringType): Integer; overload;
+    function Add(const AName: TJSONStringType; AValue : TJSONArray): Integer; overload;
+    procedure Delete(Index : Integer);
+    procedure Remove(Item : TJSONData);
+
+    // Easy access properties.
+    property Names[Index : Integer] : TJSONStringType read GetNameOf;
+    property Elements[AName: string] : TJSONData read GetElements write SetElements; default;
+
+    Property Types[AName : String] : TJSONType Read GetTypes;
+    Property Nulls[AName : String] : Boolean Read GetIsNull Write SetIsNull;
+    Property Floats[AName : String] : TJSONFloat Read GetFloats Write SetFloats;
+    Property Integers[AName : String] : Integer Read GetIntegers Write SetIntegers;
+    Property Strings[AName : String] : TJSONStringType Read GetStrings Write SetStrings;
+    Property Booleans[AName : String] : Boolean Read GetBooleans Write SetBooleans;
+    Property Arrays[AName : String] : TJSONArray Read GetArrays Write SetArrays;
+    Property Objects[AName : String] : TJSONObject Read GetObjects Write SetObjects;
+  end;
+
+  EJSON = Class(Exception);
+  
+Function StringToJSONString(S : TJSONStringType) : TJSONStringType;
+Function JSONStringToString(S : TJSONStringType) : TJSONStringType;
+
+
+
+implementation
+
+Resourcestring
+  SErrCannotConvertFromNull = 'Cannot convert data from Null value';
+  SErrCannotConvertToNull = 'Cannot convert data to Null value';
+  SErrCannotConvertFromArray = 'Cannot convert data from array value';
+  SErrCannotConvertToArray = 'Cannot convert data to array value';
+  SErrCannotConvertFromObject = 'Cannot convert data from object value';
+  SErrCannotConvertToObject = 'Cannot convert data to object value';
+  SErrInvalidFloat = 'Invalid float value : %s';
+  SErrInvalidInteger = 'Invalid float value : %s';
+  SErrCannotSetNotIsNull = 'IsNull cannot be set to False';
+  SErrCannotAddArrayTwice = 'Adding an array object to an array twice is not allowed';
+  SErrCannotAddObjectTwice = 'Adding an object to an array twice is not allowed';
+  SErrUnknownTypeInConstructor = 'Unknown type in JSON%s constructor: %d';
+  SErrNotJSONData = 'Cannot add object of type %s to TJSON%s';
+  SErrPointerNotNil = 'Cannot add non-nil pointer to JSON%s';
+  SErrOddNumber = 'TJSONObject must be constructed with name,value pairs';
+  SErrNameMustBeString = 'TJSONObject constructor element name at pos %d is not a string';
+  
+  
+Function StringToJSONString(S : TJSONStringType) : TJSONStringType;
+
+Var
+  I,J,L : Integer;
+  P : Pchar;
+
+begin
+  I:=1;
+  J:=1;
+  Result:='';
+  L:=Length(S);
+  P:=PChar(S);
+  While I<=L do
+    begin
+    if (P^ in ['"','/','\',#8,#9,#10,#12,#13]) then
+      begin
+      Result:=Result+Copy(S,J,I-J);
+      Case P^ of
+        '\' : Result:=Result+'\\';
+        '/' : Result:=Result+'\/';
+        '"' : Result:=Result+'\"';
+        #8  : Result:=Result+'\b';
+        #9  : Result:=Result+'\t';
+        #10 : Result:=Result+'\n';
+        #12 : Result:=Result+'\f';
+        #13 : Result:=Result+'\r';
+      end;
+      J:=I+1;
+      end;
+    Inc(I);
+    Inc(P);
+    end;
+  Result:=Result+Copy(S,J,I-1);
+end;
+
+Function JSONStringToString(S : TJSONStringType) : TJSONStringType;
+
+Var
+  I,J,L : Integer;
+  P : PChar;
+  w : String;
+
+begin
+  I:=1;
+  J:=1;
+  L:=Length(S);
+  Result:='';
+  P:=PChar(S);
+  While (I<=L) do
+    begin
+    if (P^='\') then
+      begin
+      Result:=Result+Copy(S,J,I-J);
+      Inc(P);
+      If (P^<>#0) then
+        begin
+        Inc(I);
+        Case P^ of
+          '\','"','/'
+              : Result:=Result+P^;
+          'b' : Result:=Result+#8;
+          't' : Result:=Result+#9;
+          'n' : Result:=Result+#10;
+          'f' : Result:=Result+#12;
+          'r' : Result:=Result+#13;
+          'u' : begin
+                W:=Copy(S,I+1,4);
+                Inc(I,4);
+                Inc(P,4);
+                Result:=Result+WideChar(StrToInt('$'+W));
+                end;
+        end;
+        end;
+      J:=I+1;
+      end;
+    Inc(I);
+    Inc(P);
+    end;
+  Result:=Result+Copy(S,J,I-J+1);
+end;
+
+
+
+{ TJSONData }
+
+
+function TJSONData.GetItem(Index : Integer): TJSONData;
+begin
+  Result:=nil;
+end;
+
+function TJSONData.GetCount: Integer;
+begin
+  Result:=0;
+end;
+
+function TJSONData.GetIsNull: Boolean;
+begin
+  Result:=False;
+end;
+
+class function TJSONData.JSONType: TJSONType;
+begin
+  JSONType:=jtUnknown;
+end;
+
+procedure TJSONData.SetItem(Index : Integer; const AValue:
+  TJSONData);
+begin
+  // Do Nothing
+end;
+
+{ TJSONnumber }
+
+class function TJSONnumber.JSONType: TJSONType;
+begin
+  Result:=jtNumber;
+end;
+
+
+{ TJSONstring }
+
+class function TJSONstring.JSONType: TJSONType;
+begin
+  Result:=jtString;
+end;
+
+function TJSONstring.GetValue: Variant;
+begin
+  Result:=FValue;
+end;
+
+procedure TJSONstring.SetValue(const AValue: Variant);
+begin
+  FValue:=AValue;
+end;
+
+
+function TJSONstring.GetAsBoolean: Boolean;
+begin
+  Result:=StrToBool(FValue);
+end;
+
+function TJSONstring.GetAsFloat: TJSONFloat;
+
+Var
+  C : Integer;
+
+begin
+  Val(FValue,Result,C);
+  If (C<>0) then
+    If Not TryStrToFloat(FValue,Result) then
+      Raise EConvertError.CreateFmt(SErrInvalidFloat,[FValue]);
+end;
+
+function TJSONstring.GetAsInteger: Integer;
+begin
+  Result:=StrToInt(FValue);
+end;
+
+procedure TJSONstring.SetAsBoolean(const AValue: Boolean);
+begin
+  FValue:=BoolToStr(AValue);
+end;
+
+procedure TJSONstring.SetAsFloat(const AValue: TJSONFloat);
+begin
+  FValue:=FloatToStr(AValue);
+end;
+
+procedure TJSONstring.SetAsInteger(const AValue: Integer);
+begin
+  FValue:=IntToStr(AValue);
+end;
+
+function TJSONstring.GetAsJSON: TJSONStringType;
+begin
+  Result:='"'+StringToJSONString(FValue)+'"';
+end;
+
+function TJSONstring.GetAsString: TJSONStringType;
+begin
+  Result:=FValue;
+end;
+
+procedure TJSONstring.SetAsString(const AValue: TJSONStringType);
+begin
+  FValue:=AValue;
+end;
+
+constructor TJSONstring.Create(AValue: TJSONStringType);
+begin
+  FValue:=AValue;
+end;
+
+{ TJSONboolean }
+
+
+function TJSONboolean.GetValue: Variant;
+begin
+  Result:=FValue;
+end;
+
+class function TJSONboolean.JSONType: TJSONType;
+begin
+  Result:=jtBoolean;
+end;
+
+
+procedure TJSONboolean.SetValue(const AValue: Variant);
+begin
+  FValue:=boolean(AValue);
+end;
+
+function TJSONboolean.GetAsBoolean: Boolean;
+begin
+  Result:=FValue;
+end;
+
+function TJSONboolean.GetAsFloat: TJSONFloat;
+begin
+  Result:=Ord(FValue);
+end;
+
+function TJSONboolean.GetAsInteger: Integer;
+begin
+  Result:=Ord(FValue);
+end;
+
+
+procedure TJSONboolean.SetAsBoolean(const AValue: Boolean);
+begin
+  FValue:=AValue;
+end;
+
+procedure TJSONboolean.SetAsFloat(const AValue: TJSONFloat);
+begin
+  FValue:=(AValue<>0)
+end;
+
+procedure TJSONboolean.SetAsInteger(const AValue: Integer);
+begin
+  FValue:=(AValue<>0)
+end;
+
+function TJSONboolean.GetAsJSON: TJSONStringType;
+begin
+  If FValue then
+    Result:='True'
+  else
+    Result:='False';
+end;
+
+function TJSONboolean.GetAsString: TJSONStringType;
+begin
+  Result:=BoolToStr(FValue);
+end;
+
+procedure TJSONboolean.SetAsString(const AValue: TJSONStringType);
+begin
+  FValue:=StrToBool(AValue);
+end;
+
+constructor TJSONboolean.Create(AValue: Boolean);
+begin
+  FValue:=AValue;
+end;
+
+{ TJSONnull }
+
+procedure TJSONnull.Converterror(From : Boolean);
+begin
+  If From then
+    Raise EJSON.Create(SErrCannotConvertFromNull)
+  else
+    Raise EJSON.Create(SErrCannotConvertToNull);
+end;
+
+function TJSONnull.GetAsBoolean: Boolean;
+begin
+  ConvertError(True);
+end;
+
+function TJSONnull.GetAsFloat: TJSONFloat;
+begin
+  ConvertError(True);
+end;
+
+function TJSONnull.GetAsInteger: Integer;
+begin
+  ConvertError(True);
+end;
+
+function TJSONnull.GetIsNull: Boolean;
+begin
+  Result:=True;
+end;
+
+procedure TJSONnull.SetAsBoolean(const AValue: Boolean);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONnull.SetAsFloat(const AValue: TJSONFloat);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONnull.SetAsInteger(const AValue: Integer);
+begin
+  ConvertError(False);
+end;
+
+function TJSONnull.GetAsJSON: TJSONStringType;
+begin
+  Result:='Null';
+end;
+
+function TJSONnull.GetAsString: TJSONStringType;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONnull.SetAsString(const AValue: TJSONStringType);
+begin
+  ConvertError(True);
+end;
+
+function TJSONnull.GetValue: Variant;
+begin
+  Result:=variants.Null;
+end;
+
+procedure TJSONnull.SetValue(const AValue: variant);
+begin
+  ConvertError(False);
+end;
+
+class function TJSONnull.JSONType: TJSONType;
+begin
+  Result:=jtNull;
+end;
+
+
+
+{ TJSONFloatNumber }
+
+function TJSONFloatNumber.GetAsBoolean: Boolean;
+begin
+  Result:=(FValue<>0);
+end;
+
+function TJSONFloatNumber.GetAsFloat: TJSONFloat;
+begin
+  Result:=FValue;
+end;
+
+function TJSONFloatNumber.GetAsInteger: Integer;
+begin
+  Result:=Round(FValue);
+end;
+
+procedure TJSONFloatNumber.SetAsBoolean(const AValue: Boolean);
+begin
+  FValue:=Ord(AValue);
+end;
+
+procedure TJSONFloatNumber.SetAsFloat(const AValue: TJSONFloat);
+begin
+  FValue:=AValue;
+end;
+
+procedure TJSONFloatNumber.SetAsInteger(const AValue: Integer);
+begin
+  FValue:=AValue;
+end;
+
+function TJSONFloatNumber.GetAsJSON: TJSONStringType;
+begin
+  Result:=AsString;
+end;
+
+function TJSONFloatNumber.GetAsString: TJSONStringType;
+begin
+  Str(FValue,Result);
+end;
+
+procedure TJSONFloatNumber.SetAsString(const AValue: TJSONStringType);
+
+Var
+  C : Integer;
+
+begin
+  Val(AValue,FValue,C);
+  If (C<>0) then
+    Raise EConvertError.CreateFmt(SErrInvalidFloat,[AValue]);
+end;
+
+function TJSONFloatNumber.GetValue: variant;
+begin
+  Result:=FValue;
+end;
+
+procedure TJSONFloatNumber.SetValue(const AValue: variant);
+begin
+  FValue:=AValue;
+end;
+
+constructor TJSONFloatNumber.Create(AValue: TJSONFloat);
+begin
+  FValue:=AValue;
+end;
+
+class function TJSONFloatNumber.NumberType: TJSONNumberType;
+begin
+  Result:=ntFloat;
+end;
+
+{ TJSONIntegerNumber }
+
+function TJSONIntegerNumber.GetAsBoolean: Boolean;
+begin
+  Result:=FValue<>0;
+end;
+
+function TJSONIntegerNumber.GetAsFloat: TJSONFloat;
+begin
+  Result:=Ord(FValue);
+end;
+
+function TJSONIntegerNumber.GetAsInteger: Integer;
+begin
+  Result:=FValue;
+end;
+
+procedure TJSONIntegerNumber.SetAsBoolean(const AValue: Boolean);
+begin
+  FValue:=Ord(AValue);
+end;
+
+procedure TJSONIntegerNumber.SetAsFloat(const AValue: TJSONFloat);
+begin
+  FValue:=Round(AValue);
+end;
+
+procedure TJSONIntegerNumber.SetAsInteger(const AValue: Integer);
+begin
+  FValue:=AValue;
+end;
+
+function TJSONIntegerNumber.GetAsJSON: TJSONStringType;
+begin
+  Result:=AsString;
+end;
+
+function TJSONIntegerNumber.GetAsString: TJSONStringType;
+begin
+  Result:=IntToStr(FValue)
+end;
+
+procedure TJSONIntegerNumber.SetAsString(const AValue: TJSONStringType);
+begin
+  FValue:=StrToInt(AValue);
+end;
+
+function TJSONIntegerNumber.GetValue: variant;
+begin
+  Result:=FValue;
+end;
+
+procedure TJSONIntegerNumber.SetValue(const AValue: variant);
+begin
+  FValue:=AValue;
+end;
+
+constructor TJSONIntegerNumber.Create(AValue: Integer);
+begin
+  FValue:=AValue;
+end;
+
+class function TJSONIntegerNumber.NumberType: TJSONNumberType;
+begin
+  Result:=ntInteger;
+end;
+
+
+{ TJSONArray }
+
+function TJSONArray.GetBooleans(Index : Integer): Boolean;
+begin
+  Result:=Items[Index].AsBoolean;
+end;
+
+function TJSONArray.GetArrays(Index : Integer): TJSONArray;
+begin
+  Result:=Items[Index] as TJSONArray;
+end;
+
+function TJSONArray.GetFloats(Index : Integer): TJSONFloat;
+begin
+  Result:=Items[Index].AsFloat;
+end;
+
+function TJSONArray.GetIntegers(Index : Integer): Integer;
+begin
+  Result:=Items[Index].AsInteger;
+end;
+
+function TJSONArray.GetNulls(Index : Integer): Boolean;
+begin
+  Result:=Items[Index].IsNull;
+end;
+
+function TJSONArray.GetObjects(Index : Integer): TJSONObject;
+begin
+  Result:=Items[Index] as TJSONObject;
+end;
+
+function TJSONArray.GetStrings(Index : Integer): TJSONStringType;
+begin
+  Result:=Items[Index].AsString;
+end;
+
+function TJSONArray.GetTypes(Index : Integer): TJSONType;
+begin
+  Result:=Items[Index].JSONType;
+end;
+
+procedure TJSONArray.SetArrays(Index : Integer; const AValue: TJSONArray);
+begin
+  Items[Index]:=AValue;
+end;
+
+procedure TJSONArray.SetBooleans(Index : Integer; const AValue: Boolean);
+
+begin
+  Items[Index]:=TJSonBoolean.Create(AValue);
+end;
+
+procedure TJSONArray.SetFloats(Index : Integer; const AValue: TJSONFloat);
+begin
+  Items[Index]:=TJSONFloatNumber.Create(AValue);
+end;
+
+procedure TJSONArray.SetIntegers(Index : Integer; const AValue: Integer);
+begin
+  Items[Index]:=TJSONIntegerNumber.Create(AValue);
+end;
+
+procedure TJSONArray.SetObjects(Index : Integer; const AValue: TJSONObject);
+begin
+  Items[Index]:=AValue;
+end;
+
+procedure TJSONArray.SetStrings(Index : Integer; const AValue: TJSONStringType);
+begin
+  Items[Index]:=TJSONString.Create(AValue);
+end;
+
+procedure TJSONArray.Converterror(From: Boolean);
+begin
+  If From then
+    Raise EJSON.Create(SErrCannotConvertFromArray)
+  else
+    Raise EJSON.Create(SErrCannotConvertToArray);
+end;
+
+function TJSONArray.GetAsBoolean: Boolean;
+begin
+  ConvertError(True);
+end;
+
+function TJSONArray.GetAsFloat: TJSONFloat;
+begin
+  ConvertError(True);
+end;
+
+function TJSONArray.GetAsInteger: Integer;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONArray.SetAsBoolean(const AValue: Boolean);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONArray.SetAsFloat(const AValue: TJSONFloat);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONArray.SetAsInteger(const AValue: Integer);
+begin
+  ConvertError(False);
+end;
+
+function TJSONArray.GetAsJSON: TJSONStringType;
+
+Var
+  I : Integer;
+
+begin
+  Result:='[';
+  For I:=0 to Count-1 do
+    begin
+    Result:=Result+Items[i].AsJSON;
+    If (I<Count-1) then
+      Result:=Result+', '
+    end;
+  Result:=Result+']';
+end;
+
+function TJSONArray.GetAsString: TJSONStringType;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONArray.SetAsString(const AValue: TJSONStringType);
+begin
+  ConvertError(False);
+end;
+
+function TJSONArray.GetValue: variant;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONArray.SetValue(const AValue: variant);
+begin
+  ConvertError(False);
+end;
+
+function TJSONArray.GetCount: Integer;
+begin
+  Result:=Flist.Count;
+end;
+
+function TJSONArray.GetItem(Index: Integer): TJSONData;
+begin
+  Result:=FList[Index] as TJSONData;
+end;
+
+procedure TJSONArray.SetItem(Index: Integer; const AValue: TJSONData);
+begin
+  If (Index=FList.Count) then
+    FList.Add(AValue)
+  else
+    FList[Index]:=AValue;
+end;
+
+constructor TJSONArray.Create;
+begin
+  Flist:=TFPObjectList.Create(True);
+end;
+
+Function VarRecToJSON(Const Element : TVarRec; SourceType : String) : TJSONData;
+
+begin
+  Result:=Nil;
+  With Element do
+    case VType of
+      vtInteger    : Result:=TJSONIntegerNumber.Create(VInteger);
+      vtBoolean    : Result:=TJSONBoolean.Create(VBoolean);
+      vtChar       : Result:=TJSONString.Create(VChar);
+      vtExtended   : Result:=TJSONFloatNumber.Create(VExtended^);
+      vtString     : Result:=TJSONString.Create(vString^);
+      vtAnsiString : Result:=TJSONString.Create(AnsiString(vAnsiString));
+      vtPChar      : Result:=TJSONString.Create(StrPas(VPChar));
+      vtPointer    : If (VPointer<>Nil) then
+                       Raise EJSON.CreateFmt(SErrPointerNotNil,[SourceType])
+                     else
+                       Result:=TJSONNull.Create;
+      vtCurrency   : Result:=TJSONFloatNumber.Create(vCurrency^);
+      vtInt64      : Result:=TJSONFloatNumber.Create(vInt64^);
+      vtObject     : if (VObject is TJSONData) then
+                       Result:=TJSONData(VObject)
+                     else
+                       Raise EJSON.CreateFmt(SErrNotJSONData,[SourceType,VObject.ClassName]);
+      //vtVariant    :
+    else
+      Raise EJSON.CreateFmt(SErrUnknownTypeInConstructor,[SourceType,VType])
+    end;
+end;
+
+constructor TJSONArray.Create(Const Elements: array of const);
+
+Var
+  I : integer;
+  J : TJSONData;
+
+begin
+  Create;
+  For I:=Low(Elements) to High(Elements) do
+    begin
+    J:=VarRecToJSON(Elements[i],'Array');
+    Add(J);
+    end;
+end;
+
+Destructor TJSONArray.Destroy;
+begin
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+class function TJSONArray.JSONType: TJSONType;
+begin
+  Result:=jtArray;
+end;
+
+procedure TJSONArray.Iterate(Iterator: TJSONArrayIterator; Data: TObject);
+
+Var
+  I : Integer;
+  Cont : Boolean;
+  
+begin
+  I:=0;
+  Cont:=True;
+  While (I<FList.Count) and cont do
+    begin
+    Iterator(Items[i],Data,Cont);
+    Inc(I);
+    end;
+end;
+
+function TJSONArray.IndexOf(obj: TJSONData): Integer;
+begin
+  Result:=FList.IndexOf(Obj);
+end;
+
+function TJSONArray.Add(Item: TJSONData): Integer;
+begin
+  Result:=FList.Add(Item);
+end;
+
+function TJSONArray.Add(I: Integer): Integer;
+begin
+  Result:=Add(TJSONIntegerNumber.Create(I));
+end;
+
+function TJSONArray.Add(S: String): Integer;
+begin
+  Result:=Add(TJSONString.Create(S));
+end;
+
+function TJSONArray.Add: Integer;
+begin
+  Result:=Add(TJSONNull.Create);
+end;
+
+function TJSONArray.Add(F: TJSONFloat): Integer;
+begin
+  Result:=Add(TJSONFloatNumber.Create(F));
+end;
+
+function TJSONArray.Add(B: Boolean): Integer;
+begin
+  Result:=Add(TJSONBoolean.Create(B));
+end;
+
+function TJSONArray.Add(AnArray: TJSONArray): Integer;
+begin
+  If (IndexOf(AnArray)<>-1) then
+    Raise EJSON.Create(SErrCannotAddArrayTwice);
+  Result:=Add(TJSONData(AnArray));
+end;
+
+function TJSONArray.Add(AnObject: TJSONObject): Integer;
+begin
+  If (IndexOf(AnObject)<>-1) then
+    Raise EJSON.Create(SErrCannotAddObjectTwice);
+  Result:=Add(TJSONData(AnObject));
+end;
+
+procedure TJSONArray.Delete(Index: Integer);
+begin
+  FList.Delete(Index);
+end;
+
+procedure TJSONArray.Remove(Item: TJSONData);
+begin
+  FList.Remove(Item);
+end;
+
+{ TJSONObject }
+
+function TJSONObject.GetArrays(AName : String): TJSONArray;
+begin
+  Result:=GetElements(AName) as TJSONArray;
+end;
+
+function TJSONObject.GetBooleans(AName : String): Boolean;
+begin
+  Result:=GetElements(AName).AsBoolean;
+end;
+
+function TJSONObject.GetElements(AName: string): TJSONData;
+begin
+  Result:=TJSONData(FHash.Find(AName));
+end;
+
+function TJSONObject.GetFloats(AName : String): TJSONFloat;
+begin
+  Result:=GetElements(AName).AsFloat;
+end;
+
+function TJSONObject.GetIntegers(AName : String): Integer;
+begin
+  Result:=GetElements(AName).AsInteger;
+end;
+
+function TJSONObject.GetIsNull(AName : String): Boolean;
+begin
+  Result:=GetElements(AName).IsNull;
+end;
+
+function TJSONObject.GetNameOf(Index: Integer): TJSONStringType;
+begin
+  Result:=FHash.NameOfIndex(Index);
+end;
+
+function TJSONObject.GetObjects(AName : String): TJSONObject;
+begin
+  Result:=GetElements(AName) as TJSONObject;
+end;
+
+function TJSONObject.GetStrings(AName : String): TJSONStringType;
+begin
+  Result:=GetElements(AName).AsString;
+end;
+
+function TJSONObject.GetTypes(AName : String): TJSONType;
+begin
+  Result:=Getelements(Aname).JSONType;
+end;
+
+procedure TJSONObject.SetArrays(AName : String; const AValue: TJSONArray);
+
+begin
+  SetElements(AName,AVAlue);
+end;
+
+procedure TJSONObject.SetBooleans(AName : String; const AValue: Boolean);
+begin
+  SetElements(AName,TJSONBoolean.Create(AVAlue));
+end;
+
+procedure TJSONObject.SetElements(AName: string; const AValue: TJSONData);
+Var
+  Index : Integer;
+
+begin
+  Index:=FHash.FindIndexOf(AName);
+  If (Index=-1) then
+    FHash.Add(AName,AValue)
+  else
+    FHash.Items[Index]:=AValue; // Will free the previous value.
+end;
+
+procedure TJSONObject.SetFloats(AName : String; const AValue: TJSONFloat);
+begin
+  SetElements(AName,TJSONFloatNumber.Create(AVAlue));
+end;
+
+procedure TJSONObject.SetIntegers(AName : String; const AValue: Integer);
+begin
+  SetElements(AName,TJSONIntegerNumber.Create(AVAlue));
+end;
+
+procedure TJSONObject.SetIsNull(AName : String; const AValue: Boolean);
+begin
+  If Not AValue then
+    Raise EJSON.Create(SErrCannotSetNotIsNull);
+  SetElements(AName,TJSONNull.Create);
+end;
+
+procedure TJSONObject.SetObjects(AName : String; const AValue: TJSONObject);
+begin
+  SetElements(AName,AValue);
+end;
+
+procedure TJSONObject.SetStrings(AName : String; const AValue: TJSONStringType);
+begin
+  SetElements(AName,TJSONString.Create(AVAlue));
+end;
+
+procedure TJSONObject.Converterror(From: Boolean);
+begin
+  If From then
+    Raise EJSON.Create(SErrCannotConvertFromObject)
+  else
+    Raise EJSON.Create(SErrCannotConvertToObject);
+end;
+
+function TJSONObject.GetAsBoolean: Boolean;
+begin
+  ConvertError(True);
+end;
+
+function TJSONObject.GetAsFloat: TJSONFloat;
+begin
+  ConvertError(True);
+end;
+
+function TJSONObject.GetAsInteger: Integer;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONObject.SetAsBoolean(const AValue: Boolean);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONObject.SetAsFloat(const AValue: TJSONFloat);
+begin
+  ConvertError(False);
+end;
+
+procedure TJSONObject.SetAsInteger(const AValue: Integer);
+begin
+  ConvertError(False);
+end;
+
+function TJSONObject.GetAsJSON: TJSONStringType;
+
+Var
+  I : Integer;
+
+begin
+  Result:='';
+  For I:=0 to Count-1 do
+    begin
+    If (Result<>'') then
+      Result:=Result+', ';
+    Result:=Result+'"'+StringToJSONString(Names[i])+'" : '+Items[I].AsJSON;
+    end;
+  If (Result<>'') then
+    Result:='{ '+Result+' }'
+  else
+    Result:='{}';
+end;
+
+function TJSONObject.GetAsString: TJSONStringType;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONObject.SetAsString(const AValue: TJSONStringType);
+begin
+  ConvertError(False);
+end;
+
+function TJSONObject.GetValue: variant;
+begin
+  ConvertError(True);
+end;
+
+procedure TJSONObject.SetValue(const AValue: variant);
+begin
+  ConvertError(False);
+end;
+
+function TJSONObject.GetCount: Integer;
+begin
+  Result:=FHash.Count;
+end;
+
+function TJSONObject.GetItem(Index: Integer): TJSONData;
+begin
+  Result:=TJSONData(FHash.Items[Index]);
+end;
+
+procedure TJSONObject.SetItem(Index: Integer; const AValue: TJSONData);
+begin
+  FHash.Items[Index]:=AValue;
+end;
+
+constructor TJSONObject.Create;
+begin
+  FHash:=TFPHashObjectList.Create(True);
+end;
+
+
+
+constructor TJSONObject.Create(const Elements: array of const);
+
+Var
+  I : integer;
+  F : TJSONFloat;
+  AName : String;
+  J : TJSONData;
+
+begin
+  Create;
+  If ((High(Elements)-Low(Elements)) mod 2)=0 then
+    Raise EJSON.Create(SErrOddNumber);
+  I:=Low(Elements);
+  While I<=High(Elements) do
+    begin
+    With Elements[i] do
+      Case VType of
+        vtChar       : AName:=VChar;
+        vtString     : AName:=vString^;
+        vtAnsiString : AName:=(AnsiString(vAnsiString));
+        vtPChar      : AName:=StrPas(VPChar);
+      else
+        Raise EJSON.CreateFmt(SErrNameMustBeString,[I+1]);
+      end;
+    If (ANAme='') then
+      Raise EJSON.CreateFmt(SErrNameMustBeString,[I+1]);
+    Inc(I);
+    J:=VarRecToJSON(Elements[i],'Object');
+    Add(AName,J);
+    Inc(I);
+    end;
+end;
+
+
+destructor TJSONObject.Destroy;
+begin
+  FreeAndNil(FHash);
+  inherited Destroy;
+end;
+
+class function TJSONObject.JSONType: TJSONType;
+begin
+  Result:=jtObject;
+end;
+
+procedure TJSONObject.Iterate(Iterator: TJSONObjectIterator; Data: TObject);
+
+Var
+  I : Integer;
+  Cont : Boolean;
+
+begin
+  I:=0;
+  Cont:=True;
+  While (I<FHash.Count) and cont do
+    begin
+    Iterator(Names[I],Items[i],Data,Cont);
+    Inc(I);
+    end;
+end;
+
+function TJSONObject.IndexOf(Item: TJSONData): Integer;
+begin
+
+end;
+
+function TJSONObject.IndexOfName(const AName: TJSONStringType): Integer;
+begin
+
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONData
+  ): Integer;
+begin
+  Result:=FHash.Add(AName,AValue);
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; AValue: Boolean
+  ): Integer;
+begin
+  Result:=Add(AName,TJSONBoolean.Create(AValue));
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONFloat): Integer;
+begin
+  Result:=Add(AName,TJSONFloatNumber.Create(AValue));
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONStringType): Integer;
+begin
+  Result:=Add(AName,TJSONString.Create(AValue));
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; Avalue: Integer): Integer;
+begin
+  Result:=Add(AName,TJSONIntegerNumber.Create(AValue));
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType): Integer;
+begin
+  Result:=Add(AName,TJSONNull.Create);
+end;
+
+function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONArray
+  ): Integer;
+begin
+  Result:=Add(AName,TJSONData(AValue));
+end;
+
+procedure TJSONObject.Delete(Index: Integer);
+begin
+  FHash.Delete(Index);
+end;
+
+procedure TJSONObject.Remove(Item: TJSONData);
+begin
+  FHash.Remove(Item);
+end;
+
+end.
+

+ 237 - 0
packages/fcl-json/src/jsonparser.pp

@@ -0,0 +1,237 @@
+unit jsonparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpJSON, jsonscanner;
+  
+Type
+
+  { TJSONParser }
+
+  TJSONParser = Class(TObject)
+  Private
+    FScanner : TJSONScanner;
+    function ParseNumber: TJSONNumber;
+  Protected
+    procedure DoError(Msg: String);
+    function DoParse(AtCurrent,AllowEOF: Boolean): TJSONData;
+    function GetNextToken: TJSONToken;
+    function CurrentTokenString: String;
+    function CurrentToken: TJSONToken;
+    function ParseArray: TJSONArray;
+    function ParseObject: TJSONObject;
+  Public
+    function Parse: TJSONData;
+    Constructor Create(Source : TStream); overload;
+    Constructor Create(Source : TJSONStringType); overload;
+  end;
+  
+  EJSONScanner = Class(Exception);
+  
+implementation
+
+Resourcestring
+  SErrUnexpectedEOF   = 'Unexpected EOF encountered.';
+  SErrUnexpectedToken = 'Unexpected token (%s) encountered.';
+  SErrExpectedColon   = 'Expected colon (:), got token "%s".';
+  SErrUnexpectedComma = 'Invalid comma encountered.';
+  SErrEmptyElement = 'Empty element encountered.';
+  SErrExpectedElementName    = 'Expected element name, got token "%s"';
+  SExpectedCommaorBraceClose = 'Expected , or ], got token "%s".';
+  SErrInvalidNumber          = 'Number is not an integer or real number: %s';
+  
+{ TJSONParser }
+
+Function TJSONParser.Parse : TJSONData;
+
+begin
+  Result:=DoParse(False,True);
+end;
+
+{
+  Consume next token and convert to JSON data structure.
+  If AtCurrent is true, the current token is used. If false,
+  a token is gotten from the scanner.
+  If AllowEOF is false, encountering a tkEOF will result in an exception.
+}
+
+Function TJSONParser.CurrentToken : TJSONToken;
+
+begin
+  Result:=FScanner.CurToken;
+end;
+
+Function TJSONParser.CurrentTokenString : String;
+
+begin
+  If CurrentToken in [tkString,tkNumber] then
+    Result:=FScanner.CurTokenString
+  else
+    Result:=TokenInfos[CurrentToken];
+end;
+
+Function TJSONParser.DoParse(AtCurrent,AllowEOF : Boolean) : TJSONData;
+
+var
+  T : TJSONToken;
+  
+begin
+  Result:=nil;
+  try
+    If not AtCurrent then
+      T:=GetNextToken
+    else
+      T:=FScanner.CurToken;
+    Case T of
+      tkEof : If Not AllowEof then
+                DoError(SErrUnexpectedEOF);
+      tkNull  : Result:=TJSONNull.Create;
+      tkTrue,
+      tkFalse : Result:=TJSONBoolean.Create(t=tkTrue);
+      tkString : Result:=TJSONString.Create(CurrentTokenString);
+      tkCurlyBraceOpen : Result:=ParseObject;
+      tkCurlyBraceClose : DoError(SErrUnexpectedToken);
+      tkSQuaredBraceOpen : Result:=ParseArray;
+      tkSQuaredBraceClose : DoError(SErrUnexpectedToken);
+      tkNumber : Result:=ParseNumber;
+      tkComma : DoError(SErrUnexpectedToken);
+    end;
+  except
+    if assigned(Result) then
+      FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+
+// Creates the correct JSON number type, based on the current token.
+Function TJSONParser.ParseNumber : TJSONNumber;
+
+Var
+  I : Integer;
+  F : TJSONFloat;
+  S : String;
+
+begin
+  S:=CurrentTokenString;
+  I:=0;
+  If TryStrToInt(S,I) then
+    Result:=TJSONIntegerNumber.Create(I)
+  else
+    begin
+    I:=0;
+    Val(S,F,I);
+    If (I<>0) then
+      DoError(SErrInvalidNumber);
+    Result:=TJSONFloatNumber.Create(F);
+    end;
+end;
+
+// Current token is {, on exit current token is }
+Function TJSONParser.ParseObject : TJSONObject;
+
+Var
+  T : TJSONtoken;
+  E : TJSONData;
+  N : String;
+  
+begin
+  Result:=TJSONObject.Create;
+  Try
+    T:=GetNextToken;
+    While T<>tkCurlyBraceClose do
+      begin
+      If T<>tkString then
+        DoError(SErrExpectedElementName);
+      N:=CurrentTokenString;
+      T:=GetNextToken;
+      If (T<>tkColon) then
+        DoError(SErrExpectedColon);
+      Writeln('Getting element');
+      E:=DoParse(False,False);
+      Result.Add(N,E);
+      T:=GetNextToken;
+      If Not (T in [tkComma,tkCurlyBraceClose]) then
+        DoError(SExpectedCommaorBraceClose);
+      If T=tkComma then
+        T:=GetNextToken;
+      end;
+  Except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+// Current token is [, on exit current token is ]
+Function TJSONParser.ParseArray : TJSONArray;
+
+Var
+  T : TJSONtoken;
+  E : TJSONData;
+  LastComma : Boolean;
+  
+begin
+  Result:=TJSONArray.Create;
+  LastComma:=False;
+  Try
+    Repeat
+      T:=GetNextToken;
+      If (T<>tkSquaredBraceClose) then
+        begin
+        E:=DoParse(True,False);
+        If (E<>Nil) then
+          Result.Add(E)
+        else if (Result.Count>0) then
+          DoError(SErrEmptyElement);
+        T:=GetNextToken;
+        If Not (T in [tkComma,tkSquaredBraceClose]) then
+          DoError(SExpectedCommaorBraceClose);
+        LastComma:=(t=TkComma);
+        end;
+    Until (T=tkSquaredBraceClose);
+    If LastComma then // Test for ,] case
+      DoError(SErrUnExpectedToken);
+  Except
+    FreeAndNil(Result);
+    Raise;
+  end;
+end;
+
+// Get next token, discarding whitespace
+Function TJSONParser.GetNextToken : TJSONToken ;
+
+begin
+  Repeat
+    Result:=FScanner.FetchToken;
+  Until (Result<>tkWhiteSpace);
+  Writeln('GetNextToken : ',CurrentTokenString);
+end;
+
+Procedure TJSONParser.DoError(Msg : String);
+
+Var
+  S : String;
+
+begin
+  S:=Format(Msg,[CurrentTokenString]);
+  S:=Format('Error at line %d, Pos %d:',[FScanner.CurRow,FSCanner.CurColumn])+S;
+  Raise EJSONScanner.Create(S);
+end;
+
+constructor TJSONParser.Create(Source: TStream);
+begin
+  Inherited Create;
+  FScanner:=TJSONScanner.Create(Source);
+end;
+
+constructor TJSONParser.Create(Source: TJSONStringType);
+begin
+  Inherited Create;
+  FScanner:=TJSONScanner.Create(Source);
+end;
+
+end.
+

+ 355 - 0
packages/fcl-json/src/jsonscanner.pp

@@ -0,0 +1,355 @@
+{
+    This file is part of the Free Component Library
+
+    JSON source lexical scanner
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    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.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+
+unit jsonscanner;
+
+interface
+
+uses SysUtils, Classes;
+
+resourcestring
+  SErrInvalidCharacter = 'Invalid character ''%s''';
+  SErrOpenString = 'string exceeds end of line';
+
+type
+
+  TJSONToken = (
+    tkEOF,
+    tkWhitespace,
+    tkString,
+    tkNumber,
+    tkTrue,
+    tkFalse,
+    tkNull,
+    // Simple (one-character) tokens
+    tkComma,                 // ','
+    tkColon,                 // ':'
+    tkCurlyBraceOpen,        // '{'
+    tkCurlyBraceClose,       // '}'
+    tkSquaredBraceOpen,       // '['
+    tkSquaredBraceClose,      // ']'
+    tkUnknown
+    );
+
+  EScannerError       = class(Exception);
+
+
+  TJSONScanner = class
+  private
+    FSource : TStringList;
+    FCurRow: Integer;
+    FCurToken: TJSONToken;
+    FCurTokenString: string;
+    FCurLine: string;
+    TokenStr: PChar;
+    function GetCurColumn: Integer;
+  protected
+    procedure Error(const Msg: string);overload;
+    procedure Error(const Msg: string; Args: array of Const);overload;
+    function DoFetchToken: TJSONToken;
+  public
+    constructor Create(Source : TStream); overload;
+    constructor Create(Source : String); overload;
+    destructor Destroy; override;
+    function FetchToken: TJSONToken;
+
+
+    property CurLine: string read FCurLine;
+    property CurRow: Integer read FCurRow;
+    property CurColumn: Integer read GetCurColumn;
+
+    property CurToken: TJSONToken read FCurToken;
+    property CurTokenString: string read FCurTokenString;
+  end;
+
+const
+  TokenInfos: array[TJSONToken] of string = (
+    'EOF',
+    'Whitespace',
+    'String',
+    'Number',
+    'True',
+    'False',
+    'Null',
+    ',',
+    ':',
+    '{',
+    '}',
+    '[',
+    ']',
+    ''
+  );
+
+
+implementation
+
+constructor TJSONScanner.Create(Source : TStream);
+
+begin
+  FSource:=TStringList.Create;
+  FSource.LoadFromStream(Source);
+end;
+
+constructor TJSONScanner.Create(Source : String);
+begin
+  FSource:=TStringList.Create;
+  FSource.Text:=Source;
+end;
+
+destructor TJSONScanner.Destroy;
+begin
+  FreeAndNil(FSource);
+  Inherited;
+end;
+
+
+function TJSONScanner.FetchToken: TJSONToken;
+  
+begin
+  Result:=DoFetchToken;
+end;
+
+procedure TJSONScanner.Error(const Msg: string);
+begin
+  raise EScannerError.Create(Msg);
+end;
+
+procedure TJSONScanner.Error(const Msg: string; Args: array of Const);
+begin
+  raise EScannerError.CreateFmt(Msg, Args);
+end;
+
+function TJSONScanner.DoFetchToken: TJSONToken;
+
+  function FetchLine: Boolean;
+  begin
+    Result:=FCurRow<FSource.Count;
+    if Result then
+      begin
+      FCurLine:=FSource[FCurRow];
+      TokenStr:=PChar(FCurLine);
+      Inc(FCurRow);
+      end
+    else             
+      begin
+      FCurLine:='';
+      TokenStr:=nil;
+      end;
+  end;
+
+var
+  TokenStart, CurPos: PChar;
+  it : TJSONToken;
+  I : Integer;
+  OldLength, SectionLength, Index: Integer;
+  S : String;
+  
+begin
+  if TokenStr = nil then
+    if not FetchLine then
+      begin
+      Result := tkEOF;
+      FCurToken := Result;
+      exit;
+      end;
+
+  FCurTokenString := '';
+
+  case TokenStr[0] of
+    #0:         // Empty line
+      begin
+      FetchLine;
+      Result := tkWhitespace;
+      end;
+    #9, ' ':
+      begin
+      Result := tkWhitespace;
+      repeat
+        Inc(TokenStr);
+        if TokenStr[0] = #0 then
+          if not FetchLine then
+          begin
+            FCurToken := Result;
+            exit;
+          end;
+      until not (TokenStr[0] in [#9, ' ']);
+      end;
+    '"':
+      begin
+        Inc(TokenStr);
+        TokenStart := TokenStr;
+        OldLength := 0;
+        FCurTokenString := '';
+
+        while not (TokenStr[0] in [#0,'"']) do
+          begin
+          if (TokenStr[0]='\') then
+            begin
+            // Save length
+            SectionLength := TokenStr - TokenStart;
+            Inc(TokenStr);
+            // Read escaped token
+            Case TokenStr[0] of
+              '"' : S:='"';
+              't' : S:=#9;
+              'b' : S:=#8;
+              'n' : S:=#10;
+              'r' : S:=#13;
+              'f' : S:=#12;
+              '\' : S:='\';
+              '/' : S:='/';
+              'u' : begin
+                    S:='0000';
+                    For I:=1 to 4 do
+                      begin
+                      Inc(TokenStr);
+                      Case TokenStr[0] of
+                        '0'..'9','A'..'F','a'..'f' :
+                          S[i]:=Upcase(TokenStr[0]);
+                      else
+                        Error(SErrInvalidCharacter, [TokenStr[0]]);
+                      end;
+                      end;
+                    // Takes care of conversion...  
+                    S:=WideChar(StrToInt('$'+S));  
+                    end;
+              #0  : Error(SErrOpenString);
+            else
+              Error(SErrInvalidCharacter, [TokenStr[0]]);  
+            end;
+            SetLength(FCurTokenString, OldLength + SectionLength+1+Length(S));
+            if SectionLength > 0 then
+              Move(TokenStart^, FCurTokenString[OldLength + 1], SectionLength);
+            Move(S[1],FCurTokenString[OldLength + SectionLength+1],Length(S));
+            Inc(OldLength, SectionLength+Length(S));
+            // Next char
+            // Inc(TokenStr);
+            TokenStart := TokenStr+1;
+            end;
+          if TokenStr[0] = #0 then
+            Error(SErrOpenString);
+          Inc(TokenStr);
+          end;
+        if TokenStr[0] = #0 then
+          Error(SErrOpenString);
+        SectionLength := TokenStr - TokenStart;
+        SetLength(FCurTokenString, OldLength + SectionLength);
+        if SectionLength > 0 then
+          Move(TokenStart^, FCurTokenString[OldLength + 1], SectionLength);
+        Inc(TokenStr);
+        Result := tkString;
+      end;
+    ',':
+      begin
+        Inc(TokenStr);
+        Result := tkComma;
+      end;
+    '0'..'9','-':
+      begin
+        TokenStart := TokenStr;
+        while true do
+        begin
+          Inc(TokenStr);
+          case TokenStr[0] of
+            '.':
+              begin
+                if TokenStr[1] in ['0'..'9', 'e', 'E'] then
+                begin
+                  Inc(TokenStr);
+                  repeat
+                    Inc(TokenStr);
+                  until not (TokenStr[0] in ['0'..'9', 'e', 'E','-','+']);
+                end;
+                break;
+              end;
+            '0'..'9': ;
+            'e', 'E':
+              begin
+                Inc(TokenStr);
+                if TokenStr[0] in ['-','+']  then
+                  Inc(TokenStr);
+                while TokenStr[0] in ['0'..'9'] do
+                  Inc(TokenStr);
+                break;
+              end;
+            else
+              break;
+          end;
+        end;
+        SectionLength := TokenStr - TokenStart;
+        SetLength(FCurTokenString, SectionLength);
+        if SectionLength > 0 then
+          Move(TokenStart^, FCurTokenString[1], SectionLength);
+        Result := tkNumber;
+      end;
+    ':':
+      begin
+        Inc(TokenStr);
+        Result := tkColon;
+      end;
+    '{':
+      begin
+        Inc(TokenStr);
+        Result := tkCurlyBraceOpen;
+      end;
+    '}':
+      begin
+        Inc(TokenStr);
+        Result := tkCurlyBraceClose;
+      end;  
+    '[':
+      begin
+        Inc(TokenStr);
+        Result := tkSquaredBraceOpen;
+      end;
+    ']':
+      begin
+        Inc(TokenStr);
+        Result := tkSquaredBraceClose;
+      end;
+    'T','t','F','f','N','n' :
+      begin
+        TokenStart := TokenStr;
+        repeat
+          Inc(TokenStr);
+        until not (TokenStr[0] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
+        SectionLength := TokenStr - TokenStart;
+        SetLength(FCurTokenString, SectionLength);
+        if SectionLength > 0 then
+          Move(TokenStart^, FCurTokenString[1], SectionLength);
+        for it := tkTrue to tkNull do
+          if CompareText(CurTokenString, TokenInfos[it]) = 0 then
+            begin
+            Result := it;
+            FCurToken := Result;
+            exit;
+            end;
+        Error(SErrInvalidCharacter, [TokenStart[0]]);
+      end;
+  else
+    Error(SErrInvalidCharacter, [TokenStr[0]]);
+  end;
+
+  FCurToken := Result;
+end;
+
+function TJSONScanner.GetCurColumn: Integer;
+begin
+  Result := TokenStr - PChar(CurLine);
+end;
+
+end.

+ 65 - 0
packages/fcl-json/tests/testjson.lpi

@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <IconPath Value="./"/>
+      <TargetFileExt Value=""/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="3">
+      <Item1>
+        <PackageName Value="LCL"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FPCUnitTestRunner"/>
+      </Item2>
+      <Item3>
+        <PackageName Value="FCL"/>
+      </Item3>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="testjson.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testjson"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="testjsonparser.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testjsonparser"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="testjsondata.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testjsondata"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 21 - 0
packages/fcl-json/tests/testjson.pp

@@ -0,0 +1,21 @@
+program testjson;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, testjsondata, testjsonparser;
+type
+  { TLazTestRunner }
+   TMyTestRunner = class(TTestRunner)
+   protected
+     // override the protected methods of TTestRunner to customize its behavior
+   end;
+      
+var
+  Application: TMyTestRunner;
+begin
+  Application := TMyTestRunner.Create(nil); 
+  Application.Initialize;
+  Application.Run;  
+  Application.Free;
+end.

+ 1786 - 0
packages/fcl-json/tests/testjsondata.pp

@@ -0,0 +1,1786 @@
+unit testjsondata; 
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, fpjson;
+
+type
+
+
+  { TTestJSONString }
+
+  TTestJSONString = Class(TTestCase)
+  Private
+    Procedure TestTo(Const Src,Dest : String);
+    Procedure TestFrom(Const Src,Dest : String);
+  Published
+    Procedure TestJSONStringToString;
+    Procedure TestStringToJSONString;
+  end;
+  
+  { TTestJSON }
+  
+  TTestJSON = Class(TTestCase)
+  Protected
+    Procedure TestItemCount(J : TJSONData;Expected : Integer);
+    Procedure TestJSONType(J : TJSONData;Expected : TJSONType);
+    Procedure TestJSON(J : TJSONData;Expected : String);
+    Procedure TestIsNull(J : TJSONData;Expected : Boolean);
+    Procedure TestAsBoolean(J : TJSONData;Expected : Boolean; ExpectError : boolean = False);
+    Procedure TestAsInteger(J : TJSONData; Expected : Integer; ExpectError : boolean = False);
+    Procedure TestAsString(J : TJSONData; Expected : String; ExpectError : boolean = False);
+    Procedure TestAsFloat(J : TJSONData; Expected : TJSONFloat; ExpectError : boolean = False);
+  end;
+  
+  { TTestNull }
+
+  TTestNull = class(TTestJSON)
+  published
+    procedure TestNull;
+  end;
+  
+  { TTestBoolean }
+
+  TTestBoolean = class(TTestJSON)
+  published
+    procedure TestTrue;
+    procedure TestFalse;
+  end;
+  
+  { TTestInteger }
+
+  TTestInteger = class(TTestJSON)
+  Private
+    Procedure DoTest(I : Integer);
+  published
+    procedure TestPositive;
+    procedure TestNegative;
+    procedure TestZero;
+  end;
+  
+  { TTestFloat }
+
+  TTestFloat = class(TTestJSON)
+  Private
+    Procedure DoTest(F : TJSONFloat);
+  published
+    procedure TestPositive;
+    procedure TestNegative;
+    procedure TestZero;
+  end;
+
+  { TTestString }
+
+  TTestString = class(TTestJSON)
+  private
+    procedure DoTestFloat(F: TJSOnFloat; S: String; OK: Boolean);
+  published
+    procedure TestString;
+    procedure TestInteger;
+    procedure TestNegativeInteger;
+    procedure TestFloat;
+    procedure TestNegativeFloat;
+    Procedure TestBooleanTrue;
+    Procedure TestBooleanFalse;
+  end;
+  
+  { TTestArray }
+
+  TTestArray = class(TTestJSON)
+  private
+    procedure TestAddBoolean(B : Boolean);
+  published
+    Procedure TestCreate;
+    Procedure TestCreateString;
+    Procedure TestCreatePchar;
+    procedure TestCreateStrings;
+    procedure TestCreateInteger;
+    procedure TestCreateInt64;
+    procedure TestCreateFloat;
+    procedure TestCreateBoolean;
+    procedure TestCreateObject;
+    procedure TestCreateJSONString;
+    procedure TestCreateJSONObject;
+    procedure TestCreateNilPointer;
+    procedure TestCreatePointer;
+    procedure TestAddInteger;
+    procedure TestAddFloat;
+    procedure TestAddBooleanTrue;
+    procedure TestAddBooleanFalse;
+    procedure TestAddString;
+    procedure TestAddNull;
+    procedure TestAddObject;
+    procedure TestAddArray;
+    procedure TestDelete;
+    procedure TestRemove;
+  end;
+  
+  { TTestObject }
+
+  TTestObject = class(TTestJSON)
+  private
+    procedure TestAddBoolean(B : Boolean);
+  published
+    Procedure TestCreate;
+    Procedure TestCreateString;
+    Procedure TestCreatePchar;
+    procedure TestCreateStrings;
+    procedure TestCreateInteger;
+    procedure TestCreateInt64;
+    procedure TestCreateFloat;
+    procedure TestCreateBoolean;
+    procedure TestCreateObject;
+    procedure TestCreateJSONString;
+    procedure TestCreateJSONObject;
+    procedure TestCreateNilPointer;
+    procedure TestCreatePointer;
+    procedure TestAddInteger;
+    procedure TestAddFloat;
+    procedure TestAddBooleanTrue;
+    procedure TestAddBooleanFalse;
+    procedure TestAddString;
+    procedure TestAddNull;
+    procedure TestAddObject;
+    procedure TestAddArray;
+    procedure TestDelete;
+    procedure TestRemove;
+  end;
+
+
+implementation
+
+{ TTestJSON }
+
+procedure TTestJSON.TestItemCount(J: TJSONData; Expected: Integer);
+begin
+  AssertEquals(J.ClassName+'.ItemCount',Expected,J.Count);
+end;
+
+procedure TTestJSON.TestJSONType(J: TJSONData; Expected: TJSONType);
+begin
+  AssertEquals(J.ClassName+'.JSONType',Ord(Expected),Ord(J.JSONType));
+end;
+
+procedure TTestJSON.TestJSON(J: TJSONData; Expected: String);
+begin
+  AssertEquals(J.ClassName+'.AsJSON',Expected,J.AsJSON);
+end;
+
+procedure TTestJSON.TestIsNull(J: TJSONData; Expected: Boolean);
+begin
+  AssertEquals(J.ClassName+'.IsNull',Expected,J.IsNull);
+end;
+
+procedure TTestJSON.TestAsBoolean(J: TJSONData; Expected: Boolean; ExpectError: boolean = False);
+
+Var
+  B : Boolean;
+  AssignOK : Boolean;
+  Msg : String;
+  
+begin
+  AssignOK:=False;
+  Try
+    B:=J.AsBoolean;
+    AssignOK:=True;
+    If Not ExpectError then
+      AssertEquals(J.Classname+'.AsBoolean',Expected,B);
+  except
+    On E : Exception do
+      begin
+      AssignOK:=False;
+      Msg:=E.Message;
+      end;
+  end;
+  If ExpectError then
+    begin
+    If AssignOK then
+      Fail(J.ClassName+'.AsBoolean must raise error');
+    end
+  else
+    begin
+    If not AssignOK then
+      Fail(J.ClassName+'.AsBoolean raised unexpected exception: '+Msg)
+    end;
+end;
+
+procedure TTestJSON.TestAsInteger(J: TJSONData; Expected: Integer;
+  ExpectError: boolean);
+
+Var
+  I : Integer;
+  AssignOK : Boolean;
+  Msg : String;
+
+begin
+  AssignOK:=False;
+  Try
+    I:=J.AsInteger;
+    AssignOK:=True;
+    If Not ExpectError then
+      AssertEquals(J.Classname+'.AsInteger',Expected,I);
+  except
+    On E : Exception do
+      begin
+      AssignOK:=False;
+      Msg:=E.Message;
+      end;
+  end;
+  If ExpectError then
+    begin
+    If AssignOK then
+      Fail(J.ClassName+'.AsInteger must raise error');
+    end
+  else
+    begin
+    If not AssignOK then
+      Fail(J.ClassName+'.AsInteger raised unexpected exception: '+Msg)
+    end;
+end;
+
+procedure TTestJSON.TestAsString(J: TJSONData; Expected: String;
+  ExpectError: boolean);
+  
+Var
+  S : String;
+  AssignOK : Boolean;
+  Msg : String;
+
+begin
+  AssignOK:=False;
+  Try
+    S:=J.AsString;
+    AssignOK:=True;
+    If Not ExpectError then
+      AssertEquals(J.Classname+'.AsString',Expected,S);
+  except
+    On E : Exception do
+      begin
+      AssignOK:=False;
+      Msg:=E.Message;
+      end;
+  end;
+  If ExpectError then
+    begin
+    If AssignOK then
+      Fail(J.ClassName+'.AsString must raise error');
+    end
+  else
+    begin
+    If not AssignOK then
+      Fail(J.ClassName+'.AsString raised unexpected exception: '+Msg)
+    end;
+end;
+
+procedure TTestJSON.TestAsFloat(J: TJSONData; Expected: TJSONFloat;
+  ExpectError: boolean);
+  
+Var
+  F : TJSONFloat;
+  AssignOK : Boolean;
+  Msg : String;
+
+begin
+  AssignOK:=False;
+  Try
+    F:=J.AsFloat;
+    AssignOK:=True;
+    If Not ExpectError then
+      AssertEquals(J.Classname+'.AsFloat',Expected,F);
+  except
+    On E : Exception do
+      begin
+      AssignOK:=False;
+      Msg:=E.Message;
+      end;
+  end;
+  If ExpectError then
+    begin
+    If AssignOK then
+      Fail(J.ClassName+'.AsFloat must raise error');
+    end
+  else
+    begin
+    If not AssignOK then
+      Fail(J.ClassName+'.AsFloat raised unexpected exception: '+Msg)
+    end;
+end;
+
+{ TTestBoolean }
+
+procedure TTestBoolean.TestTrue;
+
+Var
+  J : TJSONBoolean;
+
+begin
+  J:=TJSONBoolean.Create(True);
+  try
+    TestJSONType(J,jtBoolean);
+    TestItemCount(J,0);
+    TestJSON(J,'True');
+    TestIsNull(J,False);
+    TestAsBoolean(J,True);
+    TestAsInteger(J,1);
+    TestAsString(J,BoolToStr(True));
+    TestAsFloat(J,1.0);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestBoolean.TestFalse;
+
+Var
+  J : TJSONBoolean;
+
+begin
+  J:=TJSONBoolean.Create(False);
+  try
+    TestJSONType(J,jtBoolean);
+    TestItemCount(J,0);
+    TestJSON(J,'False');
+    TestIsNull(J,False);
+    TestAsBoolean(J,False);
+    TestAsInteger(J,0);
+    TestAsString(J,BoolToStr(False));
+    TestAsFloat(J,0.0);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+
+
+{ TTestNull }
+
+procedure TTestNull.TestNull;
+
+Var
+  J : TJSONNull;
+
+begin
+  J:=TJSONNull.Create;
+  try
+    TestJSONType(J,jtNull);
+    TestItemCount(J,0);
+    TestJSON(J,'Null');
+    TestIsNull(J,True);
+    TestAsBoolean(J,False,True);
+    TestAsInteger(J,0,true);
+    TestAsString(J,BoolToStr(False),true);
+    TestAsFloat(J,0.0,true);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+
+{ TTestString }
+
+procedure TTestString.TestString;
+
+Const
+  S = 'A string';
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,False,True);
+    TestAsInteger(J,0,true);
+    TestAsString(J,S);
+    TestAsFloat(J,0.0,true);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestString.TestInteger;
+
+Const
+  S = '1';
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,True,False);
+    TestAsInteger(J,1,False);
+    TestAsString(J,S);
+    TestAsFloat(J,1.0,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestString.TestNegativeInteger;
+
+Const
+  S = '-1';
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,True,False);
+    TestAsInteger(J,-1,False);
+    TestAsString(J,S);
+    TestAsFloat(J,-1.0,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestString.TestFloat;
+
+begin
+  DoTestFloat(1.0,'1.0',True);
+  DoTestFloat(1.0,'1',True);
+  DoTestFloat(1.0,'1e0',True);
+  DoTestFloat(1.2,'1.2',True);
+  DoTestFloat(12.0,'1.2e1',True);
+end;
+
+procedure TTestString.TestNegativeFloat;
+begin
+  DoTestFloat(-1.0,'-1.0',True);
+  DoTestFloat(-1.0,'-1',True);
+  DoTestFloat(-1.0,'-1e0',True);
+  DoTestFloat(-1.2,'-1.2',True);
+  DoTestFloat(-12.0,'-1.2e1',True);
+end;
+
+procedure TTestString.TestBooleanTrue;
+
+Const
+  S = 'True';
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,True,False);
+    TestAsInteger(J,-1,True);
+    TestAsString(J,S);
+    TestAsFloat(J,-1.0,True);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestString.TestBooleanFalse;
+
+Const
+  S = 'False';
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,False,False);
+    TestAsInteger(J,0,True);
+    TestAsString(J,S);
+    TestAsFloat(J,0,True);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestString.DoTestFloat(F : TJSOnFloat;S : String; OK : Boolean);
+
+Var
+  J : TJSONString;
+
+begin
+  J:=TJSONString.Create(S);
+  try
+    TestJSONType(J,jtString);
+    TestItemCount(J,0);
+    TestJSON(J,'"'+S+'"');
+    TestIsNull(J,False);
+    TestAsBoolean(J,(F<>0),Not OK);
+    TestAsInteger(J,Round(F),(Pos('.',S)<>0) or (Pos('E',UpperCase(S))<>0));
+    TestAsString(J,S);
+    TestAsFloat(J,F,Not OK);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+
+{ TTestInteger }
+
+procedure TTestInteger.DoTest(I: Integer);
+
+Var
+  J : TJSONIntegerNumber;
+
+begin
+  J:=TJSONIntegerNumber.Create(I);
+  try
+    TestJSONType(J,jtNumber);
+    TestItemCount(J,0);
+    AssertEquals('Numbertype is ntInteger',ord(ntInteger),Ord(J.NumberType));
+    TestJSON(J,IntToStr(i));
+    TestIsNull(J,False);
+    TestAsBoolean(J,(I<>0));
+    TestAsInteger(J,I);
+    TestAsString(J,IntToStr(I));
+    TestAsFloat(J,I);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestInteger.TestPositive;
+
+begin
+  DoTest(1);
+end;
+
+procedure TTestInteger.TestNegative;
+begin
+  DoTest(-1);
+end;
+
+procedure TTestInteger.TestZero;
+begin
+  DoTest(0);
+end;
+
+{ TTestFloat }
+
+procedure TTestFloat.DoTest(F: TJSONFloat);
+
+Var
+  J : TJSONFloatNumber;
+  S : String;
+  
+begin
+  Str(F,S);
+  J:=TJSONFloatNumber.Create(F);
+  try
+    TestJSONType(J,jtNumber);
+    TestItemCount(J,0);
+    AssertEquals('Numbertype is ntFloat',ord(ntFloat),Ord(J.NumberType));
+    TestJSON(J,S);
+    TestIsNull(J,False);
+    TestAsBoolean(J,(F<>0));
+    TestAsInteger(J,Round(F));
+    TestAsString(J,S);
+    TestAsFloat(J,F);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestFloat.TestPositive;
+begin
+  DoTest(1.0);
+  DoTest(1.2);
+  DoTest(1.2e1);
+  DoTest(1.2e-1);
+  DoTest(1.2e10);
+  DoTest(1.2e-10);
+end;
+
+procedure TTestFloat.TestNegative;
+begin
+  DoTest(-1.0);
+  DoTest(-1.2);
+  DoTest(-1.2e1);
+  DoTest(-1.2e-1);
+  DoTest(-1.2e10);
+  DoTest(-1.2e-10);
+end;
+
+procedure TTestFloat.TestZero;
+begin
+  DoTest(0.0);
+end;
+
+{ TTestArray }
+
+procedure TTestArray.TestCreate;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,0);
+    TestJSON(J,'[]');
+    TestIsNull(J,False);
+    TestAsBoolean(J,False,True);
+    TestAsInteger(J,1,True);
+    TestAsString(J,'',True);
+    TestAsFloat(J,0.0,True);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateString;
+
+Const
+  S = 'A string';
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([S]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtString);
+    TestJSON(J,'["'+S+'"]');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreatePChar;
+
+Const
+  S = 'A string';
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([Pchar(S)]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtString);
+    TestJSON(J,'["'+S+'"]');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateStrings;
+
+Const
+  S = 'A string';
+  T = 'B string';
+  
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSONArray.Create([S,T]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,2);
+    TestJSONType(J[0],jtString);
+    TestJSONType(J[1],jtString);
+    TestJSON(J,'["'+S+'", "'+T+'"]');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateInteger;
+
+Const
+  S = 3;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([S]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNumber);
+    TestJSON(J,'[3]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateFloat;
+
+Const
+  S = 1.2;
+
+Var
+  J : TJSONArray;
+  r : String;
+  
+begin
+  J:=TJSonArray.Create([S]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNumber);
+    Str(S,R);
+    TestJSON(J,'['+R+']');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateInt64;
+
+Const
+  S : Int64 = $FFFFFF;
+
+Var
+  J : TJSONArray;
+  r : String;
+  F : TJSONFloat;
+
+begin
+  J:=TJSonArray.Create([S]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNumber);
+    F:=S;
+    Str(F,R);
+    TestJSON(J,'['+R+']');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateBoolean;
+
+Const
+  S = True;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([S]);
+  try
+    TestJSONType(J,jtArray);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtBoolean);
+    TestJSON(J,'[True]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateJSONObject;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([TJSONObject.Create]);
+  try
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtObject);
+    TestJSON(J,'[{}]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+procedure TTestArray.TestCreateJSONString;
+
+Const
+  S = 'A string';
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create([TJSONString.Create(S)]);
+  try
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtString);
+    TestJSON(J,'["'+S+'"]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreateObject;
+
+Var
+  J : TJSONArray;
+  
+begin
+  J:=Nil;
+  try
+    Try
+      J:=TJSONArray.Create([TObject.Create]);
+      Fail('Array constructor accepts only TJSONData');
+    finally
+      FreeAndNil(J);
+    end;
+  except
+    // Should be OK.
+  end;
+end;
+
+procedure TTestArray.TestCreateNilPointer;
+
+Var
+  J : TJSONArray;
+  P : Pointer;
+  
+begin
+  J:=Nil;
+  P:=Nil;
+  Try
+    J:=TJSONArray.Create([P]);
+    TestJSONType(J[0],jtNull);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestCreatePointer;
+
+Var
+  J : TJSONArray;
+  P : Pointer;
+  
+begin
+  J:=Nil;
+  P:=@Self;
+  try
+    Try
+      J:=TJSONArray.Create([P]);
+      Fail('Array constructor accepts only NIL pointers');
+    finally
+      FreeAndNil(J);
+    end;
+  except
+    // Should be OK.
+  end;
+end;
+
+procedure TTestArray.TestAddInteger;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J.Add(0);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNumber);
+    AssertEquals('J[0] is TJSONIntegerNumber',J[0].ClassType,TJSONIntegerNumber);
+    AssertEquals('j.Types[0]=jtNumber',ord(J.Types[0]),Ord(jtNumber));
+    AssertEquals('J.Integers[0]=0',0,J.integers[0]);
+    TestAsInteger(J[0],0);
+    TestJSON(J,'[0]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestAddFloat;
+
+Var
+  J : TJSONArray;
+  S : String;
+  F : TJSONFloat;
+begin
+  F:=1.2;
+  J:=TJSonArray.Create;
+  try
+    J.Add(F);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNumber);
+    AssertEquals('J[0] is TJSONFloatNumber',TJSONfloatNumber,J[0].ClassType);
+    AssertEquals('j.Types[0]=jtNumber',Ord(jtNumber),ord(J.Types[0]));
+    AssertEquals('J.Floats[0]='+FloatToStr(F),F,J.Floats[0]);
+    TestAsFloat(J[0],F);
+    Str(F,S);
+    TestJSON(J,'['+S+']');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestAddBoolean(B : Boolean);
+
+Var
+  J : TJSONArray;
+
+begin
+  B:=True;
+  J:=TJSonArray.Create;
+  try
+    J.Add(B);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtBoolean);
+    AssertEquals('J[0] is TJSONBoolean',TJSONBoolean,J[0].ClassType);
+    TestAsBoolean(J[0],B);
+    AssertEquals('J.Booleans[0]='+BoolToStr(B)+'"',B,J.Booleans[0]);
+    If B then
+      TestJSON(J,'[True]')
+    else
+      TestJSON(J,'[False]');
+  finally
+    FreeAndNil(J);
+  end;
+
+end;
+
+procedure TTestArray.TestAddBooleanTrue;
+
+begin
+  TestAddBoolean(True);
+end;
+
+procedure TTestArray.TestAddBooleanFalse;
+
+begin
+  TestAddBoolean(False);
+end;
+
+procedure TTestArray.TestAddString;
+
+Var
+  J : TJSONArray;
+  S : String;
+  F : TJSONFloat;
+  
+begin
+  S:='A string';
+  J:=TJSonArray.Create;
+  try
+    J.Add(S);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtString);
+    AssertEquals('J[0] is TJSONString',TJSONString,J[0].ClassType);
+    TestAsString(J[0],S);
+    AssertEquals('J.Strings[0]="'+S+'"',S,J.Strings[0]);
+    TestJSON(J,'["'+StringToJSONString(S)+'"]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestAddNull;
+
+Var
+  J : TJSONArray;
+  S : String;
+  F : TJSONFloat;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J.Add;
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtNull);
+    AssertEquals('J[0] is TJSONNull',TJSONNull,J[0].ClassType);
+    AssertEquals('J.Nulls[0]=True',True,J.Nulls[0]);
+    TestIsNull(J[0],true);
+    TestJSON(J,'[Null]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestAddArray;
+
+Var
+  J,J2 : TJSONArray;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J2:=TJSonArray.Create;
+    J2.Add(0);
+    J2.Add(1);
+    J.Add(J2);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtArray);
+    AssertEquals('J[0] is TJSONArray',TJSONArray,J[0].ClassType);
+    AssertEquals('J.Arrays[0] is TJSONArray',TJSONArray,J.Arrays[0].ClassType);
+    TestAsInteger(J.Arrays[0][0],0);
+    TestAsInteger(J.Arrays[0][1],1);
+    TestJSON(J,'[[0, 1]]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestAddObject;
+
+Const
+  A = 'a';
+  B = 'b';
+  
+Var
+  J : TJSONArray;
+  J2 : TJSONObject;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J2:=TJSonObject.Create;
+    J2.Add(A,0);
+    J2.Add(B,1);
+    J.Add(J2);
+    TestItemCount(J,1);
+    TestJSONType(J[0],jtObject);
+    AssertEquals('J[0] is TJSONObject',TJSONObject,J[0].ClassType);
+    AssertEquals('J.Objects[0] is TJSONObject',TJSONObject,J.Objects[0].ClassType);
+    TestAsInteger(J.Objects[0][A],0);
+    TestAsInteger(J.Objects[0][B],1);
+    TestJSON(J,'[{ "a" : 0, "b" : 1 }]');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestDelete;
+
+Var
+  J : TJSONArray;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J.Add(0);
+    J.Add(1);
+    TestItemCount(J,2);
+    TestJSONType(J[0],jtNumber);
+    TestJSONType(J[1],jtNumber);
+    TestJSON(J,'[0, 1]');
+    J.Delete(1);
+    TestItemCount(J,1);
+    J.Delete(0);
+    TestItemCount(J,0);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestArray.TestRemove;
+
+Var
+  J : TJSONArray;
+  I : TJSONData;
+
+begin
+  J:=TJSonArray.Create;
+  try
+    J.Add(0);
+    J.Add(1);
+    J.Add(2);
+    TestItemCount(J,3);
+    TestJSONType(J[0],jtNumber);
+    TestJSONType(J[1],jtNumber);
+    TestJSONType(J[2],jtNumber);
+    TestJSON(J,'[0, 1, 2]');
+    I:=J[1];
+    J.Remove(I);
+    TestItemCount(J,2);
+    TestAsInteger(J[0],0);
+    TestAsInteger(J[1],2);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+{ TTestObject }
+
+procedure TTestObject.TestCreate;
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create;
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,0);
+    TestJSON(J,'{}');
+    TestIsNull(J,False);
+    TestAsBoolean(J,False,True);
+    TestAsInteger(J,1,True);
+    TestAsString(J,'',True);
+    TestAsFloat(J,0.0,True);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddInteger;
+
+Const
+  A = 'a';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,0);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtNumber);
+    AssertEquals('J[''a''] is TJSONIntegerNumber',J[A].ClassType,TJSONIntegerNumber);
+    AssertEquals('j.Types[''a'']=jtNumber',ord(J.Types[A]),Ord(jtNumber));
+    AssertEquals('J.Integers[''a'']=0',0,J.integers[A]);
+    TestAsInteger(J[A],0);
+    TestJSON(J,'{ "'+A+'" : 0 }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddFloat;
+
+Const
+  A = 'a';
+
+Var
+  J : TJSONObject;
+  S : String;
+  F : TJSONFloat;
+begin
+  F:=1.2;
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,F);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtNumber);
+    AssertEquals('J[''a''] is TJSONFloatNumber',TJSONfloatNumber,J[a].ClassType);
+    AssertEquals('j.Types[''a'']=jtNumber',Ord(jtNumber),ord(J.Types[a]));
+    AssertEquals('J.Floats[''a'']='+FloatToStr(F),F,J.Floats[a]);
+    TestAsFloat(J[A],F);
+    Str(F,S);
+    TestJSON(J,'{ "'+a+'" : '+S+' }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddBoolean(B : Boolean);
+
+Const
+  A = 'a';
+  
+Var
+  J : TJSONObject;
+
+begin
+  B:=True;
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,B);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtBoolean);
+    AssertEquals('J[''a''] is TJSONBoolean',TJSONBoolean,J[a].ClassType);
+    TestAsBoolean(J[a],B);
+    AssertEquals('J.Booleans[''a'']='+BoolToStr(B)+'"',B,J.Booleans[a]);
+    If B then
+      TestJSON(J,'{ "'+a+'" : True }')
+    else
+      TestJSON(J,'{ "'+a+'" : False }');
+  finally
+    FreeAndNil(J);
+  end;
+
+end;
+
+procedure TTestObject.TestAddBooleanTrue;
+
+begin
+  TestAddBoolean(True);
+end;
+
+procedure TTestObject.TestAddBooleanFalse;
+
+begin
+  TestAddBoolean(False);
+end;
+
+procedure TTestObject.TestAddString;
+
+Const
+  A = 'a';
+
+Var
+  J : TJSONObject;
+  S : String;
+  F : TJSONFloat;
+
+begin
+  S:='A string';
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,S);
+    TestItemCount(J,1);
+    TestJSONType(J[a],jtString);
+    AssertEquals('J[''a''] is TJSONString',TJSONString,J[A].ClassType);
+    TestAsString(J[a],S);
+    AssertEquals('J.Strings[''a'']="'+S+'"',S,J.Strings[A]);
+    TestJSON(J,'{ "'+a+'" : "'+StringToJSONString(S)+'" }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddNull;
+
+Const
+  A = 'a';
+
+Var
+  J : TJSONObject;
+  S : String;
+  F : TJSONFloat;
+
+begin
+  J:=TJSonObject.Create;
+  try
+    J.Add(a);
+    TestItemCount(J,1);
+    TestJSONType(J[a],jtNull);
+    AssertEquals('J[''a''] is TJSONNull',TJSONNull,J[A].ClassType);
+    AssertEquals('J.Nulls[''a'']=True',True,J.Nulls[A]);
+    TestIsNull(J[a],true);
+    TestJSON(J,'{ "'+a+'" : Null }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddObject;
+
+Const
+  A = 'a';
+  B = 'b';
+  C = 'c';
+
+Var
+  J,J2 : TJSONObject;
+
+begin
+  J:=TJSonObject.Create;
+  try
+    J2:=TJSonObject.Create;
+    J2.Add(B,0);
+    J2.Add(C,1);
+    J.Add(A,J2);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtObject);
+    AssertEquals('J[''a''] is TJSONObject',TJSONObject,J[A].ClassType);
+    AssertEquals('J.Objects[''a''] is TJSONObject',TJSONObject,J.Objects[A].ClassType);
+    TestAsInteger(J.Objects[A][B],0);
+    TestAsInteger(J.Objects[A][C],1);
+    TestJSON(J,'{ "a" : { "b" : 0, "c" : 1 } }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestAddArray;
+
+Const
+  A = 'a';
+
+Var
+  J : TJSONObject;
+  J2 : TJSONArray;
+
+begin
+  J:=TJSONObject.Create;
+  try
+    J2:=TJSonArray.Create;
+    J2.Add(0);
+    J2.Add(1);
+    J.Add(A,J2);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtArray);
+    AssertEquals('J[''a''] is TJSONArray',TJSONArray,J[A].ClassType);
+    AssertEquals('J.Arrays[0] is TJSONArray',TJSONArray,J.Arrays[A].ClassType);
+    TestAsInteger(J.Arrays[A][0],0);
+    TestAsInteger(J.Arrays[A][1],1);
+    TestJSON(J,'{ "a" : [0, 1] }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestDelete;
+
+Const
+  A = 'a';
+  B = 'b';
+  
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,0);
+    J.Add(B,1);
+    TestItemCount(J,2);
+    TestJSONType(J[A],jtNumber);
+    TestJSONType(J[A],jtNumber);
+    TestJSON(J,'{ "a" : 0, "b" : 1 }');
+    J.Delete(1);
+    TestItemCount(J,1);
+    J.Delete(0);
+    TestItemCount(J,0);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestRemove;
+
+Const
+  A = 'a';
+  B = 'b';
+  C = 'c';
+  
+Var
+  J : TJSONObject;
+  I : TJSONData;
+
+begin
+  J:=TJSonObject.Create;
+  try
+    J.Add(A,1);
+    J.Add(B,2);
+    J.Add(C,3);
+    TestItemCount(J,3);
+    TestJSONType(J[A],jtNumber);
+    TestJSONType(J[B],jtNumber);
+    TestJSONType(J[C],jtNumber);
+    TestJSON(J,'{ "a" : 1, "b" : 2, "c" : 3 }');
+    I:=J[b];
+    J.Remove(I);
+    TestItemCount(J,2);
+    TestAsInteger(J[a],1);
+    TestAsInteger(J[c],3);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+
+procedure TTestObject.TestCreateString;
+
+Const
+  A = 'A';
+  S = 'A string';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,S]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtString);
+    TestJSON(J,'{ "A" : "'+S+'" }');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreatePChar;
+
+Const
+  A = 'A';
+  S = 'A string';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,Pchar(S)]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtString);
+    TestJSON(J,'{ "A" : "'+S+'" }');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateStrings;
+
+Const
+  A = 'A';
+  B = 'B';
+  S = 'A string';
+  T = 'B string';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,S,B,T]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,2);
+    TestJSONType(J[A],jtString);
+    TestJSONType(J[B],jtString);
+    TestJSON(J,'{ "A" : "'+S+'", "B" : "'+T+'" }');
+    TestIsNull(J,False);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateInteger;
+
+Const
+  A = 'A';
+  S = 3;
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,S]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtNumber);
+    TestJSON(J,'{ "A" : 3 }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateFloat;
+
+Const
+  A = 'A';
+  S = 1.2;
+
+Var
+  J : TJSONObject;
+  r : String;
+
+begin
+  J:=TJSONObject.Create([A,S]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtNumber);
+    Str(S,R);
+    TestJSON(J,'{ "A" : '+R+' }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateInt64;
+
+Const
+  A = 'A';
+  S : Int64 = $FFFFFF;
+
+Var
+  J : TJSONObject;
+  r : String;
+  F : TJSONFloat;
+
+begin
+  J:=TJSONObject.Create([A,S]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtNumber);
+    F:=S;
+    Str(F,R);
+    TestJSON(J,'{ "A" : '+R+' }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateBoolean;
+
+Const
+  A = 'A';
+  S = True;
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,S]);
+  try
+    TestJSONType(J,jtObject);
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtBoolean);
+    TestJSON(J,'{ "A" : True }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateJSONObject;
+
+Const
+  A = 'A';
+  
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,TJSONObject.Create]);
+  try
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtObject);
+    TestJSON(J,'{ "A" : {} }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+procedure TTestObject.TestCreateJSONString;
+
+Const
+  A = 'A';
+  S = 'A string';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=TJSONObject.Create([A,TJSONString.Create(S)]);
+  try
+    TestItemCount(J,1);
+    TestJSONType(J[A],jtString);
+    TestJSON(J,'{ "A" : "'+S+'" }');
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreateObject;
+
+Const
+  A = 'A';
+
+Var
+  J : TJSONObject;
+
+begin
+  J:=Nil;
+  try
+    Try
+      J:=TJSONObject.Create([A,TObject.Create]);
+      Fail('Array constructor accepts only TJSONData');
+    finally
+      FreeAndNil(J);
+    end;
+  except
+    // Should be OK.
+  end;
+end;
+
+procedure TTestObject.TestCreateNilPointer;
+
+Const
+  A = 'A';
+
+Var
+  J : TJSONObject;
+  P : Pointer;
+
+begin
+  J:=Nil;
+  P:=Nil;
+  Try
+    J:=TJSONObject.Create([A,P]);
+    TestJSONType(J[A],jtNull);
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
+procedure TTestObject.TestCreatePointer;
+
+Const
+  A = 'A';
+
+Var
+  J : TJSONObject;
+  P : Pointer;
+
+begin
+  J:=Nil;
+  P:=@Self;
+  try
+    Try
+      J:=TJSONObject.Create([A,P]);
+      Fail('Array constructor accepts only NIL pointers');
+    finally
+      FreeAndNil(J);
+    end;
+  except
+    // Should be OK.
+  end;
+end;
+
+{ TTestJSONString }
+
+procedure TTestJSONString.TestTo(const Src, Dest: String);
+
+Var
+  S : String;
+
+begin
+  S:='StringToJSONString('''+Src+''')='''+Dest+'''';
+  AssertEquals(S,Dest,StringToJSONString(Src));
+end;
+
+procedure TTestJSONString.TestFrom(const Src, Dest: String);
+
+Var
+  S : String;
+
+begin
+  S:='JSONStringToString('''+Src+''')='''+Dest+'''';
+  AssertEquals(S,Dest,JSONStringToString(Src));
+end;
+
+procedure TTestJSONString.TestJSONStringToString;
+begin
+  TestFrom('','');
+  TestFrom('A','A');
+  TestFrom('AB','AB');
+  TestFrom('ABC','ABC');
+  TestFrom('\\','\');
+  TestFrom('\/','/');
+  TestFrom('\"','"');
+  TestFrom('\b',#8);
+  TestFrom('\t',#9);
+  TestFrom('\n',#10);
+  TestFrom('\f',#12);
+  TestFrom('\r',#13);
+  TestFrom('\bBC',#8'BC');
+  TestFrom('\tBC',#9'BC');
+  TestFrom('\nBC',#10'BC');
+  TestFrom('\fBC',#12'BC');
+  TestFrom('\rBC',#13'BC');
+  TestFrom('A\b','A'#8);
+  TestFrom('A\t','A'#9);
+  TestFrom('A\n','A'#10);
+  TestFrom('A\f','A'#12);
+  TestFrom('A\r','A'#13);
+  TestFrom('A\bBC','A'#8'BC');
+  TestFrom('A\tBC','A'#9'BC');
+  TestFrom('A\nBC','A'#10'BC');
+  TestFrom('A\fBC','A'#12'BC');
+  TestFrom('A\rBC','A'#13'BC');
+  TestFrom('\\\\','\\');
+  TestFrom('\/\/','//');
+  TestFrom('\"\"','""');
+  TestFrom('\b\b',#8#8);
+  TestFrom('\t\t',#9#9);
+  TestFrom('\n\n',#10#10);
+  TestFrom('\f\f',#12#12);
+  TestFrom('\r\r',#13#13);
+end;
+
+procedure TTestJSONString.TestStringToJSONString;
+begin
+  TestTo('','');
+  TestTo('A','A');
+  TestTo('AB','AB');
+  TestTo('ABC','ABC');
+  TestTo('\','\\');
+  TestTo('/','\/');
+  TestTo('"','\"');
+  TestTo(#8,'\b');
+  TestTo(#9,'\t');
+  TestTo(#10,'\n');
+  TestTo(#12,'\f');
+  TestTo(#13,'\r');
+  TestTo(#8'BC','\bBC');
+  TestTo(#9'BC','\tBC');
+  TestTo(#10'BC','\nBC');
+  TestTo(#12'BC','\fBC');
+  TestTo(#13'BC','\rBC');
+  TestTo('A'#8,'A\b');
+  TestTo('A'#9,'A\t');
+  TestTo('A'#10,'A\n');
+  TestTo('A'#12,'A\f');
+  TestTo('A'#13,'A\r');
+  TestTo('A'#8'BC','A\bBC');
+  TestTo('A'#9'BC','A\tBC');
+  TestTo('A'#10'BC','A\nBC');
+  TestTo('A'#12'BC','A\fBC');
+  TestTo('A'#13'BC','A\rBC');
+  TestTo('\\','\\\\');
+  TestTo('//','\/\/');
+  TestTo('""','\"\"');
+  TestTo(#8#8,'\b\b');
+  TestTo(#9#9,'\t\t');
+  TestTo(#10#10,'\n\n');
+  TestTo(#12#12,'\f\f');
+  TestTo(#13#13,'\r\r');
+end;
+
+initialization
+  RegisterTest(TTestJSONString);
+  RegisterTest(TTestNull);
+  RegisterTest(TTestBoolean);
+  RegisterTest(TTestInteger);
+  RegisterTest(TTestFloat);
+  RegisterTest(TTestString);
+  RegisterTest(TTestArray);
+  RegisterTest(TTestObject);
+end.
+

+ 364 - 0
packages/fcl-json/tests/testjsonparser.pp

@@ -0,0 +1,364 @@
+unit testjsonparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry,fpjson,
+  jsonParser,testjsondata;
+
+type
+
+  { TTestParser }
+
+  TTestParser= class(TTestJSON)
+  private
+    procedure DoTestError(S: String);
+    procedure DoTestFloat(F: TJSONFloat); overload;
+    procedure DoTestFloat(F: TJSONFloat; S: String); overload;
+    procedure DoTestObject(S: String; const ElNames: array of String);
+    procedure DoTestString(S : String);
+    procedure DoTestArray(S: String; ACount: Integer);
+  published
+    procedure TestEmpty;
+    procedure TestNull;
+    procedure TestTrue;
+    procedure TestFalse;
+    procedure TestFloat;
+    procedure TestInteger;
+    procedure TestString;
+    procedure TestArray;
+    procedure TestObject;
+    procedure TestMixed;
+    procedure TestErrors;
+  end;
+
+implementation
+
+procedure TTestParser.TestEmpty;
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+  
+begin
+  P:=TJSONParser.Create('');
+  Try
+    J:=P.Parse;
+    If (J<>Nil) then
+      Fail('Empty returns Nil');
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestInteger;
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create('1');
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of 1 fails');
+    TestJSONType(J,jtNumber);
+    TestAsInteger(J,1);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestNull;
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create('Null');
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of Null fails');
+    TestJSONType(J,jtNull);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestTrue;
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create('True');
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of True fails');
+    TestJSONType(J,jtBoolean);
+    TestAsBoolean(J,True);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestFalse;
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create('False');
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of False fails');
+    TestJSONType(J,jtBoolean);
+    TestAsBoolean(J,False);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestFloat;
+
+
+begin
+  DoTestFloat(1.2);
+  DoTestFloat(-1.2);
+  DoTestFloat(0);
+  DoTestFloat(1.2e1);
+  DoTestFloat(-1.2e1);
+  DoTestFloat(0);
+  DoTestFloat(1.2,'1.2');
+  DoTestFloat(-1.2,'-1.2');
+  DoTestFloat(0,'0.0');
+end;
+
+procedure TTestParser.TestString;
+
+begin
+  DoTestString('A string');
+  DoTestString('');
+  DoTestString('\"');
+end;
+
+
+procedure TTestParser.TestArray;
+
+Var
+  S1,S2,S3 : String;
+
+
+begin
+  DoTestArray('[]',0);
+  DoTestArray('[Null]',1);
+  DoTestArray('[True]',1);
+  DoTestArray('[False]',1);
+  DoTestArray('[1]',1);
+  DoTestArray('[1, 2]',2);
+  DoTestArray('[1, 2, 3]',3);
+  Str(1.2,S1);
+  Str(2.3,S2);
+  Str(3.4,S3);
+  DoTestArray('['+S1+']',1);
+  DoTestArray('['+S1+', '+S2+']',2);
+  DoTestArray('['+S1+', '+S2+', '+S3+']',3);
+  DoTestArray('["A string"]',1);
+  DoTestArray('["A string", "Another string"]',2);
+  DoTestArray('["A string", "Another string", "Yet another string"]',3);
+  DoTestArray('[Null, False]',2);
+  DoTestArray('[True, False]',2);
+  DoTestArray('[Null, 1]',2);
+  DoTestArray('[1, "A string"]',2);
+  DoTestArray('[1, []]',2);
+  DoTestArray('[1, [1, 2]]',2);
+end;
+
+procedure TTestParser.TestMixed;
+
+begin
+  DoTestArray('[1, {}]',2);
+  DoTestArray('[1, { "a" : 1 }]',2);
+  DoTestArray('[1, { "a" : 1 }, 1]',3);
+  DoTestObject('{ "a" : [1, 2] }',['a']);
+  DoTestObject('{ "a" : [1, 2], "B" : { "c" : "d" } }',['a','B']);
+end;
+
+procedure TTestParser.TestObject;
+begin
+  DoTestObject('{}',[]);
+  DoTestObject('{ "a" : 1 }',['a']);
+  DoTestObject('{ "a" : 1, "B" : "String" }',['a','B']);
+  DoTestObject('{ "a" : 1, "B" : {} }',['a','B']);
+  DoTestObject('{ "a" : 1, "B" : { "c" : "d" } }',['a','B']);
+end;
+
+
+procedure TTestParser.DoTestObject(S : String; Const ElNames : Array of String);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+  O : TJSONObject;
+  I : Integer;
+
+begin
+  P:=TJSONParser.Create(S);
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of object "'+S+'" fails');
+    TestJSONType(J,jtObject);
+    TestItemCount(J,High(ElNames)-Low(ElNames)+1);
+    O:=TJSONObject(J);
+    For I:=Low(ElNames) to High(ElNames) do
+      AssertEquals(Format('Element %d name',[I-Low(Elnames)])
+                   ,ElNames[i], O.Names[I-Low(ElNames)]);
+    TestJSON(J,S);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+
+procedure TTestParser.DoTestArray(S : String; ACount : Integer);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create(S);
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of array "'+S+'" fails');
+    TestJSONType(J,jtArray);
+    TestItemCount(J,ACount);
+    TestJSON(J,S);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+procedure TTestParser.TestErrors;
+
+begin
+  DoTestError('a');
+  DoTestError('"b');
+  DoTestError('1Tru');
+  DoTestError('b"');
+  DoTestError('{"a" : }');
+  DoTestError('{"a" : ""');
+  DoTestError('{"a : ""');
+  DoTestError('[1,]');
+  DoTestError('[,]');
+  DoTestError('[,,]');
+  DoTestError('[1,,]');
+end;
+
+procedure TTestParser.DoTestError(S : String);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+  ParseOK : Boolean;
+  N : String;
+
+begin
+  ParseOK:=False;
+  P:=TJSONParser.Create(S);
+  J:=Nil;
+  Try
+    Try
+      Repeat
+        FreeAndNil(J);
+        J:=P.Parse;
+        ParseOK:=True;
+        If (J<>Nil) then
+          N:=J.ClassName;
+      Until (J=Nil)
+    Finally
+      FreeAndNil(J);
+      FreeAndNil(P);
+    end;
+  except
+    ParseOk:=False;
+  end;
+  If ParseOK then
+    Fail('Parse of JSON string "'+S+'" should fail, but returned '+N);
+end;
+
+procedure TTestParser.DoTestString(S: String);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create('"'+S+'"');
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of string "'+S+'" fails');
+    TestJSONType(J,jtString);
+    TestAsString(J,JSONStringToString(S));
+    TestJSON(J,'"'+S+'"');
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+
+end;
+
+procedure TTestParser.DoTestFloat(F : TJSONFloat);
+
+Var
+  S : String;
+
+begin
+  Str(F,S);
+  DoTestFloat(F,S);
+end;
+
+procedure TTestParser.DoTestFloat(F : TJSONFloat; S : String);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create(S);
+  Try
+    J:=P.Parse;
+    If (J=Nil) then
+      Fail('Parse of float '+S+' fails');
+    TestJSONType(J,jtNumber);
+    TestAsFloat(J,F);
+  Finally
+    FreeAndNil(J);
+    FreeAndNil(P);
+  end;
+end;
+
+
+initialization
+  RegisterTest(TTestParser);
+end.
+