ソースを参照

Merged revisions 8522-8525,8527-8528,8535-8546,8554,8556,8560,8573,8575-8576,8581-8587,8590,8593-8594,8596,8598 via svnmerge from
http://svn.freepascal.org/svn/fpc/trunk

........
r8522 | michael | 2007-09-17 21:01:12 +0200 (Mon, 17 Sep 2007) | 1 line

* Initial implementation
........
r8523 | michael | 2007-09-17 21:09:57 +0200 (Mon, 17 Sep 2007) | 1 line

* Added fcl-json
........
r8524 | michael | 2007-09-17 21:22:53 +0200 (Mon, 17 Sep 2007) | 1 line

* Added copyright notice
........
r8525 | michael | 2007-09-17 21:37:48 +0200 (Mon, 17 Sep 2007) | 1 line

* Fixed lazarus dependencies, and added extensive object test
........
r8527 | jonas | 2007-09-17 22:04:24 +0200 (Mon, 17 Sep 2007) | 2 lines

+ added dependencies for fcl-json
........
r8528 | jonas | 2007-09-17 22:11:41 +0200 (Mon, 17 Sep 2007) | 2 lines

* also added fcl-json to plain fcl target
........
r8538 | michael | 2007-09-18 09:01:51 +0200 (Tue, 18 Sep 2007) | 1 line

* Implemented simple demo demonstrating all capacities
........
r8556 | michael | 2007-09-18 22:07:13 +0200 (Tue, 18 Sep 2007) | 3 lines

* Added parser demo
* Removed debug statements from parser code
........
r8573 | michael | 2007-09-20 21:46:39 +0200 (Thu, 20 Sep 2007) | 1 line

* Added jsonconf
........
r8598 | michael | 2007-09-21 22:46:24 +0200 (Fri, 21 Sep 2007) | 1 line

* Demo for TJONConfig committed, copyright notice added
........

git-svn-id: branches/fixes_2_2@8713 -

peter 18 年 前
コミット
798e1461d2

+ 19 - 0
.gitattributes

@@ -4282,6 +4282,25 @@ packages/fcl-image/src/pixtools.pp svneol=native#text/plain
 packages/fcl-image/src/pngcomn.pp svneol=native#text/plain
 packages/fcl-image/src/pscanvas.pp svneol=native#text/plain
 packages/fcl-image/src/targacmn.pp svneol=native#text/plain
+packages/fcl-json/Makefile svneol=native#text/plain
+packages/fcl-json/Makefile.fpc svneol=native#text/plain
+packages/fcl-json/demo/confdemo.lpi svneol=native#text/plain
+packages/fcl-json/demo/confdemo.pp svneol=native#text/plain
+packages/fcl-json/demo/parsedemo.lpi svneol=native#text/plain
+packages/fcl-json/demo/parsedemo.pp svneol=native#text/plain
+packages/fcl-json/demo/simpledemo.lpi svneol=native#text/plain
+packages/fcl-json/demo/simpledemo.pp svneol=native#text/plain
+packages/fcl-json/src/fpjson.pp svneol=native#text/plain
+packages/fcl-json/src/jsonconf.pp svneol=native#text/plain
+packages/fcl-json/src/jsonparser.pp svneol=native#text/plain
+packages/fcl-json/src/jsonscanner.pp svneol=native#text/plain
+packages/fcl-json/tests/jsonconftest.pp svneol=native#text/plain
+packages/fcl-json/tests/testjson.lpi svneol=native#text/plain
+packages/fcl-json/tests/testjson.pp svneol=native#text/plain
+packages/fcl-json/tests/testjsonconf.lpi svneol=native#text/plain
+packages/fcl-json/tests/testjsonconf.pp svneol=native#text/plain
+packages/fcl-json/tests/testjsondata.pp svneol=native#text/plain
+packages/fcl-json/tests/testjsonparser.pp svneol=native#text/plain
 packages/fcl-net/Makefile svneol=native#text/plain
 packages/fcl-net/Makefile.fpc svneol=native#text/plain
 packages/fcl-net/src/fpmake.inc svneol=native#text/plain

+ 160 - 58
packages/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2007/07/29]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2007/08/22]
 #
 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
@@ -231,160 +231,160 @@ UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
 endif
 PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra  fcl-web
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra  fcl-web
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+override TARGET_DIRS+=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 endif
 override INSTALL_FPCPACKAGE=y
 override INSTALL_FPCSUBDIR=packages
@@ -1472,6 +1472,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1486,6 +1487,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-win32)
@@ -1499,6 +1501,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1513,6 +1516,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
@@ -1526,6 +1530,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1540,6 +1545,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
@@ -1553,6 +1559,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1567,6 +1574,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1581,6 +1589,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-netware)
@@ -1594,6 +1603,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
@@ -1607,6 +1617,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1621,6 +1632,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
@@ -1634,6 +1646,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1648,6 +1661,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
@@ -1661,6 +1675,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
@@ -1674,6 +1689,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-wince)
@@ -1687,6 +1703,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1701,6 +1718,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
@@ -1714,6 +1732,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
@@ -1727,6 +1746,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1741,6 +1761,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1755,6 +1776,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1769,6 +1791,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
@@ -1782,6 +1805,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
@@ -1795,6 +1819,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1809,6 +1834,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
@@ -1822,6 +1848,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
@@ -1835,6 +1862,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1849,6 +1877,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1863,6 +1892,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
@@ -1876,6 +1906,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
@@ -1889,6 +1920,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1903,6 +1935,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
@@ -1916,6 +1949,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
@@ -1929,6 +1963,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1943,6 +1978,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1957,6 +1993,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1971,6 +2008,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
@@ -1984,6 +2022,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -1998,6 +2037,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2012,6 +2052,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2026,6 +2067,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),arm-linux)
@@ -2039,6 +2081,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2053,6 +2096,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),arm-wince)
@@ -2066,6 +2110,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2080,6 +2125,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),arm-nds)
@@ -2093,6 +2139,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
@@ -2106,6 +2153,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
@@ -2119,6 +2167,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
@@ -2132,6 +2181,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2146,6 +2196,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 TARGET_DIRS_FCL-WEB=1
 endif
@@ -2160,6 +2211,7 @@ TARGET_DIRS_FCL-PASSRC=1
 TARGET_DIRS_FCL-REGISTRY=1
 TARGET_DIRS_FCL-XML=1
 TARGET_DIRS_FCL-FPCUNIT=1
+TARGET_DIRS_FCL-JSON=1
 TARGET_DIRS_EXTRA=1
 endif
 ifdef TARGET_DIRS_BASE
@@ -2612,6 +2664,51 @@ fcl-fpcunit:
 	$(MAKE) -C fcl-fpcunit all
 .PHONY: fcl-fpcunit_all fcl-fpcunit_debug fcl-fpcunit_smart fcl-fpcunit_release fcl-fpcunit_units fcl-fpcunit_examples fcl-fpcunit_shared fcl-fpcunit_install fcl-fpcunit_sourceinstall fcl-fpcunit_exampleinstall fcl-fpcunit_distinstall fcl-fpcunit_zipinstall fcl-fpcunit_zipsourceinstall fcl-fpcunit_zipexampleinstall fcl-fpcunit_zipdistinstall fcl-fpcunit_clean fcl-fpcunit_distclean fcl-fpcunit_cleanall fcl-fpcunit_info fcl-fpcunit_makefiles fcl-fpcunit
 endif
