summaryrefslogtreecommitdiff
path: root/packages/fcl-json
diff options
context:
space:
mode:
authormichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-09-17 19:01:12 +0000
committermichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-09-17 19:01:12 +0000
commit26f39c550e9ec0b493a301d31300190c936d9c58 (patch)
treeab75aca7138d518ab1eb6dd13ac40536abcaf8a4 /packages/fcl-json
parent0fa233aa4f011488751ab4e23a6e70025faad1c2 (diff)
downloadfpc-26f39c550e9ec0b493a301d31300190c936d9c58.tar.gz
* Initial implementation
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@8522 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-json')
-rw-r--r--packages/fcl-json/Makefile2783
-rw-r--r--packages/fcl-json/Makefile.fpc29
-rw-r--r--packages/fcl-json/src/fpjson.pp1448
-rw-r--r--packages/fcl-json/src/jsonparser.pp237
-rw-r--r--packages/fcl-json/src/jsonscanner.pp355
-rw-r--r--packages/fcl-json/tests/testjson.lpi65
-rw-r--r--packages/fcl-json/tests/testjson.pp21
-rw-r--r--packages/fcl-json/tests/testjsondata.pp1786
-rw-r--r--packages/fcl-json/tests/testjsonparser.pp364
9 files changed, 7088 insertions, 0 deletions
diff --git a/packages/fcl-json/Makefile b/packages/fcl-json/Makefile
new file mode 100644
index 0000000000..3723584b1c
--- /dev/null
+++ b/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)
diff --git a/packages/fcl-json/Makefile.fpc b/packages/fcl-json/Makefile.fpc
new file mode 100644
index 0000000000..68de666016
--- /dev/null
+++ b/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)
diff --git a/packages/fcl-json/src/fpjson.pp b/packages/fcl-json/src/fpjson.pp
new file mode 100644
index 0000000000..45ff2c78a3
--- /dev/null
+++ b/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.
+
diff --git a/packages/fcl-json/src/jsonparser.pp b/packages/fcl-json/src/jsonparser.pp
new file mode 100644
index 0000000000..33bdac5dc1
--- /dev/null
+++ b/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.
+
diff --git a/packages/fcl-json/src/jsonscanner.pp b/packages/fcl-json/src/jsonscanner.pp
new file mode 100644
index 0000000000..52686fb7a6
--- /dev/null
+++ b/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 michael@freepascal.org
+
+ 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.
diff --git a/packages/fcl-json/tests/testjson.lpi b/packages/fcl-json/tests/testjson.lpi
new file mode 100644
index 0000000000..38247f31d1
--- /dev/null
+++ b/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>
diff --git a/packages/fcl-json/tests/testjson.pp b/packages/fcl-json/tests/testjson.pp
new file mode 100644
index 0000000000..aa49a5c770
--- /dev/null
+++ b/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.
diff --git a/packages/fcl-json/tests/testjsondata.pp b/packages/fcl-json/tests/testjsondata.pp
new file mode 100644
index 0000000000..be87d1cdef
--- /dev/null
+++ b/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.
+
diff --git a/packages/fcl-json/tests/testjsonparser.pp b/packages/fcl-json/tests/testjsonparser.pp
new file mode 100644
index 0000000000..070bc2e73f
--- /dev/null
+++ b/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.
+