From 332add0f0155f0033f9bec3b92957c563f2236f2 Mon Sep 17 00:00:00 2001 From: marco Date: Sun, 27 Jan 2008 17:45:38 +0000 Subject: [PATCH] * initial version git-svn-id: trunk@10064 - --- .gitattributes | 14 + packages/symbolic/Makefile | 2289 +++++++++++++++++++++++ packages/symbolic/Makefile.fpc | 30 + packages/symbolic/doc/optimization.txt | 89 + packages/symbolic/doc/symbolic.txt | 390 ++++ packages/symbolic/examples/Makefile | 1967 +++++++++++++++++++ packages/symbolic/examples/Makefile.fpc | 18 + packages/symbolic/examples/evaltest.pas | 100 + packages/symbolic/examples/rpnthing.pas | 179 ++ packages/symbolic/src/exprstrs.inc | 40 + packages/symbolic/src/parsexpr.inc | 498 +++++ packages/symbolic/src/rearrang.inc | 90 + packages/symbolic/src/symbexpr.inc | 1122 +++++++++++ packages/symbolic/src/symbolic.pas | 493 +++++ packages/symbolic/src/teval.inc | 722 +++++++ 15 files changed, 8041 insertions(+) create mode 100644 packages/symbolic/Makefile create mode 100644 packages/symbolic/Makefile.fpc create mode 100644 packages/symbolic/doc/optimization.txt create mode 100644 packages/symbolic/doc/symbolic.txt create mode 100644 packages/symbolic/examples/Makefile create mode 100644 packages/symbolic/examples/Makefile.fpc create mode 100644 packages/symbolic/examples/evaltest.pas create mode 100644 packages/symbolic/examples/rpnthing.pas create mode 100644 packages/symbolic/src/exprstrs.inc create mode 100644 packages/symbolic/src/parsexpr.inc create mode 100644 packages/symbolic/src/rearrang.inc create mode 100644 packages/symbolic/src/symbexpr.inc create mode 100644 packages/symbolic/src/symbolic.pas create mode 100644 packages/symbolic/src/teval.inc diff --git a/.gitattributes b/.gitattributes index 25c96f94db..32b9c31f6e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3901,6 +3901,20 @@ packages/svgalib/src/vgamouse.h svneol=native#text/plain packages/svgalib/src/vgamouse.pp svneol=native#text/plain packages/svgalib/tests/testvga.pp svneol=native#text/plain packages/svgalib/tests/vgatest.pp svneol=native#text/plain +packages/symbolic/Makefile svneol=native#text/plain +packages/symbolic/Makefile.fpc svneol=native#text/plain +packages/symbolic/doc/optimization.txt svneol=native#text/plain +packages/symbolic/doc/symbolic.txt svneol=native#text/plain +packages/symbolic/examples/Makefile svneol=native#text/plain +packages/symbolic/examples/Makefile.fpc svneol=native#text/plain +packages/symbolic/examples/evaltest.pas svneol=native#text/plain +packages/symbolic/examples/rpnthing.pas svneol=native#text/plain +packages/symbolic/src/exprstrs.inc svneol=native#text/plain +packages/symbolic/src/parsexpr.inc svneol=native#text/plain +packages/symbolic/src/rearrang.inc svneol=native#text/plain +packages/symbolic/src/symbexpr.inc svneol=native#text/plain +packages/symbolic/src/symbolic.pas svneol=native#text/plain +packages/symbolic/src/teval.inc svneol=native#text/plain packages/syslog/Makefile svneol=native#text/plain packages/syslog/Makefile.fpc svneol=native#text/plain packages/syslog/fpmake.pp svneol=native#text/plain diff --git a/packages/symbolic/Makefile b/packages/symbolic/Makefile new file mode 100644 index 0000000000..ec6eec7f2e --- /dev/null +++ b/packages/symbolic/Makefile @@ -0,0 +1,2289 @@ +# +# Don't edit, this file is generated by FPCMake Version 2.0.0 [2008/01/27] +# +default: all +MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded +BSDs = freebsd netbsd openbsd darwin +UNIXs = linux $(BSDs) solaris qnx +LIMIT83fs = go32v2 os2 emx watcom +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)),) +RUNBATCH=$(COMSPEC) /C +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))))) +endif +else +override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH))))) +endif +endif +override FPC:=$(subst $(SRCEXEEXT),,$(FPC)) +override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT) +FOUNDFPC:=$(strip $(wildcard $(FPC))) +ifeq ($(FOUNDFPC),) +FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))) +ifeq ($(FOUNDFPC),) +$(error Compiler $(FPC) not found) +endif +endif +ifndef FPC_COMPILERINFO +FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO) +endif +ifndef FPC_VERSION +FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO)) +endif +export FPC FPC_VERSION FPC_COMPILERINFO +unexport CHECKDEPEND ALLDEPENDENCIES +ifndef CPU_TARGET +ifdef CPU_TARGET_DEFAULT +CPU_TARGET=$(CPU_TARGET_DEFAULT) +endif +endif +ifndef OS_TARGET +ifdef OS_TARGET_DEFAULT +OS_TARGET=$(OS_TARGET_DEFAULT) +endif +endif +ifneq ($(words $(FPC_COMPILERINFO)),5) +FPC_COMPILERINFO+=$(shell $(FPC) -iSP) +FPC_COMPILERINFO+=$(shell $(FPC) -iTP) +FPC_COMPILERINFO+=$(shell $(FPC) -iSO) +FPC_COMPILERINFO+=$(shell $(FPC) -iTO) +endif +ifndef CPU_SOURCE +CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO)) +endif +ifndef CPU_TARGET +CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO)) +endif +ifndef OS_SOURCE +OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO)) +endif +ifndef OS_TARGET +OS_TARGET:=$(word 5,$(FPC_COMPILERINFO)) +endif +FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +TARGETSUFFIX=$(OS_TARGET) +SOURCESUFFIX=$(OS_SOURCE) +else +TARGETSUFFIX=$(FULL_TARGET) +SOURCESUFFIX=$(FULL_SOURCE) +endif +ifneq ($(FULL_TARGET),$(FULL_SOURCE)) +CROSSCOMPILE=1 +endif +ifeq ($(findstring makefile,$(MAKECMDGOALS)),) +ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),) +$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first) +endif +endif +ifneq ($(findstring $(OS_TARGET),$(BSDs)),) +BSDhier=1 +endif +ifeq ($(OS_TARGET),linux) +linuxHier=1 +endif +export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE +ifdef FPCDIR +override FPCDIR:=$(subst \,/,$(FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +else +override FPCDIR=wrong +endif +ifdef DEFAULT_FPCDIR +ifeq ($(FPCDIR),wrong) +override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +endif +endif +ifeq ($(FPCDIR),wrong) +ifdef inUnix +override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION) +ifeq ($(wildcard $(FPCDIR)/units),) +override FPCDIR=/usr/lib/fpc/$(FPC_VERSION) +endif +else +override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))))) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(BASEDIR) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=c:/pp +endif +endif +endif +endif +endif +ifndef CROSSBINDIR +CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX)) +endif +ifndef BINUTILSPREFIX +ifndef CROSSBINDIR +ifdef CROSSCOMPILE +BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)- +endif +endif +endif +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX)) +ifeq ($(UNITSDIR),) +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET)) +endif +PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra) +override PACKAGE_NAME=symbolic +override PACKAGE_VERSION=2.2.0 +ifeq ($(FULL_TARGET),i386-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-win32) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-os2) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-beos) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-solaris) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-qnx) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-netware) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-darwin) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-emx) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-watcom) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-wince) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),i386-symbian) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-atari) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),sparc-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-palmos) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-wince) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-gba) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-nds) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-embedded) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),arm-symbian) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override TARGET_UNITS+=symbolic +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override TARGET_UNITS+=symbolic +endif +override INSTALL_FPCPACKAGE=y +override INSTALL_FPCSUBDIR=packages +ifeq ($(FULL_TARGET),i386-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-win32) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-os2) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-beos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-solaris) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-qnx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netware) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-emx) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-watcom) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-wince) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-symbian) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-atari) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-palmos) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-wince) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-gba) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-nds) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),arm-symbian) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override COMPILER_INCLUDEDIR+=src +endif +ifeq ($(FULL_TARGET),i386-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-win32) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-os2) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-beos) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-solaris) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-qnx) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-netware) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-darwin) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-emx) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-watcom) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-wince) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),i386-symbian) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-atari) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),sparc-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-palmos) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-wince) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-gba) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-nds) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),arm-symbian) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override COMPILER_SOURCEDIR+=src tests +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override COMPILER_SOURCEDIR+=src tests +endif +override SHARED_BUILD=n +override SHARED_BUILD=n +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 +ifeq ($(OS_SOURCE),linux) +ifndef GCCLIBDIR +ifeq ($(CPU_TARGET),i386) +ifneq ($(findstring x86_64,$(shell uname -a)),) +ifeq ($(BINUTILSPREFIX),) +GCCLIBDIR:=$(shell dirname `gcc -m32 -print-libgcc-file-name`) +endif +endif +endif +ifeq ($(CPU_TARGET),powerpc64) +ifeq ($(BINUTILSPREFIX),) +GCCLIBDIR:=$(shell dirname `gcc -m64 -print-libgcc-file-name`) +endif +endif +endif +ifndef GCCLIBDIR +CROSSGCC=$(strip $(wildcard $(addsuffix /$(BINUTILSPREFIX)gcc$(SRCEXEEXT),$(SEARCHPATH)))) +ifneq ($(CROSSGCC),) +GCCLIBDIR:=$(shell dirname `$(CROSSGCC) -print-libgcc-file-name`) +endif +endif +ifndef OTHERLIBDIR +OTHERLIBDIR:=$(shell grep -v "^\#" /etc/ld.so.conf | awk '{ ORS=" "; print $1 }') +endif +endif +ifdef inUnix +ifeq ($(OS_SOURCE),netbsd) +OTHERLIBDIR+=/usr/pkg/lib +endif +export GCCLIBDIR OTHERLIB +endif +BATCHEXT=.bat +LOADEREXT=.as +EXEEXT=.exe +PPLEXT=.ppl +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.so +SHAREDLIBPREFIX=libfp +STATICLIBPREFIX=libp +IMPORTLIBPREFIX=libimp +RSTEXT=.rst +ifeq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),go32v1) +STATICLIBPREFIX= +SHORTSUFFIX=v1 +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +OEXT=.obj +ASMEXT=.asm +SHAREDLIBEXT=.dll +SHORTSUFFIX=wat +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +endif +ifeq ($(OS_TARGET),emx) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=emx +ECHO=echo +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),morphos) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=mos +endif +ifeq ($(OS_TARGET),atari) +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nw +endif +ifeq ($(OS_TARGET),netwlibc) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nwl +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +endif +ifeq ($(OS_TARGET),darwin) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=dwn +endif +ifeq ($(OS_TARGET),gba) +EXEEXT=.gba +SHAREDLIBEXT=.so +SHORTSUFFIX=gba +endif +ifeq ($(OS_TARGET),symbian) +SHAREDLIBEXT=.dll +SHORTSUFFIX=symbian +endif +else +ifeq ($(OS_TARGET),go32v1) +PPUEXT=.pp1 +OEXT=.o1 +ASMEXT=.s1 +SMARTEXT=.sl1 +STATICLIBEXT=.a1 +SHAREDLIBEXT=.so1 +STATICLIBPREFIX= +SHORTSUFFIX=v1 +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +SHORTSUFFIX=wat +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +PPUEXT=.ppw +OEXT=.ow +ASMEXT=.sw +SMARTEXT=.slw +STATICLIBEXT=.aw +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +PPUEXT=.ppo +ASMEXT=.so2 +OEXT=.oo2 +AOUTEXT=.out +SMARTEXT=.sl2 +STATICLIBPREFIX= +STATICLIBEXT=.ao2 +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),atari) +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nw +endif +ifeq ($(OS_TARGET),netwlibc) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nwl +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +endif +endif +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +FPCMADE=fpcmade.$(SHORTSUFFIX) +ZIPSUFFIX=$(SHORTSUFFIX) +ZIPCROSSPREFIX= +ZIPSOURCESUFFIX=src +ZIPEXAMPLESUFFIX=exm +else +FPCMADE=fpcmade.$(TARGETSUFFIX) +ZIPSOURCESUFFIX=.source +ZIPEXAMPLESUFFIX=.examples +ifdef CROSSCOMPILE +ZIPSUFFIX=.$(SOURCESUFFIX) +ZIPCROSSPREFIX=$(TARGETSUFFIX)- +else +ZIPSUFFIX=.$(TARGETSUFFIX) +ZIPCROSSPREFIX= +endif +endif +ifndef ECHO +ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO= __missing_command_ECHO +else +ECHO:=$(firstword $(ECHO)) +endif +else +ECHO:=$(firstword $(ECHO)) +endif +endif +export ECHO +ifndef DATE +DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE= __missing_command_DATE +else +DATE:=$(firstword $(DATE)) +endif +else +DATE:=$(firstword $(DATE)) +endif +endif +export DATE +ifndef GINSTALL +GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL= __missing_command_GINSTALL +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +endif +export GINSTALL +ifndef CPPROG +CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(CPPROG),) +CPPROG= __missing_command_CPPROG +else +CPPROG:=$(firstword $(CPPROG)) +endif +endif +export CPPROG +ifndef RMPROG +RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(RMPROG),) +RMPROG= __missing_command_RMPROG +else +RMPROG:=$(firstword $(RMPROG)) +endif +endif +export RMPROG +ifndef MVPROG +MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MVPROG),) +MVPROG= __missing_command_MVPROG +else +MVPROG:=$(firstword $(MVPROG)) +endif +endif +export MVPROG +ifndef MKDIRPROG +MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG= __missing_command_MKDIRPROG +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +endif +export MKDIRPROG +ifndef ECHOREDIR +ifndef inUnix +ECHOREDIR=echo +else +ECHOREDIR=$(ECHO) +endif +endif +ifndef COPY +COPY:=$(CPPROG) -fp +endif +ifndef COPYTREE +COPYTREE:=$(CPPROG) -Rfp +endif +ifndef MKDIRTREE +MKDIRTREE:=$(MKDIRPROG) -p +endif +ifndef MOVE +MOVE:=$(MVPROG) -f +endif +ifndef DEL +DEL:=$(RMPROG) -f +endif +ifndef DELTREE +DELTREE:=$(RMPROG) -rf +endif +ifndef INSTALL +ifdef inUnix +INSTALL:=$(GINSTALL) -c -m 644 +else +INSTALL:=$(COPY) +endif +endif +ifndef INSTALLEXE +ifdef inUnix +INSTALLEXE:=$(GINSTALL) -c -m 755 +else +INSTALLEXE:=$(COPY) +endif +endif +ifndef MKDIR +MKDIR:=$(GINSTALL) -m 755 -d +endif +export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR +ifndef PPUMOVE +PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(PPUMOVE),) +PPUMOVE= __missing_command_PPUMOVE +else +PPUMOVE:=$(firstword $(PPUMOVE)) +endif +endif +export PPUMOVE +ifndef FPCMAKE +FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(FPCMAKE),) +FPCMAKE= __missing_command_FPCMAKE +else +FPCMAKE:=$(firstword $(FPCMAKE)) +endif +endif +export FPCMAKE +ifndef ZIPPROG +ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ZIPPROG),) +ZIPPROG= __missing_command_ZIPPROG +else +ZIPPROG:=$(firstword $(ZIPPROG)) +endif +endif +export ZIPPROG +ifndef TARPROG +TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG= __missing_command_TARPROG +else +TARPROG:=$(firstword $(TARPROG)) +endif +else +TARPROG:=$(firstword $(TARPROG)) +endif +endif +export TARPROG +ASNAME=$(BINUTILSPREFIX)as +LDNAME=$(BINUTILSPREFIX)ld +ARNAME=$(BINUTILSPREFIX)ar +RCNAME=$(BINUTILSPREFIX)rc +ifneq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),win32) +ifeq ($(CROSSBINDIR),) +ASNAME=asw +LDNAME=ldw +ARNAME=arw +endif +endif +endif +ifndef ASPROG +ifdef CROSSBINDIR +ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT) +else +ASPROG=$(ASNAME) +endif +endif +ifndef LDPROG +ifdef CROSSBINDIR +LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT) +else +LDPROG=$(LDNAME) +endif +endif +ifndef RCPROG +ifdef CROSSBINDIR +RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT) +else +RCPROG=$(RCNAME) +endif +endif +ifndef ARPROG +ifdef CROSSBINDIR +ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT) +else +ARPROG=$(ARNAME) +endif +endif +AS=$(ASPROG) +LD=$(LDPROG) +RC=$(RCPROG) +AR=$(ARPROG) +PPAS=ppas$(SRCBATCHEXT) +ifdef inUnix +LDCONFIG=ldconfig +else +LDCONFIG= +endif +ifdef DATE +DATESTR:=$(shell $(DATE) +%Y%m%d) +else +DATESTR= +endif +ifndef UPXPROG +ifeq ($(OS_TARGET),go32v2) +UPXPROG:=1 +endif +ifeq ($(OS_TARGET),win32) +UPXPROG:=1 +endif +ifdef UPXPROG +UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(UPXPROG),) +UPXPROG= +else +UPXPROG:=$(firstword $(UPXPROG)) +endif +else +UPXPROG= +endif +endif +export UPXPROG +ZIPOPT=-9 +ZIPEXT=.zip +ifeq ($(USETAR),bz2) +TAROPT=vj +TAREXT=.tar.bz2 +else +TAROPT=vz +TAREXT=.tar.gz +endif +override REQUIRE_PACKAGES=rtl +ifeq ($(FULL_TARGET),i386-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-go32v2) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-win32) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-os2) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-beos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-solaris) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-qnx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netware) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-openbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-wdosx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-emx) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-watcom) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-wince) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),i386-symbian) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-amiga) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-atari) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-palmos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),m68k-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-macos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-solaris) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),sparc-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-win64) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-palmos) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-wince) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-gba) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-nds) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),arm-symbian) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +REQUIRE_PACKAGES_RTL=1 +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +REQUIRE_PACKAGES_RTL=1 +endif +ifdef REQUIRE_PACKAGES_RTL +PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR)))))) +ifneq ($(PACKAGEDIR_RTL),) +ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),) +UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX) +else +UNITDIR_RTL=$(PACKAGEDIR_RTL) +endif +ifdef CHECKDEPEND +$(PACKAGEDIR_RTL)/$(FPCMADE): + $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE) +override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE) +endif +else +PACKAGEDIR_RTL= +UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR))))) +ifneq ($(UNITDIR_RTL),) +UNITDIR_RTL:=$(firstword $(UNITDIR_RTL)) +else +UNITDIR_RTL= +endif +endif +ifdef UNITDIR_RTL +override COMPILER_UNITDIR+=$(UNITDIR_RTL) +endif +endif +ifndef NOCPUDEF +override FPCOPTDEF=$(CPU_TARGET) +endif +ifneq ($(OS_TARGET),$(OS_SOURCE)) +override FPCOPT+=-T$(OS_TARGET) +endif +ifneq ($(CPU_TARGET),$(CPU_SOURCE)) +override FPCOPT+=-P$(CPU_TARGET) +endif +ifeq ($(OS_SOURCE),openbsd) +override FPCOPT+=-FD$(NEW_BINUTILS_PATH) +endif +ifndef CROSSBOOTSTRAP +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-XP$(BINUTILSPREFIX) +endif +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-Xr$(RLINKPATH) +endif +endif +ifdef UNITDIR +override FPCOPT+=$(addprefix -Fu,$(UNITDIR)) +endif +ifdef LIBDIR +override FPCOPT+=$(addprefix -Fl,$(LIBDIR)) +endif +ifdef OBJDIR +override FPCOPT+=$(addprefix -Fo,$(OBJDIR)) +endif +ifdef INCDIR +override FPCOPT+=$(addprefix -Fi,$(INCDIR)) +endif +ifdef LINKSMART +override FPCOPT+=-XX +endif +ifdef CREATESMART +override FPCOPT+=-CX +endif +ifdef DEBUG +override FPCOPT+=-gl +override FPCOPTDEF+=DEBUG +endif +ifdef RELEASE +ifneq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(CPU_TARGET),i386) +FPCCPUOPT:=-OG2p3 +endif +ifeq ($(CPU_TARGET),powerpc) +FPCCPUOPT:=-O1r +endif +else +FPCCPUOPT:=-O2 +endif +override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n +override FPCOPTDEF+=RELEASE +endif +ifdef STRIP +override FPCOPT+=-Xs +endif +ifdef OPTIMIZE +override FPCOPT+=-O2 +endif +ifdef VERBOSE +override FPCOPT+=-vwni +endif +ifdef COMPILER_OPTIONS +override FPCOPT+=$(COMPILER_OPTIONS) +endif +ifdef COMPILER_UNITDIR +override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR)) +endif +ifdef COMPILER_LIBRARYDIR +override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR)) +endif +ifdef COMPILER_OBJECTDIR +override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR)) +endif +ifdef COMPILER_INCLUDEDIR +override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR)) +endif +ifdef CROSSBINDIR +override FPCOPT+=-FD$(CROSSBINDIR) +endif +ifdef COMPILER_TARGETDIR +override FPCOPT+=-FE$(COMPILER_TARGETDIR) +ifeq ($(COMPILER_TARGETDIR),.) +override TARGETDIRPREFIX= +else +override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/ +endif +endif +ifdef COMPILER_UNITTARGETDIR +override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR) +ifeq ($(COMPILER_UNITTARGETDIR),.) +override UNITTARGETDIRPREFIX= +else +override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/ +endif +else +ifdef COMPILER_TARGETDIR +override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR) +override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX) +endif +endif +ifdef CREATESHARED +override FPCOPT+=-Cg +ifeq ($(CPU_TARGET),i386) +override FPCOPT+=-Aas +endif +endif +ifeq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),linux) +ifeq ($(CPU_TARGET),x86_64) +override FPCOPT+=-Cg +endif +endif +endif +ifdef LINKSHARED +endif +ifdef GCCLIBDIR +override FPCOPT+=-Fl$(GCCLIBDIR) +endif +ifdef OTHERLIBDIR +override FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR)) +endif +ifdef OPT +override FPCOPT+=$(OPT) +endif +ifdef FPCOPTDEF +override FPCOPT+=$(addprefix -d,$(FPCOPTDEF)) +endif +ifdef CFGFILE +override FPCOPT+=@$(CFGFILE) +endif +ifdef USEENV +override FPCEXTCMD:=$(FPCOPT) +override FPCOPT:=!FPCEXTCMD +export FPCEXTCMD +endif +override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifneq ($(AFULL_TARGET),$(AFULL_SOURCE)) +override ACROSSCOMPILE=1 +endif +ifdef ACROSSCOMPILE +override FPCOPT+=$(CROSSOPT) +endif +override COMPILER:=$(FPC) $(FPCOPT) +ifeq (,$(findstring -s ,$(COMPILER))) +EXECPPAS= +else +ifeq ($(FULL_SOURCE),$(FULL_TARGET)) +ifdef RUNBATCH +EXECPPAS:=@$(RUNBATCH) $(PPAS) +else +EXECPPAS:=@$(PPAS) +endif +endif +endif +.PHONY: fpc_units +ifneq ($(TARGET_UNITS)$(TARGET_IMPLICITUNITS),) +override ALLTARGET+=fpc_units +override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS)) +override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS)) +override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES) +override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES) +endif +fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES) +ifdef TARGET_RSTS +override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS)) +override CLEANRSTFILES+=$(RSTFILES) +endif +.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared +$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET) + @$(ECHOREDIR) Compiled > $(FPCMADE) +fpc_all: $(FPCMADE) +fpc_smart: + $(MAKE) all LINKSMART=1 CREATESMART=1 +fpc_debug: + $(MAKE) all DEBUG=1 +fpc_release: + $(MAKE) all RELEASE=1 +.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res +$(COMPILER_UNITTARGETDIR): + $(MKDIRTREE) $(COMPILER_UNITTARGETDIR) +$(COMPILER_TARGETDIR): + $(MKDIRTREE) $(COMPILER_TARGETDIR) +%$(PPUEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(PPUEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.lpr + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.dpr + $(COMPILER) $< + $(EXECPPAS) +%.res: %.rc + windres -i $< -o $@ +vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.inc $(COMPILER_INCLUDEDIR) +vpath %$(OEXT) $(COMPILER_UNITTARGETDIR) +vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR) +.PHONY: fpc_shared +override INSTALLTARGET+=fpc_shared_install +ifndef SHARED_LIBVERSION +SHARED_LIBVERSION=$(FPC_VERSION) +endif +ifndef SHARED_LIBNAME +SHARED_LIBNAME=$(PACKAGE_NAME) +endif +ifndef SHARED_FULLNAME +SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT) +endif +ifndef SHARED_LIBUNITS +SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS) +override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS)) +endif +fpc_shared: +ifdef HASSHAREDLIB + $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1 +ifneq ($(SHARED_BUILD),n) + $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR) +endif +else + @$(ECHO) Shared Libraries not supported +endif +fpc_shared_install: +ifneq ($(SHARED_BUILD),n) +ifneq ($(SHARED_LIBUNITS),) +ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),) + $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR) +endif +endif +endif +.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall +ifdef INSTALL_UNITS +override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS)) +endif +ifdef INSTALL_BUILDUNIT +override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES)) +endif +ifdef INSTALLPPUFILES +override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) +ifneq ($(UNITTARGETDIRPREFIX),) +override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES))) +override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES)))) +endif +override INSTALL_CREATEPACKAGEFPC=1 +endif +ifdef INSTALLEXEFILES +ifneq ($(TARGETDIRPREFIX),) +override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES))) +endif +endif +fpc_install: all $(INSTALLTARGET) +ifdef INSTALLEXEFILES + $(MKDIR) $(INSTALL_BINDIR) +ifdef UPXPROG + -$(UPXPROG) $(INSTALLEXEFILES) +endif + $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR) +endif +ifdef INSTALL_CREATEPACKAGEFPC +ifdef FPCMAKE +ifdef PACKAGE_VERSION +ifneq ($(wildcard Makefile.fpc),) + $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) Package.fpc $(INSTALL_UNITDIR) +endif +endif +endif +endif +ifdef INSTALLPPUFILES + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR) +ifneq ($(INSTALLPPULINKFILES),) + $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR) +endif +ifneq ($(wildcard $(LIB_FULLNAME)),) + $(MKDIR) $(INSTALL_LIBDIR) + $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR) +ifdef inUnix + ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME) +endif +endif +endif +ifdef INSTALL_FILES + $(MKDIR) $(INSTALL_DATADIR) + $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR) +endif +fpc_sourceinstall: distclean + $(MKDIR) $(INSTALL_SOURCEDIR) + $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR) +fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS)) +ifdef HASEXAMPLES + $(MKDIR) $(INSTALL_EXAMPLEDIR) +endif +ifdef EXAMPLESOURCEFILES + $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR) +endif +ifdef TARGET_EXAMPLEDIRS + $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR) +endif +.PHONY: fpc_distinstall +fpc_distinstall: install exampleinstall +.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall +ifndef PACKDIR +ifndef inUnix +PACKDIR=$(BASEDIR)/../fpc-pack +else +PACKDIR=/tmp/fpc-pack +endif +endif +ifndef ZIPNAME +ifdef DIST_ZIPNAME +ZIPNAME=$(DIST_ZIPNAME) +else +ZIPNAME=$(PACKAGE_NAME) +endif +endif +ifndef FULLZIPNAME +FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX) +endif +ifndef ZIPTARGET +ifdef DIST_ZIPTARGET +ZIPTARGET=DIST_ZIPTARGET +else +ZIPTARGET=install +endif +endif +ifndef USEZIP +ifdef inUnix +USETAR=1 +endif +endif +ifndef inUnix +USEZIPWRAPPER=1 +endif +ifdef USEZIPWRAPPER +ZIPPATHSEP=$(PATHSEP) +ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT)) +else +ZIPPATHSEP=/ +endif +ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR)) +ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR)) +ifdef USETAR +ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT) +ZIPCMD_ZIP:=$(TARPROG) cf$(TAROPT) $(ZIPDESTFILE) * +else +ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT) +ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) * +endif +fpc_zipinstall: + $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1 + $(MKDIR) $(DIST_DESTDIR) + $(DEL) $(ZIPDESTFILE) +ifdef USEZIPWRAPPER +ifneq ($(ECHOREDIR),echo) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER) + $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER) +else + echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER) + echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER) + echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER) +endif +ifdef inUnix + /bin/sh $(ZIPWRAPPER) +else +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)) +endif +ifdef CLEAN_UNITS +override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS)) +endif +ifdef CLEANPPUFILES +override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) +ifdef DEBUGSYMEXT +override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES)) +endif +override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES)) +override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES))) +endif +fpc_clean: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +ifdef CLEAN_FILES + -$(DEL) $(CLEAN_FILES) +endif +ifdef LIB_NAME + -$(DEL) $(LIB_NAME) $(LIB_FULLNAME) +endif + -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT) +fpc_cleanall: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef COMPILER_UNITTARGETDIR +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +endif + -$(DELTREE) units + -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT) +ifneq ($(PPUEXT),.ppu) + -$(DEL) *.o *.ppu *.a +endif + -$(DELTREE) *$(SMARTEXT) + -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *_ppas$(BATCHEXT) +ifdef AOUTEXT + -$(DEL) *$(AOUTEXT) +endif +ifdef DEBUGSYMEXT + -$(DEL) *$(DEBUGSYMEXT) +endif +fpc_distclean: cleanall +.PHONY: fpc_baseinfo +override INFORULES+=fpc_baseinfo +fpc_baseinfo: + @$(ECHO) + @$(ECHO) == Package info == + @$(ECHO) Package Name..... $(PACKAGE_NAME) + @$(ECHO) Package Version.. $(PACKAGE_VERSION) + @$(ECHO) + @$(ECHO) == Configuration info == + @$(ECHO) + @$(ECHO) FPC.......... $(FPC) + @$(ECHO) FPC Version.. $(FPC_VERSION) + @$(ECHO) Source CPU... $(CPU_SOURCE) + @$(ECHO) Target CPU... $(CPU_TARGET) + @$(ECHO) Source OS.... $(OS_SOURCE) + @$(ECHO) Target OS.... $(OS_TARGET) + @$(ECHO) Full Source.. $(FULL_SOURCE) + @$(ECHO) Full Target.. $(FULL_TARGET) + @$(ECHO) SourceSuffix. $(SOURCESUFFIX) + @$(ECHO) TargetSuffix. $(TARGETSUFFIX) + @$(ECHO) + @$(ECHO) == Directory info == + @$(ECHO) + @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES) + @$(ECHO) + @$(ECHO) Basedir......... $(BASEDIR) + @$(ECHO) FPCDir.......... $(FPCDIR) + @$(ECHO) CrossBinDir..... $(CROSSBINDIR) + @$(ECHO) UnitsDir........ $(UNITSDIR) + @$(ECHO) PackagesDir..... $(PACKAGESDIR) + @$(ECHO) + @$(ECHO) GCC library..... $(GCCLIBDIR) + @$(ECHO) Other library... $(OTHERLIBDIR) + @$(ECHO) + @$(ECHO) == Tools info == + @$(ECHO) + @$(ECHO) As........ $(AS) + @$(ECHO) Ld........ $(LD) + @$(ECHO) Ar........ $(AR) + @$(ECHO) Rc........ $(RC) + @$(ECHO) + @$(ECHO) Mv........ $(MVPROG) + @$(ECHO) Cp........ $(CPPROG) + @$(ECHO) Rm........ $(RMPROG) + @$(ECHO) GInstall.. $(GINSTALL) + @$(ECHO) Echo...... $(ECHO) + @$(ECHO) Shell..... $(SHELL) + @$(ECHO) Date...... $(DATE) + @$(ECHO) FPCMake... $(FPCMAKE) + @$(ECHO) PPUMove... $(PPUMOVE) + @$(ECHO) Upx....... $(UPXPROG) + @$(ECHO) Zip....... $(ZIPPROG) + @$(ECHO) + @$(ECHO) == Object info == + @$(ECHO) + @$(ECHO) Target Loaders........ $(TARGET_LOADERS) + @$(ECHO) Target Units.......... $(TARGET_UNITS) + @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS) + @$(ECHO) Target Programs....... $(TARGET_PROGRAMS) + @$(ECHO) Target Dirs........... $(TARGET_DIRS) + @$(ECHO) Target Examples....... $(TARGET_EXAMPLES) + @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS) + @$(ECHO) + @$(ECHO) Clean Units......... $(CLEAN_UNITS) + @$(ECHO) Clean Files......... $(CLEAN_FILES) + @$(ECHO) + @$(ECHO) Install Units....... $(INSTALL_UNITS) + @$(ECHO) Install Files....... $(INSTALL_FILES) + @$(ECHO) + @$(ECHO) == Install info == + @$(ECHO) + @$(ECHO) DateStr.............. $(DATESTR) + @$(ECHO) ZipName.............. $(ZIPNAME) + @$(ECHO) ZipPrefix............ $(ZIPPREFIX) + @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX) + @$(ECHO) ZipSuffix............ $(ZIPSUFFIX) + @$(ECHO) FullZipName.......... $(FULLZIPNAME) + @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE) + @$(ECHO) + @$(ECHO) Install base dir..... $(INSTALL_BASEDIR) + @$(ECHO) Install binary dir... $(INSTALL_BINDIR) + @$(ECHO) Install library dir.. $(INSTALL_LIBDIR) + @$(ECHO) Install units dir.... $(INSTALL_UNITDIR) + @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR) + @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR) + @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR) + @$(ECHO) Install data dir..... $(INSTALL_DATADIR) + @$(ECHO) + @$(ECHO) Dist destination dir. $(DIST_DESTDIR) + @$(ECHO) Dist zip name........ $(DIST_ZIPNAME) + @$(ECHO) +.PHONY: fpc_info +fpc_info: $(INFORULES) +.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \ + fpc_makefile_dirs +fpc_makefile: + $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc +fpc_makefile_sub1: +ifdef TARGET_DIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS)) +endif +ifdef TARGET_EXAMPLEDIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS)) +endif +fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS)) +fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2 +fpc_makefiles: fpc_makefile fpc_makefile_dirs +all: fpc_all +debug: fpc_debug +smart: fpc_smart +release: fpc_release +units: fpc_units +examples: +shared: fpc_shared +install: fpc_install +sourceinstall: fpc_sourceinstall +exampleinstall: fpc_exampleinstall +distinstall: fpc_distinstall +zipinstall: fpc_zipinstall +zipsourceinstall: fpc_zipsourceinstall +zipexampleinstall: fpc_zipexampleinstall +zipdistinstall: fpc_zipdistinstall +clean: fpc_clean +distclean: fpc_distclean +cleanall: fpc_cleanall +info: fpc_info +makefiles: fpc_makefiles +.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles +ifneq ($(wildcard fpcmake.loc),) +include fpcmake.loc +endif +.NOTPARALLEL: diff --git a/packages/symbolic/Makefile.fpc b/packages/symbolic/Makefile.fpc new file mode 100644 index 0000000000..e908fe352a --- /dev/null +++ b/packages/symbolic/Makefile.fpc @@ -0,0 +1,30 @@ +# +# Makefile.fpc for Free Pascal ImLib 1.x Packages +# + +[package] +name=symbolic +version=2.2.0 + +[target] +units=symbolic + +[require] +libc=y + +[compiler] +includedir=src +sourcedir=src tests + +[install] +fpcpackage=y +fpcsubdir=packages + +[default] +fpcdir=../.. + +[shared] +build=n + +[rules] +.NOTPARALLEL: diff --git a/packages/symbolic/doc/optimization.txt b/packages/symbolic/doc/optimization.txt new file mode 100644 index 0000000000..d25f29da66 --- /dev/null +++ b/packages/symbolic/doc/optimization.txt @@ -0,0 +1,89 @@ +Simplifications +---------------- + +Simplification levels: +0 Do not simplify. +1 add real only to real and int only to int. +2 Same as 1, but integers are added to reals. (real1=int+real2) +3 Convert all integers to real, and then do 1. + +SimplifyConstants: +If Mode=0: only check integrity + + +- Evaluates all real constants, including things like Sin(5.0) +- Evaluates Real + + + CO + / \ + / \ + A B + / \ / \ + / \ / \ + C D E F + + +Node types: + + Ci constant (nodetype=iconstnode) + Cr real constant, (nodetype=constnode) + Cy expression (ExprIsConstant IN Flags, things like Sin(5) or even 4 DIV 6 if integer to real is off) + Cn is any of the three above constant types + CO= Commutative Operator (mul, add) + X Any other expression, + + + Constants always have to be arranged Ci CO then (C and D have no relevance) +if B <> CO then (E and F have no relevance) + + A C D B E F +action Cn - - CO Cn Cn (killed in SimplifyConstants} + Cn - - CO X Cn (Changed to E=C, F=X in killed in SimplifyConstants) + Cn - - CO Cn X (if A=Cx and E=Ci then swap(A,E)) + X - - CO + +---------------- +(from an older version of this doc:) + + A D Action +Xcomm <>Xcomm Process [b c d] +Xcomm Xcomm Process [b c e f] +<>Xcomm Xcomm Process [a e f] +<>Xcomm <>Xcoom Process [a d] + + +How to process: + +If Simplicationlevel<>0 then + begin + if (Simplicationlevel=3) or ((simplicationlevel=2) and (Cr in [])) then + {convert all Ci to Cr} + If more than one Ci in [] then + {addall Ci's to one Ci} + If more than one Cr in [] then + {addall Crs to one Cr} + end; +{determine how many elements in set left. (in practice kept track of in code +above)} +If we have only one xcomm on the right, xchg right and left} + +{Rearrange set so that +Ci < Cr < Cx < X + +#nodes nodes filled: +0 Not possible. +1 Root node only, but not possible (cases that could lead to this + are covered by the standard simplifications) +2 A, D +3 A, e f +4 b c e f + +TreeType: 0 A d + 1 b c d + 2 A e f + 3 b c e f + +} diff --git a/packages/symbolic/doc/symbolic.txt b/packages/symbolic/doc/symbolic.txt new file mode 100644 index 0000000000..2a032d391c --- /dev/null +++ b/packages/symbolic/doc/symbolic.txt @@ -0,0 +1,390 @@ +Unit Symbolic +------------ + +Unit Symbolic is something I wrote to take care of all my needs in the fields +of simple expression parsing and evaluating, and to act as base for more +complex manipulation. + +This doc originally was a notes file for myself. If it is unreadable, then +sorry. Rewrite of docs will have to wait until FCL doc-making practices +are clear. + +Author: +------- + +Marco van de Voort (Marco@freepascal.org) + +Target/Compiler: +------ + +FreePascal 1.1 (post 1.0 development). www.freepascal.org + +Should run on Delphi 4 with minimal changes. (and any Delphi that supports +overloading). If you remove the overloading it should run on D2..D5. I never +programmed 16-bit Object Pascal, so I don't know the D1 status + +I tested with D4, but forgot to merge all changes. +I fixed the more difficult Delphi problems see the ifdef near +the pvliwevalword definition) Probably replacing all Upcase() functions with +ansiuppercase and commenting the runerror msgs should get it to compile under +Delphi. + +Key features: +-------------- +(for the meaning of abbreviations, see the glossary + at the end of this document) + +General: + - 32-bit. Probably close to being 64-bit clean. (no integer <-> + pointer casts). D1 status unknown, since I never used it, and can't + tell easily. Biggest problem for ports is probably that it doesn't + account for aligned arrays. It also assumes pointer arithmic. + - OOP interface design, but sometimes uses procedures internally for + speed. + - Doesn't use (co)processor dependant features atm. An alternate method + in TEvaluator will have to take care of that. + - Optimised (algorithm) with high speed repeated evaluations in mind. + Parsing is NOT optimised, but not particulary dumb either. + If parsing is a speed problem, one should eliminate the parsetree + generation and conversion to back VLIWRPN, and generate VLIWRPN + directly + +- Expression parsing and conversion: + - Infix to RPN + - infix to Parsetree + - Parsetree to infix + - Parsetree to RPN + +- Symbolic Expression handling. + - Simple operators on expressions + / * - ^ + - Derivation of simple functions (all operators + most functions in math + unit) + - taylor polynomal. + - Precalculate Newton. (almost non-feature :-) + - Primitives for rearranging + - Identifying of terms. + - Simple simplying (2*2*x -> 4*x) + - (de)factoring (*) + - Rearrange so that when converted to RPN, maximal stack depth + for evaluation is 4. This also needs a detector routine + (determine required RPN stack room) + - Operator overloading possible? + +- High speed evaluating. (parse once, evaluate often principle) + - Infinite variables + - Infinite (symbolic) constants. + - Fast (hopefully) + - Structure designed so that a lowlevel (processor dependant) version of + the core evaluating routine is possible. + +TO DO, problems, missing features. +------ + +The biggest feature missing for me (at the moment) is the possibility to use +user defined (other TExpression) functions in my expressions. Only built in +functions are allowed. A procedure variable system as seen in some freeware +examples could be done too. Procedure variables would be faster. However they +would be compiletime (while texpressions can be changed runtime) +(one can workaround this for the evaluator by applying some substitutions) + +Another problem can be seen both as bug and as missing feature: 5+x+7 doesn't +get simplified to x+13 or 13+x. Only 5+7+x gets optimised. This also goes for +the other infix operators. + +- (Symbolic) Integration. At least the parts that *can* be done. Hard, there is + no foolproof approach, and even determining *if* integration is possible is + hard. + User assisted? (e.g. let the user identify the partial integration terms) + Integration further opens the door to Laplace and Fourier. +- Equation support? Or Equation is an equity operator and 2 TExpressions? +- Other mathematical symbolic functions. +- The RPNCalc example is 90% of a simple (symbolic!) RPN calculator. It looks + and feels awfull, but the base functionality is all there, and more important + easy to use and extend. + Maybe for the GUI freaks it is nice to have some GUI RPNcalc widget. Same for + TUI (TV/FV/IDE) +- Polynomal to (Jedi's or other) vector/Matrix type conversion. + Would create entanglement between the units though. Maybe better via + ^array of arbfloat. Could need an import method in target unit somewhere. +- Rearranging of the parsetree so that it requires maximally 4 stack + positions to evaluate the expression (which according to RPN theory + is possible?) + This would allow to run the evaluator purely on the i386 coprocessor + stack, which probably would mean an enormous speed increase. +- As first step: inline math functions in assembler in evaluator + (with conditional) +- Other "smart" rearranging of expressions. Since this is not always possible + without user intervention, this will boil down in creating the support + methods for user assisted symbolic rearraning. +- Clean up, real docs. I waited with real docs because Jedi and FPC use + different document formats and philosophies with it. Personally I prefer the + FPC way of course. A PDF loads as fast as such a html-hlp, and looks ten + times better. AND can generate html if necessary, and get used for real books. +- Complex? +- Predefined symbolic constants? pi, G, h, e(logaritm), e(elementary charge) + (comment: Essentially not necessary anymore.) +- Some more experienced classes programmer must decide which methods to make + virtual, and maybe rework the current inheritance between the classes. +- Support in TEvaluator for constant substitution followed by an + TExpression.Simplify BEFORE vliwarr generation. This to avoid recalculating + things like h/(2*pi) in each evaluation. Will need to copy exprtree for + this? +- Changing parser to allow foreign characters. (anything not in a certain + set is appended to token). Important for people using other codepages. +- Common subexpression elimination? (probably needed in some form for some + rearrangements) +- XML / HTML 4.0 / \Latex formatted output expression :-) +- (Delphi) Controls that allow you to enter mathematical expressions in + numerical fields? +- Graphical viewing of expressions? How to do it graph library (graph, + graphiX,GTK,QT,directx etc etc) independant? + (I have some idea for an algoritm for this from a LaTeX tutorial. Basically + parse the tree and assign all end nodes a size. Parents size can be + calculated from children. Then another pass for rendering to coordinates, + followed by the plot. Will have to be parameterized and with callbacks for + flexibility and system independance) +- Doesn't check for bounderies. (treats e.g. x/x=1 but if x=0 then officially + it isn't defined) I hope to implement a TExpression method for this + someday. (that checks a function for continuety problem spots) + +Class overview. +------------- + +1. TBaseExpression. Very basic support for creating parsetrees. +2. TBaseExprParser(TBaseExpression) Parser class. Most basic conversion + between the three expression types + (infix, RPN, parsetree) +3. TExpression(TBaseExprParser) Main class. An expression and the operations + you can do on them. + Can do some simple evaluation. +4. TEvaluator Plugin evaluation class. Operates + on a parsetree. + + +Evaluating an expression. +------------------------- + +There are two ways of evaluating a simple expression, the method +TExpression.SimplifyConstants and the class TEvaluator. The differences are: + +- TExpression.SimplifyConstants is actually not written for evaluations but + for flexible combining constants after derivation. ( deriv(2x^2) returns + 2*2*x, calling SimplifyConstants changes it to 4*x) + It can be used for simple evaluations too, but it is probably too slow for + repeated iterations. So in case of repeated iterations use TEvaluator. + For one simple evaluation: use simplify, unless you have symbolic + constants. + +- TEvaluator is written for speed. More specifically for high speed *repeated* + evaluations. So setting up the evaluation (creating the TEvaluator class), + is a parsing process and relatively slow. Each iteration after that however + is about as fast as I can imagine without using processor specific lowlevel + features in a HLL. (like internal compilation, FP assembler etc) + +- TEvaluator requires you to subst all values for symbolic constants/variables. + Simplify doesn't allow to subst values for symbolic constants/variables. + +TEvaluator algoritm and internals. +-------------------- + +TEvaluator had two design requirements: +1 High speed for repeated evaluations of the same function with slightly + different values. (read: plot a graph reasonably fast) +2 Must be usable to evaluate TExpressions, but not inherit directly from + TExpression. Since TEvaluate only needs the parsetree from TExpression, + this was easily possible. + +The reason for requirement 1 is that on modern computers the application's +speed won't be affected by a little more parsing overhead for a single +evaluation, while repeated evaluations can still slow down any system. +(people who object to this, please calculate the Wave function for all known +organic compounds:-) +This is implemented by moving as much as possible to the (single) parsing +stage, and keeping the repeated part as lean and fast as possible. + +As an application for the repeated evaluations I mainly had numerical searching +for roots and drawing graphs in mind. + + +The TEvaluator class generates something what I named VLIW-RPN array. +- RPN because the array's elemental operations are equivalent to RPN stack + operations (very comparable to a Hewlett Packard RPN calculator). + This is mainly important because RPN is + - parsed linearly, and + - each operation is very simple, which is both fast. +- VLIW because all operations are of uniform size. This makes sure that + finding the next item is equivalent to one pointer addition instruction. + Also looking ahead and back is easy. Contrary to "real" VLIW, only one + instruction per word exists. +- Array vs linked list or OOP thingy like tlist: Same reasons as VLIW. + +In TEvaluator, symbolic values are subdivided into symbolic constants and +variables. There is no mathematical difference (you define what a constant, +and what is a variable. If you choose "wrong", there is a speed penalty, but +no failure). The difference between constants and variables is that constants +are embedded in the VLIW-RPN array before each evaluation, while variables are +passed as parameters to each evaluation. +Constants can be changed between each evaluation. If a variable only changes +each 50 or more evaluations, make it a constant, and change it after 50 +evaluations. + +Example: + + somefunc(x,y,pi,h)=h/(2*pi)*x^2+5*x+y + +Obviously, it is smart to choose pi and h for constants, since they won't +change each evaluation again. (even smarter would be to evaluate h/2*pi :-) + + +A VLIW record basically can be 4 or 5 things atm: + +- a floating point value. +- an integer value. +- a RPN operator or function (which isn't a difference in RPN), though + this routine makes a difference between one and two parameter + functions/operators for speed. Two types: + - An operator or a function which takes two arguments. (there is no + difference in RPN, an operator is a function and vice versa) + - A function that takes one argument. +- (administrative value, no mathematical meaning) placeholder for a symbolic + constant, to be able to to detect a constant/variable which wasn't given a + value, and raise an exception. + +- Symbolic variables. The variables in the expression are identified by an + integer sequential value (first var=1, second 2 etc). Variable values ARE + looked up each occurance during evaluation, and the only data used from + outside the RPN-VLIW array in a standard evaluation. + +The symbolic constants initially get the "placeholder" value, and when the +user sets the constants via the SetConstant method, it gets a "floating point +value" or "integer value" type. +The class stores all references to all occurances of a constant in the VLIW +array in a tlist. + +The Parser +---------- + +The parser is based on a PD stack RPN based non symbolic constant evaluator, I +found in SWAG. It is practically rewritten, and only the elegant principle +stands. The parser is NOT recursive-descent. It purely parses from left to +right and creates for each token it finds a parsetree record. +Parsetree records that can't be added to the parsetree yet, are pushed on an +argument or separate operator stack. +When an operator is found, then the operator stack is evaluated (popping arguments +of the argument stack) until an operator with higher precendence than the new +one is found. Only then the new operator is pushed on the operator stack. + +I don't know if this is the fastest way, but it is simple, quite elegant and +probably not very bug-sensitive. If somebody has sensible reasons to change it +to recur. descent, please mail me. + +Exceptions +------------- + +I'm still working on the errorhandling (exceptions) of the classes. +Besides some more specific cases, there are two or three basic exception groups: + +- (RPN)Stack under/overflow exceptions. This is not necessarily a fault + in the program, but more likely a fault in the passed (infix) expression. + (specially if they occur in the parser). Smartest is to log the expression + passed to parser somewhere in such cases. + Note: These signal problems with internal RPN stacks, + not the processor stack. Do not mix these up. (by reraising a processor + stack exception). The fault is not necessarily in the program. + +- Internal errors. (IE) These are mosttimes problems in the class, and logging + the "message" gives some information about the location of the problem. + Most IE's are ELSE clauses that shouldn't occur, or datacorruption that + is not acceptable. Probably they only occur if one part of the package + is out of sync with another part, with dangling pointers etc. + E.g. Parser is updated to support function "x", but TEvaluator.Evaluate + wasn't. The CASE node for "x" doesn't exist, so it ends up in the ELSE + clause which triggers the exception. + If you use FPC, and your application is compiled with -gl, you'll probably + get a nice backtrace with sourcename and line of the exception. + +- Division by zero might be the third. This is NOT the processor division + trap by zero, but a RPN stack one. + +Glossary +--------- +Some often used abbreviations and terms: + +FPC : Free Pascal Compiler, the one that I use. Has a 32-bit Delphi mode. + Misses dynamic arrays, interfaces, and nearly the entire VCL in + production version 1.0.x. (Meanwhile, most of the language is + already in 1.1.x development version) + http://www.freepascal.org + +IE : Internal error. Under FPC we try to append an ELSE clause to all + CASE statements, even if the ELSE shouldn't occur. In such CASE + statement the ELSE calls an internal error procedure. + This is also used for other important decisions with situations that + shouldn't occur. (e.g. enumerations with values that aren't defined, + placed there by casts, circular references in linked lists etc.) + I use the same system in these units, but with Exceptions. + See "Exceptions" paragraph for more information about IEs. + A good generic IE routine should be able to obtain the name of the class + in string form. + +Infix: The way poeple usually write down expressions. An operator between its + operands. (5+2 operates on 5 and 2. Could also be written as add(5,2) + or 5 2 + + Has some advantages, but is complicated and slow to parse. However + users(except some Hewlett Packard calculator users like me) seem to + prefer it. + +RPN : Reverse Polish Notation, an alternate notation of expression. + Any operator appears AFTER its operands. + e.g. 1+2+3*sin(4) could be written as 1 2 + 3 4 sin * + + Biggest advantage: Linear parsing from left to right. + Being able to convert a parsetree to RPN is also a good debugging aid. + (since it can be simply printed instead of having to browse a + parsetree runtime) + You can also think of it as replacing the infix operators in an infix + expression by functions (so add(x,y) instead of x+y), and then parse + from end to start (the "Reverse" of RPN) + This also displays another feature of RPN: There is no difference between + operators and functions. There are only functions that take different + amounts of parameters. + +Parsetree: + The way an expression (or even an entire program) is stored + after parsing in compilers. Often, the main type is a variant record + (see treenode, pnode in the source) in which an operator or a function + has pointers to each operand. Parsetrees are often visualised as below. + Each operation, function or constant is a record, the lines made with + slashes are the pointers between the records. (so the top "+" has a + pointer to another "+" record, and one to a "*" record) + + + + + / \ + + \ + / \ \ + 1 2 \ + * + / \ + 3 SIN + \ + 4 + + Fig 1. 1+2+3*sin(4) + + Parsetrees are the easiest way to operate on (transform, derive etc) + expressions. Mainly because you don't have to move much data to move one + part of the expression to another place. Parsetrees are kinda slow though) + (compared to RPN), or VLIWRPN + +VLIW: Very Large Instruction Word. Acronym from the RISC world that simply + boils down to "a linear sequence (array,stream) of uniform sized + "items" is the simplest and fastest way to parse something." + The RISC people are of course talking about instructions to process + and schedule. I'm using the analogy to evaluate an array of + elementary RPN instructions. + This principle is used to get the expression evaluator fast per + iteration. The main difference is that in VLIW processors more than + one operation can be packed in a VLI-Word. (which must be independant + then). This unit doesn't :-) + + \ No newline at end of file diff --git a/packages/symbolic/examples/Makefile b/packages/symbolic/examples/Makefile new file mode 100644 index 0000000000..6325fd896c --- /dev/null +++ b/packages/symbolic/examples/Makefile @@ -0,0 +1,1967 @@ +# +# Don't edit, this file is generated by FPCMake Version 2.0.0 [2008/01/27] +# +default: all +MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded +BSDs = freebsd netbsd openbsd darwin +UNIXs = linux $(BSDs) solaris qnx +LIMIT83fs = go32v2 os2 emx watcom +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)),) +RUNBATCH=$(COMSPEC) /C +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))))) +endif +else +override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH))))) +endif +endif +override FPC:=$(subst $(SRCEXEEXT),,$(FPC)) +override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT) +FOUNDFPC:=$(strip $(wildcard $(FPC))) +ifeq ($(FOUNDFPC),) +FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))) +ifeq ($(FOUNDFPC),) +$(error Compiler $(FPC) not found) +endif +endif +ifndef FPC_COMPILERINFO +FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO) +endif +ifndef FPC_VERSION +FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO)) +endif +export FPC FPC_VERSION FPC_COMPILERINFO +unexport CHECKDEPEND ALLDEPENDENCIES +ifndef CPU_TARGET +ifdef CPU_TARGET_DEFAULT +CPU_TARGET=$(CPU_TARGET_DEFAULT) +endif +endif +ifndef OS_TARGET +ifdef OS_TARGET_DEFAULT +OS_TARGET=$(OS_TARGET_DEFAULT) +endif +endif +ifneq ($(words $(FPC_COMPILERINFO)),5) +FPC_COMPILERINFO+=$(shell $(FPC) -iSP) +FPC_COMPILERINFO+=$(shell $(FPC) -iTP) +FPC_COMPILERINFO+=$(shell $(FPC) -iSO) +FPC_COMPILERINFO+=$(shell $(FPC) -iTO) +endif +ifndef CPU_SOURCE +CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO)) +endif +ifndef CPU_TARGET +CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO)) +endif +ifndef OS_SOURCE +OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO)) +endif +ifndef OS_TARGET +OS_TARGET:=$(word 5,$(FPC_COMPILERINFO)) +endif +FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +TARGETSUFFIX=$(OS_TARGET) +SOURCESUFFIX=$(OS_SOURCE) +else +TARGETSUFFIX=$(FULL_TARGET) +SOURCESUFFIX=$(FULL_SOURCE) +endif +ifneq ($(FULL_TARGET),$(FULL_SOURCE)) +CROSSCOMPILE=1 +endif +ifeq ($(findstring makefile,$(MAKECMDGOALS)),) +ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),) +$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first) +endif +endif +ifneq ($(findstring $(OS_TARGET),$(BSDs)),) +BSDhier=1 +endif +ifeq ($(OS_TARGET),linux) +linuxHier=1 +endif +export OS_TARGET OS_SOURCE CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE +ifdef FPCDIR +override FPCDIR:=$(subst \,/,$(FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +else +override FPCDIR=wrong +endif +ifdef DEFAULT_FPCDIR +ifeq ($(FPCDIR),wrong) +override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR)) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=wrong +endif +endif +endif +ifeq ($(FPCDIR),wrong) +ifdef inUnix +override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION) +ifeq ($(wildcard $(FPCDIR)/units),) +override FPCDIR=/usr/lib/fpc/$(FPC_VERSION) +endif +else +override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH)))))) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(FPCDIR)/.. +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR:=$(BASEDIR) +ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),) +override FPCDIR=c:/pp +endif +endif +endif +endif +endif +ifndef CROSSBINDIR +CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX)) +endif +ifndef BINUTILSPREFIX +ifndef CROSSBINDIR +ifdef CROSSCOMPILE +BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)- +endif +endif +endif +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX)) +ifeq ($(UNITSDIR),) +UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET)) +endif +PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra) +ifeq ($(FULL_TARGET),i386-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-go32v2) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-win32) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-os2) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-freebsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-beos) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-netbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-solaris) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-qnx) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-netware) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-openbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-wdosx) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-darwin) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-emx) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-watcom) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-wince) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),i386-symbian) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-amiga) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-atari) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-palmos) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),m68k-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-macos) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),sparc-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),sparc-solaris) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),sparc-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),x86_64-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),x86_64-win64) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-palmos) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-wince) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-gba) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-nds) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),arm-symbian) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +override TARGET_PROGRAMS+=evaltest rpnthing +endif +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 +ifeq ($(OS_SOURCE),linux) +ifndef GCCLIBDIR +ifeq ($(CPU_TARGET),i386) +ifneq ($(findstring x86_64,$(shell uname -a)),) +ifeq ($(BINUTILSPREFIX),) +GCCLIBDIR:=$(shell dirname `gcc -m32 -print-libgcc-file-name`) +endif +endif +endif +ifeq ($(CPU_TARGET),powerpc64) +ifeq ($(BINUTILSPREFIX),) +GCCLIBDIR:=$(shell dirname `gcc -m64 -print-libgcc-file-name`) +endif +endif +endif +ifndef GCCLIBDIR +CROSSGCC=$(strip $(wildcard $(addsuffix /$(BINUTILSPREFIX)gcc$(SRCEXEEXT),$(SEARCHPATH)))) +ifneq ($(CROSSGCC),) +GCCLIBDIR:=$(shell dirname `$(CROSSGCC) -print-libgcc-file-name`) +endif +endif +ifndef OTHERLIBDIR +OTHERLIBDIR:=$(shell grep -v "^\#" /etc/ld.so.conf | awk '{ ORS=" "; print $1 }') +endif +endif +ifdef inUnix +ifeq ($(OS_SOURCE),netbsd) +OTHERLIBDIR+=/usr/pkg/lib +endif +export GCCLIBDIR OTHERLIB +endif +BATCHEXT=.bat +LOADEREXT=.as +EXEEXT=.exe +PPLEXT=.ppl +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.so +SHAREDLIBPREFIX=libfp +STATICLIBPREFIX=libp +IMPORTLIBPREFIX=libimp +RSTEXT=.rst +ifeq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),go32v1) +STATICLIBPREFIX= +SHORTSUFFIX=v1 +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +OEXT=.obj +ASMEXT=.asm +SHAREDLIBEXT=.dll +SHORTSUFFIX=wat +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +endif +ifeq ($(OS_TARGET),emx) +BATCHEXT=.cmd +AOUTEXT=.out +STATICLIBPREFIX= +SHAREDLIBEXT=.dll +SHORTSUFFIX=emx +ECHO=echo +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),morphos) +EXEEXT= +SHAREDLIBEXT=.library +SHORTSUFFIX=mos +endif +ifeq ($(OS_TARGET),atari) +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nw +endif +ifeq ($(OS_TARGET),netwlibc) +EXEEXT=.nlm +STATICLIBPREFIX= +SHORTSUFFIX=nwl +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +endif +ifeq ($(OS_TARGET),darwin) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=dwn +endif +ifeq ($(OS_TARGET),gba) +EXEEXT=.gba +SHAREDLIBEXT=.so +SHORTSUFFIX=gba +endif +ifeq ($(OS_TARGET),symbian) +SHAREDLIBEXT=.dll +SHORTSUFFIX=symbian +endif +else +ifeq ($(OS_TARGET),go32v1) +PPUEXT=.pp1 +OEXT=.o1 +ASMEXT=.s1 +SMARTEXT=.sl1 +STATICLIBEXT=.a1 +SHAREDLIBEXT=.so1 +STATICLIBPREFIX= +SHORTSUFFIX=v1 +endif +ifeq ($(OS_TARGET),go32v2) +STATICLIBPREFIX= +SHORTSUFFIX=dos +endif +ifeq ($(OS_TARGET),watcom) +STATICLIBPREFIX= +SHORTSUFFIX=wat +endif +ifeq ($(OS_TARGET),linux) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=lnx +endif +ifeq ($(OS_TARGET),freebsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=fbs +endif +ifeq ($(OS_TARGET),netbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=nbs +endif +ifeq ($(OS_TARGET),openbsd) +BATCHEXT=.sh +EXEEXT= +HASSHAREDLIB=1 +SHORTSUFFIX=obs +endif +ifeq ($(OS_TARGET),win32) +PPUEXT=.ppw +OEXT=.ow +ASMEXT=.sw +SMARTEXT=.slw +STATICLIBEXT=.aw +SHAREDLIBEXT=.dll +SHORTSUFFIX=w32 +endif +ifeq ($(OS_TARGET),os2) +BATCHEXT=.cmd +PPUEXT=.ppo +ASMEXT=.so2 +OEXT=.oo2 +AOUTEXT=.out +SMARTEXT=.sl2 +STATICLIBPREFIX= +STATICLIBEXT=.ao2 +SHAREDLIBEXT=.dll +SHORTSUFFIX=os2 +ECHO=echo +endif +ifeq ($(OS_TARGET),amiga) +EXEEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.library +SHORTSUFFIX=amg +endif +ifeq ($(OS_TARGET),atari) +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT=.ttp +SHORTSUFFIX=ata +endif +ifeq ($(OS_TARGET),beos) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=be +endif +ifeq ($(OS_TARGET),solaris) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=sun +endif +ifeq ($(OS_TARGET),qnx) +BATCHEXT=.sh +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +SHORTSUFFIX=qnx +endif +ifeq ($(OS_TARGET),netware) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nw +endif +ifeq ($(OS_TARGET),netwlibc) +STATICLIBPREFIX= +PPUEXT=.ppu +OEXT=.o +ASMEXT=.s +SMARTEXT=.sl +STATICLIBEXT=.a +SHAREDLIBEXT=.nlm +EXEEXT=.nlm +SHORTSUFFIX=nwl +endif +ifeq ($(OS_TARGET),macos) +BATCHEXT= +PPUEXT=.ppu +ASMEXT=.s +OEXT=.o +SMARTEXT=.sl +STATICLIBEXT=.a +EXEEXT= +DEBUGSYMEXT=.xcoff +SHORTSUFFIX=mac +endif +endif +ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),) +FPCMADE=fpcmade.$(SHORTSUFFIX) +ZIPSUFFIX=$(SHORTSUFFIX) +ZIPCROSSPREFIX= +ZIPSOURCESUFFIX=src +ZIPEXAMPLESUFFIX=exm +else +FPCMADE=fpcmade.$(TARGETSUFFIX) +ZIPSOURCESUFFIX=.source +ZIPEXAMPLESUFFIX=.examples +ifdef CROSSCOMPILE +ZIPSUFFIX=.$(SOURCESUFFIX) +ZIPCROSSPREFIX=$(TARGETSUFFIX)- +else +ZIPSUFFIX=.$(TARGETSUFFIX) +ZIPCROSSPREFIX= +endif +endif +ifndef ECHO +ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ECHO),) +ECHO= __missing_command_ECHO +else +ECHO:=$(firstword $(ECHO)) +endif +else +ECHO:=$(firstword $(ECHO)) +endif +endif +export ECHO +ifndef DATE +DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(DATE),) +DATE= __missing_command_DATE +else +DATE:=$(firstword $(DATE)) +endif +else +DATE:=$(firstword $(DATE)) +endif +endif +export DATE +ifndef GINSTALL +GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(GINSTALL),) +GINSTALL= __missing_command_GINSTALL +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +else +GINSTALL:=$(firstword $(GINSTALL)) +endif +endif +export GINSTALL +ifndef CPPROG +CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(CPPROG),) +CPPROG= __missing_command_CPPROG +else +CPPROG:=$(firstword $(CPPROG)) +endif +endif +export CPPROG +ifndef RMPROG +RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(RMPROG),) +RMPROG= __missing_command_RMPROG +else +RMPROG:=$(firstword $(RMPROG)) +endif +endif +export RMPROG +ifndef MVPROG +MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MVPROG),) +MVPROG= __missing_command_MVPROG +else +MVPROG:=$(firstword $(MVPROG)) +endif +endif +export MVPROG +ifndef MKDIRPROG +MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(MKDIRPROG),) +MKDIRPROG= __missing_command_MKDIRPROG +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +else +MKDIRPROG:=$(firstword $(MKDIRPROG)) +endif +endif +export MKDIRPROG +ifndef ECHOREDIR +ifndef inUnix +ECHOREDIR=echo +else +ECHOREDIR=$(ECHO) +endif +endif +ifndef COPY +COPY:=$(CPPROG) -fp +endif +ifndef COPYTREE +COPYTREE:=$(CPPROG) -Rfp +endif +ifndef MKDIRTREE +MKDIRTREE:=$(MKDIRPROG) -p +endif +ifndef MOVE +MOVE:=$(MVPROG) -f +endif +ifndef DEL +DEL:=$(RMPROG) -f +endif +ifndef DELTREE +DELTREE:=$(RMPROG) -rf +endif +ifndef INSTALL +ifdef inUnix +INSTALL:=$(GINSTALL) -c -m 644 +else +INSTALL:=$(COPY) +endif +endif +ifndef INSTALLEXE +ifdef inUnix +INSTALLEXE:=$(GINSTALL) -c -m 755 +else +INSTALLEXE:=$(COPY) +endif +endif +ifndef MKDIR +MKDIR:=$(GINSTALL) -m 755 -d +endif +export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR +ifndef PPUMOVE +PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(PPUMOVE),) +PPUMOVE= __missing_command_PPUMOVE +else +PPUMOVE:=$(firstword $(PPUMOVE)) +endif +endif +export PPUMOVE +ifndef FPCMAKE +FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(FPCMAKE),) +FPCMAKE= __missing_command_FPCMAKE +else +FPCMAKE:=$(firstword $(FPCMAKE)) +endif +endif +export FPCMAKE +ifndef ZIPPROG +ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(ZIPPROG),) +ZIPPROG= __missing_command_ZIPPROG +else +ZIPPROG:=$(firstword $(ZIPPROG)) +endif +endif +export ZIPPROG +ifndef TARPROG +TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(TARPROG),) +TARPROG= __missing_command_TARPROG +else +TARPROG:=$(firstword $(TARPROG)) +endif +else +TARPROG:=$(firstword $(TARPROG)) +endif +endif +export TARPROG +ASNAME=$(BINUTILSPREFIX)as +LDNAME=$(BINUTILSPREFIX)ld +ARNAME=$(BINUTILSPREFIX)ar +RCNAME=$(BINUTILSPREFIX)rc +ifneq ($(findstring 1.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),win32) +ifeq ($(CROSSBINDIR),) +ASNAME=asw +LDNAME=ldw +ARNAME=arw +endif +endif +endif +ifndef ASPROG +ifdef CROSSBINDIR +ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT) +else +ASPROG=$(ASNAME) +endif +endif +ifndef LDPROG +ifdef CROSSBINDIR +LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT) +else +LDPROG=$(LDNAME) +endif +endif +ifndef RCPROG +ifdef CROSSBINDIR +RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT) +else +RCPROG=$(RCNAME) +endif +endif +ifndef ARPROG +ifdef CROSSBINDIR +ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT) +else +ARPROG=$(ARNAME) +endif +endif +AS=$(ASPROG) +LD=$(LDPROG) +RC=$(RCPROG) +AR=$(ARPROG) +PPAS=ppas$(SRCBATCHEXT) +ifdef inUnix +LDCONFIG=ldconfig +else +LDCONFIG= +endif +ifdef DATE +DATESTR:=$(shell $(DATE) +%Y%m%d) +else +DATESTR= +endif +ifndef UPXPROG +ifeq ($(OS_TARGET),go32v2) +UPXPROG:=1 +endif +ifeq ($(OS_TARGET),win32) +UPXPROG:=1 +endif +ifdef UPXPROG +UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH)))) +ifeq ($(UPXPROG),) +UPXPROG= +else +UPXPROG:=$(firstword $(UPXPROG)) +endif +else +UPXPROG= +endif +endif +export UPXPROG +ZIPOPT=-9 +ZIPEXT=.zip +ifeq ($(USETAR),bz2) +TAROPT=vj +TAREXT=.tar.bz2 +else +TAROPT=vz +TAREXT=.tar.gz +endif +override REQUIRE_PACKAGES=rtl symbolic +ifeq ($(FULL_TARGET),i386-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-go32v2) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-win32) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-os2) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-freebsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-beos) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-netbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-solaris) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-qnx) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-netware) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-openbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-wdosx) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-darwin) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-emx) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-watcom) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-netwlibc) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-wince) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),i386-symbian) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-freebsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-netbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-amiga) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-atari) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-openbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-palmos) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),m68k-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-netbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-amiga) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-macos) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-darwin) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-morphos) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),sparc-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),sparc-netbsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),sparc-solaris) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),sparc-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),x86_64-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),x86_64-freebsd) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),x86_64-darwin) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),x86_64-win64) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),x86_64-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-palmos) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-wince) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-gba) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-nds) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),arm-symbian) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc64-linux) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc64-darwin) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifeq ($(FULL_TARGET),powerpc64-embedded) +REQUIRE_PACKAGES_RTL=1 +REQUIRE_PACKAGES_SYMBOLIC=1 +endif +ifdef REQUIRE_PACKAGES_RTL +PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR)))))) +ifneq ($(PACKAGEDIR_RTL),) +ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),) +UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX) +else +UNITDIR_RTL=$(PACKAGEDIR_RTL) +endif +ifdef CHECKDEPEND +$(PACKAGEDIR_RTL)/$(FPCMADE): + $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE) +override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE) +endif +else +PACKAGEDIR_RTL= +UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR))))) +ifneq ($(UNITDIR_RTL),) +UNITDIR_RTL:=$(firstword $(UNITDIR_RTL)) +else +UNITDIR_RTL= +endif +endif +ifdef UNITDIR_RTL +override COMPILER_UNITDIR+=$(UNITDIR_RTL) +endif +endif +ifdef REQUIRE_PACKAGES_SYMBOLIC +PACKAGEDIR_SYMBOLIC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /symbolic/Makefile.fpc,$(PACKAGESDIR)))))) +ifneq ($(PACKAGEDIR_SYMBOLIC),) +ifneq ($(wildcard $(PACKAGEDIR_SYMBOLIC)/units/$(TARGETSUFFIX)),) +UNITDIR_SYMBOLIC=$(PACKAGEDIR_SYMBOLIC)/units/$(TARGETSUFFIX) +else +UNITDIR_SYMBOLIC=$(PACKAGEDIR_SYMBOLIC) +endif +ifdef CHECKDEPEND +$(PACKAGEDIR_SYMBOLIC)/$(FPCMADE): + $(MAKE) -C $(PACKAGEDIR_SYMBOLIC) $(FPCMADE) +override ALLDEPENDENCIES+=$(PACKAGEDIR_SYMBOLIC)/$(FPCMADE) +endif +else +PACKAGEDIR_SYMBOLIC= +UNITDIR_SYMBOLIC:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /symbolic/Package.fpc,$(UNITSDIR))))) +ifneq ($(UNITDIR_SYMBOLIC),) +UNITDIR_SYMBOLIC:=$(firstword $(UNITDIR_SYMBOLIC)) +else +UNITDIR_SYMBOLIC= +endif +endif +ifdef UNITDIR_SYMBOLIC +override COMPILER_UNITDIR+=$(UNITDIR_SYMBOLIC) +endif +endif +ifndef NOCPUDEF +override FPCOPTDEF=$(CPU_TARGET) +endif +ifneq ($(OS_TARGET),$(OS_SOURCE)) +override FPCOPT+=-T$(OS_TARGET) +endif +ifneq ($(CPU_TARGET),$(CPU_SOURCE)) +override FPCOPT+=-P$(CPU_TARGET) +endif +ifeq ($(OS_SOURCE),openbsd) +override FPCOPT+=-FD$(NEW_BINUTILS_PATH) +endif +ifndef CROSSBOOTSTRAP +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-XP$(BINUTILSPREFIX) +endif +ifneq ($(BINUTILSPREFIX),) +override FPCOPT+=-Xr$(RLINKPATH) +endif +endif +ifdef UNITDIR +override FPCOPT+=$(addprefix -Fu,$(UNITDIR)) +endif +ifdef LIBDIR +override FPCOPT+=$(addprefix -Fl,$(LIBDIR)) +endif +ifdef OBJDIR +override FPCOPT+=$(addprefix -Fo,$(OBJDIR)) +endif +ifdef INCDIR +override FPCOPT+=$(addprefix -Fi,$(INCDIR)) +endif +ifdef LINKSMART +override FPCOPT+=-XX +endif +ifdef CREATESMART +override FPCOPT+=-CX +endif +ifdef DEBUG +override FPCOPT+=-gl +override FPCOPTDEF+=DEBUG +endif +ifdef RELEASE +ifneq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(CPU_TARGET),i386) +FPCCPUOPT:=-OG2p3 +endif +ifeq ($(CPU_TARGET),powerpc) +FPCCPUOPT:=-O1r +endif +else +FPCCPUOPT:=-O2 +endif +override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n +override FPCOPTDEF+=RELEASE +endif +ifdef STRIP +override FPCOPT+=-Xs +endif +ifdef OPTIMIZE +override FPCOPT+=-O2 +endif +ifdef VERBOSE +override FPCOPT+=-vwni +endif +ifdef COMPILER_OPTIONS +override FPCOPT+=$(COMPILER_OPTIONS) +endif +ifdef COMPILER_UNITDIR +override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR)) +endif +ifdef COMPILER_LIBRARYDIR +override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR)) +endif +ifdef COMPILER_OBJECTDIR +override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR)) +endif +ifdef COMPILER_INCLUDEDIR +override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR)) +endif +ifdef CROSSBINDIR +override FPCOPT+=-FD$(CROSSBINDIR) +endif +ifdef COMPILER_TARGETDIR +override FPCOPT+=-FE$(COMPILER_TARGETDIR) +ifeq ($(COMPILER_TARGETDIR),.) +override TARGETDIRPREFIX= +else +override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/ +endif +endif +ifdef COMPILER_UNITTARGETDIR +override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR) +ifeq ($(COMPILER_UNITTARGETDIR),.) +override UNITTARGETDIRPREFIX= +else +override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/ +endif +else +ifdef COMPILER_TARGETDIR +override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR) +override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX) +endif +endif +ifdef CREATESHARED +override FPCOPT+=-Cg +ifeq ($(CPU_TARGET),i386) +override FPCOPT+=-Aas +endif +endif +ifeq ($(findstring 2.0.,$(FPC_VERSION)),) +ifeq ($(OS_TARGET),linux) +ifeq ($(CPU_TARGET),x86_64) +override FPCOPT+=-Cg +endif +endif +endif +ifdef LINKSHARED +endif +ifdef GCCLIBDIR +override FPCOPT+=-Fl$(GCCLIBDIR) +endif +ifdef OTHERLIBDIR +override FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR)) +endif +ifdef OPT +override FPCOPT+=$(OPT) +endif +ifdef FPCOPTDEF +override FPCOPT+=$(addprefix -d,$(FPCOPTDEF)) +endif +ifdef CFGFILE +override FPCOPT+=@$(CFGFILE) +endif +ifdef USEENV +override FPCEXTCMD:=$(FPCOPT) +override FPCOPT:=!FPCEXTCMD +export FPCEXTCMD +endif +override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET) +override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE) +ifneq ($(AFULL_TARGET),$(AFULL_SOURCE)) +override ACROSSCOMPILE=1 +endif +ifdef ACROSSCOMPILE +override FPCOPT+=$(CROSSOPT) +endif +override COMPILER:=$(FPC) $(FPCOPT) +ifeq (,$(findstring -s ,$(COMPILER))) +EXECPPAS= +else +ifeq ($(FULL_SOURCE),$(FULL_TARGET)) +ifdef RUNBATCH +EXECPPAS:=@$(RUNBATCH) $(PPAS) +else +EXECPPAS:=@$(PPAS) +endif +endif +endif +.PHONY: fpc_exes +ifndef CROSSINSTALL +ifneq ($(TARGET_PROGRAMS),) +override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS)) +override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS))) $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS))) +override ALLTARGET+=fpc_exes +override INSTALLEXEFILES+=$(EXEFILES) +override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES) +ifeq ($(OS_TARGET),os2) +override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS)) +endif +ifeq ($(OS_TARGET),emx) +override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS)) +endif +endif +endif +fpc_exes: $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(EXEFILES) +ifdef TARGET_RSTS +override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS)) +override CLEANRSTFILES+=$(RSTFILES) +endif +.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared +$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET) + @$(ECHOREDIR) Compiled > $(FPCMADE) +fpc_all: $(FPCMADE) +fpc_smart: + $(MAKE) all LINKSMART=1 CREATESMART=1 +fpc_debug: + $(MAKE) all DEBUG=1 +fpc_release: + $(MAKE) all RELEASE=1 +.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res +$(COMPILER_UNITTARGETDIR): + $(MKDIRTREE) $(COMPILER_UNITTARGETDIR) +$(COMPILER_TARGETDIR): + $(MKDIRTREE) $(COMPILER_TARGETDIR) +%$(PPUEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(PPUEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pp + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.pas + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.lpr + $(COMPILER) $< + $(EXECPPAS) +%$(EXEEXT): %.dpr + $(COMPILER) $< + $(EXECPPAS) +%.res: %.rc + windres -i $< -o $@ +vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR) +vpath %.inc $(COMPILER_INCLUDEDIR) +vpath %$(OEXT) $(COMPILER_UNITTARGETDIR) +vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR) +.PHONY: fpc_shared +override INSTALLTARGET+=fpc_shared_install +ifndef SHARED_LIBVERSION +SHARED_LIBVERSION=$(FPC_VERSION) +endif +ifndef SHARED_LIBNAME +SHARED_LIBNAME=$(PACKAGE_NAME) +endif +ifndef SHARED_FULLNAME +SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT) +endif +ifndef SHARED_LIBUNITS +SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS) +override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS)) +endif +fpc_shared: +ifdef HASSHAREDLIB + $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1 +ifneq ($(SHARED_BUILD),n) + $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR) +endif +else + @$(ECHO) Shared Libraries not supported +endif +fpc_shared_install: +ifneq ($(SHARED_BUILD),n) +ifneq ($(SHARED_LIBUNITS),) +ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),) + $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR) +endif +endif +endif +.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall +ifdef INSTALL_UNITS +override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS)) +endif +ifdef INSTALL_BUILDUNIT +override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES)) +endif +ifdef INSTALLPPUFILES +override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) +ifneq ($(UNITTARGETDIRPREFIX),) +override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES))) +override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES)))) +endif +override INSTALL_CREATEPACKAGEFPC=1 +endif +ifdef INSTALLEXEFILES +ifneq ($(TARGETDIRPREFIX),) +override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES))) +endif +endif +fpc_install: all $(INSTALLTARGET) +ifdef INSTALLEXEFILES + $(MKDIR) $(INSTALL_BINDIR) +ifdef UPXPROG + -$(UPXPROG) $(INSTALLEXEFILES) +endif + $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR) +endif +ifdef INSTALL_CREATEPACKAGEFPC +ifdef FPCMAKE +ifdef PACKAGE_VERSION +ifneq ($(wildcard Makefile.fpc),) + $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) Package.fpc $(INSTALL_UNITDIR) +endif +endif +endif +endif +ifdef INSTALLPPUFILES + $(MKDIR) $(INSTALL_UNITDIR) + $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR) +ifneq ($(INSTALLPPULINKFILES),) + $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR) +endif +ifneq ($(wildcard $(LIB_FULLNAME)),) + $(MKDIR) $(INSTALL_LIBDIR) + $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR) +ifdef inUnix + ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME) +endif +endif +endif +ifdef INSTALL_FILES + $(MKDIR) $(INSTALL_DATADIR) + $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR) +endif +fpc_sourceinstall: distclean + $(MKDIR) $(INSTALL_SOURCEDIR) + $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR) +fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS)) +ifdef HASEXAMPLES + $(MKDIR) $(INSTALL_EXAMPLEDIR) +endif +ifdef EXAMPLESOURCEFILES + $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR) +endif +ifdef TARGET_EXAMPLEDIRS + $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR) +endif +.PHONY: fpc_clean fpc_cleanall fpc_distclean +ifdef EXEFILES +override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES)) +endif +ifdef CLEAN_UNITS +override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS)) +endif +ifdef CLEANPPUFILES +override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) +ifdef DEBUGSYMEXT +override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES)) +endif +override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES)) +override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES))) +endif +fpc_clean: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +ifdef CLEAN_FILES + -$(DEL) $(CLEAN_FILES) +endif +ifdef LIB_NAME + -$(DEL) $(LIB_NAME) $(LIB_FULLNAME) +endif + -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT) +fpc_cleanall: $(CLEANTARGET) +ifdef CLEANEXEFILES + -$(DEL) $(CLEANEXEFILES) +endif +ifdef COMPILER_UNITTARGETDIR +ifdef CLEANPPUFILES + -$(DEL) $(CLEANPPUFILES) +endif +ifneq ($(CLEANPPULINKFILES),) + -$(DEL) $(CLEANPPULINKFILES) +endif +ifdef CLEANRSTFILES + -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES)) +endif +endif + -$(DELTREE) units + -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT) +ifneq ($(PPUEXT),.ppu) + -$(DEL) *.o *.ppu *.a +endif + -$(DELTREE) *$(SMARTEXT) + -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE) + -$(DEL) *_ppas$(BATCHEXT) +ifdef AOUTEXT + -$(DEL) *$(AOUTEXT) +endif +ifdef DEBUGSYMEXT + -$(DEL) *$(DEBUGSYMEXT) +endif +fpc_distclean: cleanall +.PHONY: fpc_baseinfo +override INFORULES+=fpc_baseinfo +fpc_baseinfo: + @$(ECHO) + @$(ECHO) == Package info == + @$(ECHO) Package Name..... $(PACKAGE_NAME) + @$(ECHO) Package Version.. $(PACKAGE_VERSION) + @$(ECHO) + @$(ECHO) == Configuration info == + @$(ECHO) + @$(ECHO) FPC.......... $(FPC) + @$(ECHO) FPC Version.. $(FPC_VERSION) + @$(ECHO) Source CPU... $(CPU_SOURCE) + @$(ECHO) Target CPU... $(CPU_TARGET) + @$(ECHO) Source OS.... $(OS_SOURCE) + @$(ECHO) Target OS.... $(OS_TARGET) + @$(ECHO) Full Source.. $(FULL_SOURCE) + @$(ECHO) Full Target.. $(FULL_TARGET) + @$(ECHO) SourceSuffix. $(SOURCESUFFIX) + @$(ECHO) TargetSuffix. $(TARGETSUFFIX) + @$(ECHO) + @$(ECHO) == Directory info == + @$(ECHO) + @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES) + @$(ECHO) + @$(ECHO) Basedir......... $(BASEDIR) + @$(ECHO) FPCDir.......... $(FPCDIR) + @$(ECHO) CrossBinDir..... $(CROSSBINDIR) + @$(ECHO) UnitsDir........ $(UNITSDIR) + @$(ECHO) PackagesDir..... $(PACKAGESDIR) + @$(ECHO) + @$(ECHO) GCC library..... $(GCCLIBDIR) + @$(ECHO) Other library... $(OTHERLIBDIR) + @$(ECHO) + @$(ECHO) == Tools info == + @$(ECHO) + @$(ECHO) As........ $(AS) + @$(ECHO) Ld........ $(LD) + @$(ECHO) Ar........ $(AR) + @$(ECHO) Rc........ $(RC) + @$(ECHO) + @$(ECHO) Mv........ $(MVPROG) + @$(ECHO) Cp........ $(CPPROG) + @$(ECHO) Rm........ $(RMPROG) + @$(ECHO) GInstall.. $(GINSTALL) + @$(ECHO) Echo...... $(ECHO) + @$(ECHO) Shell..... $(SHELL) + @$(ECHO) Date...... $(DATE) + @$(ECHO) FPCMake... $(FPCMAKE) + @$(ECHO) PPUMove... $(PPUMOVE) + @$(ECHO) Upx....... $(UPXPROG) + @$(ECHO) Zip....... $(ZIPPROG) + @$(ECHO) + @$(ECHO) == Object info == + @$(ECHO) + @$(ECHO) Target Loaders........ $(TARGET_LOADERS) + @$(ECHO) Target Units.......... $(TARGET_UNITS) + @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS) + @$(ECHO) Target Programs....... $(TARGET_PROGRAMS) + @$(ECHO) Target Dirs........... $(TARGET_DIRS) + @$(ECHO) Target Examples....... $(TARGET_EXAMPLES) + @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS) + @$(ECHO) + @$(ECHO) Clean Units......... $(CLEAN_UNITS) + @$(ECHO) Clean Files......... $(CLEAN_FILES) + @$(ECHO) + @$(ECHO) Install Units....... $(INSTALL_UNITS) + @$(ECHO) Install Files....... $(INSTALL_FILES) + @$(ECHO) + @$(ECHO) == Install info == + @$(ECHO) + @$(ECHO) DateStr.............. $(DATESTR) + @$(ECHO) ZipName.............. $(ZIPNAME) + @$(ECHO) ZipPrefix............ $(ZIPPREFIX) + @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX) + @$(ECHO) ZipSuffix............ $(ZIPSUFFIX) + @$(ECHO) FullZipName.......... $(FULLZIPNAME) + @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE) + @$(ECHO) + @$(ECHO) Install base dir..... $(INSTALL_BASEDIR) + @$(ECHO) Install binary dir... $(INSTALL_BINDIR) + @$(ECHO) Install library dir.. $(INSTALL_LIBDIR) + @$(ECHO) Install units dir.... $(INSTALL_UNITDIR) + @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR) + @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR) + @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR) + @$(ECHO) Install data dir..... $(INSTALL_DATADIR) + @$(ECHO) + @$(ECHO) Dist destination dir. $(DIST_DESTDIR) + @$(ECHO) Dist zip name........ $(DIST_ZIPNAME) + @$(ECHO) +.PHONY: fpc_info +fpc_info: $(INFORULES) +.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \ + fpc_makefile_dirs +fpc_makefile: + $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc +fpc_makefile_sub1: +ifdef TARGET_DIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS)) +endif +ifdef TARGET_EXAMPLEDIRS + $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS)) +endif +fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS)) +fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2 +fpc_makefiles: fpc_makefile fpc_makefile_dirs +all: fpc_all +debug: fpc_debug +smart: fpc_smart +release: fpc_release +units: fpc_units +examples: +shared: fpc_shared +install: fpc_install +sourceinstall: fpc_sourceinstall +exampleinstall: fpc_exampleinstall +distinstall: +zipinstall: +zipsourceinstall: +zipexampleinstall: +zipdistinstall: +clean: fpc_clean +distclean: fpc_distclean +cleanall: fpc_cleanall +info: fpc_info +makefiles: fpc_makefiles +.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles +ifneq ($(wildcard fpcmake.loc),) +include fpcmake.loc +endif +.NOTPARALLEL: diff --git a/packages/symbolic/examples/Makefile.fpc b/packages/symbolic/examples/Makefile.fpc new file mode 100644 index 0000000000..7921740eca --- /dev/null +++ b/packages/symbolic/examples/Makefile.fpc @@ -0,0 +1,18 @@ +# +# Makefile.fpc for apache2.0 units example +# + +[target] +programs=evaltest rpnthing + +[require] +packages=symbolic + +[install] +fpcpackage=y + +[default] +fpcdir=../../.. + +[rules] +.NOTPARALLEL: diff --git a/packages/symbolic/examples/evaltest.pas b/packages/symbolic/examples/evaltest.pas new file mode 100644 index 0000000000..eeb16ca0c1 --- /dev/null +++ b/packages/symbolic/examples/evaltest.pas @@ -0,0 +1,100 @@ +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort (marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Most basic test for TEvaluator class. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + ********************************************************************** +} + +program EvalTest; + +{$AppType Console} + +Uses Classes,Symbolic, SysUtils; + +VAR Expr : TExpression; + SymVars : TStringList; + I : Longint; + VarName : TStringList; + Eval : TEvaluator; + Vars : Array[0..1] OF ArbFloat; + +begin + {Lets create in a nice equation. Totally nonsense. Don't try to + make sense of it} + + Expr:=TExpression.Create('pi*sin(x-x0)+x^(t-1)+exp(x*t)+5'); + Writeln('Expression after parsing :',Expr.InfixExpr); + + {Hmm. But the user could have typed that in. Let's check if he used + symbolic values} + + SymVars:=Expr.SymbolicValueNames; + + If SymVars.Count>0 Then + For I:=0 TO SymVars.Count-1 DO + Writeln(I:5,' ',Symvars[I]); + + {Assume the user selected X and T from above stringlist as our variables} + + VarName:=TStringList.Create; + VarName.Add('X'); + VarName.Add('T'); + + {Create the Evaluator Object} + + Eval:=TEvaluator.Create(VarName,Expr); + + {My HP48g provided this value for PI:} + + IF Symvars.IndexOf('PI')<>-1 THEN {If PI exists, then assume it is the + circle radius vs diameter ratio} + Eval.SetConstant('PI',3.14159265359); + + IF Symvars.IndexOf('X0')<>-1 THEN {Set X0 to Douglas' number} + Eval.SetConstant('X0',42); + + {All this above looks slow isn't? It probably even is. Unit symbolic has + evaluations as plus, not as target. The evaluation is built for + fast repeated evaluations, not just one. + However the Evaluate method is hopefully reasonably fast. + Under FPC TEvaluator.Evaluate is about 600-700 assembler instructions, + without operation on pointer trees and without recursion. + If your compiler (and hopefully FPC too) can inline the math unit functions, + the speed gain could be dramatic.} + + Writeln('Stackdepth needed for evaluation: ',eval.EvalDepth); + + FOR I:=1 TO 50 DO + begin + Vars[0]:=1/I *1.1; + Vars[1]:=1/I*2; + Writeln(VarName.Strings[0] + '=' + FloatToStrF(Vars[0], ffFixed, 4, 4) + ' ' + + VarName.Strings[1] + '=' + FloatToStrF(Vars[1], ffFixed, 4, 4) + ' = ' + + FloatToStrF(Eval.Evaluate(Vars), ffFixed, 4, 4)); + end; + + Eval.Free; + Expr.Free; + SymVars.Free; +// VarName.Free; {Is freed by TEvaluator.Destroy. Should TEvaluator copy it?} + + Readln; +end. + + +{ + $Log$ + Revision 1.1 2002/12/15 21:01:22 marco + Initial revision + +} diff --git a/packages/symbolic/examples/rpnthing.pas b/packages/symbolic/examples/rpnthing.pas new file mode 100644 index 0000000000..7da2f5b0db --- /dev/null +++ b/packages/symbolic/examples/rpnthing.pas @@ -0,0 +1,179 @@ +program RPNThing; +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Much too simplistic program to test some basic features of Symbolic unit. + It is the very rough skeleton of a symbolic RPN calculator like a HP48. + Since there are no exception conditions in the parser or evaluator, + please enter valid expressions. + Don't use 5E6 notation, it is not implemented yet. You can enter + symbolic expressions using x, integer constants and half the math + unit's function. + + 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. +} + +{$ifdef FPC} + {$Mode ObjFpc} +{$endif} + +Uses Symbolic,Crt; + +function GetKey:char; + +begin + repeat + while keypressed DO ; + result:=ReadKey; + if result=#0 then {Make sure control codes are skipped apropiately} + begin + result:=readKey; + result:=#0; + end; + until result IN ['X','x','O','o','q','Q',' ','+','-','*','/','^','e','E','d','D','T','t']; +end; + + +VAR Stack : array[0..100] of TExpression; + I,StackPtr : Integer; + InputC : Char; + S : String; + Flag : Boolean; + +Procedure Redraw; + +var I : Integer; + +begin + for I:=1 to 20 DO + begin + GotoXY(1,I); + Write(' ':79); + GotoXY(1,I); + IF (StackPtr>(20-I)) then + begin + IF NOT Assigned(stack[20-I]) then + begin + gotoXY(1,1); write(' ':50); + gotoxy(1,1); writeln(I,' ',20-I); + Writeln(stackptr); + HALT; + end; + Writeln(stack[StackPtr-(21-I)].InfixExpr); + end + else + write('-'); + end; + GotoXY(1,21); + Write(' ':80); +end; + +begin + Writeln(' + - / * ^ : perform the RPN operation'); + Writeln(' [space],'#39' : get a "prompt" to input a number or infix expression'); + Writeln(' E,e : Try to simplify/evaluate the expression. '); + Writeln(' For now this is restricted to constant values only'); + Writeln(' D,d : Drop 1 value from the stack'); + Writeln(' Q,q : By pressing this key you agree this program is great'); + Writeln(' O,o : Derive the expression with respect to X'); + Writeln(' T,t : Taylor polynomal. Also with respect to X, and to 2nd '); + writeln(' stacklevel degree'); + Writeln; + Writeln('Press enter to start calculating'); + ReadLn; + ClrScr; + StackPtr:=0; + repeat + InputC:=GetKey; + Case InputC OF + '+','-','*','/','^' : if stackPtr>1 then + begin + Dec(StackPtr); + case InputC of {Double case is ugly but short} + '+' : Stack[StackPtr-1].AddTo(Stack[StackPtr]); + '-' : Stack[StackPtr-1].SubFrom(Stack[StackPtr]); + '*' : Stack[StackPtr-1].Times(Stack[StackPtr]); + '/' : Stack[StackPtr-1].DivBy(Stack[StackPtr]); + '^' : Stack[StackPtr-1].RaiseTo(Stack[StackPtr]); + end; + Stack[StackPtr].free; + Redraw; + end; + 'E','e' : If Stackptr>0 then + begin + Stack[StackPtr-1].SimplifyConstants; + Redraw; + end; + 'T','t' : If StackPtr>1 then {Stackptr-1=function. Stackptr-2=degree + x is assumed, and x0 is substed} + begin + Flag:=True; + Try + i:=Stack[StackPtr-2].ValueAsInteger; + except + on ENotInt do + begin + GotoXY(1,1); + WritelN('This constant doesn''t evaluate to an integer'); + Flag:=False; + end; + end; + If I<0 then + begin + GotoXY(1,1); + WritelN('I never heard of negative terms in a Taylor polynomal'); + end + else + If Flag then + begin + Stack[StackPtr-2].Free; + Stack[StackPtr-2]:=Stack[StackPtr-1]; + Stack[StackPtr-1]:=Stack[StackPtr-2].Taylor(I,'X','0.0'); + Redraw; + end; + end; + 'O','o' : if StackPtr>0 then + begin + Stack[StackPtr]:=Stack[StackPtr-1].Derive('X'); + Inc(StackPtr); + Redraw; + end; + 'D','d' : If StackPtr>0 Then + begin + Stack[StackPtr-1].free; + Dec(StackPtr); + Redraw; + end; + ' ',#39 : If Stackptr<100 then + begin + GotoXY(1,1); Writeln(' ':60); + gotoxy(1,1); write('Enter expr. : '); readln(s); + s:=upcase(S); + stack[StackPtr]:=TExpression.Create(S); + Stack[StackPtr].Simplificationlevel:=2; {Don't add reals to integer. Only evaluates + (integer op integer) and (real op real) and + function(real)} + Inc(Stackptr); + Redraw; + end; + 'X','x' : begin + ClrScr; + Writeln(stdout,stack[StackPtr-1].InfixExpr); + Writeln; + Writeln(stdout,stack[StackPtr-1].RPNExpr); + inputC:='q'; + end; + end; + until (InputC IN ['q','Q']); + +If StackPtr>0 THEN + For I:=0 To StackPtr-1 Do + Stack[I].Free; +end. diff --git a/packages/symbolic/src/exprstrs.inc b/packages/symbolic/src/exprstrs.inc new file mode 100644 index 0000000000..353619d217 --- /dev/null +++ b/packages/symbolic/src/exprstrs.inc @@ -0,0 +1,40 @@ +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Some resourcestrings. + + 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. + + **********************************************************************} + +resourcestring + SEvalIE ='TEvaluator: Internal Error: '; + SEvalStackDepthExceeded ='TEvaluator: Stack depth Evaluate exceeded'; + SEvalBadNumberOfVars ='TEvaluator: Invalid number of variables'; + SParsIE ='TBaseExprParser: Internal Error:'; + SParseRPNOverflow ='TBaseExprParser: RPN stack overflow'; + SParseRPNUnderflow ='TBaseExprParser: RPN stack underflow'; + SParsDiv0 ='TBaseExprParser: RPN Division by zero in parser'; + SParsOpOverflow ='TBaseExprParser: Operator stack Overflow'; + SParsOpUnderflow ='TBaseExprParser: Operator stack Underflow'; + SNILDeref ='NIL dereference'; + SExprIE ='TExpression: Internal error: '; + SExprNotInt ='TExpression: This is not an integer'; + SExprNotFloat ='TExpression: This is not a float'; + SExprInvmsg ='TExpression: Inv(x) evaluates to 1/0'; + SExprInvSimp ='TExpression: Division by 0 encountered while simplifying'; + + { + $Log$ + Revision 1.1 2002/12/15 21:01:22 marco + Initial revision + +} + \ No newline at end of file diff --git a/packages/symbolic/src/parsexpr.inc b/packages/symbolic/src/parsexpr.inc new file mode 100644 index 0000000000..1c359b344f --- /dev/null +++ b/packages/symbolic/src/parsexpr.inc @@ -0,0 +1,498 @@ +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Implementation of Infix to parsetree/RPN converter based on principles + copied from a RPN constant expression evaluator by Trai Tran + (PD, from SWAG.) + + Parsetree to infix and parsetree to RPN/infix conversion + by Marco v/d Voort + OOP interface and vast improvements by Marco v/d Voort + + 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. + + ********************************************************************** + +Problems: +- -x^12 is -(x^12) or (-x)^12 ? (FIXED: Chose to do it as in FPC) +- No errorhandling. (will be rewritten to use classes and exceptions first) + (this is partially done now) + +Original comments: + +--------------------------------------------------------------------------- +THAI TRAN + +I've netmailed you the full-featured version (800 lines!) that will do +Functions, exponentiation, factorials, and has all the bells and whistles, +but I thought you might want to take a look at a simple version so you can +understand the algorithm. + +This one only works With +, -, *, /, (, and ). I wrote it quickly, so it +makes extensive use of global Variables and has no error checking; Use at +your own risk. + +Algorithm to convert infix to postfix (RPN) notation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Parse through the entire expression getting each token (number, arithmetic +operation, left or right parenthesis). For each token, if it is: + 1. an operand (number) Send it to the RPN calculator + 2. a left parenthesis Push it onto the operation stack + 3. a right parenthesis Pop operators off stack and send to RPN + calculator Until the a left parenthesis is + on top of the stack. Pop it also, but don't + send it to the calculator. + 4. an operator While the stack is not empty, pop operators + off the stack and send them to the RPN + calculator Until you reach one With a higher + precedence than the current operator (Note: + a left parenthesis has the least precendence). + Then push the current operator onto the stack. + +This will convert (4+5)*6/(2-3) to 4 5 + 6 * 2 3 - / + +Algorithm For RPN calculator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note: this Uses a different stack from the one described above. + +In RPN, if an operand (a number) is entered, it is just pushed onto the +stack. For binary arithmetic operators (+, -, *, /, and ^), the top two +operands are popped off the stack, operated on, and the result pushed back +onto the stack. if everything has gone correctly, at the end, the answer +should be at the top of the stack. + +Released to Public Domain by Thai Tran (if that matters). +--------------------------------------------------------------------------- +MvdV: It does for me. My routines might end up in either FPC or Jedi, and + anything except LGPL and PD is unacceptable. :-) + +Modifications: (starting to get so big that the original is hardly + recognisable) +- OOP. Mainly to allow symbolic TExpression class to have custom parsers. +- Working with pnode stack instead of reals. Pnodes can be any expression, + see inteface unit symbolic. (creating a parsetree) +- Support for functions(one or two parameter arguments), which weren't in the + short Swag version. Most MATH functions are supported. +- Can make a difference between the minus of (-x) and the one in (x-y). + The first is converted to function minus(x); +- power operator +- Faculty operator +- Conversions back to RPN and infix. +- Removing of excess parentheses. +} + +type {Tokens generated by the parser. Anything else is a constant or variable} + ParseOperation=(padd,psub,pmul,pdvd,ppow,pfacul,pleft,pright, + pcos,psin,ptan,psqr,psqrt,pexp,pln,pinv, + pminus, pcotan,parcsin,parccos,parctan,psinh,pcosh,ptanh, + parcsinh,parccosh,parctanh,plog10, + plog2,plnxpi,parctan2,pstep,ppower,phypot, + plogn,pnothing); + +CONST + ParserFunctionNamesUpper : array[padd..pnothing] of string[7]= + ('+','-','*','/','^','!','(',')','COS','SIN', + 'TAN','SQR','SQRT','EXP','LN','INV','-', + 'COTAN','ARCSIN','ARCCOS','ARCTAN', + 'SINH','COSH','TANH','ARCSINH', + 'ARCCOSH','ARCTANH','LOG10', + 'LOG2','LNXP1','ARCTAN2','STEP', + 'POWER','HYPOT','LOGN','NOTHING'); + + {Operator or function-} + Priority : array[padd..pnothing] of ArbInt= + (1,1,2,2,3,0,0,0, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5); + + OppsXlat='+-*/^!()'; {Must match the first entries of ParseOperation. + Pos(OppsXlat,c)-1+ord(Padd) is typecast!} + +Const + RPNMax = 20; { I think you only need 4-8, but just to be safe } + OpMax = 25; + AllowedInToken = ['0'..'9','.','E','e']; + +Type + String15 = String[15]; + +Procedure ParserInternalError(const Msg:String;A,B:ArbInt); + +VAR S,S2 : String; + +begin + Str(A,S); {Usually a identification number for the occurance} + Str(B,S2); {Usually the value that tripped the IE} + Raise EParserIE.Create(SParsIE+Msg+S+' '+S2); +end; + +function TBaseExprParser.InFixToParseTree(Expr : String;VAR RPNexpr: String):pnode; + +Var + RPNStack : Array[1..RPNMax] of PNode; { Stack For RPN calculator } + RPNTop, + OpTop : ArbInt; + OpStack : Array[1..OpMax] of ParseOperation; { Operator stack For conversion } + +Procedure RPNPush(Num : PNode); { Add an operand to the top of the RPN stack } +begin + if RPNTop < RPNMax then + begin + Inc(RPNTop); + RPNStack[RPNTop] := Num; + end + else + RAISE EParserStack.Create(SParseRPNOverflow); +end; + +Function RPNPop : pnode; { Get the operand at the top of the RPN stack } +begin + if RPNTop > 0 then + begin + RPNPop := RPNStack[RPNTop]; + Dec(RPNTop); + end + else + RAISE EParserStack.Create(SParseRPNUnderflow); +end; + +Procedure RPNCalc(Token : String15); { RPN Calculator } +Var + treal : ArbFloat; + tint : ArbInt; + Error : ArbInt; +begin + RPNExpr:=RPNExpr+token+' '; + Val(Token, treal, Error); + IF (error=0) then + begin + if (Pos('.',token)=0) and (Pos('E',token)=0) Then + begin + Val(Token,tint,Error); + RpnPush(Newiconst(tint)); + end + else + RPNPush(NewConst(Treal)); + end + else { Handle error } + RPNPush(NewVar(Token)); +end; + +Procedure RPNOperation(Operation:ParseOperation); +{The workhorse. Creates the tree, and associates a parseoperation with + the TExpression enumerations. Avoids some ugly (and shaky) typecasts + between operations like in earlier versions.} + +var Temp: pnode; + +begin + RPNExpr:=RPNExpr+ParserFunctionNamesUpper[Operation]+' '; + Case Operation of { Handle operators } + padd : RPNPush(newcalc(addo,RPNPop,RPNPop)); + psub : begin + Temp:=RPNPOP; + RPNPush(NewCalc(subo,RPNPOP,Temp)); + end; + pmul : RPNPush(newcalc(mulo,RPNPOP,RPNPop)); + pdvd : begin + Temp := RPNPop; + if Temp <> NIL then + RPNPush(newcalc(dvdo,RPNPop,Temp)) + else + Raise EDiv0.Create(SParsDiv0); { Handle divide by 0 error } + end; + ppow,ppower : {are only different in parsing x^y and power(x,y)} + begin + Temp:=RpnPop; + RpnPush(NewCalc(powo,RpnPop,Temp)); + end; + pfacul : RPNPush(NewFunc(faculx,RPNPOP)); + psin : RPNPush(NewFunc(sinx,RPNPop)); + pcos : RPNPush(NewFunc(cosx,RPNPop)); + ptan : RPNPush(NewFunc(tanx,RPNPop)); + psqr : RPNPush(NewFunc(sqrx,RPNPop)); + pexp : RPNPush(NewFunc(expx,RPNPop)); + pln : RPNPush(NewFunc(lnx,RPNPop)); + pinv : RPNPush(NewFunc(invx,RPNPop)); + Pminus : RPNPush(newFunc(minus,RPNPop)); + pcotan : RPNPush(NewFunc(cotanx,rpnpop)); + parcsin : RPNPush(NewFunc(arcsinx,rpnpop)); + parccos : RPNPush(NewFunc(arccosx,rpnpop)); + parctan : RPNPush(NewFunc(arctanx,rpnpop)); + psinh : RPNPush(NewFunc(sinhx,rpnpop)); + pcosh : RPNPush(NewFunc(coshx,rpnpop)); + ptanh : RPNPush(NewFunc(tanhx,rpnpop)); +parcsinh : RPNPush(NewFunc(arcsinhx,rpnpop)); +parccosh : RPNPush(NewFunc(arccoshx,rpnpop)); +parctanh : RPNPush(NewFunc(arctanhx,rpnpop)); + plog10 : RPNPush(NewFunc(log10x,rpnpop)); + plog2 : RPNPush(NewFunc(log2x,rpnpop)); + plnxpi : RPNPush(NewFunc(lnxpix,rpnpop)); +parctan2 : begin + Temp:=RpnPop; + RpnPush(Newfunc(arctan2x,RpnPop,temp)); + end; + pstep : begin + Temp:=RpnPop; + RpnPush(Newfunc(stepx,RpnPop,temp)); + end; + phypot: begin + Temp:=RpnPop; + RpnPush(Newfunc(hypotx,RpnPop,temp)); + end; + plogn : begin + Temp:=RpnPop; + RpnPush(Newfunc(lognx,RpnPop,Temp)); + end; + else + ParserInternalError('Unknown function',1,ORD(Operation)); + end; +end; + +Function IsFunction(S:String):ParseOperation; + +var Count:ParseOperation; + +begin + IsFunction:=pnothing; + for Count:=pCos to pInv do {Minus is a pseudo function, and in this category + because it has only 1 argument} + begin + If Copy(S,1,3)=ParserFunctionNamesUpper[Count] then + IsFunction:=Count; + end; +end; + +Procedure OpPush(operation : ParseOperation); { Add an operation onto top of the stack } +begin + if OpTop < OpMax then + begin + Inc(OpTop); + OpStack[OpTop] := operation; + end + else + RAISE EParserStack.Create(SParsOpOverflow); +end; + +Function OpPop : ParseOperation; { Get operation at the top of the stack } +begin + if OpTop > 0 then + begin + OpPop := OpStack[OpTop]; + Dec(OpTop); + end + else + RAISE EParserStack.Create(SParsOpUnderflow); +end; + +Var + I,len : ArbInt; + Token : String15; + OperationNr : ParseOperation; + FunctionNr : ArbInt; + isminus : boolean; + +begin + RPNExpr:=''; + OpTop := 0; { Reset stacks } + RPNTop := 0; + Token := ''; + {$ifdef fpc} + Expr:=Upcase(Expr); + {$endif} + i:=1; len:=Length(Expr); + while I<=Len do + begin + {Flush token, if we feel an infix operator coming} + FunctionNr:=Pos(expr[I],OppsXlat); + If (FunctionNr<>0) and (Token<>'') THEN + begin { Send last built number to calc. } + RPNCalc(Token); + Token := ''; + end; + If (FunctionNr>0) and (FunctionNr<7) then + begin + OperationNr:=ParseOperation(FunctionNr-1+ORD(padd)); + If (OperationNr=psub) then {Minus(x) or x-y?} + begin + IsMinus:=False; + if I=1 then + IsMinus:=true + else + If Expr[I-1] IN ['+','(','*','/','-','^'] then + IsMinus:=true; + If IsMinus then + OperationNr:=PMinus; + end; + While (OpTop > 0) AND + (Priority[OperationNr] <= Priority[OpStack[OpTop]]) DO + RPNOperation(OpPop); + OpPush(OperationNr); + end + else + case Expr[I] of + '0'..'9' : begin + While (Expr[I] in AllowedInToken) and (I<=len) do + begin + Token:=Token+Expr[I]; + inc(i); + end; + dec(i); + end; + ',' : if Token <> '' then {Two parameter functions} + begin { Send last built number to calc. } + RPNCalc(Token); + Token := ''; + end; + '(' : OpPush(pleft); + ')' : begin + While OpStack[OpTop] <> pleft DO + RPNOperation(OpPop); + OpPop; { Pop off and ignore the '(' } + end; + 'A'..'Z' : begin + if Token <> '' then + begin { Send last built number to calc. } + RPNCalc(Token); + Token := ''; + end; + While (Expr[I] IN ['0'..'9','A'..'Z']) AND (I<=Len) DO + begin + Token:=Token+Expr[I]; + Inc(I); + end; + Dec(i); + OperationNr:=IsFunction(Token); + if OperationNr<>pnothing then + begin + Token:=''; + While (OpTop > 0) AND + (Priority[OperationNr] <= Priority[OpStack[OpTop]]) DO + RPNOperation(OpPop); + OpPush(OperationNr); + end + else + begin + RpnCalc(Token); + Token:=''; + end; + end; + end; { Case } + inc(i); + end; + If Token<>'' Then + RpnCalc(Token); + + While OpTop > 0 do { Pop off the remaining operations } + RPNOperation(OpPop); + InFixToParseTree:=RpnPop; +end; + +function TBaseExprParser.ParseTreeToInfix(expr:pnode):string; + +var S,right,left : string; + IsSimpleExpr : boolean; + +begin + IF expr=nil then + ParserInternalError(SNILDeref,5,0); + case expr^.nodetype of + VarNode : S:=expr^.variable; + iconstnode: str(expr^.ivalue,S); + ConstNode: str(expr^.value,s); + CalcNode : begin + right:=ParseTreeToInfix(expr^.right); + left:=ParseTreeToInfix(expr^.left); + S:=left+InfixOperatorName[Expr^.op]+right; + if (expr^.op=addo) or (expr^.op=subo) then + S:='('+S+')'; + end; + FuncNode : begin + left:=functionnames[expr^.fun]; + right:=ParseTreeToInfix(expr^.son); + issimpleExpr:=false; + If ((Expr^.fun=minus) or (Expr^.fun=faculx)) and + (expr^.son^.nodetype in [varnode,iconstnode,constnode]) then + issimpleExpr:=true; + if expr^.fun<>faculx then + begin + If IsSimpleExpr then + S:=Left+Right + else + S:=Left+'('+Right+')'; + end + else + If IsSimpleExpr then + S:=Right+Left + else + S:='('+Right+')'+Left; + end; + Func2Node : begin + S:=functionnames[expr^.fun]; + Left:=ParseTreeToInfix(Expr^.son2right); + right:=ParseTreeToInfix(expr^.son2left); + S:=S+'('+Left+','+Right+')'; + end; + end; + ParseTreeToInfix:=S; +end; + +function TBaseExprParser.ParseTreeToRPN(expr:pnode):string; +{not fast because of the prepending. Creating an array of pnode would maybe +be faster} + +procedure SearchTree(Tree:pnode;var s:string); + +var temp:string; + +begin + if tree<>nil then + case Tree^.nodetype of + VarNode : s:=Tree^.Variable +' '+s; + ConstNode: begin + str(Tree^.value:5:9,temp); {should be configurable} + s:=temp+' '+s; + end; + iconstnode: begin + str(Tree^.ivalue,temp); + s:=temp+' '+s; + end; + CalcNode : begin + s:=InfixOperatorName[Tree^.op]+' '+s; + SearchTree(tree^.right,s); + SearchTree(tree^.left,s); + end; + FuncNode: begin + s:=functionnames[tree^.fun]+' '+s; + SearchTree(tree^.son,s); + end; + Func2Node: begin + s:=functionnames[tree^.fun]+' '+s; + SearchTree(tree^.son2right,s); + SearchTree(Tree^.son2left,s); + end; + end; +end; + +var s : String; + +begin + s:=''; + searchTree(expr,s); + ParseTreeToRPN:=S; +end; + +{ + $Log$ + Revision 1.1 2002/12/15 21:01:24 marco + Initial revision + +} + \ No newline at end of file diff --git a/packages/symbolic/src/rearrang.inc b/packages/symbolic/src/rearrang.inc new file mode 100644 index 0000000000..5165844717 --- /dev/null +++ b/packages/symbolic/src/rearrang.inc @@ -0,0 +1,90 @@ + + +{$IFDEF DetectConstFlagCorruption} +TYPE + EConstCorruption=Class(Exception); +{$ENDIF} + +PROCEDURE TExpression.UpdateConstants; + +function InternalUpdateConstants(expr:pnode):boolean; +{Shouldn't be necessary. Detects both corruption of flags if +DetectConstFlagCorruption is defined +and rebuilds them.} + +begin + if Expr<>NIL THEN + case Expr^.NodeType of + VarNode : begin {A symbol is not a constant} + {$IFDEF DetectConstFlagCorruption} + if (ExprIsConstant IN Expr^.Flags) then + Raise EConstCorruption.Create('Corrupt Varnode'); + {$ENDIF} + Exclude(Expr^.flags,ExprIsConstant); + Result:=false; + end; + IConstNode, + ConstNode: begin + {$IFDEF DetectConstFlagCorruption} + if NOT (ExprIsConstant IN Expr^.Flags) then + Raise EConstCorruption.Create('Corrupt (I)constnode'); + {$ENDIF} + Include(Expr^.flags,ExprIsConstant); + Result:=TRUE; + end; + calcnode: begin + Result:=InternalUpdateConstants(Expr^.Left) AND InternalUpdateConstants(Expr^.Right); + {$IFDEF DetectConstFlagCorruption} + if (ExprIsConstant IN Expr^.Flags)<>Result then + Raise EConstCorruption.Create('Corrupt calcnode'); + {$ENDIF} + IF Result THEN + Include(Expr^.flags,ExprIsConstant) + else + Exclude(Expr^.flags,ExprIsConstant) + end; + funcnode: begin + Result:=InternalUpdateConstants(Expr^.Son); + {$IFDEF DetectConstFlagCorruption} + if (ExprIsConstant IN Expr^.Flags)<>Result then + Raise EConstCorruption.Create('Corrupt funcnode'); + {$ENDIF} + IF Result THEN + Include(Expr^.flags,ExprIsConstant) + else + Exclude(Expr^.flags,ExprIsConstant) + end; + func2node: begin + Result:=InternalUpdateConstants(Expr^.Son2Left) and InternalUpdateConstants(Expr^.Son2Right); + {$IFDEF DetectConstFlagCorruption} + if (ExprIsConstant IN Expr^.Flags)<>Result then + Raise EConstCorruption.Create('Corrupt func2node'); + {$ENDIF} + IF Result THEN + Include(Expr^.flags,ExprIsConstant) + else + Exclude(Expr^.flags,ExprIsConstant) + end; + end; +end; + +begin + InternalUpdateConstants(ExprTree); +end; + +{ + + + + + + + + + + + + + + +} \ No newline at end of file diff --git a/packages/symbolic/src/symbexpr.inc b/packages/symbolic/src/symbexpr.inc new file mode 100644 index 0000000000..0959670aeb --- /dev/null +++ b/packages/symbolic/src/symbexpr.inc @@ -0,0 +1,1122 @@ +{ + $id: $ + Copyright (c) 2000 by Marco van de Voort (marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + TExpression class which does symbolic manipulation. + + Derivation routine based on 20 lines of conceptual pseudo code + provided by Osmo Ronkanen. + + 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. + + ********************************************************************** + +Problems: + +- Often untested. I used my HP48g to check some complex derivatives, + but more thorough checking and errorhandling is necessary. +- RPN to Infix adds ()'s when not necessary. Should be made aware of precedence. + (partially fixed) +} + +{Should be moved to a math unit. Calculate x! with a 23 degree polynomal for + ArbFloat values. From Numlib. + + +Works for extended only. Redefine TC1 and TC3 for your numeric type +if you want to use something else.} + +type Float10Arb =ARRAY[0..9] OF BYTE; + +const + + TC1 : Float10Arb = (0,0,$00,$00,$00,$00,0,128,192,63); {Eps} + TC3 : Float10Arb = (1,0,0,0,0,0,0,0,0,0); {3.64519953188247460E-4951} + + +var {Looks ugly, but is quite handy.} + macheps : ArbFloat absolute TC1; { macheps = r - 1, with r + the smallest ArbFloat > 1} + midget : ArbFloat absolute TC3; { the smallest positive ArbFloat} + + +function spepol(x: ArbFloat; var a: ArbFloat; n: ArbInt): ArbFloat; +var pa : ^ArbFloat; {FPC extension. Uses ^ some array of ArbFloat in TP} + i : ArbInt; + polx : ArbFloat; +begin + pa:=@a; + polx:=0; + for i:=n downto 0 do + polx:=polx*x+pa[i]; {and pa^[i] here} + spepol:=polx +end {spepol}; + + +function spegam(x: ArbFloat): ArbFloat; +const + + tmax = 170; + a: array[0..23] of ArbFloat = + ( 8.86226925452758013e-1, 1.61691987244425092e-2, + 1.03703363422075456e-1, -1.34118505705967765e-2, + 9.04033494028101968e-3, -2.42259538436268176e-3, + 9.15785997288933120e-4, -2.96890121633200000e-4, + 1.00928148823365120e-4, -3.36375833240268800e-5, + 1.12524642975590400e-5, -3.75499034136576000e-6, + 1.25281466396672000e-6, -4.17808776355840000e-7, + 1.39383522590720000e-7, -4.64774927155200000e-8, + 1.53835215257600000e-8, -5.11961333760000000e-9, + 1.82243164160000000e-9, -6.13513953280000000e-10, + 1.27679856640000000e-10,-4.01499750400000000e-11, + 4.26560716800000000e-11,-1.46381209600000000e-11); + +var tvsmall, t, g: ArbFloat; + m, i: ArbInt; +begin + if sizeof(ArbFloat) = 6 + then + tvsmall:=2*midget + else + tvsmall:=midget; + t:=abs(x); + if t > tmax + then + RunError(407); + if t < macheps + then + begin + if t < tvsmall + then + RunError(407); + spegam:=1/x + end + else { abs(x) >= macheps } + begin + m:=trunc(x); + if x > 0 + then + begin + t:=x-m; m:=m-1; g:=1; + if m<0 + then + g:=g/x + else + if m>0 + then + for i:=1 to m do + g:=(x-i)*g + end + else { x < 0 } + begin + t:=x-m+1; + if t=1 + then + RunError(407); + m:=1-m; + g:=x; + for i:=1 to m do + g:=(i+x)*g; + g:=1/g + end; + spegam:=spepol(2*t-1, a[0], sizeof(a) div sizeof(ArbFloat) - 1)*g + end { abs(x) >= macheps } +end; {spegam} + + +Procedure ExprInternalError(A,B:ArbInt); + +VAR S,S2 : String; + +begin + Str(ORD(A),S); + Str(ORD(B),S2); + Raise EExprIE.Create(SExprIE+S+' '+S2); +end; + +CONSTRUCTOR TExpression.Create(Infix:String); + +var dummy:String; + +begin + ExprTree:=NIL; + + if (Infix<>'') then + ExprTree:=InfixToParseTree(Infix,Dummy); + InfixCache:=Infix; + InfixClean:=True; {Current pnode status' infix + representation is in infixcache} +end; + +CONSTRUCTOR TExpression.EmptyCreate; + +begin + ExprTree:=Nil; + InfixClean:=false; +end; + +Procedure TExpression.SetNewInfix(Infix:String); + +var dummy:String; + +begin + if Assigned(ExprTree) Then + Dispose(ExprTree); + if infix<>'' then + ExprTree:=InFixToParseTree(Infix,Dummy) + else + ExprTree:=NIL; + InfixClean:=True; + InfixCache:=Infix; +end; + +Destructor TExpression.Destroy; + +begin + If assigned(ExprTree) then + DisposeExpr(ExprTree); + inherited Destroy; +end; + +function TExpression.GetRPN :String; + +begin + if ExprTree=NIL Then + Result:='0' + else + Result:=ParseTreeToRpn(ExprTree); +end; + +function TExpression.GetInfix:String; + +begin + if Not InfixClean then + begin + If ExprTree=NIL THEN + InfixCache:='0' + else + InfixCache:=ParseTreeToInfix(ExprTree); + InfixClean:=True; + end; + Result:=InfixCache; +end; + +Function TExpression.GetIntValue:LongInt; + +begin + SimplifyConstants; + If ExprTree^.NodeType<>Iconstnode then + Raise ENotInt.Create(SExprNotInt); + result:=ExprTree^.ivalue; +end; + +Procedure TExpression.SetIntValue(val:Longint); + +begin + if ExprTree<> NIL then + DisposeExpr(ExprTree); + New(ExprTree); + ExprTree^.NodeType:=iconstnode; + ExprTree^.Ivalue:=Val; +end; + +Function TExpression.GetFloatValue:ArbFloat; + +begin + If ExprTree^.NodeType<>constnode then + Raise ENotFloat.Create(SExprNotFloat); + result:=ExprTree^.value; +end; + +Procedure TExpression.SetFloatValue(val:ArbFloat); + +begin + if ExprTree<> NIL then + DisposeExpr(ExprTree); + New(ExprTree); + ExprTree^.NodeType:=constnode; + ExprTree^.value:=Val; +end; + +procedure TExpression.Simpleop(expr:TExpression;oper:calcop); + +begin + exprtree:=NewCalc(oper,exprtree,CopyTree(expr.exprtree)); + InFixCache:='garbadge'; + InfixClean:=False; +end; + +function TExpression.Simpleopwithresult(expr:TExpression;oper:calcop):TExpression; + +var tmp:pnode; + +begin + result.EmptyCreate; + result.SimplificationLevel:=simplificationlevel; + result.exprtree:=NewCalc(Oper,CopyTree(ExprTree),CopyTree(Expr.ExprTree)); +end; + +procedure TExpression.Addto(Expr:TExpression); + +begin + simpleop(expr,addo); +end; + + +procedure TExpression.SubFrom(Expr:TExpression); + +begin + simpleop(expr,subo); +end; + +procedure TExpression.Times(Expr:texpression); + +begin + simpleop(expr,mulo); +end; + +procedure TExpression.Divby(Expr:TExpression); + +begin + simpleop(expr,dvdo); +end; + + +procedure TExpression.RaiseTo(Expr:TExpression); + +begin + simpleop(expr,powo); +end; + + +function TExpression.add(Expr:TExpression):TExpression; + + +begin + result:=Simpleopwithresult(expr,addo); +end; + +function TExpression.sub(Expr:TExpression):TExpression; + + +begin + result:=Simpleopwithresult(expr,subo); +end; + +function TExpression.dvd(Expr:TExpression):TExpression; + +begin + result:=Simpleopwithresult(expr,dvdo); +end; + + +function TExpression.mul(Expr:TExpression):TExpression; + +begin + result:=Simpleopwithresult(expr,mulo); +end; + +Function TExpression.IntDerive(const derivvariable:String;theexpr:pnode):pnode; + +function Deriv(t:pnode):pnode; +{Derive subexpression T. Returns NIL if subexpression derives to 0, to avoid +unnecessary (de)allocations. This is the reason why NewCalc is so big.} + +var x : ArbFloat; + p1,p2 : pnode; + +begin + Deriv:=nil; + if (t=nil) then {Early out} + exit; + with t^ do begin + case nodetype of + VarNode: if upcase(variable)=derivvariable then + Deriv:=NewiConst(ArbInt(1)) + else + Deriv:=NIL; + ConstNode : Deriv:=NIL; + IConstNode: Deriv:=NIL; + CalcNode: begin + case op of + addo, + subo: Deriv:=NewCalc(op,Deriv(left),Deriv(right)); + mulo: Deriv:=NewCalc(addo, + NewCalc(mulo,Deriv(left),copyTree(right)), + NewCalc(mulo,Deriv(right),copytree(left))); + + dvdo: Deriv:=NewCalc(dvdo, + NewCalc(subo, + NewCalc(mulo,Deriv(left),copyTree(right)), + NewCalc(mulo,Deriv(right),copytree(left))), + NewFunc(sqrx,CopyTree(right))); + powo: begin + p1:=Deriv(Right); + if P1<>NIL then + p1:=NewCalc(mulo,p1,NewFunc(Lnx,CopyTree(Left))); { ln(l)*r'} + p2:=Deriv(Left); + if P2<>NIL then + p2:=Newcalc(Mulo,CopyTree(Right),newcalc(mulo,p2, + newfunc(invx,CopyTree(left)))); + IF (P1<>nil) and (p2<>nil) then + deriv:=newcalc(mulo,CopyTree(t),newcalc(addo,p1,p2)) + else + if (P1=NIL) and (P2=NIL) then {Simplify first to avoid this!} + deriv:=NIL + else + begin + if P1=NIL THEN { one of both is constant} + P1:=P2; {The appopriate term is now in P1} + deriv:=newcalc(mulo,CopyTree(t),p1); + end; + end; + end; + end; + FuncNode: begin + case fun of + invx: Deriv:=NewCalc(dvdo, + NewFunc(Minus,Deriv(son)), + NewFunc(sqrx,CopyTree(son))); + + minus: Deriv:=NewFunc(minus,Deriv(son)); + sinx: Deriv:=NewCalc(Mulo, + NewFunc(cosx,Copytree(son)), + Deriv(son)); + cosx: deriv:=NewCalc(mulo, + NewFunc(minus,NewFunc(sinx,copytree(son))), + Deriv(son)); + tanx: deriv:=Newcalc(dvdo,deriv(son), + newfunc(sqrx,newfunc(cosx,copytree(son)))); + sqrx: deriv:=newcalc(mulo, newiconst(2), + newcalc(mulo,copytree(son),deriv(son))); + { dx*1 /(2*sqrt(x)) } + sqrtx: deriv:=newcalc(mulo, deriv(son),newcalc(dvdo,newiconst(1), + newcalc(mulo,newiconst(2),newfunc(sqrtx,copytree(son))))); + lnx : deriv:=newcalc(mulo,newcalc(dvdo,newiconst(1),CopyTree(son)), + deriv(son)); { dln(x)=x' * 1/x} + expx: deriv:=newcalc(mulo,newfunc(expx,copytree(son)),deriv(son)); + cotanx: deriv:=newfunc(minus,Newcalc(dvdo,deriv(son), { -dx/sqr(sin(x))} + newfunc(sqrx,newfunc(sinx,copytree(son))))); + coshx: deriv:=newcalc(mulo,newfunc(sinhx,copytree(son)),deriv(son)); + sinhx: deriv:=newcalc(mulo,newfunc(coshx,copytree(son)),deriv(son)); + arcsinhx, {according to HP48?} + arcsinx: deriv:=newcalc(dvdo,deriv(son),newfunc(sqrtx,newcalc(subo,newiconst(1), + newfunc(sqrx,copytree(son))))); + arccosx: deriv:=newfunc(minus,newcalc(dvdo,deriv(son), + newfunc(sqrtx,newcalc(subo,newiconst(1),newfunc(sqrx,copytree(son)))))); + arctanx: deriv:=newcalc(dvdo,deriv(son),newcalc(addo,newiconst(1),newfunc(sqrx,copytree(son)))); + log10x: deriv:=newcalc(mulo,newcalc(dvdo,newconst(0.434294481902),CopyTree(son)), + deriv(son)); { dlog10(x)=x' * log10(e)/x} + log2x: deriv:=newcalc(mulo,newcalc(dvdo,newconst(1.44269504089),CopyTree(son)), + deriv(son)); { dlog2(x)=x' * log2(e)/x} + stepx: ; {Should raise exception, not easily derivatable} + tanhx: deriv:=newcalc(dvdo,deriv(son),newfunc(sqrx,newfunc(coshx,copytree(son)))); + arctanhx: deriv:=newcalc(dvdo,deriv(son),newfunc(sqrtx,newcalc(addo,newiconst(1), + newfunc(sqrx,copytree(son))))); + arccoshx: deriv:=NewCalc(dvdo,deriv(son),newcalc(mulo,newcalc(subo,newfunc(sqrtx,copytree(son)),newiconst(1)), + newcalc(addo,newfunc(sqrtx,copytree(son)),newiconst(1)))); + lnxpix,arctan2x, + hypotx,lognx : ; {Should also raise exceptions, not implemented yet} + end; + end; + Func2Node: begin + if son2left^.nodetype=constnode then + x:=son2left^.value + else + x:=son2left^.ivalue; + case fun of + lognx: deriv:=newcalc(mulo,newcalc(dvdo,newconst(logn(x,2.71828182846)), + CopyTree(son2right)),deriv(son2right)); + { dlogn(x)=x' * log(n,e)/x} + Powerx: begin + p1:=Deriv(Son2Right); + if P1<>NIL then + p1:=NewCalc(mulo,p1,NewFunc(Lnx,CopyTree(Son2Left))); { ln(l)*r'} + p2:=Deriv(Son2Left); + if P2<>NIL then + p2:=Newcalc(Mulo,CopyTree(Son2Right),newcalc(mulo,p2, + newfunc(invx,CopyTree(Son2Left)))); + IF (P1<>nil) and (p2<>nil) then + deriv:=newcalc(mulo,CopyTree(t),newcalc(addo,p1,p2)) + else + if (P1=NIL) and (P2=NIL) then {Simplify first to avoid this!} + deriv:=NIL + else + begin + if P1=NIL THEN { one of both is constant} + P1:=P2; {The appopriate term is now in P1} + deriv:=newcalc(mulo,CopyTree(t),p1); + end; + end; + end; + end; + end; + end; {WITH} +end; + +begin + Result:=Deriv(theexpr); +end; + +function TExpression.power(Expr:TExpression):TExpression; + + +begin + result:=Simpleopwithresult(expr,powo); +end; + + +Function TExpression.Derive(derivvariable:String):TExpression; + +var tmpvar : Pnode; + DerivObj: TExpression; + +begin + derivvariable:=upcase(derivvariable); + Tmpvar:=intDerive(derivvariable,exprtree); + + DerivObj:=TExpression.emptycreate; + If tmpvar=NIL then + derivobj.ExprTree:=NewIconst(0) + else + derivobj.exprtree:=tmpvar; + derivobj.simplificationlevel:=simplificationlevel; + DerivObj.InfixClean:=False; + result:=derivobj; +end; + +function ipower(x,y:ArbInt):ArbInt; + +var tmpval : ArbInt; + +begin + if y<0 then + ; {exception} + if y=0 then + result:=1 + else + begin + result:=x; + if y<>1 then + for tmpval:=2 to y do + result:=result*x; + end; +end; + +function ifacul(x:ArbInt):ArbInt; + +var tmpval : ArbInt; + +begin + if x<0 then + ; {exception} + if x=0 then + result:=1 + else + begin + result:=1; + if x<>1 then + for tmpval:=2 to x do + result:=result*tmpval; + end; +end; + +function EvaluateFunction(funcname:funcop;param:ArbFloat):ArbFloat; + +var Intermed : integer; + +begin + case funcname of + cosx : result:=Cos(param); + sinx : result:=sin(param); + tanx : result:=tan(param); + sqrx : result:=sqr(param); + sqrtx : result:=sqrt(param); + expx : result:=exp(param); + lnx : result:=ln(param); + cotanx : result:=cotan(param); + arcsinx : result:=arcsin(param); + arccosx : result:=arccos(param); + arctanx : result:=arctan(param); + sinhx : result:=sinh(param); + coshx : result:=cosh(param); + tanhx : result:=tanh(param); + arcsinhx : result:=arcsinh(param); + arccoshx : result:=arccosh(param); + arctanhx : result:=arctanh(param); + log10x : result:=log10(param); + log2x : result:=log2(param); + lnxpix : result:=lnxp1(param); + faculx : result:=spegam(param+1.0); + else + ExprInternalError(2,ord(funcname)); + end; + If Result<1E-4900 then {Uncertainty in sinus(0.0)} + Result:=0; +end; + + +procedure TExpression.SimplifyConstants; + +//procedure internalsimplify (expr:pnode;InCalc:Boolean;parent:pnode); +procedure internalsimplify (expr:pnode); + +function isconst(p:pnode):boolean; + +begin + isconst:=(p^.nodetype=iconstnode) or (p^.nodetype=constnode); +end; + +function isconstnil(p:pnode):boolean; +begin + IsConstNil:=false; + if (p^.nodetype=iconstnode) and (P^.ivalue=0) then + IsConstNil:=True; + If (p^.nodetype=constnode) and (P^.value=0) then + IsConstNil:=True +end; + +var val1,val2 : ArbFloat; + ival1, + ival2 : ArbInt; + +function setupoperation(operat:calcop;simlevel:longint;Postprocess:boolean;param2func:boolean):longint; + +function dosimple(mode:longint;theleft,theright:pnode):longint; + +begin + If Mode >3 then + ; + result:=0; + if mode=0 then + exit; + if (theright^.nodetype=iconstnode) and (theleft^.nodetype=iconstnode) then + begin + if mode=3 then + begin + result:=2; + val2:=theright^.value; + val1:=theleft^.value; + end + else + begin + result:=1; + ival2:=theright^.ivalue; + ival1:=theleft^.Ivalue; + end; + end; + if (theright^.nodetype=constnode) and (theleft^.nodetype=constnode) then + begin + result:=2; + val2:=theright^.value; + val1:=theleft^.value; + end; + if mode>1 then + begin + if result=0 then + begin + if (theright^.nodetype=constnode) and (theleft^.nodetype=iconstnode) then + begin + result:=3; + val2:=theright^.value; + val1:=theleft^.ivalue; + end; + if (theright^.nodetype=iconstnode) and (theleft^.nodetype=constnode) then + begin + result:=4; + val2:=theright^.ivalue; + val1:=theleft^.value; + end; + end; + end; +end; + +begin + Result:=0; + if SimplificationLevel<>0 then + if param2func then + result:=DoSimple(SimLevel,expr^.son2left,expr^.son2right) + else + result:=DoSimple(SimLevel,expr^.left,expr^.right); + + with expr^ do + begin + IF (result>0) and PostProcess then + begin + if (operat<>dvdo) then { Divide is special case. If + integer x/y produces a fraction + we want to be able to roll back} + begin + if Param2func then + begin + dispose(son2right); + dispose(son2left); + end + else + begin + dispose(right); + dispose(left); + end; + if result=1 then + nodetype:=iconstnode + else + nodetype:=constnode; + flags:=[ExprIsConstant]; + end; + end; + end; +end; + +procedure Checkvarnode(p:pnode); + +var treal:arbfloat; + error:integer; + tint :Integer; + +begin + TrimLeft(P^.variable); + TrimRight(p^.variable); + Val(p^.variable, treal, Error); + IF (error=0) then {Conversion to real succeeds. Numeric} + begin + p^.flags:=[ExprIsConstant]; + if (Pos('.',p^.variable)=0) and (Pos('E',p^.variable)=0) Then + begin + Val(p^.variable,tint,Error); + If error=0 then + begin + p^.nodetype:=iconstnode; + p^.ivalue:=tint; + end + else + begin + p^.nodetype:=constnode; + p^.value:=treal; + end; + end + else + begin + p^.nodetype:=constnode; + p^.value:=treal; + end; + end; +end; + +var tmpval : ArbInt; + invdummy: pnode; + +begin + case expr^.nodetype of + VarNode : CheckVarnode(expr); {sometimes a numeric value can slip in as constant. + (e.g. as people pass it as symbol to taylor or + "subst" methods} + + calcnode : begin + //If not + internalsimplify(expr^.left); {Reduce left and right as much as possible} + internalsimplify(expr^.right); + if isconst(expr^.left) and isconst(expr^.right) then + begin + TmpVal:=Setupoperation(expr^.op,SimplificationLevel,true,false); + if tmpval>0 then + with expr^ do + case op of + addo : + if tmpval=1 then + ivalue:=ival1+ival2 + else + value:=val1+val2; + subo : if tmpval=1 then + ivalue:=ival1-ival2 + else + value:=val1-val2; + mulo : if tmpval=1 then + ivalue:=ival1*ival2 + else + value:=val1*val2; + + dvdo : begin + if tmpval=1 then + begin + tmpval:=ival1 div ival2; + if (tmpval*ival2)=ival1 then {no rounding, OK!} + begin + Dispose(expr^.right); + Dispose(Expr^.left); + nodetype:=iconstnode; + ivalue:=tmpval; + end; {ELSE do nothing} + end + else + begin + dispose(expr^.right); + dispose(expr^.left); + nodetype:=constnode; + value:=val1 / val2; + end; + flags:=[ExprIsConstant]; + end; + powo : If tmpval=1 then + begin + if ival2<0 then {integer x^-y -> inv (x^y)} + begin + expr^.nodetype:=funcnode; + expr^.son:=NewIConst(IPower(Ival1,-Ival2)); + end + else + ivalue:=ipower(ival1,ival2); + end + else + value:=exp(val2*ln(val1)); + else + ExprInternalError(1,ord(Expr^.op)); + end; {case} + end {if} + else {At least one node is symbolic, or both types are wrong} + begin + With Expr^ do + if IsConstNil(Left) then + begin + Dispose(Left); + case op of + addo : begin + InvDummy:=Right; + Expr^:=Right^; + Dispose(InvDummy); + end; + subo: begin + invdummy:=right; + NodeType:=funcNode; + Fun:=Minus; + son:=invdummy; + Flags:=Son^.Flags; + end; + mulo,powo,dvdo : begin + Dispose(Right); + nodetype:=IconstNode; + ivalue:=0; + Flags:=[ExprIsConstant]; + end; + end; + end + else + if IsConstNil(Right) then + begin + if expr^.op<>dvdo then {Leave tree for DVD intact because of exception} + Dispose(Right); + case expr^.op of + addo,subo : begin + InvDummy:=left; + Expr^:=left^; + Dispose(InvDummy); + end; + mulo : begin + Dispose(Left); + nodetype:=IconstNode; + Flags:=[ExprIsConstant]; + ivalue:=0; + end; + powo : begin + Dispose(Left); + nodetype:=IconstNode; + Flags:=[ExprIsConstant]; + ivalue:=1; + end; + dvdo : Raise EDiv0.Create(SExprInvSimp); + else + ExprInternalError(6,ord(Expr^.op)); + end; + end; + end; + With Expr^ Do + Begin + IF (nodetype=calcnode) and (Op in [Mulo,Addo]) then + begin {Commutative operator rearrangements, move constants to left} + if (ExprIsConstant IN Right^.flags) and NOT (ExprIsConstant IN Left^.flags) then + begin + InvDummy:=Right; + Right:=Left; + Left:=InvDummy; + end; + IF (right^.nodetype=calcnode) and (right^.Op in [Mulo,Addo]) then + begin + end; + end; + End; + end; {case calcnode} + + funcnode: begin + internalSimplify(expr^.son); + Case Expr^.fun of + Minus : if IsConst(expr^.son) then + begin + InvDummy:=Expr^.Son; + expr^:=InvDummy^; + if InvDummy^.Nodetype=IconstNode then + expr^.ivalue:=-expr^.ivalue + else + expr^.value:=-expr^.value; + dispose(InvDummy); + end; + invx : begin + InvDummy:=Expr^.son; + If InvDummy^.nodeType=ConstNode Then + begin + if InvDummy^.Value=0.0 then + Raise EDiv0.Create(SExprInvMsg); + Expr^.NodeType:=ConstNode; + Expr^.Value:=1/InvDummy^.Value; + Dispose(InvDummy); + end + else + if InvDummy^.nodetype=iconstnode then + begin + if InvDummy^.iValue=0 then + Raise EDiv0.Create(SExprinvmsg); + If (InvDummy^.iValue=1) or (InvDummy^.iValue=-1) then + begin + expr^.NodeType:=Iconstnode; + Expr^.iValue:=InvDummy^.iValue; + Dispose(InvDummy); + end; + end; + end; + else {IE check in EvaluateFunction} + if (expr^.son^.nodetype=constnode) and (Expr^.fun<>faculx) then {Other functions, only func(real) is simplified} + begin + val1:=EvaluateFunction(expr^.fun,Expr^.son^.value); + dispose(expr^.son); + expr^.nodetype:=constnode; + expr^.value:=val1; + end; + end; {Case 2} + end; + + Func2Node : begin + internalSimplify(expr^.son2left); + internalSimplify(expr^.son2right); + case expr^.fun2 of + powerx : begin + TmpVal:=Setupoperation(powo,SimplificationLevel,true,true); + if TmpVal>1 then + begin + If tmpval=1 then + begin + if ival2<0 then {integer x^-y -> inv (x^y)} + begin + new(invdummy); + invdummy^.nodetype:=iconstnode; + invdummy^.ivalue:=ipower(ival1,-ival2); + expr^.nodetype:=funcnode; + expr^.son:=invdummy; + end + else + expr^.ivalue:=ipower(ival1,ival2); + end; + end; + end; + stepx : begin + {N/I yet} + end; + arctan2x : begin + TmpVal:=Setupoperation(powo,SimplificationLevel,false,true); + if tmpval>1 then {1 is integer, which we don't do} + begin + dispose(expr^.right); + dispose(expr^.left); + expr^.nodetype:=constnode; + expr^.value:=arctan2(ival2,ival1); + end; + end; + hypotx :begin + TmpVal:=Setupoperation(powo,SimplificationLevel,false,true); + if tmpval>1 then {1 is integer, which we don't do} + begin + dispose(expr^.right); + dispose(expr^.left); + expr^.nodetype:=constnode; + expr^.value:=hypot(ival2,ival1); + end; + end; + lognx: begin + TmpVal:=Setupoperation(powo,SimplificationLevel,false,true); + if tmpval>1 then {1 is integer, which we don't do} + begin + dispose(expr^.right); + dispose(expr^.left); + expr^.nodetype:=constnode; + expr^.value:=hypot(ival2,ival1); + end; + end; + else + ExprInternalError(3,ORD(expr^.fun2)); + end; + end; +{ else + ExprInternalError(4,ORD(expr^.nodetype));} + end; {Case 1} +end; + +begin + internalsimplify(exprtree); + InfixClean:=False; {Maybe changed} +end; + +procedure TExpression.SymbolSubst(ToSubst,SubstWith:String); + +procedure InternalSubst(expr:Pnode); + +begin + if Expr<>NIL THEN + case Expr^.NodeType of + VarNode: if Expr^.Variable=ToSubst then + Expr^.Variable:=SubstWith; + calcnode: begin + InternalSubst(Expr^.left); + InternalSubst(Expr^.right); + end; + funcnode: InternalSubst(Expr^.son); + func2node: begin + InternalSubst(Expr^.son2left); + InternalSubst(Expr^.son2right); + end; + end; +end; + +begin + InternalSubst(ExprTree); +end; + +function TExpression.SymbolicValueNames:TStringList; + +var TheList:TStringList; + +procedure InternalSearch(expr:Pnode); + +begin + if Expr<>NIL THEN {NIL shouldn't be allowed, and signals corruption. IE? Let it die?} + case Expr^.NodeType of + VarNode: begin + Expr^.Variable:=UpCase(Expr^.Variable); + TheList.Add(Expr^.Variable); + end; + calcnode: begin + InternalSearch(Expr^.left); + InternalSearch(Expr^.right); + end; + funcnode: InternalSearch(Expr^.son); + func2node: begin + InternalSearch(Expr^.son2left); + InternalSearch(Expr^.son2right); + end; + end; +end; + +begin + TheList:=TStringList.Create; + TheList.Sorted:=TRUE; + Thelist.Duplicates:=DupIgnore; + InternalSearch(ExprTree); + Result:=TheList; +end; + +function TExpression.Taylor(Degree:ArbInt;const x,x0:String):TExpression; +{Taylor(x,x0)=sum(m,0,degree, d(f)/d(x))(x0)/ m! * (x-x0)^m) + += f(x0)+ (x-x0)/1! * df/d(x) + (x-x0)^2 / 2! * d^2(f)/d^2(x) + + (x-x0)^3 / 3! * d^3(f)/d^3(x) + .... +} + +Var TaylorPol : TExpression; { The result expression} + Root, + Tmp,Tmp2, + tmp3,tmp4,tmp5 : pnode; { Always have a nice storage of pointers. + Used to hold all intermediate results} + I,facul : ArbInt; { Loop counters and faculty term} + +begin + TaylorPol:=TExpression.EmptyCreate; {New expression} + TaylorPol.ExprTree:=CopyTree(ExprTree); {make a copy of the parsetree} + TaylorPol.SymbolSubst(X,X0); {subst x by x0. All occurances + of f() refer to x0, not x} + if Degree>0 then {First term only? Or nonsense (negative?)} + {Then ready. 0th term only.} + begin {Start preparing easy creation of higher terms} + tmp2:=newcalc(subo,newvar(x), + newvar(x0)); {tmp2= x-x0 needed separately for first term} + tmp4:=Newiconst(5); {exponent for x-x0, "a" need to keep a reference} + tmp3:=newcalc(powo,tmp2,tmp4); {tmp3= (x-x0)^a} + tmp5:=newiconst(5); {faculty value, "b"=m! also keep a reference for later modification } + tmp3:=Newcalc(dvdo,tmp3,tmp5); {tmp3= (x-x0)^a / b a and b can be changed} + facul:=1; {Calculate faculty as we go along. Start with 1!=1} + root:=TaylorPol.ExprTree; {0th term} + tmp:=root; {term that needs to be differentiated per iteration} + for i:=1 to Degree do + begin + facul:=Facul*i; {Next faculty value 1!*1 =1 btw :_)} + tmp:=intderive(x0,tmp); {Differentiate f^n(x0) to f^(n+1)(x0)} + If I=1 then {first term is special case. No power } + tmp2:=NewCalc(mulo,CopyTree(tmp2),tmp) {or faculty needed (^1 and 1!)} + else + begin + tmp5^.Ivalue:=facul; {Higher terms. Set faculty} + tmp4^.ivalue:=i; {Set exponent (=a) of (x-x0)^a} + tmp2:=NewCalc(mulo,CopyTree(tmp3),tmp); {multiplicate derivative with (x-x0)^a/b term} + end; + root:=NewCalc(addo,root,tmp2); {String all terms together} + end; + DisposeExpr(tmp3); {Is only CopyTree()'d, not in new expression} + TaylorPol.Exprtree:=root; {Set result} + end; + Result:=TaylorPol; +end; + +function TExpression.Newton(x:String):TExpression; +{ + f(x) +Newton(x)=x- ---- + f'(x) +} + +Var NewtonExpr : TExpression; { The result expression} + Root, + Tmp,Tmp2, + tmp3,tmp4,tmp5 : pnode; { Always have a nice storage of pointers. + Used to hold all intermediate results} + I,facul : ArbInt; { Loop counters and faculty term} + +begin + NewtonExpr:=TExpression.EmptyCreate; {New expression} + + {Should I test for constant expr here?} + + Tmp:=CopyTree(ExprTree); {make a copy of the parsetree + for the f(x) term} + Tmp2:=intDerive(x,tmp); { calc f'(x)} + Tmp3:=NewVar(x); { Create (x)} + Tmp:=Newcalc(dvdo,tmp,tmp2); { f(x)/f'(x)} + tmp:=Newcalc(subo,tmp3,tmp); { x- f(x)/f'(x)} + + {We built the above expression using a copy of the tree. + So no pointers into self.exprtree exist. We can now safely assign it + to the new exprtree} + NewtonExpr.ExprTree:=tmp; + NewtonExpr.SimplifyConstants; {Simplify if f'(x)=constant, and + kill 0*y(x) terms} + Result:=NewtonExpr; +end; + + +{ + $Log$ + Revision 1.1 2002/12/15 21:01:26 marco + Initial revision + +} + diff --git a/packages/symbolic/src/symbolic.pas b/packages/symbolic/src/symbolic.pas new file mode 100644 index 0000000000..a62c294c51 --- /dev/null +++ b/packages/symbolic/src/symbolic.pas @@ -0,0 +1,493 @@ +unit Symbolic; +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Base types for expression trees, and some small procs to create them. + + 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. + +Seems not to have memory leaks atm. If you experience them, check procedure +newcalc first. +} + +interface + +{$ifdef FPC} + {$Mode ObjFpc} +{$ENDIF} + +Uses Math,Classes,Sysutils; + +Const + VLIWIncr = 40; { Initial size and increment of VLIW array} + DelphiMaxOps = 5000; { Unused for FPC. Max records in VLIW array + FPC: 2 Gb/sizeof(vliwevalword).} + +Type {Should be somewhere in the JCLMath or even in JCLtypes unit} + {$ifdef FPC} + ArbFloat = float; {Float is set to mathtype used by FPC Math unit} + ArbInt = longint; + {$else} + ArbFloat = extended; + ArbInt = Integer; + {$endif} + + calcop=(addo,subo,mulo,dvdo,powo); {real operators} + + FuncOp=(cosx,sinx,tanx,sqrx,sqrtx,expx,lnx,invx,minus,cotanx,arcsinx,arccosx, + arctanx,sinhx,coshx,tanhx,arcsinhx,arccoshx,arctanhx,log10x, + log2x,lnxpix,faculx,arctan2x,stepx,powerx,hypotx,lognx,unknown0, + unknown1,unknown2,unknown3,unknown4); + {functions, both one and two parameter ones. Including pseudo function + minus} + +CONST UnknownTokens : array[0..4] OF FuncOp =(unknown0,unknown1,unknown2, + unknown3,unknown4); +TYPE + Operation=(VarNode,ConstNode,iconstnode,CalcNode,FuncNode,func2node,VLIWVar,CustomNode); + TFlagsEnum=(ExprIsConstant); {ExprIsConstant signals that this node of + the tree and deeper can evaluate to a single + float constant} + + TFlags = SET OF TFlagsEnum; + + pnode =^treenode; + treenode=record + Flags : TFlags; + case nodetype:operation of + iconstnode: (ivalue:ArbInt); + VarNode: (variable:string[11]); + VLIWVar: (vliwindex:ArbInt); {^float?} + ConstNode: (value:ArbFloat); + CalcNode: (op:calcop;left,right:pnode); + FuncNode: (fun:funcop;son:pnode); + Func2Node: (fun2:funcop;son2left,son2right:pnode); + CustomNode: (Indent:Longint); + end; + + ERPNStack = Class(Exception); {All RPN stack problems category} + EIError = Class(Exception); {All internal errors. Most often + these are raised when unknown + function enumerations are found} + EDiv0 = Class(Exception); {Division by zero, but RPN, not processor!} + + TBaseExpression = class + protected + ExprTree : pnode; + function NewConst(value:ArbFloat):pnode; + function NewiConst(value:ArbInt):pnode; + function NewCalc(op:calcop;left,right:pnode):pnode; + function CopyTree(p :pnode):pnode; + function NewFunc(fun:funcop;son:pnode):pnode; overload; + function NewFunc(fun:funcop;son,son2:pnode):pnode; overload; + function NewVar(variable:string):pnode; + procedure DisposeExpr(p:pnode); + end; + + EParserStack = class(ERPNStack); {RPN stack under/overflow.} + EParserIE = class(EIError); {Internal error} + + TBaseExprParser= class(TBaseExpression) + public + function InFixToParseTree(Expr : String;VAR RPNexpr: String):pnode; virtual; + function ParseTreeToRPN (expr:pnode):string; virtual; + function ParseTreeToInfix(expr:pnode):string; virtual; + end; + + TEvaluator= CLASS; + + EFaculNotInt = Class(exception); {Faculty on a real value deviating from an integer value by more than 0.01} + EExprIE = Class(EIerror); + ENotInt = Class(exception); + ENotFloat = Class(Exception); + + TExpression = class(TBaseExprParser) + protected + InfixClean : Boolean; + InfixCache : String; + Evaluator : TEvaluator; + EvaluatorUpToDate : Boolean; + function GetInfix:String; + function GetRPN:String; + procedure Simpleop(expr:TExpression;oper:calcop); + function Simpleopwithresult(expr:TExpression;oper:calcop):TExpression; + Function IntDerive(const derivvariable:String;theexpr:pnode):pnode; + Function GetIntValue:LongInt; + Procedure SetIntValue(val:Longint); + Function GetFloatValue:ArbFloat; + Procedure SetFloatValue(val:ArbFloat); + Procedure UpdateConstants; {Kind of integrity check} + public + SimplificationLevel : Longint; + CONSTRUCTOR Create(Infix:String); + CONSTRUCTOR EmptyCreate; + DESTRUCTOR Destroy; override; + + Procedure SetNewInfix(Infix:String); + Function Derive(derivvariable:String):TExpression; + procedure SymbolSubst(ToSubst,SubstWith:String); + function SymbolicValueNames:TStringList; + function Taylor(Degree:ArbInt;const x,x0:String):TExpression; + function Newton(x:String):TExpression; + + procedure SimplifyConstants; + + function add(Expr:TExpression):TExpression; + function dvd(Expr:TExpression):TExpression; + function mul(Expr:TExpression):TExpression; + function power(Expr:TExpression):TExpression; + function sub(Expr:TExpression):TExpression; + + procedure Addto(Expr:TExpression); + procedure Divby(Expr:TExpression); + procedure RaiseTo(Expr:TExpression); + procedure SubFrom(Expr:TExpression); + procedure Times(Expr:texpression); + property InfixExpr: string read GetInfix write SetNewInfix; + property RpnExpr: string read GetRPN; + property ValueAsInteger:longint read GetIntValue write SetIntvalue; {Default?} + property ValueAsFloat:arbfloat read GetFloatValue write SetFloatValue; + end; + + + VLIWWordtype= (avariable,anoperation, afunction, + afconstant, aiconstant,placeholder); + + { RPN operators or functions with two arguments are the same.} + vliwop2=(addv,subv,mulv,dvdv,powv,arctan2v,stepv,hypotv,lognv); + + pArbFloat = ^ArbFloat; + {$ifdef FPC} + pVliwArr = ^VLIWEvalWord; + {$else} {Delphi doesn't allow referencing of ^simpletype as array, + but does allow it for ^ array of VLIWEvalWord} + TVLIWArr = array[0..DelphiMaxOps] of VLiwEvalWord; + pVliwArr = ^TVliwArr; + {$ENDIF} + + pVLIWEvalWord = ^VLIWEvalWord; + VLIWEvalword = record + case VLIWEntity : VLIWWordType OF + AVariable : (IndexOfVar : ArbInt); + AnOperation: (op:vliwop2); {2 arguments} + AFunction : (fun1:funcop); {functions with one argument} + AiConstant : (ivalue:ArbInt); + AfConstant : (value:ArbFloat); + placeholder: (IndexOfConstant:ArbInt) ; + end; + + TEvaluatorNotEnoughVariables=class(Exception); {Not enough variables passed to Evaluate} + TEvaluatorStackException =class(ERPNStack); {RPN Stack over/under flow} + TEvaluatorBadConstant =class(Exception); {Constant value not specified} + TEvaluatorIE =class(Exception); {Internal error. Probably something out of sync.} + + TEvaluator = Class {Only needs the notion of a pnode } + Private + VariableName : TStringList; + ConstantValue : TList; + ConstantNames : TStringList; + MaxStack, + VLIWCount, + VLIWAlloc : ArbInt; + VLIWRPNExpr : pVLIWArr; + public + function Evaldepth:longint; + PROCEDURE SetConstant(Name:String;Value:ArbFloat); + CONSTRUCTOR Create(VariableList:TStringList;Expression:pnode); + CONSTRUCTOR Create(VariableList:TStringList;Expression:TExpression); + DESTRUCTOR Destroy; override; + Procedure TreeToVLIWRPN(expr:pnode); + function Evaluate(const variables:Array of ArbFloat):ArbFloat; + {$IFDEF DebugDump} + procedure debugger; + procedure WriteVliw(p:VLIWEvalWord); + + {$ENDIF} + end; + +{ + Structures used to index a pnode tree to identify terms. + + PTerms = ^TTerms; + PtermNode=^TTermNode; + TtermNode= record + NrTerms :ArbInt; + Terms : Array[0..499] of PNode; + end; + TTerms = record + NrTerms : ArbInt; + Terms: Array[0..499] of PtermNode; + end; +} +const InfixOperatorName : array[addo..powo] of char= ('+','-','*','/','^'); + FunctionNames : array[cosx..lognx] of string[8]=( + 'cos','sin','tan','sqr','sqrt','exp','ln','inv','-', + 'cotan','arcsin','arccos','arctan','sinh', + 'cosh','tanh','arcsinh','arccosh','arctanh', + 'log10','log2','lnxp1','!','arctan2', + 'step','power','hypot','logn'); + FunctionNamesUpper: array[cosx..lognx] of string[8]=( + 'COS','SIN','TAN','SQR','SQRT','EXP','LN','INV','-', + 'COTAN','ARCSIN','ARCCOS','ARCTAN','SINH', + 'COSH','TANH','ARCSINH','ARCCOSH','ARCTANH', + 'LOG10','LOG2','LNXP1','!','ARCTAN2', + 'STEP','POWER','HYPOT','LOGN'); + LenFunctionNames : array[cosx..lognx] of longint= + (3,3,3,3,3,3,2,3,1,5,6,6,6,4,4,4,7,7,7,5,4,5,1,7,4,5,5,4); + +{$I exprstrs.inc} + +implementation + + +{newconst and newiconst are overloaded in FPC} + +function TBaseExpression.NewConst(value:ArbFloat):pnode; +{Generate a new node for a floating point constant} + +var t : pnode; + +begin + new(t); + t^.nodetype:=constnode; + t^.value:=value; + t^.Flags:=[ExprIsConstant]; + NewConst:=T; +end; + +function TBaseExpression.NewiConst(value:ArbInt):pnode; +{Generate a new node for integer constant} + +var t : pnode; + +begin + new(t); + t^.nodetype:=iconstnode; + t^.ivalue:=value; + t^.Flags:=[ExprIsConstant]; + NewiConst:=T; +end; + +procedure TBaseExpression.DisposeExpr(p:pnode); +{Recursively kill expression tree} + +begin + IF p<>NIL THEN + begin + case p^.nodetype of + CalcNode : begin + DisposeExpr(p^.right); + DisposeExpr(p^.left); + end; + FuncNode : DisposeExpr(p^.son); + end; + Dispose(p); + end; +end; + +function TBaseExpression.NewCalc(op:calcop;left,right:pnode):pnode; +{Create NewCalc node. Left and Right may be nil because +to avoid introducing empty nodes, the deriv() +function may return NIL's, which are to be treated as newiconst(0); + +Also one of the functions most likely to have memory leaks +} + +function isintegerone(testme:pnode) : boolean; +begin + Isintegerone:=(testme^.nodetype=iconstnode) and (testme^.ivalue=1); +end; + +var t : pnode; + +begin + if op=powo then + begin + if right=NIL then {x^0 =1 for every X} + begin + DisposeExpr(left); + newcalc:=newiconst(1); + exit; + end; + if left=NIL THEN { 0^y = 0 except for y=0, but that is} + begin { covered above} + DisposeExpr(right); + NewCalc:=NIL; + exit; + end; + if IsIntegerone(left) then {x^1 =x} + begin + DisposeExpr(left); + NewCalc:=right; + exit; + end; + If IsIntegerone(right) then { 1^y=1} + begin + DisposeExpr(left); + NewCalc:=right; + exit; + end; + end; {generate a plain power node for all other cases} + if left=NIL then + begin + if (right=nil) or (op=mulo) or (op=dvdo) then { 0*0, 0*t or 0/t =0} + begin { We have no way to check T for nul} + IF Right<>NIL then + DisposeExpr(Right); + NewCalc:=NIL; + exit; + end; + if op=addo then { Don't generate a calc node for 0+x, but return x} + begin + NewCalc:=right; + exit; + end; + new(t); + t^.nodetype:=funcnode; { 0-x = minus(x) } + t^.fun:=minus; + t^.son:=right; + t^.flags:=[]; + if ExprIsConstant in t^.son^.flags then + include(t^.flags,ExprIsConstant); + NewCalc:=T; + exit; + end; + if right=NIL then + begin + if (left=nil) or (op=mulo) or (op=dvdo) then { 0*0, 0*t or 0/t =0} + begin + IF left<>NIL then + disposeExpr(Left); + NewCalc:=Nil; + exit; + end; + NewCalc:=Left; { for x-0 or x+0, simply return 0} + exit; + end; + + If ((op=mulo) or (op=dvdo)) and isintegerone(right) then { simplify t*1 and t/1} + begin + DisposeExpr(right); + NewCalc:=Left; + exit; + end; + if (op=mulo) and isintegerone(left) then { simplify 1*t} + begin + DisposeExpr(left); + NewCalc:=right; + exit; + end; + new(t); + t^.nodetype:=calcnode; + t^.op:=op; + t^.left:=left; + t^.right:=right; + t^.Flags:=[]; + if (ExprIsConstant In T^.Left^.Flags) and (ExprIsConstant In T^.Right^.Flags) then + include(t^.flags,ExprIsConstant); + newcalc:=t; +end; + +function TBaseExpression.CopyTree(p :pnode):pnode; + +var newtree : pnode; + +begin + new(newtree); + move(p^,Newtree^,sizeof(treenode)); + if newtree^.nodetype=CalcNode then + begin + newtree^.left:=CopyTree(p^.left); + newtree^.right:=CopyTree(p^.right); + end + else + if newtree^.nodetype=FuncNode then + newtree^.son:=CopyTree(p^.son); + CopyTree:=NewTree; +end; + +function TBaseExpression.NewFunc(fun:funcop;son:pnode):pnode; + +var t : pnode; + +begin + IF son<>nil then + begin + new(t); + t^.nodetype:=funcnode; + t^.fun:=fun; + t^.son:=son; + t^.flags:=[]; + if ExprIsConstant IN son^.flags then + Include(t^.flags,ExprIsConstant); + NewFunc:=T; + end + else + NewFunc:=NIL; +end; + +function TBaseExpression.NewFunc(fun:funcop;son,son2:pnode):pnode; + +var t : pnode; + +begin + new(t); + t^.nodetype:=func2node; + t^.fun:=fun; + t^.son2Left:=son; + t^.son2Right:=son2; + t^.flags:=[]; + if(ExprIsConstant IN son^.flags) and (ExprIsConstant IN son2^.flags) then + Include(t^.flags,ExprIsConstant); + NewFunc:=T; +end; + +{function TBaseExpression.NewFunc(fun:funcop;unknownIdent:longint):pnode; + +var t : pnode; + +begin + new(t); + t^.nodetype:=func2node; + t^.fun:=fun; + t^.son2Left:=son; + t^.son2Right:=son2; + t^.flags:=[]; + if(ExprIsConstant IN son^.flags) and (ExprIsConstant IN son2^.flags) then + Include(t^.flags,ExprIsConstant); + NewFunc:=T; +end;} + + + +function TBaseExpression.NewVar(variable:string):pnode; + +var p :pnode; + +begin + new(p); + p^.nodetype:=varnode; + p^.variable:=variable; + p^.Flags:=[]; + newvar:=p; +end; + +{$I parsexpr.inc} {Parser categories} +{$I symbexpr.inc} {standard symbolic manip} +{$I teval.inc} +{$I rearrang.inc} + +end. +{ + $Log$ + Revision 1.1 2002/12/15 21:01:26 marco + Initial revision + +} diff --git a/packages/symbolic/src/teval.inc b/packages/symbolic/src/teval.inc new file mode 100644 index 0000000000..d027c2c260 --- /dev/null +++ b/packages/symbolic/src/teval.inc @@ -0,0 +1,722 @@ +{ + $ id: $ + Copyright (c) 2000 by Marco van de Voort (marco@freepascal.org) + member of the Free Pascal development team + + See the file COPYING.FPC, included in this distribution, + for details about the copyright. (LGPL) + + Evaluator class implementation. Evaluates a parsetree expression in + a way optimized for fast repeated evaluations of the same expression + with different variables and constants. + + 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. + + ********************************************************************** +} + +{$IFDEF DebugDump} +procedure TEvaluator.WriteVliw(p:VLIWEvalWord); forward; +{$ENDIF} + +Procedure TEvalInternalError(A,B:ArbInt); + +VAR S,S2 : String; + +begin + Str(ORD(A),S); + Str(ORD(B),S2); + Raise TEvaluatorIE.Create(SEvalIE+S+' '+S2); +end; + + +CONSTRUCTOR TEvaluator.Create(VariableList:TStringList;Expression:pnode); +{Constructor. Stringlist to set the order of variables in the function while +xconverting the pnode tree to a TEvaluator structure. This avoids any string +parsing during a real evaluation, and moves all stringparsing to the setup. + +So for Func(x,y,z) Variablelist contains ('x','y','z') in that order. +} + +begin + VariableName:=VariableList; + ConstantNames:=TStringList.Create; + ConstantValue:=TList.Create; + Getmem(VLIWRPnExpr,SIZEOF(VLIWEvalWord)*VLIWIncr); + VLIWCount:=0; + VLIWAlloc:=VLIWIncr; + MaxStack :=0; + TreeToVLIWRPN(Expression); +end; + +CONSTRUCTOR TEvaluator.Create(VariableList:TStringList;Expression:TExpression); +{Overloaded, same as other constructor. (which it even calls), except that +it has a TExpression as argument. + +Besides that it gets the pnode from the TExpression, it sets the +TExpression.Evaluator to self, and a flag to set in the TExpression that its +assiociated TEvaluator is up to date with the TExpression. +} + +begin + Self.Create(VariableList,Expression.ExprTree); + Expression.Evaluator:=Self; + Expression.EvaluatorUpToDate:=TRUE; +end; + +DESTRUCTOR TEvaluator.Destroy; + +VAR I : LONGINT; + TmpList : Tlist; + +begin + VariableName.Free; + ConstantNames.Free; + IF ConstantValue.Count>0 THEN + FOR I:=0 to ConstantValue.Count -1 DO + begin + TmpList:=TList(ConstantValue[I]); + TmpList.Free; + end; + ConstantValue.Free; + If VLIWAlloc>0 THEN + FreeMem(VLIWRPNExpr,VLIWAlloc*SIZEOF(VLIWEvalWord)); + inherited Destroy; +end; + +PROCEDURE TEvaluator.SetConstant(Name:String;Value:ArbFloat); + +Var Ind,I : Longint; + TmpList : TList; + +begin + Ind:=ConstantNames.IndexOf(Name); + If Ind<>-1 THEN + begin + TmpList:=TList(ConstantValue[Ind]); + I:=TmpList.Count; + If I>0 Then + For I:=0 TO TmpList.Count-1 DO + begin + PVLIWEvalWord(TmpList[I])^.VLIWEntity:=AfConstant; + PVLIWEvalWord(TmpList[I])^.Value:=Value; + end; + end; +end; + +procedure TEvaluator.TreeToVLIWRPN(expr:pnode); + +procedure CheckVLIWArr; + +begin + if VLIWCount=VLIWAlloc then + begin + ReAllocMem(VLIWRPNExpr,(VLIWAlloc+VLIWIncr)*SIZEOF(VLIWEvalWord)); + Inc(VLIWAlloc,VLIWIncr); + end; +end; + +procedure searchTree(Tree:pnode); + +var Ind : ArbInt; + TmpList : TList; + +begin + if tree<>nil then + case Tree^.nodetype of + VarNode : begin + {some variable or constant. First: Variable?} + Ind:=VariableName.IndexOf(Tree^.Variable); + If Ind<>-1 then + begin {We have identified a variable} + CheckVLIWArr; {Make sure there is at least room for one variable} + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AVariable; + IndexOfVar:=Ind; + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + inc(VLIWCount); + end + else + begin {We have a constant} + ind:=ConstantNames.IndexOf(Tree^.Variable); + if Ind=-1 then + begin {That doesn't exist. Make sure it exists} + ConstantNames.Add(Tree^.Variable); + TmpList:=TList.Create; + ConstantValue.Add(TmpList); + end + else + begin + TmpList:=tlist(ConstantValue[Ind]); + end; + + {Create the VLIW record} + CheckVLIWArr; + + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=Placeholder; + IndexOfConstant:=255; + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + {Store a pointer to the VLIW record to be able to change the + constant} + TmpList.Add(pointer(VLIWCount)); {Can't pick pointer here, due to realloc} + inc(VLIWCount); + end; {Ind<>-1} + end; + ConstNode: begin + + CheckVLIWArr; + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AfConstant; + Value:=tree^.value; + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + inc(VLIWCount); + end; + iconstnode: begin + CheckVLIWArr; + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AiConstant; + IValue:=tree^.ivalue; + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + inc(VLIWCount); + end; + CalcNode : begin + + CheckVLIWArr; + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AnOperation; + op:=vliwop2(ord(Tree^.op)); + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + inc(VLIWCount); + SearchTree(tree^.left); + SearchTree(tree^.right); + end; + FuncNode: begin + + CheckVLIWArr; + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AFunction; + fun1:=Tree^.fun; + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + inc(VLIWCount); + SearchTree(tree^.son); + + end; + Func2Node: begin + + CheckVLIWArr; + WITH VLIWRPNExpr[VLIWCount] do + begin + VLIWEntity:=AnOperation; + if tree^.fun2=powerx then + op:=VLIWOp2(powo) + else + if tree^.fun2 >powerx then + op:=vliwop2(ord(powv)+ord(tree^.fun2)-ord(arctan2x)) + else + op:=vliwop2(1+ord(powv)+ord(tree^.fun2)-ord(arctan2x)) + end; + {$IFDEF DebugDump} + WriteVliw(VLIWRPNExpr[VLIWCOUNT]); + {$ENDIF} + + inc(VLIWCount); + SearchTree(tree^.son2left); + SearchTree(tree^.son2right); + end + else + TEvalInternalError(4,ORD(Tree^.nodetype )); + end; +end; + +Procedure FixLists; +{We added constants as VLIWCount indexes. To speed up we convert them to +pointers. We couldn't do that directly as a consequence of the ReAlloc.} + +VAR I,J : Longint; + TmpList : TList; + +begin + I:=ConstantValue.Count; + IF I>0 THEN + FOR J:=0 TO I-1 DO + begin + TmpList:=TList(ConstantValue[J]); + IF (Tmplist<>NIL) and (TmpList.Count>0) then + for I:=0 TO TmpList.Count-1 DO + TmpList[I]:=@VLIWRPNExpr[longint(TmpList[I])]; + end; +end; + +begin + VLIWCount:=0; + SearchTree(expr); + FixLists; +end; + +function TEvaluator.Evaluate(const variables:Array of ArbFloat):ArbFloat; +{The one that does the work} + +CONST StackDepth=50; + + var TheArray : pVLIWEvalWord; + VLIWRecs : Longint; + RPNStack : ARRAY[0..StackDepth] OF ArbFloat; + I, + RPNPointer : Longint; +// S : ansiString; + +procedure push(Val:ArbFloat); {$IFDEF FPC} InLine; {$endif} + +begin + IF RPNPointer=StackDepth THEN + RAISE TEvaluatorStackException.Create(SEvalStackDepthExceeded); + RPNStack[RpnPointer]:=Val; + INC(RPNPointer); +end; + +begin + VLIWRecs:=VariableName.Count; + if (High(Variables)+1)<>VLIWRecs then + Raise TEvaluatorNotEnoughVariables.Create(SeValBadNumberOfVars); + RPNPointer:=0; + VliwRecs:=VliwCount-1; + TheArray:=@VLIWRPNExpr[VLIWRecs]; + REPEAT + {$IFDEF DebugMe} + Writeln(VliwRecs,' ',ord(TheArray^.VLIWEntity)); + {$ENDIF} + TheArray:=@VLIWRPNExpr[VLIWRecs]; + CASE TheArray^.VLIWEntity OF + AVariable : begin + {$IFDEF DebugMe} + Writeln('var:', TheArray^.IndexOfVar); + {$ENDIF} + Push(Variables[TheArray^.IndexOfVar]); + end; + + AfConstant : begin + {$IFDEF DebugMe} + Writeln('FP value:', TheArray^.value); + {$ENDIF} + Push(TheArray^.Value); + end; + AiConstant : begin + {$IFDEF DebugMe} + Writeln('Int value:', TheArray^.ivalue); + {$ENDIF} + Push(TheArray^.iValue); + end; + Placeholder: begin + // RAISE TEvaluatorBadConstant.Create(ConstantNames[TheArray^.IndexOfConstant]); + end; + AnOperation: begin + {$IFDEF DebugMe} + Writeln('Operator value:', ord(TheArray^.op)); + {$ENDIF} + Case TheArray^.Op of + addv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]+RPNStack[RPNPointer-1]; + end; + subv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]-RPNStack[RPNPointer-1]; + end; + mulv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]*RPNStack[RPNPointer-1]; + end; + dvdv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]/RPNStack[RPNPointer-1]; + end; + powv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=Power(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + arctan2v : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=ArcTan2(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + stepv : begin + Dec(RPNPointer); + If RPNStack[RPNPointer-1]>RPNStack[RPNPOINTER] THEN + RPNStack[RPNPointer-1]:=1.0 + else + RPNStack[RPNPointer-1]:=0.0; + end; + hypotv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=hypot(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + lognv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=logn(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + else + TEvalInternalError(1,ORD(TheArray^.op)); + end; + end; + AFunction : begin + {$IFDEF DebugMe} + Writeln('function value:', ord(TheArray^.fun1)); + {$ENDIF} + + Case TheArray^.Fun1 of + cosx: RPNStack[RPNPointer-1]:=cos(RPNStack[RPNPointer-1]); + sinx: RPNStack[RPNPointer-1]:=sin(RPNStack[RPNPointer-1]); + tanx: RPNStack[RPNPointer-1]:=tan(RPNStack[RPNPointer-1]); + sqrx: RPNStack[RPNPointer-1]:=sqr(RPNStack[RPNPointer-1]); + sqrtx: RPNStack[RPNPointer-1]:=sqrt(RPNStack[RPNPointer-1]); + expx: RPNStack[RPNPointer-1]:=exp(RPNStack[RPNPointer-1]); + lnx: RPNStack[RPNPointer-1]:=ln(RPNStack[RPNPointer-1]); + invx: RPNStack[RPNPointer-1]:=1/RPNStack[RPNPointer-1]; + minus: RPNStack[RPNPointer-1]:=-RPNStack[RPNPointer-1]; + cotanx: RPNStack[RPNPointer-1]:=cotan(RPNStack[RPNPointer-1]); + arcsinx: RPNStack[RPNPointer-1]:=arcsin(RPNStack[RPNPointer-1]); + arccosx: RPNStack[RPNPointer-1]:=arccos(RPNStack[RPNPointer-1]); + arctanx: RPNStack[RPNPointer-1]:=arctan(RPNStack[RPNPointer-1]); + sinhx: RPNStack[RPNPointer-1]:=sinh(RPNStack[RPNPointer-1]); + coshx: RPNStack[RPNPointer-1]:=cosh(RPNStack[RPNPointer-1]); + tanhx: RPNStack[RPNPointer-1]:=tanh(RPNStack[RPNPointer-1]); + arcsinhx: RPNStack[RPNPointer-1]:=ArcSinh(RPNStack[RPNPointer-1]); + arccoshx: RPNStack[RPNPointer-1]:=ArcCosh(RPNStack[RPNPointer-1]); + arctanhx: RPNStack[RPNPointer-1]:=ArcTanh(RPNStack[RPNPointer-1]); + log10x: RPNStack[RPNPointer-1]:=Log10(RPNStack[RPNPointer-1]); + log2x: RPNStack[RPNPointer-1]:=Log2(RPNStack[RPNPointer-1]); + lnxpix: RPNStack[RPNPointer-1]:=lnxp1(RPNStack[RPNPointer-1]); + else + TEvalInternalError(2,ORD(TheArray^.fun1)); + end; + end; + else + TEvalInternalError(3,ORD(TheArray^.VLIWEntity)); + end; + {$Ifdef DebugDump} + Writeln('RecordNo: ',VliwRecs); + IF RPNPointer>0 then + begin + Writeln('RPN stack'); + for I:=0 TO RpnPointer-1 DO + Writeln(I:2,' ',RpnStack[I]); + end; + {$Endif} + dec(TheArray); + dec(VliwRecs); + UNTIL VliwRecs<0; + Result:=RPNStack[0]; +end; + +{ +function TEvaluator.i387Evaluate(const variables:Array of ArbFloat):ArbFloat; +{This should become the really *cool* one in time. +Still experimental though. + +Current status: +- Can be entirely FP, but isn't allowed to use more that 4 stack-pos then. +- Math's ARCCOS ARCCOSH ARCSIN ARCSINH ARCTAN2 ARCTANH COSH COTAN HYPOT LNXP1 LOG10 + LOG2 LOGN POWER SINH TAN TANH + and System.Exp are forbidden because they use stackroom internally. + This is a problem, because specially Exp() is much too common. + } + +CONST StackDepth=50; + + var TheArray : pVLIWEvalWord; + VLIWRecs : Longint; + RPNStack : ARRAY[0..StackDepth] OF ArbFloat; + I, + RPNPointer : Longint; + +procedure push(Val:ArbFloat); {$IFDEF FPC} InLine; {$endif} + +begin + IF RPNPointer=StackDepth THEN + RAISE TEvaluatorStackException.Create(SEvalStackDepthExceeded); + RPNStack[RpnPointer]:=Val; + INC(RPNPointer); +end; + +begin + VLIWRecs:=VariableName.Count; + if (High(Variables)+1)<>VLIWRecs then + Raise TEvaluatorNotEnoughVariables.Create(SeValBadNumberOfVars); + RPNPointer:=0; + VliwRecs:=VliwCount-1; + TheArray:=@VLIWRPNExpr[VLIWRecs]; + REPEAT + {$IFDEF DebugMe} + Writeln(VliwRecs,' ',ord(TheArray^.VLIWEntity)); + {$ENDIF} + TheArray:=@VLIWRPNExpr[VLIWRecs]; + CASE TheArray^.VLIWEntity OF + AVariable : begin + {$IFDEF DebugMe} + Writeln('var:', TheArray^.IndexOfVar); + {$ENDIF} + Push(Variables[TheArray^.IndexOfVar]); + end; + + AfConstant : begin + {$IFDEF DebugMe} + Writeln('FP value:', TheArray^.value); + {$ENDIF} + Push(TheArray^.Value); + end; + AiConstant : begin + {$IFDEF DebugMe} + Writeln('Int value:', TheArray^.ivalue); + {$ENDIF} + Push(TheArray^.iValue); + end; + Placeholder: begin + // RAISE TEvaluatorBadConstant.Create(ConstantNames[TheArray^.IndexOfConstant]); + end; + AnOperation: begin + {$IFDEF DebugMe} + Writeln('Operator value:', ord(TheArray^.op)); + {$ENDIF} + Case TheArray^.Op of + addv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]+RPNStack[RPNPointer-1]; + end; + subv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]-RPNStack[RPNPointer-1]; + end; + mulv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]*RPNStack[RPNPointer-1]; + end; + dvdv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=RPNStack[RPNPointer]/RPNStack[RPNPointer-1]; + end; + powv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=Power(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + arctan2v : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=ArcTan2(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + stepv : begin + Dec(RPNPointer); + If RPNStack[RPNPointer-1]>RPNStack[RPNPOINTER] THEN + RPNStack[RPNPointer-1]:=1.0 + else + RPNStack[RPNPointer-1]:=0.0; + end; + hypotv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=hypot(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + lognv : begin + Dec(RPNPointer); + RPNStack[RPNPointer-1]:=logn(RPNStack[RPNPointer],RPNStack[RPNPointer-1]); + end; + else + TEvalInternalError(1,ORD(TheArray^.op)); + end; + end; + AFunction : begin + {$IFDEF DebugMe} + Writeln('function value:', ord(TheArray^.fun1)); + {$ENDIF} + + Case TheArray^.Fun1 of + cosx: RPNStack[RPNPointer-1]:=cos(RPNStack[RPNPointer-1]); + sinx: RPNStack[RPNPointer-1]:=sin(RPNStack[RPNPointer-1]); + tanx: RPNStack[RPNPointer-1]:=tan(RPNStack[RPNPointer-1]); + sqrx: RPNStack[RPNPointer-1]:=sqr(RPNStack[RPNPointer-1]); + sqrtx: RPNStack[RPNPointer-1]:=sqrt(RPNStack[RPNPointer-1]); + expx: RPNStack[RPNPointer-1]:=exp(RPNStack[RPNPointer-1]); + lnx: RPNStack[RPNPointer-1]:=ln(RPNStack[RPNPointer-1]); + invx: RPNStack[RPNPointer-1]:=1/RPNStack[RPNPointer-1]; + minus: RPNStack[RPNPointer-1]:=-RPNStack[RPNPointer-1]; + cotanx: RPNStack[RPNPointer-1]:=cotan(RPNStack[RPNPointer-1]); + arcsinx: RPNStack[RPNPointer-1]:=arcsin(RPNStack[RPNPointer-1]); + arccosx: RPNStack[RPNPointer-1]:=arccos(RPNStack[RPNPointer-1]); + arctanx: RPNStack[RPNPointer-1]:=arctan(RPNStack[RPNPointer-1]); + sinhx: RPNStack[RPNPointer-1]:=sinh(RPNStack[RPNPointer-1]); + coshx: RPNStack[RPNPointer-1]:=cosh(RPNStack[RPNPointer-1]); + tanhx: RPNStack[RPNPointer-1]:=tanh(RPNStack[RPNPointer-1]); + arcsinhx: RPNStack[RPNPointer-1]:=ArcSinh(RPNStack[RPNPointer-1]); + arccoshx: RPNStack[RPNPointer-1]:=ArcCosh(RPNStack[RPNPointer-1]); + arctanhx: RPNStack[RPNPointer-1]:=ArcTanh(RPNStack[RPNPointer-1]); + log10x: RPNStack[RPNPointer-1]:=Log10(RPNStack[RPNPointer-1]); + log2x: RPNStack[RPNPointer-1]:=Log2(RPNStack[RPNPointer-1]); + lnxpix: RPNStack[RPNPointer-1]:=lnxp1(RPNStack[RPNPointer-1]); + else + TEvalInternalError(2,ORD(TheArray^.fun1)); + end; + end; + else + TEvalInternalError(3,ORD(TheArray^.VLIWEntity)); + end; + {$Ifdef DebugDump} + Writeln('RecordNo: ',VliwRecs); + IF RPNPointer>0 then + begin + Writeln('RPN stack'); + for I:=0 TO RpnPointer-1 DO + Writeln(I:2,' ',RpnStack[I]); + end; + {$Endif} + dec(TheArray); + dec(VliwRecs); + UNTIL VliwRecs<0; + Result:=RPNStack[0]; +end; +} + +function TEvaluator.Evaldepth:longint; +{estimate stackdepth} + +var TheArray : pVLIWEvalWord; + VLIWRecs : Longint; + Deepest : Longint; + RPNPointer : Longint; + +begin + RPNPointer:=0; + Deepest:=0; + VliwRecs:=VliwCount-1; + TheArray:=@VLIWRPNExpr[VLIWRecs]; + REPEAT + TheArray:=@VLIWRPNExpr[VLIWRecs]; + CASE TheArray^.VLIWEntity OF + AVariable, + afconstant, + aiconstant, {a placeholder always changes into a push} + placeholder : Inc(rpnpointer); + AnOperation : Dec(rpnpointer); {take two args, put one back} + { AFunction : Doesn't do anything} + end; + If Deepest