+ifdef TARGET_DIRS_FCL-JSON
+fcl-json_all:
+	$(MAKE) -C fcl-json all
+fcl-json_debug:
+	$(MAKE) -C fcl-json debug
+fcl-json_smart:
+	$(MAKE) -C fcl-json smart
+fcl-json_release:
+	$(MAKE) -C fcl-json release
+fcl-json_units:
+	$(MAKE) -C fcl-json units
+fcl-json_examples:
+	$(MAKE) -C fcl-json examples
+fcl-json_shared:
+	$(MAKE) -C fcl-json shared
+fcl-json_install:
+	$(MAKE) -C fcl-json install
+fcl-json_sourceinstall:
+	$(MAKE) -C fcl-json sourceinstall
+fcl-json_exampleinstall:
+	$(MAKE) -C fcl-json exampleinstall
+fcl-json_distinstall:
+	$(MAKE) -C fcl-json distinstall
+fcl-json_zipinstall:
+	$(MAKE) -C fcl-json zipinstall
+fcl-json_zipsourceinstall:
+	$(MAKE) -C fcl-json zipsourceinstall
+fcl-json_zipexampleinstall:
+	$(MAKE) -C fcl-json zipexampleinstall
+fcl-json_zipdistinstall:
+	$(MAKE) -C fcl-json zipdistinstall
+fcl-json_clean:
+	$(MAKE) -C fcl-json clean
+fcl-json_distclean:
+	$(MAKE) -C fcl-json distclean
+fcl-json_cleanall:
+	$(MAKE) -C fcl-json cleanall
+fcl-json_info:
+	$(MAKE) -C fcl-json info
+fcl-json_makefiles:
+	$(MAKE) -C fcl-json makefiles
+fcl-json:
+	$(MAKE) -C fcl-json all
+.PHONY: fcl-json_all fcl-json_debug fcl-json_smart fcl-json_release fcl-json_units fcl-json_examples fcl-json_shared fcl-json_install fcl-json_sourceinstall fcl-json_exampleinstall fcl-json_distinstall fcl-json_zipinstall fcl-json_zipsourceinstall fcl-json_zipexampleinstall fcl-json_zipdistinstall fcl-json_clean fcl-json_distclean fcl-json_cleanall fcl-json_info fcl-json_makefiles fcl-json
+endif
 ifdef TARGET_DIRS_EXTRA
 extra_all:
 	$(MAKE) -C extra all
@@ -2746,6 +2843,11 @@ fcl-xml_debug: fcl-base_debug
 fcl-xml_smart: fcl-base_smart
 fcl-xml_release: fcl-base_release
 fcl-xml_shared: fcl-base_shared
+fcl-json_all: fcl-base_all
+fcl-json_debug: fcl-base_debug
+fcl-json_smart: fcl-base_smart
+fcl-json_release: fcl-base_release
+fcl-json_shared: fcl-base_shared
 fcl-image_all: fcl-base_all
 fcl-image_debug: fcl-base_debug
 fcl-image_smart: fcl-base_smart
@@ -2776,8 +2878,8 @@ fcl-db_debug: fcl-base_debug
 fcl-db_smart: fcl-base_smart
 fcl-db_release: fcl-base_release
 fcl-db_shared: fcl-base_shared
-fcl_all: fcl-base_all fcl-xml_all fcl-fpcunit_all fcl-db_all fcl-web_all fcl-registry_all fcl-passrc_all fcl-image_all fcl-net_all
-fcl_debug: fcl-base_debug fcl-xml_debug fcl-fpcunit_debug fcl-db_debug fcl-web_debug fcl-registry_debug fcl-passrc_debug fcl-image_debug fcl-net_debug
-fcl_smart: fcl-base_smart fcl-xml_smart fcl-fpcunit_smart fcl-db_smart fcl-web_smart fcl-registry_smart fcl-passrc_smart fcl-image_smart fcl-net_smart
-fcl_release: fcl-base_release fcl-xml_release fcl-fpcunit_release fcl-db_release fcl-web_release fcl-registry_release fcl-passrc_release fcl-image_release fcl-net_release
-fcl_shared: fcl-base_shared fcl-xml_shared fcl-fpcunit_shared fcl-db_shared fcl-web_shared fcl-registry_shared fcl-passrc_shared fcl-image_shared fcl-net_shared
+fcl_all: fcl-base_all fcl-xml_all fcl-fpcunit_all fcl-db_all fcl-web_all fcl-registry_all fcl-passrc_all fcl-image_all fcl-net_all fcl-json_all
+fcl_debug: fcl-base_debug fcl-xml_debug fcl-fpcunit_debug fcl-db_debug fcl-web_debug fcl-registry_debug fcl-passrc_debug fcl-image_debug fcl-net_debug fcl-json_debug
+fcl_smart: fcl-base_smart fcl-xml_smart fcl-fpcunit_smart fcl-db_smart fcl-web_smart fcl-registry_smart fcl-passrc_smart fcl-image_smart fcl-net_smart fcl-json_smart
+fcl_release: fcl-base_release fcl-xml_release fcl-fpcunit_release fcl-db_release fcl-web_release fcl-registry_release fcl-passrc_release fcl-image_release fcl-net_release fcl-json_release
+fcl_shared: fcl-base_shared fcl-xml_shared fcl-fpcunit_shared fcl-db_shared fcl-web_shared fcl-registry_shared fcl-passrc_shared fcl-image_shared fcl-net_shared fcl-json_shared

+ 12 - 6
packages/Makefile.fpc

@@ -3,7 +3,7 @@
 #
 
 [target]
-dirs=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit extra
+dirs=base fpmkunit fcl-base fcl-db fcl-image fcl-net fcl-passrc fcl-registry fcl-xml fcl-fpcunit fcl-json extra
 dirs_freebsd=fcl-web
 dirs_darwin=fcl-web
 dirs_solaris=fcl-web
@@ -46,6 +46,12 @@ fcl-xml_smart: fcl-base_smart
 fcl-xml_release: fcl-base_release
 fcl-xml_shared: fcl-base_shared
 
+fcl-json_all: fcl-base_all
+fcl-json_debug: fcl-base_debug
+fcl-json_smart: fcl-base_smart
+fcl-json_release: fcl-base_release
+fcl-json_shared: fcl-base_shared
+
 fcl-image_all: fcl-base_all
 fcl-image_debug: fcl-base_debug
 fcl-image_smart: fcl-base_smart
@@ -82,9 +88,9 @@ fcl-db_smart: fcl-base_smart
 fcl-db_release: fcl-base_release
 fcl-db_shared: fcl-base_shared
 
-fcl_all: fcl-base_all fcl-xml_all fcl-fpcunit_all fcl-db_all fcl-web_all fcl-registry_all fcl-passrc_all fcl-image_all fcl-net_all
-fcl_debug: fcl-base_debug fcl-xml_debug fcl-fpcunit_debug fcl-db_debug fcl-web_debug fcl-registry_debug fcl-passrc_debug fcl-image_debug fcl-net_debug
-fcl_smart: fcl-base_smart fcl-xml_smart fcl-fpcunit_smart fcl-db_smart fcl-web_smart fcl-registry_smart fcl-passrc_smart fcl-image_smart fcl-net_smart
-fcl_release: fcl-base_release fcl-xml_release fcl-fpcunit_release fcl-db_release fcl-web_release fcl-registry_release fcl-passrc_release fcl-image_release fcl-net_release
-fcl_shared: fcl-base_shared fcl-xml_shared fcl-fpcunit_shared fcl-db_shared fcl-web_shared fcl-registry_shared fcl-passrc_shared fcl-image_shared fcl-net_shared
+fcl_all: fcl-base_all fcl-xml_all fcl-fpcunit_all fcl-db_all fcl-web_all fcl-registry_all fcl-passrc_all fcl-image_all fcl-net_all fcl-json_all
+fcl_debug: fcl-base_debug fcl-xml_debug fcl-fpcunit_debug fcl-db_debug fcl-web_debug fcl-registry_debug fcl-passrc_debug fcl-image_debug fcl-net_debug fcl-json_debug
+fcl_smart: fcl-base_smart fcl-xml_smart fcl-fpcunit_smart fcl-db_smart fcl-web_smart fcl-registry_smart fcl-passrc_smart fcl-image_smart fcl-net_smart fcl-json_smart
+fcl_release: fcl-base_release fcl-xml_release fcl-fpcunit_release fcl-db_release fcl-web_release fcl-registry_release fcl-passrc_release fcl-image_release fcl-net_release fcl-json_release
+fcl_shared: fcl-base_shared fcl-xml_shared fcl-fpcunit_shared fcl-db_shared fcl-web_shared fcl-registry_shared fcl-passrc_shared fcl-image_shared fcl-net_shared fcl-json_shared
 

