Selaa lähdekoodia

* webidl added

git-svn-id: trunk@39292 -
michael 7 vuotta sitten
vanhempi
commit
e655b9137b

+ 14 - 0
.gitattributes

@@ -8130,6 +8130,20 @@ packages/uuid/examples/testuid.pp svneol=native#text/plain
 packages/uuid/fpmake.pp svneol=native#text/plain
 packages/uuid/src/libuuid.pp svneol=native#text/plain
 packages/uuid/src/macuuid.pp svneol=native#text/plain
+packages/webidl/Makefile svneol=native#text/plain
+packages/webidl/Makefile.fpc svneol=native#text/plain
+packages/webidl/examples/parsewebidl.lpi svneol=native#text/plain
+packages/webidl/examples/parsewebidl.pas svneol=native#text/plain
+packages/webidl/fpmake.pp svneol=native#text/plain
+packages/webidl/src/webidldefs.pp svneol=native#text/plain
+packages/webidl/src/webidlparser.pp svneol=native#text/plain
+packages/webidl/src/webidlscanner.pp svneol=native#text/plain
+packages/webidl/src/webidltopas.pp svneol=native#text/plain
+packages/webidl/tests/tcidlparser.pp svneol=native#text/plain
+packages/webidl/tests/tcidlscanner.pp svneol=native#text/plain
+packages/webidl/tests/tcwebidldefs.pp svneol=native#text/plain
+packages/webidl/tests/testidl.lpi svneol=native#text/plain
+packages/webidl/tests/testidl.pas svneol=native#text/plain
 packages/winceunits/Makefile svneol=native#text/plain
 packages/winceunits/Makefile.fpc svneol=native#text/plain
 packages/winceunits/Makefile.fpc.fpcmake svneol=native#text/plain

+ 1 - 0
packages/fpmake_add.inc

@@ -138,5 +138,6 @@
   add_libgc(ADirectory+IncludeTrailingPathDelimiter('libgc'));
   add_libfontconfig(ADirectory+IncludeTrailingPathDelimiter('libfontconfig'));
   add_fcl_report(ADirectory+IncludeTrailingPathDelimiter('fcl-report'));
+  add_webidl(ADirectory+IncludeTrailingPathDelimiter('webidl'));
   add_ide(ADirectory+IncludeTrailingPathDelimiter('ide'));
   

+ 7 - 0
packages/fpmake_proc.inc

@@ -789,4 +789,11 @@ begin
 {$include fcl-report/fpmake.pp}
 end;
 
+procedure add_webidl(const ADirectory: string);
+begin
+  with Installer do
+{$include webidl/fpmake.pp}
+end;
+
+
 {$include ide/fpmake.pp}

+ 2742 - 0
packages/webidl/Makefile