+ 2784 - 0
packages/fcl-json/Makefile

@@ -0,0 +1,2784 @@
+#
+# 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 jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_UNITS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_RSTS+=fpjson jsonscanner jsonparser jsonconf
+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)
+jsonconf$(PPUEXT): jsonparser$(PPUEXT) fpjson$(PPUEXT)

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

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

+ 46 - 0
packages/fcl-json/demo/confdemo.lpi

@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <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>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="confdemo.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="confdemo"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src/"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 101 - 0
packages/fcl-json/demo/confdemo.pp

@@ -0,0 +1,101 @@
+{
+    This file is part of the Free Component Library
+
+    JSON Config file demo
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program confdemo;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes,
+  { add your units here }
+  jsonconf;
+
+Procedure TestConf;
+
+Var
+  C : TJSONConfig;
+  L : TStrings;
+  I : Integer;
+  
+begin
+  // TJSONConf is component, so needs an owner.
+  C:=TJSONConfig.Create(nil);
+  Try
+    // Set filename. This will read the file.
+    C.FileName:='sample.conf';
+    // Set an integer value "a" equal to 1 in the root object
+    C.SetValue('/a',1);
+    // Set a integer value "a" equal to 2 in the object "b" below root.
+    C.SetValue('b/a',2);
+    // Set a string value "b" equal to 1 in the object "b" below root.
+    C.SetValue('b/b','Some String');
+    // Set a float value "c" equal to 1.23 in the object "b" below root.
+    C.SetValue('b/c',1.23);
+    // Set a boolean value "d" equal to "False" in the object "b" below root.
+    C.SetValue('b/d',False);
+    // Read values:
+    // Integer. If none found, 0 is returned)
+    Writeln('/a :',C.GetValue('/a',0));
+    // String. If none found, a default 'XYZ' is returned)
+    Writeln('/b/b :',C.GetValue('/b/b','XYZ'));
+    // Float. If none found, 0 is returned)
+    Writeln('/b/c :',C.GetValue('/b/c',0));
+    // Boolean. If none found, true is returned)
+    Writeln('/b/d :',C.GetValue('/b/d',true));
+    // You can open a key. All paths are then relative to the open key.
+    // The default open key is the root key.
+    // The second element determines if the key should b created if it does not exist.
+    C.OpenKey('/b',False);
+    // Read relative to b
+    Writeln('a, relative to key (/b):',C.GetValue('a',0));
+    // Absolute paths disregard the open key
+    Writeln('/a, absolute:',C.GetValue('/a',0));
+    // Reset or closekey reset the open key to the root key.
+    C.OpenKey('/b/c/d/e',True);
+    C.SetValue('q','Q is good for you');
+    // Opening keys also works relative:
+    C.OpenKey('/b',False);
+    Writeln('a, in b : ',C.GetValue('a',0));
+    C.OpenKey('c/d/e',False);
+    Writeln('q, in /b, then c/d/e : ',C.GetValue('q',''));
+    C.ResetKey;
+    C.OpenKey('/b2',True);
+    C.OpenKey('/b3',True);
+    L:=TStringList.Create;
+    try
+      // You can enumerate keys below a certain key:
+      C.EnumSubKeys('/',L);
+      Writeln('Found ',L.Count,' keys below root key: ');
+      For I:=0 to L.Count-1 do
+        Writeln(i+1,': ',L[I]);
+      // You can also enumerate the values below a certain key:
+      L.Clear;
+      C.EnumValues('/b',L);
+      Writeln('Found ',L.Count,' values below "/b" key: ');
+      For I:=0 to L.Count-1 do
+        Writeln(i+1,': ',L[I]);
+    finally
+      L.Free;
+    end;
+    // Write all in-memory changes to disk
+    C.Flush;
+  Finally
+    C.Free;
+  end;
+end;
+
+begin
+  TestConf;
+end.
+

+ 46 - 0
packages/fcl-json/demo/parsedemo.lpi

@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <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>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="parsedemo.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="parsedemo"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src/"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 137 - 0
packages/fcl-json/demo/parsedemo.pp

@@ -0,0 +1,137 @@
+{
+    This file is part of the Free Component Library
+
+    JSON Parser demo
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program parsedemo;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, SysUtils, fpjson,jsonparser;
+
+Procedure DoParse(P : TJSONParser);
+
+Var
+  J : TJSONData;
+  
+begin
+  Try
+    J:=P.Parse;
+    Try
+      Writeln('Parse succesful. Dumping JSON data : ');
+      If Assigned(J) then
+        begin
+        Writeln('Returned JSON structure has class : ',J.ClassName);
+        Writeln(J.AsJSON)
+        end
+      else
+        Writeln('No JSON data available');
+    Finally
+      FreeAndNil(J);
+    end;
+  except
+    On E : Exception do
+      Writeln('An Exception occurred when parsing : ',E.Message);
+  end;
+end;
+
+
+Procedure ParseFile (FileName : String);
+
+Var
+  F : TFileStream;
+  P : TJSONParser;
+
+begin
+  F:=TFileStream.Create(FileName,fmopenRead);
+  try
+    // Create parser with Stream as source.
+    P:=TJSONParser.Create(F);
+    try
+      DoParse(P);
+    finally
+      FreeAndNil(P);
+    end;
+  finally
+    F.Destroy;
+  end;
+end;
+
+Procedure ParseString(S : String);
+
+Var
+  P : TJSONParser;
+begin
+  // Create parser with Stream as source.
+  P:=TJSONParser.Create(S);
+  try
+    DoParse(P);
+  finally
+    FreeAndNil(P);
+  end;
+end;
+
+Procedure DefaultParsing;
+
+Const
+  // From JSON website
+ SAddr ='{ "addressbook": { "name": "Mary Lebow", '+
+         '  "address": {'+
+         '      "street": "5 Main Street",'+LineEnding+
+         '        "city": "San Diego, CA",'+LineEnding+
+         '        "zip": 91912,'+LineEnding+
+         '    },'+LineEnding+
+         '    "phoneNumbers": [  '+LineEnding+
+         '        "619 332-3452",'+LineEnding+
+         '        "664 223-4667"'+LineEnding+
+         '    ]'+LineEnding+
+         ' }'+LineEnding+
+         '}';
+
+
+begin
+  ParseString('');
+  ParseString('NULL');
+  ParseString('1');
+  ParseString('2.3');
+  ParseString('True');
+  ParseString('False');
+  ParseString('"A string"');
+  ParseString('[ Null, False, 1 , 2.3,  "a" , { "b" : 1 }]');
+  ParseString('{ "a" : 1, "b" : "Something" }');
+  ParseString(SAddr);
+end;
+
+Procedure Usage;
+
+begin
+  Writeln('Usage : parsedemo arg1 [arg2 [arg3 ...[argN]]]');
+  Writeln('  ArgN can be the name of an existing file, or a JSON string');
+end;
+
+Var
+  I : Integer;
+  
+begin
+  If (ParamCount=0) then
+    DefaultParsing
+  else if (ParamCount=1) and ((Paramstr(1)='-h') or (ParamStr(1)='--help')) then
+    Usage
+  else
+    For I:=1 to ParamCount do
+      If FileExists(Paramstr(i)) then
+        ParseFile(ParamStr(I))
+      else
+        ParseString(Paramstr(I));
+end.
+

+ 46 - 0
packages/fcl-json/demo/simpledemo.lpi

@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <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>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="simpledemo.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="simpledemo"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src/"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 331 - 0
packages/fcl-json/demo/simpledemo.pp

@@ -0,0 +1,331 @@
+{
+    This file is part of the Free Component Library
+
+    JSON Data structures demo
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program simpledemo;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, SysUtils, fpjson;
+
+Procedure DumpJSONData(J : TJSonData; DOEOLN : Boolean = True);
+
+Var
+  I : Integer;
+
+begin
+  // JSONType property determines kind of value.
+  Case J.jsontype of
+    jtNull   : Write('Null');
+    jtBoolean : If J.AsBoolean then
+                  Write('True')
+                else
+                  Write('False');
+    jtNumber : {JSONNumber has extra NumberType property
+                which determines kind of value (int/float).}
+               Case TJSONNumber(J).NumberType of
+                 ntInteger : Write(J.AsInteger);
+                 ntFloat   : Write(J.AsFloat:10:2);
+               end;
+    jtString : Write('"',J.AsString,'"');
+    jtArray  : begin
+               Write('[ ');
+               For I:=0 to J.Count-1 do
+                 begin
+                 DumpJSONData(J.Items[I],False);
+                 If I<J.Count-1 then
+                   Write(', ');
+                 end;
+               Write(' ]');
+               end;
+    jtObject : begin
+               Write('{ ');
+               For I:=0 to J.Count-1 do
+                 begin
+                 Writeln('"',TJSONObject(J).Names[i],'" : ');
+                 DumpJSONData(J.Items[I],False);
+                 If I<J.Count-1 then
+                   Write(',')
+                 end;
+               Write('}');
+               end;
+   end;
+   If DOEOLN then
+     Writeln;
+end;
+
+
+Procedure EndTest(Msg : String;J : TJSOnData);
+
+begin
+  Write(Msg, ' : ');
+  DumpJSONData(J);
+  FreeAndNil(J);
+end;
+
+Procedure DoTestCreate;
+
+
+begin
+  Writeln('Constructor tests');
+  EndTest('Null value',TJSOnNull.Create);
+  EndTest('Boolean true',TJSONBoolean.Create(True));
+  EndTest('Boolean false',TJSONBoolean.Create(False));
+  EndTest('Integer value',TJSONIntegerNumber.Create(100));
+  EndTest('Float value',TJSONFloatNumber.Create(1.2e3));
+  EndTest('String value',TJSONString.Create('Some weird JSON string'));
+  EndTest('Empty Array value',TJSONArray.Create);
+  EndTest('Array value from array of const',TJSONArray.Create([1,'a',2,'b']));
+  EndTest('Empty Object value',TJSONObject.Create);
+  // Name, Value, name, value
+  EndTest('Object from array of const',TJSONArray.Create(['a',1,'b',True,'C',Nil]));
+
+end;
+
+Procedure DoTestAs;
+
+Var
+  J : TJsonData;
+
+begin
+  Writeln('AsNNN value accessing tests, number with value 123:');
+  J:=TJSonIntegerNumber.Create(123);
+  Writeln('IsNull    : ',J.IsNull);
+  Writeln('AsInteger : ',J.AsInteger);
+  Writeln('AsBoolean : ',J.AsBoolean);
+  Writeln('AsString  : ',J.AsString);
+  Writeln('AsFloat   : ',J.AsFloat:5:3);
+  FreeAndNil(J);
+  Writeln('Test IsNull');
+  J:=TJSonNull.Create;
+  Writeln('Test for null with IsNull');
+  Writeln('IsNull : ',J.ISNull);
+  Writeln('Test number of children :');
+  Writeln('Count (0) : ',J.Count);
+  FreeAndNil(J);
+  J:=TJSONArray.Create(['a','b','c']);
+  Writeln('Count (3): ',J.Count);
+  FreeAndNil(J);
+  J:=TJSONObject.Create(['a',1,'b',2]);
+  Writeln('Count (2): ',J.Count);
+  FreeAndNil(J);
+end;
+
+Procedure DoTestArray;
+
+Var
+  J : TJSOnArray;
+  I : Integer;
+
+begin
+  Writeln('JSON array with elements 0,1,2,3');
+  J:=TJSONArray.Create([0,1,2,3]);
+  Write('Access through Elements[] (default) array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J[I].AsString);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Nulls[] array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J.Nulls[I]);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Booleans[] array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J.Booleans[I]);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Integers[] array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J.Integers[I]);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Floats[] array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J.Floats[I]:5:2);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Strings[] array property : ');
+  For I:=0 to J.Count-1 do
+    begin
+    Write(J.Strings[I]);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create with 3 empty TJSONObjects in array constructor');
+  Write('Access through Objects[] array property : ');
+  J:=TJSONArray.Create([TJSOnObject.Create,TJSOnObject.Create,TJSOnObject.Create]);
+  For I:=0 to J.Count-1 do
+    begin
+    DumpJSONData(J.Objects[I],False);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create with 3 empty TJSONArrays in array constructor');
+  Write('Access through Arrays[] array property : ');
+  J:=TJSONArray.Create([TJSOnArray.Create,TJSOnArray.Create,TJSOnArray.Create]);
+  For I:=0 to J.Count-1 do
+    begin
+    DumpJSONData(J.Arrays[I],False);
+    If I<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create empty array. Add elements with overloaded Add() method');
+  J:=TJSONArray.Create;
+  J.Add; // Null
+  J.Add(True);
+  J.Add(False);
+  J.Add(123);
+  J.Add(2.34);
+  J.Add('A string');
+  J.Add(TJSOnArray.Create);
+  J.Add(TJSOnObject.Create);
+  DumpJSONData(J);
+  FreeAndNil(J);
+end;
+
+Procedure DoTestObject;
+
+Var
+  J : TJSONObject;
+  I : Char;
+  k : Integer;
+  
+begin
+  Writeln('JSON object with elements a=0,b=1,c=2,d=3');
+  J:=TJSONObject.Create(['a',0,'b',1,'c',2,'d',3]);
+  Write('Get element names with Names[] array property : ');
+  For K:=1 to J.Count-1 do
+    begin
+    Write(J.Names[k]);
+    If K<J.Count-1 then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Elements[] (default) array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J[I].AsString);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Nulls[] array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J.Nulls[I]);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Booleans[] array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J.Booleans[I]);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Integers[] array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J.Integers[I]);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Floats[] array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J.Floats[I]:5:2);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  Write('Access through Strings[] array property : ');
+  For I:='a' to 'd' do
+    begin
+    Write(i,' : ',J.Strings[I]);
+    If I<'d' then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create with 3 empty TJSONObjects in array constructor');
+  Write('Access through Objects[] array property : ');
+  J:=TJSONObject.Create(['a',TJSOnObject.Create,'b',TJSOnObject.Create,'c',TJSOnObject.Create]);
+  For I:='a' to 'c' do
+    begin
+    Write(i,' : ');
+    DumpJSONData(J.Objects[i],False);
+    If I<'c' then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create with 3 empty TJSONArrays in array constructor');
+  Write('Access through Arrays[] array property : ');
+  J:=TJSONObject.Create(['a',TJSONArray.Create,'b',TJSONArray.Create,'c',TJSONArray.Create]);
+  For I:='a' to 'c' do
+    begin
+    Write(i,' : ');
+    DumpJSONData(J.Arrays[I],False);
+    If I<'c' then
+      Write(', ');
+    end;
+  Writeln;
+  FreeAndNil(J);
+  Writeln('Create empty object. Add elements with overloaded Add() method');
+  J:=TJSONObject.Create;
+  J.Add('a'); // Null
+  J.Add('b',True);
+  J.Add('c',False);
+  J.Add('d',123);
+  J.Add('e',2.34);
+  J.Add('f','A string');
+  J.Add('g',TJSONArray.Create);
+  J.Add('h',TJSOnObject.Create);
+  DumpJSONData(J);
+  FreeAndNil(J);
+end;
+
+
+begin
+  DoTestCreate;
+  DoTestAs;
+  DoTestArray;
+  DoTestObject;
+end.
+

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