@@ -0,0 +1,2742 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2017-12-27 rev 37833]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-netbsd m68k-amiga m68k-atari m68k-palmos m68k-macos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android arm-aros powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-embedded i8086-msdos i8086-win16 aarch64-linux aarch64-darwin wasm-wasm sparc64-linux
+BSDs = freebsd netbsd openbsd darwin dragonfly
+UNIXs = linux $(BSDs) solaris qnx haiku aix
+LIMIT83fs = go32v2 os2 emx watcom msdos win16 atari
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for avr-embedded, a sub-architecture (e.g. SUBARCH=avr25 or SUBARCH=avr35) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+ifneq ($(findstring $(OS_TARGET),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+endif
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+ifndef CROSSCOMPILE
+BUILDFULLNATIVE=1
+export BUILDFULLNATIVE
+endif
+ifdef BUILDFULLNATIVE
+BUILDNATIVE=1
+export BUILDNATIVE
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl)),)
+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)),)
+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)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifneq ($(OS_TARGET),msdos)
+ifndef DARWIN2DARWIN
+ifneq ($(CPU_TARGET),jvm)
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+ifeq ($(OS_TARGET),android)
+ifeq ($(CPU_TARGET),arm)
+BINUTILSPREFIX=arm-linux-androideabi-
+else
+ifeq ($(CPU_TARGET),i386)
+BINUTILSPREFIX=i686-linux-android-
+else
+ifeq ($(CPU_TARGET),mipsel)
+BINUTILSPREFIX=mipsel-linux-android-
+endif
+endif
+endif
+endif
+endif
+endif
+else
+BINUTILSPREFIX=$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages)
+ifndef FPCFPMAKE
+ifdef CROSSCOMPILE
+ifeq ($(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR)))),)
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPCFPMAKE:=$(shell $(FPCPROG) -PB)
+ifeq ($(strip $(wildcard $(FPCFPMAKE))),)
+FPCFPMAKE:=$(firstword $(FPCPROG))
+endif
+else
+override FPCFPMAKE=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+FPCFPMAKE=$(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR))))
+FPMAKE_SKIP_CONFIG=-n
+export FPCFPMAKE
+export FPMAKE_SKIP_CONFIG
+endif
+else
+FPMAKE_SKIP_CONFIG=-n
+FPCFPMAKE=$(FPC)
+endif
+endif
+override PACKAGE_NAME=webidl
+override PACKAGE_VERSION=3.1.1
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+override INSTALL_FPCPACKAGE=y
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+EXEDBGEXT=.dbg
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifneq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),dragonfly)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=df
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),aros)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=aros
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+EXEDBGEXT=.dSYM
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+ifeq ($(OS_TARGET),wii)
+EXEEXT=.dol
+SHAREDLIBEXT=.so
+SHORTSUFFIX=wii
+endif
+ifeq ($(OS_TARGET),aix)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=aix
+endif
+ifeq ($(OS_TARGET),java)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=java
+endif
+ifeq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=android
+endif
+endif
+ifeq ($(OS_TARGET),msdos)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHORTSUFFIX=d16
+endif
+ifeq ($(OS_TARGET),embedded)
+ifeq ($(CPU_TARGET),i8086)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+else
+EXEEXT=.bin
+endif
+SHORTSUFFIX=emb
+endif
+ifeq ($(OS_TARGET),win16)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w16
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+NASMNAME=$(BINUTILSPREFIX)nasm
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+ifndef NASMPROG
+ifdef CROSSBINDIR
+NASMPROG=$(CROSSBINDIR)/$(NASMNAME)$(SRCEXEEXT)
+else
+NASMPROG=$(NASMNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+NASM=$(NASMPROG)
+ifdef inUnix
+PPAS=./ppas$(SRCBATCHEXT)
+else
+PPAS=ppas$(SRCBATCHEXT)
+endif
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl rtl-objpas fpmkunit fcl-base
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mips-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),jvm-java)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i8086-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i8086-msdos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i8086-win16)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),wasm-wasm)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_RTL-OBJPAS=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
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+ifdef UNITDIR_FPMAKE_RTL
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_PASZLIB
+PACKAGEDIR_PASZLIB:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_PASZLIB),)
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)),)
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)
+else
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_PASZLIB)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_PASZLIB) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_PASZLIB)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_PASZLIB=
+UNITDIR_PASZLIB:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_PASZLIB),)
+UNITDIR_PASZLIB:=$(firstword $(UNITDIR_PASZLIB))
+else
+UNITDIR_PASZLIB=
+endif
+endif
+ifdef UNITDIR_PASZLIB
+override COMPILER_UNITDIR+=$(UNITDIR_PASZLIB)
+endif
+ifdef UNITDIR_FPMAKE_PASZLIB
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_PASZLIB)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-PROCESS
+PACKAGEDIR_FCL-PROCESS:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-PROCESS),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FCL-PROCESS) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-PROCESS=
+UNITDIR_FCL-PROCESS:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-PROCESS),)
+UNITDIR_FCL-PROCESS:=$(firstword $(UNITDIR_FCL-PROCESS))
+else
+UNITDIR_FCL-PROCESS=
+endif
+endif
+ifdef UNITDIR_FCL-PROCESS
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-PROCESS)
+endif
+ifdef UNITDIR_FPMAKE_FCL-PROCESS
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FCL-PROCESS)
+endif
+endif
+ifdef REQUIRE_PACKAGES_HASH
+PACKAGEDIR_HASH:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /hash/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_HASH),)
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)),)
+UNITDIR_HASH=$(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)
+else
+UNITDIR_HASH=$(PACKAGEDIR_HASH)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_HASH)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_HASH) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_HASH)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_HASH=
+UNITDIR_HASH:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /hash/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_HASH),)
+UNITDIR_HASH:=$(firstword $(UNITDIR_HASH))
+else
+UNITDIR_HASH=
+endif
+endif
+ifdef UNITDIR_HASH
+override COMPILER_UNITDIR+=$(UNITDIR_HASH)
+endif
+ifdef UNITDIR_FPMAKE_HASH
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_HASH)
+endif
+endif
+ifdef REQUIRE_PACKAGES_LIBTAR
+PACKAGEDIR_LIBTAR:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libtar/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_LIBTAR),)
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)),)
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)
+else
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_LIBTAR)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_LIBTAR) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_LIBTAR)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_LIBTAR=
+UNITDIR_LIBTAR:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /libtar/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_LIBTAR),)
+UNITDIR_LIBTAR:=$(firstword $(UNITDIR_LIBTAR))
+else
+UNITDIR_LIBTAR=
+endif
+endif
+ifdef UNITDIR_LIBTAR
+override COMPILER_UNITDIR+=$(UNITDIR_LIBTAR)
+endif
+ifdef UNITDIR_FPMAKE_LIBTAR
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_LIBTAR)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FPMKUNIT
+PACKAGEDIR_FPMKUNIT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FPMKUNIT),)
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)),)
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FPMKUNIT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FPMKUNIT=
+UNITDIR_FPMKUNIT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FPMKUNIT),)
+UNITDIR_FPMKUNIT:=$(firstword $(UNITDIR_FPMKUNIT))
+else
+UNITDIR_FPMKUNIT=
+endif
+endif
+ifdef UNITDIR_FPMKUNIT
+override COMPILER_UNITDIR+=$(UNITDIR_FPMKUNIT)
+endif
+ifdef UNITDIR_FPMAKE_FPMKUNIT
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FPMKUNIT)
+endif
+endif
+ifdef REQUIRE_PACKAGES_RTL-OBJPAS
+PACKAGEDIR_RTL-OBJPAS:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl-objpas/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL-OBJPAS),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL-OBJPAS)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL-OBJPAS=$(PACKAGEDIR_RTL-OBJPAS)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL-OBJPAS=$(PACKAGEDIR_RTL-OBJPAS)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_RTL-OBJPAS)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL-OBJPAS=$(PACKAGEDIR_RTL-OBJPAS)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL-OBJPAS)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL-OBJPAS=$(PACKAGEDIR_RTL-OBJPAS)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL-OBJPAS=$(PACKAGEDIR_RTL-OBJPAS)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL-OBJPAS)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL-OBJPAS) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL-OBJPAS)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL-OBJPAS=
+UNITDIR_RTL-OBJPAS:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl-objpas/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL-OBJPAS),)
+UNITDIR_RTL-OBJPAS:=$(firstword $(UNITDIR_RTL-OBJPAS))
+else
+UNITDIR_RTL-OBJPAS=
+endif
+endif
+ifdef UNITDIR_RTL-OBJPAS
+override COMPILER_UNITDIR+=$(UNITDIR_RTL-OBJPAS)
+endif
+ifdef UNITDIR_FPMAKE_RTL-OBJPAS
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL-OBJPAS)
+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
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)
+endif
+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
+ifdef UNITDIR_FPMAKE_FCL-BASE
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FCL-BASE)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPMAKE_BUILD_OPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+override FPMAKE_BUILD_OPT+=-XP$(BINUTILSPREFIX)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+endif
+ifneq ($(findstring $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
+ifneq ($(findstring $(CPU_TARGET),x86_64 mips mipsel),)
+override FPCOPT+=-Cg
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPMAKEBUILDOPT
+override FPMAKE_BUILD_OPT+=$(FPMAKEBUILDOPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(strip $(FPC) $(FPCOPT))
+ifneq (,$(findstring -sh ,$(COMPILER)))
+UseEXECPPAS=1
+endif
+ifneq (,$(findstring -s ,$(COMPILER)))
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+UseEXECPPAS=1
+endif
+endif
+ifneq ($(UseEXECPPAS),1)
+EXECPPAS=
+else
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+ifneq ($(IMPORTLIBPREFIX)-$(STATICLIBEXT),$(STATICLIBPREFIX)-$(STATICLIBEXT))
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+else
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+endif
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(EXAMPLEINSTALLTARGET) $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+	$(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+	$(MKDIR) $(DIST_DESTDIR)
+	$(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+	echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+	echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+	echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+	/bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+	$(RUNBATCH) $(ZIPWRAPPER)
+else
+	$(ZIPWRAPPER)
+endif
+endif
+	$(DEL) $(ZIPWRAPPER)
+else
+	$(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+	$(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+	$(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=distinstall
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+override CLEANEXEDBGFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEDBGFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEDBGEXT), $(CLEAN_PROGRAMS)))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANEXEDBGFILES
+	-$(DELTREE) $(CLEANEXEDBGFILES)
+endif
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+	-$(DELTREE) units
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+	-$(DEL) *.o *.ppu *.a
+endif
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+	-$(DEL) *$(DEBUGSYMEXT)
+endif
+ifdef LOCALFPMAKEBIN
+	-$(DEL) $(LOCALFPMAKEBIN)
+	-$(DEL) $(FPMAKEBINOBJ)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+	@$(ECHO)
+	@$(ECHO)  == Package info ==
+	@$(ECHO)  Package Name..... $(PACKAGE_NAME)
+	@$(ECHO)  Package Version.. $(PACKAGE_VERSION)
+	@$(ECHO)
+	@$(ECHO)  == Configuration info ==
+	@$(ECHO)
+	@$(ECHO)  FPC.......... $(FPC)
+	@$(ECHO)  FPC Version.. $(FPC_VERSION)
+	@$(ECHO)  Source CPU... $(CPU_SOURCE)
+	@$(ECHO)  Target CPU... $(CPU_TARGET)
+	@$(ECHO)  Source OS.... $(OS_SOURCE)
+	@$(ECHO)  Target OS.... $(OS_TARGET)
+	@$(ECHO)  Full Source.. $(FULL_SOURCE)
+	@$(ECHO)  Full Target.. $(FULL_TARGET)
+	@$(ECHO)  SourceSuffix. $(SOURCESUFFIX)
+	@$(ECHO)  TargetSuffix. $(TARGETSUFFIX)
+	@$(ECHO)  FPC fpmake... $(FPCFPMAKE)
+	@$(ECHO)
+	@$(ECHO)  == Directory info ==
+	@$(ECHO)
+	@$(ECHO)  Required pkgs... $(REQUIRE_PACKAGES)
+	@$(ECHO)
+	@$(ECHO)  Basedir......... $(BASEDIR)
+	@$(ECHO)  FPCDir.......... $(FPCDIR)
+	@$(ECHO)  CrossBinDir..... $(CROSSBINDIR)
+	@$(ECHO)  UnitsDir........ $(UNITSDIR)
+	@$(ECHO)  PackagesDir..... $(PACKAGESDIR)
+	@$(ECHO)
+	@$(ECHO)  GCC library..... $(GCCLIBDIR)
+	@$(ECHO)  Other library... $(OTHERLIBDIR)
+	@$(ECHO)
+	@$(ECHO)  == Tools info ==
+	@$(ECHO)
+	@$(ECHO)  As........ $(AS)
+	@$(ECHO)  Ld........ $(LD)
+	@$(ECHO)  Ar........ $(AR)
+	@$(ECHO)  Rc........ $(RC)
+	@$(ECHO)
+	@$(ECHO)  Mv........ $(MVPROG)
+	@$(ECHO)  Cp........ $(CPPROG)
+	@$(ECHO)  Rm........ $(RMPROG)
+	@$(ECHO)  GInstall.. $(GINSTALL)
+	@$(ECHO)  Echo...... $(ECHO)
+	@$(ECHO)  Shell..... $(SHELL)
+	@$(ECHO)  Date...... $(DATE)
+	@$(ECHO)  FPCMake... $(FPCMAKE)
+	@$(ECHO)  PPUMove... $(PPUMOVE)
+	@$(ECHO)  Zip....... $(ZIPPROG)
+	@$(ECHO)
+	@$(ECHO)  == Object info ==
+	@$(ECHO)
+	@$(ECHO)  Target Loaders........ $(TARGET_LOADERS)
+	@$(ECHO)  Target Units.......... $(TARGET_UNITS)
+	@$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)
+	@$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)
+	@$(ECHO)  Target Dirs........... $(TARGET_DIRS)
+	@$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)
+	@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+	@$(ECHO)
+	@$(ECHO)  Clean Units......... $(CLEAN_UNITS)
+	@$(ECHO)  Clean Files......... $(CLEAN_FILES)
+	@$(ECHO)
+	@$(ECHO)  Install Units....... $(INSTALL_UNITS)
+	@$(ECHO)  Install Files....... $(INSTALL_FILES)
+	@$(ECHO)
+	@$(ECHO)  == Install info ==
+	@$(ECHO)
+	@$(ECHO)  DateStr.............. $(DATESTR)
+	@$(ECHO)  ZipName.............. $(ZIPNAME)
+	@$(ECHO)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(ECHO)  FullZipName.......... $(FULLZIPNAME)
+	@$(ECHO)  Install FPC Package.. $(INSTALL_FPCPACKAGE)
+	@$(ECHO)
+	@$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)
+	@$(ECHO)  Install binary dir... $(INSTALL_BINDIR)
+	@$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)
+	@$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)
+	@$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)
+	@$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)
+	@$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)
+	@$(ECHO)  Install data dir..... $(INSTALL_DATADIR)
+	@$(ECHO)
+	@$(ECHO)  Dist destination dir. $(DIST_DESTDIR)
+	@$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)
+	@$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+	fpc_makefile_dirs
+fpc_makefile:
+	$(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+units:
+examples:
+shared:
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+zipexampleinstall: fpc_zipexampleinstall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: units examples shared sourceinstall exampleinstall zipexampleinstall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+fpmake$(SRCEXEEXT): fpmake.pp
+	$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+	$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean:	$(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+	{ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi;  }
+else
+	$(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+	-$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+distinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif

+ 102 - 0
packages/webidl/Makefile.fpc

@@ -0,0 +1,102 @@
+#
+#   Makefile.fpc for running fpmake
+#
+
+[package]
+name=webidl
+version=3.1.1
+
+[require]
+packages=rtl rtl-objpas fpmkunit fcl-base
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+[prerules]
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+
+[rules]
+# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own.
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+
+fpmake$(SRCEXEEXT): fpmake.pp
+	$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
+# most often fail because the dependencies are cleared.
+# In case of a clean, simply do nothing
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+	$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
+# when the package is compiled using fpcmake prior to running this clean using fpmake
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean:	$(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+        { $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi;  }
+else
+        $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+	-$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+# distinstall also installs the example-sources and omits the location of the source-
+# files from the fpunits.cfg files.
+distinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif

+ 68 - 0
packages/webidl/examples/parsewebidl.lpi

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="Parse WEB IDL Application"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="parsewebidl.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="webidldefs.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="webidlparser.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="webidlscanner.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="parsewebidl"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 119 - 0
packages/webidl/examples/parsewebidl.pas

@@ -0,0 +1,119 @@
+program parsewebidl;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, SysUtils, CustApp, webidlparser, webidlscanner,webidldefs;
+
+ResourceString
+  SErrNeedInputFiles = 'Need one or more input files';
+
+type
+
+  { TParseWebIDLApplication }
+
+  TParseWebIDLApplication = class(TCustomApplication)
+  private
+    FContext : TWebIDLContext;
+    procedure ParseWebIDL(const AFileName: String);
+  protected
+    procedure DoRun; override;
+  public
+    constructor Create(TheOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure WriteHelp(Const Msg : String); virtual;
+  end;
+
+
+{ TParseWebIDLApplication }
+
+procedure TParseWebIDLApplication.ParseWebIDL(Const AFileName : String);
+
+Var
+  F : TFileStream;
+  P : TWebIDLParser;
+  S : TWebIDLScanner;
+  I : Integer;
+
+begin
+  FreeAndNil(FContext);
+  FContext:=TWebIDLContext.Create;
+  P:=Nil;
+  S:=Nil;
+  F:=TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    S:=TWebIDLScanner.Create(F);
+    P:=TWebIDLParser.Create(FContext,S);
+    P.Parse;
+    Writeln('// Contents of '+AFileName);
+    For I:=0 to FConText.Definitions.Count-1 do
+      begin
+      Writeln('// Definition ',I+1:3,': ',FConText.Definitions[i].ClassName);
+      Writeln(FConText.Definitions[i].AsString(True)+';');
+      end;
+  finally
+    F.Free;
+    P.Free;
+    S.Free;
+  end;
+end;
+
+
+procedure TParseWebIDLApplication.DoRun;
+
+var
+  FN,ErrorMsg: UTF8String;
+  NoF : TStringArray;
+
+begin
+  Terminate;
+  ErrorMsg:=CheckOptions('hi:', ['help','input']);
+  if (ErrorMsg<>'') or HasOption('h','help') then
+    begin
+    WriteHelp(ErrorMsg);
+    Exit;
+    end;
+  FN:=GetOptionValue('i','input');
+  if FN='' then
+    NoF:=GetNonOptions('hi:', ['help','input'])
+  else
+    begin
+    SetLength(NOF,1);
+    NOF[0]:=FN;
+    end;
+  if Length(Nof)=0 then
+    WriteHelp(SErrNeedInputFiles);
+  For FN in NoF do
+    ParseWebIDL(FN);
+end;
+
+constructor TParseWebIDLApplication.Create(TheOwner: TComponent);
+begin
+  inherited Create(TheOwner);
+  StopOnException:=True;
+  FContext:=TWebIDLContext.Create;
+end;
+
+destructor TParseWebIDLApplication.Destroy;
+begin
+  FreeAndNil(FContext);
+  inherited Destroy;
+end;
+
+procedure TParseWebIDLApplication.WriteHelp(Const Msg : String);
+begin
+  if Msg<>'' then
+    Writeln('Error : ',Msg);
+  writeln('Usage: ', ExeName, ' -h');
+  ExitCode:=Ord(Msg<>'');
+end;
+
+var
+  Application: TParseWebIDLApplication;
+begin
+  Application:=TParseWebIDLApplication.Create(nil);
+  Application.Title:='Parse WEB IDL Application';
+  Application.Run;
+  Application.Free;
+end.
+

+ 53 - 0
packages/webidl/fpmake.pp

@@ -0,0 +1,53 @@
+{$ifndef ALLPACKAGES}
+{$mode objfpc}{$H+}
+program fpmake;
+
+uses fpmkunit;
+
+Var
+  T : TTarget;
+  P : TPackage;
+begin
+  With Installer do
+    begin
+{$endif ALLPACKAGES}
+
+    P:=AddPackage('webidl');
+    P.ShortName:='webidl';
+{$ifdef ALLPACKAGES}
+    P.Directory:=ADirectory;
+{$endif ALLPACKAGES}
+    P.Version:='3.1.1';
+    P.Dependencies.Add('fcl-base');
+    P.Author := 'Michael Van Canneyt';
+    P.License := 'LGPL with modification, ';
+    P.HomepageURL := 'www.freepascal.org';
+    P.Email := '';
+    P.Description := 'WEB IDL parser and converter to Object Pascal classes';
+    P.NeedLibC:= false;
+    P.OSes:=AllOSes-[embedded,msdos,win16,macos,palmos];
+
+    P.SourcePath.Add('src');
+
+    T:=P.Targets.AddUnit('webidldefs.pp');
+    T.ResourceStrings := True;
+    T:=P.Targets.AddUnit('webidlscanner.pp');
+    T.ResourceStrings := True;
+    T:=P.Targets.AddUnit('webidlparser.pp');
+      with T.Dependencies do
+        begin
+          AddUnit('webidldefs');
+          AddUnit('webidlscanner');
+        end;
+    T:=P.Targets.AddUnit('webidltopas.pp');
+      with T.Dependencies do
+        begin
+          AddUnit('webidldefs');
+          AddUnit('webidlscanner');
+          AddUnit('webidlparser');
+        end;
+{$ifndef ALLPACKAGES}
+    Run;
+    end;
+end.
+{$endif ALLPACKAGES}

+ 1267 - 0
packages/webidl/src/webidldefs.pp

@@ -0,0 +1,1267 @@
+unit webidldefs;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, contnrs;
+
+Type
+
+  { TAttributeList }
+
+  TAttributeList = Class(TPersistent)
+  private
+    Fattrs: TStringList;
+    function GetAttrs(aIndex : Integer): UTF8String;
+    function GetCount: Integer;
+  Public
+    Constructor Create;
+    Destructor destroy; override;
+    Procedure Assign(aSource : TPersistent); override;
+    Procedure Add(aAttribute : UTF8String);
+    Function ToLine (ASep : String): UTF8String;
+    Function AsString (Full : Boolean = False): UTF8String;
+    Function IndexOf(Const aName : UTF8string) : Integer;
+    Property Attrs[aIndex : Integer] : UTF8String Read GetAttrs; default;
+    Property Count : Integer Read GetCount;
+  end;
+
+  { TIDLDefinition }
+  TIDLDefinition = Class;
+  TIDLTypeDefDefinition = Class;
+  TIDLDefinitionClass = Class of TIDLDefinition;
+
+  TIDLBaseObject = Class
+  Public
+    // The IDLBaseobject is owner of the newly created instance !
+    Function Add(aClass : TIDLDefinitionClass; Const AName : UTF8String) : TIDLDefinition; virtual; abstract;
+    Function AsString(Full : Boolean): UTF8String; virtual; abstract;
+  end;
+
+  TIDLDefinition = Class(TIDLBaseObject)
+  private
+    FAttributes: TAttributeList;
+    FData: TObject;
+    FName: UTF8String;
+    FParent: TIDLDefinition;
+    function GetAttributes: TAttributeList;
+    procedure SetAttributes(AValue: TAttributeList);
+  Public
+    Constructor Create(aParent : TIDLDefinition;Const aName : UTF8String); virtual;
+    Function Add(aClass : TIDLDefinitionClass; Const AName : UTF8String) : TIDLDefinition; override;
+    Destructor Destroy; override;
+    // This definition extens an existing one. It will not be in the lookup list of symbols
+    Function IsExtension : Boolean; virtual;
+    Function AsString(Full : Boolean): UTF8String; override;
+    Function HasAttributes : Boolean;
+    Function HasSimpleAttribute(Const AName : UTF8String) : Boolean;
+    Property Name : UTF8String Read FName Write FName;
+    Property Data : TObject Read FData Write FData;
+    Property Parent : TIDLDefinition Read FParent Write FParent;
+    // Attributes are owned by the definition. If you set it, your list will be freed by the definition
+    Property Attributes : TAttributeList Read GetAttributes Write SetAttributes;
+  end;
+
+  { TIDLDefinitionList }
+  TIDLDefinitionList = Class;
+
+  { TIDLDefinitionEnumerator }
+
+  TIDLDefinitionEnumerator = class
+  private
+    FList: TIDLDefinitionList;
+    FPosition: Integer;
+  public
+    constructor Create(AList: TIDLDefinitionList);
+    function GetCurrent: TIDLDefinition;
+    function MoveNext: Boolean;
+    property Current: TIDLDefinition read GetCurrent;
+  end;
+
+  TIDLDefinitionList = Class (TIDLBaseObject)
+  private
+    FList : TFPObjectList;
+    FParent: TIDLDefinition;
+    function GetCount: Integer;
+    function GetD(aIndex : Integer): TIDLDefinition;
+    function GetOwnsDefinitions: Boolean;
+  Public
+    Constructor Create(AParent : TIDLDefinition; OwnsDefinitions : Boolean = True); virtual; overload;
+    Destructor Destroy; override;
+    Procedure Clear;
+    function AsString(const aSep, aStart, aEnd, aIndent: String; aFull,
+      AppendSep: Boolean): UTF8String;
+    Function AsString(Full : Boolean): UTF8String; override;
+    Function Add(aClass : TIDLDefinitionClass; Const AName : UTF8String) : TIDLDefinition; override;
+    Function Add(aItem : TIDLDefinition) : Integer;
+    function GetEnumerator: TIDLDefinitionEnumerator;
+    Property Parent : TIDLDefinition Read FParent;
+    Property Definitions[aIndex : Integer] : TIDLDefinition Read GetD;default;
+    Property Count : Integer Read GetCount;
+    Property OwnsDefinitions : Boolean Read GetOwnsDefinitions;
+  end;
+
+  { TIDLConstDefinition }
+  TConstType = (ctFloat,ctInteger,ctBoolean,ctInfinity,ctNegInfinity,ctNan,ctNull,ctString,ctEmptyArray);
+  TIDLConstDefinition = Class(TIDLDefinition)
+  private
+    FConstType: TConstType;
+    FNull: Boolean;
+    FTypeName: UTF8String;
+    FValue: UTF8String;
+  Public
+    Function AsString(Full : Boolean): UTF8String; override;
+    Property TypeName : UTF8String Read FTypeName Write FTypeName;
+    Property Value : UTF8String Read FValue Write FValue;
+    Property AllowNull : Boolean Read FNull Write FNull;
+    Property ConstType : TConstType Read FConstType Write FConstType;
+  end;
+
+  TAttributeOption = (aoStatic,aoInherit,aoReadOnly,aoStringifier);
+  TAttributeOptions = set of TAttributeOption;
+
+  { TIDLAttributeDefinition }
+
+  TIDLAttributeDefinition = Class(TIDLDefinition)
+  private
+    FOptions : TAttributeOptions;
+    FType: TIDLTypeDefDefinition;
+    procedure SetType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    Function AsString(Full : Boolean): UTF8String; override;
+    // Owned by definition
+    Property AttributeType : TIDLTypeDefDefinition Read FType Write SetType;
+    Property Options : TAttributeOptions Read FOptions Write FOptions;
+  end;
+
+  { TIDLStructuredDefinition }
+
+  TIDLStructuredDefinition = Class(TIDLDefinition)
+  Private
+    FIsCallBack: Boolean;
+    FPartials,
+    FMembers: TIDLDefinitionList;
+    FParentName: String;
+    FPartial: Boolean;
+    function GetMember(Aindex : Integer): TIDLDefinition;
+    function GetMembers: TIDLDefinitionList;
+    function GetPartial(Aindex : Integer): TIDLStructuredDefinition;
+    function GetPartials: TIDLDefinitionList;
+  Public
+    Destructor Destroy; override;
+    Function IsExtension : Boolean; override;
+    Function GetFullMemberList(aList : TIDLDefinitionList) : Integer;
+    Function HasMembers : Boolean;
+    // Members are owned by this instance.
+    Property members : TIDLDefinitionList Read GetMembers;
+    Property Member[Aindex : Integer] : TIDLDefinition Read GetMember; default;
+    Function HasPartials : Boolean;
+    // Partials are NOT owned by this instance
+    Property Partials : TIDLDefinitionList Read GetPartials;
+    Property Partial[Aindex : Integer] : TIDLStructuredDefinition Read GetPartial;
+    Property ParentName : String Read FParentName Write FParentName;
+    // is this a partial definition?
+    Property IsPartial : Boolean Read FPartial Write FPartial;
+    // is this a callback definition?
+    Property IsCallBack : Boolean Read FIsCallBack Write FIsCallBack;
+  end;
+
+
+  { TIDLInterfaceDefinition }
+
+  TIDLInterfaceDefinition = Class(TIDLStructuredDefinition)
+  private
+    FHasSerializer: Boolean;
+    FIsInclude: Boolean;
+    FIsMixin: Boolean;
+    FParentInterface: TIDLInterfaceDefinition;
+  Public
+    Function AsString (aFull : Boolean) : UTF8String; override;
+    Property ParentInterface : TIDLInterfaceDefinition Read FParentInterface Write FParentInterface;
+    Property HasSerializer : Boolean Read FHasSerializer Write FHasSerializer;
+    // is this a mixin definition?
+    Property IsMixin : Boolean Read FIsMixin Write FIsMixin;
+    Property IsInclude : Boolean Read FIsInclude Write FIsInclude;
+  end;
+
+  { TIDLArgumentDefinition }
+
+  TIDLArgumentDefinition = Class(TIDLDefinition)
+  private
+    FDefaultValue: String;
+    FHasDefaultValue: Boolean;
+    FIsOptional: Boolean;
+    FType: TIDLTypeDefDefinition;
+    procedure SetType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    Function Clone(aType : TIDLTypeDefDefinition) : TIDLArgumentDefinition; // need
+    Function AsString(Full : Boolean) : UTF8String; override;
+    // Owned by definition
+    Property ArgumentType : TIDLTypeDefDefinition Read FType Write SetType;
+    Property IsOptional : Boolean Read FIsOptional Write FIsOptional;
+    Property HasDefaultValue : Boolean Read FHasDefaultValue Write FHasDefaultValue;
+    Property DefaultValue : String Read FDefaultValue Write FDefaultValue;
+  end;
+
+  { TIDLFunctionDefinition }
+  TFunctionOption = (foCallBack,foStatic,foStringifier,foGetter, foSetter, foDeleter, foLegacyCaller);
+  TFunctionOptions = Set of TFunctionOption;
+
+  TIDLFunctionDefinition = Class(TIDLDefinition)
+  private
+    FOptions : TFunctionOptions;
+    FReturnType: TIDLTypeDefDefinition;
+    Farguments: TIDLDefinitionList;
+    function GetA(AIndex : Integer): TIDLArgumentDefinition;
+    function GetArguments: TIDLDefinitionList;
+    procedure SetReturnType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    Function HasArguments : Boolean;
+    Function AsString(Full : Boolean) : UTF8String; override;
+    Property Arguments : TIDLDefinitionList Read GetArguments;
+    Property Argument[AIndex : Integer] : TIDLArgumentDefinition Read GetA; default;
+    // Owned by function definition.
+    Property ReturnType : TIDLTypeDefDefinition Read FReturnType Write SetReturnType;
+    // is this a callback function definition?
+    Property Options : TFunctionOptions Read FOptions Write FOptions;
+  end;
+
+  TSerializerKind = (skObject,skArray,skSingle,skFunction);
+
+  { TIDLSerializerDefinition }
+
+  TIDLSerializerDefinition = Class(TIDLDefinition)
+  private
+    FKind: TSerializerKind;
+    FIdentifiers : TAttributeList;
+    FSerializerFunction: TIDLFunctionDefinition;
+    procedure SetIdentifierList(AValue: TAttributeList);
+    Procedure SetSerializerFunction (aValue : TIDLFunctionDefinition);
+    function GetIdentifierList: TAttributeList;
+  Public
+    Destructor Destroy; override;
+    Function HasIdentifiers : Boolean;
+    Property Identifiers : TAttributeList Read GetIdentifierList Write SetIDentifierList;
+    Property SerializerFunction : TIDLFunctionDefinition Read FSerializerFunction Write SetSerializerFunction;
+    Property Kind : TSerializerKind Read FKind Write FKind;
+  end;
+
+
+  { TIDLDictionaryMemberDefinition }
+
+  TIDLDictionaryMemberDefinition = Class(TIDLDefinition)
+  private
+    FDefaultValue: TIDLConstDefinition;
+    FMemberType: TIDLTypeDefDefinition;
+    FRequired: Boolean;
+  Public
+    Destructor Destroy; override;
+    Function AsString(Full : Boolean) : UTF8String;  override;
+    Property IsRequired : Boolean Read FRequired Write FRequired;
+    // Owned  by memberdefinition
+    Property MemberType : TIDLTypeDefDefinition Read FMemberType Write FMemberType;
+    Property DefaultValue : TIDLConstDefinition Read FDefaultValue Write FDefaultValue;
+  end;
+
+  { TIDLDictionaryDefinition }
+
+  TIDLDictionaryDefinition = Class(TIDLStructuredDefinition)
+  private
+    FParentDictionary: TIDLDictionaryDefinition;
+    function GetDM(AIndex : Integer): TIDLDictionaryMemberDefinition;
+  Public
+    Function AsString(Full : Boolean) : UTF8String; override;
+    Property ParentDictionary : TIDLDictionaryDefinition Read FParentDictionary Write FParentDictionary;
+    Property DictionaryMembers[AIndex : Integer] : TIDLDictionaryMemberDefinition Read GetDM; default;
+  end;
+
+  { TIDLEnumDefinition }
+
+  TIDLEnumDefinition = Class(TIDLDefinition)
+  private
+    FValues: TStrings;
+  Public
+    Constructor Create(aParent : TIDLDefinition;Const aName : UTF8String); override;
+    Destructor Destroy; override;
+    Procedure AddValue(Const aValue : String);
+    Property Values : TStrings Read FValues;
+  end;
+
+  { TIDLTypeDefDefinition }
+
+  TIDLTypeDefDefinition = Class(TIDLDefinition)
+  private
+    FNull: Boolean;
+    FTypeName: String;
+  Public
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; virtual;
+    Function AsString(Full: Boolean): UTF8String; override;
+    Property TypeName : String Read FTypeName Write FTypeName;
+    Property AllowNull : Boolean Read FNull Write FNull;
+  end;
+  TIDLTypeDefDefinitionClass = Class of TIDLTypeDefDefinition;
+
+  { TIDLPromiseTypeDefDefinition }
+
+  TIDLPromiseTypeDefDefinition = Class(TIDLTypeDefDefinition)
+  private
+    FReturnType: TIDLTypeDefDefinition;
+    procedure SetReturnType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; override;
+    Function AsString(Full: Boolean): UTF8String; override;
+    property ReturnType : TIDLTypeDefDefinition Read FReturnType Write SetReturnType;
+  end;
+
+  { TIDLMapLikeDefinition }
+
+  { TIDLKeyValueDefinition }
+
+  TIDLKeyValueDefinition = Class(TIDLTypeDefDefinition)
+  private
+    FKeyType: TIDLTypeDefDefinition;
+    FValueType: TIDLTypeDefDefinition;
+    procedure SetKeyType(AValue: TIDLTypeDefDefinition);
+    procedure SetValueType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; override;
+    property KeyType : TIDLTypeDefDefinition Read FKeyType Write SetKeyType;
+    property ValueType : TIDLTypeDefDefinition Read FValueType Write SetValueType;
+  end;
+
+  TIDLMapLikeDefinition = Class(TIDLKeyValueDefinition)
+  private
+    FIsReadonly: Boolean;
+  Public
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; override;
+    Function AsString(Full: Boolean): UTF8String; override;
+    property IsReadonly: Boolean Read FIsReadonly Write FIsReadonly;
+  end;
+
+  { TIDLRecordDefinition }
+
+  TIDLRecordDefinition = Class(TIDLKeyValueDefinition)
+  Public
+    Function AsString(Full: Boolean): UTF8String; override;
+  end;
+
+  { TIDLSequenceTypeDefDefinition }
+
+  TIDLSequenceTypeDefDefinition = Class(TIDLTypeDefDefinition)
+  private
+    FElementType: TIDLTypeDefDefinition;
+    procedure SetElementType(AValue: TIDLTypeDefDefinition);
+  Public
+    Function AsString(Full: Boolean): UTF8String; override;
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; override;
+    Destructor Destroy; override;
+    property ElementType : TIDLTypeDefDefinition Read FElementType Write SetElementType;
+  end;
+
+  { TIDLSetlikeDefinition }
+
+  TIDLSetlikeDefinition = Class(TIDLDefinition)
+  private
+    FElementType: TIDLTypeDefDefinition;
+    FIsReadonly: Boolean;
+    procedure SetElementType(AValue: TIDLTypeDefDefinition);
+  Public
+    Function AsString(Full: Boolean): UTF8String; override;
+    Destructor Destroy; override;
+    property ElementType : TIDLTypeDefDefinition Read FElementType Write SetElementType;
+    property IsReadonly: Boolean Read FIsReadonly Write FIsReadonly;
+  end;
+
+  { TIDLUnionTypeDefDefinition }
+
+  TIDLUnionTypeDefDefinition = Class(TIDLTypeDefDefinition)
+  private
+    FUnion: TIDLDefinitionList;
+  Public
+    Constructor Create(aParent : TIDLDefinition;Const aName : UTF8String); override;
+    Destructor Destroy; override;
+    Function Clone (aParent : TIDLDefinition) : TIDLTypeDefDefinition; override;
+    Function AsString(Full: Boolean): UTF8String; override;
+    property Union : TIDLDefinitionList Read FUnion;
+  end;
+
+  { TIDLImplementsDefinition }
+
+  TIDLImplementsDefinition = Class(TIDLDefinition)
+  private
+    FImplementedInterface: UTF8String;
+  Public
+    Function IsExtension : Boolean; override;
+    Function AsString(Full: Boolean): UTF8String; override;
+    Property ImplementedInterface  : UTF8String Read FImplementedInterface Write FImplementedInterface;
+  end;
+
+  { TIDLIncludesDefinition }
+
+  TIDLIncludesDefinition = Class(TIDLDefinition)
+  private
+    FIncludedInterface : UTF8String;
+  Public
+    Function IsExtension : Boolean; override;
+    Function AsString(Full: Boolean): UTF8String; override;
+    Property IncludedInterface  : UTF8String Read FIncludedInterface Write FIncludedInterface;
+  end;
+
+  { TIDLIterableDefinition }
+
+  TIDLIterableDefinition = Class(TIDLDefinition)
+  private
+    FValueType: TIDLTypeDefDefinition;
+    FKeyType: TIDLTypeDefDefinition;
+    procedure SetKeyType(AValue: TIDLTypeDefDefinition);
+    procedure SetValueType(AValue: TIDLTypeDefDefinition);
+  Public
+    Destructor Destroy; override;
+    property ValueType : TIDLTypeDefDefinition Read FValueType Write SetValueType;
+    property KeyType : TIDLTypeDefDefinition Read FKeyType Write SetKeyType;
+  end;
+
+
+implementation
+
+{ TIDLSetlikeDefinition }
+
+procedure TIDLSetlikeDefinition.SetElementType(
+  AValue: TIDLTypeDefDefinition);
+begin
+  if FElementType=AValue then Exit;
+  FreeAndNil(FElementType);
+  FElementType:=AValue;
+  if Assigned(FElementType) then
+    FElementType.Parent:=Self
+end;
+
+function TIDLSetlikeDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:='setlike <'+ElementType.TypeName+'>';
+  if IsReadonly then
+    Result:='readonly '+Result;
+  if full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+destructor TIDLSetlikeDefinition.Destroy;
+begin
+  FreeAndNil(FElementType);
+  inherited Destroy;
+end;
+
+{ TIDLRecordDefinition }
+
+function TIDLRecordDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:='record <'+KeyType.AsString(False)+','+ValueType.AsString(False)+'>';
+  if AllowNull then
+    Result:=Result+'?';
+  if Full then
+      begin
+      Result:='typedef '+Result;
+      if HasAttributes then
+        Result:=Attributes.AsString(True)+' '+Result;
+      end;
+end;
+
+{ TIDLMapLikeDefinition }
+
+procedure TIDLKeyValueDefinition.SetKeyType(AValue: TIDLTypeDefDefinition);
+begin
+  if FKeyType=AValue then Exit;
+  FreeAndNil(FKeyType);
+  FKeyType:=AValue;
+  if Assigned(FKeyType) then
+    FKeyType.Parent:=Self
+end;
+
+procedure TIDLKeyValueDefinition.SetValueType(AValue: TIDLTypeDefDefinition);
+begin
+  if FValueType=AValue then Exit;
+  FreeAndNil(FValueType);
+  FValueType:=AValue;
+  if Assigned(FValueType) then
+    FValueType.Parent:=Self
+end;
+
+
+destructor TIDLKeyValueDefinition.Destroy;
+begin
+  FreeAndNil(FKeyType);
+  FreeAndNil(FValueType);
+  inherited Destroy;
+end;
+
+function TIDLKeyValueDefinition.Clone(aParent: TIDLDefinition
+  ): TIDLTypeDefDefinition;
+begin
+  Result:=inherited Clone(aParent);
+  if Assigned(KeyType) then
+    TIDLKeyValueDefinition(Result).KeyType:=KeyType.Clone(Result);
+  if Assigned(ValueType) then
+    TIDLKeyValueDefinition(Result).ValueType:=ValueType.Clone(Result);
+end;
+
+function TIDLMapLikeDefinition.Clone(aParent: TIDLDefinition
+  ): TIDLTypeDefDefinition;
+begin
+  Result:=inherited Clone(aParent);
+  TIDLMapLikeDefinition(Result).IsReadonly:=IsReadonly;
+end;
+
+function TIDLMapLikeDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:='maplike <'+KeyType.AsString(False)+','+ValueType.AsString(False)+'>';
+  if IsReadonly then
+    Result:='readonly '+Result;
+  if Full and HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+{ TIDLIncludesDefinition }
+
+function TIDLIncludesDefinition.IsExtension: Boolean;
+begin
+  Result:=True;
+end;
+
+function TIDLIncludesDefinition.AsString(Full: Boolean): UTF8String;
+
+begin
+  Result:=Name+' includes '+IncludedInterface;
+  If Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+{ TIDLDefinitionEnumerator }
+
+constructor TIDLDefinitionEnumerator.Create(AList: TIDLDefinitionList);
+begin
+  FList:=AList;
+  FPosition:=-1;
+end;
+
+function TIDLDefinitionEnumerator.GetCurrent: TIDLDefinition;
+begin
+  Result := FList[FPosition];
+end;
+
+function TIDLDefinitionEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FList.Count;
+end;
+
+{ TIDLInterfaceDefinition }
+
+function TIDLInterfaceDefinition.AsString(aFull: Boolean): UTF8String;
+begin
+  Result:='interface '+Name;
+  if IsPartial then
+    Result:='partial '+Result
+  else if IsCallBack then
+    Result:='callback '+Result;
+  if ParentName<>'' then
+    Result:=Result+' : '+ParentName;
+  if Not HasMembers then
+    Result:=Result+' {'+sLineBreak+'}'
+  else
+    Result:=Result+' '+members.AsString(true);
+
+  if aFull and HasAttributes then
+    Result:=Attributes.AsString(true)+' '+Result;
+end;
+
+{ TIDLTypeDefDefinition }
+
+function TIDLTypeDefDefinition.Clone(aParent: TIDLDefinition): TIDLTypeDefDefinition;
+begin
+  Result:=TIDLTypeDefDefinitionClass(Self.ClassType).Create(aParent,Name);
+  Result.TypeName:=Self.TypeName;
+end;
+
+function TIDLTypeDefDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=TypeName;
+  if AllowNull then
+    Result:=Result+'?';
+  If Full then
+    begin
+    Result:='typedef '+Result+' '+Name;
+    if HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+    end;
+end;
+
+{ TIDLImplementsDefinition }
+
+function TIDLImplementsDefinition.IsExtension: Boolean;
+begin
+  Result:=True;
+end;
+
+function TIDLImplementsDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=Name+' implements '+ImplementedInterface;
+  If Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+{ TIDLConstDefinition }
+
+function TIDLConstDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=TypeName+' '+Name+' '+Value;
+  If Full then
+    begin
+    Result:='const '+Result;
+    if HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+    end;
+end;
+
+{ TIDLSerializerDefinition }
+
+procedure TIDLSerializerDefinition.SetSerializerFunction(aValue: TIDLFunctionDefinition);
+begin
+  if (FSerializerFunction=aValue) then exit;
+  FreeAndNil(FSerializerFunction);
+  FSerializerFunction:=aValue;
+  if AValue<>Nil then
+    Kind:=skFunction;
+end;
+
+procedure TIDLSerializerDefinition.SetIdentifierList(AValue: TAttributeList);
+begin
+  If (FIdentifiers=AValue) then
+    exit;
+  FreeAndNil(FAttributes);
+  FAttributes:=AValue;
+end;
+
+function TIDLSerializerDefinition.GetIdentifierList: TAttributeList;
+
+begin
+  If FIdentifiers=Nil then
+    FIdentifiers:=TAttributeList.Create;
+  Result:=FIdentifiers;
+end;
+
+destructor TIDLSerializerDefinition.Destroy;
+begin
+  FreeAndNil(FIdentifiers);
+  FreeAndNil(FSerializerFunction);
+  inherited Destroy;
+end;
+
+function TIDLSerializerDefinition.HasIdentifiers: Boolean;
+
+begin
+  Result:=Assigned(FIdentifiers) and (FIdentifiers.Count>0);
+end;
+
+{ TIDLIterableDefinition }
+
+procedure TIDLIterableDefinition.SetKeyType(AValue: TIDLTypeDefDefinition);
+begin
+  if (AValue=FKeyType) then exit;
+  FreeAndNil(FKeyType);
+  FKeyType:=AValue;
+end;
+
+procedure TIDLIterableDefinition.SetValueType(AValue: TIDLTypeDefDefinition);
+begin
+  if (AValue=FValueType) then exit;
+  FreeAndNil(FValueType);
+  FValueType:=AValue;
+end;
+
+destructor TIDLIterableDefinition.Destroy;
+begin
+  ValueType:=Nil;
+  KeyType:=Nil;
+  inherited Destroy;
+end;
+
+{ TIDLAttributeDefinition }
+
+procedure TIDLAttributeDefinition.SetType(AValue: TIDLTypeDefDefinition);
+begin
+  If (AValue=FType) then exit;
+  FreeAndNil(FType);
+  FType:=AValue;
+end;
+
+destructor TIDLAttributeDefinition.Destroy;
+begin
+  AttributeType:=Nil;
+  inherited Destroy;
+end;
+
+function TIDLAttributeDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=Name;
+  if Assigned(AttributeType) then
+    Result:=AttributeType.TypeName+' '+Result;
+  if Full then
+    begin
+    Result:='attribute '+Result;
+    if (aoReadonly in Options) then
+      Result:='readonly '+Result;
+    if (aoInherit in Options) then
+      Result:='inherit '+Result;
+    if (aoStatic in Options) then
+      Result:='static '+Result;
+    if (aoStringifier in Options) then
+      Result:='stringifier '+Result;
+    if HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+    end;
+end;
+
+{ TIDLArgumentDefinition }
+
+procedure TIDLArgumentDefinition.SetType(AValue: TIDLTypeDefDefinition);
+begin
+  if FType=AValue then Exit;
+  FreeAndNil(FType);
+  FType:=AValue;
+end;
+
+destructor TIDLArgumentDefinition.Destroy;
+begin
+  ArgumentType:=Nil;
+  inherited Destroy;
+end;
+
+function TIDLArgumentDefinition.Clone(aType: TIDLTypeDefDefinition): TIDLArgumentDefinition;
+
+begin
+  Result:=TIDLArgumentDefinition.Create(Nil,Self.Name);
+  if (AType=Nil) and Assigned(ArgumentType) then
+    begin
+    AType:=ArgumentType.Clone(Result);
+    AType.TypeName:=Self.ArgumentType.TypeName;
+    end;
+  Result.ArgumentType:=aType;
+end;
+
+function TIDLArgumentDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=ArgumentType.AsString(False)+' '+Name;
+  If IsOptional then
+    Result:='optional '+Result;
+  if HasDefaultValue then
+    if DefaultValue='' then
+      Result:=Result+' = ""'
+    else
+      Result:=Result+' = '+DefaultValue;
+  if Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+{ TIDLFunctionDefinition }
+
+procedure TIDLFunctionDefinition.SetReturnType(AValue: TIDLTypeDefDefinition);
+begin
+  if FReturnType=AValue then Exit;
+  FreeAndNil(FReturnType);
+  FReturnType:=AValue;
+end;
+
+function TIDLFunctionDefinition.GetArguments: TIDLDefinitionList;
+begin
+  if FArguments=nil then
+    Farguments:=TIDLDefinitionList.Create(Self);
+  Result:=Farguments;
+end;
+
+function TIDLFunctionDefinition.GetA(AIndex : Integer): TIDLArgumentDefinition;
+begin
+  Result:=Arguments[AIndex] as TIDLArgumentDefinition;
+end;
+
+destructor TIDLFunctionDefinition.Destroy;
+begin
+  FreeAndNil(FArguments);
+  ReturnType:=nil;
+  inherited Destroy;
+end;
+
+function TIDLFunctionDefinition.HasArguments: Boolean;
+begin
+  Result:=Assigned(FArguments) and (FArguments.Count>0);
+end;
+
+function TIDLFunctionDefinition.AsString(Full: Boolean): UTF8String;
+
+  Procedure MaybeAdd(O : TFunctionOption; S : String);
+
+  begin
+    if O in options then
+      Result:=S+' '+Result;
+  end;
+
+begin
+  if foCallBack in Options then
+    Result:=Name+' = '+ReturnType.AsString(False)
+  else
+    Result:=ReturnType.AsString(False)+' '+Name;
+  Result:=Result+' '+Arguments.AsString(', ','(',')','',True,False);
+  MaybeAdd(foCallback,'callback');
+  MaybeAdd(foStatic,'static');
+  MaybeAdd(foGetter,'getter');
+  MaybeAdd(foSetter,'setter');
+  MaybeAdd(foDeleter,'deleter');
+  MaybeAdd(foStringifier,'stringifier');
+  if Full and HasAttributes then
+    Result:=Attributes.AsString(Full)+' '+Result;
+end;
+
+{ TIDLDictionaryDefinition }
+
+function TIDLDictionaryDefinition.GetDM(AIndex : Integer
+  ): TIDLDictionaryMemberDefinition;
+begin
+  Result:=Members[aIndex] as TIDLDictionaryMemberDefinition;
+end;
+
+function TIDLDictionaryDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:='dictionary '+Name;
+  if (ParentName<>'') then
+    Result:=Result+' : '+ParentName;
+  if Not HasMembers then
+    Result:=Result+' {'+sLineBreak+'}'
+  else
+    Result:=Result+' '+members.AsString(true);
+  if Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result
+end;
+
+{ TIDLDictionaryMemberDefinition }
+
+destructor TIDLDictionaryMemberDefinition.Destroy;
+begin
+  FreeAndNil(FMemberType);
+  FreeAndNil(FDefaultValue);
+  inherited Destroy;
+end;
+
+function TIDLDictionaryMemberDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=MemberType.AsString(False)+' '+Name;
+  if IsRequired then
+    Result:='required '+Result;
+  If DefaultValue<>Nil then
+    Result:=Result+' = '+DefaultValue.Value;
+  if Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+{ TIDLSequenceTypeDefDefinition }
+
+procedure TIDLSequenceTypeDefDefinition.SetElementType(
+  AValue: TIDLTypeDefDefinition);
+begin
+  if FElementType=AValue then Exit;
+  FreeAndNil(FElementType);
+  FElementType:=AValue;
+  if Assigned(FElementType) then
+    FElementType.Parent:=Self
+end;
+
+function TIDLSequenceTypeDefDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  if Full then
+    Result:='typedef sequence <'+ElementType.TypeName+'> '+Name
+  else
+    Result:='sequence <'+ElementType.TypeName+'>';
+  if full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+function TIDLSequenceTypeDefDefinition.Clone(aParent: TIDLDefinition
+  ): TIDLTypeDefDefinition;
+begin
+  Result:=inherited Clone(aParent);
+  if Assigned(ElementType) then
+    TIDLSequenceTypeDefDefinition(Result).ElementType:=ElementType.Clone(Result);
+end;
+
+destructor TIDLSequenceTypeDefDefinition.Destroy;
+begin
+  ElementType:=nil;
+  inherited Destroy;
+end;
+
+{ TIDLPromiseTypeDefDefinition }
+
+procedure TIDLPromiseTypeDefDefinition.SetReturnType(AValue: TIDLTypeDefDefinition);
+begin
+  if FReturnType=AValue then Exit;
+  FreeAndNil(FReturnType);
+  FReturnType:=AValue;
+end;
+
+destructor TIDLPromiseTypeDefDefinition.Destroy;
+begin
+  ReturnType:=Nil;
+  inherited Destroy;
+end;
+
+function TIDLPromiseTypeDefDefinition.Clone(aParent: TIDLDefinition
+  ): TIDLTypeDefDefinition;
+begin
+  Result:=inherited Clone(aParent);
+  if Assigned(ReturnType) then
+    TIDLPromiseTypeDefDefinition(Result).ReturnType:=ReturnType.Clone(Result);
+end;
+
+function TIDLPromiseTypeDefDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:='promise <'+ReturnType.AsString(False)+'>';
+  if AllowNull then
+    Result:=Result+'?';
+  if Full then
+    begin
+    Result:='typedef '+Result+' '+Name;
+    If HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+    end;
+end;
+
+{ TIDLUnionTypeDefDefinition }
+
+constructor TIDLUnionTypeDefDefinition.Create(aParent: TIDLDefinition;
+  const aName: UTF8String);
+begin
+  inherited Create(aParent, aName);
+  FUnion:=TIDLDefinitionList.Create(Self,True);
+end;
+
+destructor TIDLUnionTypeDefDefinition.Destroy;
+begin
+  FreeAndNil(FUnion);
+  inherited Destroy;
+end;
+
+function TIDLUnionTypeDefDefinition.Clone(aParent: TIDLDefinition
+  ): TIDLTypeDefDefinition;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  Result:=inherited Clone(aParent);
+  For D in Union do
+    if D is TIDLTypeDefDefinition then
+      TIDLUnionTypeDefDefinition(Result).Union.Add(TIDLTypeDefDefinition(D).Clone(Result));
+end;
+
+function TIDLUnionTypeDefDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=Union.AsString(' or ','(',')','',false,False);
+  if Full  then
+    begin
+    Result:='typedef '+Result+' '+Name;
+    if HasAttributes then
+      Result:=Attributes.AsString(True)+' '+Result;
+    end;
+end;
+
+{ TIDLEnumDefinition }
+
+constructor TIDLEnumDefinition.Create(aParent: TIDLDefinition;
+  const aName: UTF8String);
+begin
+  inherited Create(aParent, aName);
+  FValues:=TStringList.Create;
+end;
+
+destructor TIDLEnumDefinition.Destroy;
+begin
+  FreeAndNil(FValues);
+  inherited Destroy;
+end;
+
+procedure TIDLEnumDefinition.AddValue(const aValue: String);
+begin
+  FValues.Add(aValue);
+end;
+
+{ TIDLInterfaceDefinition }
+
+function TIDLStructuredDefinition.GetMembers: TIDLDefinitionList;
+begin
+  if Not Assigned(FMembers) then
+    FMembers:=TIDLDefinitionList.Create(Self);
+  Result:=FMembers;
+end;
+
+function TIDLStructuredDefinition.GetMember(Aindex : Integer): TIDLDefinition;
+begin
+  Result:=Members[AIndex] as TIDLDefinition;
+end;
+
+function TIDLStructuredDefinition.GetPartial(Aindex : Integer
+  ): TIDLStructuredDefinition;
+begin
+  Result:=Partials[AIndex] as TIDLStructuredDefinition;
+end;
+
+function TIDLStructuredDefinition.GetPartials: TIDLDefinitionList;
+begin
+  if Not Assigned(FPartials) then
+    FPartials:=TIDLDefinitionList.Create(Self,False);
+  Result:=FPartials;
+end;
+
+destructor TIDLStructuredDefinition.Destroy;
+begin
+  FreeAndNil(FMembers);
+  FreeAndNil(FPartials);
+  inherited Destroy;
+end;
+
+function TIDLStructuredDefinition.IsExtension: Boolean;
+begin
+  Result:=IsPartial;
+end;
+
+function TIDLStructuredDefinition.GetFullMemberList(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  Result:=aList.Count;
+  For D in Members do
+    aList.Add(D);
+  Result:=aList.Count-Result;
+  For D in Partials do
+    Result:=Result+(D as TIDLStructuredDefinition).GetFullMemberList(aList);
+end;
+
+function TIDLStructuredDefinition.HasMembers: Boolean;
+begin
+  Result:=Assigned(FMembers) and (FMembers.Count>0)
+end;
+
+function TIDLStructuredDefinition.HasPartials: Boolean;
+begin
+  Result:=Assigned(FPartials) and (FPartials.Count>0);
+end;
+
+{ TAttributeList }
+
+function TAttributeList.GetAttrs(aIndex : Integer): UTF8String;
+begin
+  Result:=FAttrs[aIndex];
+end;
+
+function TAttributeList.GetCount: Integer;
+begin
+  Result:=FAttrs.Count;
+end;
+
+constructor TAttributeList.Create;
+begin
+  Fattrs:=TStringList.Create;
+end;
+
+destructor TAttributeList.destroy;
+begin
+  FreeAndNil(Fattrs);
+  inherited;
+end;
+
+procedure TAttributeList.Assign(aSource: TPersistent);
+begin
+  If aSource is TAttributeList then
+    Fattrs.Assign(TAttributeList(aSource).Fattrs);
+end;
+
+procedure TAttributeList.Add(aAttribute: UTF8String);
+begin
+  FAttrs.Add(aAttribute);
+end;
+
+function TAttributeList.ToLine(ASep: String): UTF8String;
+
+Var
+  I : Integer;
+
+begin
+  Result:='';
+  For I:=0 to Count-1 do
+    begin
+    if (Result<>'') then
+      Result:=Result+ASep;
+    Result:=Result+Attrs[I];
+    end;
+end;
+
+function TAttributeList.AsString(Full: Boolean): UTF8String;
+
+begin
+  Result:=ToLine(',');
+  if Full and (Result<>'') then
+    Result:='['+Result+']';
+end;
+
+function TAttributeList.IndexOf(const aName: UTF8string): Integer;
+begin
+  Result:=Fattrs.IndexOf(aName);
+end;
+
+{ TIDLDefinitionList }
+
+function TIDLDefinitionList.GetD(aIndex : Integer): TIDLDefinition;
+begin
+  Result:= FList[aIndex] as TIDLDefinition;
+end;
+
+function TIDLDefinitionList.GetOwnsDefinitions: Boolean;
+begin
+  Result:=FList.OwnsObjects;
+end;
+
+function TIDLDefinitionList.GetCount: Integer;
+begin
+  Result:=FList.Count;
+end;
+
+constructor TIDLDefinitionList.Create(AParent: TIDLDefinition; OwnsDefinitions : Boolean = True);
+begin
+  FParent:=AParent;
+  FList:=TFPObjectList.Create(OwnsDefinitions);
+end;
+
+destructor TIDLDefinitionList.Destroy;
+begin
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+procedure TIDLDefinitionList.Clear;
+begin
+  FList.Clear;
+end;
+
+function TIDLDefinitionList.AsString(const aSep, aStart, aEnd, aIndent : String; aFull,AppendSep : Boolean): UTF8String;
+
+Var
+  I : Integer;
+
+begin
+  Result:=aStart;
+  if Count>0 then
+    begin
+    Result:=Result+aIndent+Definitions[0].AsString(aFull);
+    For I:=1 to Count-1 do
+      begin
+      Result:=Result+aSep;
+      Result:=Result+aIndent+Definitions[I].AsString(aFull);
+      end;
+    If AppendSep and (Count>0) then
+      Result:=Result+aSep;
+    end;
+  Result:=Result+aEnd;
+end;
+
+function TIDLDefinitionList.AsString(Full: Boolean): UTF8String;
+
+begin
+  if Full then
+    Result:=AsString(';'+sLineBreak,'{'+sLineBreak,'}','  ',Full,True)
+  else
+    Result:=AsString(';'+sLineBreak,'','','',Full,true);
+end;
+
+function TIDLDefinitionList.Add(aClass: TIDLDefinitionClass;
+  const AName: UTF8String): TIDLDefinition;
+begin
+  Result:=aClass.Create(FParent,aName);
+  FList.Add(Result);
+end;
+
+function TIDLDefinitionList.Add(aItem: TIDLDefinition): Integer;
+begin
+  Result:=FList.Add(aItem);
+  if (FParent<>nil) then
+    aItem.Parent:=FParent;
+end;
+
+function TIDLDefinitionList.GetEnumerator: TIDLDefinitionEnumerator;
+begin
+  Result:=TIDLDefinitionEnumerator.Create(Self);
+end;
+
+{ TIDLDefinition }
+
+procedure TIDLDefinition.SetAttributes(AValue: TAttributeList);
+begin
+  if FAttributes=AValue then Exit;
+  FreeAndNil(FAttributes);
+  FAttributes:=AValue;
+end;
+
+function TIDLDefinition.GetAttributes: TAttributeList;
+begin
+  if FAttributes=Nil then
+    Fattributes:=TAttributeList.Create;
+  Result:=Fattributes;
+end;
+
+constructor TIDLDefinition.Create(aParent : TIDLDefinition; const aName: UTF8String);
+begin
+  FName:=AName;
+  FParent:=AParent;
+end;
+
+function TIDLDefinition.Add(aClass: TIDLDefinitionClass; const AName: UTF8String
+  ): TIDLDefinition;
+begin
+  Result:=aClass.Create(Self,AName);
+end;
+
+destructor TIDLDefinition.Destroy;
+begin
+  FreeAndNil(FAttributes);
+  Inherited;
+end;
+
+function TIDLDefinition.IsExtension: Boolean;
+begin
+  Result:=False;
+end;
+
+function TIDLDefinition.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=Name;
+  if Full and HasAttributes then
+    Result:=Attributes.AsString(True)+' '+Result;
+end;
+
+function TIDLDefinition.HasAttributes: Boolean;
+begin
+  Result:=Assigned(FAttributes) and (FAttributes.Count>0)
+end;
+
+function TIDLDefinition.HasSimpleAttribute(const AName : UTF8String): Boolean;
+begin
+  Result:=HasAttributes and (FAttributes.IndexOf(aName)<>-1);
+end;
+
+end.
+

+ 1431 - 0
packages/webidl/src/webidlparser.pp

@@ -0,0 +1,1431 @@
+unit webidlparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Contnrs, webidlscanner, webidldefs;
+
+Type
+  EWebIDLParser = Class(Exception);
+
+  { TWebIDLContext }
+  TWebIDLVersion = webidlscanner.TWebIDLVersion;
+
+  TWebIDLContext = Class (TIDLBaseObject)
+  private
+    FDefinitions: TIDLDefinitionList;
+    FHash : TFPObjectHashTable;
+  Protected
+    function FindDictionary(aName: UTF8String): TIDLDictionaryDefinition; virtual;
+    function FindInterface(aName: UTF8String): TIDLInterfaceDefinition; virtual;
+    procedure AppendDictionaryPartials; virtual;
+    procedure AppendInterfacePartials; virtual;
+    procedure AppendInterfaceIncludes; virtual;
+    procedure ResolveParentTypes; virtual;
+  Public
+    Constructor Create(OwnsDefinitions : Boolean = True);
+    Destructor Destroy; override;
+    Procedure AppendPartials; virtual;
+    Procedure AppendIncludes; virtual;
+    Procedure ResolveTypes; virtual;
+    function IndexOfDefinition(const AName: String): Integer;
+    Function FindDefinition(const AName : String) : TIDLDefinition;
+    Function AsString(Full: Boolean): UTF8String; override;
+    Function Add(aClass : TIDLDefinitionClass; const AName : UTF8String) : TIDLDefinition; override;
+    Function Add(aParent : TIDLBaseObject; aClass : TIDLDefinitionClass; const AName : UTF8String) : TIDLDefinition; virtual;
+    Property Definitions : TIDLDefinitionList Read FDefinitions;
+  end;
+
+  { TWebIDLParser }
+
+  TWebIDLParser = Class
+  private
+    FContext: TWebIDLContext;
+    FScanner: TWebIDLScanner;
+    FOwnsScanner : Boolean;
+    FVersion: TWebIDLVersion;
+    procedure SetVersion(AValue: TWebIDLVersion);
+  Protected
+    function GetErrorPos: String; virtual;
+    // Error mechanism
+    Procedure Error(Msg : String);
+    Procedure Error(Fmt : String; Args : Array of const);
+    // Scanner access. Only use this, do not use scanner directly.
+    function CurrentToken: TIDLToken; virtual;
+    function GetToken: TIDLToken; virtual;
+    function CurrentTokenString: UTF8String;
+    // Get next token, see if it is valid. Raise exception if not.
+    procedure MaybeFree(Result: TIDLDefinition; aParent: TIDLBaseObject);
+    Procedure CheckCurrentToken(aToken: TIDLToken);
+    Procedure CheckCurrentTokens(aTokens: TIDLTokens);
+    function ExpectToken(aToken: TIDLToken): TIDLToken;
+    function ExpectTokens(aTokens: TIDLTokens): TIDLToken;
+    // Attributes
+    function ParseAttributes: TAttributeList;
+    procedure ParseAttributes(aList: TAttributeList; aTerminator: TIDLToken; ForSerializer: Boolean=False); virtual;
+    // Definitions
+    // Type is a type without name of the type
+    function ParseAttribute(aParent: TIDLBaseObject): TIDLAttributeDefinition; virtual;
+    function ParseArgument(aParent: TIDLBaseObject): TIDLArgumentDefinition; virtual;
+    procedure ParseArguments(aParent: TIDLBaseObject);virtual;
+    function ParseFunction(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
+    function ParseType(aParent: TIDLBaseObject; FetchFirst: Boolean=True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition; virtual;
+    function ParseDictionaryMember(aParent: TIDLBaseObject): TIDLDictionaryMemberDefinition; virtual;
+    function CompleteSimpleType(tk: TIDLToken; Var S: UTF8String; out IsNull: Boolean): TIDLToken; virtual;
+    function ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition; virtual;
+    function ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition; virtual;
+    function ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition; virtual;
+    function ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition; virtual;
+    function ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition; virtual;
+    function ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition; virtual;
+    function ParseConstValue(out aValue: UTF8String; aExtended: Boolean): TConstType; virtual;
+    function ParseConst(aParent: TIDLBaseObject ): TIDLConstDefinition; virtual;
+    function ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition; virtual;
+    function ParseStringifier(aParent : TIDLBaseObject): TIDLDefinition; virtual;
+    function ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition; virtual;
+    function ParseSerializer(aParent: TIDLBaseObject): TIDLSerializerDefinition; virtual;
+    function ParseStatic(aParent: TIDLBaseObject): TIDLDefinition;virtual;
+    function ParseIterable(aParent : TIDLBaseObject): TIDLIterableDefinition; virtual;
+    function ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition; virtual;
+    function ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition; virtual;
+    function ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition; virtual;
+    function ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition; virtual;
+    function ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition; virtual;
+    function ParseImplements(aParent : TIDLBaseObject): TIDLImplementsDefinition; virtual;
+    function ParseIncludes(aParent : TIDLBaseObject): TIDLIncludesDefinition; virtual;
+    function ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition; virtual;
+    procedure ParseDefinitions(aParent : TIDLBaseObject); virtual;
+  Public
+    Constructor Create(aContext : TWEBIDLContext; aScanner : TWebIDLScanner); overload;
+    Constructor Create(aContext : TWEBIDLContext; aSource : UTF8String);overload;
+    Destructor Destroy; override;
+    Procedure Parse;
+    Property Scanner : TWebIDLScanner Read FScanner;
+    Property Context : TWebIDLContext Read FContext;
+    Property Version : TWebIDLVersion Read FVersion Write SetVersion;
+  end;
+
+implementation
+
+Resourcestring
+  SErrInvalidToken = 'Invalid token: expected "%s", got: "%s"';
+  SErrInvalidTokenList = 'Invalid token: expected one of "%s", got: "%s"';
+  SExpectedOther = 'Unexpected token in attribute list: "%s".';
+  SErrUnExpectedToken = 'Unexpected token : "%s"';
+  SErrTypeNotAllowed = 'Type "%s" not allowed in "%s" type.';
+  SErrDictionaryNotFound = 'Dictionary %s not found';
+  SErrInterfaceNotFound = 'Interface %s not found';
+
+{ TWebIDLParser }
+
+constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aScanner: TWebIDLScanner);
+begin
+  FScanner:=aScanner;
+  FContext:=aContext;
+end;
+
+constructor TWebIDLParser.Create(aContext: TWEBIDLContext; aSource: UTF8String);
+begin
+  FOwnsScanner:=True;
+  Create(aContext,TWebIDLScanner.Create(aSource));
+end;
+
+destructor TWebIDLParser.Destroy;
+begin
+  if FOwnsScanner then
+    FreeAndNil(FScanner);
+  inherited Destroy;
+end;
+
+function TWebIDLParser.CurrentToken: TIDLToken;
+
+begin
+  Result:=FScanner.CurToken;
+end;
+
+function TWebIDLParser.GetToken: TIDLToken;
+
+begin
+  Repeat
+    Result:=FScanner.FetchToken;
+  until Not (Result in [tkWhitespace,tkComment]);
+end;
+
+procedure TWebIDLParser.SetVersion(AValue: TWebIDLVersion);
+begin
+  if FVersion=AValue then Exit;
+  FVersion:=AValue;
+  if Assigned(Scanner) then
+    FScanner.Version:=FVersion;
+end;
+
+function TWebIDLParser.GetErrorPos: String;
+
+begin
+  Result:='';
+  If Assigned(FScanner) then
+    Result:=Format('Error in IDL at line %d, pos %d: ',[FScanner.CurRow,FScanner.CurColumn]);
+end;
+
+procedure TWebIDLParser.Error(Msg: String);
+
+begin
+  Raise EWebIDLParser.Create(GetErrorPos+Msg);
+end;
+
+procedure TWebIDLParser.Error(Fmt: String; Args: array of const);
+begin
+  Raise EWebIDLParser.Create(GetErrorPos+Format(Fmt,Args));
+end;
+
+function TWebIDLParser.CurrentTokenString: UTF8String;
+
+begin
+  Result:=Fscanner.CurTokenString;
+end;
+
+procedure TWebIDLParser.CheckCurrentToken(aToken: TIDLToken);
+begin
+  if (aToken<>CurrentToken) then
+    Error(SErrInvalidToken,[GetTokenName(aToken),CurrenttokenString]);
+end;
+
+procedure TWebIDLParser.CheckCurrentTokens(aTokens: TIDLTokens);
+begin
+  if Not (CurrentToken in aTokens) then
+    Error(SErrInvalidTokenList,[GetTokenNames(aTokens),CurrentTokenString]);
+end;
+
+function TWebIDLParser.ExpectToken(aToken: TIDLToken): TIDLToken;
+
+begin
+  Result:=GetToken;
+  CheckCurrentToken(aToken);
+end;
+
+function TWebIDLParser.ExpectTokens(aTokens: TIDLTokens): TIDLToken;
+
+begin
+  Result:=GetToken;
+  CheckCurrentTokens(aTokens);
+end;
+
+// We're at the [,{,( token when we enter here
+// On exit, we're on the terminator token.
+
+procedure TWebIDLParser.ParseAttributes(aList: TAttributeList; aTerminator: TIDLToken; ForSerializer : Boolean = False);
+
+  Function AddSub(aTerm : TIDLTOken) : String;
+
+  Var
+    L : TAttributeList;
+
+  begin
+    Result:=CurrentTokenString;
+    L:=TAttributeList.Create;
+    try
+      ParseAttributes(L,aTerm,ForSerializer);
+      Result:=Trim(Result+L.ToLine(',')+CurrentTokenString);
+    finally
+      L.Free;
+    end;
+  end;
+
+  Procedure AddToCurrent(Var Current : UTF8String; Const aTerm : String);
+
+  begin
+    if (Current<>'') then
+      Current:=Current+' ';
+    Current:=Current+aterm;
+  end;
+
+  Procedure AddToList(Var aTerm : UTF8String);
+
+  begin
+    ATerm:=Trim(ATerm);
+    if (ATerm<>'') then
+      begin
+      AList.Add(aTerm);
+      aTerm:='';
+      end;
+  end;
+
+Const
+  OtherTokens = [tkNumberInteger,tkNumberFloat,tkIdentifier,tkString, {tkOther, tkMinus,}tkNegInfinity,
+                 tkDot,tkEllipsis,tkColon,tkSemicolon,tkLess,tkEqual,tkLarger,tkQuestionmark,tkByteString,
+                 tkDOMString,tkInfinity,tkNan,tkUSVString,tkAny,tkboolean,tkbyte,tkDouble,tkFalse,tkFloat,tkComma,
+                 tkLong,tkNull,tkObject,tkOctet,tkOr,tkOptional,tkSequence,tkShort,tkTrue,tkUnsigned,tkVoid];
+
+Var
+  tk : TIDLToken;
+  ValidTokens : TIDLTokens;
+  S : UTF8String;
+  WasSub : Boolean;
+
+begin
+  ValidTokens:=OtherTokens;
+  if ForSerializer then
+    ValidTokens:=ValidTokens + [tkInherit,tkGetter];
+  tk:=GetToken;
+  S:='';
+  While Not (tk=aTerminator) do
+    begin
+    WasSub:=True;
+    Case tk of
+      tkEOF :
+        CheckCurrentToken(aTerminator);
+      tkSquaredBraceOpen:
+        S:=S+AddSub(tkSquaredBraceClose);
+      tkBracketOpen:
+        S:=S+AddSub(tkBracketClose);
+      tkCurlyBraceOpen :
+        S:=S+AddSub(tkCurlyBraceClose);
+      else
+        WasSub:=False;
+        // Check
+        While (tk in ValidTokens) do
+          begin
+          AddToCurrent(S,CurrentTokenString);
+          if tk=tkComma then
+            AddToList(S);
+          tk:=GetToken;
+          end;
+      end;
+    if WasSub then
+      tk:=GetToken;
+    end;
+  AddToList(S);
+end;
+
+function TWebIDLParser.ParseAttributes: TAttributeList;
+
+
+begin
+  Result:=TAttributeList.Create;
+  try
+    ParseAttributes(Result,tkSquaredBraceClose);
+  except
+    FreeandNil(Result);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseArgument(aParent : TIDLBaseObject): TIDLArgumentDefinition;
+
+(* On Entry, we're on the argument start
+  on exit, on the token after the argument definition i.e. a comma or )  *)
+
+begin
+  Result:=TIDLArgumentDefinition(Context.Add(aParent,TIDLArgumentDefinition,''));
+  try
+    if (CurrentToken=tkSquaredBraceOpen) then
+      begin
+      Result.Attributes:=ParseAttributes;
+      getToken;
+      end;
+    if CurrentToken=tkOptional then
+      begin
+      Result.isOptional:=True;
+      GetToken;
+      end;
+    Result.ArgumentType:=ParseType(Result,False);
+    CheckCurrentToken(tkIdentifier);
+    Result.Name:=CurrentTokenString;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseFunction(aParent : TIDLBaseObject): TIDLFunctionDefinition;
+
+(* On Entry, we're on the function identifier, on exit, on the final ) *)
+
+
+begin
+  Result:=TIDLFunctionDefinition(Context.Add(aParent,TIDLFunctionDefinition,CurrentTokenString));
+  try
+    ExpectToken(tkEqual);
+    Result.ReturnType:=ParseType(Result,True,True);
+    ParseArguments(Result.Arguments);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseCallBack(aParent : TIDLBaseObject): TIDLDefinition;
+
+var
+  tk : TIDLToken;
+
+begin
+  tk:=GetToken;
+  Case tk of
+    tkInterface :
+       begin
+       Result:=ParseInterface(aParent);
+       TIDLInterfaceDefinition(Result).IsCallBack:=True;
+       end;
+    tkIdentifier :
+       begin
+       Result:=ParseFunction(aParent);
+       With TIDLFunctionDefinition(Result) do
+         Options:=Options+[foCallBack];
+       end;
+  else
+    Error(SErrInvalidTokenList,[GetTokenNames([tkInterface,tkIdentifier])]);
+  end;
+end;
+
+procedure TWebIDLParser.ParseArguments(aParent: TIDLBaseObject);
+
+Var
+  A : TIDLArgumentDefinition;
+  S : UTF8String;
+
+begin
+  CheckCurrentToken(tkBracketOpen);
+  GetToken;
+  While (CurrentToken<>tkBracketClose) do
+    begin
+    A:=ParseArgument(aParent);
+    ExpectTokens([tkEqual,tkComma,tkBracketClose]);
+    if (CurrentToken=tkEqual) then
+      begin
+      ParseConstValue(S,True);
+      A.HasDefaultValue:=True;
+      A.DefaultValue:=S;
+      GetToken;
+      end;
+    if (CurrentToken=tkComma) then
+      GetToken;
+    end;
+end;
+
+function TWebIDLParser.ParseOperation(aParent: TIDLBaseObject): TIDLFunctionDefinition;
+{ On entry, we're on the type definition or on one of getter,setter,deleter,legacycaller,
+  on exit, we're on the final ) }
+
+Const
+  Specials = [tkGetter, tkSetter, tkDeleter, tkLegacyCaller];
+
+Var
+  Opts : TFunctionOptions;
+  FO : TFunctionOption;
+
+begin
+  Opts:=[];
+  While CurrentToken in Specials do
+    begin
+    Case CurrentToken of
+      tkGetter : FO:=foGetter;
+      tkSetter : FO:=foSetter;
+      tkDeleter : FO:=foDeleter;
+      tkLegacyCaller : FO:=foLegacyCaller;
+    end;
+    Include(Opts,FO);
+    GetToken;
+    end;
+  Result:=TIDLFunctionDefinition(Context.Add(aParent,TIDLFunctionDefinition,''));
+  try
+    Result.ReturnType:=ParseType(Result,False,True);
+    CheckCurrentToken(tkIdentifier);
+    Result.Name:=CurrentTokenString;
+    GetToken;
+    ParseArguments(Result.Arguments);
+    Result.Options:=Result.Options+Opts;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseStringifier(aParent: TIDLBaseObject): TIDLDefinition;
+
+(* On entry we're on stringifier, on exit, we're on the end of the definition, before ; *)
+
+Var
+  tk : TIDLToken;
+
+begin
+  tk:=getToken;
+  if tk in [tkReadOnly,tkAttribute] then
+    begin
+    Result:=ParseAttribute(aParent);
+    With TIDLAttributeDefinition(result) do
+      Options:=Options+[aoStringifier];
+    end
+  else
+    begin
+    Result:=ParseOperation(aParent);
+    With TIDLFunctionDefinition(result) do
+      Options:=Options+[foStringifier];
+    end;
+end;
+
+function TWebIDLParser.ParseIterable(aParent: TIDLBaseObject): TIDLIterableDefinition;
+
+Var
+  T1,T2 : TIDLTypeDefDefinition;
+
+begin
+  ExpectToken(tkLess);
+  T1:=Nil;
+  T2:=nil;
+  try
+    Result:=TIDLIterableDefinition(Context.Add(aParent,TIDLIterableDefinition,''));
+    T1:=ParseType(Result,True,True);
+    if (CurrentToken=tkComma) then
+      T2:=ParseType(Result,True,True);
+    CheckCurrentToken(tkLarger);
+    if T2=Nil then
+      Result.ValueType:=T1
+    else
+      begin
+      Result.ValueType:=T2;
+      T2:=Nil;
+      Result.KeyType:=T1;
+      end;
+    T1:=nil;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.CompleteSimpleType(tk: TIDLToken; Var S: UTF8String; out
+  IsNull: Boolean): TIDLToken;
+
+begin
+  Result:=tk;
+  S:='';
+  if (Result=tkUnsigned) then
+    begin
+    S:=CurrentTokenString+' ';
+    Result:=GetToken;
+    end
+  else if (Result=tkUnrestricted) then
+    begin
+    S:=CurrentTokenString+' ';
+    Result:=GetToken;
+    end;
+  // long
+  S:=S+CurrentTokenString;
+  if (Result<>tkLong) then
+    Result:=GetToken
+  else
+    begin
+    Result:=GetToken;
+    // Long long
+    if Result=tkLong then
+      begin
+      S:=S+' '+CurrentTokenString;
+      Result:=GetToken;
+      end;
+    end;
+  if Result=tkQuestionmark then
+    begin
+    IsNull:=True;
+    Result:=GetToken;
+    end;
+end;
+
+function TWebIDLParser.ParseMapLikeMember(aParent: TIDLBaseObject): TIDLMaplikeDefinition;
+begin
+  Result:=TIDLMaplikeDefinition(Context.Add(aParent,TIDLMaplikeDefinition,''));
+  try
+    Result.TypeName:='maplike';
+    ExpectToken(tkLess);
+    Result.KeyType:=ParseType(Result,True,true);
+    CheckCurrentToken(tkComma);
+    Result.ValueType:=ParseType(Result,True,true);
+    CheckCurrentToken(tkLarger);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseSetLikeMember(aParent: TIDLBaseObject): TIDLSetlikeDefinition;
+(* On Entry we're on setlike. On exit, we're on the > token *)
+
+begin
+  Result:=TIDLSetlikeDefinition(Context.Add(aParent,TIDLSetlikeDefinition,''));
+  try
+    ExpectToken(tkLess);
+    Result.ElementType:=ParseType(Result);
+    Result.ElementType.Parent:=Result;
+    CheckCurrentToken(tkLarger);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseRecordTypeDef(aParent: TIDLBaseObject): TIDLRecordDefinition;
+
+begin
+  Result:=TIDLRecordDefinition(Context.Add(aParent,TIDLRecordDefinition,''));
+  try
+    Result.TypeName:='record';
+    ExpectToken(tkLess);
+    Result.KeyType:=ParseType(Result,True,true);
+    CheckCurrentToken(tkComma);
+    Result.ValueType:=ParseType(Result,True,true);
+    CheckCurrentToken(tkLarger);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseConstValue(out aValue: UTF8String;
+  aExtended: Boolean): TConstType;
+
+Const
+  ValueTokens = [tkTrue,tkFalse,tkNumberFloat,tkNumberInteger,tkNull,tkInfinity,tkNegInfinity,tkNan];
+  ExtendedTokens = [tkSquaredBraceOpen,tkString];
+  ExtendedValueTokens = ExtendedTokens + ValueTokens;
+  AllowedTokens : Array[Boolean] of TIDLTokens = (ValueTokens,ExtendedValueTokens);
+
+begin
+  ExpectTokens(AllowedTokens[aExtended]);
+  aValue:=CurrentTokenString;
+  Case CurrentToken of
+    tkTrue,tkFalse : Result:=ctBoolean;
+    tkNumberFloat : Result:=ctFloat;
+    tkNumberInteger : Result:=ctInteger;
+    tkNull : Result:=ctNull;
+    tkNan : Result:=ctNan;
+    tkInfinity : Result:=ctInfinity;
+    tkNegInfinity : Result:=ctNegInfinity;
+    tkString :
+      If aExtended then
+        Result:=ctString
+      else
+        Error(SErrUnExpectedToken,[CurrentTokenString]);
+    tkSquaredBraceOpen :
+      If aExtended then
+        begin
+        ExpectToken(tkSquaredBraceClose);
+        aValue:=AValue+CurrentTokenString;
+        Result:=ctEmptyArray
+        end
+      else
+        Error(SErrUnExpectedToken,[CurrentTokenString]);
+  end;
+end;
+
+function TWebIDLParser.ParseConst(aParent : TIDLBaseObject): TIDLConstDefinition;
+
+(*
+  On Entry we're on const. On exit, we're before the ;
+*)
+
+Const
+  PrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
+  SingleTokens = [tkIdentifier,tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort];
+  TypeTokens = SingleTokens+PrefixTokens;
+
+Var
+  S : UTF8String;
+  isNull : Boolean;
+  tk : TIDLToken;
+
+begin
+  Result:=Nil;
+  isNull:=False;
+  S:='';
+  tk:=ExpectTokens(TypeTokens);
+  // Unsigned
+  Tk:=CompleteSimpleType(tk,S,IsNull);
+  CheckCurrentToken(tkIdentifier);
+  Result:=TIDLConstDefinition(Context.Add(aParent,TIDLConstDefinition,CurrentTokenString));
+  try
+    Result.TypeName:=S;
+    Result.AllowNull:=isNull;
+    ExpectToken(tkEqual);
+    Result.ConstType:=ParseConstValue(S,false);
+    Result.Value:=S;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+procedure TWebIDLParser.MaybeFree(Result: TIDLDefinition; aParent : TIDLBaseObject);
+
+begin
+  if (AParent=Nil)  then
+    Result.Free
+  else if (aParent is TIDLDefinitionList) and (Not TIDLDefinitionList(AParent).OwnsDefinitions) then
+    Result.Free;
+end;
+
+
+function TWebIDLParser.ParseAttribute(aParent : TIDLBaseObject): TIDLAttributeDefinition;
+(*
+  On Entry we're on readonly, inherit or attribute.
+  On Exit, we're on the last token of the attribute definition, the name
+*)
+Var
+  Options : TAttributeOptions;
+
+begin
+  Options:=[];
+  if CurrentToken=tkInherit then
+    begin
+    Include(Options,aoInherit);
+    GetToken;
+    end;
+  if (CurrentToken=tkReadOnly) then
+    begin
+    Include(Options,aoReadOnly);
+    GetToken;
+    end;
+  CheckCurrentToken(tkAttribute);
+  Result:=TIDLAttributeDefinition(Context.Add(aParent,TIDLAttributeDefinition,''));
+  try
+    Result.AttributeType:=ParseType(Result,True,True);
+    CheckCurrentToken(tkIdentifier);
+    Result.Name:=CurrentTokenString;
+    Result.Options:=Options;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseStatic(aParent : TIDLBaseObject): TIDLDefinition;
+
+(* On Entry we're on static. On exit, we're on the end of the definition, before the ; *)
+
+Var
+  A : TIDLAttributeDefinition;
+  F : TIDLFunctionDefinition;
+  tk : TIDLToken;
+
+begin
+  tk:=GetToken;
+  if (Tk in [tkReadonly,tkAttribute]) then
+    begin
+    A:=ParseAttribute(aParent);
+    A.Options:=A.Options+[aoStatic];
+    Result:=A;
+    end
+  else
+    begin
+    F:=ParseFunction(aParent);
+    F.Options:=F.Options+[foStatic];
+    Result:=F;
+    end;
+end;
+
+function TWebIDLParser.ParseSerializer(aParent : TIDLBaseObject): TIDLSerializerDefinition;
+
+Var
+  tk : TIDLToken;
+
+begin
+  Result:=Nil;
+  tk:=GetToken;
+  if tk=tkSemiColon then
+    exit;
+  Result:=TIDLSerializerDefinition(Context.Add(aParent,TIDLSerializerDefinition,''));
+  try
+    if tk<>tkEqual then
+      begin
+      Result.SerializerFunction:=ParseOperation(Result);
+      Exit;
+      end;
+    ExpectTokens([tkSquaredBraceOpen,tkCurlyBraceOpen,tkIdentifier]);
+    case CurrentToken of
+      tkSquaredBraceOpen :
+        begin
+        ParseAttributes(Result.Identifiers,tkSquaredBraceClose,True);
+        Result.Kind:=skArray;
+        end;
+      tkCurlyBraceOpen :
+        begin
+        ParseAttributes(Result.Identifiers,tkCurlyBraceClose,True);
+        Result.Kind:=skObject;
+        end;
+      tkIdentifier :
+        begin
+        Result.Identifiers.Add(CurrentTokenString);
+        Result.Kind:=skSingle;
+        end;
+      end;
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseInterface(aParent : TIDLBaseObject): TIDLInterfaceDefinition;
+(*
+  On Entry we're on interface. On exit, we're on the } character
+*)
+
+Var
+  tk : TIDLToken;
+  Attrs : TAttributeList;
+  M : TIDLDefinition;
+  isMixin,SemicolonSeen : Boolean;
+
+begin
+  Attrs:=nil;
+  ExpectTokens([tkMixin,tkIdentifier]);
+  isMixin:=CurrentToken=tkMixin;
+  if CurrentToken=tkMixin then
+    ExpectToken(tkIdentifier);
+  Result:=TIDLInterfaceDefinition(Context.Add(aParent,TIDLInterfaceDefinition,CurrentTokenString));
+  try
+    Result.IsMixin:=IsMixin;
+    tk:=GetToken;
+    if tk=tkColon then
+      begin
+      ExpectToken(tkIdentifier);
+      Result.ParentName:=CurrentTokenString;
+      tk:=GetToken;
+      end;
+    CheckCurrentToken(tkCurlyBraceOpen);
+    tk:=GetToken;
+    While (tk<>tkCurlyBraceClose) do
+      begin
+      SemicolonSeen:=False;
+      Attrs:=nil;
+      M:=Nil;
+      if tk=tkSquaredBraceOpen then
+        begin
+        Attrs:=ParseAttributes;
+        tk:=GetToken;
+        end;
+      Case tk of
+        tkConst : M:=ParseConst(Result.Members);
+        tkSetLike : M:=ParseSetLikeMember(Result.Members);
+        tkMapLike : M:=ParseMapLikeMember(Result.Members);
+        tkReadOnly :
+          begin
+          Case GetToken of
+            tkAttribute,tkInherit:
+              begin
+              M:=ParseAttribute(Result.Members);
+              With TIDLAttributeDefinition(M) do
+                Options:=Options+[aoReadOnly];
+              end;
+            tkMapLike:
+              begin
+              M:=ParseMapLikeMember (Result.Members);
+              TIDLMapLikeDefinition(M).IsReadonly:=True;
+              end;
+            tkSetLike:
+              begin
+              M:=ParseSetLikeMember (Result.Members);
+              TIDLSetLikeDefinition(M).IsReadonly:=True;
+              end
+          else
+            CheckCurrentTokens([tkAttribute,tkInherit,tkMapLike,tkSetLike]);
+          end;
+          end;
+        tkInherit,
+        tkAttribute : M:=ParseAttribute(Result.Members);
+        tkStatic : M:=ParseStatic(Result.Members);
+        tkSerializer :
+          begin
+          M:=ParseSerializer(Result.Members);
+          Result.HasSerializer:=True;
+          SemicolonSeen:=M=Nil;
+          end;
+        tkStringifier : M:=ParseStringifier(Result.Members);
+        tkIterable : ParseIterable(Result.Members);
+      else
+        {
+        tkGetter, tkSetter, tkDeleter, tkLegacyCaller
+        }
+        M:=ParseOperation(Result.Members);
+      end;
+      IF Assigned(M) then
+        begin
+        M.Attributes:=Attrs;
+        Attrs:=Nil; // So it does not get freed in except
+        end;
+      if not SemicolonSeen then
+        GetToken;
+      CheckCurrentToken(tkSemicolon);
+      tk:=GetToken;
+      end;
+  except
+    FreeAndNil(Attrs);
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParsePartial(aParent : TIDLBaseObject): TIDLStructuredDefinition;
+
+(* On entry, we're on Partial. On exit, we're on the } character *)
+
+begin
+  Case GetToken of
+    tkInterface : Result:=ParseInterface(aParent);
+    tkDictionary : Result:=ParseDictionary(aParent);
+  else
+    Error(SErrInvalidTokenList,[GetTokenNames([tkInterface,tkDictionary]),CurrentTokenString]);
+  end;
+  Result.IsPartial:=True;
+end;
+
+function TWebIDLParser.ParseEnum(aParent : TIDLBaseObject): TIDLEnumDefinition;
+(* On entry, we're on enum. On exit, we're on the } character *)
+
+Var
+  tk : TIDLToken;
+
+begin
+  ExpectToken(tkIdentifier);
+  Result:=TIDLEnumDefinition(Context.Add(aParent,TIDLEnumDefinition,CurrentTokenString));
+  ExpectToken(tkCurlyBraceOpen);
+  Repeat
+    tk:=ExpectTokens([tkCurlyBraceClose,tkString]);
+    if tk=tkString then
+      begin
+      Result.AddValue(CurrentTokenString);
+      tk:=ExpectTokens([tkCurlyBraceClose,tkComma]);
+      end;
+  Until (tk=tkCurlyBraceClose);
+end;
+
+function TWebIDLParser.ParseDictionaryMember(aParent : TIDLBaseObject): TIDLDictionaryMemberDefinition;
+
+{ On Entry, we're at the start of the member. This may be required, attributes or the type.
+  On Exit, we're on the ; }
+
+Var
+  Attrs : TAttributeList;
+  tk : TIDLToken;
+  isRequired : Boolean;
+  S : UTF8String;
+
+begin
+  Attrs:=Nil;
+  tk:=CurrentToken;
+  isRequired:=(tk=tkRequired);
+  if IsRequired then
+    tk:=GetToken;
+  if tk=tkSquaredBraceOpen then
+    begin
+    Attrs:=ParseAttributes;
+    tk:=GetToken;
+    end;
+  Result:=TIDLDictionaryMemberDefinition(Context.Add(aParent,TIDLDictionaryMemberDefinition,''));
+  try
+    Result.Attributes:=Attrs;
+    Result.IsRequired:=isRequired;
+    Result.MemberType:=ParseType(Result,Assigned(Attrs),True);
+    CheckCurrentToken(tkIdentifier);
+    Result.Name:=CurrentTokenString;
+    tk:=GetToken;
+    if tk=tkEqual then
+      begin
+      Result.DefaultValue:=TIDLConstDefinition(Context.Add(Result,TIDLConstDefinition,''));
+      Result.DefaultValue.ConstType:=ParseConstValue(S,True);
+      Result.DefaultValue.Value:=S;
+      tk:=GetToken;
+      end;
+    CheckCurrentToken(tkSemicolon);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseDictionary(aParent : TIDLBaseObject; AllowInheritance : Boolean = True): TIDLDictionaryDefinition;
+(* On entry, we're on dictionary, on eexit, we're on { *)
+
+Var
+  Name,ParentName : UTF8String;
+  tk : TIDLToken;
+
+begin
+  ExpectToken(tkIdentifier);
+  Name:=CurrentTokenString;
+  tk:=GetToken;
+  if (tk=tkColon) then
+    begin
+    If Not AllowInheritance then
+      Error(SErrUnExpectedToken,[CurrentTokenString]);
+    ExpectToken(tkIdentifier);
+    ParentName:=CurrentTokenString;
+    tk:=GetToken;
+    end;
+  CheckCurrentToken(tkCurlyBraceOpen);
+  Result:=TIDLDictionaryDefinition(Context.Add(aParent,TIDLDictionaryDefinition,Name));
+  Result.ParentName:=ParentName;
+  GetToken;
+  Repeat
+     ParseDictionaryMember(Result.Members);
+     CheckCurrentTokens([tkSemicolon,tkCurlyBraceClose]);
+     if (CurrentToken=tkSemicolon) then
+       GetToken;
+  Until (CurrentToken=tkCurlyBraceClose);
+end;
+
+function TWebIDLParser.ParseSequenceTypeDef(aParent : TIDLBaseObject): TIDLSequenceTypeDefDefinition;
+(* On Entry we're on sequence. On exit, we're on the > token *)
+
+begin
+  Result:=TIDLSequenceTypeDefDefinition(Context.Add(aParent,TIDLSequenceTypeDefDefinition,''));
+  try
+    Result.TypeName:='sequence';
+    ExpectToken(tkLess);
+    Result.ElementType:=ParseType(Result);
+    Result.ElementType.Parent:=Result;
+    CheckCurrentToken(tkLarger);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseUnionTypeDef(aParent : TIDLBaseObject): TIDLUnionTypeDefDefinition;
+
+(* On Entry we're on (. On exit, we're on the ) token *)
+
+Var
+  D : TIDLTypeDefDefinition;
+  tk : TIDLToken;
+  Attr : TAttributeList;
+
+begin
+  Attr:=Nil;
+  Result:=TIDLUnionTypeDefDefinition(Context.Add(aParent,TIDLUnionTypeDefDefinition,''));
+  try
+    Result.TypeName:='union';
+    Repeat
+      Attr:=Nil;
+      tk:=GetToken;
+      if Tk=tkSquaredBraceOpen then
+        begin
+        Attr:=ParseAttributes;
+        tk:=getToken;
+        end;
+      D:=ParseType(Result.Union,False);
+      D.Attributes:=Attr;
+      Attr:=Nil;
+      if (D.TypeName='any') then
+        Error(SErrTypeNotAllowed,['any','union']);
+      CheckCurrentTokens([tkOr,tkBracketClose]);
+      tk:=CurrentToken;
+    until (tk=tkBracketClose);
+  except
+    FreeAndNil(Attr);
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParsePromiseTypeDef(aParent: TIDLBaseObject): TIDLPromiseTypeDefDefinition;
+(* On Entry we're on promise. On exit, we're on the > token *)
+
+begin
+  Result:=TIDLPromiseTypeDefDefinition(Context.Add(aParent,TIDLPromiseTypeDefDefinition,''));
+  try
+    Result.TypeName:='Promise';
+    ExpectToken(tkLess);
+    Result.ReturnType:=ParseType(Result,True,true);
+    CheckCurrentToken(tkLarger);
+  except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseType(aParent : TIDLBaseObject; FetchFirst : Boolean = True; AllowExtraTypes : Boolean = False): TIDLTypeDefDefinition;
+
+(* On Entry
+   if FetchFirst = true we're on "typedef", "(", "or" or "<" tokens.
+   if FetchFirst = true we're on the first actual token
+   On exit, we're on the first token after the type
+
+   *)
+
+Const
+  SimplePrefixTokens = [tkUnsigned,tkLong,tkUnrestricted];
+  ComplexPrefixTokens = [tkSequence,tkPromise,tkBracketOpen,tkRecord];
+  PrefixTokens  = ComplexPrefixTokens+SimplePrefixTokens;
+  PrimitiveTokens = [tkBoolean,tkByte,tkOctet,tkFloat,tkDouble,tkShort,tkAny,tkObject];
+  IdentifierTokens = [tkIdentifier,tkByteString,tkUSVString,tkDOMString];
+  SimpleTypeTokens = PrimitiveTokens+IdentifierTokens;
+  TypeTokens = PrefixTokens+SimpleTypeTokens;
+  ExtraTypeTokens = TypeTokens +[tkStringToken,tkVoid];
+
+Var
+  isNull : Boolean;
+  typeName: UTF8String;
+  Allowed : TIDLTokens;
+  tk : TIDLToken;
+
+begin
+  if AllowExtraTypes then
+    Allowed:=ExtraTypeTokens
+  else
+    Allowed:=TypeTokens;
+  Result:=Nil;
+  try
+    isNull:=False;
+    if FetchFirst then
+      tk:=GetToken
+    else
+      tk:=CurrentToken;
+    CheckCurrentTokens(Allowed);
+    TypeName:=CurrentTokenString;
+    if (tk in SimplePrefixTokens) then
+      begin
+      tk:=CompleteSimpleType(tk,TypeName,isNull);
+      Result:=TIDLTypeDefDefinition(Context.Add(aParent,TIDLTypeDefDefinition,''));
+      end
+    else
+      begin
+      Case tk of
+        tkRecord : Result:=ParseRecordTypeDef(aParent);
+        tkSequence : Result:=ParseSequenceTypeDef(aParent);
+        tkPromise : Result:=ParsePromiseTypeDef(aParent);
+        tkBracketOpen : Result:=ParseUnionTypeDef(aParent);
+      else
+        Result:=TIDLTypeDefDefinition(Context.Add(aParent,TIDLTypeDefDefinition,''));
+      end;
+      tk:=GetToken;
+      end;
+    if Result.TypeName='' then
+      Result.TypeName:=TypeName;
+    // Null ?
+    if tk=tkQuestionmark then
+      begin
+      tk:=GetToken;
+      isNull:=True;
+      end;
+    if Assigned(Result) then
+      Result.AllowNull:=isNull;
+  Except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseTypeDef(aParent : TIDLBaseObject): TIDLTypeDefDefinition;
+(* On Entry we're on "typedef", "or" or "<" tokens. On exit, we're on the identifier *)
+
+
+begin
+  Result:=ParseType(aParent);
+  try
+    CheckCurrentToken(tkIdentifier);
+    Result.Name:=CurrentTokenString;
+  Except
+    MaybeFree(Result,aParent);
+    Raise;
+  end;
+end;
+
+function TWebIDLParser.ParseImplements(aParent : TIDLBaseObject): TIDLImplementsDefinition;
+(* On entry, we're on the identifier. On Exit, we're on the last identifier *)
+
+begin
+  Result:=TIDLImplementsDefinition(Context.Add(aParent,TIDLImplementsDefinition,CurrentTokenString));
+  try
+    ExpectToken(tkImplements);
+    ExpectToken(tkIdentifier);
+    Result.ImplementedInterface:=CurrentTokenString;
+  except
+    MaybeFree(Result,aParent);
+  end;
+end;
+
+function TWebIDLParser.ParseIncludes(aParent: TIDLBaseObject): TIDLIncludesDefinition;
+
+(* On entry, we're on the identifier. On Exit, we're on the last identifier *)
+
+begin
+  Result:=TIDLIncludesDefinition(Context.Add(aParent,TIDLIncludesDefinition,CurrentTokenString));
+  try
+    ExpectToken(tkIncludes);
+    ExpectToken(tkIdentifier);
+    Result.IncludedInterface:=CurrentTokenString;
+  except
+    MaybeFree(Result,aParent);
+  end;
+end;
+
+
+function TWebIDLParser.ParseDefinition(aParent : TIDLBaseObject): TIDLDefinition;
+
+Var
+  tk : TIDLToken;
+  Attrs : TAttributeList;
+
+begin
+  Result:=Nil;
+  Attrs:=Nil;
+  tk:=GetToken;
+  if tk=tkSquaredBraceOpen then
+    begin
+    Attrs:=ParseAttributes;
+    tk:=GetToken;
+    end;
+  Try
+    Case tk of
+      tkCallback : Result:=ParseCallBack(aParent);
+      tkInterface : Result:=ParseInterface(aParent);
+      tkDictionary : Result:=ParseDictionary(aParent);
+      tkPartial : Result:=ParsePartial(aParent);
+      tkEnum : Result:=ParseEnum(aParent);
+      tkTypeDef : Result:=ParseTypeDef(aParent);
+      tkIdentifier :
+        if version=v1 then
+          Result:=ParseImplements(aParent)
+        else
+          Result:=ParseIncludes(aParent);
+      tkEOF : exit;
+    else
+      Error(SErrUnExpectedToken,[CurrentTokenString]);
+    end;
+    if Assigned(Result) then
+      begin
+      Result.Attributes:=Attrs;
+      Attrs:=nil;
+      end;
+  except
+    FreeAndNil(Attrs);
+    Raise;
+  end;
+  ExpectToken(tkSemicolon);
+end;
+
+procedure TWebIDLParser.ParseDefinitions(aParent : TIDLBaseObject);
+
+begin
+  Repeat
+    ParseDefinition(aParent);
+  Until (CurrentToken=tkEOF)
+end;
+
+procedure TWebIDLParser.Parse;
+begin
+  ParseDefinitions(Context.Definitions);
+end;
+
+{ TWebIDLContext }
+
+constructor TWebIDLContext.Create(OwnsDefinitions : Boolean = True);
+begin
+  FDefinitions:=TIDLDefinitionList.Create(Nil,OwnsDefinitions);
+end;
+
+destructor TWebIDLContext.Destroy;
+begin
+  FreeAndNil(FDefinitions);
+  FreeAndNil(FHash);
+  inherited Destroy;
+end;
+
+function TWebIDLContext.FindDictionary(aName: UTF8String
+  ): TIDLDictionaryDefinition;
+
+Var
+  I : Integer;
+
+begin
+  I:=0;
+  Result:=Nil;
+  While (Result=Nil) and (I<FDefinitions.Count) do
+    begin
+    if (FDefinitions[i] is TIDLDictionaryDefinition) then
+      begin
+      Result:=TIDLDictionaryDefinition(FDefinitions[i]);
+      if (Result.Name<>aName) or (Result.IsPartial) then
+        Result:=nil;
+      end;
+    Inc(I);
+    end;
+end;
+function TWebIDLContext.FindInterface(aName: UTF8String
+  ): TIDLInterfaceDefinition;
+
+Var
+  I : Integer;
+
+begin
+  I:=0;
+  Result:=Nil;
+  While (Result=Nil) and (I<FDefinitions.Count) do
+    begin
+    if (FDefinitions[i] is TIDLInterfaceDefinition) then
+      begin
+      Result:=TIDLInterfaceDefinition(FDefinitions[i]);
+      if (Result.Name<>aName) or (Result.IsPartial) then
+        Result:=nil;
+      end;
+    Inc(I);
+    end;
+end;
+
+procedure TWebIDLContext.AppendDictionaryPartials;
+
+Var
+  D : TIDLDefinition;
+  DD : TIDLDictionaryDefinition absolute D;
+  OD : TIDLDictionaryDefinition;
+
+begin
+  For D in FDefinitions do
+    if (D is TIDLDictionaryDefinition) and (DD.IsPartial) then
+      begin
+      OD:=FindDictionary(DD.Name);
+      If (OD=Nil) then
+        Raise EWebIDLParser.CreateFmt(SErrDictionaryNotFound,[DD.Name]);
+      OD.Partials.Add(DD);
+      end;
+end;
+
+procedure TWebIDLContext.AppendInterfacePartials;
+
+Var
+  D : TIDLDefinition;
+  ID : TIDLInterfaceDefinition absolute D;
+  OD : TIDLInterfaceDefinition;
+
+begin
+  For D in FDefinitions do
+    if (D is TIDLInterfaceDefinition) and (ID.IsPartial) then
+      begin
+      OD:=FindInterface(ID.Name);
+      If (OD=Nil) then
+        Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFound,[ID.Name]);
+      OD.Partials.Add(ID);
+      end;
+end;
+
+procedure TWebIDLContext.AppendInterfaceIncludes;
+Var
+  D : TIDLDefinition;
+  ID : TIDLIncludesDefinition absolute D;
+  II,OI : TIDLInterfaceDefinition; // Includes and original
+
+begin
+  For D in FDefinitions do
+    if (D is TIDLIncludesDefinition)  then
+      begin
+      OI:=FindInterface(ID.Name);
+      If (OI=Nil) then
+        Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFound,[ID.Name]);
+      II:=FindInterface(ID.IncludedInterface);
+      If (II=Nil) then
+        Raise EWebIDLParser.CreateFmt(SErrInterfaceNotFound,[ID.Name]);
+      II.IsInclude:=True;
+      OI.Partials.Add(II);
+      end;
+  // if there is a single include, no members and no parent, make it a descendent
+  For D in FDefinitions do
+    if (D is TIDLInterfaceDefinition)  then
+      begin
+      OI:=D as TIDLInterfaceDefinition;
+      if (OI.ParentName='') and (OI.Partials.Count=1) then
+        if (OI.Partial[0] is TIDLInterfaceDefinition) then
+          begin
+          II:=OI.Partial[0] as TIDLInterfaceDefinition;
+          if II.IsInclude then
+            begin
+            // DoLog('Converting single include %s to parent class for %s',[II.Name,OI.Name]);
+            OI.ParentName:=II.Name;
+            OI.ParentInterface:=II;
+            OI.Partials.Clear;
+            end;
+          end;
+      end;
+end;
+
+procedure TWebIDLContext.AppendPartials;
+
+begin
+  AppendDictionaryPartials;
+  AppendInterfacePartials;
+end;
+
+procedure TWebIDLContext.AppendIncludes;
+begin
+  AppendInterfaceIncludes;
+end;
+
+procedure TWebIDLContext.ResolveParentTypes;
+
+Var
+  D : TIDLDefinition;
+  ID : TIDLInterfaceDefinition absolute D;
+  DD : TIDLDictionaryDefinition absolute D;
+
+begin
+  For D in FDefinitions do
+    if D is TIDLInterfaceDefinition then
+      begin
+      if (ID.ParentName<>'') then
+        ID.ParentInterface:=FindInterface(ID.ParentName);
+      end
+    else if D is TIDLDictionaryDefinition then
+      if (DD.ParentName<>'') then
+        DD.ParentDictionary:=FindDictionary(DD.ParentName);
+end;
+
+procedure TWebIDLContext.ResolveTypes;
+begin
+  ResolveParentTypes;
+end;
+
+function TWebIDLContext.IndexOfDefinition(const AName: String): Integer;
+begin
+  Result:=Definitions.Count-1;
+  While (Result>=0) and (Definitions[Result].Name<>AName) do
+    Dec(Result);
+end;
+
+
+function TWebIDLContext.FindDefinition(const AName: String): TIDLDefinition;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  if (FHash=Nil) then
+    begin
+    FHash:=TFPObjectHashTable.Create(False);
+    For D in Definitions do
+      if not D.IsExtension then
+        FHash.Add(D.Name,D);
+    end;
+  Result:=TIDLDefinition(FHash.Items[AName]);
+end;
+
+function TWebIDLContext.AsString(Full: Boolean): UTF8String;
+begin
+  Result:=Definitions.AsString(';'+sLineBreak,'','','',True,True);
+end;
+
+function TWebIDLContext.Add(aClass: TIDLDefinitionClass; const AName: UTF8String): TIDLDefinition;
+begin
+  Result:=Add(FDefinitions,aClass,AName);
+end;
+
+
+function TWebIDLContext.Add(aParent: TIDLBaseObject; aClass: TIDLDefinitionClass; const AName: UTF8String): TIDLDefinition;
+begin
+  if Assigned(aParent) then
+    Result:=aParent.Add(aClass,aName)
+  else
+    Result:=aClass.Create(Nil,aName)
+end;
+
+end.
+

+ 700 - 0
packages/webidl/src/webidlscanner.pp

@@ -0,0 +1,700 @@
+{
+    This file is part of the Free Component Library
+
+    WEBIDL source lexical scanner
+    Copyright (c) 2018 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 webidlscanner;
+
+interface
+
+uses SysUtils, Classes;
+
+
+type
+  TWebIDLVersion = (v1,v2);
+
+  TIDLToken = (
+    tkEOF,
+    tkUnknown ,
+    tkComment,
+    tkWhitespace,
+    tkString,
+    tkNumberInteger,
+    tkNumberFloat,
+    // Simple (one-character) tokens
+    tkDot, // '.',
+    tkSemiColon, // ';'
+    tkComma,                 // ','
+    tkColon,                 // ':'
+    tkBracketOpen,           // '('
+    tkBracketClose,          // ')'
+    tkCurlyBraceOpen,        // '{'
+    tkCurlyBraceClose,       // '}'
+    tkSquaredBraceOpen,       // '['
+    tkSquaredBraceClose,      // ']'
+    tkLess, // '<'
+    tkEqual, // '='
+    tkLarger, // '>'
+    tkQuestionmark, // '?'
+    tkminus, // '-'
+    tkIdentifier,            // Any  identifier
+    tkTrue,
+    tkFalse,
+    tkNull,
+    tkAny,
+    tkAttribute,
+    tkCallback,
+    tkConst,
+    tkDeleter,
+    tkDictionary,
+    tkEllipsis,
+    tkEnum,
+    tkGetter,
+    tkImplements,
+    tkInfinity,
+    tkInherit,
+    tkInterface,
+    tkIterable,
+    tkLegacyCaller,
+    tkNan,
+    tkNegInfinity,
+    tkOptional,
+    tkOr,
+    tkPartial,
+    tkReadOnly,
+    tkRequired,
+    tkSetter,
+    tkStatic,
+    tkStringifier,
+    tkSerializer,
+    tkTypedef,
+    tkUnrestricted,
+    tkPromise,
+    tkByteString,
+    tkDOMString,
+    tkUSVString,
+    tkboolean,
+    tkbyte,
+    tkdouble,
+    tkfloat,
+    tklong,
+    tkobject,
+    tkoctet,
+    tkunsigned,
+    tkvoid,
+    tkShort,
+    tkSequence,
+    tkStringToken,
+    tkMixin,
+    tkIncludes,
+    tkMapLike,
+    tkRecord,
+    tkSetLike,
+    tkOther
+    );
+  TIDLTokens = Set of TIDLToken;
+  EWebIDLScanner = class(EParserError);
+
+Const
+  V2Tokens = [tkMixin,tkIncludes,tkMapLike,tkRecord,tkSetLike];
+  V1Tokens = [tkImplements];
+  VersionNonTokens : Array[TWebIDLVersion] of TIDLTokens = (V2Tokens,V1Tokens);
+
+Type
+
+  { TWebIDLScanner }
+
+  TWebIDLScanner = class
+  private
+    FSource : TStringList;
+    FCurRow: Integer;
+    FCurToken: TIDLToken;
+    FCurTokenString: UTF8string;
+    FCurLine: UTF8string;
+    FVersion: TWebIDLVersion;
+    TokenStr: PChar;
+    function DetermineToken: TIDLToken;
+    function DetermineToken2: TIDLToken;
+    function FetchLine: Boolean;
+    function GetCurColumn: Integer;
+    function ReadComment: UTF8String;
+    function ReadIdent: UTF8String;
+    function ReadNumber(var S: UTF8String): TIDLToken;
+  protected
+    Function GetErrorPos : String;
+    procedure Error(const Msg: string);overload;
+    procedure Error(const Msg: string; Const Args: array of Const);overload;
+    function ReadString: UTF8String; virtual;
+    function DoFetchToken: TIDLToken;
+  public
+    constructor Create(Source: TStream); overload;
+    constructor Create(const Source: UTF8String); overload;
+    constructor CreateFile(const aFileName: UTF8String);
+    destructor Destroy; override;
+    function FetchToken: TIDLToken;
+
+    property CurLine: UTF8String read FCurLine;
+    property CurRow: Integer read FCurRow;
+    property CurColumn: Integer read GetCurColumn;
+
+    property CurToken: TIDLToken read FCurToken;
+    property CurTokenString: UTF8String read FCurTokenString;
+    Property Version : TWebIDLVersion Read FVersion Write FVersion;
+  end;
+
+const
+  TokenInfos: array[TIDLToken] of string = (
+  '',
+  '',
+  '',
+  '',
+  '',
+  '',
+  '',
+  // Simple (one-character) tokens
+  '.',
+  ';',
+  ',',                 // ','
+  ':',                 // ':'
+  '(',           // '('
+  ')',          // ')'
+  '{',        // '{'
+  '}',       // '}'
+  '[',       // '['
+  ']',      // ']'
+  '<',
+  '=',
+  '>',
+  '?',
+  '-',
+  '',            // Any  identifier
+  'true',
+  'false',
+  'null',
+  'any',
+  'attribute',
+  'callback',
+  'const',
+  'deleter',
+  'dictionary',
+  'ellipsis',
+  'enum',
+  'getter',
+  'implements',
+  'Infinity',
+  'inherit',
+  'interface',
+  'iterable',
+  'legacycaller',
+  'NaN',
+  '-Infinity',
+  'optional',
+  'or',
+  'partial',
+  'readonly',
+  'required',
+  'setter',
+  'static',
+  'stringifier',
+  'serializer',
+  'typedef',
+  'unrestricted',
+  'Promise',
+  'ByteString',
+  'DOMString',
+  'USVString',
+  'boolean',
+  'byte',
+  'double',
+  'float',
+  'long',
+  'object',
+  'octet',
+  'unsigned',
+  'void',
+  'short',
+  'sequence',
+  'string',
+  'mixin',
+  'includes',
+  'maplike',
+  'record',
+  'setlike',
+  'other'
+  );
+
+Function GetTokenName(aToken : TIDLToken) : String;
+Function GetTokenNames(aTokenList : TIDLTokens) : String;
+
+implementation
+
+uses typinfo;
+
+Resourcestring
+  SErrUnknownTerminator = 'Unknown terminator: "%s"';
+  SErrInvalidCharacter = 'Invalid character at line %d, pos %d: ''%s''';
+  SUnterminatedComment = 'Unterminated comment at line %d, pos %d: ''%s''';
+  SErrOpenString = 'string exceeds end of line';
+  SErrInvalidEllipsis = 'Invalid ellipsis token';
+  SErrUnknownToken = 'Unknown token, expected number or minus : "%s"';
+//  SerrExpectedTokenButWasIdentifier = 'Invalid terminator: "%s"';
+
+Function GetTokenName(aToken : TIDLToken) : String;
+
+begin
+  Result:=TokenInfos[aToken];
+  if Result='' then
+    begin
+    Result:=GetEnumName(TypeInfo(TIDLToken),Ord(aToken));
+    Delete(Result,1,2);
+    end;
+end;
+
+Function GetTokenNames(aTokenList : TIDLTokens) : String;
+
+Var
+  T : TIDLToken;
+
+begin
+  Result:='';
+  For T in aTokenList do
+    begin
+    if (Result<>'') then
+      Result:=Result+',';
+    Result:=Result+GetTokenName(T);
+    end;
+end;
+
+
+constructor TWebIDLScanner.Create(Source: TStream);
+begin
+  FSource:=TStringList.Create;
+  FSource.LoadFromStream(Source);
+end;
+
+constructor TWebIDLScanner.Create(const Source: UTF8String);
+begin
+  FSource:=TStringList.Create;
+  FSource.Text:=Source;
+end;
+
+constructor TWebIDLScanner.CreateFile(const aFileName: UTF8String);
+begin
+  FSource:=TStringList.Create;
+  FSource.LoadFromFile(aFileName);
+end;
+
+destructor TWebIDLScanner.Destroy;
+begin
+  FreeAndNil(FSource);
+  Inherited;
+end;
+
+
+function TWebIDLScanner.FetchToken: TIDLToken;
+
+begin
+  Result:=DoFetchToken;
+end;
+
+procedure TWebIDLScanner.Error(const Msg: string);
+begin
+  raise EWebIDLScanner.Create(GetErrorPos+Msg);
+end;
+
+procedure TWebIDLScanner.Error(const Msg: string; const Args: array of const);
+begin
+  raise EWebIDLScanner.Create(GetErrorPos+Format(Msg, Args));
+end;
+
+function TWebIDLScanner.ReadString : UTF8String;
+
+Var
+  C : Char;
+  I, OldLength, SectionLength: Integer;
+  S : UTF8String;
+  TokenStart: PChar;
+begin
+  C:=TokenStr[0];
+  Inc(TokenStr);
+  TokenStart := TokenStr;
+  OldLength := 0;
+  Result := '';
+  while not (TokenStr[0] in [#0,C]) do
+    begin
+    if (TokenStr[0]='\') then
+      begin
+      // Save length
+      SectionLength := TokenStr - TokenStart;
+      Inc(TokenStr);
+      // Read escaped token
+      Case TokenStr[0] of
+        '"' : S:='"';
+        '''' : 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, [CurRow,CurColumn,TokenStr[0]]);
+                end;
+                end;
+              // WideChar takes care of conversion...
+              S:=Utf8Encode(WideString(WideChar(StrToInt('$'+S))))
+              end;
+        #0  : Error(SErrOpenString);
+      else
+        Error(SErrInvalidCharacter, [CurRow,CurColumn,TokenStr[0]]);
+      end;
+      SetLength(Result, OldLength + SectionLength+1+Length(S));
+      if SectionLength > 0 then
+        Move(TokenStart^, Result[OldLength + 1], SectionLength);
+      Move(S[1],Result[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(Result, OldLength + SectionLength);
+  if SectionLength > 0 then
+    Move(TokenStart^, Result[OldLength + 1], SectionLength);
+  Inc(TokenStr);
+end;
+
+function TWebIDLScanner.ReadIdent: UTF8String;
+
+Var
+  TokenStart : PChar;
+  SectionLength : Integer;
+
+begin
+  Result:='';
+  if TokenStr[0]='_' then
+    Inc(TokenStr);
+  if TokenStr[0]=#0 then
+    Exit;
+  TokenStart := TokenStr;
+  repeat
+    Inc(TokenStr);
+  until not (TokenStr[0] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
+  SectionLength := TokenStr - TokenStart;
+  SetString(Result, TokenStart, SectionLength);
+end;
+
+function TWebIDLScanner.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;
+
+function TWebIDLScanner.ReadNumber(var S : UTF8String) : TIDLToken;
+
+Var
+  TokenStart : PChar;
+  SectionLength : Integer;
+  isHex : Boolean;
+
+begin
+  isHex:=False;
+  TokenStart := TokenStr;
+  Result:=tkNumberInteger;
+  while true do
+    begin
+    Inc(TokenStr);
+    SectionLength := TokenStr - TokenStart;
+    case TokenStr[0] of
+    'x':
+      begin
+      isHex:=True;
+      end;
+    'I':
+      begin
+      repeat
+        Inc(TokenStr);
+      until not (TokenStr[0] in ['i','n','f','t','y']);
+      Result:=tkNegInfinity; // We'll check at the end if the string is actually correct
+      break;
+      end;
+    '.':
+      begin
+      Result:=tkNumberFloat;
+      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':
+      begin
+      end;
+    'a'..'d','f',
+    'A'..'D','F':
+      begin
+      if Not isHex then
+        Error(SErrUnknownToken,[S]);
+      end;
+    'e', 'E':
+      begin
+      if not  IsHex then
+        begin
+        Inc(TokenStr);
+        if TokenStr[0] in ['-','+']  then
+          Inc(TokenStr);
+        while TokenStr[0] in ['0'..'9'] do
+          Inc(TokenStr);
+        break;
+        end;
+      end;
+    else
+      if (SectionLength=1) and (TokenStart[0]='-') then
+        result:=tkMinus;
+      break;
+    end;
+    end;
+  SectionLength := TokenStr - TokenStart;
+  S:='';
+  SetString(S, TokenStart, SectionLength);
+  if (Result=tkNegInfinity) and (S<>'-Infinity') then
+    Error(SErrUnknownToken,[S]);
+  if (Result=tkMinus) and (S<>'-') then
+    Error(SErrUnknownTerminator,[s]);
+end;
+
+function TWebIDLScanner.GetErrorPos: String;
+begin
+  Result:=Format('Scanner error at line %d, pos %d: ',[CurRow,CurColumn]);
+end;
+
+function TWebIDLScanner.ReadComment : UTF8String;
+
+Var
+  TokenStart : PChar;
+  SectionLength : Integer;
+  EOC,IsStar : Boolean;
+  S : String;
+
+begin
+  Result:='';
+  TokenStart:=TokenStr;
+  Inc(TokenStr);
+  Case Tokenstr[0] of
+    '/' : begin
+          SectionLength := Length(FCurLine)- (TokenStr - PChar(FCurLine));
+          Inc(TokenStr);
+          SetString(Result, TokenStr, SectionLength);
+          Fetchline;
+          end;
+    '*' :
+      begin
+      IsStar:=False;
+      Inc(TokenStr);
+      TokenStart:=TokenStr;
+      Repeat
+        if (TokenStr[0]=#0) then
+          begin
+          SectionLength := (TokenStr - TokenStart);
+          S:='';
+          SetString(S, TokenStart, SectionLength);
+          Result:=Result+S;
+          if not fetchLine then
+            Error(SUnterminatedComment, [CurRow,CurCOlumn,TokenStr[0]]);
+          TokenStart:=TokenStr;
+          end;
+        IsStar:=TokenStr[0]='*';
+        Inc(TokenStr);
+        EOC:=(isStar and (TokenStr[0]='/'));
+      Until EOC;
+      if EOC then
+        begin
+        SectionLength := (TokenStr - TokenStart-1);
+        S:='';
+        SetString(S, TokenStart, SectionLength);
+        Result:=Result+S;
+        Inc(TokenStr);
+        end;
+      end;
+  else
+    Error(SErrInvalidCharacter, [CurRow,CurCOlumn,TokenStr[0]]);
+  end;
+end;
+
+function TWebIDLScanner.DetermineToken : TIDLToken;
+
+begin
+  Result:=High(TIDLToken);
+  While (Result<>tkIdentifier) and (TokenInfos[result]<>FCurTokenString) do
+    Result:=Pred(Result);
+  if Result in VersionNonTokens[Version] then
+    Result:=tkIdentifier;
+//  if Result=tkIdentifier then
+//    Error(SErrExpectedTokenButWasIdentifier,[FCurTokenString]);
+end;
+
+function TWebIDLScanner.DetermineToken2 : TIDLToken;
+
+Const
+  InfTokens = [tkNan,tkInfinity,tkNegInfinity,tkByteString,tkUSVString,tkDOMString,tkPromise];
+
+begin
+  For Result in InfTokens do
+    if (TokenInfos[result]=FCurTokenString) then exit;
+  Result:=tkIdentifier;
+end;
+
+function TWebIDLScanner.DoFetchToken: TIDLToken;
+
+  Procedure SetSingleToken(tk : TIDLToken);
+
+  begin
+    FCurTokenString:=TokenStr[0];
+    Inc(TokenStr);
+    Result :=tk;
+  end;
+
+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
+      if not FetchLine then
+        Result:=tkEOF
+      else
+        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
+        FCurTokenString:=ReadString;
+        Result := tkString;
+      end;
+    ',':
+      begin
+        Inc(TokenStr);
+        Result := tkComma;
+      end;
+    '0'..'9','-':
+      begin
+      Result := ReadNumber(FCurTokenString);
+      end;
+    ':': SetSingleToken(tkColon);
+    '(': SetSingleToken(tkBracketOpen);
+    ')': SetSingleToken(tkBracketClose);
+    '{': SetSingleToken(tkCurlyBraceOpen);
+    '}': SetSingleToken(tkCurlyBraceClose);
+    '[': SetSingleToken(tkSquaredBraceOpen);
+    ']': SetSingleToken(tkSquaredBraceClose);
+    '<': SetSingleToken(tkLess);
+    '=': SetSingleToken(tkEqual);
+    '>': SetSingleToken(tkLarger);
+    '?' : SetSingleToken(tkQuestionmark);
+    ';' : SetSingleToken(tkSemicolon);
+    '.' :
+       begin
+       inc(TokenStr);
+       if TokenStr[0]<>'.' then
+         begin
+         Dec(Tokenstr);// Setsingletoken advances
+         SetSingleToken(tkDot);
+         end
+       else
+         begin
+         inc(TokenStr);
+         if TokenStr[0]<>'.' then
+           Error(SErrInvalidEllipsis);
+         FCurTokenString:='...';
+         Result:=tkEllipsis;
+         end;
+       end;
+    '/' :
+      begin
+      FCurTokenString:=ReadComment;
+      Result:=tkComment;
+      end;
+    'a'..'z':
+      begin
+      FCurTokenString:=ReadIdent;
+      Result:=DetermineToken;
+      end;
+    'A'..'Z','_':
+      begin
+      FCurTokenString:=ReadIdent;
+      Result:=tkIdentifier;
+      Result:=DetermineToken2;
+      end;
+  else
+    Error(SErrInvalidCharacter, [CurRow,CurCOlumn,TokenStr[0]]);
+  end;
+
+  FCurToken := Result;
+end;
+
+function TWebIDLScanner.GetCurColumn: Integer;
+begin
+  Result := TokenStr - PChar(CurLine);
+end;
+
+
+end.

+ 1326 - 0
packages/webidl/src/webidltopas.pp

@@ -0,0 +1,1326 @@
+unit webidltopas;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, contnrs, WebIDLParser, WebIDLScanner, WebIDLDefs, pascodegen;
+
+Type
+
+  { TWebIDLToPas }
+
+  { TPasData }
+
+  TPasData = Class(TObject)
+  private
+    FPasName: String;
+  Public
+    Constructor Create(APasName : String);
+    Property PasName : String read FPasName;
+  end;
+
+  TConversionOption = (coDictionaryAsClass,coUseNativeTypeAliases,coExternalConst,coExpandUnionTypeArgs,coaddOptionsToheader);
+  TConversionOptions = Set of TConversionOption;
+
+  TWebIDLToPas = Class(TPascalCodeGenerator)
+  private
+    FClassPrefix: String;
+    FClassSuffix: String;
+    FContext: TWebIDLContext;
+    FDictionaryClassParent: String;
+    FFieldPrefix: String;
+    FIncludeImplementationCode: TStrings;
+    FIncludeInterfaceCode: TStrings;
+    FInputFileName: String;
+    FOptions: TConversionOptions;
+    FOutputFileName: String;
+    FTypeAliases: TStrings;
+    FVerbose: Boolean;
+    FWebIDLVersion: TWebIDLVersion;
+    FPasNameList : TFPObjectList;
+    FAutoTypes : TStrings;
+    procedure SetIncludeImplementationCode(AValue: TStrings);
+    procedure SetIncludeInterfaceCode(AValue: TStrings);
+    procedure SetTypeAliases(AValue: TStrings);
+  Protected
+    procedure AddOptionsToHeader;
+    Procedure Parse; virtual;
+    Procedure WritePascal; virtual;
+    function CreateParser(aContext: TWebIDLContext; S: TWebIDLScanner): TWebIDLParser; virtual;
+    function CreateScanner(S: TStream): TWebIDLScanner;virtual;
+    Function CreateContext : TWebIDLContext; virtual;
+    Function BaseUnits : String; override;
+    // Auxiliary routines
+    procedure Getoptions(L: TStrings); virtual;
+    procedure ProcessDefinitions; virtual;
+    function CreatePasName(aName: String): TPasData;virtual;
+    procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String='');virtual;
+    Function AllocatePasName(D: TIDLDefinition; ParentName: String='') : TPasData;virtual;
+    procedure EnsureUniqueNames(ML: TIDLDefinitionList);virtual;
+    function WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer;virtual;
+    function GetName(ADef: TIDLDefinition): String;virtual;
+    function GetTypeName(Const aTypeName: String; ForTypeDef: Boolean=False): String;virtual;
+    function GetTypeName(aTypeDef: TIDLTypeDefDefinition; ForTypeDef: Boolean=False): String;virtual;
+    function CheckUnionTypeDefinition(D: TIDLDefinition): TIDLUnionTypeDefDefinition;virtual;
+    procedure AddArgumentToOverloads(aList: TFPObjectlist; AName, ATypeName: String);virtual;
+    procedure AddUnionOverloads(aList: TFPObjectlist; AName: String;  UT: TIDLUnionTypeDefDefinition);virtual;
+    procedure AddArgumentToOverloads(aList: TFPObjectlist; adef: TIDLArgumentDefinition);virtual;
+    procedure AddOverloads(aList: TFPObjectlist; adef: TIDLFunctionDefinition; aIdx: Integer);virtual;
+    function CloneNonPartialArgumentList(aList: TFPObjectlist; ADest: TFPObjectlist= Nil; AsPartial: Boolean=True): integer;virtual;
+    function GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist;virtual;
+    function GetArguments(aList: TIDLDefinitionList; ForceBrackets: Boolean): String;virtual;
+    function HaveConsts(aList: TIDLDefinitionList): Boolean;virtual;
+    // Actual code generation routines
+    // Lists. Return the number of actually written defs.
+    function WriteCallBackDefs(aList: TIDLDefinitionList): Integer; virtual;
+    Function WriteDictionaryDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    Function WriteForwardClassDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    Function WriteInterfaceDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    Function WriteMethodDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    Function WriteTypeDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    Function WriteEnumDefs(aList: TIDLDefinitionList) : Integer;virtual;
+    function WriteConsts(aList: TIDLDefinitionList): Integer;virtual;
+    function WriteProperties(aList: TIDLDefinitionList): Integer;
+    function WritePlainFields(aList: TIDLDefinitionList): Integer;virtual;
+    function WriteDictionaryFields(aList: TIDLDefinitionList): Integer;virtual;
+    function WritePrivateReadOnlyFields(aList: TIDLDefinitionList): Integer;virtual;
+    // Actual definitions. Return true if a definition was written.
+    Function WriteForwardClassDef(D: TIDLStructuredDefinition) : Boolean;virtual;
+    function WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition): Boolean;virtual;
+    function WriteFunctionDefinition(aDef: TIDLFunctionDefinition): Boolean;virtual;
+    function WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean; virtual;
+    function WriteRecordDef(aDef: TIDLRecordDefinition): Boolean; virtual;
+    function WriteEnumDef(aDef: TIDLEnumDefinition): Boolean; virtual;
+    function WriteDictionaryField(aField: TIDLDictionaryMemberDefinition): Boolean;virtual;
+    Function WritePrivateReadOnlyField(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
+    Function WriteField(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
+    Function WriteReadonlyProperty(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
+    Function WriteConst(aConst: TIDLConstDefinition) : Boolean ;virtual;
+    function WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean; virtual;
+    function WriteDictionaryDef(aDict: TIDLDictionaryDefinition): Boolean; virtual;
+    // Additional
+    procedure WriteAliasTypeDef(aDef: TIDLTypeDefDefinition);virtual;
+    procedure WritePromiseDef(aDef: TIDLPromiseTypeDefDefinition);virtual;
+    procedure WriteSequenceDef(aDef: TIDLSequenceTypeDefDefinition);virtual;
+    procedure WriteUnionDef(aDef: TIDLUnionTypeDefDefinition);virtual;
+    // Extra interface/Implementation code.
+    procedure WriteImplementation; virtual;
+    procedure WriteIncludeInterfaceCode; virtual;
+    Property Context : TWebIDLContext Read FContext;
+  Public
+    Constructor Create(Aowner : TComponent); override;
+    Destructor Destroy; override;
+    Procedure Execute;
+  Published
+    Property InputFileName : String Read FInputFileName Write FInputFileName;
+    Property OutputFileName : String Read FOutputFileName Write FOutputFileName;
+    Property Verbose : Boolean Read FVerbose Write FVerbose;
+    Property FieldPrefix : String Read FFieldPrefix Write FFieldPrefix;
+    Property ClassPrefix : String Read FClassPrefix Write FClassPrefix;
+    Property ClassSuffix : String Read FClassSuffix Write FClassSuffix;
+    Property Options : TConversionOptions Read FOptions Write FOptions;
+    Property WebIDLVersion : TWebIDLVersion Read FWebIDLVersion Write FWebIDLVersion;
+    Property TypeAliases : TStrings Read FTypeAliases Write SetTypeAliases;
+    Property IncludeInterfaceCode : TStrings Read FIncludeInterfaceCode Write SetIncludeInterfaceCode;
+    Property IncludeImplementationCode : TStrings Read FIncludeImplementationCode Write SetIncludeImplementationCode;
+    Property DictionaryClassParent : String Read FDictionaryClassParent Write FDictionaryClassParent;
+  end;
+
+implementation
+
+uses typinfo;
+
+{ TPasData }
+
+constructor TPasData.Create(APasName: String);
+begin
+  FPasName:=APasName;
+end;
+
+{ TWebIDLToPas }
+
+function TWebIDLToPas.CreateContext: TWebIDLContext;
+begin
+  Result:=TWebIDLContext.Create(True);
+end;
+
+function TWebIDLToPas.CreateScanner(S : TStream) :  TWebIDLScanner;
+
+begin
+  Result:=TWebIDLScanner.Create(S);
+end;
+
+function TWebIDLToPas.CreateParser(aContext : TWebIDLContext;S : TWebIDLScanner) :  TWebIDLParser;
+
+begin
+  Result:=TWebIDLParser.Create(aContext,S);
+  Result.Version:=FWebIDLVersion;
+end;
+
+procedure TWebIDLToPas.Parse;
+
+Var
+  F : TFileStream;
+  S : TWebIDLScanner;
+  P : TWebIDLParser;
+
+begin
+  P:=Nil;
+  F:=TFileStream.Create(InputFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    S:=CreateScanner(F);
+    P:=CreateParser(Context,S);
+    P.Parse;
+  finally
+    P.Free;
+    S.Free;
+    F.Free;
+  end;
+end;
+
+function TWebIDLToPas.GetName(ADef: TIDLDefinition): String;
+
+begin
+  If Assigned(ADef) and (TObject(ADef.Data) is TPasData) then
+    Result:=TPasData(ADef.Data).PasName
+  else
+    Result:=ADef.Name;
+end;
+
+function TWebIDLToPas.HaveConsts(aList: TIDLDefinitionList): Boolean;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  Result:=False;
+  For D in aList do
+    if D is TIDLConstDefinition then
+      Exit(True);
+end;
+
+function TWebIDLToPas.WritePrivateReadOnlyFields(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  A : TIDLAttributeDefinition absolute D;
+
+begin
+  Result:=0;
+  For D in aList do
+    if (D is TIDLAttributeDefinition) then
+      if (aoReadOnly in A.Options) then
+        if WritePrivateReadOnlyField(A) then
+          Inc(Result);
+end;
+
+function TWebIDLToPas.WriteProperties(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  A : TIDLAttributeDefinition absolute D;
+
+begin
+  Result:=0;
+  For D in aList do
+    if (D is TIDLAttributeDefinition) then
+      if (aoReadOnly in A.Options) then
+        if WriteReadOnlyProperty(A) then
+          Inc(Result);
+end;
+
+function TWebIDLToPas.WriteConst(aConst: TIDLConstDefinition): Boolean;
+
+Const
+  ConstTypes : Array[TConstType] of String =
+     ('Double','NativeInt','Boolean','JSValue','JSValue','JSValue','JSValue','String','JSValue');
+Var
+  S : String;
+
+begin
+  Result:=True;
+  // Consts cannot be strings
+  if coExternalConst in Options then
+    begin
+    S:=ConstTypes[aConst.ConstType];
+    Addln('%s : %s;',[GetName(aConst),S])
+    end
+  else
+    begin
+    S:=aConst.Value;
+    if aConst.ConstType=ctInteger then
+      S:=StringReplace(S,'0x','$',[]);
+    Addln('%s = %s;',[GetName(aConst),S])
+    end;
+end;
+
+function TWebIDLToPas.WriteConsts(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  EnsureSection(csConst);
+  Indent;
+  Result:=0;
+  For D in aList do
+    if D is TIDLConstDefinition then
+      if WriteConst(D as TIDLConstDefinition) then
+        Inc(Result);
+  Undent;
+end;
+
+function TWebIDLToPas.WritePlainFields(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  A : TIDLAttributeDefinition absolute D;
+
+begin
+  EnsureSection(csDeclaration);
+  Indent;
+  Result:=0;
+  For D in aList do
+    if D is TIDLAttributeDefinition then
+      if Not (aoReadOnly in A.Options) then
+        if WriteField(A) then
+          Inc(Result);
+  Undent;
+end;
+
+function TWebIDLToPas.WriteDictionaryField(
+  aField: TIDLDictionaryMemberDefinition): Boolean;
+
+Var
+  Def,N,TN : String;
+
+begin
+  Result:=True;
+  N:=GetName(aField);
+  TN:=GetTypeName(aField.MemberType);
+  if TN='record' then
+    TN:='TJSObject';
+  if SameText(N,TN) then
+    N:='_'+N;
+  Def:=Format('%s : %s;',[N,TN]);
+  if (N<>aField.Name) then
+    Def:=Def+Format('external name ''%s'';',[aField.Name]);
+  AddLn(Def);
+end;
+
+function TWebIDLToPas.WriteDictionaryFields(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  M : TIDLDictionaryMemberDefinition absolute D;
+
+begin
+  Indent;
+  Result:=0;
+  For D in aList do
+    if D is TIDLDictionaryMemberDefinition then
+      if WriteDictionaryField(M) then
+        Inc(Result);
+  Undent;
+end;
+
+function TWebIDLToPas.WriteMethodDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  FD : TIDLFunctionDefinition absolute D;
+
+begin
+  Result:=0;
+  for D in aList do
+    if D is TIDLFunctionDefinition then
+      if Not (foCallBack in FD.Options) then
+         if WriteFunctionDefinition(FD) then
+           Inc(Result);
+end;
+
+function TWebIDLToPas.WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer;
+
+
+  Procedure AddSequenceDef (ST : TIDLSequenceTypeDefDefinition);
+
+  var
+    TN : String;
+  begin
+    TN:=GetTypeName(ST);
+    if FAutoTypes.IndexOf(TN)=-1 then
+      begin
+      FAutoTypes.Add(TN);
+      DoLog('Automatically adding %s sequence definition.',[TN]);
+      AddLn('%s = Array of %s;',[TN,GetTypeName(ST.ElementType)]);
+      ST.Data:=CreatePasName(TN);
+      Inc(Result);
+      end;
+  end;
+
+Var
+  D,D2,D3 : TIDLDefinition;
+  FD : TIDLFunctionDefinition absolute D;
+  DA : TIDLArgumentDefinition absolute D2;
+  UT : TIDLUnionTypeDefDefinition;
+
+begin
+  Result:=0;
+  for D in aList do
+    if D is TIDLFunctionDefinition then
+      if Not (foCallBack in FD.Options) then
+        begin
+        if (FD.ReturnType is TIDLSequenceTypeDefDefinition) then
+          AddSequenceDef(FD.ReturnType as TIDLSequenceTypeDefDefinition);
+        For D2 in FD.Arguments do
+          if (DA.ArgumentType is TIDLSequenceTypeDefDefinition) then
+            AddSequenceDef(DA.ArgumentType as TIDLSequenceTypeDefDefinition)
+          else
+            begin
+            UT:=CheckUnionTypeDefinition(DA.ArgumentType);
+            if Assigned(UT) then
+              For D3 in UT.Union do
+                if (D3 is TIDLSequenceTypeDefDefinition) then
+                  AddSequenceDef(D3 as TIDLSequenceTypeDefDefinition);
+            end;
+        end;
+  if Result>0 then
+    AddLn('');
+end;
+
+procedure TWebIDLToPas.EnsureUniqueNames(ML : TIDLDefinitionList);
+
+Var
+  L : TFPObjectHashTable;
+
+  Procedure CheckRename(aD : TIDLDefinition);
+
+  var
+    I : integer;
+    P : TPasData;
+    NOrig,N,N2 : String;
+    isDup : Boolean;
+    D2 : TIDLDefinition;
+
+  begin
+    NOrig:=GetName(aD);
+    N:=LowerCase(NOrig);
+    N2:=N;
+    I:=0;
+    isDup:=False;
+    Repeat
+      D2:=TIDLDefinition(L.Items[N2]);
+      if (D2<>Nil) then
+        // Overloads
+        begin
+        isDup:=((D2 is TIDLFunctionDefinition) and (ad is TIDLFunctionDefinition));
+        if IsDup then
+          D2:=Nil
+        else
+          begin
+          inc(I);
+          N2:=KeywordPrefix+N+KeywordSuffix;
+          Norig:=KeywordPrefix+NOrig+KeywordSuffix;
+          end;
+        end;
+    Until (D2=Nil);
+    if (N<>N2) then
+      begin
+      N:=GetName(aD);
+      DoLog('Renaming duplicate identifier (%s) %s to %s',[aD.ClassName,N,Norig]);
+      // Original TPasName is in list, will be freed automatically
+      aD.Data:=CreatePasName(NOrig);
+      end;
+    if not IsDup then
+      L.Add(N2,aD);
+  end;
+
+var
+  D : TIDLDefinition;
+
+begin
+  L:=TFPObjectHashTable.Create(False);
+  try
+    For D in ML Do
+      if not (D is TIDLConstDefinition) then
+        CheckRename(D);
+    For D in ML Do
+      if (D is TIDLConstDefinition) then
+        CheckRename(D);
+  finally
+    L.Free;
+  end;
+end;
+
+function TWebIDLToPas.WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean;
+
+Var
+  CN,PN : String;
+  Decl : String;
+  ML : TIDLDefinitionList;
+
+begin
+  Result:=True;
+  ML:=TIDLDefinitionList.Create(Nil,False);
+  try
+    Intf.GetFullMemberList(ML);
+    EnsureUniqueNames(ML);
+    CN:=GetName(Intf);
+    ClassHeader(CN);
+    WriteFunctionImplicitTypes(ML);
+    Decl:=Format('%s = class external name %s ',[CN,MakePascalString(Intf.Name,True)]);
+    if Assigned(Intf.ParentInterface) then
+      PN:=GetName(Intf.ParentInterface)
+    else
+      PN:=GetTypeName(Intf.ParentName);
+    if PN<>'' then
+      Decl:=Decl+Format(' (%s)',[PN]);
+    AddLn(Decl);
+    AddLn('Private');
+    Indent;
+    WritePrivateReadOnlyFields(ML);
+    Undent;
+    AddLn('Public');
+    if HaveConsts(ML) then
+      begin
+      Indent;
+      PushSection(csUnknown);
+      WriteConsts(ML);
+      PopSection;
+      Undent;
+      AddLn('Public');
+      end;
+    Indent;
+    WritePlainFields(ML);
+    WriteMethodDefs(ML);
+    WriteProperties(ML);
+    Undent;
+    AddLn('end;');
+  finally
+    ML.Free;
+  end;
+end;
+
+function TWebIDLToPas.WriteDictionaryDef(aDict: TIDLDictionaryDefinition
+  ): Boolean;
+
+Var
+  CN,CP : String;
+  ML : TIDLDefinitionList;
+  PD: TIDLDictionaryDefinition;
+
+begin
+  Result:=True;
+  ML:=TIDLDefinitionList.Create(Nil,False);
+  try
+    PD:=aDict;
+    While PD<>Nil do
+      begin
+      PD.GetFullMemberList(ML);
+      PD:=PD.ParentDictionary;
+      end;
+    CN:=GetName(aDict);
+    CP:=DictionaryClassParent;
+    if CP='' then
+      CP:='TJSObject';
+    ClassHeader(CN);
+    if (coDictionaryAsClass in Options) then
+      Addln('%s = class(%s)',[CN,CP])
+    else
+      Addln('%s = record',[CN]);
+    WriteDictionaryFields(ML);
+    AddLn('end;');
+  finally
+    ML.Free;
+  end;
+end;
+
+constructor TWebIDLToPas.Create(Aowner: TComponent);
+begin
+  inherited Create(Aowner);
+  WebIDLVersion:=v2;
+  FieldPrefix:='F';
+  ClassPrefix:='T';
+  ClassSuffix:='';
+  Switches.Add('modeswitch externalclass');
+  FTypeAliases:=TStringList.Create;
+  FPasNameList:=TFPObjectList.Create(True);
+  FAutoTypes:=TStringList.Create;
+  FIncludeInterfaceCode:=TStringList.Create;
+  FIncludeImplementationCode:=TStringList.Create;
+end;
+
+
+destructor TWebIDLToPas.Destroy;
+begin
+  FreeAndNil(FIncludeInterfaceCode);
+  FreeAndNil(FIncludeImplementationCode);
+  FreeAndNil(FAutoTypes);
+  FreeAndNil(FTypeAliases);
+  FreeAndNil(FPasNameList);
+  inherited Destroy;
+end;
+
+procedure TWebIDLToPas.WriteImplementation;
+
+Var
+  S : String;
+
+begin
+  Addln('');
+  For S in FIncludeImplementationCode do
+    Addln(S);
+  Addln('');
+end;
+
+function TWebIDLToPas.GetTypeName(aTypeDef : TIDLTypeDefDefinition; ForTypeDef : Boolean = False): String;
+
+begin
+  if ATypeDef is TIDLSequenceTypeDefDefinition then
+    begin
+    if Assigned(aTypeDef.Data) then
+      Result:=GetName(aTypeDef)
+    else
+      begin
+      Result:=GetTypeName(TIDLSequenceTypeDefDefinition(aTypeDef).ElementType,ForTypeDef);
+      Result:='T'+Result+'DynArray';
+      end
+    end
+  else
+    Result:=GetTypeName(aTypeDef.TypeName,ForTypeDef);
+end;
+
+function TWebIDLToPas.GetTypeName(const aTypeName: String; ForTypeDef: Boolean
+  ): String;
+
+
+  Function UsePascalType(Const aPascalType : string) : String;
+
+  begin
+    if (coUseNativeTypeAliases in Options) and ForTypeDef then
+      Result:=StringReplace(aTypeName,' ','',[rfReplaceAll])
+    else
+      Result:=aPascalType;
+  end;
+
+Var
+  A,TN : UTF8String;
+  D : TIDLDefinition;
+
+begin
+  Case aTypeName of
+    'union': TN:='JSValue';
+    'short': TN:=UsePascalType('Integer');
+    'long': TN:=UsePascalType('Integer');
+    'long long': TN:=UsePascalType('NativeInt');
+    'unsigned short': TN:=UsePascalType('Cardinal');
+    'unrestricted float': TN:=UsePascalType('Double');
+    'unsigned long': TN:=UsePascalType('NativeInt');
+    'unsigned long long': TN:=UsePascalType('NativeInt');
+    'octet': TN:=UsePascalType('Byte');
+    'any' : TN:=UsePascalType('JSValue');
+    'float' : TN:=UsePascalType('Double');
+    'double' : TN:=UsePascalType('Double');
+    'DOMString',
+    'USVString',
+    'ByteString' : TN:=UsePascalType('String');
+    'object' : TN:=UsePascalType('TJSObject');
+    'Error' : TN:=UsePascalType('TJSError');
+    'DOMException' : TN:=UsePascalType('TJSError');
+    'ArrayBuffer',
+    'DataView',
+    'Int8Array',
+    'Int16Array',
+    'Int32Array',
+    'Uint8Array',
+    'Uint16Array',
+    'Uint32Array',
+    'Uint8ClampedArray',
+    'Float32Array',
+    'Float64Array' : TN:='TJS'+aTypeName;
+  else
+    TN:=aTypeName;
+    D:=FContext.FindDefinition(TN);
+    if D<>Nil then
+      TN:=GetName(D)
+    else
+      begin
+      A:=FTypeAliases.Values[TN];
+      If (A<>'') then
+        TN:=A;
+      end;
+  end;
+  Result:=TN;
+end;
+
+function TWebIDLToPas.WritePrivateReadOnlyField(aAttr: TIDLAttributeDefinition
+  ): Boolean;
+
+begin
+  AddLn('%s%s : %s; external name ''%s''; ',[FieldPrefix,GetName(aAttr),GetTypeName(aAttr.AttributeType),aAttr.Name]);
+end;
+
+function TWebIDLToPas.WriteField(aAttr: TIDLAttributeDefinition): Boolean;
+
+Var
+  Def,TN,N : String;
+
+begin
+  Result:=True;
+  N:=GetName(aAttr);
+  TN:=GetTypeName(aAttr.AttributeType);
+  if TN='record' then
+    TN:='TJSObject';
+  if SameText(N,TN) then
+    N:='_'+N;
+  Def:=Format('%s : %s;',[N,TN]);
+  if (N<>aAttr.Name) then
+    Def:=Def+Format('external name ''%s'';',[aAttr.Name]);
+  AddLn(Def);
+end;
+
+function TWebIDLToPas.WriteReadonlyProperty(aAttr: TIDLAttributeDefinition
+  ): Boolean;
+
+Var
+  N : String;
+
+begin
+  Result:=True;
+  N:=GetName(aAttr);
+  AddLn('Property %s : %s Read %s%s; ',[N,GetTypeName(aAttr.AttributeType),FieldPrefix,N]);
+end;
+
+
+function TWebIDLToPas.WriteForwardClassDef(D: TIDLStructuredDefinition): Boolean;
+
+begin
+  Result:=not D.IsPartial;
+  if Result then
+    AddLn('%s = Class;',[GetName(D)]);
+end;
+
+function TWebIDLToPas.WriteForwardClassDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+
+begin
+  Result:=0;
+  Comment('Forward class definitions');
+  For D in aList do
+    if D is TIDLInterfaceDefinition then
+      if WriteForwardClassDef(D as TIDLInterfaceDefinition) then
+        Inc(Result);
+  if coDictionaryAsClass in Options then
+    For D in aList do
+      if D is TIDLDictionaryDefinition then
+        if WriteForwardClassDef(D as TIDLDictionaryDefinition) then
+          Inc(Result);
+end;
+
+procedure TWebIDLToPas.WriteSequenceDef(aDef : TIDLSequenceTypeDefDefinition);
+
+begin
+  Addln('%s = array of %s;',[GetName(aDef),GetTypeName(aDef.ElementType)])
+end;
+
+
+procedure TWebIDLToPas.WriteUnionDef(aDef : TIDLUnionTypeDefDefinition);
+
+Var
+  S : UTF8String;
+  D : TIDLDefinition;
+begin
+  S:='';
+  For D in adef.Union do
+    begin
+    if (S<>'') then
+      S:=S+', ';
+    S:=S+(D as TIDLTypeDefDefinition).TypeName;
+    end;
+  Comment('Union of '+S);
+  AddLn('%s = JSValue; ',[GetName(aDef)])
+end;
+
+
+procedure TWebIDLToPas.WritePromiseDef(aDef : TIDLPromiseTypeDefDefinition);
+
+begin
+  AddLn('%s = TJSPromise;',[GetName(aDef)]);
+end;
+
+procedure TWebIDLToPas.WriteAliasTypeDef(aDef : TIDLTypeDefDefinition);
+
+Var
+  TN : String;
+
+begin
+  TN:=GetTypeName(aDef,True);
+  AddLn('%s = %s;',[GetName(aDef),TN]);
+end;
+
+function TWebIDLToPas.WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean;
+
+begin
+  Result:=True;
+  if ADef is TIDLSequenceTypeDefDefinition then
+    WriteSequenceDef(aDef as TIDLSequenceTypeDefDefinition)
+  else if ADef is TIDLUnionTypeDefDefinition then
+    WriteUnionDef(aDef as TIDLUnionTypeDefDefinition)
+  else if ADef is TIDLPromiseTypeDefDefinition then
+    WritePromiseDef(aDef as TIDLPromiseTypeDefDefinition)
+  else if ADef is TIDLRecordDefinition then
+    WriteRecordDef(aDef as TIDLRecordDefinition)
+  else
+    WriteAliasTypeDef(aDef);
+end;
+
+function TWebIDLToPas.WriteRecordDef(aDef: TIDLRecordDefinition): Boolean;
+
+Var
+  KT,VT : String;
+
+begin
+  Result:=True;
+  KT:=GetTypeName(aDef.KeyType);
+  VT:=GetTypeName(aDef.ValueType);
+  AddLn('%s = Class(TJSObject)',[GetName(aDef)]);
+  AddLn('private');
+  Indent;
+  AddLn('function GetValue(aKey: %s): %s; external name ''[]'';',[KT,VT]);
+  AddLn('procedure SetValue(aKey: %s; const AValue: %s); external name ''[]'';',[KT,VT]);
+  undent;
+  AddLn('public');
+  Indent;
+  AddLn('property Values[Name: %s]: %s read GetProperties write SetProperties; default;',[KT,VT]);
+  undent;
+  AddLn('end;');
+end;
+
+function TWebIDLToPas.WriteTypeDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  TD : TIDLTypeDefDefinition absolute D;
+
+begin
+  Result:=0;
+  EnsureSection(csType);
+  for D in aList do
+    if D is TIDLTypeDefDefinition then
+      if WriteTypeDef(TD) then
+        Inc(Result);
+end;
+
+function TWebIDLToPas.WriteEnumDef(aDef: TIDLEnumDefinition): Boolean;
+
+begin
+  Result:=True;
+  AddLn('%s = String;',[GetName(aDef)]);
+end;
+
+function TWebIDLToPas.WriteEnumDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  ED : TIDLEnumDefinition absolute D;
+
+begin
+  Result:=0;
+  EnsureSection(csType);
+  for D in aList do
+    if D is TIDLEnumDefinition then
+      if WriteEnumDef(ED) then
+        Inc(Result);
+end;
+
+function TWebIDLToPas.GetArguments(aList: TIDLDefinitionList;
+  ForceBrackets: Boolean): String;
+
+Var
+  I : TIDLDefinition;
+  A : TIDLArgumentDefinition absolute I;
+  Arg : string;
+
+begin
+  Result:='';
+  For I in aList do
+    begin
+    Arg:=GetName(A);
+    Arg:=Arg+' : '+GetTypeName(A.ArgumentType);
+    if Result<>'' then
+      Result:=Result+'; ';
+    Result:=Result+Arg;
+    end;
+  if (Result<>'') or ForceBrackets then
+    Result:='('+Result+')';
+end;
+
+Type
+  // A partial argument list is a list which has been generated for a optional argument.
+  // Additional arguments can never be added to a partial list...
+  TIDLPartialDefinitionList = Class(TIDLDefinitionList);
+
+function TWebIDLToPas.CloneNonPartialArgumentList(aList: TFPObjectlist;
+  ADest: TFPObjectlist; AsPartial: Boolean): integer;
+
+Var
+  I,J : Integer;
+  CD : TIDLDefinition;
+  DL,CL : TIDLDefinitionList;
+
+begin
+  Result:=0;
+  if ADest=Nil then
+    ADest:=aList;
+  I:=aList.Count-1;
+  While (I>=0) do
+    begin
+    DL:=TIDLDefinitionList(alist[i]);
+    if Not (DL is TIDLPartialDefinitionList) then
+      begin
+      Inc(Result);
+      if AsPartial then
+        CL:=TIDLPartialDefinitionList.Create(Nil,True)
+      else
+        CL:=TIDLDefinitionList.Create(Nil,True);
+      aDest.Add(CL);
+      For J:=0 to DL.Count-1 do
+        begin
+        CD:=(DL.Definitions[J] as TIDLArgumentDefinition).Clone(Nil);
+        CL.Add(CD);
+        AllocatePasName(CD);
+        end;
+      end;
+    Dec(I);
+    end;
+end;
+
+procedure TWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; AName,ATypeName : String);
+
+Var
+  I : Integer;
+  CD : TIDLArgumentDefinition;
+  DL : TIDLDefinitionList;
+
+begin
+  For I:=0 to aList.Count-1 do
+    begin
+    DL:=TIDLDefinitionList(alist[i]);
+    if Not (DL is TIDLPartialDefinitionList) then
+      begin
+      CD:=TIDLArgumentDefinition.Create(Nil,aName);
+      CD.ArgumentType:=TIDLTypeDefDefinition.Create(CD,'');
+      CD.ArgumentType.TypeName:=aTypeName;
+      DL.Add(CD);
+      AllocatePasName(cd,'');
+      end;
+    end;
+end;
+
+procedure TWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; adef: TIDLArgumentDefinition);
+
+Var
+  I : Integer;
+  CD : TIDLDefinition;
+  DL : TIDLDefinitionList;
+
+begin
+  For I:=0 to aList.Count-1 do
+    begin
+    DL:=TIDLDefinitionList(alist[i]);
+    if Not (DL is TIDLPartialDefinitionList) then
+      begin
+      CD:=aDef.Clone(Nil);
+      DL.Add(CD);
+      if aDef.Data<>Nil then
+        CD.Data:=CreatePasName(TPasData(aDef.Data).PasName)
+      else
+        AllocatePasName(cd,'');
+      end;
+    end;
+end;
+
+procedure TWebIDLToPas.AddUnionOverloads(aList: TFPObjectlist; AName : String; UT : TIDLUnionTypeDefDefinition);
+
+Var
+  L,L2 : TFPObjectList;
+  I,J : Integer;
+  D : TIDLDefinitionList;
+  Dups : TStringList;
+
+begin
+  L2:=Nil;
+  Dups:=TStringList.Create;
+  Dups.Sorted:=True;
+  Dups.Duplicates:=dupIgnore;
+  L:=TFPObjectList.Create(False);
+  try
+    L2:=TFPObjectList.Create(False);
+    // Collect non partial argument lists
+    for I:=0 to AList.Count-1 do
+      begin
+      D:=TIDLDefinitionList(alist[i]);
+      if Not (D is TIDLPartialDefinitionList) then
+        L.Add(D);
+      end;
+    // Collect unique pascal types. Note that this can reduce the list to 1 element...
+    For I:=0 to UT.Union.Count-1 do
+      Dups.AddObject(GetTypeName(UT.Union[I] as TIDLTypeDefDefinition),UT.Union[I]);
+    // First, clone list and add argument to cloned lists
+    For I:=1 to Dups.Count-1 do
+      begin
+      // Clone list
+      CloneNonPartialArgumentList(L,L2,False);
+      // Add argument to cloned list
+      AddArgumentToOverloads(L2,aName,Dups[i]);
+      // Add overloads to original list
+      For J:=0 to L2.Count-1 do
+        aList.Add(L2[J]);
+      L2.Clear;
+      end;
+    // Add first Union to original list
+    AddArgumentToOverloads(L,aName,Dups[0]);
+  finally
+    Dups.Free;
+    L2.Free;
+    L.Free;
+  end;
+end;
+
+function TWebIDLToPas.CheckUnionTypeDefinition(D: TIDLDefinition
+  ): TIDLUnionTypeDefDefinition;
+
+begin
+  Result:=Nil;
+  If (D is TIDLUnionTypeDefDefinition) then
+    Result:=D as TIDLUnionTypeDefDefinition
+  else
+    begin
+    D:=Context.FindDefinition((D as TIDLTypeDefDefinition).TypeName);
+    if (D is TIDLUnionTypeDefDefinition) then
+      Result:=D as TIDLUnionTypeDefDefinition
+    end
+end;
+
+procedure TWebIDLToPas.AddOverloads(aList: TFPObjectlist;
+  adef: TIDLFunctionDefinition; aIdx: Integer);
+
+Var
+  Arg : TIDLArgumentDefinition;
+  D : TIDLDefinition;
+  UT : TIDLUnionTypeDefDefinition;
+
+begin
+ if aIdx>=ADef.Arguments.Count then
+    exit;
+  Arg:=ADef.Argument[aIdx];
+  if Arg.IsOptional then
+    CloneNonPartialArgumentList(aList);
+  // Add current to list.
+  D:=Arg.ArgumentType;
+  UT:=Nil;
+  if coExpandUnionTypeArgs in Options then
+    UT:=CheckUnionTypeDefinition(D);
+  if UT=Nil then
+    AddArgumentToOverloads(aList,Arg)
+  else
+    AddUnionOverLoads(aList,Arg.Name,UT);
+  AddOverloads(aList,aDef,aIdx+1);
+end;
+
+function TWebIDLToPas.GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist;
+
+begin
+  Result:=TFPObjectList.Create;
+  try
+    Result.Add(TIDLDefinitionList.Create(Nil,True));
+    AddOverloads(Result,adef,0);
+  except
+    Result.Free;
+    Raise;
+  end;
+end;
+
+function TWebIDLToPas.WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition): Boolean;
+
+Var
+  FN,RT,Args : String;
+
+begin
+  Result:=True;
+  FN:=GetName(aDef);
+  RT:=GetTypeName(aDef.ReturnType,False);
+  if (RT='void') then
+    RT:='';
+  Args:=GetArguments(aDef.Arguments,False);
+  if (RT='') then
+    AddLn('%s = Procedure %s;',[FN,Args])
+  else
+    AddLn('%s = function %s: %s;',[FN,Args,RT])
+end;
+
+function TWebIDLToPas.WriteFunctionDefinition(aDef: TIDLFunctionDefinition): Boolean;
+
+Var
+  FN,RT,Suff,Args : String;
+  Overloads : TFPObjectList;
+  I : Integer;
+
+begin
+  Result:=True;
+  FN:=GetName(aDef);
+  if FN<>aDef.Name then
+    Suff:=Format('; external name ''%s''',[aDef.Name]);
+  RT:=GetTypeName(aDef.ReturnType,False);
+  if (RT='void') then
+    RT:='';
+  Overloads:=GetOverloads(ADef);
+  try
+    if Overloads.Count>1 then
+      Suff:=Suff+'; overload';
+    For I:=0 to Overloads.Count-1 do
+      begin
+      Args:=GetArguments(TIDLDefinitionList(Overloads[i]),False);
+      if (RT='') then
+        AddLn('Procedure %s%s%s;',[FN,Args,Suff])
+      else
+        AddLn('function %s%s: %s%s;',[FN,Args,RT,Suff])
+      end;
+  finally
+    Overloads.Free;
+  end;
+end;
+
+function TWebIDLToPas.WriteCallBackDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  FD : TIDLFunctionDefinition absolute D;
+
+begin
+  Result:=0;
+  EnsureSection(csType);
+  for D in aList do
+    if D is TIDLFunctionDefinition then
+      if (foCallBack in FD.Options) then
+         if WriteFunctionTypeDefinition(FD) then
+           Inc(Result);
+end;
+
+function TWebIDLToPas.WriteDictionaryDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  DD : TIDLDictionaryDefinition absolute D;
+
+begin
+  Result:=0;
+  EnsureSection(csType);
+  for D in aList do
+    if D is TIDLDictionaryDefinition then
+      if WriteDictionaryDef(DD) then
+        Inc(Result);
+end;
+
+function TWebIDLToPas.WriteInterfaceDefs(aList: TIDLDefinitionList): Integer;
+
+Var
+  D : TIDLDefinition;
+  ID : TIDLInterfaceDefinition absolute D;
+
+begin
+  Result:=0;
+  EnsureSection(csType);
+  for D in aList do
+    if D is TIDLInterfaceDefinition then
+      if WriteInterfaceDef(ID) then
+        Inc(Result);
+end;
+
+procedure TWebIDLToPas.Getoptions(L : TStrings);
+
+Var
+  S : String;
+  I : Integer;
+
+begin
+  L.Add('Automatically generated file by '+ClassName+' on '+FormatDateTime('yyyy-mm-dd hh:nn:ss',Now));
+  L.Add('');
+  L.Add('Used command-line options : ');
+  For I:=1 to ParamCount do
+    L.Add(ParamStr(i));
+  L.Add('');
+  L.Add('Command-line options translate to: ');
+  L.Add('');
+  S:=SetToString(PtypeInfo(TypeInfo(TConversionOptions)),Integer(OPtions),True);
+  L.Add('Options : '+S);
+  L.Add('Keyword prefix : '+KeywordPrefix);
+  L.Add('Keyword suffix : '+KeywordSuffix);
+  L.Add('Class prefix : '+ClassPrefix);
+  L.Add('Class suffix : '+ClassSuffix);
+  L.Add('Field prefix : '+FieldPrefix);
+  Str(WebIDLversion,S);
+  L.Add('WEBIDLversion : '+S);
+  if TypeAliases.Count>0 then
+    begin
+    L.Add('Type aliases:');
+    L.AddStrings(Self.TypeAliases);
+    end;
+end;
+
+procedure TWebIDLToPas.AddOptionsToHeader;
+
+Var
+  L : TStrings;
+begin
+  L:=TStringList.Create;
+  try
+    GetOptions(L);
+    Comment(L);
+  finally
+    L.Free;
+  end;
+end;
+
+procedure TWebIDLToPas.WriteIncludeInterfaceCode;
+
+Var
+  S : String;
+
+begin
+  For S in IncludeInterfaceCode do
+    Addln(S);
+end;
+
+procedure TWebIDLToPas.WritePascal;
+
+begin
+  CreateUnitClause;
+  CreateHeader;
+  if coaddOptionsToheader in Options then
+    AddOptionsToHeader;
+  EnsureSection(csType);
+  Indent;
+  WriteForwardClassDefs(Context.Definitions);
+  WriteEnumDefs(Context.Definitions);
+  WriteTypeDefs(Context.Definitions);
+  WriteCallbackDefs(Context.Definitions);
+  WriteDictionaryDefs(Context.Definitions);
+  WriteInterfaceDefs(Context.Definitions);
+  Undent;
+  WriteIncludeInterfaceCode;
+  Addln('');
+  AddLn('implementation');
+  WriteImplementation;
+  AddLn('end.');
+  Source.SaveToFile(OutputFileName);
+end;
+
+function TWebIDLToPas.BaseUnits: String;
+
+begin
+  Result:='SysUtils, JS'
+end;
+
+function TWebIDLToPas.CreatePasName(aName: String): TPasData;
+
+begin
+  Result:=TPasData.Create(EscapeKeyWord(aName));
+  FPasNameList.Add(Result);
+end;
+
+function TWebIDLToPas.AllocatePasName(D: TIDLDefinition; ParentName: String): TPasData;
+
+Var
+  CN : String;
+
+begin
+  if D Is TIDLInterfaceDefinition then
+    begin
+    CN:=ClassPrefix+D.Name+ClassSuffix;
+    Result:=CreatePasname(CN);
+    D.Data:=Result;
+    AllocatePasNames((D as TIDLInterfaceDefinition).members,D.Name);
+    end
+  else if D Is TIDLDictionaryDefinition then
+    begin
+    CN:=D.Name;
+    if coDictionaryAsClass in Options then
+      CN:=ClassPrefix+CN+ClassSuffix;
+    Result:=CreatePasname(EscapeKeyWord(CN));
+    D.Data:=Result;
+    AllocatePasNames((D as TIDLDictionaryDefinition).members,D.Name);
+    end
+  else
+    begin
+    Result:=CreatePasName(D.Name);
+    D.Data:=Result;
+    if D Is TIDLFunctionDefinition then
+      AllocatePasNames((D as TIDLFunctionDefinition).Arguments,D.Name);
+    end;
+  if Verbose and (TPasData(D.Data).PasName<>D.Name) then
+    begin
+    if (ParentName<>'') then
+      ParentName:=ParentName+'.';
+    DoLog('Renamed %s to %s',[ParentName+D.Name,TPasData(D.Data).PasName]);
+    end;
+end;
+
+procedure TWebIDLToPas.SetTypeAliases(AValue: TStrings);
+begin
+  if FTypeAliases=AValue then Exit;
+  FTypeAliases.Assign(AValue);
+end;
+
+procedure TWebIDLToPas.SetIncludeInterfaceCode(AValue: TStrings);
+begin
+  if FIncludeInterfaceCode=AValue then Exit;
+  FIncludeInterfaceCode.Assign(AValue);
+end;
+
+procedure TWebIDLToPas.SetIncludeImplementationCode(AValue: TStrings);
+begin
+  if FIncludeImplementationCode=AValue then Exit;
+  FIncludeImplementationCode.Assign(AValue);
+end;
+
+procedure TWebIDLToPas.AllocatePasNames(aList : TIDLDefinitionList; ParentName: String = '');
+
+var
+  D : TIDLDefinition;
+
+begin
+  For D in aList do
+    AllocatePasName(D,ParentName);
+end;
+
+
+procedure TWebIDLToPas.ProcessDefinitions;
+
+begin
+  FContext.AppendPartials;
+  FContext.AppendIncludes;
+  AllocatePasNames(FContext.Definitions);
+end;
+
+procedure TWebIDLToPas.Execute;
+
+begin
+  FContext:=CreateContext;
+  try
+    Parse;
+    if Verbose then
+      DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
+    ProcessDefinitions;
+    WritePascal;
+  finally
+    FreeAndNil(FContext);
+  end;
+end;
+
+end.
+

+ 1594 - 0
packages/webidl/tests/tcidlparser.pp

@@ -0,0 +1,1594 @@
+unit tcidlparser;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testregistry, webidldefs, webidlparser, webidlscanner;
+
+Type
+
+  { TTestParser }
+
+  TTestParser = Class(TTestCase)
+  private
+    FContext: TWebIDLContext;
+    FParser: TWebIDLParser;
+    FVersion: TWebIDLVersion;
+    function GetList: TIDLDefinitionList;
+    procedure SetVersion(AValue: TWebIDLVersion);
+  Protected
+    Procedure Setup; override;
+    Procedure TearDown; override;
+    Procedure InitSource(Const aSource: UTF8String);
+    procedure AssertParserError(const Msg: String; const aSource: UTF8String);
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TConstType); overload;
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TAttributeOption); overload;
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TFunctionOption); overload;
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TAttributeOptions); overload;
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TFunctionOptions); overload;
+  Public
+    Property Parser : TWebIDLParser Read FParser;
+    Property Context : TWebIDLContext Read FContext;
+    Property Definitions : TIDLDefinitionList Read GetList;
+    Property Version : TWebIDLVersion Read FVersion Write SetVersion;
+  end;
+
+  { TTestEnumParser }
+
+  TTestEnumParser = Class(TTestParser)
+  Public
+    Procedure TestEnum(Const aSource,AName : UTF8String; AValues : Array of UTF8String);
+  Published
+    Procedure TestSingle;
+    Procedure TestTwo;
+    Procedure TestMissingIdent;
+    Procedure TestMissingOpening;
+    Procedure TestMissingClosing;
+    Procedure TestMissingSemicolon;
+    Procedure TestMissingComma;
+  end;
+
+  { TTestTypeDefParser }
+
+  TTestTypeDefParser = Class(TTestParser)
+  private
+    function DoTestPromise(aDef: UTF8String; AReturnType: String=''): TIDLPromiseTypeDefDefinition;
+    function DoTestSequence(aDef: UTF8String): TIDLSequenceTypeDefDefinition;
+    function DoTestRecord(aDef: UTF8String; const aKeyTypeName,
+      aValueTypeName: String): TIDLRecordDefinition;
+    function DoTestUnion(aDef: String): TIDLUnionTypeDefDefinition;
+  Public
+    function TestTypeDef(const aSource, AName, aType: UTF8String): TIDLTypeDefDefinition;
+  Published
+    Procedure TestSimpleBoolean;
+    Procedure TestSimpleBooleanNull;
+    Procedure TestSimpleInt;
+    procedure TestSimpleIntNull;
+    Procedure TestSimpleLongint;
+    procedure TestSimpleLongintNull;
+    Procedure TestSimpleLongLongint;
+    Procedure TestSimpleLongLongintNull;
+    Procedure TestSimpleUnsignedShortint;
+    Procedure TestSimpleUnsignedShortintNull;
+    Procedure TestSimpleUnsignedLongint;
+    Procedure TestSimpleUnsignedLongintNull;
+    Procedure TestSimpleUnsignedLongLongint;
+    Procedure TestSimpleUnsignedLongLongintNull;
+    Procedure TestUnrestrictedFloat;
+    Procedure TestSimpleFloat;
+    Procedure TestSimpleFloatNull;
+    Procedure TestSimpleDouble;
+    Procedure TestSimpleDoubleNull;
+    Procedure TestSimpleOctet;
+    Procedure TestSimpleOctetNull;
+    Procedure TestSimpleByte;
+    procedure TestSimpleByteNull;
+    Procedure TestSimpleIdentifier;
+    Procedure TestSimpleIdentifierNull;
+    Procedure TestAnyType;
+    Procedure TestAnyTypeNull;
+    Procedure TestUnion;
+    Procedure TestUnionNull;
+    Procedure TestSequence;
+    Procedure TestSequenceNull;
+    Procedure TestPromise;
+    Procedure TestPromiseVoid;
+    Procedure TestPromiseNull;
+    Procedure TestPromiseReturnNull;
+    Procedure TestRecord;
+  end;
+
+  { TTestInterfaceParser }
+
+  { TTestBaseInterfaceParser }
+
+  TTestBaseInterfaceParser = Class(TTestParser)
+  private
+    FCustAttributes: String;
+    FisMixin: Boolean;
+  Protected
+    Procedure Setup; override;
+  Public
+    Function ParseInterface(AName,aInheritance : UTF8String; AMembers : Array of UTF8String) : TIDLInterfaceDefinition;
+    Property isMixin : Boolean Read FisMixin Write FisMixin;
+    Property CustAttributes : String Read FCustAttributes Write FCustAttributes;
+  end;
+
+  TTestInterfaceParser = Class(TTestBaseInterfaceParser)
+  Published
+    Procedure ParseEmpty;
+    Procedure ParseEmptyInheritance;
+    Procedure ParseMixinEmpty;
+    Procedure ParseMixinEmptyInheritance;
+    Procedure ParseCustomAttributes1;
+  end;
+
+  { TTestMapLikeInterfaceParser }
+
+  TTestMapLikeInterfaceParser = Class(TTestBaseInterfaceParser)
+  Public
+    function ParseMapLike(const AKeyTypeName, aValueTypeName: UTF8String; IsReadOnly: Boolean): TIDLMapLikeDefinition;
+  Published
+    Procedure Parse;
+    Procedure ParseReadOnly;
+  end;
+
+  { TTestSetLikeInterfaceParser }
+
+  TTestSetLikeInterfaceParser = Class(TTestBaseInterfaceParser)
+  Public
+    Function ParseSetLike(const aElementTypeName : UTF8String; IsReadOnly : Boolean) : TIDLSetlikeDefinition;
+  Published
+    Procedure Parse;
+    Procedure ParseReadOnly;
+  end;
+  { TTestConstInterfaceParser }
+
+  TTestConstInterfaceParser = Class(TTestBaseInterfaceParser)
+  Public
+    Function ParseConst(AName,ATypeName,aValue : UTF8String; AType : TConstType) : TIDLConstDefinition;
+  Published
+    Procedure ParseConstInt;
+    Procedure Parse2ConstInt;
+    Procedure ParseConstIntHex;
+    Procedure ParseConstLongint;
+    Procedure ParseConstLongLongint;
+    Procedure ParseConstUnsignedShortint;
+    Procedure ParseConstUnsignedLongint;
+    Procedure ParseConstUnsignedLongLongint;
+    Procedure ParseConstFloat;
+    Procedure ParseConstNan;
+    Procedure ParseConstInfinity;
+    Procedure ParseConstNegInfinity;
+    Procedure ParseConstNull;
+    Procedure ParseConstOctet;
+    Procedure ParseConstByte;
+    Procedure ParseConstBooleantrue;
+    Procedure ParseConstBooleanFalse;
+    Procedure ParseConstIdentifier;
+  end;
+
+  { TTestAttributeInterfaceParser }
+
+  TTestAttributeInterfaceParser = Class(TTestBaseInterfaceParser)
+  private
+    Fattr: TIDLAttributeDefinition;
+  Public
+    Function ParseAttribute(ADef,AName,ATypeName : UTF8String; Options : TAttributeOptions = []) : TIDLAttributeDefinition;
+    Property Attr : TIDLAttributeDefinition Read Fattr;
+  Published
+    Procedure ParseSimpleAttribute;
+    Procedure ParseSimpleAttributeWithExtendedAttrs;
+    Procedure ParseSimpleStaticAttribute;
+    Procedure ParseSimpleStringifierAttribute;
+    Procedure ParseSimpleReadonlyAttribute;
+    Procedure ParseSimpleInheritedAttribute;
+    Procedure ParseSimpleReadonlyInheritedAttribute;
+    Procedure ParseSimpleReadonlyStaticAttribute;
+    Procedure ParseSimpleReadonlyStringifierAttribute;
+    Procedure ParseComplexReadonlyStaticAttribute;
+    Procedure ParseIdentifierAttribute;
+    Procedure Parse2IdentifierAttributes;
+  end;
+
+  { TTestSerializerInterfaceParser }
+
+  TTestSerializerInterfaceParser = Class(TTestBaseInterfaceParser)
+  private
+    FSer: TIDLSerializerDefinition;
+  Public
+    Function ParseSerializer(ADef : UTF8String; Attrs : Array of UTF8String) : TIDLSerializerDefinition;
+    Property Ser : TIDLSerializerDefinition Read FSer;
+  Published
+    Procedure TestSimpleIdentifier;
+    Procedure TestSimpleFunction;
+    Procedure TestMap;
+    Procedure TestMapWithInherited;
+    Procedure TestMapWithGetter;
+    Procedure TestList;
+    Procedure TestListWithGetter;
+  end;
+
+  { TTestOperationInterfaceParser }
+
+  TTestOperationInterfaceParser = Class(TTestBaseInterfaceParser)
+  private
+    FFunc: TIDLFunctionDefinition;
+  Public
+    Function ParseFunction(ADef,aName,aReturnType : UTF8String; aArguments : Array of UTF8String) : TIDLFunctionDefinition;
+    Property Func : TIDLFunctionDefinition Read FFunc;
+  Published
+    Procedure TestSimpleFunction;
+    Procedure TestSimpleGetterFunction;
+    Procedure TestSimpleSetterFunction;
+    Procedure TestSimpleLegacyCallerFunction;
+    Procedure TestSimpleDeleterFunction;
+    Procedure TestAttrFunctionFunction;
+    Procedure TestOptionalDefaultArgFunction;
+  end;
+
+  { TTestDictionaryParser }
+
+  TTestDictionaryParser = Class(TTestParser)
+  private
+    FDict: TIDLDictionaryDefinition;
+    FisPartial: Boolean;
+    procedure AssertMember(aIndex: Integer; Aname, ATypeName, aDefaultValue: String; aDefaultType: TConstType=ctNull; isRequired: Boolean=False);
+  Protected
+    Property isPartial : Boolean Read FisPartial Write FisPartial;
+  Public
+    Function ParseDictionary(AName,aInheritance : UTF8String; AMembers : Array of UTF8String) : TIDLDictionaryDefinition;
+    Property Dict : TIDLDictionaryDefinition read FDict;
+  Published
+    Procedure ParseSingleSimpleElement;
+    Procedure ParseSingleSimpleElementInheritance;
+    Procedure ParseSingleSimpleElementAttributes;
+    Procedure ParseSingleSimpleElementRequired;
+    Procedure ParseSingleSimpleElementDefaultString;
+    Procedure ParseSingleSimpleElementRequiredDefaultString;
+    Procedure ParseSingleSimpleElementRequiredDefaultEmptyArray;
+    Procedure ParseSingleSimpleElementRequiredDefaultNull;
+    Procedure ParseSingleSimpleElementUnsignedLongLong;
+    Procedure ParseTwoSimpleElements;
+    Procedure ParseThreeElements;
+    Procedure ParsePartialSingleSimpleElement;
+  end;
+
+  { TTestFunctionCallbackParser }
+
+  TTestFunctionCallbackParser = Class(TTestParser)
+  private
+    FFunction: TIDLFunctionDefinition;
+  Public
+    function ParseCallback(Const AName, aReturnType: UTF8String; AArguments: array of UTF8String): TIDLFunctionDefinition;
+    Property Func : TIDLFunctionDefinition Read FFunction;
+  Published
+    Procedure ParseNoArgumentsReturnVoid;
+    Procedure ParseOneArgumentReturnVoid;
+    Procedure ParseOneUnsignedLongLongArgumentReturnVoid;
+    Procedure ParseOneUnsignedLongLongArgumentReturnUnsignedLongLong;
+    Procedure ParseOneArgumentWithAttrsReturnVoid;
+    Procedure ParseOneOptionalArgumentReturnVoid;
+    Procedure ParseOneOptionalArgumentWithAttrsReturnVoid;
+    Procedure ParseTwoArgumentsReturnVoid;
+    Procedure ParseTwoArgumentsAttrsReturnVoid;
+    Procedure ParseThreeArgumentsAttrsReturnVoid;
+  end;
+
+  { TTestImplementsParser }
+
+  TTestImplementsParser = Class(TTestParser)
+  private
+    FImpl: TIDLImplementsDefinition;
+  Public
+    Function ParseImplements(Const AName,aImplements: UTF8String) : TIDLImplementsDefinition;
+    Property Impl: TIDLImplementsDefinition Read FImpl;
+  Published
+    Procedure ParseImplementsSimple;
+  end;
+
+  { TTestIncludesParser }
+
+  TTestIncludesParser = Class(TTestParser)
+  private
+    FImpl: TIDLIncludesDefinition;
+  Public
+    Function ParseIncludes(Const AName,aIncludes: UTF8String) : TIDLIncludesDefinition;
+    Property Impl: TIDLIncludesDefinition Read FImpl;
+  Published
+    Procedure ParseIncludesSimple;
+  end;
+
+  { TTestIterableInterfaceParser }
+
+  TTestIterableInterfaceParser = Class(TTestBaseInterfaceParser)
+  private
+    Fiter: TIDLIterableDefinition;
+  Public
+    Function ParseIterable(Const AValueTypeName,AKeyTypeName : UTF8String) : TIDLIterableDefinition;
+    Property Iter : TIDLIterableDefinition Read FIter;
+  Published
+    Procedure ParseSimpleIter;
+    Procedure ParseKeyValueIter;
+  end;
+
+implementation
+
+uses typinfo;
+
+{ TTestSetLikeInterfaceParser }
+
+function TTestSetLikeInterfaceParser.ParseSetLike(
+  const aElementTypeName: UTF8String; IsReadOnly: Boolean
+  ): TIDLSetlikeDefinition;
+Var
+  Id : TIDLInterfaceDefinition;
+  S : UTF8String;
+
+begin
+  Version:=V2;
+  S:=Format('setlike <%s>',[aElementTypeName]);
+  if isReadOnly then
+    S:='readonly '+S;
+  Id:=ParseInterFace('IA','',[S]);
+  AssertEquals('Correct class',TIDLSetLikeDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLSetLikeDefinition;
+  AssertNotNull('Have key type',Result.ElementType);
+  AssertEquals('key type',TIDLTypeDefDefinition, Result.ElementType.ClassType);
+  AssertEquals('Key type Name',AElementTypeName,Result.ElementType.TypeName);
+  AssertEquals('Readonly',IsReadOnly,Result.IsReadOnly);
+end;
+
+procedure TTestSetLikeInterfaceParser.Parse;
+begin
+  ParseSetLike('short',False);
+end;
+
+procedure TTestSetLikeInterfaceParser.ParseReadOnly;
+begin
+  ParseSetLike('short',True);
+end;
+
+{ TTestMapLikeInterfaceParser }
+
+function TTestMapLikeInterfaceParser.ParseMapLike(const AKeyTypeName,
+  aValueTypeName: UTF8String; IsReadOnly : Boolean): TIDLMapLikeDefinition;
+Var
+  Id : TIDLInterfaceDefinition;
+  S : UTF8String;
+
+begin
+  Version:=V2;
+  S:=Format('maplike <%s,%s>',[aKeyTypeName,aValueTypeName]);
+  if isReadOnly then
+    S:='readonly '+S;
+  Id:=ParseInterFace('IA','',[S]);
+  AssertEquals('Correct class',TIDLMapLikeDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLMapLikeDefinition;
+  AssertNotNull('Have key type',Result.KeyType);
+  AssertEquals('key type',TIDLTypeDefDefinition, Result.KeyType.ClassType);
+  AssertEquals('Key type Name',AKeyTypeName,Result.KeyType.TypeName);
+  AssertNotNull('Have value type',Result.ValueType);
+  AssertEquals('key value',TIDLTypeDefDefinition, Result.ValueType.ClassType);
+  AssertEquals('Key value Name',AValueTypeName,Result.ValueType.TypeName);
+  AssertEquals('Readonly',IsReadOnly,Result.IsReadOnly);
+end;
+
+procedure TTestMapLikeInterfaceParser.Parse;
+begin
+  ParseMapLike('short','string',False);
+end;
+
+procedure TTestMapLikeInterfaceParser.ParseReadOnly;
+begin
+  ParseMapLike('short','string',True);
+end;
+
+{ TTestIncludesParser }
+
+function TTestIncludesParser.ParseIncludes(const AName, aIncludes: UTF8String
+  ): TIDLIncludesDefinition;
+Var
+  Src : UTF8String;
+begin
+  Src:=AName+' includes '+aIncludes+';'+sLineBreak;
+  InitSource(Src);
+  Parser.Version:=v2;
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLIncludesDefinition,Definitions[0].ClassType);
+  Result:=Definitions[0] as TIDLIncludesDefinition;
+  AssertEquals('Correct name ',AName,Result.Name);
+  AssertEquals('Correct implements ',aIncludes,Result.IncludedInterface);
+  FImpl:=Result;
+end;
+
+procedure TTestIncludesParser.ParseIncludesSimple;
+begin
+
+end;
+
+{ TTestOperationInterfaceParser }
+
+function TTestOperationInterfaceParser.ParseFunction(ADef, aName,
+  aReturnType: UTF8String; aArguments: array of UTF8String): TIDLFunctionDefinition;
+Var
+  TN,Src : UTF8String;
+  P,I,Idx : integer;
+  Arg : TIDLArgumentDefinition;
+  ID : TIDLInterfaceDefinition;
+
+begin
+  ID:=ParseInterface('IA','',[aDef]);
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLFunctionDefinition,ID.Members[0].ClassType);
+  Result:=ID.Members[0] as TIDLFunctionDefinition;
+  AssertEquals('Name',AName,Result.Name);
+  AssertNotNull('Have return type',Result.ReturnType);
+  AssertEquals('Return type name',aReturnType,Result.ReturnType.TypeName);
+  AssertEquals('Have arguments',Length(aArguments)>0,Result.HasArguments);
+  AssertEquals('Argument count',Length(aArguments) div 2,Result.Arguments.Count);
+  I:=0;
+  While I<Length(aArguments)-1 do
+    begin
+    Idx:=I div 2;
+    Arg:=Result.Argument[idx];
+    AssertEquals('Argument '+IntToStr(Idx)+' name',aArguments[I+1],Arg.Name);
+    AssertNotNull('Argument '+IntToStr(Idx)+' have type',Arg.ArgumentType);
+    TN:=aArguments[I];
+    P:=Pos(']',TN);
+    If P>0 then
+      TN:=Trim(Copy(TN,P+1,Length(TN)-P));
+    if Pos('optional',TN)=1 then
+      TN:=Trim(Copy(TN,9,Length(TN)-8));
+    AssertEquals('Argument '+IntToStr(I div 2)+' type name',TN,Arg.ArgumentType.TypeName);
+    Inc(I,2);
+    end;
+  FFunc:=Result;
+end;
+
+procedure TTestOperationInterfaceParser.TestSimpleFunction;
+begin
+  ParseFunction('short A()','A','short',[]);
+end;
+
+procedure TTestOperationInterfaceParser.TestSimpleGetterFunction;
+begin
+  AssertEquals('Options',[foGetter],ParseFunction('getter short A()','A','short',[]).Options);
+
+end;
+
+procedure TTestOperationInterfaceParser.TestSimpleSetterFunction;
+begin
+  AssertEquals('Options',[foSetter],ParseFunction('setter short A()','A','short',[]).Options);
+end;
+
+procedure TTestOperationInterfaceParser.TestSimpleLegacyCallerFunction;
+begin
+  AssertEquals('Options',[foLegacyCaller],ParseFunction('legacycaller short A()','A','short',[]).Options);
+end;
+
+procedure TTestOperationInterfaceParser.TestSimpleDeleterFunction;
+begin
+  AssertEquals('Options',[foDeleter],ParseFunction('deleter short A()','A','short',[]).Options);
+end;
+
+procedure TTestOperationInterfaceParser.TestAttrFunctionFunction;
+begin
+  AssertTrue('HasAttribute',ParseFunction('[Me] short A()','A','short',[]).HasSimpleAttribute('Me'));
+end;
+
+procedure TTestOperationInterfaceParser.TestOptionalDefaultArgFunction;
+begin
+  ParseFunction('void A(optional short me = 0,optional short you = 0)','A','void',['short','me','short','you'])
+end;
+
+{ TTestSerializerInterfaceParser }
+
+function TTestSerializerInterfaceParser.ParseSerializer(ADef: UTF8String; Attrs: array of UTF8String): TIDLSerializerDefinition;
+
+Var
+  Id : TIDLInterfaceDefinition;
+  i : Integer;
+
+begin
+  Id:=ParseInterFace('IA','',['serializer '+ADef]);
+  AssertEquals('Correct class',TIDLSerializerDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLSerializerDefinition;
+  if (Length(Attrs)>0) then
+    begin
+    AssertTrue('Kind is object or array',Result.Kind in [skObject,skArray,skSingle]);
+    AssertEquals('Identifier count',Length(Attrs),Result.Identifiers.Count);
+    For I:=0 to Length(Attrs)-1 do
+      AssertEquals('Identifier',Attrs[I],Result.Identifiers[i]);
+    end
+  else if (Result.SerializerFunction<>Nil) then
+    AssertTrue('Kind is function',Result.Kind=skFunction);
+  FSer:=Result;
+end;
+
+procedure TTestSerializerInterfaceParser.TestSimpleIdentifier;
+begin
+  ParseSerializer('= A',['A']);
+end;
+
+procedure TTestSerializerInterfaceParser.TestSimpleFunction;
+
+Var
+  D : TIDLFunctionDefinition;
+
+begin
+  AssertNotNull(ParseSerializer('string A ()',[]).SerializerFunction);
+  D:=Ser.SerializerFunction;
+  AssertEquals('Function name','A',D.Name);
+end;
+
+procedure TTestSerializerInterfaceParser.TestMap;
+begin
+  ParseSerializer('= {A, B, C}',['A','B','C']);
+  AssertTrue('Map',Ser.Kind=skObject);
+end;
+
+procedure TTestSerializerInterfaceParser.TestMapWithInherited;
+begin
+  ParseSerializer('= {inherit, B, C}',['inherit','B','C']);
+  AssertTrue('Map',Ser.Kind=skObject);
+end;
+
+procedure TTestSerializerInterfaceParser.TestMapWithGetter;
+begin
+  ParseSerializer('= {getter, B, C}',['getter','B','C']);
+  AssertTrue('Map',Ser.Kind=skObject);
+end;
+
+procedure TTestSerializerInterfaceParser.TestList;
+begin
+  ParseSerializer('= [A, B, C]',['A','B','C']);
+  AssertTrue('Map',Ser.Kind=skArray);
+end;
+
+procedure TTestSerializerInterfaceParser.TestListWithGetter;
+begin
+  ParseSerializer('= [getter, B, C]',['getter','B','C']);
+  AssertTrue('Map',Ser.Kind=skArray);
+end;
+
+{ TTestIterableInterfaceParser }
+
+function TTestIterableInterfaceParser.ParseIterable(const AValueTypeName,
+  AKeyTypeName: UTF8String): TIDLIterableDefinition;
+
+Var
+  Id : TIDLInterfaceDefinition;
+  Src : UTF8String;
+
+begin
+  Src:='iterable <';
+  if AKeyTypeName<>'' then
+    Src:=Src+aKeyTypeName+',';
+  Src:=Src+aValueTypeName+'>';
+  Id:=ParseInterFace('IA','',[Src]);
+  AssertEquals('Correct class',TIDLIterableDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLIterableDefinition;
+  AssertNotNull('Have value type',Result.ValueType);
+  AssertEquals('Attr type',AValueTypeName,Result.ValueType.TypeName);
+  if AKeyTypeName='' then
+    AssertNull('No key type',Result.KeyType)
+  else
+    begin
+    AssertNotNull('Have key type',Result.KeyType);
+    AssertEquals('Attr type',AKeyTypeName,Result.KeyType.TypeName);
+    end;
+  Fiter:=Result;
+end;
+
+procedure TTestIterableInterfaceParser.ParseSimpleIter;
+begin
+  ParseIterable('short','');
+end;
+
+procedure TTestIterableInterfaceParser.ParseKeyValueIter;
+begin
+  ParseIterable('short','long');
+end;
+
+{ TTestAttributeInterfaceParser }
+
+
+function TTestAttributeInterfaceParser.ParseAttribute(ADef, AName,
+  ATypeName: UTF8String; Options: TAttributeOptions): TIDLAttributeDefinition;
+
+Var
+  Id : TIDLInterfaceDefinition;
+
+begin
+  Id:=ParseInterFace('IA','',[aDef]);
+  AssertEquals('Correct class',TIDLAttributeDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLAttributeDefinition;
+  AssertEquals('Attr name',AName,Result.Name);
+  AssertNotNull('Have type',Result.AttributeType);
+  AssertEquals('Attr type',ATypeName,Result.AttributeType.TypeName);
+  AssertEquals('Attr options',Options,Result.Options);
+  FAttr:=Result;
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleAttribute;
+begin
+  ParseAttribute('attribute short A','A','short',[]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleAttributeWithExtendedAttrs;
+begin
+  AssertTrue('Have attribute',ParseAttribute('[Me] attribute short A','A','short',[]).HasSimpleAttribute('Me'));
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleStaticAttribute;
+begin
+  ParseAttribute('static attribute short A','A','short',[aoStatic]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleStringifierAttribute;
+begin
+  ParseAttribute('stringifier attribute short A','A','short',[aoStringifier]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleReadonlyAttribute;
+begin
+  ParseAttribute('readonly attribute short A','A','short',[aoReadOnly]);
+
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleInheritedAttribute;
+begin
+  ParseAttribute('inherit attribute short A','A','short',[aoInherit]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleReadonlyInheritedAttribute;
+begin
+  ParseAttribute('inherit readonly attribute short A','A','short',[aoInherit,aoReadonly]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleReadonlyStaticAttribute;
+begin
+  ParseAttribute('static readonly attribute short A','A','short',[aoStatic,aoReadOnly]);
+
+end;
+
+procedure TTestAttributeInterfaceParser.ParseSimpleReadonlyStringifierAttribute;
+begin
+  ParseAttribute('stringifier readonly attribute short A','A','short',[aoStringifier,aoReadOnly]);
+end;
+
+procedure TTestAttributeInterfaceParser.ParseComplexReadonlyStaticAttribute;
+begin
+  ParseAttribute('static readonly attribute unsigned long long A','A','unsigned long long',[aoStatic,aoReadOnly]);
+end;
+
+
+procedure TTestAttributeInterfaceParser.ParseIdentifierAttribute;
+begin
+  ParseAttribute('attribute B A','A','B',[]);
+end;
+
+procedure TTestAttributeInterfaceParser.Parse2IdentifierAttributes;
+
+Var
+  Id : TIDLInterfaceDefinition;
+begin
+  Id:=ParseInterFace('IA','',['attribute B A','readonly attribute C D']);
+  AssertEquals('Correct class',TIDLAttributeDefinition,Id.Members[0].ClassType);
+  FAttr:=Id.Members[0] as TIDLAttributeDefinition;
+  AssertEquals('Attr name','A',FAttr.Name);
+  AssertNotNull('Have type',FAttr.AttributeType);
+  AssertEquals('Attr type','B',FAttr.AttributeType.TypeName);
+  AssertEquals('Attr options',[],FAttr.Options);
+  FAttr:=Id.Members[1] as TIDLAttributeDefinition;
+  AssertEquals('Attr name','D',FAttr.Name);
+  AssertNotNull('Have type',FAttr.AttributeType);
+  AssertEquals('Attr type','C',FAttr.AttributeType.TypeName);
+  AssertEquals('Attr options',[aoReadonly],FAttr.Options);
+end;
+
+{ TTestImplementsParser }
+
+function TTestImplementsParser.ParseImplements(const AName,
+  aImplements: UTF8String): TIDLImplementsDefinition;
+Var
+  Src : UTF8String;
+begin
+  Src:=AName+' implements '+aImplements+';'+sLineBreak;
+  InitSource(Src);
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLImplementsDefinition,Definitions[0].ClassType);
+  Result:=Definitions[0] as TIDLImplementsDefinition;
+  AssertEquals('Correct name ',AName,Result.Name);
+  AssertEquals('Correct implements ',aImplements,Result.ImplementedInterface);
+  FImpl:=Result;
+end;
+
+procedure TTestImplementsParser.ParseImplementsSimple;
+begin
+  ParseImplements('A','B');
+end;
+
+{ TTestFunctionCallbackParser }
+
+function TTestFunctionCallbackParser.ParseCallback(const AName,
+  aReturnType: UTF8String; AArguments: array of UTF8String
+  ): TIDLFunctionDefinition;
+Var
+  TN,Src : UTF8String;
+  P,I,Idx : integer;
+  Arg : TIDLArgumentDefinition;
+
+begin
+  Src:='callback '+aName+' = '+AReturnType+' (';
+  I:=0;
+  While I<Length(aArguments) do
+    begin
+    if I>0 then
+      Src:=Src+', ';
+    Src:=Src+aArguments[I]+ ' '+aArguments[I+1];
+    Inc(I,2);
+    end;
+  Src:=Src+');'+sLineBreak;
+  InitSource(Src);
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLFunctionDefinition,Definitions[0].ClassType);
+  Result:=Definitions[0] as TIDLFunctionDefinition;
+  AssertEquals('Name',AName,Result.Name);
+  AssertNotNull('Have return type',Result.ReturnType);
+  AssertEquals('Return type name',aReturnType,Result.ReturnType.TypeName);
+  AssertEquals('Have arguments',Length(aArguments)>0,Result.HasArguments);
+  AssertEquals('Argument count',Length(aArguments) div 2,Result.Arguments.Count);
+  I:=0;
+  While I<Length(aArguments)-1 do
+    begin
+    Idx:=I div 2;
+    Arg:=Result.Argument[idx];
+    AssertEquals('Argument '+IntToStr(Idx)+' name',aArguments[I+1],Arg.Name);
+    AssertNotNull('Argument '+IntToStr(Idx)+' have type',Arg.ArgumentType);
+    TN:=aArguments[I];
+    P:=Pos(']',TN);
+    If P>0 then
+      TN:=Trim(Copy(TN,P+1,Length(TN)-P));
+    if Pos('optional',TN)=1 then
+      TN:=Trim(Copy(TN,9,Length(TN)-8));
+    AssertEquals('Argument '+IntToStr(I div 2)+' type name',TN,Arg.ArgumentType.TypeName);
+    Inc(I,2);
+    end;
+  FFunction:=Result;
+end;
+
+procedure TTestFunctionCallbackParser.ParseNoArgumentsReturnVoid;
+begin
+  ParseCallback('A','void',[]);
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneArgumentReturnVoid;
+begin
+  ParseCallback('A','void',['short','A']);
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneUnsignedLongLongArgumentReturnVoid;
+begin
+  ParseCallback('A','void',['unsigned long long','A']);
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneUnsignedLongLongArgumentReturnUnsignedLongLong;
+begin
+  ParseCallback('A','unsigned long long',['unsigned long long','A']);
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneArgumentWithAttrsReturnVoid;
+begin
+  ParseCallback('A','void',['[Me] unsigned long long','A']);
+  AssertTrue('Have attribute',Func.Arguments[0].HasSimpleAttribute('Me'));
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneOptionalArgumentReturnVoid;
+begin
+  ParseCallback('A','void',['optional unsigned long long','A']);
+  AssertTrue('is optional',Func.Argument[0].IsOptional);
+  AssertEquals('Type name','unsigned long long',Func.Argument[0].ArgumentType.TypeName);
+end;
+
+procedure TTestFunctionCallbackParser.ParseOneOptionalArgumentWithAttrsReturnVoid;
+begin
+  ParseCallback('A','void',['[Me] optional unsigned long long','A']);
+  AssertTrue('is optional',Func.Argument[0].IsOptional);
+  AssertEquals('Type name','unsigned long long',Func.Argument[0].ArgumentType.TypeName);
+  AssertTrue('Have attribute',Func.Arguments[0].HasSimpleAttribute('Me'));
+end;
+
+procedure TTestFunctionCallbackParser.ParseTwoArgumentsReturnVoid;
+begin
+  ParseCallback('A','void',['short','B','short','C']);
+end;
+
+procedure TTestFunctionCallbackParser.ParseTwoArgumentsAttrsReturnVoid;
+begin
+  ParseCallback('A','void',['[Me] short','B','[Me] short','C']);
+  AssertTrue('Have attribute',Func.Arguments[0].HasSimpleAttribute('Me'));
+  AssertTrue('Have attribute',Func.Arguments[1].HasSimpleAttribute('Me'));
+end;
+
+procedure TTestFunctionCallbackParser.ParseThreeArgumentsAttrsReturnVoid;
+begin
+  ParseCallback('A','void',['[Me] short','B','[Me] short','C','[Me] optional unsigned long long','D']);
+  AssertTrue('Have attribute',Func.Arguments[0].HasSimpleAttribute('Me'));
+  AssertTrue('Have attribute',Func.Arguments[1].HasSimpleAttribute('Me'));
+  AssertTrue('Have attribute',Func.Arguments[2].HasSimpleAttribute('Me'));
+  AssertTrue('Have attribute',Func.Argument[2].IsOptional);
+end;
+
+{ TTestDictionaryParser }
+
+function TTestDictionaryParser.ParseDictionary(AName, aInheritance: UTF8String;
+  AMembers: array of UTF8String): TIDLDictionaryDefinition;
+Var
+  Src : UTF8String;
+  I : integer;
+
+begin
+  Src:='dictionary '+aName+' ';
+  If IsPartial then
+    Src:='partial '+Src;
+
+  if (aInheritance<>'') then
+    Src:=Src+': '+aInheritance+' ';
+  Src:=Src+'{'+sLineBreak;
+  For I:=0 to Length(AMembers)-1 do
+    Src:=Src+AMembers[I]+';'+sLineBreak;
+  Src:=Src+'};'+sLineBreak;
+  InitSource(Src);
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLDictionaryDefinition,Definitions[0].ClassType);
+  Result:=Definitions[0] as TIDLDictionaryDefinition;
+  AssertEquals('Name',AName,Result.Name);
+  AssertEquals('Inheritance : ',aInheritance,Result.ParentName);
+  AssertEquals('Member count',Length(AMembers),Result.Members.Count);
+  FDict:=Result;
+end;
+
+procedure TTestDictionaryParser.AssertMember(aIndex : Integer; Aname, ATypeName,aDefaultValue : String; aDefaultType  : TConstType = ctNull; isRequired : Boolean = False);
+
+Var
+  m : TIDLDictionaryMemberDefinition;
+  S : string;
+
+begin
+  S:=Format('Member %d (Name %s)',[aIndex,AName]);
+  AssertNotNull(S+' have dict',Dict);
+  AssertTrue(S+' dict has members',Dict.HasMembers);
+  AssertTrue(S+' index in range',(aIndex>=0) and (aIndex<Dict.Members.Count));
+  AssertEquals(S+' element has correct class',TIDLDictionaryMemberDefinition,Dict.Members[aIndex].ClassType);
+  M:=Dict[aIndex];
+  AssertEquals(S+' isRequired : ',isRequired,M.IsRequired);
+  AssertEquals(S+' Name : ',aName,M.Name);
+  AssertNotNull(S+' Have type',M.MemberType);
+  AssertEquals(S+' type name',aTypeName,M.MemberType.TypeName);
+  if (aDefaultValue='') then
+    AssertNull(S+' Have no default value',M.DefaultValue)
+  else
+    begin
+    AssertNotNull(S+' Have default value',M.DefaultValue);
+    AssertEquals(S+' default value',aDefaultValue,M.DefaultValue.Value);
+    AssertEquals(S+' default value type',aDefaultType,M.DefaultValue.ConstType);
+    end;
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElement;
+
+begin
+  ParseDictionary('A','',['string B']);
+  AssertMember(0,'B','string','');
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementInheritance;
+begin
+  ParseDictionary('A','C',['string B']);
+  AssertMember(0,'B','string','');
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementAttributes;
+begin
+  ParseDictionary('A','',['[Replaceable] required string B']);
+  AssertMember(0,'B','string','',ctNull,False);
+  AssertTrue('Has attributes',Dict[0].HasAttributes);
+  AssertEquals('Attribute count',1,Dict[0].Attributes.Count);
+  AssertEquals('Has attributes','Replaceable',Dict[0].Attributes[0]);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementRequired;
+begin
+  ParseDictionary('A','',['required string B']);
+  AssertMember(0,'B','string','',ctNull,True);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementDefaultString;
+begin
+  ParseDictionary('A','',['string B = "abc"']);
+  AssertMember(0,'B','string','abc',ctString);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementRequiredDefaultString;
+begin
+  ParseDictionary('A','',['required string B = "abc"']);
+  AssertMember(0,'B','string','abc',ctString,true);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementRequiredDefaultEmptyArray;
+begin
+  ParseDictionary('A','',['required string B = []']);
+  AssertMember(0,'B','string','[]',ctEmptyArray,true);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementRequiredDefaultNull;
+begin
+  ParseDictionary('A','',['string B = null']);
+  AssertMember(0,'B','string','null',ctNull,False);
+end;
+
+procedure TTestDictionaryParser.ParseSingleSimpleElementUnsignedLongLong;
+begin
+  ParseDictionary('A','',['required unsigned long long B']);
+  AssertMember(0,'B','unsigned long long','',ctNull,True);
+end;
+
+procedure TTestDictionaryParser.ParseTwoSimpleElements;
+begin
+  ParseDictionary('A','',['string B','short C']);
+  AssertMember(0,'B','string','');
+  AssertMember(1,'C','short','');
+end;
+
+procedure TTestDictionaryParser.ParseThreeElements;
+begin
+  ParseDictionary('A','',['string B','short C','required unsigned long long D']);
+  AssertMember(0,'B','string','');
+  AssertMember(1,'C','short','');
+  AssertMember(2,'D','unsigned long long','',ctNull,true);
+end;
+
+procedure TTestDictionaryParser.ParsePartialSingleSimpleElement;
+begin
+  isPartial:=True;
+  ParseDictionary('A','',['string B']);
+  AssertMember(0,'B','string','');
+  AssertTrue('Partial',Dict.IsPartial);
+end;
+
+{ TTestTypeDefParser }
+
+function TTestTypeDefParser.TestTypeDef(const aSource, AName, aType: UTF8String
+  ): TIDLTypeDefDefinition;
+
+Var
+  E : TIDLTypeDefDefinition;
+
+begin
+  InitSource('typedef '+ASource+';');
+  Parser.Parse;
+  AssertEquals('Definition count',1,Definitions.Count);
+  AssertTrue('Correct class',Definitions[0].ClassType.InheritsFrom(TIDLTypeDefDefinition));
+  E:=Definitions[0] as TIDLTypeDefDefinition;
+  AssertEquals('Name',AName,E.Name);
+  AssertEquals('Type name',AType,E.TypeName);
+  if Pos('?',aSource)=0 then
+    AssertEquals('Not Null',False,E.AllowNull);
+  Result:=E;
+end;
+
+procedure TTestTypeDefParser.TestSimpleBoolean;
+begin
+  TestTypeDef('boolean A','A','boolean');
+end;
+
+procedure TTestTypeDefParser.TestSimpleBooleanNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('boolean ? A','A','boolean').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleInt;
+begin
+  TestTypeDef('short A','A','short');
+end;
+
+procedure TTestTypeDefParser.TestSimpleIntNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('short ? A','A','short').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleLongint;
+begin
+  TestTypeDef('long A','A','long');
+end;
+
+procedure TTestTypeDefParser.TestSimpleLongintNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('long ? A','A','long').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleLongLongint;
+begin
+  TestTypeDef('long long A','A','long long');
+end;
+
+procedure TTestTypeDefParser.TestSimpleLongLongintNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('long long ? A','A','long long').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedShortint;
+begin
+  TestTypeDef('unsigned short A','A','unsigned short');
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedShortintNull;
+
+begin
+  AssertTrue('AllowNull',TestTypeDef('unsigned short ? A','A','unsigned short').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedLongint;
+begin
+  TestTypeDef('unsigned long A','A','unsigned long');
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedLongintNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('unsigned long ? A','A','unsigned long').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedLongLongint;
+begin
+  TestTypeDef('unsigned long long A','A','unsigned long long');
+end;
+
+procedure TTestTypeDefParser.TestSimpleUnsignedLongLongintNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('unsigned long long ? A','A','unsigned long long').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestUnrestrictedFloat;
+begin
+  TestTypeDef('unrestricted float A','A','unrestricted float');
+end;
+
+procedure TTestTypeDefParser.TestSimpleFloat;
+begin
+  TestTypeDef('float A','A','float');
+end;
+
+procedure TTestTypeDefParser.TestSimpleFloatNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('float ? A','A','float').AllowNull)
+end;
+
+procedure TTestTypeDefParser.TestSimpleDouble;
+begin
+  TestTypeDef('double A','A','double');
+end;
+
+procedure TTestTypeDefParser.TestSimpleDoubleNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('double ? A','A','double').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleOctet;
+begin
+  TestTypeDef('octet A','A','octet');
+end;
+
+procedure TTestTypeDefParser.TestSimpleOctetNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('octet ? A','A','octet').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleByte;
+begin
+  TestTypeDef('byte A','A','byte');
+end;
+
+procedure TTestTypeDefParser.TestSimpleByteNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('byte ? A','A','byte').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestSimpleIdentifier;
+begin
+  TestTypeDef('Zaza A','A','Zaza');
+end;
+
+procedure TTestTypeDefParser.TestSimpleIdentifierNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('Zaza ? A','A','Zaza').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestAnyType;
+begin
+  TestTypeDef('any A','A','any');
+end;
+
+procedure TTestTypeDefParser.TestAnyTypeNull;
+begin
+  AssertTrue('AllowNull',TestTypeDef('any ? A','A','any').AllowNull);
+end;
+
+function TTestTypeDefParser.DoTestUnion(aDef: String): TIDLUnionTypeDefDefinition;
+
+Var
+  D : TIDLTypeDefDefinition;
+  U : TIDLUnionTypeDefDefinition;
+
+begin
+  D:=TestTypeDef(aDef,'A','union');
+  AssertEquals('Correct class',TIDLUnionTypeDefDefinition,D.ClassType);
+  U:=TIDLUnionTypeDefDefinition(D);
+  AssertEquals('Union types',2,U.Union.Count);
+  AssertNotNull('Have type 1',U.Union[0]);
+  AssertEquals('1: Correct class',TIDLTypeDefDefinition,U.Union[0].ClassType);
+  D:=TIDLTypeDefDefinition(U.Union[0]);
+  AssertEquals('1: Correct type name','byte',D.TypeName);
+  AssertNotNull('Have type 2',U.Union[1]);
+  AssertEquals('2: Correct class',TIDLTypeDefDefinition,U.Union[1].ClassType);
+  D:=TIDLTypeDefDefinition(U.Union[1]);
+  AssertEquals('2: Correct type name','octet',D.TypeName);
+  Result:=U;
+end;
+
+procedure TTestTypeDefParser.TestUnion;
+
+begin
+  DoTestUnion('(byte or octet) A');
+end;
+
+procedure TTestTypeDefParser.TestUnionNull;
+begin
+  AssertTrue('Is null',DoTestUnion('(byte or octet) ? A').AllowNull);
+end;
+
+function TTestTypeDefParser.DoTestSequence(aDef: UTF8String
+  ): TIDLSequenceTypeDefDefinition;
+
+Var
+  D : TIDLTypeDefDefinition;
+  S : TIDLSequenceTypeDefDefinition;
+
+begin
+  D:=TestTypeDef(aDef ,'A','sequence');
+  AssertEquals('Correct class',TIDLSequenceTypeDefDefinition,D.ClassType);
+  S:=TIDLSequenceTypeDefDefinition(D);
+  AssertNotNull('Have element type',S.ElementType);
+  D:=TIDLTypeDefDefinition(S.ElementType);
+  AssertEquals('1: Correct type name','byte',D.TypeName);
+  Result:=S;
+end;
+
+function TTestTypeDefParser.DoTestRecord(aDef: UTF8String; const aKeyTypeName,
+  aValueTypeName: String): TIDLRecordDefinition;
+Var
+  D : TIDLTypeDefDefinition;
+  R : TIDLRecordDefinition;
+
+begin
+  Version:=v2;
+  D:=TestTypeDef(aDef ,'A','record'});
+  AssertEquals('Correct class',TIDLRecordDefinition,D.ClassType);
+  R:=TIDLRecordDefinition(D);
+  AssertNotNull('Have key type',R.KeyType);
+  D:=TIDLTypeDefDefinition(R.KeyType);
+  AssertEquals('1: Correct type name',aKeyTypeName,D.TypeName);
+  AssertNotNull('Have value type',R.ValueType);
+  D:=TIDLTypeDefDefinition(R.ValueType);
+  AssertEquals('1: Correct type name',aValueTypeName,D.TypeName);
+  Result:=R;
+
+end;
+
+procedure TTestTypeDefParser.TestSequence;
+
+begin
+  DoTestSequence('sequence<byte> A');
+end;
+
+procedure TTestTypeDefParser.TestSequenceNull;
+
+begin
+  AssertTrue('Is Null ',DoTestSequence('sequence<byte> ? A').AllowNull);
+end;
+
+function TTestTypeDefParser.DoTestPromise(aDef: UTF8String; AReturnType : String = ''): TIDLPromiseTypeDefDefinition;
+
+Var
+  D : TIDLTypeDefDefinition;
+  S : TIDLPromiseTypeDefDefinition;
+
+begin
+  D:=TestTypeDef(ADef,'A','Promise');
+  AssertEquals('Correct class',TIDLPromiseTypeDefDefinition,D.ClassType);
+  S:=TIDLPromiseTypeDefDefinition(D);
+  AssertNotNull('Have element type',S.ReturnType);
+  D:=TIDLTypeDefDefinition(S.ReturnType);
+  if aReturnType='' then
+    aReturnType:='byte';
+  AssertEquals('1: Correct type name',aReturnType,D.TypeName);
+  Result:=S;
+end;
+
+
+procedure TTestTypeDefParser.TestPromise;
+
+begin
+  DoTestPromise('Promise<byte> A');
+end;
+
+procedure TTestTypeDefParser.TestPromiseVoid;
+begin
+  DoTestPromise('Promise<void> A','void');
+end;
+
+procedure TTestTypeDefParser.TestPromiseNull;
+begin
+  AssertTrue('Is Null',DoTestPromise('Promise<byte> ? A').AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestPromiseReturnNull;
+begin
+  AssertTrue('ReturnType Is Null',DoTestPromise('Promise<byte ?> A').ReturnType.AllowNull);
+end;
+
+procedure TTestTypeDefParser.TestRecord;
+begin
+  DoTestRecord('record <short,string> A','short','string');
+end;
+
+{ TTestInterfaceParser }
+
+procedure TTestBaseInterfaceParser.Setup;
+begin
+  inherited Setup;
+  FIsMixin:=False
+end;
+
+function TTestBaseInterfaceParser.ParseInterface(AName,aInheritance: UTF8String;
+  AMembers: array of UTF8String): TIDLInterfaceDefinition;
+
+Var
+  Src : UTF8String;
+  I : integer;
+
+begin
+  if IsMixin then
+    Src:='interface mixin '+aName+' '
+  else
+    Src:='interface '+aName+' ';
+  if (FCustAttributes<>'') then
+    Src:=FCustAttributes+' '+Src;
+  if (aInheritance<>'') then
+    Src:=Src+': '+aInheritance+' ';
+  Src:=Src+'{'+sLineBreak;
+  For I:=0 to Length(AMembers)-1 do
+    Src:=Src+'  '+AMembers[I]+';'+sLineBreak;
+  Src:=Src+'};'+sLineBreak;
+  InitSource(Src);
+  Parser.Parse;
+  AssertEquals('Correct class',TIDLInterfaceDefinition,Definitions[0].ClassType);
+  Result:=Definitions[0] as TIDLInterfaceDefinition;
+  AssertEquals('Name',AName,Result.Name);
+  AssertEquals('Inheritance : ',aInheritance,Result.ParentName);
+  AssertEquals('Member count',Length(AMembers),Result.Members.Count);
+  AssertEquals('Mixin correct',IsMixin,Result.IsMixin);
+end;
+
+function TTestConstInterfaceParser.ParseConst(AName, ATypeName, aValue: UTF8String;
+  AType: TConstType): TIDLConstDefinition;
+
+Var
+  Id : TIDLInterfaceDefinition;
+  P : Integer;
+  isNull : Boolean;
+
+begin
+  Id:=ParseInterFace('IA','',['const '+aTypeName+' '+AName+' = '+AValue]);
+  AssertEquals('Correct class',TIDLConstDefinition,Id.Members[0].ClassType);
+  Result:=Id.Members[0] as TIDLConstDefinition;
+  AssertEquals('Const Name',AName,Result.Name);
+  P:=Pos('?',ATypeName);
+  isNull:=P>0;
+  if IsNull then
+    ATypeName:=Trim(Copy(ATypeName,1,P-1));
+  AssertEquals('Const type',ATypeName,Result.TypeName);
+  AssertEquals('Const consttype',AType,Result.ConstType);
+  AssertEquals('Const value',AValue,Result.Value);
+  AssertEquals('Const null allowed',IsNull,Result.AllowNull);
+end;
+
+procedure TTestInterfaceParser.ParseEmpty;
+begin
+  ParseInterface('A','',[]);
+end;
+
+procedure TTestInterfaceParser.ParseEmptyInheritance;
+begin
+  ParseInterface('A','B',[]);
+end;
+
+procedure TTestInterfaceParser.ParseMixinEmpty;
+begin
+  IsMixin:=true;
+  Version:=v2;
+  ParseInterface('A','',[]);
+end;
+
+procedure TTestInterfaceParser.ParseMixinEmptyInheritance;
+begin
+  IsMixin:=true;
+  Version:=v2;
+  ParseInterface('A','B',[]);
+end;
+
+procedure TTestInterfaceParser.ParseCustomAttributes1;
+begin
+  CustAttributes:='[Constructor(DOMString type,optional WebGLContextEventInit eventInit)]';
+  AssertEquals('Attributes',CustAttributes,ParseInterface('A','B',[]).Attributes.AsString(True));
+end;
+
+procedure TTestConstInterfaceParser.ParseConstInt;
+begin
+  ParseConst('A','short','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.Parse2ConstInt;
+Var
+  Id : TIDLInterfaceDefinition;
+  CD : TIDLConstDefinition;
+
+begin
+  Id:=ParseInterFace('IA','',['const GLenum READ_BUFFER = 0x0C02','const GLenum UNPACK_ROW_LENGTH = 0x0CF2']);
+  AssertEquals('Correct class',TIDLConstDefinition,Id.Members[0].ClassType);
+  CD:=Id.Members[0] as TIDLConstDefinition;
+  AssertEquals('Const Name','READ_BUFFER',CD.Name);
+  AssertEquals('Const type','GLenum',CD.TypeName);
+  AssertEquals('Const consttype',ctInteger,CD.ConstType);
+  AssertEquals('Const value','0x0C02',CD.Value);
+  AssertEquals('Const null allowed',False,CD.AllowNull);
+  CD:=Id.Members[1] as TIDLConstDefinition;
+  AssertEquals('Const Name','UNPACK_ROW_LENGTH',CD.Name);
+  AssertEquals('Const type','GLenum',CD.TypeName);
+  AssertEquals('Const consttype',ctInteger,CD.ConstType);
+  AssertEquals('Const value','0x0CF2',CD.Value);
+  AssertEquals('Const null allowed',False,CD.AllowNull);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstIntHex;
+begin
+  ParseConst('A','short','0xABCDEF',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstLongint;
+begin
+  ParseConst('A','long','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstLongLongint;
+begin
+  ParseConst('A','long long','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstUnsignedShortint;
+begin
+  ParseConst('A','unsigned short','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstUnsignedLongint;
+begin
+  ParseConst('A','unsigned long','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstUnsignedLongLongint;
+begin
+  ParseConst('A','unsigned long long','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstFloat;
+begin
+  ParseConst('A','float','1.23',ctFloat);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstNan;
+begin
+  ParseConst('A','float','NaN',ctNaN);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstInfinity;
+begin
+  ParseConst('A','float','Infinity',ctInfinity);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstNegInfinity;
+begin
+  ParseConst('A','float','-Infinity',ctNegInfinity);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstNull;
+begin
+  ParseConst('A','short ?','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstOctet;
+begin
+  ParseConst('A','octet','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstByte;
+begin
+  ParseConst('A','byte','123',ctInteger);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstBooleantrue;
+begin
+  ParseConst('A','boolean','true',ctBoolean);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstBooleanFalse;
+begin
+  ParseConst('A','boolean','false',ctBoolean);
+end;
+
+procedure TTestConstInterfaceParser.ParseConstIdentifier;
+begin
+  ParseConst('A','Zaza','false',ctBoolean);
+end;
+
+
+{ TTestEnumParser }
+
+procedure TTestEnumParser.TestEnum(const aSource, AName: UTF8String;
+  AValues: array of UTF8String);
+
+Var
+  E : TIDLEnumDefinition;
+  i : Integer;
+
+begin
+  InitSource('enum '+ASource+';');
+  Parser.Parse;
+  AssertEquals('Definition count',1,Definitions.Count);
+  AssertEquals('Correct class',TIDLEnumDefinition,Definitions[0].ClassType);
+  E:=Definitions[0] as TIDLEnumDefinition;
+  AssertEquals('Name',AName,E.Name);
+  AssertEquals('Value count',Length(AValues),E.Values.Count);
+  For I:=0 to E.Values.Count-1 do
+    AssertEquals('Value '+IntToStr(i),AValues[i],E.Values[i]);
+end;
+
+procedure TTestEnumParser.TestSingle;
+begin
+  TestEnum('A { "one" }','A',['one']);
+end;
+
+procedure TTestEnumParser.TestTwo;
+begin
+  TestEnum('A { "one", "two" }','A',['one','two']);
+end;
+
+procedure TTestEnumParser.TestMissingIdent;
+begin
+  AssertParserError('No ident','enum { "one" };');
+end;
+
+procedure TTestEnumParser.TestMissingOpening;
+begin
+  AssertParserError('No {','enum A "one" };');
+end;
+
+procedure TTestEnumParser.TestMissingClosing;
+begin
+  AssertParserError('No }','enum A { "one" ;');
+end;
+
+procedure TTestEnumParser.TestMissingSemicolon;
+begin
+  AssertParserError('No ; ','enum A { "one" }');
+end;
+
+procedure TTestEnumParser.TestMissingComma;
+begin
+  AssertParserError('No ; ','enum A { "one" "two"}');
+end;
+
+{ TTestParser }
+
+function TTestParser.GetList: TIDLDefinitionList;
+begin
+  Result:=Context.Definitions;
+end;
+
+procedure TTestParser.SetVersion(AValue: TWebIDLVersion);
+begin
+  if FVersion=AValue then Exit;
+  FVersion:=AValue;
+  if Assigned(FParser) then
+    FParser.Version:=aValue;
+end;
+
+procedure TTestParser.Setup;
+begin
+  FContext:=TWebIDLContext.Create;
+  FVersion:=v1;
+  inherited Setup;
+end;
+
+procedure TTestParser.TearDown;
+begin
+  FreeAndNil(FParser);
+  FreeAndNil(FContext);
+  inherited TearDown;
+end;
+
+procedure TTestParser.InitSource(const aSource: UTF8String);
+begin
+  Writeln(TestName+' source : ');
+  Writeln(aSource);
+  FParser:=TWebIDLParser.Create(Context,aSource);
+  FParser.Version:=Version;
+end;
+
+procedure TTestParser.AssertParserError(const Msg: String;
+  const aSource: UTF8String);
+begin
+  InitSource(aSource);
+  AssertException(Msg,EWebIDLParser,@Parser.Parse);
+end;
+
+class procedure TTestParser.AssertEquals(Msg: String; AExpected,
+  AActual: TConstType);
+begin
+  AssertEQuals(Msg,GetEnumName(TypeInfo(TConstType),Ord(AExpected)),GetEnumName(TypeInfo(TConstType),Ord(AActual)));
+end;
+
+class procedure TTestParser.AssertEquals(Msg: String; AExpected,
+  AActual: TAttributeOption);
+begin
+  AssertEquals(Msg,GetEnumName(TypeInfo(TAttributeOption),Ord(AExpected)),GetEnumName(TypeInfo(TAttributeOption),Ord(AActual)));
+end;
+
+class procedure TTestParser.AssertEquals(Msg: String; AExpected, AActual: TFunctionOption);
+begin
+  AssertEquals(Msg,GetEnumName(TypeInfo(TFunctionOption),Ord(AExpected)),GetEnumName(TypeInfo(TFunctionOption),Ord(AActual)));
+end;
+
+class procedure TTestParser.AssertEquals(Msg: String; AExpected,
+  AActual: TAttributeOptions);
+begin
+  AssertEquals(Msg,SetToString(PTypeInfo(TypeInfo(TAttributeOptions)),Integer(AExpected),True),
+                   SetToString(PTypeInfo(TypeInfo(TAttributeOptions)),Integer(AActual),True));
+end;
+
+class procedure TTestParser.AssertEquals(Msg: String; AExpected,
+  AActual: TFunctionOptions);
+begin
+  AssertEquals(Msg,SetToString(PTypeInfo(TypeInfo(TFunctionOptions)),Integer(AExpected),True),
+                   SetToString(PTypeInfo(TypeInfo(TFunctionOptions)),Integer(AActual),True));
+end;
+
+initialization
+  RegisterTests([TTestEnumParser,
+                 TTestInterfaceParser,
+                 TTestConstInterfaceParser,
+                 TTestTypeDefParser,
+                 TTestDictionaryParser,
+                 TTestFunctionCallbackParser,
+                 TTestImplementsParser,
+                 TTestIncludesParser,
+                 TTestAttributeInterfaceParser,
+                 TTestIterableInterfaceParser,
+                 TTestSerializerInterfaceParser,
+                 TTestOperationInterfaceParser,
+                 TTestMapLikeInterfaceParser,
+                 TTestSetLikeInterfaceParser]);
+end.
+

+ 577 - 0
packages/webidl/tests/tcidlscanner.pp

@@ -0,0 +1,577 @@
+unit tcidlscanner;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, webidlscanner;
+
+type
+
+  { TTestScanner }
+
+  TTestScanner= class(TTestCase)
+  private
+    FScanner: TWebIDLScanner;
+    FVersion: TWEbIDLversion;
+    procedure SetVersion(AValue: TWEbIDLversion);
+  protected
+    procedure Init(Const aSource : string);
+    Class Procedure AssertEquals(Msg : String; AExpected,AActual : TIDLToken); overload;
+    Procedure TestSingle(Const aSource : String; AToken : TIDLToken);
+    Procedure TestMulti(Const aSource : String; AToken : Array of TIDLToken);
+    Procedure TestSingle(Const aSource : String; AToken : TIDLToken; AValue : String);
+    Procedure TestMulti(Const aSource : String; AToken : Array of TIDLToken; AValues : Array of String);
+    procedure SetUp; override;
+    procedure TearDown; override;
+    Property Scanner : TWebIDLScanner Read FScanner;
+    Property Version : TWEbIDLversion Read FVersion Write SetVersion;
+  published
+    procedure TestHookUp;
+    Procedure TestComment;
+    Procedure TestWhitespace;
+    Procedure TestString;
+    Procedure TestNumberInteger;
+    Procedure TestNumberFloat;
+    Procedure TestNumberHex;
+    Procedure TestNumberHex2;
+    // Simple (one-character) tokens
+    Procedure TestComma;                 // ','
+    Procedure TestColon;                 // ':'
+    Procedure TestBracketOpen;           // '('
+    Procedure TestBracketClose;          // ')'
+    Procedure TestCurlyBraceOpen;        // '{'
+    Procedure TestCurlyBraceClose;       // '}'
+    Procedure TestSquaredBraceOpen;       // '['
+    Procedure TestSquaredBraceClose;      // ']'
+    Procedure TestIdentifier;            // Any  identifier
+    Procedure TestDot;  //       '.',
+    Procedure TestSemicolon;//  ';',
+    Procedure TestLess;//  '<',
+    Procedure TestEqual;//  '=',
+    Procedure TestLarger;//  '=',
+    Procedure TestQuestionMark;//  '?',
+    Procedure TestMinus;//  '-',
+    Procedure TestOther;// 'other',
+    Procedure Testshort;// 'other',
+
+    Procedure TestTrue;
+    Procedure TestFalse;
+    Procedure TestNull;
+    Procedure TestAny;
+    Procedure TestAttribute;
+    Procedure TestCallback;
+    Procedure TestConst;
+    Procedure TestDeleter;
+    Procedure TestDictionary;
+    Procedure TestEllipsis;
+    Procedure TestEnum;
+    Procedure TestGetter;
+    Procedure TestImplements;
+    Procedure TestMapLike;
+    Procedure TestSetLike;
+    Procedure TestRecord;
+    Procedure TestInfinity;
+    Procedure TestInherit;
+    Procedure TestInterface;
+    Procedure TestIterable;
+    Procedure TestLegacyCaller;
+    Procedure TestNan;
+    Procedure TestNegInfinity;
+    Procedure TestOptional;
+    Procedure TestOr;
+    Procedure TestPartial;
+    Procedure TestReadOnly;
+    Procedure TestRequired;
+    Procedure TestSetter;
+    Procedure TestStatic;
+    Procedure TestStringifier;
+    Procedure TestTypedef;
+    Procedure TestUnrestricted;
+    Procedure TestPromise;
+    Procedure TestByteString;
+    Procedure TestDOMString;
+    Procedure TestUSVString;
+    Procedure Testboolean;
+    Procedure Testbyte;
+    Procedure Testdouble;
+    Procedure Testfloat;
+    Procedure Testlong;
+    Procedure Testobject;
+    Procedure Testoctet;
+    Procedure Testunsigned;
+    Procedure Testvoid;
+  end;
+
+implementation
+
+uses typinfo;
+
+procedure TTestScanner.TestHookUp;
+begin
+  Init('');
+  AssertNotNull('Have scanner',Scanner);
+end;
+
+procedure TTestScanner.TestComment;
+begin
+  TestSingle('// me',tkComment);
+end;
+
+procedure TTestScanner.TestWhitespace;
+begin
+  TestSingle('',tkWhitespace);
+end;
+
+procedure TTestScanner.TestString;
+begin
+  TestSingle('"abcd"',webidlscanner.tkString,'abcd');
+end;
+
+procedure TTestScanner.TestNumberInteger;
+begin
+  TestSingle('123',tkNumberInteger,'123');
+end;
+
+procedure TTestScanner.TestNumberFloat;
+begin
+  TestSingle('1.23',tkNumberFloat,'1.23');
+end;
+
+procedure TTestScanner.TestNumberHex;
+begin
+  TestSingle('0xABCDEF',tkNumberInteger,'0xABCDEF');
+end;
+
+procedure TTestScanner.TestNumberHex2;
+begin
+  // E is special
+  TestSingle('0xABCDE',tkNumberInteger,'0xABCDE');
+end;
+
+procedure TTestScanner.TestComma;
+begin
+  TestSingle(',',tkComma);
+end;
+
+procedure TTestScanner.TestColon;
+begin
+  TestSingle(':',tkColon);
+end;
+
+procedure TTestScanner.TestBracketOpen;
+begin
+  TestSingle('(',tkBracketOpen);
+end;
+
+procedure TTestScanner.TestBracketClose;
+begin
+  TestSingle(')',tkBracketClose);
+end;
+
+procedure TTestScanner.TestCurlyBraceOpen;
+begin
+  TestSingle('{',tkCurlyBraceOpen);
+end;
+
+procedure TTestScanner.TestCurlyBraceClose;
+begin
+  TestSingle('}',tkCurlyBraceClose);
+end;
+
+procedure TTestScanner.TestSquaredBraceOpen;
+begin
+  TestSingle('[',tkSquaredBraceOpen);
+end;
+
+procedure TTestScanner.TestSquaredBraceClose;
+begin
+  TestSingle(']',tkSquaredBraceClose);
+end;
+
+procedure TTestScanner.TestIdentifier;
+begin
+  TestSingle('A',tkIdentifier,'A');
+end;
+
+procedure TTestScanner.TestDot;
+begin
+  TestSingle('.',tkDot);
+end;
+
+procedure TTestScanner.TestSemicolon;
+begin
+  TestSingle(';',tkSemiColon);
+end;
+
+procedure TTestScanner.TestLess;
+begin
+  TestSingle('<',tkLess);
+end;
+
+procedure TTestScanner.TestEqual;
+begin
+  TestSingle('=',tkEqual);
+end;
+
+procedure TTestScanner.TestLarger;
+begin
+  TestSingle('>',tkLarger);
+end;
+
+procedure TTestScanner.TestQuestionMark;
+begin
+  TestSingle('?',tkQuestionMark);
+end;
+
+procedure TTestScanner.TestMinus;
+begin
+  TestSingle('-',tkMinus);
+end;
+
+procedure TTestScanner.TestOther;
+begin
+  TestSingle('other',tkOther);
+end;
+
+procedure TTestScanner.Testshort;
+begin
+  TestSingle('short',tkShort);
+end;
+
+procedure TTestScanner.TestTrue;
+begin
+  TestSingle('true',tkTrue);
+end;
+
+procedure TTestScanner.TestFalse;
+begin
+  TestSingle('false',tkFalse);
+end;
+
+procedure TTestScanner.TestNull;
+begin
+  TestSingle('null',tkNull);
+end;
+
+procedure TTestScanner.TestAny;
+begin
+  TestSingle('any',webidlscanner.tkAny);
+end;
+
+procedure TTestScanner.TestAttribute;
+begin
+  TestSingle('attribute',tkAttribute);
+end;
+
+procedure TTestScanner.TestCallback;
+begin
+  TestSingle('callback',tkCallBack);
+end;
+
+procedure TTestScanner.TestConst;
+begin
+  TestSingle('const',tkConst);
+end;
+
+procedure TTestScanner.TestDeleter;
+begin
+  TestSingle('deleter',tkDeleter);
+end;
+
+procedure TTestScanner.TestDictionary;
+begin
+  TestSingle('dictionary',tkDictionary);
+end;
+
+procedure TTestScanner.TestEllipsis;
+begin
+  TestSingle('ellipsis',tkellipsis);
+end;
+
+procedure TTestScanner.TestEnum;
+begin
+  TestSingle('enum',tkenum);
+end;
+
+procedure TTestScanner.TestGetter;
+begin
+  TestSingle('getter',tkgetter);
+end;
+
+procedure TTestScanner.TestImplements;
+begin
+  TestSingle('implements',tkimplements);
+  Version:=v2;
+  TestSingle('implements',tkIdentifier);
+end;
+
+procedure TTestScanner.TestMapLike;
+begin
+  Version:=v2;
+  TestSingle('maplike',tkmaplike);
+  Version:=v1;
+  TestSingle('maplike',tkIdentifier);
+end;
+
+procedure TTestScanner.TestSetLike;
+begin
+  Version:=v2;
+  TestSingle('setlike',tkSetlike);
+  Version:=v1;
+  TestSingle('setlike',tkIdentifier);
+end;
+
+procedure TTestScanner.TestRecord;
+begin
+  Version:=v2;
+  TestSingle('record',webidlscanner.tkRecord);
+  Version:=v1;
+  TestSingle('record',tkIdentifier);
+end;
+
+procedure TTestScanner.TestInfinity;
+begin
+  TestSingle('Infinity',tkinfinity);
+end;
+
+procedure TTestScanner.TestInherit;
+begin
+  TestSingle('inherit',tkinherit);
+end;
+
+procedure TTestScanner.TestInterface;
+begin
+  TestSingle('interface',webidlscanner.tkinterface);
+end;
+
+procedure TTestScanner.TestIterable;
+begin
+  TestSingle('iterable',tkiterable);
+end;
+
+procedure TTestScanner.TestLegacyCaller;
+begin
+  TestSingle('legacycaller',tklegacycaller);
+end;
+
+procedure TTestScanner.TestNan;
+begin
+  TestSingle('NaN',tkNan);
+end;
+
+procedure TTestScanner.TestNegInfinity;
+begin
+  TestSingle('-Infinity',tkneginfinity);
+end;
+
+procedure TTestScanner.TestOptional;
+begin
+  TestSingle('optional',tkoptional);
+end;
+
+procedure TTestScanner.TestOr;
+begin
+  TestSingle('or',tkOR);
+end;
+
+procedure TTestScanner.TestPartial;
+begin
+  TestSingle('partial',tkPartial);
+end;
+
+procedure TTestScanner.TestReadOnly;
+begin
+  TestSingle('readonly',tkreadonly);
+end;
+
+procedure TTestScanner.TestRequired;
+begin
+  TestSingle('required',tkrequired);
+end;
+
+procedure TTestScanner.TestSetter;
+begin
+  TestSingle('setter',tksetter);
+end;
+
+procedure TTestScanner.TestStatic;
+begin
+  TestSingle('static',tkstatic);
+end;
+
+procedure TTestScanner.TestStringifier;
+begin
+  TestSingle('stringifier',tkstringifier);
+end;
+
+procedure TTestScanner.TestTypedef;
+begin
+  TestSingle('typedef',tktypeDef);
+end;
+
+procedure TTestScanner.TestUnrestricted;
+begin
+  TestSingle('unrestricted',tkunrestricted);
+end;
+
+procedure TTestScanner.TestPromise;
+begin
+  TestSingle('Promise',tkpromise);
+end;
+
+procedure TTestScanner.TestByteString;
+begin
+  TestSingle('ByteString',tkBytestring);
+end;
+
+procedure TTestScanner.TestDOMString;
+begin
+  TestSingle('DOMString',tkDOMstring);
+end;
+
+procedure TTestScanner.TestUSVString;
+begin
+  TestSingle('USVString',tkUSVString);
+end;
+
+procedure TTestScanner.Testboolean;
+begin
+  TestSingle('boolean',tkBoolean);
+end;
+
+procedure TTestScanner.Testbyte;
+begin
+  TestSingle('byte',tkByte);
+end;
+
+procedure TTestScanner.Testdouble;
+begin
+  TestSingle('double',webidlscanner.tkDouble);
+end;
+
+procedure TTestScanner.Testfloat;
+begin
+  TestSingle('float',webidlscanner.tkfloat);
+end;
+
+procedure TTestScanner.Testlong;
+begin
+  TestSingle('long',tklong);
+end;
+
+procedure TTestScanner.Testobject;
+begin
+  TestSingle('object',webidlscanner.tkObject);
+end;
+
+procedure TTestScanner.Testoctet;
+begin
+  TestSingle('octet',tkOctet);
+end;
+
+procedure TTestScanner.Testunsigned;
+begin
+  TestSingle('unsigned',tkUnsigned);
+end;
+
+procedure TTestScanner.Testvoid;
+begin
+  TestSingle('void',tkVoid);
+end;
+
+procedure TTestScanner.SetVersion(AValue: TWEbIDLversion);
+begin
+  if FVersion=AValue then Exit;
+  FVersion:=AValue;
+  if Assigned(FScanner) then
+    FScanner.Version:=FVersion;
+end;
+
+procedure TTestScanner.Init(const aSource: string);
+begin
+  FreeAndNil(FScanner);
+  FScanner:=TWebIDLScanner.Create(aSource);
+  FScanner.Version:=FVersion;
+end;
+
+class procedure TTestScanner.AssertEquals(Msg: String; AExpected,AActual: TIDLToken);
+begin
+  AssertEQuals(Msg,GetEnumName(TypeInfo(TIDLToken),Ord(AExpected)),GetEnumName(TypeInfo(TIDLToken),Ord(AActual)));
+end;
+
+procedure TTestScanner.TestSingle(const aSource: String; AToken: TIDLToken);
+begin
+  TestMulti(aSource,[aToken]);
+end;
+
+procedure TTestScanner.TestMulti(const aSource: String;
+  AToken: array of TIDLToken);
+
+Var
+  I : Integer;
+  t : TIDLToken;
+
+begin
+  Init(ASource);
+  I:=0;
+  Repeat
+    t:=Scanner.FetchToken;
+    If T<>tkEOF then
+      begin
+      If I>High(AToken) then
+        Fail(Format('"%s": Too many tokens in source (got: %d, expected: %d)',[aSource,I+1,High(aToken)+1]));
+      AssertEquals('"'+ASource+'": token '+IntToStr(I),AToken[I],T);
+      Inc(I);
+      end
+  Until (t=tkEOF);
+  If I<High(AToken) then
+    Fail('"'+ASource+'": Too little tokens in source');
+end;
+
+procedure TTestScanner.TestSingle(const aSource: String; AToken: TIDLToken;
+  AValue: String);
+begin
+  TestMulti(aSource,[aToken],[aValue]);
+end;
+
+procedure TTestScanner.TestMulti(const aSource: String;
+  AToken: array of TIDLToken; AValues: array of String);
+Var
+  I : Integer;
+  t : TIDLToken;
+
+begin
+  Init(ASource);
+  I:=0;
+  Repeat
+    t:=Scanner.FetchToken;
+    If T<>tkEOF then
+      begin
+      If I>High(AToken) then
+        Fail(Format('"%s": Too many tokens in source (got: %d, expected: %d)',[aSource,I+1,High(aToken)+1]));
+      AssertEquals('"'+ASource+'": token '+IntToStr(I),AToken[I],T);
+      AssertEquals('"'+ASource+'": String '+IntToStr(I),AValues[I],FScanner.CurTokenString);
+      Inc(I);
+      end
+  Until (t=tkEOF);
+  If I<High(AToken) then
+    Fail('"'+ASource+'": Too little tokens in source');
+end;
+
+procedure TTestScanner.SetUp;
+begin
+  Version:=v1;
+end;
+
+procedure TTestScanner.TearDown;
+begin
+  FreeAndNil(FScanner);
+end;
+
+initialization
+
+  RegisterTest(TTestScanner);
+end.
+

+ 549 - 0
packages/webidl/tests/tcwebidldefs.pp

@@ -0,0 +1,549 @@
+unit tcwebidldefs;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testregistry, webidldefs;
+
+Type
+
+  { TTestParser }
+
+  { TTestDefinition }
+
+  TTestDefinition = Class(TTestCase)
+  private
+    FDef: TIDLDefinition;
+    function CreateUnionTypeDef(Types : Array of UTF8String; withAttrs: Boolean=False): TIDLUnionTypeDefDefinition;
+    function CreateArgument(isOptional : Boolean; DefaultValue : string = ''; withAttrs: Boolean=False): TIDLArgumentDefinition;
+    function CreateFunction(Options: TFunctionOptions; Args: Array of UTF8String; withAttrs: Boolean=False): TIDLFunctionDefinition;
+    function CreateAttribute(Options: TAttributeOptions; withAttrs: Boolean=False): TIDLAttributeDefinition;
+    function CreateConst(withAttrs: Boolean=False): TIDLConstDefinition;
+    function CreateImplements(Const ATypeName : String; withAttrs: Boolean=False): TIDLImplementsDefinition;
+    function CreateIncludes(Const ATypeName : String; withAttrs: Boolean=False): TIDLIncludesDefinition;
+    function CreateTypeDef(Const ATypeName : String; withAttrs: Boolean=False): TIDLTypeDefDefinition;
+    function CreateInterface(Const AParentName : String; aMembers : Array of TIDLDefinition; withAttrs: Boolean=False): TIDLInterfaceDefinition;
+    function CreateDictionaryMember(Const AName,aTypeName,aDefault : String; aRequired : Boolean; withAttrs: Boolean=False): TIDLDictionaryMemberDefinition;
+    function CreateDictionary(Const AParentName : String; aMembers : Array of TIDLDictionaryMemberDefinition; withAttrs: Boolean=False): TIDLDictionaryDefinition;
+    function CreateSequence(Const AElementName : String; withAttrs: Boolean=False): TIDLSequenceTypeDefDefinition;
+    function CreatePromise(Const AReturnTypeName: String; withAttrs: Boolean=False): TIDLPromiseTypeDefDefinition;
+    function CreateSetLike(Const AElementName: String; withAttrs: Boolean=False): TIDLSetLikeDefinition;
+    function CreateMapLike(Const AKeyTypeName,AValueTypeName: String; withAttrs: Boolean=False): TIDLMapLikeDefinition;
+    function CreateRecord(Const AKeyTypeName,AValueTypeName: String; withAttrs: Boolean=False): TIDLRecordDefinition;
+  Public
+    Procedure TearDown; override;
+    function CreateDef(aClass: TIDLDefinitionClass; WithAttrs: Boolean=False): TIDLDefinition;
+    Procedure TestDef(Const aDef : String; AFull : Boolean);
+    Property Def : TIDLDefinition Read FDef Write FDef;
+  published
+    Procedure TestConst;
+    procedure TestAttribute;
+    procedure TestStringifierAttribute;
+    procedure TestStringifierFunction;
+    procedure TestFunction;
+    procedure TestCallBackFunction;
+    procedure TestArgument;
+    procedure TestImplements;
+    procedure TestIncludes;
+    procedure TestTypeDef;
+    procedure TestUnionTypeDef;
+    procedure TestInterface;
+    procedure TestDictionaryMember;
+    procedure TestDictionary;
+    procedure TestCallbackInterface;
+    procedure TestSequence;
+    procedure TestPromise;
+    procedure TestMapLike;
+    procedure TestSetLike;
+    procedure TestRecord;
+  end;
+
+implementation
+
+{ TTestDefinition }
+
+procedure TTestDefinition.TearDown;
+begin
+  FreeAndNil(FDef);
+  inherited TearDown;
+end;
+
+function TTestDefinition.CreateDef(aClass: TIDLDefinitionClass; WithAttrs : Boolean = False): TIDLDefinition;
+begin
+  FreeAndNil(FDef);
+  FDef:=aClass.Create(Nil,'A');
+  if WithAttrs then
+    FDef.Attributes.Add('Me');
+  Result:=FDef;
+end;
+
+procedure TTestDefinition.TestDef(const aDef: String; AFull: Boolean);
+
+begin
+  AssertEquals('Def '+FDef.ClassName +'.AsString('+BoolToStr(aFull,'True','False')+')',ADef,FDef.AsString(afull));
+end;
+
+function TTestDefinition.CreateConst(withAttrs: Boolean): TIDLConstDefinition;
+
+begin
+  Result:=CreateDef(TIDLConstDefinition,WithAttrs) as TIDLConstDefinition;
+  Result.TypeName:='short';
+  Result.Value:='0x8080';
+end;
+
+function TTestDefinition.CreateImplements(const ATypeName: String;
+  withAttrs: Boolean): TIDLImplementsDefinition;
+begin
+  Result:=CreateDef(TIDLImplementsDefinition,WithAttrs) as TIDLImplementsDefinition;
+  Result.ImplementedInterface:=ATypeName;
+end;
+
+function TTestDefinition.CreateIncludes(const ATypeName: String;
+  withAttrs: Boolean): TIDLIncludesDefinition;
+begin
+  Result:=CreateDef(TIDLIncludesDefinition,WithAttrs) as TIDLIncludesDefinition;
+  Result.IncludedInterface:=ATypeName;
+end;
+
+function TTestDefinition.CreateTypeDef(const ATypeName: String;
+  withAttrs: Boolean): TIDLTypeDefDefinition;
+begin
+  Result:=CreateDef(TIDLTypeDefDefinition,WithAttrs) as TIDLTypeDefDefinition;
+  Result.TypeName:=ATypeName;
+end;
+
+function TTestDefinition.CreateInterface(const AParentName: String;
+  aMembers: array of TIDLDefinition; withAttrs: Boolean
+  ): TIDLInterfaceDefinition;
+
+Var
+  M : TIDLDefinition;
+
+begin
+  Result:=CreateDef(TIDLInterfaceDefinition,WithAttrs) as TIDLInterfaceDefinition;
+  Result.ParentName:=AParentName;
+  For M in aMembers do
+    Result.members.Add(M);
+end;
+
+function TTestDefinition.CreateDictionaryMember(const AName, aTypeName,
+  aDefault: String; aRequired: Boolean; withAttrs: Boolean
+  ): TIDLDictionaryMemberDefinition;
+begin
+  Result:=CreateDef(TIDLDictionaryMemberDefinition,WithAttrs) as TIDLDictionaryMemberDefinition;
+  Result.Name:=aName;
+  Result.MemberType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.MemberType.TypeName:=aTypeName;
+  Result.IsRequired:=aRequired;
+  if (aDefault<>'') then
+    begin
+    Result.DefaultValue:=TIDLConstDefinition.Create(Result,'');
+    Result.DefaultValue.Value:=aDefault;
+    end;
+end;
+
+function TTestDefinition.CreateDictionary(const AParentName: String;
+  aMembers: array of TIDLDictionaryMemberDefinition; withAttrs: Boolean
+  ): TIDLDictionaryDefinition;
+
+Var
+  M : TIDLDictionaryMemberDefinition;
+
+begin
+  Result:=CreateDef(TIDLDictionaryDefinition,WithAttrs) as TIDLDictionaryDefinition;
+  Result.ParentName:=aParentName;
+  for M in aMembers do
+    Result.Members.Add(M);
+end;
+
+function TTestDefinition.CreateSequence(const AElementName: String;
+  withAttrs: Boolean): TIDLSequenceTypeDefDefinition;
+
+begin
+  Result:=CreateDef(TIDLSequenceTypeDefDefinition,WithAttrs) as TIDLSequenceTypeDefDefinition;
+  Result.ElementType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.ElementType.TypeName:=AElementName;
+end;
+
+function TTestDefinition.CreatePromise(const AReturnTypeName: String;
+  withAttrs: Boolean): TIDLPromiseTypeDefDefinition;
+begin
+  Result:=CreateDef(TIDLPromiseTypeDefDefinition,withAttrs) as TIDLPromiseTypeDefDefinition;
+  Result.ReturnType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.ReturnType.TypeName:=AReturnTypeName;
+end;
+
+function TTestDefinition.CreateSetLike(const AElementName: String;
+  withAttrs: Boolean): TIDLSetLikeDefinition;
+begin
+  Result:=CreateDef(TIDLSetLikeDefinition,WithAttrs) as TIDLSetLikeDefinition;
+  Result.ElementType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.ElementType.TypeName:=AElementName;
+
+end;
+
+function TTestDefinition.CreateMapLike(const AKeyTypeName,
+  AValueTypeName: String; withAttrs: Boolean): TIDLMapLikeDefinition;
+begin
+  Result:=CreateDef(TIDLMapLikeDefinition,WithAttrs) as TIDLMapLikeDefinition;
+  Result.KeyType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.KeyType.TypeName:=AKeyTypeName;
+  Result.ValueType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.ValueType.TypeName:=AValueTypeName;
+end;
+
+function TTestDefinition.CreateRecord(const AKeyTypeName,
+  AValueTypeName: String; withAttrs: Boolean): TIDLRecordDefinition;
+begin
+  Result:=CreateDef(TIDLRecordDefinition,WithAttrs) as TIDLRecordDefinition;
+  Result.KeyType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.KeyType.TypeName:=AKeyTypeName;
+  Result.ValueType:=TIDLTypeDefDefinition.Create(Result,'');
+  Result.ValueType.TypeName:=AValueTypeName;
+end;
+
+procedure TTestDefinition.TestConst;
+
+begin
+  CreateConst(False);
+  TestDef('const short A 0x8080',true);
+  TestDef('short A 0x8080',False);
+  CreateConst(True);
+  TestDef('[Me] const short A 0x8080',true);
+  TestDef('short A 0x8080',False);
+end;
+
+function TTestDefinition.CreateUnionTypeDef(Types: array of UTF8String;
+  withAttrs: Boolean): TIDLUnionTypeDefDefinition;
+
+Var
+  S : UTF8String;
+  T : TIDLTypeDefDefinition;
+
+begin
+  Result:=CreateDef(TIDLUnionTypeDefDefinition,WithAttrs) as TIDLUnionTypeDefDefinition;
+  for S in Types do
+    begin
+    T:=TIDLTypeDefDefinition.Create(Result,'');
+    T.TypeName:=S;
+    Result.Union.Add(T);
+    end;
+end;
+
+function TTestDefinition.CreateArgument(isOptional: Boolean; DefaultValue: string; withAttrs: Boolean): TIDLArgumentDefinition;
+begin
+  Result:=CreateDef(TIDLArgumentDefinition,WithAttrs) as TIDLArgumentDefinition;
+  Result.ArgumentType:=TIDLTypeDefDefinition.Create(Result,'AN');
+  Result.ArgumentType.TypeName:='short';
+  Result.HasDefaultValue:=(DefaultValue<>'');
+  Result.DefaultValue:=DefaultValue;
+  Result.IsOptional:=IsOptional;
+end;
+
+function TTestDefinition.CreateFunction(Options: TFunctionOptions; Args: array of UTF8String; withAttrs: Boolean): TIDLFunctionDefinition;
+
+Var
+  I : integer;
+
+begin
+  Result:=CreateDef(TIDLFunctionDefinition,WithAttrs) as TIDLFunctionDefinition;
+  Result.ReturnType:=TIDLTypeDefDefinition.Create(Result,'AN');
+  Result.ReturnType.TypeName:='short';
+  Result.Options:=Options;
+  I:=0;
+  While I<Length(Args)-1 do
+    begin
+    Result.Arguments.Add(TIDLArgumentDefinition,args[I+1]);
+    Result.Argument[I div 2].ArgumentType:=TIDLTypeDefDefinition.Create(Result,'AN'+IntToStr(i));
+    Result.Argument[I div 2].ArgumentType.TypeName:=args[i];
+//    With Result.Argument[I div 2] do
+//      Writeln(I,': ',Name+'->',ArgumentType.TypeName);
+    Inc(I,2);
+    end;
+end;
+
+function TTestDefinition.CreateAttribute(Options: TAttributeOptions;
+  withAttrs: Boolean): TIDLAttributeDefinition;
+
+begin
+  Result:=CreateDef(TIDLAttributeDefinition,WithAttrs) as TIDLAttributeDefinition;
+  Result.AttributeType:=TIDLTypeDefDefinition.Create(Result,'AN');
+  Result.AttributeType.TypeName:='short';
+  Result.Options:=Options;
+end;
+
+procedure TTestDefinition.TestAttribute;
+
+begin
+  CreateAttribute([],False);
+  TestDef('attribute short A',true);
+  TestDef('short A',False);
+  CreateAttribute([],True);
+  TestDef('[Me] attribute short A',true);
+  TestDef('short A',False);
+  CreateAttribute([aoReadonly],false);
+  TestDef('readonly attribute short A',true);
+  TestDef('short A',False);
+  CreateAttribute([aoStatic],false);
+  TestDef('static attribute short A',true);
+  TestDef('short A',False);
+end;
+
+procedure TTestDefinition.TestStringifierAttribute;
+begin
+  CreateAttribute([aoStringifier],false);
+  TestDef('stringifier attribute short A',true);
+  TestDef('short A',False);
+  CreateAttribute([aoStringifier,aoReadOnly],false);
+  TestDef('stringifier readonly attribute short A',true);
+  TestDef('short A',False);
+end;
+
+procedure TTestDefinition.TestStringifierFunction;
+begin
+  CreateFunction([foStringifier],[],False);
+  TestDef('stringifier short A ()',True);
+end;
+
+procedure TTestDefinition.TestFunction;
+
+Var
+  F : TIDLFunctionDefinition;
+
+begin
+  CreateFunction([],[],False);
+  TestDef('short A ()',True);
+  CreateFunction([],['short','B'],False);
+  TestDef('short A (short B)',True);
+  TestDef('short A (short B)',False);
+  CreateFunction([],['short','B'],True);
+  TestDef('[Me] short A (short B)',True);
+  F:=CreateFunction([],['short','B','long','C'],False);
+  F.Argument[1].IsOptional:=True;
+  TestDef('short A (short B, optional long C)',True);
+  F.Argument[1].HasDefaultValue:=True;
+  F.Argument[1].DefaultValue:='123';
+  TestDef('short A (short B, optional long C = 123)',True);
+  CreateFunction([foStatic],[],False);
+  TestDef('static short A ()',True);
+  CreateFunction([foGetter],[],False);
+  TestDef('getter short A ()',True);
+  CreateFunction([foSetter],[],False);
+  TestDef('setter short A ()',True);
+end;
+
+procedure TTestDefinition.TestCallBackFunction;
+begin
+  CreateFunction([foCallback],[],False);
+  TestDef('callback A = short ()',True);
+end;
+
+procedure TTestDefinition.TestArgument;
+
+begin
+  CreateArgument(False,'',False);
+  TestDef('short A',true);
+  CreateArgument(False,'',False).ArgumentType.AllowNull:=True;
+  TestDef('short? A',true);
+  CreateArgument(true,'',False);
+  TestDef('optional short A',true);
+  CreateArgument(true,'',true);
+  TestDef('[Me] optional short A',true);
+  CreateArgument(true,'1',true);
+  TestDef('[Me] optional short A = 1',true);
+end;
+
+procedure TTestDefinition.TestImplements;
+
+begin
+  CreateImplements('IME',False);
+  TestDef('A implements IME',False);
+  TestDef('A implements IME',True);
+  CreateImplements('IME',True);
+  TestDef('A implements IME',False);
+  TestDef('[Me] A implements IME',True);
+end;
+
+procedure TTestDefinition.TestIncludes;
+begin
+  CreateIncludes('IME',False);
+  TestDef('A includes IME',False);
+  TestDef('A includes IME',True);
+  CreateIncludes('IME',True);
+  TestDef('A includes IME',False);
+  TestDef('[Me] A includes IME',True);
+end;
+
+procedure TTestDefinition.TestTypeDef;
+
+begin
+  CreateTypeDef('IME',False);
+  TestDef('IME',False);
+  TestDef('typedef IME A',true);
+  CreateTypeDef('IME',True);
+  TestDef('IME',False);
+  TestDef('[Me] typedef IME A',true);
+  CreateTypeDef('IME',True).AllowNull:=True;
+  TestDef('IME?',False);
+  TestDef('[Me] typedef IME? A',true);
+end;
+
+procedure TTestDefinition.TestUnionTypeDef;
+begin
+  CreateUnionTypeDef(['string','short'],False);
+  TestDef('(string or short)',False);
+  TestDef('typedef (string or short) A',true);
+  CreateUnionTypeDef(['string','short','unsigned long long'],true);
+  TestDef('(string or short or unsigned long long)',False);
+  TestDef('[Me] typedef (string or short or unsigned long long) A',true);
+end;
+
+procedure TTestDefinition.TestInterface;
+
+Var
+  C : TIDLConstDefinition;
+  D : TIDLFunctionDefinition;
+
+begin
+  CreateInterface('',[],False);
+  TestDef('interface A {'+sLinebreak+'}',True);
+  CreateInterface('B',[]);
+  TestDef('interface A : B {'+sLinebreak+'}',True);
+  C:=CreateConst(False);
+  Def:=Nil;
+  CreateInterface('B',[C]);
+  TestDef('interface A : B {'+sLinebreak+'  const short A 0x8080;'+sLineBreak+'}',True);
+  C:=CreateConst(False);
+  C.Name:='D';
+  Def:=Nil;
+  D:=CreateFunction([],[],True);
+  D.Name:='C';
+  Def:=Nil;
+  CreateInterface('B',[C,D]);
+  TestDef('interface A : B {'+sLinebreak
+  +'  const short D 0x8080;'+sLineBreak
+  +'  [Me] short C ();'+sLineBreak
+  +'}',True);
+  CreateInterface('',[],False).IsPartial:=True;
+  TestDef('partial interface A {'+sLinebreak+'}',True);
+end;
+
+procedure TTestDefinition.TestDictionaryMember;
+
+begin
+  CreateDictionaryMember('A','short','',False,False);
+  TestDef('short A',False);
+  TestDef('short A',True);
+  CreateDictionaryMember('A','short','""',False,False);
+  TestDef('short A = ""',False);
+  TestDef('short A = ""',True);
+  CreateDictionaryMember('A','short','',True,False);
+  TestDef('required short A',False);
+  TestDef('required short A',True);
+  CreateDictionaryMember('A','short','',False,True);
+  TestDef('short A',False);
+  TestDef('[Me] short A',True);
+  CreateDictionaryMember('A','short','',true,True);
+  TestDef('required short A',False);
+  TestDef('[Me] required short A',True);
+end;
+
+procedure TTestDefinition.TestDictionary;
+
+Var
+  m1,m2 : TIDLDictionaryMemberDefinition;
+
+begin
+  CreateDictionary('',[],False);
+  TestDef('dictionary A {'+sLinebreak+'}',True);
+  CreateDictionary('B',[],False);
+  TestDef('dictionary A : B {'+sLinebreak+'}',True);
+  m1:=CreateDictionaryMember('B','short','',False,False);
+  Def:=Nil;
+  CreateDictionary('',[m1],False);
+  TestDef('dictionary A {'+sLinebreak+
+  '  short B;'+sLinebreak+
+  '}',True);
+  m1:=CreateDictionaryMember('C','short','',False,False);
+  Def:=Nil;
+  m2:=CreateDictionaryMember('D','short','',true,True);
+  Def:=Nil;
+  CreateDictionary('B',[m1,m2],False);
+  TestDef('dictionary A : B {'+sLinebreak+
+  '  short C;'+sLinebreak+
+  '  [Me] required short D;'+sLinebreak+
+  '}',True);
+
+end;
+
+procedure TTestDefinition.TestCallbackInterface;
+begin
+  CreateInterface('',[],False).IsCallBack:=True;
+  TestDef('callback interface A {'+sLinebreak+'}',True);
+end;
+
+procedure TTestDefinition.TestSequence;
+begin
+  CreateSequence('short',false);
+  TestDef('typedef sequence <short> A',True);
+  TestDef('sequence <short>',False);
+  CreateSequence('short',True);
+  TestDef('[Me] typedef sequence <short> A',True);
+  TestDef('sequence <short>',False);
+end;
+
+procedure TTestDefinition.TestPromise;
+begin
+  CreatePromise('short',false);
+  TestDef('typedef promise <short> A',True);
+  TestDef('promise <short>',False);
+  CreatePromise('short',true);
+  TestDef('[Me] typedef promise <short> A',True);
+  TestDef('promise <short>',False);
+  CreatePromise('short',False).AllowNull:=True;
+  TestDef('typedef promise <short>? A',True);
+  TestDef('promise <short>?',False);
+end;
+
+procedure TTestDefinition.TestMapLike;
+begin
+  CreateMapLike('short','string',false);
+  TestDef('maplike <short,string>',True);
+  TestDef('maplike <short,string>',False);
+  CreateMapLike('short','string', True);
+  TestDef('[Me] maplike <short,string>',True);
+  TestDef('maplike <short,string>',False);
+  CreateMapLike('short','string' ,false).IsReadOnly:=True;
+  TestDef('readonly maplike <short,string>',True);
+  TestDef('readonly maplike <short,string>',False);
+end;
+
+procedure TTestDefinition.TestSetLike;
+begin
+  CreateSetLike('string',false);
+  TestDef('setlike <string>',True);
+  TestDef('setlike <string>',False);
+  CreateSetLike('string', True);
+  TestDef('[Me] setlike <string>',True);
+  TestDef('setlike <string>',False);
+  CreateSetLike('string' ,false).IsReadOnly:=True;
+  TestDef('readonly setlike <string>',True);
+  TestDef('readonly setlike <string>',False);
+end;
+
+procedure TTestDefinition.TestRecord;
+begin
+  CreateRecord('short','string',false);
+  TestDef('typedef record <short,string>',True);
+  TestDef('record <short,string>',False);
+  CreateRecord('short','string', True);
+  TestDef('[Me] typedef record <short,string>',True);
+  TestDef('record <short,string>',False);
+end;
+
+initialization
+  RegisterTests([TTestDefinition])
+end.
+

+ 96 - 0
packages/webidl/tests/testidl.lpi

@@ -0,0 +1,96 @@
+r<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="testidl"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <CommandLineParams Value="--suite=TTestMapLikeInterfaceParser"/>
+      </local>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default">
+          <local>
+            <CommandLineParams Value="--suite=TTestMapLikeInterfaceParser"/>
+          </local>
+        </Mode0>
+      </Modes>
+    </RunParams>
+    <Units Count="7">
+      <Unit0>
+        <Filename Value="testidl.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="../src/webidlscanner.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="tcidlscanner.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="../src/webidlparser.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="../src/webidldefs.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="tcidlparser.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="tcwebidldefs.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit6>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="testidl"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 21 - 0
packages/webidl/tests/testidl.pas

@@ -0,0 +1,21 @@
+program testidl;
+
+{$mode objfpc}
+{$H+}
+
+uses
+  consoletestrunner, webidlscanner, tcidlscanner, webidlparser, webidldefs,
+  tcidlparser, tcwebidldefs;
+
+Var
+  Application : TTestRunner;
+
+begin
+  DefaultRunAllTests:=True;
+  DefaultFormat:=fPlain;
+  Application:=TTestRunner.Create(Nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.
+