@@ -0,0 +1,1512 @@
+{
+    This file is part of the Free Component Library
+
+    JSON Data structures
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit 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
+    Constructor Create; virtual;
+    Class function JSONType: TJSONType; virtual;
+    Procedure Clear;  virtual; Abstract;
+    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;
+
+  TJSONDataClass = Class of TJSONData;
+  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;
+    Procedure Clear;  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;
+    Procedure Clear;  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;
+    Procedure Clear;  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;
+    Procedure Clear;  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;
+    Procedure Clear;  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
+    Procedure Clear;  override;
+    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
+    Procedure Clear;  override;
+    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;
+
+constructor TJSONData.Create;
+begin
+  Clear;
+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;
+
+procedure TJSONString.Clear;
+begin
+  FValue:='';
+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.Clear;
+begin
+  FValue:=False;
+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;
+
+procedure TJSONNull.Clear;
+begin
+  // Do nothing
+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;
+
+procedure TJSONFloatNumber.Clear;
+begin
+  FValue:=0;
+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;
+
+procedure TJSONIntegerNumber.Clear;
+begin
+  FValue:=0;
+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;
+
+procedure TJSONArray.Clear;
+begin
+  FList.Clear;
+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
+  Result:=FHash.IndexOf(Item);
+end;
+
+function TJSONObject.IndexOfName(const AName: TJSONStringType): Integer;
+begin
+  Result:=FHash.FindIndexOf(AName);
+end;
+
+procedure TJSONObject.Clear;
+begin
+  FHash.Clear;
+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.
+

+ 625 - 0
packages/fcl-json/src/jsonconf.pp

@@ -0,0 +1,625 @@
+{
+    This file is part of the Free Component Library
+
+    Implementation of TJSONConfig class
+    Copyright (c) 2007 Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{
+  TJSONConfig enables applications to use JSON files for storing their
+  configuration data
+}
+
+{$IFDEF FPC}
+{$MODE objfpc}
+{$H+}
+{$ENDIF}
+
+unit jsonConf;
+
+interface
+
+uses
+  SysUtils, Classes, fpjson, jsonparser;
+
+resourcestring
+  SWrongRootName = 'XML file has wrong root element name';
+
+type
+  EJSONConfigError = class(Exception);
+  TPathFlags = set of (pfHasValue, pfWriteAccess);
+
+(* ********************************************************************
+   "APath" is the path and name of a value: A JSON configuration file 
+   is hierachical. "/" is the path delimiter, the part after the last 
+   "/" is the name of the value. The path components will be mapped 
+   to nested JSON objects, with the name equal to the part. In practice 
+   this means that "/my/path/value" will be written as:
+   { 
+     "my" : {
+       "path" : {
+         "value" : Value
+       }
+     }
+   }
+   ******************************************************************** *)
+
+  { TJSONConfig }
+
+  TJSONConfig = class(TComponent)
+  private
+    FFilename: String;
+    FKey: TJSONObject;
+    procedure DoSetFilename(const AFilename: String; ForceReload: Boolean);
+    procedure SetFilename(const AFilename: String);
+    Function StripSlash(P : WideString) : WideString;
+  protected
+    FJSON: TJSONObject;
+    FModified: Boolean;
+    procedure Loaded; override;
+    function FindPath(Const APath: WideString; AllowCreate : Boolean) : TJSONObject;
+    function FindObject(Const APath: WideString; AllowCreate : Boolean) : TJSONObject;
+    function FindObject(Const APath: WideString; AllowCreate : Boolean;Var ElName : WideString) : TJSONObject;
+    function FindElement(Const APath: WideString; CreateParent : Boolean) : TJSONData;
+    function FindElement(Const APath: WideString; CreateParent : Boolean; Var AParent : TJSONObject; Var ElName : WideString) : TJSONData;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure Clear;
+    procedure Flush;    // Writes the JSON file
+    procedure OpenKey(const aPath: WideString; AllowCreate : Boolean);
+    procedure CloseKey;
+    procedure ResetKey;
+    Procedure EnumSubKeys(Const APath : String; List : TStrings);
+    Procedure EnumValues(Const APath : String; List : TStrings);
+
+    function  GetValue(const APath: WideString; const ADefault: WideString): WideString; overload;
+    function  GetValue(const APath: WideString; ADefault: Integer): Integer; overload;
+    function  GetValue(const APath: WideString; ADefault: Boolean): Boolean; overload;
+    function  GetValue(const APath: WideString; ADefault: Double): Double; overload;
+    procedure SetValue(const APath: WideString; const AValue: WideString); overload;
+    procedure SetValue(const APath: WideString; AValue: Integer); overload;
+    procedure SetValue(const APath: WideString; AValue: Boolean); overload;
+    procedure SetValue(const APath: WideString; AValue: Double); overload;
+
+    procedure SetDeleteValue(const APath: WideString; const AValue, DefValue: WideString); overload;
+    procedure SetDeleteValue(const APath: WideString; AValue, DefValue: Integer); overload;
+    procedure SetDeleteValue(const APath: WideString; AValue, DefValue: Boolean); overload;
+
+    procedure DeletePath(const APath: WideString);
+    procedure DeleteValue(const APath: WideString);
+    property Modified: Boolean read FModified;
+  published
+    property Filename: String read FFilename write SetFilename;
+  end;
+
+
+// ===================================================================
+
+implementation
+
+Const
+  SErrInvalidJSONFile = '"%s" is not a valid JSON configuration file.';
+  SErrCouldNotOpenKey = 'Could not open key "%s".';
+
+constructor TJSONConfig.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FJSON:=TJSONObject.Create;
+  FKey:=FJSON;
+end;
+
+destructor TJSONConfig.Destroy;
+begin
+  if Assigned(FJSON) then
+    begin
+    Flush;
+    FreeANdNil(FJSON);
+    end;
+  inherited Destroy;
+end;
+
+procedure TJSONConfig.Clear;
+begin
+  FJSON.Clear;
+  FKey:=FJSON;
+end;
+
+procedure TJSONConfig.Flush;
+
+Var
+  F : Text;
+
+begin
+  if Modified then
+    begin
+    AssignFile(F,FileName);
+    Rewrite(F);
+    Try
+      Writeln(F,FJSON.AsJSON);
+    Finally
+      CloseFile(F);
+    end;
+    FModified := False;
+    end;
+end;
+
+
+function TJSONConfig.FindObject(Const APath: WideString; AllowCreate : Boolean) : TJSONObject;
+
+Var
+  Dummy : WideString;
+
+begin
+  Result:=FindObject(APath,AllowCreate,Dummy);
+end;
+
+function TJSONConfig.FindObject(Const APath: WideString; AllowCreate : Boolean;Var ElName : WideString) : TJSONObject;
+
+Var
+  S,El : WideString;
+  P,I : Integer;
+  T : TJSonObject;
+  
+begin
+//  Writeln('Looking for : ', APath);
+  S:=APath;
+  If Pos('/',S)=1 then
+    Result:=FJSON
+  else
+    Result:=FKey;
+  Repeat
+    P:=Pos('/',S);
+    If (P<>0) then
+      begin
+      // Only real paths, ignore double slash
+      If (P<>1) then
+        begin
+        El:=Copy(S,1,P-1);
+        If (Result.Count=0) then
+          I:=-1
+        else
+          I:=Result.IndexOfName(El);
+        If (I=-1) then
+          // No element with this name.
+          begin
+          If AllowCreate then
+            begin
+            // Create new node.
+            T:=Result;
+            Result:=TJSonObject.Create;
+            T.Add(El,Result);
+            end
+          else
+            Result:=Nil
+          end
+        else
+          // Node found, check if it is an object
+          begin
+          if (Result.Items[i].JSONtype=jtObject) then
+            Result:=Result.Objects[el]
+          else
+            begin
+//            Writeln(el,' type wrong');
+            If AllowCreate then
+              begin
+//              Writeln('Creating ',el);
+              Result.Delete(I);
+              T:=Result;
+              Result:=TJSonObject.Create;
+              T.Add(El,Result);
+              end
+            else
+              Result:=Nil
+            end;
+          end;
+        end;
+      Delete(S,1,P);
+      end;
+  Until (P=0) or (Result=Nil);
+  ElName:=S;
+end;
+
+function TJSONConfig.FindElement(Const APath: WideString; CreateParent : Boolean) : TJSONData;
+
+Var
+  O : TJSONObject;
+  ElName : WideString;
+  
+begin
+  Result:=FindElement(APath,CreateParent,O,ElName);
+end;
+
+function TJSONConfig.FindElement(Const APath: WideString; CreateParent : Boolean; Var AParent : TJSONObject; Var ElName : WideString) : TJSONData;
+
+Var
+  I : Integer;
+
+begin
+  Result:=Nil;
+  Aparent:=FindObject(APath,CreateParent,ElName);
+  If Assigned(Aparent) then
+    begin
+//    Writeln('Found parent, looking for element:',elName);
+    I:=AParent.IndexOfName(ElName);
+//    Writeln('Element index is',I);
+    If (I<>-1) And (AParent.items[I].JSONType<>jtObject) then
+      Result:=AParent.Items[i];
+    end;
+end;
+
+
+function TJSONConfig.GetValue(const APath: WideString; const ADefault: WideString): WideString;
+
+var
+  El : TJSONData;
+  
+begin
+  El:=FindElement(StripSlash(APath),False);
+  If Assigned(El) then
+    Result:=El.AsString
+  else
+    Result:=ADefault;
+end;
+
+function TJSONConfig.GetValue(const APath: WideString; ADefault: Integer): Integer;
+var
+  El : TJSONData;
+  
+begin
+  El:=FindElement(StripSlash(APath),False);
+  If Not Assigned(el) then
+    Result:=ADefault
+  else if (el is TJSONNumber) then
+    Result:=El.AsInteger
+  else
+    Result:=StrToIntDef(El.AsString,ADefault);
+end;
+
+function TJSONConfig.GetValue(const APath: WideString; ADefault: Boolean): Boolean;
+
+var
+  El : TJSONData;
+  
+begin
+  El:=FindElement(StripSlash(APath),False);
+  If Not Assigned(el) then
+    Result:=ADefault
+  else if (el is TJSONBoolean) then
+    Result:=El.AsBoolean
+  else
+    Result:=StrToBoolDef(El.AsString,ADefault);
+end;
+
+function TJSONConfig.GetValue(const APath: WideString; ADefault: Double): Double;
+
+var
+  El : TJSONData;
+
+begin
+  El:=FindElement(StripSlash(APath),False);
+  If Not Assigned(el) then
+    Result:=ADefault
+  else if (el is TJSONNumber) then
+    Result:=El.AsFloat
+  else
+    Result:=StrToFloatDef(El.AsString,ADefault);
+end;
+
+
+procedure TJSONConfig.SetValue(const APath: WideString; const AValue: WideString);
+
+var
+  El : TJSONData;
+  ElName : WideString;
+  O : TJSONObject;
+  I : integer;
+  
+begin
+  El:=FindElement(StripSlash(APath),True,O,ElName);
+  if Assigned(El) and (El.JSONType<>jtString) then
+    begin
+    I:=O.IndexOfName(elName);
+    O.Delete(i);
+    El:=Nil;
+    end;
+  If Not Assigned(el) then
+    begin
+    El:=TJSONString.Create(AValue);
+    O.Add(ElName,El);
+    end
+  else
+    El.AsString:=AVAlue;
+  FModified:=True;
+end;
+
+procedure TJSONConfig.SetDeleteValue(const APath: WideString; const AValue, DefValue: WideString);
+begin
+  if AValue = DefValue then
+    DeleteValue(APath)
+  else
+    SetValue(APath, AValue);
+end;
+
+procedure TJSONConfig.SetValue(const APath: WideString; AValue: Integer);
+
+var
+  El : TJSONData;
+  ElName : WideString;
+  O : TJSONObject;
+  I : integer;
+
+begin
+  El:=FindElement(StripSlash(APath),True,O,ElName);
+  if Assigned(El) and (Not (El is TJSONIntegerNumber)) then
+    begin
+    I:=O.IndexOfName(elName);
+    If (I<>-1) then // Normally not needed...
+      O.Delete(i);
+    El:=Nil;
+    end;
+  If Not Assigned(el) then
+    begin
+    El:=TJSONIntegerNumber.Create(AValue);
+    O.Add(ElName,El);
+    end
+  else
+    El.AsInteger:=AValue;
+  FModified:=True;
+end;
+
+procedure TJSONConfig.SetDeleteValue(const APath: WideString; AValue,
+  DefValue: Integer);
+begin
+  if AValue = DefValue then
+    DeleteValue(APath)
+  else
+    SetValue(APath, AValue);
+end;
+
+procedure TJSONConfig.SetValue(const APath: WideString; AValue: Boolean);
+
+var
+  El : TJSONData;
+  ElName : WideString;
+  O : TJSONObject;
+  I : integer;
+
+begin
+  El:=FindElement(StripSlash(APath),True,O,ElName);
+  if Assigned(El) and (el.JSONType<>jtBoolean) then
+    begin
+    I:=O.IndexOfName(elName);
+    O.Delete(i);
+    El:=Nil;
+    end;
+  If Not Assigned(el) then
+    begin
+    El:=TJSONBoolean.Create(AValue);
+    O.Add(ElName,El);
+    end
+  else
+    El.AsBoolean:=AValue;
+  FModified:=True;
+end;
+
+procedure TJSONConfig.SetValue(const APath: WideString; AValue: Double);
+
+var
+  El : TJSONData;
+  ElName : WideString;
+  O : TJSONObject;
+  I : integer;
+
+begin
+  El:=FindElement(StripSlash(APath),True,O,ElName);
+  if Assigned(El) and (Not (El is TJSONFloatNumber)) then
+    begin
+    I:=O.IndexOfName(elName);
+    O.Delete(i);
+    El:=Nil;
+    end;
+  If Not Assigned(el) then
+    begin
+    El:=TJSONFloatNumber.Create(AValue);
+    O.Add(ElName,El);
+    end
+  else
+    El.AsFloat:=AValue;
+  FModified:=True;
+end;
+
+procedure TJSONConfig.SetDeleteValue(const APath: WideString; AValue,
+  DefValue: Boolean);
+begin
+  if AValue = DefValue then
+    DeleteValue(APath)
+  else
+    SetValue(APath,AValue);
+end;
+
+procedure TJSONConfig.DeletePath(const APath: WideString);
+
+Var
+  P : String;
+  L : integer;
+  Node : TJSONObject;
+  ElName : WideString;
+  
+begin
+  P:=StripSlash(APath);
+  L:=Length(P);
+  If (L>0) then
+    begin
+    Node := FindObject(P,False,ElName);
+    If Assigned(Node) then
+      begin
+      L:=Node.IndexOfName(ElName);
+      If (L<>-1) then
+        Node.Delete(L);
+      end;
+    end;
+end;
+
+procedure TJSONConfig.DeleteValue(const APath: WideString);
+
+begin
+  DeletePath(APath);
+end;
+
+procedure TJSONConfig.Loaded;
+begin
+  inherited Loaded;
+  if Length(Filename) > 0 then
+    DoSetFilename(Filename,True);
+end;
+
+function TJSONConfig.FindPath(const APath: WideString; AllowCreate: Boolean
+  ): TJSONObject;
+  
+Var
+  P : WideString;
+  L : Integer;
+  
+begin
+  P:=APath;
+  L:=Length(P);
+  If (L=0) or (P[L]<>'/') then
+    P:=P+'/';
+  Result:=FindObject(P,AllowCreate);
+end;
+
+procedure TJSONConfig.DoSetFilename(const AFilename: String; ForceReload: Boolean);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+  F : TFileStream;
+  
+begin
+  if (not ForceReload) and (FFilename = AFilename) then
+    exit;
+  FFilename := AFilename;
+
+  if csLoading in ComponentState then
+    exit;
+
+  Flush;
+  If Not FileExists(AFileName) then
+    Clear
+  else
+    begin
+    F:=TFileStream.Create(AFileName,fmopenRead);
+    try
+      P:=TJSONParser.Create(F);
+      try
+        J:=P.Parse;
+        If (J is TJSONObject) then
+          begin
+          FreeAndNil(FJSON);
+          FJSON:=J as TJSONObject;
+          FKey:=FJSON;
+          end
+        else
+          Raise EJSONConfigError.CreateFmt(SErrInvalidJSONFile,[AFileName]);
+      finally
+        P.Free;
+      end;
+    finally
+      F.Free;
+    end;
+    end;
+end;
+
+procedure TJSONConfig.SetFilename(const AFilename: String);
+begin
+  DoSetFilename(AFilename, False);
+end;
+
+function TJSONConfig.StripSlash(P: WideString): WideString;
+
+Var
+  L : Integer;
+
+begin
+  L:=Length(P);
+  If (L>0) and (P[l]='/') then
+    Result:=Copy(P,1,L-1)
+  else
+    Result:=P;
+end;
+
+
+procedure TJSONConfig.CloseKey;
+begin
+  ResetKey;
+end;
+
+procedure TJSONConfig.OpenKey(const aPath: WideString; AllowCreate: Boolean);
+
+Var
+  ElName : WideString;
+  P : String;
+  L : Integer;
+begin
+  P:=APath;
+  L:=Length(P);
+  If (L=0) then
+    FKey:=FJSON
+  else
+    begin
+    if (P[L]<>'/') then
+      P:=P+'/';
+    FKey:=FindObject(P,AllowCreate);
+    If (FKey=Nil) Then
+      Raise EJSONConfigError.CreateFmt(SErrCouldNotOpenKey,[APath]);
+    end;
+end;
+
+procedure TJSONConfig.ResetKey;
+begin
+  FKey:=FJSON;
+end;
+
+procedure TJSONConfig.EnumSubKeys(const APath: String; List: TStrings);
+
+Var
+  AKey : TJSONObject;
+  I : Integer;
+  
+begin
+  AKey:=FindPath(APath,False);
+  If Assigned(AKey) then
+    begin
+    For I:=0 to AKey.Count-1 do
+      If AKey.Items[i] is TJSONObject then
+        List.Add(AKey.Names[i]);
+    end;
+end;
+
+procedure TJSONConfig.EnumValues(const APath: String; List: TStrings);
+
+Var
+  AKey : TJSONObject;
+  I : Integer;
+
+begin
+  AKey:=FindPath(APath,False);
+  If Assigned(AKey) then
+    begin
+    For I:=0 to AKey.Count-1 do
+      If Not (AKey.Items[i] is TJSONObject) then
+        List.Add(AKey.Names[i]);
+    end;
+end;
+
+
+end.

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

@@ -0,0 +1,249 @@
+{
+    This file is part of the Free Component Library
+
+    JSON source parser
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit jsonparser;
+
+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);
+      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);
+end;
+
+Procedure TJSONParser.DoError(Msg : String);
+
+Var
+  S : String;
+
+begin
+  S:=Format(Msg,[CurrentTokenString]);
+  S:=Format('Error at line %d, Pos %d:',[FScanner.CurRow,FSCanner.CurColumn])+S;
+  Raise EJSONScanner.Create(S);
+end;
+
+constructor TJSONParser.Create(Source: TStream);
+begin
+  Inherited Create;
+  FScanner:=TJSONScanner.Create(Source);
+end;
+
+constructor TJSONParser.Create(Source: TJSONStringType);
+begin
+  Inherited Create;
+  FScanner:=TJSONScanner.Create(Source);
+end;
+
+end.
+

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

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

+ 258 - 0
packages/fcl-json/tests/jsonconftest.pp

@@ -0,0 +1,258 @@
+unit jsonconftest;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, jsonconf;
+
+type
+
+  { TTestJSONConfig }
+
+  TTestJSONConfig= class(TTestCase)
+  Private
+    Function CreateConf(AFileName : String) : TJSONCOnfig;
+    Procedure DeleteConf(C : TJSONConfig; DeleteConfFile : Boolean = true);
+  published
+    procedure TestDataTypes;
+    procedure TestSubNodes;
+    procedure TestEnumSubkeys;
+    procedure TestEnumValues;
+    procedure TestClear;
+    procedure TestKey;
+  end;
+
+implementation
+
+function TTestJSONConfig.CreateConf(AFileName: String): TJSONCOnfig;
+begin
+  Result:=TJSONConfig.Create(Nil);
+  Result.FileName:=AFileName;
+end;
+
+procedure TTestJSONConfig.DeleteConf(C: TJSONConfig; DeleteConfFile: Boolean);
+
+Var
+  FN : String;
+
+begin
+  If DeleteConfFile then
+    FN:=C.FileName;
+  FreeAndNil(C);
+  If DeleteConfFile then
+    DeleteFile(FN);
+end;
+
+procedure TTestJSONConfig.TestDataTypes;
+
+Const
+  A = 1;
+  B = 'A string';
+  C = 1.23;
+  D = True;
+
+Var
+  Co : TJSONCOnfig;
+
+begin
+  Co:=CreateConf('test.json');
+  try
+    Co.SetValue('a',a);
+    AssertEquals('Integer read/Write',a,Co.GetValue('a',0));
+    Co.SetValue('b',b);
+    AssertEquals('String read/Write',b,Co.GetValue('b',''));
+    Co.SetValue('c',C);
+    AssertEquals('Float read/Write',c,Co.GetValue('c',0.0),0.01);
+    Co.SetValue('d',d);
+    AssertEquals('Boolean read/Write',d,Co.GetValue('d',False));
+    Co.Flush;
+  finally
+    DeleteConf(Co,True);
+  end;
+end;
+
+procedure TTestJSONConfig.TestSubNodes;
+
+Var
+  C : TJSONCOnfig;
+
+begin
+  C:=CreateConf('test.json');
+  try
+    C.SetValue('a',1);
+    AssertEquals('Read at root',1,C.GetValue('a',0));
+    C.SetValue('b/a',2);
+    AssertEquals('Read at root',2,C.GetValue('b/a',2));
+    C.SetValue('b/c/a',3);
+    AssertEquals('Read at root',3,C.GetValue('b/c/a',3));
+  finally
+    DeleteConf(C,True);
+  end;
+end;
+
+procedure TTestJSONConfig.TestEnumSubkeys;
+Var
+  C : TJSONCOnfig;
+  L : TStringList;
+  
+begin
+  C:=CreateConf('test.json');
+  try
+    C.SetValue('/a',1);
+    C.SetValue('/b/a',2);
+    C.SetValue('/b/b',2);
+    C.SetValue('/c/a',3);
+    C.SetValue('/c/b/a',4);
+    C.SetValue('/c/c/a',4);
+    C.SetValue('/c/d/d',4);
+    L:=TStringList.Create;
+    try
+      C.EnumSubKeys('/',L);
+      If (L.Count<>2) then
+        Fail('EnumSubkeys count');
+      If (L[0]<>'b') then
+        Fail('EnumSubkeys first element');
+      If (L[1]<>'c') then
+        Fail('EnumSubkeys second element');
+    finally
+      L.Free;
+    end;
+  finally
+    DeleteConf(C,True);
+  end;
+end;
+
+procedure TTestJSONConfig.TestEnumValues;
+Var
+  C : TJSONCOnfig;
+  L : TStringList;
+
+begin
+  C:=CreateConf('test.json');
+  try
+    C.SetValue('/a',1);
+    C.SetValue('/b/a',2);
+    C.SetValue('/b/b',2);
+    C.SetValue('/c/a',3);
+    C.SetValue('/c/b/a',4);
+    C.SetValue('/c/c/a',4);
+    C.SetValue('/c/d/d',4);
+    L:=TStringList.Create;
+    try
+      C.EnumValues('/',L);
+      If (L.Count<>1) then
+        Fail('EnumValues count');
+      If (L[0]<>'a') then
+        Fail('EnumValues first element');
+      L.Clear;
+      C.EnumValues('/b',L);
+      If (L.Count<>2) then
+        Fail('EnumValues subkey count');
+      If (L[0]<>'a') then
+        Fail('EnumValues subkey first element');
+      If (L[1]<>'b') then
+        Fail('EnumValues subkey second element');
+    finally
+      L.Free;
+    end;
+  finally
+    DeleteConf(C,True);
+  end;
+end;
+
+procedure TTestJSONConfig.TestClear;
+
+Var
+  C : TJSONCOnfig;
+
+begin
+  C:=CreateConf('test.json');
+  try
+    C.SetValue('a',1);
+    C.DeleteValue('a');
+    AssertEquals('Delete value',0,C.GetValue('a',0));
+    C.SetValue('b/a',1);
+    C.SetValue('b/c',2);
+    C.DeleteValue('b/a');
+    AssertEquals('Delete value in subkey',0,C.GetValue('a',0));
+    AssertEquals('Delete value only clears deleted value',2,C.GetValue('b/c',0));
+    C.SetValue('b/a',1);
+    C.DeletePath('b');
+    AssertEquals('Delete path',0,C.GetValue('b/a',0));
+    AssertEquals('Delete path deletes all values',0,C.GetValue('b/c',0));
+    C.Clear;
+    AssertEquals('Clear',0,C.GetValue('/a',0));
+  finally
+    DeleteConf(C,True);
+  end;
+end;
+
+procedure TTestJSONConfig.TestKey;
+
+Var
+  C : TJSONCOnfig;
+  L : TStrings;
+  
+begin
+  C:=CreateConf('test.json');
+  try
+    C.SetValue('a',1);
+    C.SetValue('b/a',2);
+    C.SetValue('b/b',2);
+    C.SetValue('b/c/a',3);
+    C.SetValue('b/c/b',3);
+    C.OpenKey('/b',False);
+    AssertEquals('Read relative to key a',2,C.GetValue('a',0));
+    AssertEquals('Read relative to key b',2,C.GetValue('b',0));
+    AssertEquals('Read in subkey relative to key a',3,C.GetValue('c/a',0));
+    AssertEquals('Read in subkey relative to key b',3,C.GetValue('c/b',0));
+    AssertEquals('Read absolute, disregarding key',1,C.GetValue('/a',0));
+    AssertEquals('Read absolute in subkey, disregarding key',2,C.GetValue('/b/a',0));
+    AssertEquals('Read absolute in subkeys, disregarding key',3,C.GetValue('/b/c/a',0));
+    C.CloseKey;
+    AssertEquals('Closekey',1,C.GetValue('a',0));
+    C.OpenKey('b',False);
+    C.OpenKey('c',False);
+    AssertEquals('Open relative key',3,C.GetValue('a',0));
+    C.ResetKey;
+    AssertEquals('ResetKey',1,C.GetValue('a',0));
+    C.Clear;
+    L:=TStringList.Create;
+    try
+      C.EnumSubKeys('/',L);
+      If (L.Count<>0) then
+        Fail('clear failed');
+      C.OpenKey('/a/b/c/d',true);
+      C.EnumSubKeys('/a',L);
+      If (L.Count<>1) then
+        Fail('Open key with allowcreate, level 1');
+      If (L[0]<>'b') then
+        Fail('Open key with allowcreate, level 1');
+      L.Clear;
+      C.EnumSubKeys('/a/b',L);
+      If (L.Count<>1) then
+        Fail('Open key with allowcreate, level 2');
+      If (L[0]<>'c') then
+        Fail('Open key with allowcreate, level 2');
+      L.Clear;
+      C.EnumSubKeys('/a/b/c',L);
+      If (L.Count<>1) then
+        Fail('Open key with allowcreate, level 3');
+      If (L[0]<>'d') then
+        Fail('Open key with allowcreate, level 3');
+    finally
+      L.Free;
+    end;
+  finally
+    DeleteConf(C,True);
+  end;
+end;
+
+
+initialization
+
+  RegisterTest(TTestJSONConfig); 
+end.
+

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

@@ -0,0 +1,71 @@
+<?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="4">
+      <Item1>
+        <PackageName Value="fpcunitconsolerunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+      <Item3>
+        <PackageName Value="FPCUnitTestRunner"/>
+      </Item3>
+      <Item4>
+        <PackageName Value="FCL"/>
+      </Item4>
+    </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"/>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src/"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

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

@@ -0,0 +1,36 @@
+{
+    This file is part of the Free Component Library
+
+    JSON fpcunit tester program
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+program testjson;
+
+uses
+  Classes, consoletestrunner, testjsondata, testjsonparser,
+  fpcunitconsolerunner;
+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.

+ 64 - 0
packages/fcl-json/tests/testjsonconf.lpi

@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="5"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <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="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="testjsonconf.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="testjsonconf"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="jsonconftest.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="jsonconftest"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="../src/jsonconf.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="jsonConf"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src/"/>
+    </SearchPaths>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 25 - 0
packages/fcl-json/tests/testjsonconf.pp

@@ -0,0 +1,25 @@
+program testjsonconf;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, jsonconftest, jsonconf;
+
+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.

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

@@ -0,0 +1,1800 @@
+{
+    This file is part of the Free Component Library
+
+    JSON FPCUNit test for data structures
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit testjsondata; 
+
+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.
+

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

@@ -0,0 +1,395 @@
+{
+    This file is part of the Free Component Library
+
+    JSON FPCUNit test for parser
+    Copyright (c) 2007 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit testjsonparser;
+
+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; DoJSONTest : Boolean = True);
+    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;
+
+Const
+
+  SAddr ='{ "addressbook": { "name": "Mary Lebow", '+
+         '  "address": {'+
+         '      "street": "5 Main Street",'+LineEnding+
+         '        "city": "San Diego, CA",'+LineEnding+
+         '        "zip": 91912,'+LineEnding+
+         '    },'+LineEnding+
+         '    "phoneNumbers": [  '+LineEnding+
+         '        "619 332-3452",'+LineEnding+
+         '        "664 223-4667"'+LineEnding+
+         '    ]'+LineEnding+
+         ' }'+LineEnding+
+         '}';
+
+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']);
+  DoTestObject(SAddr,['addressbook'],False);
+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; DoJSONTest : Boolean = True);
+
+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)]);
+    If DoJSONTest then
+      self.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.
+