Imported sources from kde-2.2 distribution
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/ChangeLog b/JavaScriptCore/kjs/ChangeLog
new file mode 100644
index 0000000..8176cf4
--- /dev/null
+++ b/JavaScriptCore/kjs/ChangeLog
@@ -0,0 +1,24 @@
+2001-01-04 Harri Porten <harri@trolltech.com>
+
+ * ustring.h: pack bytes to avoid alignment problems (ARM) reported
+ by Stefan Hanske <sh990154@mail.uni-greifswald.de>
+ * nodes.cpp: typeof fix by Emmeran Seehuber <the_emmy@gmx.de>
+ * nodes.cpp: fixed order of function declaration proccessing
+
+2000-12-18 Harri Porten <harri@trolltech.com>
+
+ * string_object.cpp: fixed out-of-bounds error in fromCharCode()
+
+2000-12-11 Harri Porten <harri@trolltech.com>
+
+ * regexp.h: compile fix for buggy libc
+ * ustring.cpp: format string conversion of numbers with %g
+
+2000-12-10 Harri Porten <harri@trolltech.com>
+
+ * lexer.cpp: parsing != was broken, added \v escape in strings,
+ fixed "\u" and "\x" and \x with non hex chars following.
+ * nodes.cpp: implemented <<=, >>=, >>>=, &=, ^=, |= and %=
+ * internal.cpp: create error message including line no on parse errors
+
+
diff --git a/JavaScriptCore/kjs/Makefile.am b/JavaScriptCore/kjs/Makefile.am
new file mode 100644
index 0000000..1cd1be0
--- /dev/null
+++ b/JavaScriptCore/kjs/Makefile.am
@@ -0,0 +1,66 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1999 Harri Porten (porten@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library 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. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+YACC = bison
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkjs.la
+
+libkjs_la_SOURCES = kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp \
+ operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp \
+ internal.cpp regexp.cpp global_object.cpp math_object.cpp \
+ bool_object.cpp object_object.cpp error_object.cpp \
+ array_object.cpp string_object.cpp number_object.cpp \
+ date_object.cpp regexp_object.cpp collector.cpp function_object.cpp \
+ debugger.cpp
+
+kjsincludedir = $(includedir)/kjs
+kjsinclude_HEADERS = kjs.h object.h operations.h ustring.h \
+ function.h lookup.h types.h
+
+noinst_HEADERS = nodes.h lexer.h regexp.h internal.h collector.h \
+ grammar.h object_object.h function_object.h function_object.h \
+ bool_object.h math_object.h array_object.h string_object.h \
+ number_object.h date_object.h regexp_object.h error_object.h \
+ debugger.h
+
+libkjs_la_LDFLAGS = -version-info 1:0 -no-undefined $(USER_LDFLAGS)
+libkjs_la_LIBADD = -lm $(LIBPCRE)
+
+parser: $(srcdir)/grammar.y
+ cd $(srcdir); \
+ $(YACC) -d -p kjsyy grammar.y && mv grammar.tab.c grammar.cpp; \
+ if test -f grammar.tab.h; then \
+ if cmp -s grammar.tab.h grammar.h; then rm -f grammar.tab.h; \
+ else mv grammar.tab.h grammar.h; fi \
+ else :; fi
+
+## with debugger interface
+debugger: $(libkjs_la_SOURCES) $(kjsinclude_HEADERS) $(noinst_HEADERS)
+ $(MAKE) DEFS="-DKJS_DEBUGGER $(DEFS)" libkjs.la
+
+## test program (in one program for easier profiling/memory debugging)
+EXTRA_PROGRAMS = testkjs_static
+testkjs_static_SOURCES = testkjs.cpp $(libkjs_la_SOURCES)
+testkjs_static_LDADD = $(LIBPCRE)
+
+## test program (linked to libkjs)
+check_PROGRAMS = testkjs
+testkjs_SOURCES = testkjs.cpp
+testkjs_LDADD = libkjs.la
+
diff --git a/JavaScriptCore/kjs/Makefile.in b/JavaScriptCore/kjs/Makefile.in
new file mode 100644
index 0000000..dd601f3
--- /dev/null
+++ b/JavaScriptCore/kjs/Makefile.in
@@ -0,0 +1,738 @@
+# KDE tags expanded automatically by am_edit - $Revision$
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# This file is part of the KDE libraries
+# Copyright (C) 1999 Harri Porten (porten@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library 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. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+#>-
+bindir = @bindir@
+#>+ 3
+DEPDIR = .deps
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+ARTSCCONFIG = @ARTSCCONFIG@
+ARTS_BUILD_GMCOP = @ARTS_BUILD_GMCOP@
+ARTS_BUILD_KDE = @ARTS_BUILD_KDE@
+ARTS_MAJOR_VERSION = @ARTS_MAJOR_VERSION@
+ARTS_MICRO_VERSION = @ARTS_MICRO_VERSION@
+ARTS_MINOR_VERSION = @ARTS_MINOR_VERSION@
+ARTS_VERSION = @ARTS_VERSION@
+AS = @AS@
+AUTODIRS = @AUTODIRS@
+BZIP2DIR = @BZIP2DIR@
+BZIP2_FILTER = @BZIP2_FILTER@
+CC = @CC@
+CONF_FILES = @CONF_FILES@
+CPP = @CPP@
+CUPSSUBDIR = @CUPSSUBDIR@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+DCOPIDL = @DCOPIDL@
+DCOPIDL2CPP = @DCOPIDL2CPP@
+DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@
+DLLTOOL = @DLLTOOL@
+DPMSINC = @DPMSINC@
+DPMSLIB = @DPMSLIB@
+EXEEXT = @EXEEXT@
+EXTRA_SUBDIRS = @EXTRA_SUBDIRS@
+GCJ = @GCJ@
+GCJFLAGS = @GCJFLAGS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_DEPLIBS = @GLIB_DEPLIBS@
+GLIB_LIBS = @GLIB_LIBS@
+GLINC = @GLINC@
+GLLIB = @GLLIB@
+GMSGFMT = @GMSGFMT@
+HAVE_MITSHM = @HAVE_MITSHM@
+HELP_SUBDIR = @HELP_SUBDIR@
+ICE_RLIB = @ICE_RLIB@
+ICE_SUBDIR = @ICE_SUBDIR@
+IDL = @IDL@
+IDL_DEPENDENCIES = @IDL_DEPENDENCIES@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVAH = @JAVAH@
+JVMLIBS = @JVMLIBS@
+KDECONFIG = @KDECONFIG@
+KDE_CXXFLAGS = @KDE_CXXFLAGS@
+KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@
+KDE_INCLUDES = @KDE_INCLUDES@
+KDE_LDFLAGS = @KDE_LDFLAGS@
+KDE_PLUGIN = @KDE_PLUGIN@
+KDE_RPATH = @KDE_RPATH@
+KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@
+KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@
+KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@
+KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@
+KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@
+LIBASOUND = @LIBASOUND@
+LIBAUDIOFILE = @LIBAUDIOFILE@
+LIBAUDIOIO = @LIBAUDIOIO@
+LIBAUDIONAS = @LIBAUDIONAS@
+LIBBZ2 = @LIBBZ2@
+LIBCOMPAT = @LIBCOMPAT@
+LIBCRYPT = @LIBCRYPT@
+LIBDL = @LIBDL@
+LIBFAM = @LIBFAM@
+LIBGEN = @LIBGEN@
+LIBICE = @LIBICE@
+LIBJPEG = @LIBJPEG@
+LIBMICO = @LIBMICO@
+LIBOBJS = @LIBOBJS@
+LIBOSSAUDIO = @LIBOSSAUDIO@
+LIBPCRE = @LIBPCRE@
+LIBPNG = @LIBPNG@
+LIBPOSIX1E = @LIBPOSIX1E@
+LIBPTHREAD = @LIBPTHREAD@
+LIBPYTHON = @LIBPYTHON@
+LIBQIMGIO = @LIBQIMGIO@
+LIBRESOLV = @LIBRESOLV@
+LIBSHADOW = @LIBSHADOW@
+LIBSM = @LIBSM@
+LIBSOCKET = @LIBSOCKET@
+LIBSSL = @LIBSSL@
+LIBTIFF = @LIBTIFF@
+LIBTOOL = @LIBTOOL@
+LIBUCB = @LIBUCB@
+LIBUTIL = @LIBUTIL@
+LIBVOLMGT = @LIBVOLMGT@
+LIBXINERAMA = @LIBXINERAMA@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_RPATH = @LIBXML_RPATH@
+LIBXSLT_MAJOR_VERSION = @LIBXSLT_MAJOR_VERSION@
+LIBXSLT_MICRO_VERSION = @LIBXSLT_MICRO_VERSION@
+LIBXSLT_MINOR_VERSION = @LIBXSLT_MINOR_VERSION@
+LIBXSLT_VERSION = @LIBXSLT_VERSION@
+LIBXSLT_VERSION_INFO = @LIBXSLT_VERSION_INFO@
+LIBXSLT_VERSION_NUMBER = @LIBXSLT_VERSION_NUMBER@
+LIBZ = @LIBZ@
+LIB_CUPS = @LIB_CUPS@
+LIB_DCOP = @LIB_DCOP@
+LIB_DMALLOC = @LIB_DMALLOC@
+LIB_KAB = @LIB_KAB@
+LIB_KDECORE = @LIB_KDECORE@
+LIB_KDEUI = @LIB_KDEUI@
+LIB_KFILE = @LIB_KFILE@
+LIB_KFM = @LIB_KFM@
+LIB_KFORMULA = @LIB_KFORMULA@
+LIB_KHTML = @LIB_KHTML@
+LIB_KIMGIO = @LIB_KIMGIO@
+LIB_KIO = @LIB_KIO@
+LIB_KPARTS = @LIB_KPARTS@
+LIB_KSPELL = @LIB_KSPELL@
+LIB_KSSL = @LIB_KSSL@
+LIB_KSYCOCA = @LIB_KSYCOCA@
+LIB_KWRITE = @LIB_KWRITE@
+LIB_QT = @LIB_QT@
+LIB_SMB = @LIB_SMB@
+LIB_X11 = @LIB_X11@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MCOPIDL = @MCOPIDL@
+MEINPROC = @MEINPROC@
+MICO_INCLUDES = @MICO_INCLUDES@
+MICO_LDFLAGS = @MICO_LDFLAGS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+M_LIBS = @M_LIBS@
+NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@
+NOREPO = @NOREPO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PAMLIBS = @PAMLIBS@
+PASSWDLIBS = @PASSWDLIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHONINC = @PYTHONINC@
+PYTHONLIB = @PYTHONLIB@
+PYTHONMODDIR = @PYTHONMODDIR@
+QNAMESPACE_H = @QNAMESPACE_H@
+QTDOCDIR = @QTDOCDIR@
+QT_INCLUDES = @QT_INCLUDES@
+QT_LDFLAGS = @QT_LDFLAGS@
+RANLIB = @RANLIB@
+REPO = @REPO@
+SETUIDFLAGS = @SETUIDFLAGS@
+SSL_INCLUDES = @SSL_INCLUDES@
+SSL_LDFLAGS = @SSL_LDFLAGS@
+STRIP = @STRIP@
+TOPSUBDIRS = @TOPSUBDIRS@
+UIC = @UIC@
+USER_INCLUDES = @USER_INCLUDES@
+USER_LDFLAGS = @USER_LDFLAGS@
+USE_EXCEPTIONS = @USE_EXCEPTIONS@
+USE_RTTI = @USE_RTTI@
+USE_THREADS = @USE_THREADS@
+VERSION = @VERSION@
+WITH_MEM_DEBUG = @WITH_MEM_DEBUG@
+WITH_XSLT_DEBUG = @WITH_XSLT_DEBUG@
+XGETTEXT = @XGETTEXT@
+XPMINC = @XPMINC@
+XPMLIB = @XPMLIB@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_INCLUDES = @X_INCLUDES@
+X_LDFLAGS = @X_LDFLAGS@
+X_PRE_LIBS = @X_PRE_LIBS@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+idldir = @idldir@
+jni_includes = @jni_includes@
+kde_appsdir = @kde_appsdir@
+kde_bindir = @kde_bindir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_includes = @kde_includes@
+kde_libraries = @kde_libraries@
+kde_libs_htmldir = @kde_libs_htmldir@
+kde_libs_prefix = @kde_libs_prefix@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_moduledir = @kde_moduledir@
+kde_servicesdir = @kde_servicesdir@
+kde_servicetypesdir = @kde_servicetypesdir@
+kde_sounddir = @kde_sounddir@
+kde_templatesdir = @kde_templatesdir@
+kde_wallpaperdir = @kde_wallpaperdir@
+micodir = @micodir@
+path_su = @path_su@
+qt_includes = @qt_includes@
+qt_libraries = @qt_libraries@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+
+YACC = bison
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkjs.la
+
+libkjs_la_SOURCES = kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp internal.cpp regexp.cpp global_object.cpp math_object.cpp bool_object.cpp object_object.cpp error_object.cpp array_object.cpp string_object.cpp number_object.cpp date_object.cpp regexp_object.cpp collector.cpp function_object.cpp debugger.cpp
+
+
+kjsincludedir = $(includedir)/kjs
+kjsinclude_HEADERS = kjs.h object.h operations.h ustring.h function.h lookup.h types.h
+
+
+noinst_HEADERS = nodes.h lexer.h regexp.h internal.h collector.h grammar.h object_object.h function_object.h function_object.h bool_object.h math_object.h array_object.h string_object.h number_object.h date_object.h regexp_object.h error_object.h debugger.h
+
+
+libkjs_la_LDFLAGS = -version-info 1:0 -no-undefined $(USER_LDFLAGS)
+libkjs_la_LIBADD = -lm $(LIBPCRE)
+
+EXTRA_PROGRAMS = testkjs_static
+testkjs_static_SOURCES = testkjs.cpp $(libkjs_la_SOURCES)
+testkjs_static_LDADD = $(LIBPCRE)
+
+check_PROGRAMS = testkjs
+testkjs_SOURCES = testkjs.cpp
+testkjs_LDADD = libkjs.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(lib_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libkjs_la_DEPENDENCIES =
+#>- libkjs_la_OBJECTS = kjs.lo grammar.lo lexer.lo nodes.lo object.lo \
+#>- operations.lo ustring.lo function.lo types.lo lookup.lo internal.lo \
+#>- regexp.lo global_object.lo math_object.lo bool_object.lo \
+#>- object_object.lo error_object.lo array_object.lo string_object.lo \
+#>- number_object.lo date_object.lo regexp_object.lo collector.lo \
+#>- function_object.lo debugger.lo
+#>+ 9
+libkjs_la_final_OBJECTS = libkjs_la.all_cpp.lo
+libkjs_la_nofinal_OBJECTS = kjs.lo grammar.lo lexer.lo nodes.lo object.lo \
+operations.lo ustring.lo function.lo types.lo lookup.lo internal.lo \
+regexp.lo global_object.lo math_object.lo bool_object.lo \
+object_object.lo error_object.lo array_object.lo string_object.lo \
+number_object.lo date_object.lo regexp_object.lo collector.lo \
+function_object.lo debugger.lo
+@KDE_USE_FINAL_FALSE@libkjs_la_OBJECTS = $(libkjs_la_nofinal_OBJECTS)
+@KDE_USE_FINAL_TRUE@libkjs_la_OBJECTS = $(libkjs_la_final_OBJECTS)
+check_PROGRAMS = testkjs$(EXEEXT)
+#>- testkjs_static_OBJECTS = testkjs.$(OBJEXT) kjs.$(OBJEXT) \
+#>- grammar.$(OBJEXT) lexer.$(OBJEXT) nodes.$(OBJEXT) object.$(OBJEXT) \
+#>- operations.$(OBJEXT) ustring.$(OBJEXT) function.$(OBJEXT) \
+#>- types.$(OBJEXT) lookup.$(OBJEXT) internal.$(OBJEXT) regexp.$(OBJEXT) \
+#>- global_object.$(OBJEXT) math_object.$(OBJEXT) bool_object.$(OBJEXT) \
+#>- object_object.$(OBJEXT) error_object.$(OBJEXT) array_object.$(OBJEXT) \
+#>- string_object.$(OBJEXT) number_object.$(OBJEXT) date_object.$(OBJEXT) \
+#>- regexp_object.$(OBJEXT) collector.$(OBJEXT) function_object.$(OBJEXT) \
+#>- debugger.$(OBJEXT)
+#>+ 9
+testkjs_static_OBJECTS = testkjs.$(OBJEXT) kjs.$(OBJEXT) \
+grammar.$(OBJEXT) lexer.$(OBJEXT) nodes.$(OBJEXT) object.$(OBJEXT) \
+operations.$(OBJEXT) ustring.$(OBJEXT) function.$(OBJEXT) \
+types.$(OBJEXT) lookup.$(OBJEXT) internal.$(OBJEXT) regexp.$(OBJEXT) \
+global_object.$(OBJEXT) math_object.$(OBJEXT) bool_object.$(OBJEXT) \
+object_object.$(OBJEXT) error_object.$(OBJEXT) array_object.$(OBJEXT) \
+string_object.$(OBJEXT) number_object.$(OBJEXT) date_object.$(OBJEXT) \
+regexp_object.$(OBJEXT) collector.$(OBJEXT) function_object.$(OBJEXT) \
+debugger.$(OBJEXT)
+testkjs_static_DEPENDENCIES =
+testkjs_static_LDFLAGS =
+#>- testkjs_OBJECTS = testkjs.$(OBJEXT)
+#>+ 1
+testkjs_OBJECTS = testkjs.$(OBJEXT)
+testkjs_DEPENDENCIES = libkjs.la
+testkjs_LDFLAGS =
+CXXFLAGS = @CXXFLAGS@
+#>- CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 1
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+#>- LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 1
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile --tag=CXX $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+CXXLD = $(CXX)
+#>- CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+#>+ 1
+CXXLINK = $(LIBTOOL) --mode=link --tag=CXX $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS) $(LDFLAGS) -o $@
+HEADERS = $(kjsinclude_HEADERS) $(noinst_HEADERS)
+
+DIST_COMMON = README ChangeLog Makefile.am Makefile.in THANKS
+
+
+#>- DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+#>+ 4
+KDE_DIST=configure.in.in grammar.y keywords.table math_object.lut.h test.js create_hash_table lexer.lut.h
+
+DISTFILES= $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST)
+
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(libkjs_la_SOURCES) $(testkjs_static_SOURCES) $(testkjs_SOURCES)
+OBJECTS = $(libkjs_la_OBJECTS) $(testkjs_static_OBJECTS) $(testkjs_OBJECTS)
+
+#>- all: all-redirect
+#>+ 1
+all: docs-am all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cpp .lo .o .obj .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+#>- cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+#>+ 2
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+ cd $(top_srcdir) && perl admin/am_edit kjs/Makefile.in
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-libLTLIBRARIES:
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+
+distclean-libLTLIBRARIES:
+
+maintainer-clean-libLTLIBRARIES:
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \
+ $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+#>- libkjs.la: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+#>+ 2
+@KDE_USE_CLOSURE_TRUE@libkjs.la: libkjs.la.closure $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+@KDE_USE_CLOSURE_FALSE@libkjs.la: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libkjs_la_LDFLAGS) $(libkjs_la_OBJECTS) $(libkjs_la_LIBADD) $(LIBS)
+
+mostlyclean-checkPROGRAMS:
+
+clean-checkPROGRAMS:
+ -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+
+distclean-checkPROGRAMS:
+
+maintainer-clean-checkPROGRAMS:
+
+testkjs_static$(EXEEXT): $(testkjs_static_OBJECTS) $(testkjs_static_DEPENDENCIES)
+ @rm -f testkjs_static$(EXEEXT)
+ $(CXXLINK) $(testkjs_static_LDFLAGS) $(testkjs_static_OBJECTS) $(testkjs_static_LDADD) $(LIBS)
+
+testkjs$(EXEEXT): $(testkjs_OBJECTS) $(testkjs_DEPENDENCIES)
+ @rm -f testkjs$(EXEEXT)
+ $(CXXLINK) $(testkjs_LDFLAGS) $(testkjs_OBJECTS) $(testkjs_LDADD) $(LIBS)
+.cpp.o:
+ $(CXXCOMPILE) -c $<
+.cpp.obj:
+ $(CXXCOMPILE) -c `cygpath -w $<`
+.cpp.lo:
+ $(LTCXXCOMPILE) -c $<
+
+install-kjsincludeHEADERS: $(kjsinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(kjsincludedir)
+ @list='$(kjsinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(kjsincludedir)/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(kjsincludedir)/$$p; \
+ done
+
+uninstall-kjsincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ list='$(kjsinclude_HEADERS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(kjsincludedir)/$$p; \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = kjs
+
+distdir: $(DISTFILES)
+#>- @for file in $(DISTFILES); do \
+#>- d=$(srcdir); \
+#>- if test -d $$d/$$file; then \
+#>- cp -pr $$/$$file $(distdir)/$$file; \
+#>- else \
+#>- test -f $(distdir)/$$file \
+#>- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+#>- || cp -p $$d/$$file $(distdir)/$$file || :; \
+#>- fi; \
+#>- done
+#>+ 10
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-libLTLIBRARIES
+install-exec: install-exec-am
+
+install-data-am: install-kjsincludeHEADERS
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-libLTLIBRARIES uninstall-kjsincludeHEADERS
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(kjsincludedir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-checkPROGRAMS \
+ mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+#>- clean-am: clean-libLTLIBRARIES clean-compile clean-libtool \
+#>- clean-checkPROGRAMS clean-tags clean-generic \
+#>- mostlyclean-am
+#>+ 3
+clean-am: clean-closures clean-final clean-libLTLIBRARIES clean-compile clean-libtool \
+ clean-checkPROGRAMS clean-tags clean-generic \
+ mostlyclean-am
+
+#>- clean: clean-am
+#>+ 1
+clean: kde-rpo-clean clean-am
+
+distclean-am: distclean-libLTLIBRARIES distclean-compile \
+ distclean-libtool distclean-checkPROGRAMS \
+ distclean-tags distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-checkPROGRAMS maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
+clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
+uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool mostlyclean-checkPROGRAMS \
+distclean-checkPROGRAMS clean-checkPROGRAMS \
+maintainer-clean-checkPROGRAMS uninstall-kjsincludeHEADERS \
+install-kjsincludeHEADERS tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+parser: $(srcdir)/grammar.y
+ cd $(srcdir); \
+ $(YACC) -d -p kjsyy grammar.y && mv grammar.tab.c grammar.cpp; \
+ if test -f grammar.tab.h; then \
+ if cmp -s grammar.tab.h grammar.h; then rm -f grammar.tab.h; \
+ else mv grammar.tab.h grammar.h; fi \
+ else :; fi
+
+debugger: $(libkjs_la_SOURCES) $(kjsinclude_HEADERS) $(noinst_HEADERS)
+ $(MAKE) DEFS="-DKJS_DEBUGGER $(DEFS)" libkjs.la
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+#>+ 8
+libkjs.la.closure: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+ @echo "int main() {return 0;}" > libkjs_la_closure.cpp
+ @$(LTCXXCOMPILE) -c libkjs_la_closure.cpp
+ @$(CXXLINK) libkjs_la_closure.lo $(libkjs_la_LDFLAGS) $(libkjs_la_OBJECTS) $(libkjs_la_LIBADD) $(LIBS)
+ @rm -f libkjs_la_closure.* libkjs.la.closure
+ @echo "timestamp" > libkjs.la.closure
+
+
+#>+ 3
+clean-closures:
+ -rm -f libkjs.la.closure
+
+#>+ 2
+docs-am:
+
+#>+ 5
+force-reedit:
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+ cd $(top_srcdir) && perl admin/am_edit kjs/Makefile.in
+
+
+#>+ 11
+libkjs_la.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/kjs.cpp $(srcdir)/grammar.cpp $(srcdir)/lexer.cpp $(srcdir)/nodes.cpp $(srcdir)/object.cpp $(srcdir)/operations.cpp $(srcdir)/ustring.cpp $(srcdir)/function.cpp $(srcdir)/types.cpp $(srcdir)/lookup.cpp $(srcdir)/internal.cpp $(srcdir)/regexp.cpp $(srcdir)/global_object.cpp $(srcdir)/math_object.cpp $(srcdir)/bool_object.cpp $(srcdir)/object_object.cpp $(srcdir)/error_object.cpp $(srcdir)/array_object.cpp $(srcdir)/string_object.cpp $(srcdir)/number_object.cpp $(srcdir)/date_object.cpp $(srcdir)/regexp_object.cpp $(srcdir)/collector.cpp $(srcdir)/function_object.cpp $(srcdir)/debugger.cpp
+ @echo 'creating libkjs_la.all_cpp.cpp ...'; \
+ rm -f libkjs_la.all_cpp.files libkjs_la.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> libkjs_la.all_cpp.final; \
+ for file in kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp internal.cpp regexp.cpp global_object.cpp math_object.cpp bool_object.cpp object_object.cpp error_object.cpp array_object.cpp string_object.cpp number_object.cpp date_object.cpp regexp_object.cpp collector.cpp function_object.cpp debugger.cpp ; do \
+ echo "#include \"$$file\"" >> libkjs_la.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> libkjs_la.all_cpp.final; \
+ done; \
+ cat libkjs_la.all_cpp.final libkjs_la.all_cpp.files > libkjs_la.all_cpp.cpp; \
+ rm -f libkjs_la.all_cpp.final libkjs_la.all_cpp.files
+
+#>+ 11
+testkjs.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/testkjs.cpp
+ @echo 'creating testkjs.all_cpp.cpp ...'; \
+ rm -f testkjs.all_cpp.files testkjs.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> testkjs.all_cpp.final; \
+ for file in testkjs.cpp ; do \
+ echo "#include \"$$file\"" >> testkjs.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> testkjs.all_cpp.final; \
+ done; \
+ cat testkjs.all_cpp.final testkjs.all_cpp.files > testkjs.all_cpp.cpp; \
+ rm -f testkjs.all_cpp.final testkjs.all_cpp.files
+
+#>+ 3
+clean-final:
+ -rm -f libkjs_la.all_cpp.cpp testkjs.all_cpp.cpp
+
+#>+ 2
+final:
+ $(MAKE) libkjs_la_OBJECTS="$(libkjs_la_final_OBJECTS)" all-am
+#>+ 2
+no-final:
+ $(MAKE) libkjs_la_OBJECTS="$(libkjs_la_nofinal_OBJECTS)" all-am
+#>+ 3
+cvs-clean:
+ $(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean
+
+#>+ 3
+kde-rpo-clean:
+ -rm -f *.rpo
diff --git a/JavaScriptCore/kjs/README b/JavaScriptCore/kjs/README
new file mode 100644
index 0000000..b4a0fcc
--- /dev/null
+++ b/JavaScriptCore/kjs/README
@@ -0,0 +1,25 @@
+This library provides an ECMAScript compatible interpreter. The ECMA standard
+is based on well known scripting languages such as Netscape's JavaScript and
+Microsoft's JScript.
+
+I'm currently pursuing to be compliant with Edition 3 of ECMA-262. Postscript
+and pdf versions of the standard are avaiable at:
+
+http://www.ecma.ch
+
+About 90% of the required features should be covered by now. Note that this
+number covers the core language elements only. Features like the famous
+roll-over buttons on the www are NOT part of the standard. Those extensions
+are added via a module loaded dynamically by the KHTML Widget.
+
+I'll provide some examples of how to extend this library for various needs at
+a later point in time. Feel free to contact me via mail if you have any
+questions on how to provide scripting capabilites for your application.
+
+A debugger is being worked on. To compile it, add -DKJS_DEBUGGER to the CXXFLAGS
+section in the Makefile.am of kdelibs/kjs and kdelibs/khtml/ecma.
+
+Bug reports, patches or feedback of any kind is very welcome.
+
+Harri Porten <porten@kde.org>
+
diff --git a/JavaScriptCore/kjs/THANKS b/JavaScriptCore/kjs/THANKS
new file mode 100644
index 0000000..036e5e7
--- /dev/null
+++ b/JavaScriptCore/kjs/THANKS
@@ -0,0 +1,7 @@
+I would like to thank the following people for their help:
+
+Richard Moore <rich@kde.org> - for filling the Math object with some life
+Daegeun Lee <realking@mizi.com> - for pointing out some bugs and providing
+ much code for the String and Date object.
+Marco Pinelli <pinmc@libero.it> - for his patches
+Christian Kirsch <ck@held.mind.de> - for his contribution to the Date object
diff --git a/JavaScriptCore/kjs/array_object.cpp b/JavaScriptCore/kjs/array_object.cpp
new file mode 100644
index 0000000..cc97dff
--- /dev/null
+++ b/JavaScriptCore/kjs/array_object.cpp
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "array_object.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+ArrayObject::ArrayObject(const Object &funcProto,
+ const Object &arrayProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.4.3.1 Array.prototype
+ setPrototypeProperty(arrayProto);
+}
+
+// ECMA 15.6.1
+Completion ArrayObject::execute(const List &args)
+{
+ // equivalent to 'new Array(....)'
+ KJSO result = construct(args);
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.6.2
+Object ArrayObject::construct(const List &args)
+{
+ Object result = Object::create(ArrayClass);
+
+ unsigned int len;
+ ListIterator it = args.begin();
+ // a single argument might denote the array size
+ if (args.size() == 1 && it->isA(NumberType))
+ len = it->toUInt32();
+ else {
+ // initialize array
+ len = args.size();
+ for (unsigned int u = 0; it != args.end(); it++, u++)
+ result.put(UString::from(u), *it);
+ }
+
+ // array size
+ result.put("length", len, DontEnum | DontDelete);
+
+ return result;
+}
+
+// ECMA 15.6.4
+ArrayPrototype::ArrayPrototype(const Object& proto)
+ : ObjectImp(ArrayClass, Null(), proto)
+{
+ // The constructor will be added later in ArrayObject's constructor
+
+ put("length", 0u, DontEnum | DontDelete);
+}
+
+KJSO ArrayPrototype::get(const UString &p) const
+{
+ int id;
+ if(p == "toString")
+ id = ArrayProtoFunc::ToString;
+ else if(p == "toLocaleString")
+ id = ArrayProtoFunc::ToLocaleString;
+ else if(p == "concat")
+ id = ArrayProtoFunc::Concat;
+ else if (p == "join")
+ id = ArrayProtoFunc::Join;
+ else if(p == "pop")
+ id = ArrayProtoFunc::Pop;
+ else if(p == "push")
+ id = ArrayProtoFunc::Push;
+ else if(p == "reverse")
+ id = ArrayProtoFunc::Reverse;
+ else if(p == "shift")
+ id = ArrayProtoFunc::Shift;
+ else if(p == "slice")
+ id = ArrayProtoFunc::Slice;
+ else if(p == "sort")
+ id = ArrayProtoFunc::Sort;
+ else if(p == "splice")
+ id = ArrayProtoFunc::Splice;
+ else if(p == "unshift")
+ id = ArrayProtoFunc::UnShift;
+ else
+ return Imp::get(p);
+
+ return Function(new ArrayProtoFunc(id));
+}
+
+// ECMA 15.4.4
+Completion ArrayProtoFunc::execute(const List &args)
+{
+ KJSO result, obj, obj2;
+ Object thisObj = Object::dynamicCast(thisValue());
+ unsigned int length = thisObj.get("length").toUInt32();
+ unsigned int middle;
+ UString str = "", str2;
+ UString separator = ",";
+
+ switch (id) {
+ case ToLocaleString:
+ /* TODO */
+ // fall trough
+ case ToString:
+ if (!thisObj.getClass() == ArrayClass) {
+ result = Error::create(TypeError);
+ break;
+ }
+ // fall trough
+ case Join:
+ {
+ if (!args[0].isA(UndefinedType))
+ separator = args[0].toString().value();
+ for (unsigned int k = 0; k < length; k++) {
+ if (k >= 1)
+ str += separator;
+ obj = thisObj.get(UString::from(k));
+ if (!obj.isA(UndefinedType) && !obj.isA(NullType))
+ str += obj.toString().value();
+ }
+ }
+ result = String(str);
+ break;
+ case Concat: {
+ result = Object::create(ArrayClass);
+ int n = 0;
+ obj = thisObj;
+ ListIterator it = args.begin();
+ for (;;) {
+ if (obj.isA(ObjectType) &&
+ static_cast<Object&>(obj).getClass() == ArrayClass) {
+ unsigned int k = 0;
+ if (n > 0)
+ length = obj.get("length").toUInt32();
+ while (k < length) {
+ UString p = UString::from(k);
+ if (obj.hasProperty(p))
+ result.put(UString::from(n), obj.get(p));
+ n++;
+ k++;
+ }
+ } else {
+ result.put(UString::from(n), obj);
+ n++;
+ }
+ if (it == args.end())
+ break;
+ obj = it++;
+ }
+ result.put("length", Number(n), DontEnum | DontDelete);
+ }
+ break;
+ case Pop:
+ if (length == 0) {
+ thisObj.put("length", Number(length), DontEnum | DontDelete);
+ result = Undefined();
+ } else {
+ str = UString::from(length - 1);
+ result = thisObj.get(str);
+ thisObj.deleteProperty(str);
+ thisObj.put("length", length - 1, DontEnum | DontDelete);
+ }
+ break;
+ case Push:
+ {
+ for (int n = 0; n < args.size(); n++)
+ thisObj.put(UString::from(length + n), args[n]);
+ length += args.size();
+ thisObj.put("length", length, DontEnum | DontDelete);
+ result = Number(length);
+ }
+ break;
+ case Reverse:
+ {
+ middle = length / 2;
+ for (unsigned int k = 0; k < middle; k++) {
+ str = UString::from(k);
+ str2 = UString::from(length - k - 1);
+ obj = thisObj.get(str);
+ obj2 = thisObj.get(str2);
+ if (thisObj.hasProperty(str2)) {
+ if (thisObj.hasProperty(str)) {
+ thisObj.put(str, obj2);
+ thisObj.put(str2, obj);
+ } else {
+ thisObj.put(str, obj2);
+ thisObj.deleteProperty(str2);
+ }
+ } else {
+ if (thisObj.hasProperty(str)) {
+ thisObj.deleteProperty(str);
+ thisObj.put(str2, obj);
+ } else {
+ // why delete something that's not there ? Strange.
+ thisObj.deleteProperty(str);
+ thisObj.deleteProperty(str2);
+ }
+ }
+ }
+ }
+ result = thisObj;
+ break;
+ case Shift:
+ if (length == 0) {
+ thisObj.put("length", Number(length), DontEnum | DontDelete);
+ result = Undefined();
+ } else {
+ result = thisObj.get("0");
+ for(unsigned int k = 1; k < length; k++) {
+ str = UString::from(k);
+ str2 = UString::from(k-1);
+ if (thisObj.hasProperty(str)) {
+ obj = thisObj.get(str);
+ thisObj.put(str2, obj);
+ } else
+ thisObj.deleteProperty(str2);
+ }
+ thisObj.deleteProperty(UString::from(length - 1));
+ thisObj.put("length", length - 1, DontEnum | DontDelete);
+ }
+ break;
+ case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713
+ {
+ result = Object::create(ArrayClass); // We return a new array
+ int begin = args[0].toUInt32();
+ int end = length;
+ if (!args[1].isA(UndefinedType))
+ {
+ end = args[1].toUInt32();
+ if ( end < 0 )
+ end += length;
+ }
+ // safety tests
+ if ( begin < 0 || end < 0 || begin >= end ) {
+ result.put("length", Number(0), DontEnum | DontDelete);
+ break;
+ }
+ //printf( "Slicing from %d to %d \n", begin, end );
+ for(unsigned int k = 0; k < (unsigned int) end-begin; k++) {
+ str = UString::from(k+begin);
+ str2 = UString::from(k);
+ if (thisObj.hasProperty(str)) {
+ obj = thisObj.get(str);
+ result.put(str2, obj);
+ }
+ }
+ result.put("length", end - begin, DontEnum | DontDelete);
+ break;
+ }
+ case Sort:
+ {
+#if 0
+ printf("KJS Array::Sort length=%d\n", length);
+ for ( unsigned int i = 0 ; i<length ; ++i )
+ printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );
+#endif
+ Object sortFunction;
+ bool useSortFunction = !args[0].isA(UndefinedType);
+ if (useSortFunction)
+ {
+ sortFunction = args[0].toObject();
+ if (!sortFunction.implementsCall())
+ useSortFunction = false;
+ }
+
+ if (length == 0) {
+ thisObj.put("length", Number(0), DontEnum | DontDelete);
+ result = Undefined();
+ break;
+ }
+
+ // "Min" sort. Not the fastest, but definitely less code than heapsort
+ // or quicksort, and much less swapping than bubblesort/insertionsort.
+ for ( unsigned int i = 0 ; i<length-1 ; ++i )
+ {
+ KJSO iObj = thisObj.get(UString::from(i));
+ unsigned int themin = i;
+ KJSO minObj = iObj;
+ for ( unsigned int j = i+1 ; j<length ; ++j )
+ {
+ KJSO jObj = thisObj.get(UString::from(j));
+ int cmp;
+ if ( useSortFunction )
+ {
+ List l;
+ l.append(jObj);
+ l.append(minObj);
+ cmp = sortFunction.executeCall( Global::current(), &l ).toInt32();
+ }
+ else
+ cmp = ( jObj.toString().value() < minObj.toString().value() ) ? -1 : 1;
+ if ( cmp < 0 )
+ {
+ themin = j;
+ minObj = jObj;
+ }
+ }
+ // Swap themin and i
+ if ( themin > i )
+ {
+ //printf("KJS Array::Sort: swapping %d and %d\n", i, themin );
+ thisObj.put( UString::from(i), minObj );
+ thisObj.put( UString::from(themin), iObj );
+ }
+ }
+#if 0
+ printf("KJS Array::Sort -- Resulting array:\n");
+ for ( unsigned int i = 0 ; i<length ; ++i )
+ printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );
+#endif
+ result = thisObj;
+ break;
+ }
+ // TODO Splice
+ // TODO Unshift
+ default:
+ result = Undefined();
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/JavaScriptCore/kjs/array_object.h b/JavaScriptCore/kjs/array_object.h
new file mode 100644
index 0000000..f4d56e4
--- /dev/null
+++ b/JavaScriptCore/kjs/array_object.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ARRAY_OBJECT_H_
+#define _ARRAY_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ArrayObject : public ConstructorImp {
+ public:
+ ArrayObject(const Object &funcProto, const Object &arrayProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class ArrayPrototype : public ObjectImp {
+ public:
+ ArrayPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+ class ArrayProtoFunc : public InternalFunctionImp {
+ public:
+ ArrayProtoFunc(int i) : id(i) { }
+ Completion execute(const List &);
+ enum { ToString, ToLocaleString, Concat, Join, Pop, Push,
+ Reverse, Shift, Slice, Sort, Splice, UnShift };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/bool_object.cpp b/JavaScriptCore/kjs/bool_object.cpp
new file mode 100644
index 0000000..08fcc5c
--- /dev/null
+++ b/JavaScriptCore/kjs/bool_object.cpp
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "bool_object.h"
+#include "error_object.h"
+
+using namespace KJS;
+
+BooleanObject::BooleanObject(const KJSO& funcProto, const KJSO &booleanProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // Boolean.prototype
+ setPrototypeProperty(booleanProto);
+}
+
+// ECMA 15.6.1
+Completion BooleanObject::execute(const List &args)
+{
+ Boolean b;
+
+ if (args.isEmpty())
+ b = Boolean(false);
+ else
+ b = args[0].toBoolean();
+
+ return Completion(ReturnValue, b);
+}
+
+// ECMA 15.6.2
+Object BooleanObject::construct(const List &args)
+{
+ Boolean b;
+ if (args.size() > 0)
+ b = args.begin()->toBoolean();
+ else
+ b = Boolean(false);
+
+ return Object::create(BooleanClass, b);
+}
+
+// ECMA 15.6.4
+BooleanPrototype::BooleanPrototype(const Object& proto)
+ : ObjectImp(BooleanClass, Boolean(false), proto)
+{
+ // The constructor will be added later in BooleanObject's constructor
+}
+
+KJSO BooleanPrototype::get(const UString &p) const
+{
+ if (p == "toString")
+ return Function(new BooleanProtoFunc(ToString));
+ else if (p == "valueOf")
+ return Function(new BooleanProtoFunc(ValueOf));
+ else
+ return Imp::get(p);
+}
+
+BooleanProtoFunc::BooleanProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.6.4.2 + 15.6.4.3
+Completion BooleanProtoFunc::execute(const List &)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // no generic function. "this" has to be a Boolean object
+ if (thisObj.isNull() || thisObj.getClass() != BooleanClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ // execute "toString()" or "valueOf()", respectively
+ KJSO v = thisObj.internalValue();
+ if (id == BooleanPrototype::ToString)
+ result = v.toString();
+ else
+ result = v.toBoolean();
+
+ return Completion(ReturnValue, result);
+}
diff --git a/JavaScriptCore/kjs/bool_object.h b/JavaScriptCore/kjs/bool_object.h
new file mode 100644
index 0000000..89dc451
--- /dev/null
+++ b/JavaScriptCore/kjs/bool_object.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _BOOL_OBJECT_H_
+#define _BOOL_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class BooleanObject : public ConstructorImp {
+ public:
+ BooleanObject(const KJSO& funcProto, const KJSO &booleanProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class BooleanPrototype : public ObjectImp {
+ public:
+ BooleanPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ enum { ToString, ValueOf };
+ };
+
+ class BooleanProtoFunc : public InternalFunctionImp {
+ public:
+ BooleanProtoFunc(int i);
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/kjs/collector.cpp
new file mode 100644
index 0000000..df79038
--- /dev/null
+++ b/JavaScriptCore/kjs/collector.cpp
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "collector.h"
+#include "object.h"
+#include "internal.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+namespace KJS {
+
+ class CollectorBlock {
+ public:
+ CollectorBlock(int s);
+ ~CollectorBlock();
+ int size;
+ int filled;
+ void** mem;
+ CollectorBlock *prev, *next;
+ };
+
+}; // namespace
+
+using namespace KJS;
+
+CollectorBlock::CollectorBlock(int s)
+ : size(s),
+ filled(0),
+ prev(0L),
+ next(0L)
+{
+ mem = new void*[size];
+ memset(mem, 0, size * sizeof(void*));
+}
+
+CollectorBlock::~CollectorBlock()
+{
+ delete [] mem;
+ mem = 0L;
+}
+
+CollectorBlock* Collector::root = 0L;
+CollectorBlock* Collector::currentBlock = 0L;
+unsigned long Collector::filled = 0;
+unsigned long Collector::softLimit = KJS_MEM_INCREMENT;
+#ifdef KJS_DEBUG_MEM
+bool Collector::collecting = false;
+#endif
+
+void* Collector::allocate(size_t s)
+{
+ if (s == 0)
+ return 0L;
+
+ if (filled >= softLimit) {
+ collect();
+ if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) // we are actually using all this memory
+ softLimit *= 2;
+ }
+
+ void *m = malloc(s);
+
+ // hack to ensure obj is protected from GC before any constructors are run
+ // (prev = marked, next = gcallowed)
+ static_cast<Imp*>(m)->prev = 0;
+ static_cast<Imp*>(m)->next = 0;
+
+ if (!root) {
+ root = new CollectorBlock(BlockSize);
+ currentBlock = root;
+ }
+
+ CollectorBlock *block = currentBlock;
+ if (!block)
+ block = root;
+
+ // search for a block with space left
+ while (block->next && block->filled == block->size)
+ block = block->next;
+
+ if (block->filled >= block->size) {
+#ifdef KJS_DEBUG_MEM
+ printf("allocating new block of size %d\n", block->size);
+#endif
+ CollectorBlock *tmp = new CollectorBlock(BlockSize);
+ block->next = tmp;
+ tmp->prev = block;
+ block = tmp;
+ }
+ currentBlock = block;
+ // look for a free spot in the block
+ void **r = block->mem;
+ while (*r)
+ r++;
+ *r = m;
+ filled++;
+ block->filled++;
+
+ if (softLimit >= KJS_MEM_LIMIT) {
+ KJScriptImp::setException("Out of memory");
+ }
+
+ return m;
+}
+
+/**
+ * Mark-sweep garbage collection.
+ */
+void Collector::collect()
+{
+#ifdef KJS_DEBUG_MEM
+ printf("collecting %d objects total\n", Imp::count);
+ collecting = true;
+#endif
+
+ // MARK: first set all ref counts to 0 ....
+ CollectorBlock *block = root;
+ while (block) {
+#ifdef KJS_DEBUG_MEM
+ printf("cleaning block filled %d out of %d\n", block->filled, block->size);
+#endif
+ Imp **r = (Imp**)block->mem;
+ assert(r);
+ for (int i = 0; i < block->size; i++, r++)
+ if (*r) {
+ (*r)->setMarked(false);
+ }
+ block = block->next;
+ }
+
+ // ... increase counter for all referenced objects recursively
+ // starting out from the set of root objects
+ if (KJScriptImp::hook) {
+ KJScriptImp *scr = KJScriptImp::hook;
+ do {
+ scr->mark();
+ scr = scr->next;
+ } while (scr != KJScriptImp::hook);
+ }
+
+ // mark any other objects that we wouldn't delete anyway
+ block = root;
+ while (block) {
+ Imp **r = (Imp**)block->mem;
+ assert(r);
+ for (int i = 0; i < block->size; i++, r++)
+ if (*r && (*r)->created() && ((*r)->refcount || !(*r)->gcAllowed()) && !(*r)->marked())
+ (*r)->mark();
+ block = block->next;
+ }
+
+ // SWEEP: delete everything with a zero refcount (garbage)
+ block = root;
+ while (block) {
+ Imp **r = (Imp**)block->mem;
+ int del = 0;
+ for (int i = 0; i < block->size; i++, r++) {
+ if (*r && ((*r)->refcount == 0) && !(*r)->marked() && (*r)->gcAllowed()) {
+ // emulate destructing part of 'operator delete()'
+ (*r)->~Imp();
+ free(*r);
+ *r = 0L;
+ del++;
+ }
+ }
+ filled -= del;
+ block->filled -= del;
+ block = block->next;
+ }
+
+ // delete the emtpy containers
+ block = root;
+ while (block) {
+ CollectorBlock *next = block->next;
+ if (block->filled == 0) {
+ if (block->prev)
+ block->prev->next = next;
+ if (block == root)
+ root = next;
+ if (next)
+ next->prev = block->prev;
+ if (block == currentBlock) // we don't want a dangling pointer
+ currentBlock = 0L;
+ assert(block != root);
+ delete block;
+ }
+ block = next;
+ }
+
+#ifdef KJS_DEBUG_MEM
+ collecting = false;
+#endif
+}
diff --git a/JavaScriptCore/kjs/collector.h b/JavaScriptCore/kjs/collector.h
new file mode 100644
index 0000000..7e88e7f
--- /dev/null
+++ b/JavaScriptCore/kjs/collector.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSCOLLECTOR_H_
+#define _KJSCOLLECTOR_H_
+
+// KJS_MEM_LIMIT and KJS_MEM_INCREMENT can be tweaked to adjust how the
+// garbage collector allocates memory. KJS_MEM_LIMIT is the largest # of objects
+// the collector will allow to be present in memory. Once this limit is reached,
+// a running script will get an "out of memory" exception.
+//
+// KJS_MEM_INCREMENT specifies the amount by which the "soft limit" on memory is
+// increased when the memory gets filled up. The soft limit is the amount after
+// which the GC will run and delete unused objects.
+//
+// If you are debugging seemingly random crashes where an object has been deleted,
+// try setting KJS_MEM_INCREMENT to something small, e.g. 300, to force garbage
+// collection to happen more often, and disable the softLimit increase &
+// out-of-memory testing code in Collector::allocate()
+
+#define KJS_MEM_LIMIT 500000
+#define KJS_MEM_INCREMENT 1000
+
+#include <stdlib.h>
+
+namespace KJS {
+
+ class Imp;
+ class CollectorBlock;
+
+ /**
+ * @short Garbage collector.
+ */
+ class Collector {
+ // disallow direct construction/destruction
+ Collector();
+ public:
+ /**
+ * Register an object with the collector. The following assumptions are
+ * made:
+ * @li the operator new() of the object class is overloaded.
+ * @li operator delete() has been overloaded as well and does not free
+ * the memory on its own.
+ *
+ * @param s Size of the memory to be registered.
+ * @return A pointer to the allocated memory.
+ */
+ static void* allocate(size_t s);
+ /**
+ * Run the garbage collection. This involves calling the delete operator
+ * on each object and freeing the used memory.
+ * In the current implemenation this will basically free all registered
+ * object regardless whether they are still references by others or not.
+ *
+ */
+ static void collect();
+ static int size() { return filled; }
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static bool collecting;
+#endif
+ private:
+ static CollectorBlock* root;
+ static CollectorBlock* currentBlock;
+ static unsigned long filled;
+ static unsigned long softLimit;
+ enum { BlockSize = 100 };
+ };
+
+};
+
+#endif
diff --git a/JavaScriptCore/kjs/configure.in.in b/JavaScriptCore/kjs/configure.in.in
new file mode 100644
index 0000000..d789ce3
--- /dev/null
+++ b/JavaScriptCore/kjs/configure.in.in
@@ -0,0 +1,51 @@
+dnl KDE JavaScript specific configure tests
+
+AC_CHECK_HEADERS(ieeefp.h float.h)
+AC_CHECK_LIB(m, isinf, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_ISINF, 1, [Define if you have isinf])
+])
+AC_CHECK_LIB(m, finite, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_FINITE, 1, [Define if you have finite])
+])
+AC_CHECK_LIB(m, _finite, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC__FINITE, 1, [Define if you have _finite])
+])
+AC_CHECK_LIB(m, isnan, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_ISNAN, 1, [Define if you have isnan])
+])
+
+AC_DEFUN(AC_CHECK_PCREPOSIX,
+[
+ AC_MSG_CHECKING([for pcreposix])
+ AC_CACHE_VAL(ac_cv_have_pcreposix,
+ [
+ ac_save_libs="$LIBS"
+ KDE_FIND_PATH(pcre-config, PCRE_CONFIG, [${prefix}/bin /usr/local/bin /opt/local/bin], [PCRE_CONFIG="" ])
+ if test -n "$PCRE_CONFIG" && $PCRE_CONFIG --libs >/dev/null 2>&1; then
+ LIBS=`$PCRE_CONFIG --libs --libs-posix`
+ CPPFLAGS="$CPPFLAGS `$PCRE_CONFIG --cflags`"
+ else
+ LIBS="-lpcre -lpcreposix"
+ fi
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+ ac_LDFLAGS_save="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $all_libraries"
+ AC_TRY_LINK(
+ [#include <pcreposix.h>],
+ [regfree(0);],
+ [ac_cv_have_pcreposix="yes"],
+ [ac_cv_have_pcreposix="no"]
+ )
+ LIBS="$ac_save_libs"
+ LDFLAGS="$ac_LDFLAGS_save"
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ ])
+ AC_MSG_RESULT($ac_cv_have_pcreposix)
+ if test "$ac_cv_have_pcreposix" = "yes"; then
+ LIBPCRE="-lpcre -lpcreposix"
+ AC_DEFINE(HAVE_PCREPOSIX, 1, [Define if you have pcreposix libraries and header files.])
+ fi
+])
+AC_CHECK_PCREPOSIX
+AC_SUBST(LIBPCRE)
diff --git a/JavaScriptCore/kjs/create_hash_table b/JavaScriptCore/kjs/create_hash_table
new file mode 100755
index 0000000..85c6744
--- /dev/null
+++ b/JavaScriptCore/kjs/create_hash_table
@@ -0,0 +1,116 @@
+#! /usr/bin/perl
+
+$file = $ARGV[0];
+open(IN, $file) or die "No such file $file";
+
+@keys = ();
+@values = ();
+@attrs = ();
+
+my $inside = 0;
+my $name;
+my $size;
+my $hashsize;
+my $banner = 0;
+
+while (<IN>) {
+ chop;
+ s/^\s*//g;
+ if (/^\#|^$/) {
+ # comment. do nothing
+ } elsif (/^\@begin\s*(\w+)\s*(\d+)\s*$/ && !$inside) {
+ $inside = 1;
+ $name = $1;
+ $hashsize = $2;
+ } elsif (/^\@end\s*$/ && $inside) {
+ calcTable();
+ output();
+ @keys = ();
+ @values = ();
+ @attrs = ();
+ $inside = 0;
+ } elsif (/^(\w+)\s*([\w\:]+)\s*([\w\|]*)\s*$/ && $inside) {
+ push(@keys, $1);
+ push(@values, $2);
+ push(@attrs, length($3) > 0 ? $3 : "0");
+ } else {
+ die "invalid data";
+ }
+}
+
+die "missing closing \@end" if ($inside);
+
+sub calcTable() {
+ @table = ();
+ @links = ();
+ $size = $hashsize;
+ my $collisions = 0;
+ my $i = 0;
+ foreach $key (@keys) {
+ my $h = hashValue($key) % $hashsize;
+ while (defined($table[$h])) {
+ if (defined($links[$h])) {
+ $h = $links[$h];
+ } else {
+ $collisions++;
+ $links[$h] = $size;
+ $h = $size;
+ $size++;
+ }
+ }
+ $table[$h] = $i;
+ $i++;
+ }
+
+# print "// Number of collisions: $collisions\n";
+# printf "total size: $size\n";
+# my $i = 0;
+# foreach $entry (@table) {
+# print "$i " . $entry;
+# print " -> " . $links[$i] if (defined($links[$i]));
+# print "\n";
+# $i++;
+# }
+}
+
+sub hashValue {
+ @chars = split(/ */, @_[0]);
+ my $val = 0;
+ foreach $c (@chars) {
+ $val += ord($c);
+ }
+ return $val;
+}
+
+sub output {
+ if (!$banner) {
+ $banner = 1;
+ print "/* automatically generated from $file. DO NOT EDIT ! */\n";
+ }
+
+ print "\nnamespace KJS {\n";
+ print "\nconst struct HashEntry2 ${name}Entries[] = {\n";
+ my $i = 0;
+ foreach $entry (@table) {
+ if (defined($entry)) {
+ my $key = $keys[$entry];
+ print " \{ \"" . $key . "\"";
+ print ", " . $values[$entry];
+ print ", " . $attrs[$entry] . ", ";
+ if (defined($links[$i])) {
+ print "&${name}Entries[$links[$i]]" . " \}";
+ } else {
+ print "0 \}"
+ }
+ } else {
+ print " \{ 0, 0, 0, 0 \}";
+ }
+ print "," unless ($i == $size - 1);
+ print "\n";
+ $i++;
+ }
+ print "};\n";
+ print "\nconst struct HashTable2 $name = ";
+ print "\{ 2, $size, ${name}Entries, $hashsize \};\n\n";
+ print "}; // namespace\n";
+}
diff --git a/JavaScriptCore/kjs/date_object.cpp b/JavaScriptCore/kjs/date_object.cpp
new file mode 100644
index 0000000..ab81504
--- /dev/null
+++ b/JavaScriptCore/kjs/date_object.cpp
@@ -0,0 +1,466 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifndef HAVE_SYS_TIMEB_H
+#define HAVE_SYS_TIMEB_H 0
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+# include <time.h>
+# endif
+#endif
+#if HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif // HAVE_SYS_PARAM_H
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <locale.h>
+
+#include "kjs.h"
+#include "date_object.h"
+
+namespace KJS {
+
+ class DateObjectFunc : public InternalFunctionImp {
+ public:
+ DateObjectFunc(int i) : id(i) { };
+ Completion execute(const List &);
+ enum { Parse, UTC };
+ private:
+ int id;
+ };
+
+ class DateProtoFunc : public InternalFunctionImp {
+ public:
+ DateProtoFunc(int i, bool u);
+ Completion execute(const List &);
+ enum { ToString, ToDateString, ToTimeString, ToLocaleString,
+ ToLocaleDateString, ToLocaleTimeString, ValueOf, GetTime,
+ GetFullYear, GetMonth, GetDate, GetDay, GetHours, GetMinutes,
+ GetSeconds, GetMilliSeconds, GetTimezoneOffset, SetTime,
+ SetMilliSeconds, SetSeconds, SetMinutes, SetHours, SetDate,
+ SetMonth, SetFullYear, ToUTCString,
+ // non-normative properties (Appendix B)
+ GetYear, SetYear, ToGMTString };
+ private:
+ int id;
+ bool utc;
+ };
+
+ // helper functions
+ KJSO parseDate(const String &s);
+ KJSO timeClip(const KJSO &t);
+};
+
+using namespace KJS;
+
+KJSO KJS::parseDate(const String &s)
+{
+ UString u = s.value();
+ int firstSlash = u.find('/');
+ if ( firstSlash == -1 )
+ {
+ /* TODO parse dates like "December 25, 1995 23:15:00"*/
+ fprintf(stderr,"KJS::parseDate parsing for this format isn't implemented\n%s", u.ascii());
+ return Number(0);
+ }
+ else
+ {
+ // Found 12/31/2099 on some website -> obviously MM/DD/YYYY
+ int month = u.substr(0,firstSlash).toULong();
+ int secondSlash = u.find('/',firstSlash+1);
+ //fprintf(stdout,"KJS::parseDate firstSlash=%d, secondSlash=%d\n", firstSlash, secondSlash);
+ if ( secondSlash == -1 )
+ {
+ fprintf(stderr,"KJS::parseDate parsing for this format isn't implemented\n%s", u.ascii());
+ return Number(0);
+ }
+ int day = u.substr(firstSlash+1,secondSlash-firstSlash-1).toULong();
+ int year = u.substr(secondSlash+1).toULong();
+ //fprintf(stdout,"KJS::parseDate day=%d, month=%d, year=%d\n", day, month, year);
+ struct tm t;
+ memset( &t, 0, sizeof(t) );
+ year = (year > 2037) ? 2037 : year; // mktime is limited to 2037 !!!
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = month-1; // mktime wants 0-11 for some reason
+ t.tm_mday = day;
+ time_t seconds = mktime(&t);
+ if ( seconds == -1 )
+ {
+ fprintf(stderr,"KJS::parseDate mktime returned -1.\n%s", u.ascii());
+ return Undefined();
+ }
+ else
+ return Number(seconds * 1000.0);
+ }
+}
+
+KJSO KJS::timeClip(const KJSO &t)
+{
+ /* TODO */
+ return t;
+}
+
+DateObject::DateObject(const Object& funcProto, const Object &dateProto)
+ : ConstructorImp(funcProto, 7)
+{
+ // ECMA 15.9.4.1 Date.prototype
+ setPrototypeProperty(dateProto);
+}
+
+// ECMA 15.9.2
+Completion DateObject::execute(const List &)
+{
+ time_t t = time(0L);
+ UString s(ctime(&t));
+
+ // return formatted string minus trailing \n
+ return Completion(ReturnValue, String(s.substr(0, s.size() - 1)));
+}
+
+// ECMA 15.9.3
+Object DateObject::construct(const List &args)
+{
+ KJSO value;
+
+ int numArgs = args.size();
+
+ if (numArgs == 0) { // new Date() ECMA 15.9.3.3
+#if HAVE_SYS_TIMEB_H
+# if defined(__BORLANDC__)
+ struct timeb timebuffer;
+ ftime(&timebuffer);
+# else
+ struct _timeb timebuffer;
+ _ftime(&timebuffer);
+# endif
+ double utc = floor((double)timebuffer.time * 1000.0 + (double)timebuffer.millitm);
+#else
+ struct timeval tv;
+ gettimeofday(&tv, 0L);
+ double utc = floor((double)tv.tv_sec * 1000.0 + (double)tv.tv_usec / 1000.0);
+#endif
+ value = Number(utc);
+ } else if (numArgs == 1) {
+ KJSO p = args[0].toPrimitive();
+ if (p.isA(StringType))
+ value = parseDate(p.toString());
+ else
+ value = p.toNumber();
+ } else {
+ struct tm t;
+ memset(&t, 0, sizeof(t));
+ Number y = args[0].toNumber();
+ /* TODO: check for NaN */
+ int year = y.toInt32();
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = args[1].toInt32();
+ t.tm_mday = (numArgs >= 3) ? args[2].toInt32() : 1;
+ t.tm_hour = (numArgs >= 4) ? args[3].toInt32() : 0;
+ t.tm_min = (numArgs >= 5) ? args[4].toInt32() : 0;
+ t.tm_sec = (numArgs >= 6) ? args[5].toInt32() : 0;
+ t.tm_isdst = -1;
+ int ms = (numArgs >= 7) ? args[6].toInt32() : 0;
+ value = Number(mktime(&t) * 1000.0 + ms);
+ }
+
+ return Object::create(DateClass, timeClip(value));
+}
+
+KJSO DateObject::get(const UString &p) const
+{
+ int id;
+
+ if (p == "parse")
+ id = DateObjectFunc::Parse;
+ else if (p == "UTC")
+ id = DateObjectFunc::UTC;
+ else
+ return Imp::get(p);
+
+ return Function(new DateObjectFunc(id));
+}
+
+// ECMA 15.9.4.2 - 3
+Completion DateObjectFunc::execute(const List &args)
+{
+ KJSO result;
+
+ if (id == Parse)
+ if (args[0].isA(StringType))
+ result = parseDate(args[0].toString());
+ else
+ result = Undefined();
+ else {
+ struct tm t;
+ memset(&t, 0, sizeof(t));
+ int n = args.size();
+ Number y = args[0].toNumber();
+ /* TODO: check for NaN */
+ int year = y.toInt32();
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = args[1].toInt32();
+ t.tm_mday = (n >= 3) ? args[2].toInt32() : 1;
+ t.tm_hour = (n >= 4) ? args[3].toInt32() : 0;
+ t.tm_min = (n >= 5) ? args[4].toInt32() : 0;
+ t.tm_sec = (n >= 6) ? args[5].toInt32() : 0;
+ int ms = (n >= 7) ? args[6].toInt32() : 0;
+ result = Number(mktime(&t) * 1000.0 + ms);
+ }
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.9.4
+DatePrototype::DatePrototype(const Object& proto)
+ : ObjectImp(DateClass, Number(NaN), proto)
+{
+ // The constructor will be added later in DateObject's constructor
+}
+
+KJSO DatePrototype::get(const UString &p) const
+{
+ int id;
+
+ if (p == "toString" || p == "toUTCString")
+ id = DateProtoFunc::ToString;
+ else if (p == "toDateString")
+ id = DateProtoFunc::ToDateString;
+ else if (p == "toTimeString")
+ id = DateProtoFunc::ToTimeString;
+ else if (p == "toLocaleString")
+ id = DateProtoFunc::ToLocaleString;
+ else if (p == "toLocaleDateString")
+ id = DateProtoFunc::ToLocaleDateString;
+ else if (p == "toLocaleTimeString")
+ id = DateProtoFunc::ToLocaleTimeString;
+ else if (p == "valueOf")
+ id = DateProtoFunc::ValueOf;
+ else if (p == "getTime")
+ id = DateProtoFunc::GetTime;
+ else if (p == "getFullYear" || p == "getUTCFullYear")
+ id = DateProtoFunc::GetFullYear;
+ else if (p == "toGMTString")
+ id = DateProtoFunc::ToGMTString;
+ else if (p == "getMonth" || p == "getUTCMonth")
+ id = DateProtoFunc::GetMonth;
+ else if (p == "getDate" || p == "getUTCDate")
+ id = DateProtoFunc::GetDate;
+ else if (p == "getDay" || p == "getUTCDay")
+ id = DateProtoFunc::GetDay;
+ else if (p == "getHours" || p == "getUTCHours")
+ id = DateProtoFunc::GetHours;
+ else if (p == "getMinutes" || p == "getUTCMinutes")
+ id = DateProtoFunc::GetMinutes;
+ else if (p == "getSeconds" || p == "getUTCSeconds")
+ id = DateProtoFunc::GetSeconds;
+ else if (p == "getMilliseconds" || p == "getUTCMilliseconds")
+ id = DateProtoFunc::GetMilliSeconds;
+ else if (p == "getTimezoneOffset")
+ id = DateProtoFunc::GetTimezoneOffset;
+ else if (p == "setTime")
+ id = DateProtoFunc::SetTime;
+ else if (p == "setMilliseconds" || p == "setUTCMilliseconds")
+ id = DateProtoFunc::SetMilliSeconds;
+ else if (p == "setSeconds" || p == "setUTCSeconds")
+ id = DateProtoFunc::SetSeconds;
+ else if (p == "setMinutes" || p == "setUTCMinutes")
+ id = DateProtoFunc::SetMinutes;
+ else if (p == "setHours" || p == "setUTCHours")
+ id = DateProtoFunc::SetHours;
+ else if (p == "setDate" || p == "setUTCDate")
+ id = DateProtoFunc::SetDate;
+ else if (p == "setMonth" || p == "setUTCMonth")
+ id = DateProtoFunc::SetMonth;
+ else if (p == "setFullYear" || p == "setUTCFullYear")
+ id = DateProtoFunc::SetFullYear;
+ else if (p == "setYear" )
+ id = DateProtoFunc::SetYear;
+ // non-normative
+ else if (p == "getYear")
+ id = DateProtoFunc::GetYear;
+ else if (p == "toGMTString")
+ id = DateProtoFunc::ToGMTString;
+ else
+ return Undefined();
+
+ bool utc = (p.find("UTC") >= 0) ? true : false;
+ return Function(new DateProtoFunc(id, utc));
+}
+
+DateProtoFunc::DateProtoFunc(int i, bool u) : id(i), utc(u)
+{
+}
+
+Completion DateProtoFunc::execute(const List &args)
+{
+ KJSO result;
+ UString s;
+ const int bufsize=100;
+ char timebuffer[bufsize];
+ char *oldlocale = setlocale(LC_TIME,NULL);
+ if (!oldlocale)
+ oldlocale = setlocale(LC_ALL, NULL);
+ Object thisObj = Object::dynamicCast(thisValue());
+ KJSO v = thisObj.internalValue();
+ double milli = v.toNumber().value();
+ time_t tv = (time_t) floor(milli / 1000.0);
+ int ms = int(milli - tv * 1000.0);
+
+ struct tm *t;
+ if (utc)
+ t = gmtime(&tv);
+ else
+ t = localtime(&tv);
+
+ switch (id) {
+ case ToString:
+ s = ctime(&tv);
+ result = String(s.substr(0, s.size() - 1));
+ break;
+ case ToDateString:
+ case ToTimeString:
+ case ToGMTString:
+ setlocale(LC_TIME,"C");
+ if (id == DateProtoFunc::ToDateString) {
+ strftime(timebuffer, bufsize, "%x",t);
+ } else if (id == DateProtoFunc::ToTimeString) {
+ strftime(timebuffer, bufsize, "%X",t);
+ } else {
+ t = gmtime(&tv);
+ strftime(timebuffer, bufsize, "%a, %d-%b-%y %H:%M:%S %Z", t);
+ }
+ setlocale(LC_TIME,oldlocale);
+ result = String(timebuffer);
+ break;
+ case ToLocaleString:
+ strftime(timebuffer, bufsize, "%c", t);
+ result = String(timebuffer);
+ break;
+ case ToLocaleDateString:
+ strftime(timebuffer, bufsize, "%x", t);
+ result = String(timebuffer);
+ break;
+ case ToLocaleTimeString:
+ strftime(timebuffer, bufsize, "%X", t);
+ result = String(timebuffer);
+ break;
+ case ValueOf:
+ result = Number(milli);
+ break;
+ case GetTime:
+ if (thisObj.getClass() == DateClass)
+ result = Number(milli);
+ else
+ result = Error::create(TypeError);
+ break;
+ case GetYear:
+ result = Number(t->tm_year);
+ break;
+ case GetFullYear:
+ result = Number(1900 + t->tm_year);
+ break;
+ case GetMonth:
+ result = Number(t->tm_mon);
+ break;
+ case GetDate:
+ result = Number(t->tm_mday);
+ break;
+ case GetDay:
+ result = Number(t->tm_wday);
+ break;
+ case GetHours:
+ result = Number(t->tm_hour);
+ break;
+ case GetMinutes:
+ result = Number(t->tm_min);
+ break;
+ case GetSeconds:
+ result = Number(t->tm_sec);
+ break;
+ case GetMilliSeconds:
+ result = Undefined();
+ break;
+ case GetTimezoneOffset:
+#if defined BSD || defined(__APPLE__)
+ result = Number(-( t->tm_gmtoff / 60 ) + ( t->tm_isdst ? 60 : 0 ));
+#else
+# if defined(__BORLANDC__)
+#error please add daylight savings offset here!
+ result = Number(_timezone / 60 - (_daylight ? 60 : 0));
+# else
+ result = Number(( timezone / 60 - ( daylight ? 60 : 0 )));
+# endif
+#endif
+ break;
+ case SetTime:
+ milli = args[0].round();
+ result = Number(milli);
+ thisObj.setInternalValue(result);
+ break;
+ case SetMilliSeconds:
+ ms = args[0].toInt32();
+ break;
+ case SetSeconds:
+ t->tm_sec = args[0].toInt32();
+ break;
+ case SetMinutes:
+ t->tm_min = args[0].toInt32();
+ break;
+ case SetHours:
+ t->tm_hour = args[0].toInt32();
+ break;
+ case SetDate:
+ t->tm_mday = args[0].toInt32();
+ break;
+ case SetMonth:
+ t->tm_mon = args[0].toInt32();
+ break;
+ case SetFullYear:
+ t->tm_year = args[0].toInt32() - 1900;
+ break;
+ case SetYear:
+ t->tm_year = args[0].toInt32() >= 1900 ? args[0].toInt32() - 1900 : args[0].toInt32();
+ break;
+ }
+
+ if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
+ id == SetMinutes || id == SetHours || id == SetDate ||
+ id == SetMonth || id == SetFullYear ) {
+ result = Number(mktime(t) * 1000.0 + ms);
+ thisObj.setInternalValue(result);
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/JavaScriptCore/kjs/date_object.h b/JavaScriptCore/kjs/date_object.h
new file mode 100644
index 0000000..5eed675
--- /dev/null
+++ b/JavaScriptCore/kjs/date_object.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _DATE_OBJECT_H_
+#define _DATE_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class DateObject : public ConstructorImp {
+ public:
+ DateObject(const Object& funcProto, const Object &dateProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ KJSO get(const UString &p) const;
+ };
+
+ class DatePrototype : public ObjectImp {
+ public:
+ DatePrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/debugger.cpp b/JavaScriptCore/kjs/debugger.cpp
new file mode 100644
index 0000000..e0f3859
--- /dev/null
+++ b/JavaScriptCore/kjs/debugger.cpp
@@ -0,0 +1,229 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef KJS_DEBUGGER
+
+#include "debugger.h"
+#include "kjs.h"
+#include "internal.h"
+#include "ustring.h"
+
+using namespace KJS;
+
+Debugger::Debugger(KJScript *engine)
+ : eng(0L),
+ sid(-1)
+{
+ attach(engine);
+}
+
+Debugger::~Debugger()
+{
+ detach();
+}
+
+void Debugger::attach(KJScript *e)
+{
+ dmode = Disabled;
+ if (e) {
+ if (!eng || e->rep != eng->rep) {
+ eng = e;
+ eng->rep->attachDebugger(this);
+ }
+ } else {
+ eng = 0L;
+ }
+ reset();
+}
+
+KJScript *Debugger::engine() const
+{
+ return eng;
+}
+
+void Debugger::detach()
+{
+ reset();
+ if (!eng)
+ return;
+ eng->rep->attachDebugger(0L);
+ eng = 0L;
+}
+
+void Debugger::setMode(Mode m)
+{
+ dmode = m;
+}
+
+Debugger::Mode Debugger::mode() const
+{
+ return dmode;
+}
+
+// supposed to be overriden by the user
+bool Debugger::stopEvent()
+{
+ return true;
+}
+
+void Debugger::callEvent(const UString &, const UString &)
+{
+}
+
+void Debugger::returnEvent()
+{
+}
+
+void Debugger::reset()
+{
+ l = -1;
+}
+
+int Debugger::freeSourceId() const
+{
+ return eng ? eng->rep->sourceId()+1 : -1;
+}
+
+bool Debugger::setBreakpoint(int id, int line)
+{
+ if (!eng)
+ return false;
+ return eng->rep->setBreakpoint(id, line, true);
+}
+
+bool Debugger::deleteBreakpoint(int id, int line)
+{
+ if (!eng)
+ return false;
+ return eng->rep->setBreakpoint(id, line, false);
+}
+
+void Debugger::clearAllBreakpoints(int id)
+{
+ if (!eng)
+ return;
+ eng->rep->setBreakpoint(id, -1, false);
+}
+
+UString Debugger::varInfo(const UString &ident)
+{
+ if (!eng)
+ return UString();
+
+ int dot = ident.find('.');
+ if (dot < 0)
+ dot = ident.size();
+ UString sub = ident.substr(0, dot);
+ KJSO obj;
+ // resolve base
+ if (sub == "this") {
+ obj = Context::current()->thisValue();
+ } else {
+ const List *chain = Context::current()->pScopeChain();
+ ListIterator scope = chain->begin();
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+ obj = scope->get(ident);
+ break;
+ }
+ scope++;
+ }
+ if (scope == chain->end())
+ return UString();
+ }
+ // look up each part of a.b.c.
+ while (dot < ident.size()) {
+ int olddot = dot;
+ dot = ident.find('.', olddot+1);
+ if (dot < 0)
+ dot = ident.size();
+ sub = ident.substr(olddot+1, dot-olddot-1);
+ obj = obj.get(sub);
+ if (!obj.isDefined())
+ break;
+ }
+
+ return sub + "=" + objInfo(obj) + ":" + UString(obj.imp()->typeInfo()->name);
+}
+
+// called by varInfo() and recursively by itself on each properties
+UString Debugger::objInfo(const KJSO &obj) const
+{
+ const char *cnames[] = { "Undefined", "Array", "String", "Boolean",
+ "Number", "Object", "Date", "RegExp",
+ "Error", "Function" };
+ PropList *plist = obj.imp()->propList(0, 0, false);
+ if (!plist)
+ return obj.toString().value();
+ else {
+ UString result = "{";
+ while (1) {
+ result += plist->name + "=";
+ KJSO p = obj.get(plist->name);
+ result += objInfo(p) + ":";
+ Object obj = Object::dynamicCast(p);
+ if (obj.isNull())
+ result += p.imp()->typeInfo()->name;
+ else
+ result += cnames[int(obj.getClass())];
+ plist = plist->next;
+ if (!plist)
+ break;
+ result += ",";
+ }
+ result += "}";
+ return result;
+ }
+}
+
+bool Debugger::setVar(const UString &ident, const KJSO &value)
+{
+ if (!eng)
+ return false;
+ const List *chain = Context::current()->pScopeChain();
+ ListIterator scope = chain->begin();
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+ if (!scope->canPut(ident))
+ return false;
+ scope->put(ident, value);
+ return true;
+ }
+ scope++;
+ }
+ // didn't find variable
+ return false;
+}
+
+// called from the scripting engine each time a statement node is hit.
+bool Debugger::hit(int line, bool breakPoint)
+{
+ l = line;
+ if (!eng)
+ return true;
+
+ if (!breakPoint && ( mode() == Continue || mode() == Disabled ) )
+ return true;
+
+ bool ret = stopEvent();
+ eng->init(); // in case somebody used a different interpreter meanwhile
+ return ret;
+}
+
+#endif
diff --git a/JavaScriptCore/kjs/debugger.h b/JavaScriptCore/kjs/debugger.h
new file mode 100644
index 0000000..b0e97fe
--- /dev/null
+++ b/JavaScriptCore/kjs/debugger.h
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSDEBUGGER_H_
+#define _KJSDEBUGGER_H_
+
+#include "internal.h"
+
+namespace KJS {
+
+ //
+ // NOTE: this interface is not ready, yet. Do not use unless you
+ // don't mind source and binary incompatible changes that may arise
+ // before the final version is released.
+ //
+
+#ifdef KJS_DEBUGGER
+ class Debugger {
+ friend class KJScriptImp;
+ friend class StatementNode;
+ friend class DeclaredFunctionImp;
+ friend class FunctionImp;
+ public:
+ /**
+ * Available modes of the debugger.
+ */
+ enum Mode { Disabled = 0, Next, Step, Continue, Stop };
+ /**
+ * Construct a debugger and attach it to the scripting engine s.
+ */
+ Debugger(KJScript *s);
+ /**
+ * Destruct the debugger and detach from the scripting engine we
+ * might have been attached to.
+ */
+ virtual ~Debugger();
+ /**
+ * Attaches the debugger to specified scripting engine.
+ */
+ void attach(KJScript *e);
+ /**
+ * Returns the engine the interpreter is currently attached to. Null
+ * if there isn't any.
+ */
+ KJScript* engine() const;
+ /**
+ * Detach the debugger from any scripting engine.
+ */
+ void detach();
+ /**
+ * Set debugger into specified mode. This will influence further behaviour
+ * if execution of the programm is started or continued.
+ */
+ virtual void setMode(Mode m);
+ /**
+ * Returns the current operation mode.
+ */
+ Mode mode() const;
+ /**
+ * Returns the line number the debugger currently has stopped at.
+ * -1 if the debugger is not in a break status.
+ */
+ int lineNumber() const { return l; }
+ /**
+ * Returns the source id the debugger currently has stopped at.
+ * -1 if the debugger is not in a break status.
+ */
+ int sourceId() const { return sid; }
+ /**
+ * Sets a breakpoint in the first statement where line lies in between
+ * the statements range. Returns true if sucessfull, false if no
+ * matching statement could be found.
+ */
+ bool setBreakpoint(int id, int line);
+ bool deleteBreakpoint(int id, int line);
+ void clearAllBreakpoints(int id=-1);
+ /**
+ * Returns the value of ident out of the current context in string form
+ */
+ UString varInfo(const UString &ident);
+ /**
+ * Set variable ident to value. Returns true if successful, false if
+ * the specified variable doesn't exist or isn't writable.
+ */
+ bool setVar(const UString &ident, const KJSO &value);
+
+ protected:
+ /**
+ * Invoked in case a breakpoint or the next statement is reached in step
+ * mode. The return value decides whether execution will continue. True
+ * denotes continuation, false an abortion, respectively.
+ *
+ * The default implementation does nothing. Overload this method if
+ * you want to process this event.
+ */
+ virtual bool stopEvent();
+ /**
+ * Returns an integer that will be assigned to the code passed
+ * next to one of the KJScript::evaluate() methods. It's basically
+ * a counter to will only be reset to 0 on KJScript::clear().
+ *
+ * This information is useful in case you evaluate multiple blocks of
+ * code containing some function declarations. Keep a map of source id/
+ * code pairs, query sourceId() in case of a stopEvent() and update
+ * your debugger window with the matching source code.
+ */
+ int freeSourceId() const;
+ /**
+ * Invoked on each function call. Use together with @ref returnEvent
+ * if you want to keep track of the call stack.
+ */
+ virtual void callEvent(const UString &fn = UString::null,
+ const UString &s = UString::null);
+ /**
+ * Invoked on each function exit.
+ */
+ virtual void returnEvent();
+
+ private:
+ void reset();
+ bool hit(int line, bool breakPoint);
+ void setSourceId(int i) { sid = i; }
+ UString objInfo(const KJSO &obj) const;
+
+ KJScript *eng;
+ Mode dmode;
+ int l;
+ int sid;
+ };
+#endif
+
+};
+
+#endif
diff --git a/JavaScriptCore/kjs/error_object.cpp b/JavaScriptCore/kjs/error_object.cpp
new file mode 100644
index 0000000..a5aa6d8
--- /dev/null
+++ b/JavaScriptCore/kjs/error_object.cpp
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "internal.h"
+#include "error_object.h"
+#include "debugger.h"
+
+using namespace KJS;
+
+const char *ErrorObject::errName[] = {
+ "No Error",
+ "Error",
+ "EvalError",
+ "RangeError",
+ "ReferenceError",
+ "SyntaxError",
+ "TypeError",
+ "URIError"
+};
+
+ErrorObject::ErrorObject(const Object &funcProto, const Object &errProto,
+ ErrorType t)
+ : ConstructorImp(funcProto, 1), errType(t)
+{
+ // ECMA 15.11.3.1 Error.prototype
+ setPrototypeProperty(errProto);
+ const char *n = errName[errType];
+
+ put("name", String(n));
+}
+
+ErrorObject::ErrorObject(const Object& proto, ErrorType t,
+ const char *m, int l)
+ : ConstructorImp(proto, 1), errType(t)
+{
+ const char *n = errName[errType];
+
+ put("name", String(n));
+ put("message", String(m));
+ put("line", Number(l));
+#ifdef KJS_DEBUGGER
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ if (dbg)
+ put("sid", Number(dbg->sourceId()));
+#endif
+}
+
+// ECMA 15.9.2
+Completion ErrorObject::execute(const List &args)
+{
+ // "Error()" gives the sames result as "new Error()"
+ return Completion(ReturnValue, construct(args));
+}
+
+// ECMA 15.9.3
+Object ErrorObject::construct(const List &args)
+{
+ if (args.isEmpty() == 1 || !args[0].isDefined())
+ return Object::create(ErrorClass, Undefined());
+
+ String message = args[0].toString();
+ return Object::create(ErrorClass, message);
+}
+
+Object ErrorObject::create(ErrorType e, const char *m, int l)
+{
+ Global global(Global::current());
+ KJSO prot = Global::current().get("[[Error.prototype]]");
+ assert(prot.isObject());
+ Imp *d = new ErrorObject(Object(prot.imp()), e, m, l);
+
+ return Object(d);
+}
+
+// ECMA 15.9.4
+ErrorPrototype::ErrorPrototype(const Object& proto)
+ : ObjectImp(ErrorClass, Undefined(), proto)
+{
+ // The constructor will be added later in ErrorObject's constructor
+}
+
+KJSO ErrorPrototype::get(const UString &p) const
+{
+ const char *s;
+
+ /* TODO: are these properties dynamic, i.e. should we put() them ? */
+ if (p == "name")
+ s = "Error";
+ else if (p == "message")
+ s = "Error message.";
+ else if (p == "toString")
+ return Function(new ErrorProtoFunc());
+ else
+ return Imp::get(p);
+
+ return String(s);
+}
+
+Completion ErrorProtoFunc::execute(const List &)
+{
+ // toString()
+ const char *s = "Error message.";
+
+ return Completion(ReturnValue, String(s));
+}
+
diff --git a/JavaScriptCore/kjs/error_object.h b/JavaScriptCore/kjs/error_object.h
new file mode 100644
index 0000000..8e515f0
--- /dev/null
+++ b/JavaScriptCore/kjs/error_object.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ERROR_OBJECT_H_
+#define _ERROR_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ErrorObject : public ConstructorImp {
+ public:
+ ErrorObject(const Object &funcProto, const Object &errProto,
+ ErrorType t = GeneralError);
+ ErrorObject(const Object& proto, ErrorType t, const char *m, int l = -1);
+ Completion execute(const List &);
+ Object construct(const List &);
+ static Object create(ErrorType e, const char *m, int ln);
+ private:
+ ErrorType errType;
+ static const char *errName[];
+ };
+
+ class ErrorPrototype : public ObjectImp {
+ public:
+ ErrorPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+ class ErrorProtoFunc : public InternalFunctionImp {
+ public:
+ ErrorProtoFunc() { }
+ Completion execute(const List &);
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/function.cpp b/JavaScriptCore/kjs/function.cpp
new file mode 100644
index 0000000..22db1d2
--- /dev/null
+++ b/JavaScriptCore/kjs/function.cpp
@@ -0,0 +1,355 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "function.h"
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "nodes.h"
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace KJS;
+
+const TypeInfo FunctionImp::info = { "Function", FunctionType,
+ &ObjectImp::info, 0, 0 };
+const TypeInfo InternalFunctionImp::info = { "InternalFunction",
+ InternalFunctionType,
+ &FunctionImp::info, 0, 0 };
+const TypeInfo ConstructorImp::info = { "Function", ConstructorType,
+ &InternalFunctionImp::info, 0, 0 };
+
+namespace KJS {
+
+ class Parameter {
+ public:
+ Parameter(const UString &n) : name(n), next(0L) { }
+ ~Parameter() { delete next; }
+ UString name;
+ Parameter *next;
+ };
+
+};
+
+FunctionImp::FunctionImp()
+ : ObjectImp(/*TODO*/BooleanClass), param(0L)
+{
+}
+
+FunctionImp::FunctionImp(const UString &n)
+ : ObjectImp(/*TODO*/BooleanClass), ident(n), param(0L)
+{
+}
+
+FunctionImp::~FunctionImp()
+{
+ delete param;
+}
+
+KJSO FunctionImp::thisValue() const
+{
+ return KJSO(Context::current()->thisValue());
+}
+
+void FunctionImp::addParameter(const UString &n)
+{
+ Parameter **p = ¶m;
+ while (*p)
+ p = &(*p)->next;
+
+ *p = new Parameter(n);
+}
+
+void FunctionImp::setLength(int l)
+{
+ put("length", Number(l), ReadOnly|DontDelete|DontEnum);
+}
+
+// ECMA 10.1.3
+void FunctionImp::processParameters(const List *args)
+{
+ KJSO variable = Context::current()->variableObject();
+
+ assert(args);
+
+#ifdef KJS_VERBOSE
+ fprintf(stderr, "---------------------------------------------------\n"
+ "processing parameters for %s call\n",
+ name().isEmpty() ? "(internal)" : name().ascii());
+#endif
+
+ if (param) {
+ ListIterator it = args->begin();
+ Parameter **p = ¶m;
+ while (*p) {
+ if (it != args->end()) {
+#ifdef KJS_VERBOSE
+ fprintf(stderr, "setting parameter %s ", (*p)->name.ascii());
+ printInfo("to", *it);
+#endif
+ variable.put((*p)->name, *it);
+ it++;
+ } else
+ variable.put((*p)->name, Undefined());
+ p = &(*p)->next;
+ }
+ }
+#ifdef KJS_VERBOSE
+ else {
+ for (int i = 0; i < args->size(); i++)
+ printInfo("setting argument", (*args)[i]);
+ }
+#endif
+#ifdef KJS_DEBUGGER
+ if (KJScriptImp::current()->debugger()) {
+ UString argStr;
+ for (int i = 0; i < args->size(); i++) {
+ if (i > 0)
+ argStr += ", ";
+ Imp *a = (*args)[i].imp();
+ argStr += a->toString().value() + " : " + UString(a->typeInfo()->name);
+ }
+ UString n = name().isEmpty() ? UString( "(internal)" ) : name();
+ KJScriptImp::current()->debugger()->callEvent(n, argStr);
+ }
+#endif
+}
+
+// ECMA 13.2.1
+KJSO FunctionImp::executeCall(Imp *thisV, const List *args)
+{
+ return executeCall(thisV,args,0);
+}
+
+KJSO FunctionImp::executeCall(Imp *thisV, const List *args, const List *extraScope)
+{
+ bool dummyList = false;
+ if (!args) {
+ args = new List();
+ dummyList = true;
+ }
+
+ KJScriptImp *curr = KJScriptImp::current();
+ Context *save = curr->context();
+
+ Context *ctx = new Context(codeType(), save, this, args, thisV);
+ curr->setContext(ctx);
+
+ int numScopes = 0;
+ if (extraScope) {
+ ListIterator scopeIt = extraScope->begin();
+ for (; scopeIt != extraScope->end(); scopeIt++) {
+ KJSO obj(*scopeIt);
+ ctx->pushScope(obj);
+ numScopes++;
+ }
+ }
+
+ // assign user supplied arguments to parameters
+ processParameters(args);
+
+ Completion comp = execute(*args);
+
+ if (dummyList)
+ delete args;
+
+ int i;
+ for (i = 0; i < numScopes; i++)
+ ctx->popScope();
+
+ put("arguments", Null());
+ delete ctx;
+ curr->setContext(save);
+
+#ifdef KJS_VERBOSE
+ if (comp.complType() == Throw)
+ printInfo("throwing", comp.value());
+ else if (comp.complType() == ReturnValue)
+ printInfo("returning", comp.value());
+ else
+ fprintf(stderr, "returning: undefined\n");
+#endif
+#ifdef KJS_DEBUGGER
+ if (KJScriptImp::current()->debugger())
+ KJScriptImp::current()->debugger()->returnEvent();
+#endif
+
+ if (comp.complType() == Throw)
+ return comp.value();
+ else if (comp.complType() == ReturnValue)
+ return comp.value();
+ else
+ return Undefined();
+}
+
+UString FunctionImp::name() const
+{
+ return ident;
+}
+
+InternalFunctionImp::InternalFunctionImp()
+{
+}
+
+InternalFunctionImp::InternalFunctionImp(int l)
+{
+ if (l >= 0)
+ setLength(l);
+}
+
+InternalFunctionImp::InternalFunctionImp(const UString &n)
+ : FunctionImp(n)
+{
+}
+
+String InternalFunctionImp::toString() const
+{
+ if (name().isNull())
+ return UString("(Internal function)");
+ else
+ return UString("function " + name() + "()");
+}
+
+Completion InternalFunctionImp::execute(const List &)
+{
+ return Completion(ReturnValue, Undefined());
+}
+
+ConstructorImp::ConstructorImp() {
+ setPrototype(Global::current().functionPrototype());
+ // TODO ??? put("constructor", this);
+ setLength(1);
+}
+
+ConstructorImp::ConstructorImp(const UString &n)
+ : InternalFunctionImp(n)
+{
+}
+
+ConstructorImp::ConstructorImp(const KJSO &p, int len)
+{
+ setPrototype(p);
+ // TODO ??? put("constructor", *this);
+ setLength(len);
+}
+
+ConstructorImp::ConstructorImp(const UString &n, const KJSO &p, int len)
+ : InternalFunctionImp(n)
+{
+ setPrototype(p);
+ // TODO ??? put("constructor", *this);
+ setLength(len);
+}
+
+ConstructorImp::~ConstructorImp() { }
+
+Completion ConstructorImp::execute(const List &)
+{
+ /* TODO */
+ return Completion(ReturnValue, Null());
+}
+
+Function::Function(Imp *d)
+ : KJSO(d)
+{
+ if (d) {
+ static_cast<FunctionImp*>(rep)->attr = ImplicitNone;
+ assert(Global::current().hasProperty("[[Function.prototype]]"));
+ setPrototype(Global::current().functionPrototype());
+ }
+}
+
+Completion Function::execute(const List &args)
+{
+ assert(rep);
+ return static_cast<FunctionImp*>(rep)->execute(args);
+}
+
+bool Function::hasAttribute(FunctionAttribute a) const
+{
+ assert(rep);
+ return static_cast<FunctionImp*>(rep)->hasAttribute(a);
+}
+
+#if 0
+InternalFunction::InternalFunction(Imp *d)
+ : Function(d)
+{
+ param = 0L;
+}
+
+InternalFunction::~InternalFunction()
+{
+}
+#endif
+
+Constructor::Constructor(Imp *d)
+ : Function(d)
+{
+ if (d) {
+ assert(Global::current().hasProperty("[[Function.prototype]]"));
+ setPrototype(Global::current().get("[[Function.prototype]]"));
+ put("constructor", *this);
+ KJSO tmp(d); // protect from GC
+ ((FunctionImp*)d)->setLength(1);
+ }
+}
+
+#if 0
+Constructor::Constructor(const Object& proto, int len)
+{
+ setPrototype(proto);
+ put("constructor", *this);
+ put("length", len, DontEnum);
+}
+#endif
+
+Constructor::~Constructor()
+{
+}
+
+Completion Constructor::execute(const List &)
+{
+ /* TODO: call construct instead ? */
+ return Completion(ReturnValue, Undefined());
+}
+
+Object Constructor::construct(const List &args)
+{
+ assert(rep && rep->type() == ConstructorType);
+ return ((ConstructorImp*)rep)->construct(args);
+}
+
+Constructor Constructor::dynamicCast(const KJSO &obj)
+{
+ // return null object on type mismatch
+ if (!obj.isA(ConstructorType))
+ return Constructor(0L);
+
+ return Constructor(obj.imp());
+}
+
+KJSO Function::thisValue() const
+{
+ return KJSO(Context::current()->thisValue());
+}
diff --git a/JavaScriptCore/kjs/function.h b/JavaScriptCore/kjs/function.h
new file mode 100644
index 0000000..70c1f3a
--- /dev/null
+++ b/JavaScriptCore/kjs/function.h
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_FUNCTION_H_
+#define _KJS_FUNCTION_H_
+
+#include <assert.h>
+
+#include "object.h"
+#include "types.h"
+
+namespace KJS {
+
+ enum CodeType { GlobalCode,
+ EvalCode,
+ FunctionCode,
+ AnonymousCode,
+ HostCode };
+
+ enum FunctionAttribute { ImplicitNone, ImplicitThis, ImplicitParents };
+
+ class Function;
+ class Parameter;
+
+ /**
+ * @short Implementation class for Functions.
+ */
+ class FunctionImp : public ObjectImp {
+ friend class Function;
+ public:
+ FunctionImp();
+ FunctionImp(const UString &n);
+ virtual ~FunctionImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &) = 0;
+ bool hasAttribute(FunctionAttribute a) const { return (attr & a) != 0; }
+ virtual CodeType codeType() const = 0;
+ KJSO thisValue() const;
+ void addParameter(const UString &n);
+ void setLength(int l);
+ KJSO executeCall(Imp *thisV, const List *args);
+ KJSO executeCall(Imp *thisV, const List *args, const List *extraScope);
+ UString name() const;
+ protected:
+ UString ident;
+ FunctionAttribute attr;
+ Parameter *param;
+ private:
+ void processParameters(const List *);
+ };
+
+ /**
+ * @short Abstract base class for internal functions.
+ */
+ class InternalFunctionImp : public FunctionImp {
+ public:
+ InternalFunctionImp();
+ InternalFunctionImp(int l);
+ InternalFunctionImp(const UString &n);
+ virtual ~InternalFunctionImp() { }
+ virtual String toString() const;
+ virtual KJSO toPrimitive(Type) const { return toString(); }
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &);
+ virtual CodeType codeType() const { return HostCode; }
+ };
+
+ /**
+ * @short Base class for Function objects.
+ */
+ class Function : public KJSO {
+ public:
+ Function(Imp *);
+ virtual ~Function() { }
+ Completion execute(const List &);
+ bool hasAttribute(FunctionAttribute a) const;
+ CodeType codeType() const { return HostCode; }
+ KJSO thisValue() const;
+ };
+
+ /**
+ * @short Implementation class for Constructors.
+ */
+ class ConstructorImp : public InternalFunctionImp {
+ public:
+ ConstructorImp();
+ ConstructorImp(const UString &n); /* TODO: add length */
+ ConstructorImp(const KJSO &, int);
+ ConstructorImp(const UString &n, const KJSO &p, int len);
+ virtual ~ConstructorImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &);
+ virtual Object construct(const List &) = 0;
+ };
+
+ /**
+ * @short Constructor object for use with the 'new' operator
+ */
+ class Constructor : public Function {
+ public:
+ Constructor(Imp *);
+ virtual ~Constructor();
+ // Constructor(const Object& proto, int len);
+ /**
+ * @return @ref ConstructorType
+ */
+ Completion execute(const List &);
+ Object construct(const List &args);
+ static Constructor dynamicCast(const KJSO &obj);
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/function_object.cpp b/JavaScriptCore/kjs/function_object.cpp
new file mode 100644
index 0000000..63b8b63
--- /dev/null
+++ b/JavaScriptCore/kjs/function_object.cpp
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "function_object.h"
+
+#include "lexer.h"
+#include "nodes.h"
+#include "error_object.h"
+
+extern int kjsyyparse();
+
+using namespace KJS;
+
+FunctionObject::FunctionObject(const Object& funcProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.3.3.1 Function.prototype
+ setPrototypeProperty(funcProto);
+}
+
+// ECMA 15.3.1 The Function Constructor Called as a Function
+Completion FunctionObject::execute(const List &args)
+{
+ return Completion(ReturnValue, construct(args));
+}
+
+// ECMA 15.3.2 The Function Constructor
+Object FunctionObject::construct(const List &args)
+{
+ UString p("");
+ UString body;
+ int argsSize = args.size();
+ if (argsSize == 0) {
+ body = "";
+ } else if (argsSize == 1) {
+ body = args[0].toString().value();
+ } else {
+ p = args[0].toString().value();
+ for (int k = 1; k < argsSize - 1; k++)
+ p += "," + args[k].toString().value();
+ body = args[argsSize-1].toString().value();
+ }
+
+ Lexer::curr()->setCode(body.data(), body.size());
+
+ KJScriptImp::current()->pushStack();
+ int yp = kjsyyparse();
+ ProgramNode *progNode = KJScriptImp::current()->progNode();
+ KJScriptImp::current()->popStack();
+ if (yp) {
+ /* TODO: free nodes */
+ return ErrorObject::create(SyntaxError,
+ I18N_NOOP("Syntax error in function body"), -1);
+ }
+
+ List scopeChain;
+ scopeChain.append(Global::current());
+ FunctionBodyNode *bodyNode = progNode;
+ FunctionImp *fimp = new DeclaredFunctionImp(UString::null, bodyNode,
+ &scopeChain);
+ Object ret(fimp); // protect from GC
+
+ // parse parameter list. throw syntax error on illegal identifiers
+ int len = p.size();
+ const UChar *c = p.data();
+ int i = 0, params = 0;
+ UString param;
+ while (i < len) {
+ while (*c == ' ' && i < len)
+ c++, i++;
+ if (Lexer::isIdentLetter(c->unicode())) { // else error
+ param = UString(c, 1);
+ c++, i++;
+ while (i < len && (Lexer::isIdentLetter(c->unicode()) ||
+ Lexer::isDecimalDigit(c->unicode()))) {
+ param += UString(c, 1);
+ c++, i++;
+ }
+ while (i < len && *c == ' ')
+ c++, i++;
+ if (i == len) {
+ fimp->addParameter(param);
+ params++;
+ break;
+ } else if (*c == ',') {
+ fimp->addParameter(param);
+ params++;
+ c++, i++;
+ continue;
+ } // else error
+ }
+ return ErrorObject::create(SyntaxError,
+ I18N_NOOP("Syntax error in parameter list"),
+ -1);
+ }
+
+ fimp->setLength(params);
+ fimp->setPrototypeProperty(Global::current().functionPrototype());
+ return ret;
+}
+
+FunctionPrototype::FunctionPrototype(const Object &p)
+ : ObjectImp(FunctionClass, Null(), p)
+{
+}
diff --git a/JavaScriptCore/kjs/function_object.h b/JavaScriptCore/kjs/function_object.h
new file mode 100644
index 0000000..9617ac0
--- /dev/null
+++ b/JavaScriptCore/kjs/function_object.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _FUNCTION_OBJECT_H_
+#define _FUNCTION_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class FunctionPrototype : public ObjectImp {
+ public:
+ FunctionPrototype(const Object &p);
+ };
+
+ class FunctionObject : public ConstructorImp {
+ public:
+ FunctionObject(const Object &funcProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/global_object.cpp b/JavaScriptCore/kjs/global_object.cpp
new file mode 100644
index 0000000..c5bb3ed9
--- /dev/null
+++ b/JavaScriptCore/kjs/global_object.cpp
@@ -0,0 +1,373 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "operations.h"
+#include "internal.h"
+#include "types.h"
+#include "lexer.h"
+#include "nodes.h"
+#include "lexer.h"
+
+#include "object_object.h"
+#include "function_object.h"
+#include "array_object.h"
+#include "bool_object.h"
+#include "string_object.h"
+#include "number_object.h"
+#include "math_object.h"
+#include "date_object.h"
+#include "regexp_object.h"
+#include "error_object.h"
+
+extern int kjsyyparse();
+
+namespace KJS {
+
+ class GlobalImp : public ObjectImp {
+ public:
+ GlobalImp();
+ virtual ~GlobalImp();
+ virtual void mark(Imp*);
+ void init();
+ virtual KJSO get(const UString &p) const;
+ virtual void put(const UString &p, const KJSO& v);
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ Imp *filter;
+ void *extraData;
+ private:
+ class GlobalInternal;
+ GlobalInternal *internal;
+ };
+
+};
+
+using namespace KJS;
+
+class GlobalFunc : public InternalFunctionImp {
+public:
+ GlobalFunc(int i) : id(i) { }
+ Completion execute(const List &c);
+ virtual CodeType codeType() const;
+ enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape };
+private:
+ int id;
+};
+
+Global::Global()
+ : Object(0L)
+{
+ rep = 0;
+ init();
+}
+
+Global::Global(void *)
+ : Object(0L)
+{
+}
+
+Global::~Global()
+{
+}
+
+void Global::init()
+{
+ if (rep)
+ rep->deref();
+ GlobalImp *g = new GlobalImp();
+ rep = g;
+ rep->ref();
+ g->init();
+}
+
+void Global::clear()
+{
+// if (rep && rep->deref())
+// delete rep;
+// rep = 0L;
+}
+
+Global Global::current()
+{
+ assert(KJScriptImp::current());
+ return KJScriptImp::current()->glob;
+}
+
+KJSO Global::objectPrototype() const
+{
+ return get("[[Object.prototype]]");
+}
+
+KJSO Global::functionPrototype() const
+{
+ return get("[[Function.prototype]]");
+}
+
+void Global::setFilter(const KJSO &f)
+{
+ static_cast<GlobalImp*>(rep)->filter = f.imp();
+}
+
+KJSO Global::filter() const
+{
+ Imp *f = static_cast<GlobalImp*>(rep)->filter;
+ return f ? KJSO(f) : KJSO(Null());
+}
+
+void *Global::extra() const
+{
+ return static_cast<GlobalImp*>(rep)->extraData;
+}
+
+void Global::setExtra(void *e)
+{
+ static_cast<GlobalImp*>(rep)->extraData = e;
+}
+
+GlobalImp::GlobalImp()
+ : ObjectImp(ObjectClass),
+ filter(0L),
+ extraData(0L)
+{
+ // constructor properties. prototypes as Global's member variables first.
+ Object objProto(new ObjectPrototype());
+ Object funcProto(new FunctionPrototype(objProto));
+ Object arrayProto(new ArrayPrototype(objProto));
+ Object stringProto(new StringPrototype(objProto));
+ Object booleanProto(new BooleanPrototype(objProto));
+ Object numberProto(new NumberPrototype(objProto));
+ Object dateProto(new DatePrototype(objProto));
+ Object regexpProto(new RegExpPrototype(objProto));
+ Object errorProto(new ErrorPrototype(objProto));
+
+ put("[[Object.prototype]]", objProto);
+ put("[[Function.prototype]]", funcProto);
+ put("[[Array.prototype]]", arrayProto);
+ put("[[String.prototype]]", stringProto);
+ put("[[Boolean.prototype]]", booleanProto);
+ put("[[Number.prototype]]", numberProto);
+ put("[[Date.prototype]]", dateProto);
+ put("[[RegExp.prototype]]", regexpProto);
+ put("[[Error.prototype]]", errorProto);
+
+ Object objectObj(new ObjectObject(funcProto, objProto));
+ Object funcObj(new FunctionObject(funcProto));
+ Object arrayObj(new ArrayObject(funcProto, arrayProto));
+ Object stringObj(new StringObject(funcProto, stringProto));
+ Object boolObj(new BooleanObject(funcProto, booleanProto));
+ Object numObj(new NumberObject(funcProto, numberProto));
+ Object dateObj(new DateObject(funcProto, dateProto));
+ Object regObj(new RegExpObject(funcProto, regexpProto));
+ Object errObj(new ErrorObject(funcProto, errorProto));
+
+ Imp::put("Object", objectObj, DontEnum);
+ Imp::put("Function", funcObj, DontEnum);
+ Imp::put("Array", arrayObj, DontEnum);
+ Imp::put("Boolean", boolObj, DontEnum);
+ Imp::put("String", stringObj, DontEnum);
+ Imp::put("Number", numObj, DontEnum);
+ Imp::put("Date", dateObj, DontEnum);
+ Imp::put("RegExp", regObj, DontEnum);
+ Imp::put("Error", errObj, DontEnum);
+
+ objProto.setConstructor(objectObj);
+ funcProto.setConstructor(funcObj);
+ arrayProto.setConstructor(arrayObj);
+ booleanProto.setConstructor(boolObj);
+ stringProto.setConstructor(stringObj);
+ numberProto.setConstructor(numObj);
+ dateProto.setConstructor(dateObj);
+ regexpProto.setConstructor(regObj);
+ errorProto.setConstructor(errObj);
+};
+
+void GlobalImp::init()
+{
+ Imp::put("eval", Function(new GlobalFunc(GlobalFunc::Eval)));
+ Imp::put("parseInt", Function(new GlobalFunc(GlobalFunc::ParseInt)));
+ Imp::put("parseFloat", Function(new GlobalFunc(GlobalFunc::ParseFloat)));
+ Imp::put("isNaN", Function(new GlobalFunc(GlobalFunc::IsNaN)));
+ Imp::put("isFinite", Function(new GlobalFunc(GlobalFunc::IsFinite)));
+ Imp::put("escape", Function(new GlobalFunc(GlobalFunc::Escape)));
+ Imp::put("unescape", Function(new GlobalFunc(GlobalFunc::UnEscape)));
+
+ // other properties
+ Imp::put("Math", Object(new Math()), DontEnum);
+}
+
+GlobalImp::~GlobalImp() { }
+
+void GlobalImp::mark(Imp*)
+{
+ ObjectImp::mark();
+ /* TODO: remove in next version */
+ if (filter && !filter->marked())
+ filter->mark();
+}
+
+KJSO GlobalImp::get(const UString &p) const
+{
+ if (p == "NaN")
+ return Number(NaN);
+ else if (p == "Infinity")
+ return Number(Inf);
+ else if (p == "undefined")
+ return Undefined();
+
+ return Imp::get(p);
+}
+
+void GlobalImp::put(const UString &p, const KJSO& v)
+{
+ // if we already have this property (added by init() or a variable
+ // declaration) overwrite it. Otherwise pass it to the prototype.
+ // Needed to get something like a browser's window object working.
+ if (!prototype() || hasProperty(p, false) || Imp::hasProperty(p, false))
+ Imp::put(p, v);
+ else
+ prototype()->put(p, v);
+#if 0
+ if (filter)
+ filter->put(p, v); /* TODO: remove in next version */
+ else
+ Imp::put(p, v);
+#endif
+}
+
+bool GlobalImp::hasProperty(const UString &p, bool recursive) const
+{
+ if (p == "NaN" || p == "Infinity" || p == "undefined")
+ return true;
+ return (recursive && Imp::hasProperty(p, recursive));
+}
+
+CodeType GlobalFunc::codeType() const
+{
+ return id == Eval ? EvalCode : InternalFunctionImp::codeType();
+}
+
+Completion GlobalFunc::execute(const List &args)
+{
+ KJSO res;
+
+ static const char non_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789@*_+-./";
+
+ if (id == Eval) { // eval()
+ KJSO x = args[0];
+ if (x.type() != StringType)
+ return Completion(ReturnValue, x);
+ else {
+ UString s = x.toString().value();
+ Lexer::curr()->setCode(s.data(), s.size());
+ Node::setFirstNode(KJScriptImp::current()->firstNode());
+ int yp = kjsyyparse();
+ KJScriptImp::current()->setFirstNode(Node::firstNode());
+ if (yp) {
+ // TODO: stop this from growing (will be deleted at end of global eval)
+ // KJS::Node::deleteAllNodes();
+ return Completion(ReturnValue, Error::create(SyntaxError));
+ }
+
+ Completion c = KJScriptImp::current()->progNode()->execute();
+ if (c.complType() == ReturnValue)
+ return c;
+ else if (c.complType() == Normal) {
+ if (c.isValueCompletion())
+ return Completion(ReturnValue, c.value());
+ else
+ return Completion(ReturnValue, Undefined());
+ } else
+ return c;
+
+ // if (KJS::Node::progNode())
+ // KJS::Node::progNode()->deleteStatements();
+ }
+ } else if (id == ParseInt) {
+ String str = args[0].toString();
+ int radix = args[1].toInt32();
+ if (radix == 0)
+ radix = 10;
+ else if (radix < 2 || radix > 36) {
+ res = Number(NaN);
+ return Completion(ReturnValue, res);
+ }
+ /* TODO: use radix */
+ int i = 0;
+ sscanf(str.value().ascii(), "%d", &i);
+ res = Number(i);
+ } else if (id == ParseFloat) {
+ String str = args[0].toString();
+ double d = 0.0;
+ sscanf(str.value().ascii(), "%lf", &d);
+ res = Number(d);
+ } else if (id == IsNaN) {
+ res = Boolean(args[0].toNumber().isNaN());
+ } else if (id == IsFinite) {
+ Number n = args[0].toNumber();
+ res = Boolean(!n.isNaN() && !n.isInf());
+ } else if (id == Escape) {
+ UString r = "", s, str = args[0].toString().value();
+ const UChar *c = str.data();
+ for (int k = 0; k < str.size(); k++, c++) {
+ int u = c->unicode();
+ if (u > 255) {
+ char tmp[7];
+ sprintf(tmp, "%%u%04x", u);
+ s = UString(tmp);
+ } else if (strchr(non_escape, (char)u)) {
+ s = UString(c, 1);
+ } else {
+ char tmp[4];
+ sprintf(tmp, "%%%02x", u);
+ s = UString(tmp);
+ }
+ r += s;
+ }
+ res = String(r);
+ } else if (id == UnEscape) {
+ UString s, str = args[0].toString().value();
+ int k = 0, len = str.size();
+ while (k < len) {
+ const UChar *c = str.data() + k;
+ UChar u;
+ if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
+ u = Lexer::convertUnicode((c+2)->unicode(), (c+3)->unicode(),
+ (c+4)->unicode(), (c+5)->unicode());
+ c = &u;
+ k += 5;
+ } else if (*c == UChar('%') && k <= len - 3) {
+ u = UChar(Lexer::convertHex((c+1)->unicode(), (c+2)->unicode()));
+ c = &u;
+ k += 2;
+ }
+ k++;
+ s += UString(c, 1);
+ }
+ res = String(s);
+ }
+
+ return Completion(ReturnValue, res);
+}
diff --git a/JavaScriptCore/kjs/grammar.cpp b/JavaScriptCore/kjs/grammar.cpp
new file mode 100644
index 0000000..9639e01
--- /dev/null
+++ b/JavaScriptCore/kjs/grammar.cpp
@@ -0,0 +1,2220 @@
+
+/* A Bison parser, made from grammar.y
+ by GNU Bison version 1.28 */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define yyparse kjsyyparse
+#define yylex kjsyylex
+#define yyerror kjsyyerror
+#define yylval kjsyylval
+#define yychar kjsyychar
+#define yydebug kjsyydebug
+#define yynerrs kjsyynerrs
+#define YYLSP_NEEDED
+
+#define NULLTOKEN 257
+#define TRUETOKEN 258
+#define FALSETOKEN 259
+#define STRING 260
+#define NUMBER 261
+#define BREAK 262
+#define CASE 263
+#define DEFAULT 264
+#define FOR 265
+#define NEW 266
+#define VAR 267
+#define CONTINUE 268
+#define FUNCTION 269
+#define RETURN 270
+#define VOID 271
+#define DELETE 272
+#define IF 273
+#define THIS 274
+#define DO 275
+#define WHILE 276
+#define ELSE 277
+#define IN 278
+#define INSTANCEOF 279
+#define TYPEOF 280
+#define SWITCH 281
+#define WITH 282
+#define RESERVED 283
+#define THROW 284
+#define TRY 285
+#define CATCH 286
+#define FINALLY 287
+#define EQEQ 288
+#define NE 289
+#define STREQ 290
+#define STRNEQ 291
+#define LE 292
+#define GE 293
+#define OR 294
+#define AND 295
+#define PLUSPLUS 296
+#define MINUSMINUS 297
+#define LSHIFT 298
+#define RSHIFT 299
+#define URSHIFT 300
+#define PLUSEQUAL 301
+#define MINUSEQUAL 302
+#define MULTEQUAL 303
+#define DIVEQUAL 304
+#define LSHIFTEQUAL 305
+#define RSHIFTEQUAL 306
+#define URSHIFTEQUAL 307
+#define ANDEQUAL 308
+#define MODEQUAL 309
+#define XOREQUAL 310
+#define OREQUAL 311
+#define IDENT 312
+#define AUTO 313
+
+#line 1 "grammar.y"
+
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+
+/* default values for bison */
+#define YYDEBUG 0
+#define YYMAXDEPTH 0
+#ifdef KJS_DEBUGGER
+#define YYERROR_VERBOSE
+#define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line); } // location
+#else
+#undef YYLSP_NEEDED
+#define DBG(l, s, e)
+#endif
+
+extern int yylex();
+int yyerror (const char *);
+bool automatic();
+
+using namespace KJS;
+
+
+#line 49 "grammar.y"
+typedef union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+} YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 358
+#define YYFLAG -32768
+#define YYNTBASE 84
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 313 ? yytranslate[x] : 148)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 73, 2, 2, 2, 75, 78, 2, 61,
+ 62, 74, 70, 67, 71, 69, 60, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 68, 83, 76,
+ 82, 77, 81, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 65, 2, 66, 79, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 63, 80, 64, 72, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 24, 27, 31, 35, 39, 45, 48, 53, 54,
+ 56, 58, 61, 65, 71, 73, 75, 77, 79, 81,
+ 86, 90, 94, 96, 99, 102, 105, 110, 114, 117,
+ 121, 123, 127, 129, 131, 133, 136, 139, 141, 144,
+ 147, 150, 153, 157, 160, 164, 167, 170, 173, 176,
+ 178, 182, 186, 190, 192, 196, 200, 202, 206, 210,
+ 214, 216, 220, 224, 228, 232, 236, 240, 242, 246,
+ 250, 254, 258, 260, 264, 266, 270, 272, 276, 278,
+ 282, 284, 288, 290, 296, 298, 302, 304, 306, 308,
+ 310, 312, 314, 316, 318, 320, 322, 324, 326, 328,
+ 332, 334, 336, 338, 340, 342, 344, 346, 348, 350,
+ 352, 354, 356, 358, 360, 363, 367, 369, 372, 376,
+ 380, 382, 386, 388, 391, 394, 396, 399, 402, 408,
+ 416, 423, 429, 439, 450, 458, 467, 477, 478, 480,
+ 483, 486, 490, 494, 497, 500, 504, 508, 511, 514,
+ 518, 522, 528, 534, 538, 544, 545, 547, 549, 552,
+ 556, 561, 564, 568, 572, 576, 580, 584, 589, 595,
+ 598, 604, 611, 616, 622, 624, 628, 631, 635, 637,
+ 639, 642, 644
+};
+
+static const short yyrhs[] = { 3,
+ 0, 4, 0, 5, 0, 7, 0, 6, 0, 60,
+ 0, 20, 0, 58, 0, 84, 0, 86, 0, 61,
+ 113, 62, 0, 63, 64, 0, 63, 90, 64, 0,
+ 65, 88, 66, 0, 65, 87, 66, 0, 65, 87,
+ 67, 88, 66, 0, 88, 111, 0, 87, 67, 88,
+ 111, 0, 0, 89, 0, 67, 0, 89, 67, 0,
+ 91, 68, 111, 0, 90, 67, 91, 68, 111, 0,
+ 58, 0, 6, 0, 7, 0, 85, 0, 142, 0,
+ 92, 65, 113, 66, 0, 92, 69, 58, 0, 12,
+ 92, 95, 0, 92, 0, 12, 93, 0, 92, 95,
+ 0, 94, 95, 0, 94, 65, 113, 66, 0, 94,
+ 69, 58, 0, 61, 62, 0, 61, 96, 62, 0,
+ 111, 0, 96, 67, 111, 0, 93, 0, 94, 0,
+ 97, 0, 97, 42, 0, 97, 43, 0, 98, 0,
+ 18, 99, 0, 17, 99, 0, 26, 99, 0, 42,
+ 99, 0, 59, 42, 99, 0, 43, 99, 0, 59,
+ 43, 99, 0, 70, 99, 0, 71, 99, 0, 72,
+ 99, 0, 73, 99, 0, 99, 0, 100, 74, 99,
+ 0, 100, 60, 99, 0, 100, 75, 99, 0, 100,
+ 0, 101, 70, 100, 0, 101, 71, 100, 0, 101,
+ 0, 102, 44, 101, 0, 102, 45, 101, 0, 102,
+ 46, 101, 0, 102, 0, 103, 76, 102, 0, 103,
+ 77, 102, 0, 103, 38, 102, 0, 103, 39, 102,
+ 0, 103, 25, 102, 0, 103, 24, 102, 0, 103,
+ 0, 104, 34, 103, 0, 104, 35, 103, 0, 104,
+ 36, 103, 0, 104, 37, 103, 0, 104, 0, 105,
+ 78, 104, 0, 105, 0, 106, 79, 104, 0, 106,
+ 0, 107, 80, 104, 0, 107, 0, 108, 41, 107,
+ 0, 108, 0, 109, 40, 108, 0, 109, 0, 109,
+ 81, 111, 68, 111, 0, 110, 0, 97, 112, 111,
+ 0, 82, 0, 47, 0, 48, 0, 49, 0, 50,
+ 0, 51, 0, 52, 0, 53, 0, 54, 0, 56,
+ 0, 57, 0, 55, 0, 111, 0, 113, 67, 111,
+ 0, 115, 0, 117, 0, 121, 0, 122, 0, 123,
+ 0, 124, 0, 126, 0, 127, 0, 128, 0, 129,
+ 0, 130, 0, 136, 0, 137, 0, 138, 0, 63,
+ 64, 0, 63, 116, 64, 0, 114, 0, 116, 114,
+ 0, 13, 118, 83, 0, 13, 118, 1, 0, 119,
+ 0, 118, 67, 119, 0, 58, 0, 58, 120, 0,
+ 82, 111, 0, 83, 0, 113, 83, 0, 113, 1,
+ 0, 19, 61, 113, 62, 114, 0, 19, 61, 113,
+ 62, 114, 23, 114, 0, 21, 114, 22, 61, 113,
+ 62, 0, 22, 61, 113, 62, 114, 0, 11, 61,
+ 125, 83, 125, 83, 125, 62, 114, 0, 11, 61,
+ 13, 118, 83, 125, 83, 125, 62, 114, 0, 11,
+ 61, 97, 24, 113, 62, 114, 0, 11, 61, 13,
+ 58, 24, 113, 62, 114, 0, 11, 61, 13, 58,
+ 120, 24, 113, 62, 114, 0, 0, 113, 0, 14,
+ 83, 0, 14, 1, 0, 14, 58, 83, 0, 14,
+ 58, 1, 0, 8, 83, 0, 8, 1, 0, 8,
+ 58, 83, 0, 8, 58, 1, 0, 16, 83, 0,
+ 16, 1, 0, 16, 113, 83, 0, 16, 113, 1,
+ 0, 28, 61, 113, 62, 114, 0, 27, 61, 113,
+ 62, 131, 0, 63, 132, 64, 0, 63, 132, 135,
+ 132, 64, 0, 0, 133, 0, 134, 0, 133, 134,
+ 0, 9, 113, 68, 0, 9, 113, 68, 116, 0,
+ 10, 68, 0, 10, 68, 116, 0, 58, 68, 114,
+ 0, 30, 113, 83, 0, 31, 115, 139, 0, 31,
+ 115, 140, 0, 31, 115, 139, 140, 0, 32, 61,
+ 58, 62, 115, 0, 33, 115, 0, 15, 58, 61,
+ 62, 144, 0, 15, 58, 61, 143, 62, 144, 0,
+ 15, 61, 62, 144, 0, 15, 61, 143, 62, 144,
+ 0, 58, 0, 143, 67, 58, 0, 63, 64, 0,
+ 63, 146, 64, 0, 146, 0, 147, 0, 146, 147,
+ 0, 114, 0, 141, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 156, 158, 159, 160, 161, 162, 167, 169, 171, 172,
+ 173, 174, 175, 178, 180, 181, 184, 186, 190, 192,
+ 195, 197, 200, 202, 206, 209, 210, 213, 215, 216,
+ 217, 219, 222, 224, 227, 229, 230, 231, 234, 236,
+ 239, 241, 244, 246, 249, 251, 252, 255, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 270,
+ 272, 273, 274, 277, 279, 280, 283, 285, 286, 287,
+ 290, 292, 294, 296, 298, 300, 302, 306, 308, 309,
+ 310, 311, 314, 316, 319, 321, 324, 326, 329, 331,
+ 335, 337, 341, 343, 347, 349, 353, 355, 356, 357,
+ 358, 359, 360, 361, 362, 363, 364, 365, 368, 370,
+ 373, 375, 376, 377, 378, 379, 380, 381, 382, 383,
+ 384, 385, 386, 387, 390, 392, 395, 397, 400, 403,
+ 412, 414, 418, 420, 423, 427, 431, 434, 441, 443,
+ 447, 449, 450, 453, 456, 459, 463, 469, 471, 474,
+ 476, 480, 482, 489, 491, 495, 497, 505, 507, 511,
+ 512, 518, 523, 528, 530, 534, 536, 539, 541, 544,
+ 546, 549, 551, 554, 560, 564, 566, 567, 570, 574,
+ 578, 581, 585, 587, 592, 594, 598, 600, 603, 608,
+ 610, 613, 615
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = { "$","error","$undefined.","NULLTOKEN",
+"TRUETOKEN","FALSETOKEN","STRING","NUMBER","BREAK","CASE","DEFAULT","FOR","NEW",
+"VAR","CONTINUE","FUNCTION","RETURN","VOID","DELETE","IF","THIS","DO","WHILE",
+"ELSE","IN","INSTANCEOF","TYPEOF","SWITCH","WITH","RESERVED","THROW","TRY","CATCH",
+"FINALLY","EQEQ","NE","STREQ","STRNEQ","LE","GE","OR","AND","PLUSPLUS","MINUSMINUS",
+"LSHIFT","RSHIFT","URSHIFT","PLUSEQUAL","MINUSEQUAL","MULTEQUAL","DIVEQUAL",
+"LSHIFTEQUAL","RSHIFTEQUAL","URSHIFTEQUAL","ANDEQUAL","MODEQUAL","XOREQUAL",
+"OREQUAL","IDENT","AUTO","'/'","'('","')'","'{'","'}'","'['","']'","','","':'",
+"'.'","'+'","'-'","'~'","'!'","'*'","'%'","'<'","'>'","'&'","'^'","'|'","'?'",
+"'='","';'","Literal","PrimaryExpr","ArrayLiteral","ElementList","ElisionOpt",
+"Elision","PropertyNameAndValueList","PropertyName","MemberExpr","NewExpr","CallExpr",
+"Arguments","ArgumentList","LeftHandSideExpr","PostfixExpr","UnaryExpr","MultiplicativeExpr",
+"AdditiveExpr","ShiftExpr","RelationalExpr","EqualityExpr","BitwiseANDExpr",
+"BitwiseXORExpr","BitwiseORExpr","LogicalANDExpr","LogicalORExpr","ConditionalExpr",
+"AssignmentExpr","AssignmentOperator","Expr","Statement","Block","StatementList",
+"VariableStatement","VariableDeclarationList","VariableDeclaration","Initializer",
+"EmptyStatement","ExprStatement","IfStatement","IterationStatement","ExprOpt",
+"ContinueStatement","BreakStatement","ReturnStatement","WithStatement","SwitchStatement",
+"CaseBlock","CaseClausesOpt","CaseClauses","CaseClause","DefaultClause","LabelledStatement",
+"ThrowStatement","TryStatement","Catch","Finally","FunctionDeclaration","FunctionExpr",
+"FormalParameterList","FunctionBody","Program","SourceElements","SourceElement", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 84, 84, 84, 84, 84, 84, 85, 85, 85, 85,
+ 85, 85, 85, 86, 86, 86, 87, 87, 88, 88,
+ 89, 89, 90, 90, 91, 91, 91, 92, 92, 92,
+ 92, 92, 93, 93, 94, 94, 94, 94, 95, 95,
+ 96, 96, 97, 97, 98, 98, 98, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 100,
+ 100, 100, 100, 101, 101, 101, 102, 102, 102, 102,
+ 103, 103, 103, 103, 103, 103, 103, 104, 104, 104,
+ 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
+ 109, 109, 110, 110, 111, 111, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112, 112, 113, 113,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 115, 115, 116, 116, 117, 117,
+ 118, 118, 119, 119, 120, 121, 122, 122, 123, 123,
+ 124, 124, 124, 124, 124, 124, 124, 125, 125, 126,
+ 126, 126, 126, 127, 127, 127, 127, 128, 128, 128,
+ 128, 129, 130, 131, 131, 132, 132, 133, 133, 134,
+ 134, 135, 135, 136, 137, 138, 138, 138, 139, 140,
+ 141, 141, 142, 142, 143, 143, 144, 144, 145, 146,
+ 146, 147, 147
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 2, 3, 3, 3, 5, 2, 4, 0, 1,
+ 1, 2, 3, 5, 1, 1, 1, 1, 1, 4,
+ 3, 3, 1, 2, 2, 2, 4, 3, 2, 3,
+ 1, 3, 1, 1, 1, 2, 2, 1, 2, 2,
+ 2, 2, 3, 2, 3, 2, 2, 2, 2, 1,
+ 3, 3, 3, 1, 3, 3, 1, 3, 3, 3,
+ 1, 3, 3, 3, 3, 3, 3, 1, 3, 3,
+ 3, 3, 1, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 5, 1, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 3, 1, 2, 3, 3,
+ 1, 3, 1, 2, 2, 1, 2, 2, 5, 7,
+ 6, 5, 9, 10, 7, 8, 9, 0, 1, 2,
+ 2, 3, 3, 2, 2, 3, 3, 2, 2, 3,
+ 3, 5, 5, 3, 5, 0, 1, 1, 2, 3,
+ 4, 2, 3, 3, 3, 3, 3, 4, 5, 2,
+ 5, 6, 4, 5, 1, 3, 2, 3, 1, 1,
+ 2, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 1, 2, 3, 5, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 6, 0, 0,
+ 19, 0, 0, 0, 0, 136, 9, 28, 10, 33,
+ 43, 44, 45, 48, 60, 64, 67, 71, 78, 83,
+ 85, 87, 89, 91, 93, 95, 109, 0, 192, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 193, 29, 189, 190, 155, 0, 154,
+ 148, 0, 8, 0, 33, 34, 133, 0, 131, 151,
+ 0, 150, 0, 0, 159, 158, 0, 45, 50, 49,
+ 0, 0, 0, 51, 0, 0, 0, 0, 0, 52,
+ 54, 0, 0, 0, 0, 5, 4, 8, 12, 0,
+ 0, 127, 0, 21, 0, 0, 20, 56, 57, 58,
+ 59, 0, 0, 0, 35, 0, 0, 36, 46, 47,
+ 98, 99, 100, 101, 102, 103, 104, 105, 108, 106,
+ 107, 97, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 138, 0, 137,
+ 191, 157, 156, 0, 45, 149, 0, 26, 27, 25,
+ 12, 32, 0, 134, 130, 0, 129, 153, 152, 0,
+ 185, 0, 0, 161, 160, 0, 0, 0, 0, 0,
+ 175, 125, 0, 0, 176, 177, 174, 53, 55, 11,
+ 13, 0, 0, 126, 128, 15, 19, 14, 17, 22,
+ 39, 0, 41, 0, 31, 0, 38, 96, 62, 61,
+ 63, 65, 66, 68, 69, 70, 77, 76, 74, 75,
+ 72, 73, 79, 80, 81, 82, 84, 86, 88, 90,
+ 92, 0, 110, 133, 0, 0, 148, 135, 132, 0,
+ 0, 0, 183, 0, 0, 0, 0, 0, 0, 0,
+ 0, 180, 178, 0, 23, 0, 40, 0, 30, 37,
+ 0, 0, 134, 148, 0, 0, 181, 0, 187, 0,
+ 184, 186, 139, 0, 142, 166, 163, 162, 0, 0,
+ 16, 18, 42, 94, 0, 0, 0, 0, 148, 182,
+ 188, 0, 141, 0, 0, 167, 168, 0, 24, 0,
+ 0, 148, 145, 0, 140, 0, 0, 164, 166, 169,
+ 179, 146, 0, 0, 0, 170, 172, 0, 147, 0,
+ 143, 171, 173, 165, 144, 0, 0, 0
+};
+
+static const short yydefgoto[] = { 37,
+ 38, 39, 125, 126, 127, 120, 121, 40, 41, 42,
+ 135, 232, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 153, 58, 59,
+ 60, 123, 61, 88, 89, 194, 62, 63, 64, 65,
+ 187, 66, 67, 68, 69, 70, 307, 325, 326, 327,
+ 339, 71, 72, 73, 215, 216, 74, 75, 203, 273,
+ 356, 76, 77
+};
+
+static const short yypact[] = { 699,
+-32768,-32768,-32768,-32768,-32768, 2, -29, 121, 34, 4,
+ 129, 227, 1171, 1171, 42,-32768, 772, 89, 1171, 107,
+ 128, 1171, -7, 1171, 1171, 62, -2,-32768, 1171, 334,
+ 124, 1171, 1171, 1171, 1171,-32768,-32768,-32768,-32768, 51,
+-32768, 73, 769,-32768,-32768, 69, 90, 210, 72, 201,
+ 115, 60, 145, 186, -13,-32768,-32768, 11,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768, 699,-32768,-32768, 5,-32768,
+ 887, 168,-32768, 101, 51,-32768, 161, 15,-32768,-32768,
+ 6,-32768, 185, 28,-32768,-32768, 16, 27,-32768,-32768,
+ 1171, 230, 1171,-32768, 1171, 1171, -59, 407, 144,-32768,
+-32768, 772, 1171, 1171, -4, 192, 194, 62, 853, 157,
+ 196,-32768, 480,-32768, 153, 958, 215,-32768,-32768,-32768,
+-32768, 1029, 1171, 225,-32768, 1171, 226,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1171, 1171, 1171, 1171, 1171, 1171,-32768, 1171,-32768,
+-32768,-32768,-32768, 231, -5, 228, 211,-32768,-32768,-32768,
+-32768,-32768, 1171,-32768,-32768, 34,-32768,-32768,-32768, 61,
+-32768, 233, 17,-32768,-32768, 55, 241, 78, 84, 85,
+-32768,-32768, 242, -7, 271,-32768,-32768,-32768,-32768,-32768,
+-32768, 23, 1171,-32768,-32768,-32768, 124,-32768,-32768,-32768,
+-32768, 96,-32768, 174,-32768, 191,-32768,-32768,-32768,-32768,
+-32768, 69, 69, 90, 90, 90, 210, 210, 210, 210,
+ 210, 210, 72, 72, 72, 72, 201, 201, 201, 145,
+ 186, 239,-32768, -15, -44, 1171, 1171,-32768,-32768, 233,
+ 100, 553,-32768, 233, 250, 772, 1171, 772, 246, 772,
+ 253,-32768,-32768, 244,-32768, 1100,-32768, 1171,-32768,-32768,
+ 1171, 1171, 290, 1171, 116, 234,-32768, 233,-32768, 626,
+-32768,-32768, 293, 118,-32768, 310,-32768,-32768, 258, 1171,
+-32768,-32768,-32768,-32768, 155, 1171, 238, 772, 1171,-32768,
+-32768, 772,-32768, 1171, 12, 310,-32768, -7,-32768, 772,
+ 156, 1171,-32768, 260,-32768, 200, 256,-32768, 310,-32768,
+-32768,-32768, 772, 263, 772, 772, 772, 268,-32768, 772,
+-32768, 772, 772,-32768,-32768, 327, 343,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,-32768,-32768, 130,-32768,-32768, 122, 326, 350,-32768,
+ -24,-32768, 40,-32768, 1, 117, 112, 8, 80, 105,
+-32768,-32768, 184, 187,-32768,-32768, -122,-32768, -1, -17,
+ -22, -66,-32768, 182, 171, 104,-32768,-32768,-32768,-32768,
+ -201,-32768,-32768,-32768,-32768,-32768,-32768, 30,-32768, 44,
+-32768,-32768,-32768,-32768,-32768, 158,-32768,-32768, 172, -161,
+-32768, 99, -74
+};
+
+
+#define YYLAST 1244
+
+
+static const short yytable[] = { 102,
+ 109, 181, 78, 229, 90, 182, 198, 179, 292, 233,
+ 97, 178, 122, 99, 100, 195, 204, 138, 266, 104,
+ 107, 337, 196, 211, 110, 111, 176, 115, 188, 189,
+ 238, 81, 128, 129, 130, 131, 139, 140, 294, 113,
+ 114, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 98, 98, 262, 108, 263, 220, 98, 79,
+ 192, 91, 179, 98, 98, 296, 193, 177, 139, 140,
+ 268, 98, 98, 98, 98, 338, 152, 179, 274, 186,
+ 190, 196, 179, 275, 80, 201, 92, 183, 199, 202,
+ 122, 87, 317, 180, 217, 162, 163, 197, 205, 206,
+ 285, 208, 101, 209, 210, 225, 188, 189, 297, 164,
+ 165, 132, 301, 218, 219, 133, 276, 334, 201, 134,
+ 185, 179, 270, 1, 2, 3, 4, 5, 154, 112,
+ 344, 234, 8, 132, 236, 82, 320, 136, 173, 278,
+ 16, 137, 155, 156, 179, 279, 280, 166, 167, 103,
+ 179, 179, 98, 98, 239, 240, 241, 287, 190, 157,
+ 158, 298, 288, 312, 191, 313, 275, 105, 314, 247,
+ 248, 249, 250, 251, 252, 213, 214, 318, 83, 323,
+ 28, 29, 179, 84, 179, 31, 93, 329, 106, 94,
+ 124, 282, 172, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 330, 343, 226, 227,
+ 221, 179, 179, 222, 174, 181, 175, 95, 94, 1,
+ 2, 3, 4, 5, 168, 169, 170, 171, 8, 289,
+ 179, 82, 193, 13, 14, 200, 16, 253, 254, 255,
+ 256, 207, 19, 159, 160, 161, 290, 179, 303, -26,
+ 305, -27, 308, 223, 295, 186, 179, 346, 24, 25,
+ 244, 245, 246, 242, 243, 304, 257, 258, 259, 352,
+ 353, 230, 235, 237, 83, 27, 28, 29, 264, 84,
+ 315, 31, 186, 267, 179, 272, 32, 33, 34, 35,
+ 333, 277, 281, 214, 335, 341, 291, 302, 306, 96,
+ 309, 310, 342, 316, 331, 322, 319, 186, 324, 328,
+ 332, 345, 336, 347, 350, 349, 357, 351, 122, 122,
+ 186, 354, 355, 85, 225, 225, 1, 2, 3, 116,
+ 117, 6, 358, 284, 7, 8, 9, 10, 82, 12,
+ 13, 14, 15, 16, 17, 18, 286, 86, 260, 19,
+ 20, 21, 261, 22, 23, 265, 269, 293, 348, 340,
+ 300, 271, 283, 0, 0, 24, 25, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 118, 27, 28, 29, 0, 30, 119, 31, 0,
+ 0, 0, 0, 32, 33, 34, 35, 0, 0, 1,
+ 2, 3, 4, 5, 6, 0, 36, 7, 8, 9,
+ 10, 82, 12, 13, 14, 15, 16, 17, 18, 0,
+ 0, 0, 19, 20, 21, 0, 22, 23, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 26, 27, 28, 29, 0, 30,
+ 212, 31, 0, 0, 0, 0, 32, 33, 34, 35,
+ 0, 0, 1, 2, 3, 4, 5, 6, 0, 36,
+ 7, 8, 9, 10, 82, 12, 13, 14, 15, 16,
+ 17, 18, 0, 0, 0, 19, 20, 21, 0, 22,
+ 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 24, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26, 27, 28,
+ 29, 0, 30, 224, 31, 0, 0, 0, 0, 32,
+ 33, 34, 35, 0, 0, 1, 2, 3, 4, 5,
+ 6, 0, 36, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 0, 0, 0, 19, 20,
+ 21, 0, 22, 23, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24, 25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 26, 27, 28, 29, 0, 30, 299, 31, 0, 0,
+ 0, 0, 32, 33, 34, 35, 0, 0, 1, 2,
+ 3, 4, 5, 6, 0, 36, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 0, 0,
+ 0, 19, 20, 21, 0, 22, 23, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 24, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 27, 28, 29, 0, 30, 321,
+ 31, 0, 0, 0, 0, 32, 33, 34, 35, 0,
+ 0, 1, 2, 3, 4, 5, 6, 0, 36, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 0, 0, 0, 19, 20, 21, 0, 22, 23,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 24, 25, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 26, 27, 28, 29,
+ 0, 30, 0, 31, 0, 0, 0, 0, 32, 33,
+ 34, 35, 0, 0, 1, 2, 3, 4, 5, 6,
+ 0, 36, 7, 8, 9, 10, 82, 12, 13, 14,
+ 15, 16, 17, 18, 0, 0, 0, 19, 20, 21,
+ 0, 22, 23, 0, 0, 0, 0, 0, 0, 0,
+ 139, 140, 0, 24, 25, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 0, 0, 0, 26,
+ 27, 28, 29, 0, 30, 0, 31, 0, 0, 0,
+ 0, 32, 33, 34, 35, 0, 0, 0, 0, 0,
+ 152, 0, -125, 0, 36, -125, -125, -125, -125, -125,
+ -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+ -125, -125, -125, -125, -125, -125, 0, 0, -125, -125,
+ -125, 0, -125, -125, 0, 0, 0, 0, 0, 1,
+ 2, 3, 4, 5, 0, 0, 0, 0, 8, 184,
+ 0, 82, 0, 13, 14, 0, 16, 0, 0, 0,
+ -125, -125, 19, 0, 0, -125, -125, 0, 0, 0,
+ 0, 0, 0, 0, -125, -125, 0, 0, 24, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 27, 28, 29, 0, 84,
+ 0, 31, 0, 0, 0, 0, 32, 33, 34, 35,
+ 1, 2, 3, 4, 5, 0, 0, 0, 0, 8,
+ 0, 0, 82, 0, 13, 14, 0, 16, 0, 0,
+ 0, 0, 0, 19, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 83, 27, 28, 29, 0,
+ 84, 0, 31, 228, 0, 0, 0, 32, 33, 34,
+ 35, 1, 2, 3, 4, 5, 0, 0, 0, 0,
+ 8, 0, 0, 82, 0, 13, 14, 0, 16, 0,
+ 0, 0, 0, 0, 19, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 24, 25, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 83, 27, 28, 29,
+ 231, 84, 0, 31, 0, 0, 0, 0, 32, 33,
+ 34, 35, 1, 2, 3, 4, 5, 0, 0, 0,
+ 0, 8, 0, 0, 82, 0, 13, 14, 0, 16,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 24, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 83, 27, 28,
+ 29, 0, 84, 0, 31, 311, 0, 0, 0, 32,
+ 33, 34, 35, 1, 2, 3, 4, 5, 0, 0,
+ 0, 0, 8, 0, 0, 82, 0, 13, 14, 0,
+ 16, 0, 0, 0, 0, 0, 19, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 24, 25, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 27,
+ 28, 29, 0, 84, 0, 31, 0, 0, 0, 0,
+ 32, 33, 34, 35
+};
+
+static const short yycheck[] = { 17,
+ 23, 76, 1, 126, 1, 1, 1, 67, 24, 132,
+ 12, 1, 30, 13, 14, 1, 1, 42, 24, 19,
+ 22, 10, 67, 83, 24, 25, 40, 29, 6, 7,
+ 153, 61, 32, 33, 34, 35, 42, 43, 83, 42,
+ 43, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 13, 14, 177, 63, 179, 62, 19, 58,
+ 85, 58, 67, 24, 25, 267, 82, 81, 42, 43,
+ 193, 32, 33, 34, 35, 64, 82, 67, 62, 81,
+ 58, 67, 67, 67, 83, 58, 83, 83, 83, 62,
+ 108, 58, 294, 83, 112, 24, 25, 83, 83, 101,
+ 223, 103, 61, 105, 106, 123, 6, 7, 270, 38,
+ 39, 61, 274, 113, 114, 65, 62, 319, 58, 69,
+ 81, 67, 62, 3, 4, 5, 6, 7, 60, 68,
+ 332, 133, 12, 61, 136, 15, 298, 65, 79, 62,
+ 20, 69, 74, 75, 67, 62, 62, 76, 77, 61,
+ 67, 67, 113, 114, 154, 155, 156, 62, 58, 70,
+ 71, 62, 67, 286, 64, 288, 67, 61, 291, 162,
+ 163, 164, 165, 166, 167, 32, 33, 62, 58, 62,
+ 60, 61, 67, 63, 67, 65, 58, 310, 61, 61,
+ 67, 214, 78, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 62, 62, 66, 67,
+ 64, 67, 67, 67, 80, 300, 41, 1, 61, 3,
+ 4, 5, 6, 7, 34, 35, 36, 37, 12, 66,
+ 67, 15, 82, 17, 18, 61, 20, 168, 169, 170,
+ 171, 22, 26, 44, 45, 46, 66, 67, 276, 68,
+ 278, 68, 280, 68, 266, 267, 67, 68, 42, 43,
+ 159, 160, 161, 157, 158, 277, 172, 173, 174, 346,
+ 347, 67, 58, 58, 58, 59, 60, 61, 58, 63,
+ 292, 65, 294, 83, 67, 63, 70, 71, 72, 73,
+ 318, 61, 61, 33, 322, 328, 68, 58, 63, 83,
+ 58, 68, 330, 24, 316, 23, 83, 319, 9, 62,
+ 83, 62, 324, 68, 62, 343, 0, 345, 346, 347,
+ 332, 64, 350, 8, 352, 353, 3, 4, 5, 6,
+ 7, 8, 0, 222, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 227, 8, 175, 26,
+ 27, 28, 176, 30, 31, 184, 196, 264, 339, 326,
+ 272, 200, 215, -1, -1, 42, 43, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 58, 59, 60, 61, -1, 63, 64, 65, -1,
+ -1, -1, -1, 70, 71, 72, 73, -1, -1, 3,
+ 4, 5, 6, 7, 8, -1, 83, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, -1,
+ -1, -1, 26, 27, 28, -1, 30, 31, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 42, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 58, 59, 60, 61, -1, 63,
+ 64, 65, -1, -1, -1, -1, 70, 71, 72, 73,
+ -1, -1, 3, 4, 5, 6, 7, 8, -1, 83,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, -1, -1, -1, 26, 27, 28, -1, 30,
+ 31, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 42, 43, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 58, 59, 60,
+ 61, -1, 63, 64, 65, -1, -1, -1, -1, 70,
+ 71, 72, 73, -1, -1, 3, 4, 5, 6, 7,
+ 8, -1, 83, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, -1, -1, -1, 26, 27,
+ 28, -1, 30, 31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 42, 43, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 58, 59, 60, 61, -1, 63, 64, 65, -1, -1,
+ -1, -1, 70, 71, 72, 73, -1, -1, 3, 4,
+ 5, 6, 7, 8, -1, 83, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, -1, -1,
+ -1, 26, 27, 28, -1, 30, 31, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 42, 43, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 58, 59, 60, 61, -1, 63, 64,
+ 65, -1, -1, -1, -1, 70, 71, 72, 73, -1,
+ -1, 3, 4, 5, 6, 7, 8, -1, 83, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, -1, -1, -1, 26, 27, 28, -1, 30, 31,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 58, 59, 60, 61,
+ -1, 63, -1, 65, -1, -1, -1, -1, 70, 71,
+ 72, 73, -1, -1, 3, 4, 5, 6, 7, 8,
+ -1, 83, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, -1, -1, -1, 26, 27, 28,
+ -1, 30, 31, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, 42, 43, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, -1, -1, -1, 58,
+ 59, 60, 61, -1, 63, -1, 65, -1, -1, -1,
+ -1, 70, 71, 72, 73, -1, -1, -1, -1, -1,
+ 82, -1, 0, -1, 83, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, -1, -1, 26, 27,
+ 28, -1, 30, 31, -1, -1, -1, -1, -1, 3,
+ 4, 5, 6, 7, -1, -1, -1, -1, 12, 13,
+ -1, 15, -1, 17, 18, -1, 20, -1, -1, -1,
+ 58, 59, 26, -1, -1, 63, 64, -1, -1, -1,
+ -1, -1, -1, -1, 72, 73, -1, -1, 42, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 58, 59, 60, 61, -1, 63,
+ -1, 65, -1, -1, -1, -1, 70, 71, 72, 73,
+ 3, 4, 5, 6, 7, -1, -1, -1, -1, 12,
+ -1, -1, 15, -1, 17, 18, -1, 20, -1, -1,
+ -1, -1, -1, 26, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 42,
+ 43, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 58, 59, 60, 61, -1,
+ 63, -1, 65, 66, -1, -1, -1, 70, 71, 72,
+ 73, 3, 4, 5, 6, 7, -1, -1, -1, -1,
+ 12, -1, -1, 15, -1, 17, 18, -1, 20, -1,
+ -1, -1, -1, -1, 26, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 58, 59, 60, 61,
+ 62, 63, -1, 65, -1, -1, -1, -1, 70, 71,
+ 72, 73, 3, 4, 5, 6, 7, -1, -1, -1,
+ -1, 12, -1, -1, 15, -1, 17, 18, -1, 20,
+ -1, -1, -1, -1, -1, 26, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 42, 43, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 58, 59, 60,
+ 61, -1, 63, -1, 65, 66, -1, -1, -1, 70,
+ 71, 72, 73, 3, 4, 5, 6, 7, -1, -1,
+ -1, -1, 12, -1, -1, 15, -1, 17, 18, -1,
+ 20, -1, -1, -1, -1, -1, 26, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 42, 43, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 58, 59,
+ 60, 61, -1, 63, -1, 65, -1, -1, -1, -1,
+ 70, 71, 72, 73
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/misc/bison.simple"
+/* This file comes from bison-1.28. */
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ 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. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
+/* #include <malloc.h> */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ unsigned int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+ register char *t = to;
+ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 217 "/usr/share/misc/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 1:
+#line 157 "grammar.y"
+{ yyval.node = new NullNode(); ;
+ break;}
+case 2:
+#line 158 "grammar.y"
+{ yyval.node = new BooleanNode(true); ;
+ break;}
+case 3:
+#line 159 "grammar.y"
+{ yyval.node = new BooleanNode(false); ;
+ break;}
+case 4:
+#line 160 "grammar.y"
+{ yyval.node = new NumberNode(yyvsp[0].dval); ;
+ break;}
+case 5:
+#line 161 "grammar.y"
+{ yyval.node = new StringNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 6:
+#line 162 "grammar.y"
+{ Lexer *l = Lexer::curr();
+ if (!l->scanRegExp()) YYABORT;
+ yyval.node = new RegExpNode(l->pattern,l->flags);;
+ break;}
+case 7:
+#line 168 "grammar.y"
+{ yyval.node = new ThisNode(); ;
+ break;}
+case 8:
+#line 169 "grammar.y"
+{ yyval.node = new ResolveNode(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 11:
+#line 173 "grammar.y"
+{ yyval.node = new GroupNode(yyvsp[-1].node); ;
+ break;}
+case 12:
+#line 174 "grammar.y"
+{ yyval.node = new ObjectLiteralNode(0L); ;
+ break;}
+case 13:
+#line 175 "grammar.y"
+{ yyval.node = new ObjectLiteralNode(yyvsp[-1].node); ;
+ break;}
+case 14:
+#line 179 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].eli); ;
+ break;}
+case 15:
+#line 180 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].elm); ;
+ break;}
+case 16:
+#line 181 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].eli, yyvsp[-3].elm); ;
+ break;}
+case 17:
+#line 185 "grammar.y"
+{ yyval.elm = new ElementNode(yyvsp[-1].eli, yyvsp[0].node); ;
+ break;}
+case 18:
+#line 187 "grammar.y"
+{ yyval.elm = new ElementNode(yyvsp[-3].elm, yyvsp[-1].eli, yyvsp[0].node); ;
+ break;}
+case 19:
+#line 191 "grammar.y"
+{ yyval.eli = 0L; ;
+ break;}
+case 21:
+#line 196 "grammar.y"
+{ yyval.eli = new ElisionNode(0L); ;
+ break;}
+case 22:
+#line 197 "grammar.y"
+{ yyval.eli = new ElisionNode(yyvsp[-1].eli); ;
+ break;}
+case 23:
+#line 201 "grammar.y"
+{ yyval.node = new PropertyValueNode(yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 24:
+#line 203 "grammar.y"
+{ yyval.node = new PropertyValueNode(yyvsp[-2].node, yyvsp[0].node, yyvsp[-4].node); ;
+ break;}
+case 25:
+#line 207 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 26:
+#line 209 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 27:
+#line 210 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].dval); ;
+ break;}
+case 30:
+#line 216 "grammar.y"
+{ yyval.node = new AccessorNode1(yyvsp[-3].node, yyvsp[-1].node); ;
+ break;}
+case 31:
+#line 217 "grammar.y"
+{ yyval.node = new AccessorNode2(yyvsp[-2].node, yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 32:
+#line 219 "grammar.y"
+{ yyval.node = new NewExprNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 34:
+#line 224 "grammar.y"
+{ yyval.node = new NewExprNode(yyvsp[0].node); ;
+ break;}
+case 35:
+#line 228 "grammar.y"
+{ yyval.node = new FunctionCallNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 36:
+#line 229 "grammar.y"
+{ yyval.node = new FunctionCallNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 37:
+#line 230 "grammar.y"
+{ yyval.node = new AccessorNode1(yyvsp[-3].node, yyvsp[-1].node); ;
+ break;}
+case 38:
+#line 231 "grammar.y"
+{ yyval.node = new AccessorNode2(yyvsp[-2].node, yyvsp[0].ustr); ;
+ break;}
+case 39:
+#line 235 "grammar.y"
+{ yyval.args = new ArgumentsNode(0L); ;
+ break;}
+case 40:
+#line 236 "grammar.y"
+{ yyval.args = new ArgumentsNode(yyvsp[-1].alist); ;
+ break;}
+case 41:
+#line 240 "grammar.y"
+{ yyval.alist = new ArgumentListNode(yyvsp[0].node); ;
+ break;}
+case 42:
+#line 241 "grammar.y"
+{ yyval.alist = new ArgumentListNode(yyvsp[-2].alist, yyvsp[0].node); ;
+ break;}
+case 46:
+#line 251 "grammar.y"
+{ yyval.node = new PostfixNode(yyvsp[-1].node, OpPlusPlus); ;
+ break;}
+case 47:
+#line 252 "grammar.y"
+{ yyval.node = new PostfixNode(yyvsp[-1].node, OpMinusMinus); ;
+ break;}
+case 49:
+#line 257 "grammar.y"
+{ yyval.node = new DeleteNode(yyvsp[0].node); ;
+ break;}
+case 50:
+#line 258 "grammar.y"
+{ yyval.node = new VoidNode(yyvsp[0].node); ;
+ break;}
+case 51:
+#line 259 "grammar.y"
+{ yyval.node = new TypeOfNode(yyvsp[0].node); ;
+ break;}
+case 52:
+#line 260 "grammar.y"
+{ yyval.node = new PrefixNode(OpPlusPlus, yyvsp[0].node); ;
+ break;}
+case 53:
+#line 261 "grammar.y"
+{ yyval.node = new PrefixNode(OpPlusPlus, yyvsp[0].node); ;
+ break;}
+case 54:
+#line 262 "grammar.y"
+{ yyval.node = new PrefixNode(OpMinusMinus, yyvsp[0].node); ;
+ break;}
+case 55:
+#line 263 "grammar.y"
+{ yyval.node = new PrefixNode(OpMinusMinus, yyvsp[0].node); ;
+ break;}
+case 56:
+#line 264 "grammar.y"
+{ yyval.node = new UnaryPlusNode(yyvsp[0].node); ;
+ break;}
+case 57:
+#line 265 "grammar.y"
+{ yyval.node = new NegateNode(yyvsp[0].node); ;
+ break;}
+case 58:
+#line 266 "grammar.y"
+{ yyval.node = new BitwiseNotNode(yyvsp[0].node); ;
+ break;}
+case 59:
+#line 267 "grammar.y"
+{ yyval.node = new LogicalNotNode(yyvsp[0].node); ;
+ break;}
+case 61:
+#line 272 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node, yyvsp[0].node, '*'); ;
+ break;}
+case 62:
+#line 273 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node, yyvsp[0].node, '/'); ;
+ break;}
+case 63:
+#line 274 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node,yyvsp[0].node,'%'); ;
+ break;}
+case 65:
+#line 279 "grammar.y"
+{ yyval.node = new AddNode(yyvsp[-2].node, yyvsp[0].node, '+'); ;
+ break;}
+case 66:
+#line 280 "grammar.y"
+{ yyval.node = new AddNode(yyvsp[-2].node, yyvsp[0].node, '-'); ;
+ break;}
+case 68:
+#line 285 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpLShift, yyvsp[0].node); ;
+ break;}
+case 69:
+#line 286 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpRShift, yyvsp[0].node); ;
+ break;}
+case 70:
+#line 287 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpURShift, yyvsp[0].node); ;
+ break;}
+case 72:
+#line 293 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpLess, yyvsp[0].node); ;
+ break;}
+case 73:
+#line 295 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpGreater, yyvsp[0].node); ;
+ break;}
+case 74:
+#line 297 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpLessEq, yyvsp[0].node); ;
+ break;}
+case 75:
+#line 299 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpGreaterEq, yyvsp[0].node); ;
+ break;}
+case 76:
+#line 301 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpInstanceOf, yyvsp[0].node); ;
+ break;}
+case 77:
+#line 303 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpIn, yyvsp[0].node); ;
+ break;}
+case 79:
+#line 308 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpEqEq, yyvsp[0].node); ;
+ break;}
+case 80:
+#line 309 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpNotEq, yyvsp[0].node); ;
+ break;}
+case 81:
+#line 310 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpStrEq, yyvsp[0].node); ;
+ break;}
+case 82:
+#line 311 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpStrNEq, yyvsp[0].node);;
+ break;}
+case 84:
+#line 316 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitAnd, yyvsp[0].node); ;
+ break;}
+case 86:
+#line 321 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitXOr, yyvsp[0].node); ;
+ break;}
+case 88:
+#line 326 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitOr, yyvsp[0].node); ;
+ break;}
+case 90:
+#line 332 "grammar.y"
+{ yyval.node = new BinaryLogicalNode(yyvsp[-2].node, OpAnd, yyvsp[0].node); ;
+ break;}
+case 92:
+#line 338 "grammar.y"
+{ yyval.node = new BinaryLogicalNode(yyvsp[-2].node, OpOr, yyvsp[0].node); ;
+ break;}
+case 94:
+#line 344 "grammar.y"
+{ yyval.node = new ConditionalNode(yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 96:
+#line 350 "grammar.y"
+{ yyval.node = new AssignNode(yyvsp[-2].node, yyvsp[-1].op, yyvsp[0].node);;
+ break;}
+case 97:
+#line 354 "grammar.y"
+{ yyval.op = OpEqual; ;
+ break;}
+case 98:
+#line 355 "grammar.y"
+{ yyval.op = OpPlusEq; ;
+ break;}
+case 99:
+#line 356 "grammar.y"
+{ yyval.op = OpMinusEq; ;
+ break;}
+case 100:
+#line 357 "grammar.y"
+{ yyval.op = OpMultEq; ;
+ break;}
+case 101:
+#line 358 "grammar.y"
+{ yyval.op = OpDivEq; ;
+ break;}
+case 102:
+#line 359 "grammar.y"
+{ yyval.op = OpLShift; ;
+ break;}
+case 103:
+#line 360 "grammar.y"
+{ yyval.op = OpRShift; ;
+ break;}
+case 104:
+#line 361 "grammar.y"
+{ yyval.op = OpURShift; ;
+ break;}
+case 105:
+#line 362 "grammar.y"
+{ yyval.op = OpAndEq; ;
+ break;}
+case 106:
+#line 363 "grammar.y"
+{ yyval.op = OpXOrEq; ;
+ break;}
+case 107:
+#line 364 "grammar.y"
+{ yyval.op = OpOrEq; ;
+ break;}
+case 108:
+#line 365 "grammar.y"
+{ yyval.op = OpModEq; ;
+ break;}
+case 110:
+#line 370 "grammar.y"
+{ yyval.node = new CommaNode(yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 125:
+#line 391 "grammar.y"
+{ yyval.stat = new BlockNode(0L); DBG(yyval.stat, yylsp[0], yylsp[0]); ;
+ break;}
+case 126:
+#line 392 "grammar.y"
+{ yyval.stat = new BlockNode(yyvsp[-1].slist); DBG(yyval.stat, yylsp[0], yylsp[0]); ;
+ break;}
+case 127:
+#line 396 "grammar.y"
+{ yyval.slist = new StatListNode(yyvsp[0].stat); ;
+ break;}
+case 128:
+#line 397 "grammar.y"
+{ yyval.slist = new StatListNode(yyvsp[-1].slist, yyvsp[0].stat); ;
+ break;}
+case 129:
+#line 401 "grammar.y"
+{ yyval.stat = new VarStatementNode(yyvsp[-1].vlist);
+ DBG(yyval.stat, yylsp[-2], yylsp[0]); ;
+ break;}
+case 130:
+#line 403 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new VarStatementNode(yyvsp[-1].vlist);
+ DBG(yyval.stat, yylsp[-2], yylsp[-1]);
+ } else {
+ YYABORT;
+ }
+ ;
+ break;}
+case 131:
+#line 413 "grammar.y"
+{ yyval.vlist = new VarDeclListNode(yyvsp[0].decl); ;
+ break;}
+case 132:
+#line 415 "grammar.y"
+{ yyval.vlist = new VarDeclListNode(yyvsp[-2].vlist, yyvsp[0].decl); ;
+ break;}
+case 133:
+#line 419 "grammar.y"
+{ yyval.decl = new VarDeclNode(yyvsp[0].ustr, 0); delete yyvsp[0].ustr; ;
+ break;}
+case 134:
+#line 420 "grammar.y"
+{ yyval.decl = new VarDeclNode(yyvsp[-1].ustr, yyvsp[0].init); delete yyvsp[-1].ustr; ;
+ break;}
+case 135:
+#line 424 "grammar.y"
+{ yyval.init = new AssignExprNode(yyvsp[0].node); ;
+ break;}
+case 136:
+#line 428 "grammar.y"
+{ yyval.stat = new EmptyStatementNode(); ;
+ break;}
+case 137:
+#line 432 "grammar.y"
+{ yyval.stat = new ExprStatementNode(yyvsp[-1].node);
+ DBG(yyval.stat, yylsp[-1], yylsp[0]); ;
+ break;}
+case 138:
+#line 434 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ExprStatementNode(yyvsp[-1].node);
+ DBG(yyval.stat, yylsp[-1], yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 139:
+#line 442 "grammar.y"
+{ yyval.stat = new IfNode(yyvsp[-2].node,yyvsp[0].stat,0L);DBG(yyval.stat,yylsp[-4],yylsp[-1]); ;
+ break;}
+case 140:
+#line 444 "grammar.y"
+{ yyval.stat = new IfNode(yyvsp[-4].node,yyvsp[-2].stat,yyvsp[0].stat);DBG(yyval.stat,yylsp[-6],yylsp[-3]); ;
+ break;}
+case 141:
+#line 448 "grammar.y"
+{ yyval.stat=new DoWhileNode(yyvsp[-4].stat,yyvsp[-1].node);DBG(yyval.stat,yylsp[-5],yylsp[-3]);;
+ break;}
+case 142:
+#line 449 "grammar.y"
+{ yyval.stat = new WhileNode(yyvsp[-2].node,yyvsp[0].stat);DBG(yyval.stat,yylsp[-4],yylsp[-1]); ;
+ break;}
+case 143:
+#line 451 "grammar.y"
+{ yyval.stat = new ForNode(yyvsp[-6].node,yyvsp[-4].node,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-8],yylsp[-1]); ;
+ break;}
+case 144:
+#line 454 "grammar.y"
+{ yyval.stat = new ForNode(yyvsp[-6].vlist,yyvsp[-4].node,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-9],yylsp[-1]); ;
+ break;}
+case 145:
+#line 457 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-6],yylsp[-1]); ;
+ break;}
+case 146:
+#line 460 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-4].ustr,0L,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-7],yylsp[-1]);
+ delete yyvsp[-4].ustr; ;
+ break;}
+case 147:
+#line 464 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-5].ustr,yyvsp[-4].init,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-8],yylsp[-1]);
+ delete yyvsp[-5].ustr; ;
+ break;}
+case 148:
+#line 470 "grammar.y"
+{ yyval.node = 0L; ;
+ break;}
+case 150:
+#line 475 "grammar.y"
+{ yyval.stat = new ContinueNode(); DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 151:
+#line 476 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ContinueNode(); DBG(yyval.stat,yylsp[-1],yylsp[0]);
+ } else
+ YYABORT; ;
+ break;}
+case 152:
+#line 480 "grammar.y"
+{ yyval.stat = new ContinueNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[0]);
+ delete yyvsp[-1].ustr; ;
+ break;}
+case 153:
+#line 482 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ContinueNode(yyvsp[-1].ustr);DBG(yyval.stat,yylsp[-2],yylsp[-1]);
+ delete yyvsp[-1].ustr;
+ } else
+ YYABORT; ;
+ break;}
+case 154:
+#line 490 "grammar.y"
+{ yyval.stat = new BreakNode();DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 155:
+#line 491 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new BreakNode(); DBG(yyval.stat,yylsp[-1],yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 156:
+#line 495 "grammar.y"
+{ yyval.stat = new BreakNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[0]);
+ delete yyvsp[-1].ustr; ;
+ break;}
+case 157:
+#line 497 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new BreakNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[-1]);
+ delete yyvsp[-1].ustr;
+ } else
+ YYABORT;
+ ;
+ break;}
+case 158:
+#line 506 "grammar.y"
+{ yyval.stat = new ReturnNode(0L); DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 159:
+#line 507 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ReturnNode(0L); DBG(yyval.stat,yylsp[-1],yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 160:
+#line 511 "grammar.y"
+{ yyval.stat = new ReturnNode(yyvsp[-1].node); ;
+ break;}
+case 161:
+#line 512 "grammar.y"
+{ if (automatic())
+ yyval.stat = new ReturnNode(yyvsp[-1].node);
+ else
+ YYABORT; ;
+ break;}
+case 162:
+#line 519 "grammar.y"
+{ yyval.stat = new WithNode(yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat, yylsp[-4], yylsp[-1]); ;
+ break;}
+case 163:
+#line 524 "grammar.y"
+{ yyval.stat = new SwitchNode(yyvsp[-2].node, yyvsp[0].cblk);
+ DBG(yyval.stat, yylsp[-4], yylsp[-1]); ;
+ break;}
+case 164:
+#line 529 "grammar.y"
+{ yyval.cblk = new CaseBlockNode(yyvsp[-1].clist, 0L, 0L); ;
+ break;}
+case 165:
+#line 531 "grammar.y"
+{ yyval.cblk = new CaseBlockNode(yyvsp[-3].clist, yyvsp[-2].ccl, yyvsp[-1].clist); ;
+ break;}
+case 166:
+#line 535 "grammar.y"
+{ yyval.clist = 0L; ;
+ break;}
+case 168:
+#line 540 "grammar.y"
+{ yyval.clist = new ClauseListNode(yyvsp[0].ccl); ;
+ break;}
+case 169:
+#line 541 "grammar.y"
+{ yyval.clist = yyvsp[-1].clist->append(yyvsp[0].ccl); ;
+ break;}
+case 170:
+#line 545 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(yyvsp[-1].node, 0L); ;
+ break;}
+case 171:
+#line 546 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(yyvsp[-2].node, yyvsp[0].slist); ;
+ break;}
+case 172:
+#line 550 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(0L, 0L);; ;
+ break;}
+case 173:
+#line 551 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(0L, yyvsp[0].slist); ;
+ break;}
+case 174:
+#line 555 "grammar.y"
+{ yyvsp[0].stat->pushLabel(yyvsp[-2].ustr);
+ yyval.stat = new LabelNode(yyvsp[-2].ustr, yyvsp[0].stat);
+ delete yyvsp[-2].ustr; ;
+ break;}
+case 175:
+#line 561 "grammar.y"
+{ yyval.stat = new ThrowNode(yyvsp[-1].node); ;
+ break;}
+case 176:
+#line 565 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-1].stat, yyvsp[0].node); ;
+ break;}
+case 177:
+#line 566 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-1].stat, 0L, yyvsp[0].node); ;
+ break;}
+case 178:
+#line 567 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-2].stat, yyvsp[-1].node, yyvsp[0].node); ;
+ break;}
+case 179:
+#line 571 "grammar.y"
+{ yyval.node = new CatchNode(yyvsp[-2].ustr, yyvsp[0].stat); delete yyvsp[-2].ustr; ;
+ break;}
+case 180:
+#line 575 "grammar.y"
+{ yyval.node = new FinallyNode(yyvsp[0].stat); ;
+ break;}
+case 181:
+#line 579 "grammar.y"
+{ yyval.func = new FuncDeclNode(yyvsp[-3].ustr, 0L, yyvsp[0].body);
+ delete yyvsp[-3].ustr; ;
+ break;}
+case 182:
+#line 582 "grammar.y"
+{ yyval.func = new FuncDeclNode(yyvsp[-4].ustr, yyvsp[-2].param, yyvsp[0].body);
+ delete yyvsp[-4].ustr; ;
+ break;}
+case 183:
+#line 586 "grammar.y"
+{ yyval.node = new FuncExprNode(0L, yyvsp[0].body); ;
+ break;}
+case 184:
+#line 588 "grammar.y"
+{ yyval.node = new FuncExprNode(yyvsp[-2].param, yyvsp[0].body); ;
+ break;}
+case 185:
+#line 593 "grammar.y"
+{ yyval.param = new ParameterNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 186:
+#line 594 "grammar.y"
+{ yyval.param = yyvsp[-2].param->append(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 187:
+#line 599 "grammar.y"
+{ yyval.body = new FunctionBodyNode(0L); ;
+ break;}
+case 188:
+#line 600 "grammar.y"
+{ yyval.body = new FunctionBodyNode(yyvsp[-1].srcs); ;
+ break;}
+case 189:
+#line 604 "grammar.y"
+{ yyval.prog = new ProgramNode(yyvsp[0].srcs);
+ KJScriptImp::current()->setProgNode(yyval.prog); ;
+ break;}
+case 190:
+#line 609 "grammar.y"
+{ yyval.srcs = new SourceElementsNode(yyvsp[0].src); ;
+ break;}
+case 191:
+#line 610 "grammar.y"
+{ yyval.srcs = new SourceElementsNode(yyvsp[-1].srcs, yyvsp[0].src); ;
+ break;}
+case 192:
+#line 614 "grammar.y"
+{ yyval.src = new SourceElementNode(yyvsp[0].stat); ;
+ break;}
+case 193:
+#line 615 "grammar.y"
+{ yyval.src = new SourceElementNode(yyvsp[0].func); ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/share/misc/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
+}
+#line 618 "grammar.y"
+
+
+int yyerror (const char *) /* Called by yyparse on error */
+{
+// fprintf(stderr, "ERROR: %s at line %d\n",
+// s, KJScript::lexer()->lineNo());
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+bool automatic()
+{
+ if (yychar == '}' || yychar == 0)
+ return true;
+ else if (Lexer::curr()->prevTerminator())
+ return true;
+
+ return false;
+}
diff --git a/JavaScriptCore/kjs/grammar.h b/JavaScriptCore/kjs/grammar.h
new file mode 100644
index 0000000..38eb0ba
--- /dev/null
+++ b/JavaScriptCore/kjs/grammar.h
@@ -0,0 +1,102 @@
+typedef union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+} YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#define NULLTOKEN 257
+#define TRUETOKEN 258
+#define FALSETOKEN 259
+#define STRING 260
+#define NUMBER 261
+#define BREAK 262
+#define CASE 263
+#define DEFAULT 264
+#define FOR 265
+#define NEW 266
+#define VAR 267
+#define CONTINUE 268
+#define FUNCTION 269
+#define RETURN 270
+#define VOID 271
+#define DELETE 272
+#define IF 273
+#define THIS 274
+#define DO 275
+#define WHILE 276
+#define ELSE 277
+#define IN 278
+#define INSTANCEOF 279
+#define TYPEOF 280
+#define SWITCH 281
+#define WITH 282
+#define RESERVED 283
+#define THROW 284
+#define TRY 285
+#define CATCH 286
+#define FINALLY 287
+#define EQEQ 288
+#define NE 289
+#define STREQ 290
+#define STRNEQ 291
+#define LE 292
+#define GE 293
+#define OR 294
+#define AND 295
+#define PLUSPLUS 296
+#define MINUSMINUS 297
+#define LSHIFT 298
+#define RSHIFT 299
+#define URSHIFT 300
+#define PLUSEQUAL 301
+#define MINUSEQUAL 302
+#define MULTEQUAL 303
+#define DIVEQUAL 304
+#define LSHIFTEQUAL 305
+#define RSHIFTEQUAL 306
+#define URSHIFTEQUAL 307
+#define ANDEQUAL 308
+#define MODEQUAL 309
+#define XOREQUAL 310
+#define OREQUAL 311
+#define IDENT 312
+#define AUTO 313
+
+
+extern YYSTYPE kjsyylval;
diff --git a/JavaScriptCore/kjs/grammar.y b/JavaScriptCore/kjs/grammar.y
new file mode 100644
index 0000000..cf07456
--- /dev/null
+++ b/JavaScriptCore/kjs/grammar.y
@@ -0,0 +1,636 @@
+%{
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+
+/* default values for bison */
+#define YYDEBUG 0
+#define YYMAXDEPTH 0
+#ifdef KJS_DEBUGGER
+#define YYERROR_VERBOSE
+#define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line); } // location
+#else
+#undef YYLSP_NEEDED
+#define DBG(l, s, e)
+#endif
+
+extern int yylex();
+int yyerror (const char *);
+bool automatic();
+
+using namespace KJS;
+
+%}
+
+%union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+}
+
+%start Program
+
+/* expect a shift/reduce conflict from the "dangling else" problem
+ when using bison the warning can be supressed */
+// %expect 1
+
+/* literals */
+%token NULLTOKEN TRUETOKEN FALSETOKEN
+%token STRING NUMBER
+
+/* keywords */
+%token BREAK CASE DEFAULT FOR NEW VAR CONTINUE
+%token FUNCTION RETURN VOID DELETE
+%token IF THIS DO WHILE ELSE IN INSTANCEOF TYPEOF
+%token SWITCH WITH RESERVED
+%token THROW TRY CATCH FINALLY
+
+/* punctuators */
+%token EQEQ NE /* == and != */
+%token STREQ STRNEQ /* === and !== */
+%token LE GE /* < and > */
+%token OR AND /* || and && */
+%token PLUSPLUS MINUSMINUS /* ++ and -- */
+%token LSHIFT /* << */
+%token RSHIFT URSHIFT /* >> and >>> */
+%token PLUSEQUAL MINUSEQUAL /* += and -= */
+%token MULTEQUAL DIVEQUAL /* *= and /= */
+%token LSHIFTEQUAL /* <<= */
+%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
+%token ANDEQUAL MODEQUAL /* &= and %= */
+%token XOREQUAL OREQUAL /* ^= and |= */
+
+/* terminal types */
+%token <dval> NUMBER
+%token <ustr> STRING
+%token <ustr> IDENT
+
+/* automatically inserted semicolon */
+%token AUTO
+
+/* non-terminal types */
+%type <node> Literal PrimaryExpr Expr MemberExpr FunctionExpr NewExpr CallExpr
+%type <node> ArrayLiteral PropertyName PropertyNameAndValueList
+%type <node> LeftHandSideExpr PostfixExpr UnaryExpr
+%type <node> MultiplicativeExpr AdditiveExpr
+%type <node> ShiftExpr RelationalExpr EqualityExpr
+%type <node> BitwiseANDExpr BitwiseXORExpr BitwiseORExpr
+%type <node> LogicalANDExpr LogicalORExpr
+%type <node> ConditionalExpr AssignmentExpr
+%type <node> ExprOpt
+%type <node> CallExpr
+%type <node> Catch Finally
+
+%type <stat> Statement Block
+%type <stat> VariableStatement EmptyStatement ExprStatement
+%type <stat> IfStatement IterationStatement ContinueStatement
+%type <stat> BreakStatement ReturnStatement WithStatement
+%type <stat> SwitchStatement LabelledStatement
+%type <stat> ThrowStatement TryStatement
+
+%type <slist> StatementList
+%type <init> Initializer
+%type <func> FunctionDeclaration
+%type <body> FunctionBody
+%type <src> SourceElement
+%type <srcs> SourceElements
+%type <param> FormalParameterList
+%type <op> AssignmentOperator
+%type <prog> Program
+%type <args> Arguments
+%type <alist> ArgumentList
+%type <vlist> VariableDeclarationList
+%type <decl> VariableDeclaration
+%type <cblk> CaseBlock
+%type <ccl> CaseClause DefaultClause
+%type <clist> CaseClauses CaseClausesOpt
+%type <eli> Elision ElisionOpt
+%type <elm> ElementList
+
+%%
+
+Literal:
+ NULLTOKEN { $$ = new NullNode(); }
+ | TRUETOKEN { $$ = new BooleanNode(true); }
+ | FALSETOKEN { $$ = new BooleanNode(false); }
+ | NUMBER { $$ = new NumberNode($1); }
+ | STRING { $$ = new StringNode($1); delete $1; }
+ | '/' /* a RegExp ? */ { Lexer *l = Lexer::curr();
+ if (!l->scanRegExp()) YYABORT;
+ $$ = new RegExpNode(l->pattern,l->flags);}
+;
+
+PrimaryExpr:
+ THIS { $$ = new ThisNode(); }
+ | IDENT { $$ = new ResolveNode($1);
+ delete $1; }
+ | Literal
+ | ArrayLiteral
+ | '(' Expr ')' { $$ = new GroupNode($2); }
+ | '{' '}' { $$ = new ObjectLiteralNode(0L); }
+ | '{' PropertyNameAndValueList '}' { $$ = new ObjectLiteralNode($2); }
+;
+
+ArrayLiteral:
+ '[' ElisionOpt ']' { $$ = new ArrayNode($2); }
+ | '[' ElementList ']' { $$ = new ArrayNode($2); }
+ | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
+;
+
+ElementList:
+ ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $2); }
+ | ElementList ',' ElisionOpt AssignmentExpr
+ { $$ = new ElementNode($1, $3, $4); }
+;
+
+ElisionOpt:
+ /* nothing */ { $$ = 0L; }
+ | Elision
+;
+
+Elision:
+ ',' { $$ = new ElisionNode(0L); }
+ | Elision ',' { $$ = new ElisionNode($1); }
+;
+
+PropertyNameAndValueList:
+ PropertyName ':' AssignmentExpr { $$ = new PropertyValueNode($1, $3); }
+ | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
+ { $$ = new PropertyValueNode($3, $5, $1); }
+;
+
+PropertyName:
+ IDENT { $$ = new PropertyNode($1);
+ delete $1; }
+ | STRING { $$ = new PropertyNode($1); delete $1; }
+ | NUMBER { $$ = new PropertyNode($1); }
+;
+
+MemberExpr:
+ PrimaryExpr
+ | FunctionExpr
+ | MemberExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
+ | MemberExpr '.' IDENT { $$ = new AccessorNode2($1, $3);
+ delete $3; }
+ | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
+;
+
+NewExpr:
+ MemberExpr
+ | NEW NewExpr { $$ = new NewExprNode($2); }
+;
+
+CallExpr:
+ MemberExpr Arguments { $$ = new FunctionCallNode($1, $2); }
+ | CallExpr Arguments { $$ = new FunctionCallNode($1, $2); }
+ | CallExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
+ | CallExpr '.' IDENT { $$ = new AccessorNode2($1, $3); }
+;
+
+Arguments:
+ '(' ')' { $$ = new ArgumentsNode(0L); }
+ | '(' ArgumentList ')' { $$ = new ArgumentsNode($2); }
+;
+
+ArgumentList:
+ AssignmentExpr { $$ = new ArgumentListNode($1); }
+ | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
+;
+
+LeftHandSideExpr:
+ NewExpr
+ | CallExpr
+;
+
+PostfixExpr: /* TODO: no line terminator here */
+ LeftHandSideExpr
+ | LeftHandSideExpr PLUSPLUS { $$ = new PostfixNode($1, OpPlusPlus); }
+ | LeftHandSideExpr MINUSMINUS { $$ = new PostfixNode($1, OpMinusMinus); }
+;
+
+UnaryExpr:
+ PostfixExpr
+ | DELETE UnaryExpr { $$ = new DeleteNode($2); }
+ | VOID UnaryExpr { $$ = new VoidNode($2); }
+ | TYPEOF UnaryExpr { $$ = new TypeOfNode($2); }
+ | PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
+ | AUTO PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $3); }
+ | MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
+ | AUTO MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $3); }
+ | '+' UnaryExpr { $$ = new UnaryPlusNode($2); }
+ | '-' UnaryExpr { $$ = new NegateNode($2); }
+ | '~' UnaryExpr { $$ = new BitwiseNotNode($2); }
+ | '!' UnaryExpr { $$ = new LogicalNotNode($2); }
+;
+
+MultiplicativeExpr:
+ UnaryExpr
+ | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
+ | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
+ | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
+;
+
+AdditiveExpr:
+ MultiplicativeExpr
+ | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
+ | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
+;
+
+ShiftExpr:
+ AdditiveExpr
+ | ShiftExpr LSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpLShift, $3); }
+ | ShiftExpr RSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpRShift, $3); }
+ | ShiftExpr URSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpURShift, $3); }
+;
+
+RelationalExpr:
+ ShiftExpr
+ | RelationalExpr '<' ShiftExpr
+ { $$ = new RelationalNode($1, OpLess, $3); }
+ | RelationalExpr '>' ShiftExpr
+ { $$ = new RelationalNode($1, OpGreater, $3); }
+ | RelationalExpr LE ShiftExpr
+ { $$ = new RelationalNode($1, OpLessEq, $3); }
+ | RelationalExpr GE ShiftExpr
+ { $$ = new RelationalNode($1, OpGreaterEq, $3); }
+ | RelationalExpr INSTANCEOF ShiftExpr
+ { $$ = new RelationalNode($1, OpInstanceOf, $3); }
+ | RelationalExpr IN ShiftExpr
+ { $$ = new RelationalNode($1, OpIn, $3); }
+;
+
+EqualityExpr:
+ RelationalExpr
+ | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, OpEqEq, $3); }
+ | EqualityExpr NE RelationalExpr { $$ = new EqualNode($1, OpNotEq, $3); }
+ | EqualityExpr STREQ RelationalExpr { $$ = new EqualNode($1, OpStrEq, $3); }
+ | EqualityExpr STRNEQ RelationalExpr { $$ = new EqualNode($1, OpStrNEq, $3);}
+;
+
+BitwiseANDExpr:
+ EqualityExpr
+ | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
+;
+
+BitwiseXORExpr:
+ BitwiseANDExpr
+ | BitwiseXORExpr '^' EqualityExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
+;
+
+BitwiseORExpr:
+ BitwiseXORExpr
+ | BitwiseORExpr '|' EqualityExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
+;
+
+LogicalANDExpr:
+ BitwiseORExpr
+ | LogicalANDExpr AND BitwiseORExpr
+ { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
+;
+
+LogicalORExpr:
+ LogicalANDExpr
+ | LogicalORExpr OR LogicalANDExpr
+ { $$ = new BinaryLogicalNode($1, OpOr, $3); }
+;
+
+ConditionalExpr:
+ LogicalORExpr
+ | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = new ConditionalNode($1, $3, $5); }
+;
+
+AssignmentExpr:
+ ConditionalExpr
+ | LeftHandSideExpr AssignmentOperator AssignmentExpr
+ { $$ = new AssignNode($1, $2, $3);}
+;
+
+AssignmentOperator:
+ '=' { $$ = OpEqual; }
+ | PLUSEQUAL { $$ = OpPlusEq; }
+ | MINUSEQUAL { $$ = OpMinusEq; }
+ | MULTEQUAL { $$ = OpMultEq; }
+ | DIVEQUAL { $$ = OpDivEq; }
+ | LSHIFTEQUAL { $$ = OpLShift; }
+ | RSHIFTEQUAL { $$ = OpRShift; }
+ | URSHIFTEQUAL { $$ = OpURShift; }
+ | ANDEQUAL { $$ = OpAndEq; }
+ | XOREQUAL { $$ = OpXOrEq; }
+ | OREQUAL { $$ = OpOrEq; }
+ | MODEQUAL { $$ = OpModEq; }
+;
+
+Expr:
+ AssignmentExpr
+ | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
+;
+
+Statement:
+ Block
+ | VariableStatement
+ | EmptyStatement
+ | ExprStatement
+ | IfStatement
+ | IterationStatement
+ | ContinueStatement
+ | BreakStatement
+ | ReturnStatement
+ | WithStatement
+ | SwitchStatement
+ | LabelledStatement
+ | ThrowStatement
+ | TryStatement
+;
+
+Block:
+ '{' '}' { $$ = new BlockNode(0L); DBG($$, @2, @2); }
+ | '{' StatementList '}' { $$ = new BlockNode($2); DBG($$, @3, @3); }
+;
+
+StatementList:
+ Statement { $$ = new StatListNode($1); }
+ | StatementList Statement { $$ = new StatListNode($1, $2); }
+;
+
+VariableStatement:
+ VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
+ DBG($$, @1, @3); }
+ | VAR VariableDeclarationList error { if (automatic()) {
+ $$ = new VarStatementNode($2);
+ DBG($$, @1, @2);
+ } else {
+ YYABORT;
+ }
+ }
+;
+
+VariableDeclarationList:
+ VariableDeclaration { $$ = new VarDeclListNode($1); }
+ | VariableDeclarationList ',' VariableDeclaration
+ { $$ = new VarDeclListNode($1, $3); }
+;
+
+VariableDeclaration:
+ IDENT { $$ = new VarDeclNode($1, 0); delete $1; }
+ | IDENT Initializer { $$ = new VarDeclNode($1, $2); delete $1; }
+;
+
+Initializer:
+ '=' AssignmentExpr { $$ = new AssignExprNode($2); }
+;
+
+EmptyStatement:
+ ';' { $$ = new EmptyStatementNode(); }
+;
+
+ExprStatement:
+ Expr ';' { $$ = new ExprStatementNode($1);
+ DBG($$, @1, @2); }
+ | Expr error { if (automatic()) {
+ $$ = new ExprStatementNode($1);
+ DBG($$, @1, @1);
+ } else
+ YYABORT; }
+;
+
+IfStatement: /* shift/reduce conflict due to dangling else */
+ IF '(' Expr ')' Statement { $$ = new IfNode($3,$5,0L);DBG($$,@1,@4); }
+ | IF '(' Expr ')' Statement ELSE Statement
+ { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
+;
+
+IterationStatement:
+ DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
+ | WHILE '(' Expr ')' Statement { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
+ | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
+ Statement { $$ = new ForNode($3,$5,$7,$9);
+ DBG($$,@1,@8); }
+ | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
+ Statement { $$ = new ForNode($4,$6,$8,$10);
+ DBG($$,@1,@9); }
+ | FOR '(' LeftHandSideExpr IN Expr ')'
+ Statement { $$ = new ForInNode($3, $5, $7);
+ DBG($$,@1,@6); }
+ | FOR '(' VAR IDENT IN Expr ')'
+ Statement { $$ = new ForInNode($4,0L,$6,$8);
+ DBG($$,@1,@7);
+ delete $4; }
+ | FOR '(' VAR IDENT Initializer IN Expr ')'
+ Statement { $$ = new ForInNode($4,$5,$7,$9);
+ DBG($$,@1,@8);
+ delete $4; }
+;
+
+ExprOpt:
+ /* nothing */ { $$ = 0L; }
+ | Expr
+;
+
+ContinueStatement:
+ CONTINUE ';' { $$ = new ContinueNode(); DBG($$,@1,@2); }
+ | CONTINUE error { if (automatic()) {
+ $$ = new ContinueNode(); DBG($$,@1,@2);
+ } else
+ YYABORT; }
+ | CONTINUE IDENT ';' { $$ = new ContinueNode($2); DBG($$,@1,@3);
+ delete $2; }
+ | CONTINUE IDENT error { if (automatic()) {
+ $$ = new ContinueNode($2);DBG($$,@1,@2);
+ delete $2;
+ } else
+ YYABORT; }
+;
+
+BreakStatement:
+ BREAK ';' { $$ = new BreakNode();DBG($$,@1,@2); }
+ | BREAK error { if (automatic()) {
+ $$ = new BreakNode(); DBG($$,@1,@1);
+ } else
+ YYABORT; }
+ | BREAK IDENT ';' { $$ = new BreakNode($2); DBG($$,@1,@3);
+ delete $2; }
+ | BREAK IDENT error { if (automatic()) {
+ $$ = new BreakNode($2); DBG($$,@1,@2);
+ delete $2;
+ } else
+ YYABORT;
+ }
+;
+
+ReturnStatement:
+ RETURN ';' { $$ = new ReturnNode(0L); DBG($$,@1,@2); }
+ | RETURN error { if (automatic()) {
+ $$ = new ReturnNode(0L); DBG($$,@1,@1);
+ } else
+ YYABORT; }
+ | RETURN Expr ';' { $$ = new ReturnNode($2); }
+ | RETURN Expr error { if (automatic())
+ $$ = new ReturnNode($2);
+ else
+ YYABORT; }
+;
+
+WithStatement:
+ WITH '(' Expr ')' Statement { $$ = new WithNode($3,$5);
+ DBG($$, @1, @4); }
+;
+
+SwitchStatement:
+ SWITCH '(' Expr ')' CaseBlock { $$ = new SwitchNode($3, $5);
+ DBG($$, @1, @4); }
+;
+
+CaseBlock:
+ '{' CaseClausesOpt '}' { $$ = new CaseBlockNode($2, 0L, 0L); }
+ | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
+ { $$ = new CaseBlockNode($2, $3, $4); }
+;
+
+CaseClausesOpt:
+ /* nothing */ { $$ = 0L; }
+ | CaseClauses
+;
+
+CaseClauses:
+ CaseClause { $$ = new ClauseListNode($1); }
+ | CaseClauses CaseClause { $$ = $1->append($2); }
+;
+
+CaseClause:
+ CASE Expr ':' { $$ = new CaseClauseNode($2, 0L); }
+ | CASE Expr ':' StatementList { $$ = new CaseClauseNode($2, $4); }
+;
+
+DefaultClause:
+ DEFAULT ':' { $$ = new CaseClauseNode(0L, 0L);; }
+ | DEFAULT ':' StatementList { $$ = new CaseClauseNode(0L, $3); }
+;
+
+LabelledStatement:
+ IDENT ':' Statement { $3->pushLabel($1);
+ $$ = new LabelNode($1, $3);
+ delete $1; }
+;
+
+ThrowStatement:
+ THROW Expr ';' { $$ = new ThrowNode($2); }
+;
+
+TryStatement:
+ TRY Block Catch { $$ = new TryNode($2, $3); }
+ | TRY Block Finally { $$ = new TryNode($2, 0L, $3); }
+ | TRY Block Catch Finally { $$ = new TryNode($2, $3, $4); }
+;
+
+Catch:
+ CATCH '(' IDENT ')' Block { $$ = new CatchNode($3, $5); delete $3; }
+;
+
+Finally:
+ FINALLY Block { $$ = new FinallyNode($2); }
+;
+
+FunctionDeclaration:
+ FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode($2, 0L, $5);
+ delete $2; }
+ | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
+ { $$ = new FuncDeclNode($2, $4, $6);
+ delete $2; }
+
+FunctionExpr:
+ FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode(0L, $4); }
+ | FUNCTION '(' FormalParameterList ')' FunctionBody
+ { $$ = new FuncExprNode($3, $5); }
+
+;
+
+FormalParameterList:
+ IDENT { $$ = new ParameterNode($1); delete $1; }
+ | FormalParameterList ',' IDENT { $$ = $1->append($3);
+ delete $3; }
+;
+
+FunctionBody:
+ '{' '}' /* TODO: spec ??? */ { $$ = new FunctionBodyNode(0L); }
+ | '{' SourceElements '}' { $$ = new FunctionBodyNode($2); }
+;
+
+Program:
+ SourceElements { $$ = new ProgramNode($1);
+ KJScriptImp::current()->setProgNode($$); }
+;
+
+SourceElements:
+ SourceElement { $$ = new SourceElementsNode($1); }
+ | SourceElements SourceElement { $$ = new SourceElementsNode($1, $2); }
+;
+
+SourceElement:
+ Statement { $$ = new SourceElementNode($1); }
+ | FunctionDeclaration { $$ = new SourceElementNode($1); }
+;
+
+%%
+
+int yyerror (const char *) /* Called by yyparse on error */
+{
+// fprintf(stderr, "ERROR: %s at line %d\n",
+// s, KJScript::lexer()->lineNo());
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+bool automatic()
+{
+ if (yychar == '}' || yychar == 0)
+ return true;
+ else if (Lexer::curr()->prevTerminator())
+ return true;
+
+ return false;
+}
diff --git a/JavaScriptCore/kjs/internal.cpp b/JavaScriptCore/kjs/internal.cpp
new file mode 100644
index 0000000..9fc40fa
--- /dev/null
+++ b/JavaScriptCore/kjs/internal.cpp
@@ -0,0 +1,912 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "internal.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "types.h"
+#include "operations.h"
+#include "regexp.h"
+#include "nodes.h"
+#include "lexer.h"
+#include "collector.h"
+#include "debugger.h"
+
+#define I18N_NOOP(s) s
+
+extern int kjsyyparse();
+
+using namespace KJS;
+
+const TypeInfo UndefinedImp::info = { "Undefined", UndefinedType, 0, 0, 0 };
+const TypeInfo NullImp::info = { "Null", NullType, 0, 0, 0 };
+const TypeInfo NumberImp::info = { "Number", NumberType, 0, 0,0 };
+const TypeInfo StringImp::info = { "String", StringType, 0, 0, 0 };
+const TypeInfo BooleanImp::info = { "Boolean", BooleanType, 0, 0, 0 };
+const TypeInfo CompletionImp::info = { "Completion", CompletionType, 0, 0, 0 };
+const TypeInfo ReferenceImp::info = { "Reference", ReferenceType, 0, 0, 0 };
+
+UndefinedImp *UndefinedImp::staticUndefined = 0;
+
+UndefinedImp::UndefinedImp()
+{
+}
+
+KJSO UndefinedImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean UndefinedImp::toBoolean() const
+{
+ return Boolean(false);
+}
+
+Number UndefinedImp::toNumber() const
+{
+ return Number(NaN);
+}
+
+String UndefinedImp::toString() const
+{
+ return String("undefined");
+}
+
+Object UndefinedImp::toObject() const
+{
+ return Error::createObject(TypeError, I18N_NOOP("Undefined value"));
+}
+
+NullImp *NullImp::staticNull = 0;
+
+NullImp::NullImp()
+{
+}
+
+KJSO NullImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean NullImp::toBoolean() const
+{
+ return Boolean(false);
+}
+
+Number NullImp::toNumber() const
+{
+ return Number(0);
+}
+
+String NullImp::toString() const
+{
+ return String("null");
+}
+
+Object NullImp::toObject() const
+{
+ return Error::createObject(TypeError, I18N_NOOP("Null value"));
+}
+
+BooleanImp* BooleanImp::staticTrue = 0;
+BooleanImp* BooleanImp::staticFalse = 0;
+
+KJSO BooleanImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean BooleanImp::toBoolean() const
+{
+ return Boolean((BooleanImp*)this);
+}
+
+Number BooleanImp::toNumber() const
+{
+ return Number(val ? 1 : 0);
+}
+
+String BooleanImp::toString() const
+{
+ return String(val ? "true" : "false");
+}
+
+Object BooleanImp::toObject() const
+{
+ return Object::create(BooleanClass, Boolean((BooleanImp*)this));
+}
+
+NumberImp::NumberImp(double v)
+ : val(v)
+{
+}
+
+KJSO NumberImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean NumberImp::toBoolean() const
+{
+ bool b = !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
+
+ return Boolean(b);
+}
+
+Number NumberImp::toNumber() const
+{
+ return Number((NumberImp*)this);
+}
+
+String NumberImp::toString() const
+{
+ return String(UString::from(val));
+}
+
+Object NumberImp::toObject() const
+{
+ return Object::create(NumberClass, Number((NumberImp*)this));
+}
+
+StringImp::StringImp(const UString& v)
+ : val(v)
+{
+}
+
+KJSO StringImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean StringImp::toBoolean() const
+{
+ return Boolean(val.size() > 0);
+}
+
+Number StringImp::toNumber() const
+{
+ return Number(val.toDouble());
+}
+
+String StringImp::toString() const
+{
+ return String((StringImp*)this);
+}
+
+Object StringImp::toObject() const
+{
+ return Object::create(StringClass, String((StringImp*)this));
+}
+
+ReferenceImp::ReferenceImp(const KJSO& b, const UString& p)
+ : base(b), prop(p)
+{
+}
+
+void ReferenceImp::mark(Imp*)
+{
+ Imp::mark();
+ Imp *im = base.imp();
+ if (im && !im->marked())
+ im->mark();
+}
+
+CompletionImp::CompletionImp(Compl c, const KJSO& v, const UString& t)
+ : comp(c), val(v), tar(t)
+{
+}
+
+void CompletionImp::mark(Imp*)
+{
+ Imp::mark();
+ Imp *im = val.imp();
+ if (im && !im->marked())
+ im->mark();
+}
+
+RegExpImp::RegExpImp()
+ : ObjectImp(RegExpClass), reg(0L)
+{
+}
+
+RegExpImp::~RegExpImp()
+{
+ delete reg;
+}
+
+// ECMA 10.2
+Context::Context(CodeType type, Context *callingContext,
+ FunctionImp *func, const List *args, Imp *thisV)
+{
+ Global glob(Global::current());
+
+ // create and initialize activation object (ECMA 10.1.6)
+ if (type == FunctionCode || type == AnonymousCode || type == HostCode) {
+ activation = new ActivationImp(func, args);
+ variable = activation;
+ } else {
+ activation = KJSO();
+ variable = glob;
+ }
+
+ // ECMA 10.2
+ switch(type) {
+ case EvalCode:
+ if (callingContext) {
+ scopeChain = callingContext->copyOfChain();
+ variable = callingContext->variableObject();
+ thisVal = callingContext->thisValue();
+ break;
+ } // else same as GlobalCode
+ case GlobalCode:
+ scopeChain = new List();
+ scopeChain->append(glob);
+ thisVal = glob.imp();
+ break;
+ case FunctionCode:
+ case AnonymousCode:
+ if (type == FunctionCode) {
+ scopeChain = ((DeclaredFunctionImp*)func)->scopeChain()->copy();
+ scopeChain->prepend(activation);
+ } else {
+ scopeChain = new List();
+ scopeChain->append(activation);
+ scopeChain->append(glob);
+ }
+ variable = activation; /* TODO: DontDelete ? (ECMA 10.2.3) */
+ if (thisV->type() >= ObjectType) {
+ thisVal = thisV;
+ }
+ else
+ thisVal = glob.imp();
+ break;
+ case HostCode:
+ if (thisV->type() >= ObjectType)
+ thisVal = thisV;
+ else
+ thisVal = glob;
+ variable = activation; /* TODO: DontDelete (ECMA 10.2.4) */
+ scopeChain = new List();
+ scopeChain->append(activation);
+ if (func->hasAttribute(ImplicitThis))
+ scopeChain->append(KJSO(thisVal));
+ if (func->hasAttribute(ImplicitParents)) {
+ /* TODO ??? */
+ }
+ scopeChain->append(glob);
+ break;
+ }
+}
+
+Context::~Context()
+{
+ delete scopeChain;
+}
+
+Context *Context::current()
+{
+ return KJScriptImp::curr ? KJScriptImp::curr->con : 0L;
+}
+
+void Context::setCurrent(Context *c)
+{
+ KJScriptImp::current()->con = c;
+}
+
+void Context::pushScope(const KJSO &s)
+{
+ scopeChain->prepend(s);
+}
+
+void Context::popScope()
+{
+ scopeChain->removeFirst();
+}
+
+List* Context::copyOfChain()
+{
+ return scopeChain->copy();
+}
+
+
+AnonymousFunction::AnonymousFunction()
+ : Function(0L)
+{
+ /* TODO */
+}
+
+DeclaredFunctionImp::DeclaredFunctionImp(const UString &n,
+ FunctionBodyNode *b, const List *sc)
+ : ConstructorImp(n), body(b), scopes(sc->copy())
+{
+}
+
+DeclaredFunctionImp::~DeclaredFunctionImp()
+{
+ delete scopes;
+}
+
+// step 2 of ECMA 13.2.1. rest in FunctionImp::executeCall()
+Completion DeclaredFunctionImp::execute(const List &)
+{
+ /* TODO */
+
+#ifdef KJS_DEBUGGER
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ int oldSourceId = -1;
+ if (dbg) {
+ oldSourceId = dbg->sourceId();
+ dbg->setSourceId(body->sourceId());
+ }
+#endif
+
+ Completion result = body->execute();
+
+#ifdef KJS_DEBUGGER
+ if (dbg) {
+ dbg->setSourceId(oldSourceId);
+ }
+#endif
+
+ if (result.complType() == Throw || result.complType() == ReturnValue)
+ return result;
+ return Completion(Normal, Undefined()); /* TODO: or ReturnValue ? */
+}
+
+// ECMA 13.2.2 [[Construct]]
+Object DeclaredFunctionImp::construct(const List &args)
+{
+ Object obj(ObjectClass);
+ KJSO p = get("prototype");
+ if (p.isObject())
+ obj.setPrototype(p);
+ else
+ obj.setPrototype(Global::current().objectPrototype());
+
+ KJSO res = executeCall(obj.imp(), &args);
+
+ Object v = Object::dynamicCast(res);
+ if (v.isNull())
+ return obj;
+ else
+ return v;
+}
+
+Completion AnonymousFunction::execute(const List &)
+{
+ /* TODO */
+ return Completion(Normal, Null());
+}
+
+// ECMA 10.1.8
+class ArgumentsObject : public ObjectImp {
+public:
+ ArgumentsObject(FunctionImp *func, const List *args);
+};
+
+ArgumentsObject::ArgumentsObject(FunctionImp *func, const List *args)
+ : ObjectImp(UndefClass)
+{
+ put("callee", Function(func), DontEnum);
+ if (args) {
+ put("length", Number(args->size()), DontEnum);
+ ListIterator arg = args->begin();
+ for (int i = 0; arg != args->end(); arg++, i++) {
+ put(UString::from(i), *arg, DontEnum);
+ }
+ }
+}
+
+const TypeInfo ActivationImp::info = { "Activation", ActivationType, 0, 0, 0 };
+
+// ECMA 10.1.6
+ActivationImp::ActivationImp(FunctionImp *f, const List *args)
+{
+ KJSO aobj(new ArgumentsObject(f, args));
+ put("arguments", aobj, DontDelete);
+ /* TODO: this is here to get myFunc.arguments and myFunc.a1 going.
+ I can't see this described in the spec but it's possible in browsers. */
+ if (!f->name().isNull())
+ f->put("arguments", aobj);
+}
+
+ExecutionStack::ExecutionStack()
+ : progNode(0L), firstNode(0L), prev(0)
+{
+}
+
+ExecutionStack* ExecutionStack::push()
+{
+ ExecutionStack *s = new ExecutionStack();
+ s->prev = this;
+
+ return s;
+}
+
+ExecutionStack* ExecutionStack::pop()
+{
+ ExecutionStack *s = prev;
+ delete this;
+
+ return s;
+}
+
+KJScriptImp* KJScriptImp::curr = 0L;
+KJScriptImp* KJScriptImp::hook = 0L;
+int KJScriptImp::instances = 0;
+int KJScriptImp::running = 0;
+
+KJScriptImp::KJScriptImp(KJScript *s)
+ : scr(s),
+ initialized(false),
+ glob(0L),
+#ifdef KJS_DEBUGGER
+ dbg(0L),
+#endif
+ retVal(0L)
+{
+ instances++;
+ KJScriptImp::curr = this;
+ // are we the first interpreter instance ? Initialize some stuff
+ if (instances == 1)
+ globalInit();
+ stack = new ExecutionStack();
+ clearException();
+ lex = new Lexer();
+}
+
+KJScriptImp::~KJScriptImp()
+{
+ KJScriptImp::curr = this;
+
+#ifdef KJS_DEBUGGER
+ attachDebugger(0L);
+#endif
+
+ clear();
+
+ delete lex;
+ lex = 0L;
+
+ delete stack;
+ stack = 0L;
+
+ KJScriptImp::curr = 0L;
+ // are we the last of our kind ? Free global stuff.
+ if (instances == 1)
+ globalClear();
+ instances--;
+}
+
+void KJScriptImp::globalInit()
+{
+ UndefinedImp::staticUndefined = new UndefinedImp();
+ UndefinedImp::staticUndefined->ref();
+ NullImp::staticNull = new NullImp();
+ NullImp::staticNull->ref();
+ BooleanImp::staticTrue = new BooleanImp(true);
+ BooleanImp::staticTrue->ref();
+ BooleanImp::staticFalse = new BooleanImp(false);
+ BooleanImp::staticFalse->ref();
+}
+
+void KJScriptImp::globalClear()
+{
+ UndefinedImp::staticUndefined->deref();
+ UndefinedImp::staticUndefined = 0L;
+ NullImp::staticNull->deref();
+ NullImp::staticNull = 0L;
+ BooleanImp::staticTrue->deref();
+ BooleanImp::staticTrue = 0L;
+ BooleanImp::staticFalse->deref();
+ BooleanImp::staticFalse = 0L;
+}
+
+void KJScriptImp::mark()
+{
+ if (exVal && !exVal->marked())
+ exVal->mark();
+ if (retVal && !retVal->marked())
+ retVal->mark();
+ UndefinedImp::staticUndefined->mark();
+ NullImp::staticNull->mark();
+ BooleanImp::staticTrue->mark();
+ BooleanImp::staticFalse->mark();
+}
+
+void KJScriptImp::init()
+{
+ KJScriptImp::curr = this;
+
+ clearException();
+ retVal = 0L;
+
+ if (!initialized) {
+ // add this interpreter to the global chain
+ // as a root set for garbage collection
+ if (hook) {
+ prev = hook;
+ next = hook->next;
+ hook->next->prev = this;
+ hook->next = this;
+ } else {
+ hook = next = prev = this;
+ }
+
+ glob.init();
+ con = new Context();
+ firstN = 0L;
+ progN = 0L;
+ recursion = 0;
+ errMsg = "";
+ initialized = true;
+#ifdef KJS_DEBUGGER
+ sid = -1;
+#endif
+ }
+}
+
+void KJScriptImp::clear()
+{
+ if ( recursion ) {
+#ifndef NDEBUG
+ fprintf(stderr, "KJS: ignoring clear() while running\n");
+#endif
+ return;
+ }
+ KJScriptImp *old = curr;
+ if (initialized) {
+ KJScriptImp::curr = this;
+
+ Node::setFirstNode(firstNode());
+ Node::deleteAllNodes();
+ setFirstNode(0L);
+ setProgNode(0L);
+
+ clearException();
+ retVal = 0L;
+
+ delete con; con = 0L;
+ glob.clear();
+
+ Collector::collect();
+
+ // remove from global chain (see init())
+ next->prev = prev;
+ prev->next = next;
+ hook = next;
+ if (hook == this)
+ hook = 0L;
+
+#ifdef KJS_DEBUGGER
+ sid = -1;
+#endif
+
+ initialized = false;
+ }
+ if (old != this)
+ KJScriptImp::curr = old;
+}
+
+bool KJScriptImp::evaluate(const UChar *code, unsigned int length, const KJSO &thisV,
+ bool onlyCheckSyntax)
+{
+ init();
+
+#ifdef KJS_DEBUGGER
+ sid++;
+ if (debugger())
+ debugger()->setSourceId(sid);
+#endif
+ if (recursion > 7) {
+ fprintf(stderr, "KJS: breaking out of recursion\n");
+ return true;
+ } else if (recursion > 0) {
+#ifndef NDEBUG
+ fprintf(stderr, "KJS: entering recursion level %d\n", recursion);
+#endif
+ pushStack();
+ }
+
+ assert(Lexer::curr());
+ Lexer::curr()->setCode(code, length);
+ Node::setFirstNode(firstNode());
+ int parseError = kjsyyparse();
+ setFirstNode(Node::firstNode());
+
+ if (parseError) {
+ errType = 99; /* TODO */
+ errLine = Lexer::curr()->lineNo();
+ errMsg = "Parse error at line " + UString::from(errLine);
+#ifndef NDEBUG
+ fprintf(stderr, "JavaScript parse error at line %d.\n", errLine);
+#endif
+ /* TODO: either clear everything or keep previously
+ parsed function definitions */
+ // Node::deleteAllNodes();
+ return false;
+ }
+
+ if (onlyCheckSyntax)
+ return true;
+
+ clearException();
+
+ KJSO oldVar;
+ if (!thisV.isNull()) {
+ context()->setThisValue(thisV);
+ context()->pushScope(thisV);
+ oldVar = context()->variableObject();
+ context()->setVariableObject(thisV);
+ }
+
+ running++;
+ recursion++;
+ assert(progNode());
+ Completion res = progNode()->execute();
+ recursion--;
+ running--;
+
+ if (hadException()) {
+ KJSO err = exception();
+ errType = 99; /* TODO */
+ errLine = err.get("line").toInt32();
+ errMsg = err.get("name").toString().value() + ". ";
+ errMsg += err.get("message").toString().value();
+#ifdef KJS_DEBUGGER
+ if (dbg)
+ dbg->setSourceId(err.get("sid").toInt32());
+#endif
+ clearException();
+ } else {
+ errType = 0;
+ errLine = -1;
+ errMsg = "";
+
+ // catch return value
+ retVal = 0L;
+ if (res.complType() == ReturnValue || !thisV.isNull())
+ retVal = res.value().imp();
+ }
+
+ if (!thisV.isNull()) {
+ context()->popScope();
+ context()->setVariableObject(oldVar);
+ }
+
+ if (progNode())
+ progNode()->deleteGlobalStatements();
+
+ if (recursion > 0) {
+ popStack();
+ }
+
+ return !errType;
+}
+
+void KJScriptImp::pushStack()
+{
+ stack = stack->push();
+}
+
+void KJScriptImp::popStack()
+{
+ stack = stack->pop();
+ assert(stack);
+}
+
+bool KJScriptImp::call(const KJSO &scope, const UString &func, const List &args)
+{
+ init();
+ KJSO callScope(scope);
+ if (callScope.isNull())
+ callScope = Global::current().imp();
+ if (!callScope.hasProperty(func)) {
+#ifndef NDEBUG
+ fprintf(stderr, "couldn't resolve function name %s. call() failed\n",
+ func.ascii());
+#endif
+ return false;
+ }
+ KJSO v = callScope.get(func);
+ if (!v.isA(ConstructorType)) {
+#ifndef NDEBUG
+ fprintf(stderr, "%s is not a function. call() failed.\n", func.ascii());
+#endif
+ return false;
+ }
+ running++;
+ recursion++;
+ static_cast<ConstructorImp*>(v.imp())->executeCall(scope.imp(), &args);
+ recursion--;
+ running--;
+ return !hadException();
+}
+
+bool KJScriptImp::call(const KJSO &func, const KJSO &thisV,
+ const List &args, const List &extraScope)
+{
+ init();
+ if(!func.implementsCall())
+ return false;
+
+ running++;
+ recursion++;
+ retVal = func.executeCall(thisV, &args, &extraScope).imp();
+ recursion--;
+ running--;
+
+ return !hadException();
+}
+
+void KJScriptImp::setException(Imp *e)
+{
+ assert(curr);
+ curr->exVal = e;
+ curr->exMsg = "Exception"; // not very meaningful but we use !0L to test
+}
+
+void KJScriptImp::setException(const char *msg)
+{
+ assert(curr);
+ curr->exVal = 0L; // will be created later on exception()
+ curr->exMsg = msg;
+}
+
+KJSO KJScriptImp::exception()
+{
+ assert(curr);
+ if (!curr->exMsg)
+ return Undefined();
+ if (curr->exVal)
+ return curr->exVal;
+ return Error::create(GeneralError, curr->exMsg);
+}
+
+void KJScriptImp::clearException()
+{
+ assert(curr);
+ curr->exMsg = 0L;
+ curr->exVal = 0L;
+}
+
+#ifdef KJS_DEBUGGER
+void KJScriptImp::attachDebugger(Debugger *d)
+{
+ static bool detaching = false;
+ if (detaching) // break circular detaching
+ return;
+
+ if (dbg) {
+ detaching = true;
+ dbg->detach();
+ detaching = false;
+ }
+
+ dbg = d;
+}
+
+bool KJScriptImp::setBreakpoint(int id, int line, bool set)
+{
+ init();
+ return Node::setBreakpoint(firstNode(), id, line, set);
+}
+
+#endif
+
+bool PropList::contains(const UString &name)
+{
+ PropList *p = this;
+ while (p) {
+ if (name == p->name)
+ return true;
+ p = p->next;
+ }
+ return false;
+}
+
+bool LabelStack::push(const UString &id)
+{
+ if (id.isEmpty() || contains(id))
+ return false;
+
+ StackElm *newtos = new StackElm;
+ newtos->id = id;
+ newtos->prev = tos;
+ tos = newtos;
+ return true;
+}
+
+bool LabelStack::contains(const UString &id) const
+{
+ if (id.isEmpty())
+ return true;
+
+ for (StackElm *curr = tos; curr; curr = curr->prev)
+ if (curr->id == id)
+ return true;
+
+ return false;
+}
+
+void LabelStack::pop()
+{
+ if (tos) {
+ StackElm *prev = tos->prev;
+ delete tos;
+ tos = prev;
+ }
+}
+
+LabelStack::~LabelStack()
+{
+ StackElm *prev;
+
+ while (tos) {
+ prev = tos->prev;
+ delete tos;
+ tos = prev;
+ }
+}
+
+// ECMA 15.3.5.3 [[HasInstance]]
+// see comment in header file
+KJSO KJS::hasInstance(const KJSO &F, const KJSO &V)
+{
+ if (V.isObject()) {
+ KJSO prot = F.get("prototype");
+ if (!prot.isObject())
+ return Error::create(TypeError, "Invalid prototype encountered "
+ "in instanceof operation.");
+ Imp *v = V.imp();
+ while ((v = v->prototype())) {
+ if (v == prot.imp())
+ return Boolean(true);
+ }
+ }
+ return Boolean(false);
+}
+
+#ifndef NDEBUG
+#include <stdio.h>
+void KJS::printInfo( const char *s, const KJSO &o )
+{
+ if (o.isNull())
+ fprintf(stderr, "%s: (null)\n", s);
+ else {
+ KJSO v = o;
+ if (o.isA(ReferenceType))
+ v = o.getValue();
+ fprintf(stderr, "JS: %s: %s : %s (%p)\n",
+ s,
+ v.toString().value().ascii(),
+ v.imp()->typeInfo()->name,
+ (void*)v.imp());
+ if (o.isA(ReferenceType)) {
+ fprintf(stderr, "JS: Was property '%s'\n", o.getPropertyName().ascii());
+ printInfo("of", o.getBase());
+ }
+ }
+}
+#endif
diff --git a/JavaScriptCore/kjs/internal.h b/JavaScriptCore/kjs/internal.h
new file mode 100644
index 0000000..51a8ece
--- /dev/null
+++ b/JavaScriptCore/kjs/internal.h
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _INTERNAL_H_
+#define _INTERNAL_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kjs.h"
+#include "object.h"
+#include "function.h"
+
+#define I18N_NOOP(s) s
+
+namespace KJS {
+
+ class Boolean;
+ class Number;
+ class String;
+ class Object;
+ class RegExp;
+ class Node;
+ class FunctionBodyNode;
+ class ProgramNode;
+#ifdef KJS_DEBUGGER
+ class Debugger;
+#endif
+
+ class UndefinedImp : public Imp {
+ public:
+ UndefinedImp();
+ virtual ~UndefinedImp() { }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static UndefinedImp *staticUndefined;
+ };
+
+ class NullImp : public Imp {
+ public:
+ NullImp();
+ virtual ~NullImp() { }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static NullImp *staticNull;
+ };
+
+ class BooleanImp : public Imp {
+ public:
+ virtual ~BooleanImp() { }
+ BooleanImp(bool v = false) : val(v) { }
+ bool value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static BooleanImp *staticTrue, *staticFalse;
+ private:
+ bool val;
+ };
+
+ class NumberImp : public Imp {
+ public:
+ NumberImp(double v);
+ virtual ~NumberImp() { }
+ double value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ double val;
+ };
+
+ class StringImp : public Imp {
+ public:
+ StringImp(const UString& v);
+ virtual ~StringImp() { }
+ UString value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ UString val;
+ };
+
+ class ReferenceImp : public Imp {
+ public:
+ ReferenceImp(const KJSO& b, const UString& p);
+ virtual ~ReferenceImp() { }
+ virtual void mark(Imp*);
+ KJSO getBase() const { return base; }
+ UString getPropertyName() const { return prop; }
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ KJSO base;
+ UString prop;
+ };
+
+ class CompletionImp : public Imp {
+ public:
+ CompletionImp(Compl c, const KJSO& v, const UString& t);
+ virtual ~CompletionImp() { }
+ virtual void mark(Imp*);
+ Compl completion() const { return comp; }
+ KJSO value() const { return val; }
+ UString target() const { return tar; }
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ Compl comp;
+ KJSO val;
+ UString tar;
+ };
+
+ class RegExpImp : public ObjectImp {
+ public:
+ RegExpImp();
+ ~RegExpImp();
+ void setRegExp(RegExp *r) { reg = r; }
+ RegExp* regExp() const { return reg; }
+ private:
+ RegExp *reg;
+ };
+
+ class StatementNode;
+ class UString;
+
+ class Reference : public KJSO {
+ public:
+ Reference(const KJSO& b, const UString &p);
+ virtual ~Reference();
+ };
+
+ /**
+ * @short The "label set" in Ecma-262 spec
+ */
+ class LabelStack {
+ public:
+ LabelStack(): tos(0L) {}
+ ~LabelStack();
+
+ /**
+ * If id is not empty and is not in the stack already, puts it on top of
+ * the stack and returns true, otherwise returns false
+ */
+ bool push(const UString &id);
+ /**
+ * Is the id in the stack?
+ */
+ bool contains(const UString &id) const;
+ /**
+ * Removes from the stack the last pushed id (what else?)
+ */
+ void pop();
+ private:
+ struct StackElm {
+ UString id;
+ StackElm *prev;
+ };
+
+ StackElm *tos;
+ };
+
+ /**
+ * @short Execution context.
+ */
+ class Context {
+ public:
+ Context(CodeType type = GlobalCode, Context *callingContext = 0L,
+ FunctionImp *func = 0L, const List *args = 0L, Imp *thisV = 0L);
+ virtual ~Context();
+ static Context *current();
+ static void setCurrent(Context *c);
+ const List *pScopeChain() const { return scopeChain; }
+ void pushScope(const KJSO &s);
+ void popScope();
+ List *copyOfChain();
+ KJSO variableObject() const { return variable; }
+ void setVariableObject( const KJSO &obj ) { variable = obj; }
+ KJSO thisValue() const { return thisVal; }
+ void setThisValue(const KJSO &t) { thisVal = t; }
+ LabelStack *seenLabels() { return &ls; }
+ private:
+ LabelStack ls;
+ KJSO thisVal;
+ KJSO activation;
+ KJSO variable;
+ List *scopeChain;
+ };
+
+ class DeclaredFunctionImp : public ConstructorImp {
+ public:
+ DeclaredFunctionImp(const UString &n, FunctionBodyNode *b,
+ const List *sc);
+ ~DeclaredFunctionImp();
+ Completion execute(const List &);
+ Object construct(const List &);
+ CodeType codeType() const { return FunctionCode; }
+ List *scopeChain() const { return scopes; }
+ private:
+ FunctionBodyNode *body;
+ List *scopes;
+ };
+
+ class AnonymousFunction : public Function {
+ public:
+ AnonymousFunction();
+ Completion execute(const List &);
+ CodeType codeType() const { return AnonymousCode; }
+ };
+
+ class ActivationImp : public Imp {
+ public:
+ ActivationImp(FunctionImp *f, const List *args);
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ };
+
+ class ExecutionStack {
+ public:
+ ExecutionStack();
+ ExecutionStack *push();
+ ExecutionStack *pop();
+
+ ProgramNode *progNode;
+ Node *firstNode;
+ private:
+ ExecutionStack *prev;
+ };
+
+ class KJScriptImp {
+ friend class ::KJScript;
+ friend class Lexer;
+ friend class Context;
+ friend class Global;
+ friend class Collector;
+ public:
+ KJScriptImp(KJScript *s);
+ ~KJScriptImp();
+ void mark();
+ static KJScriptImp *current() { return curr; }
+ static void setException(Imp *e);
+ static void setException(const char *msg);
+ static bool hadException();
+ static KJSO exception();
+ static void clearException();
+
+ Context *context() const { return con; }
+ void setContext(Context *c) { con = c; }
+
+#ifdef KJS_DEBUGGER
+ /**
+ * Attach debugger d to this engine. If there already was another instance
+ * attached it will be detached.
+ */
+ void attachDebugger(Debugger *d);
+ Debugger *debugger() const { return dbg; }
+ int sourceId() const { return sid; }
+ bool setBreakpoint(int id, int line, bool set);
+#endif
+ private:
+ /**
+ * Initialize global object and context. For internal use only.
+ */
+ void init();
+ void clear();
+ /**
+ * Called when the first interpreter is instanciated. Initializes
+ * global pointers.
+ */
+ void globalInit();
+ /**
+ * Called when the last interpreter instance is destroyed. Frees
+ * globally allocated memory.
+ */
+ void globalClear();
+ bool evaluate(const UChar *code, unsigned int length, const KJSO &thisV = KJSO(),
+ bool onlyCheckSyntax = false);
+ bool call(const KJSO &scope, const UString &func, const List &args);
+ bool call(const KJSO &func, const KJSO &thisV,
+ const List &args, const List &extraScope);
+
+ public:
+ ProgramNode *progNode() const { return stack->progNode; }
+ void setProgNode(ProgramNode *p) { stack->progNode = p; }
+ Node *firstNode() const { return stack->firstNode; }
+ void setFirstNode(Node *n) { stack->firstNode = n; }
+ void pushStack();
+ void popStack();
+ KJScriptImp *next, *prev;
+ KJScript *scr;
+ ExecutionStack *stack;
+
+ private:
+ ProgramNode *progN;
+ Node *firstN;
+
+ static KJScriptImp *curr, *hook;
+ static int instances; // total number of instances
+ static int running; // total number running
+ bool initialized;
+ Lexer *lex;
+ Context *con;
+ Global glob;
+ int errType, errLine;
+ UString errMsg;
+#ifdef KJS_DEBUGGER
+ Debugger *dbg;
+ int sid;
+#endif
+ const char *exMsg;
+ Imp *exVal;
+ Imp *retVal;
+ int recursion;
+ };
+
+ inline bool KJScriptImp::hadException()
+ {
+ assert(curr);
+ return curr->exMsg;
+ }
+
+ /**
+ * @short Struct used to return the property names of an object
+ */
+ class PropList {
+ public:
+ PropList(UString nm = UString::null, PropList *nx = 0) :
+ name(nm), next(nx) {};
+ ~PropList() {
+ if(next) delete next;
+ }
+ /**
+ * The property name
+ */
+ UString name;
+ /**
+ * The next property
+ */
+ PropList *next;
+ bool contains(const UString &name);
+ };
+
+ /* TODO just temporary until functions are objects and this becomes
+ a member function. Called by RelationNode for 'instanceof' operator. */
+ KJSO hasInstance(const KJSO &F, const KJSO &V);
+
+// #define KJS_VERBOSE
+#ifndef NDEBUG
+ void printInfo( const char *s, const KJSO &o );
+#endif
+
+}; // namespace
+
+
+#endif
diff --git a/JavaScriptCore/kjs/keywords.table b/JavaScriptCore/kjs/keywords.table
new file mode 100644
index 0000000..391aa34
--- /dev/null
+++ b/JavaScriptCore/kjs/keywords.table
@@ -0,0 +1,66 @@
+# main keywords
+@begin mainTable 41
+# types
+null NULLTOKEN
+true TRUETOKEN
+false FALSETOKEN
+# keywords
+break BREAK
+case CASE
+catch CATCH
+default DEFAULT
+finally FINALLY
+for FOR
+instanceof INSTANCEOF
+new NEW
+var VAR
+continue CONTINUE
+function FUNCTION
+return RETURN
+void VOID
+delete DELETE
+if IF
+this THIS
+do DO
+while WHILE
+else ELSE
+in IN
+switch SWITCH
+throw THROW
+try TRY
+typeof TYPEOF
+with WITH
+# reserved for future use
+abstract RESERVED
+boolean RESERVED
+byte RESERVED
+char RESERVED
+class RESERVED
+const RESERVED
+debugger RESERVED
+double RESERVED
+enum RESERVED
+export RESERVED
+extends RESERVED
+final RESERVED
+float RESERVED
+goto RESERVED
+implements RESERVED
+import RESERVED
+int RESERVED
+interface RESERVED
+long RESERVED
+native RESERVED
+package RESERVED
+private RESERVED
+protected RESERVED
+public RESERVED
+short RESERVED
+static RESERVED
+super RESERVED
+synchronized RESERVED
+throws RESERVED
+transient RESERVED
+volatile RESERVED
+@end
+
diff --git a/JavaScriptCore/kjs/kjs.cpp b/JavaScriptCore/kjs/kjs.cpp
new file mode 100644
index 0000000..d6c0260
--- /dev/null
+++ b/JavaScriptCore/kjs/kjs.cpp
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "collector.h"
+
+using namespace KJS;
+
+KJScript::KJScript()
+{
+ rep = new KJScriptImp(this);
+ rep->init();
+}
+
+KJScript::~KJScript()
+{
+ delete rep;
+
+#ifdef KJS_DEBUG_MEM
+ //printf("Imp::count: %d\n", Imp::count);
+ // assert(Imp::count == 0);
+#endif
+}
+
+void KJScript::init()
+{
+ rep->init();
+}
+
+Imp *KJScript::globalObject() const
+{
+ return rep->glob.imp();
+}
+
+void KJScript::setCurrent( KJScript *newCurr )
+{
+ KJScriptImp::curr = newCurr ? newCurr->rep : 0L;
+}
+
+KJScript *KJScript::current()
+{
+ return KJScriptImp::current() ? KJScriptImp::current()->scr : 0L;
+}
+
+int KJScript::recursion() const
+{
+ return rep->recursion;
+}
+
+bool KJScript::evaluate(const char *code)
+{
+ return rep->evaluate(UString(code).data(), strlen(code));
+}
+
+bool KJScript::evaluate(const UString &code)
+{
+ return rep->evaluate(code.data(), code.size());
+}
+
+bool KJScript::evaluate(const KJSO &thisV,
+ const QChar *code, unsigned int length)
+{
+ return rep->evaluate((UChar*)code, length, thisV);
+}
+
+bool KJScript::call(const KJS::UString &func, const List &args)
+{
+ return rep->call(0, func, args);
+}
+
+bool KJScript::call(const KJSO &scope, const KJS::UString &func,
+ const KJS::List &args)
+{
+ return rep->call(scope.imp(), func, args);
+}
+
+bool KJScript::call(const KJS::KJSO &func, const KJSO &thisV,
+ const KJS::List &args, const KJS::List &extraScope)
+{
+ return rep->call(func, thisV, args, extraScope);
+}
+
+void KJScript::clear()
+{
+ rep->clear();
+}
+
+Imp *KJScript::returnValue() const
+{
+ return rep->retVal;
+}
+
+int KJScript::errorType() const
+{
+ return rep->errType;
+}
+
+int KJScript::errorLine() const
+{
+ return rep->errLine;
+}
+
+const char* KJScript::errorMsg() const
+{
+ return rep->errMsg.ascii();
+}
+
+bool KJScript::checkSyntax(const KJS::UString &code )
+{
+ return rep->evaluate(code.data(), code.size(), 0, true);
+}
+
+/**
+ * @short Print to stderr for debugging purposes.
+ */
+namespace KJS {
+ class DebugPrint : public InternalFunctionImp {
+ public:
+ Completion execute(const List &args)
+ {
+ KJSO v = args[0];
+ String s = v.toString();
+ fprintf(stderr, "---> %s\n", s.value().cstring().c_str());
+
+ return Completion(Normal);
+ }
+ };
+};
+
+void KJScript::enableDebug()
+{
+ rep->init();
+ Global::current().put("debug", Function(new DebugPrint()));
+}
diff --git a/JavaScriptCore/kjs/kjs.h b/JavaScriptCore/kjs/kjs.h
new file mode 100644
index 0000000..42a866d
--- /dev/null
+++ b/JavaScriptCore/kjs/kjs.h
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_H_
+#define _KJS_H_
+
+class QChar;
+
+namespace KJS {
+ class UString;
+ class Lexer;
+ class Context;
+ class Global;
+ class KJSO;
+ class Object;
+ class Imp;
+ class List;
+ class KJScriptImp;
+#ifdef KJS_DEBUGGER
+ class Debugger;
+#endif
+};
+
+/**
+ * @libdoc ECMAScript interpreter
+ *
+ * This library provides an interpreter for ECMAScript aka JavaScript.
+ * It currently aims at compliance with Edition 3 of the standard.
+ */
+
+/**
+ * @short ECMAScript interpreter
+ */
+class KJScript {
+ friend class KJS::KJScriptImp;
+ friend class KJS::KJSO;
+ friend class KJS::Context;
+ friend class KJS::Lexer;
+ friend class KJS::Global;
+public:
+ /**
+ * Create a new ECMAScript interpreter. You can later ask it to interprete
+ * code by passing it via @ref #evaluate.
+ */
+ KJScript();
+ /**
+ * Destructor
+ */
+ ~KJScript();
+ /**
+ * Force a "context switch". You usually do not need to do that,
+ * evaluate() does it too.
+ */
+ void init();
+ /**
+ * Returns a pointer to the Global object.
+ */
+ KJS::Imp *globalObject() const;
+ /**
+ * Don't use. May disappear.
+ */
+ static KJScript *current();
+ /**
+ * Don't use. May disappear.
+ */
+ static void setCurrent( KJScript *newCurr );
+
+ /**
+ * Current level of recursive calls to this interpreter. 0 initially.
+ */
+ int recursion() const;
+ /**
+ * Asks the interpreter to evaluate a piece of code. If called more than
+ * once the state (global variables, functions etc.) will be preserved
+ * between each call.
+ * @param code is a string containing the code to be executed.
+ * @return True if the code was evaluated successfully, false if an error
+ * occured.
+ */
+ bool evaluate(const char *code);
+ /**
+ * Same as above. Only differing in the arguments accepted.
+ * @param code is a pointer to an Unicode string containing the code to
+ * be executed.
+ * @param length number of characters.
+ */
+ bool evaluate(const KJS::KJSO &thisV,
+ const QChar *code, unsigned int length);
+ /**
+ * Added for convenience in case you have the code in available in
+ * internal representation already.
+ * @param code is an Unicode string containing the code to be executed.
+ */
+ bool evaluate(const KJS::UString &code);
+ /**
+ * Call the specified function directly, optionally passing args as a
+ * list of arguments. Return value and treatment of errors is analog
+ * to the evaluate() calls.
+ */
+ bool call(const KJS::UString &func, const KJS::List &args);
+ bool call(const KJS::KJSO &scope, const KJS::UString &func,
+ const KJS::List &args);
+ bool call(const KJS::KJSO &func, const KJS::KJSO &thisV,
+ const KJS::List &args, const KJS::List &extraScope );
+ /**
+ * Clear the interpreter's memory. Otherwise, function declarations
+ * and global variables will be remembered after each invokation of
+ * @ref KJScript::evaluate.
+ */
+ void clear();
+ /**
+ * @return Return value from the last call to @ref evaluate(). Null if there
+ * hasn't been any.
+ */
+ KJS::Imp *returnValue() const;
+ /**
+ * @return Return code from last call to @ref evaluate(). 0 on success.
+ */
+ int errorType() const;
+ /**
+ * @return Return line of last error. -1 if last call didn't have an error.
+ */
+ int errorLine() const;
+ /**
+ * @return Error message from last call to @ref evaluate(). Empty string
+ * if no error occured.
+ */
+ const char *errorMsg() const;
+ /**
+ * Check the syntax of a piece of code. Return true if the code could be
+ * parsed without errors, false otherwise. @ref errorLine() will tell you
+ * approximately where the syntax error happened.
+ */
+ bool checkSyntax(const KJS::UString &code);
+ /**
+ * Adds a debug() function to the set of pre-defined properties.
+ * debug(arg) tries to convert 'arg' to a string and prints the result
+ * to stderr. If you want to debug self defined Host Objects this way
+ * you should provide them with a toString() method that returns a string.
+ */
+ void enableDebug();
+private:
+ KJS::KJScriptImp *rep;
+ // not implemented
+ KJScript(const KJScript&);
+ KJScript operator=(const KJScript&);
+
+#ifdef KJS_DEBUGGER
+ friend class KJS::Debugger;
+#endif
+};
+
+#endif
diff --git a/JavaScriptCore/kjs/lexer.cpp b/JavaScriptCore/kjs/lexer.cpp
new file mode 100644
index 0000000..7ce1a3d
--- /dev/null
+++ b/JavaScriptCore/kjs/lexer.cpp
@@ -0,0 +1,744 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+#include "ustring.h"
+#include "lookup.h"
+#include "internal.h"
+
+// we can't specify the namespace in yacc's C output, so do it here
+using namespace KJS;
+
+#ifndef KDE_USE_FINAL
+#include "grammar.h"
+#endif
+
+#include "lexer.lut.h"
+
+#ifdef KJS_DEBUGGER
+extern YYLTYPE yylloc; // global bison variable holding token info
+#endif
+
+// a bridge for yacc from the C world to C++
+int kjsyylex()
+{
+ return Lexer::curr()->lex();
+}
+
+Lexer::Lexer()
+ : yylineno(0),
+ size8(128), size16(128), restrKeyword(false),
+ stackToken(-1), pos(0),
+ code(0), length(0),
+#ifndef KJS_PURE_ECMA
+ bol(true),
+#endif
+ current(0), next1(0), next2(0), next3(0)
+{
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new UChar[size16];
+
+}
+
+Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+Lexer *Lexer::curr()
+{
+ assert(KJScriptImp::current());
+ return KJScriptImp::current()->lex;
+}
+
+void Lexer::setCode(const UChar *c, unsigned int len)
+{
+ yylineno = 0;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c;
+ length = len;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void Lexer::shift(unsigned int p)
+{
+ while (p--) {
+ pos++;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ unsigned short stringType = 0; // either single or double quotes
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = 0;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ if (!terminator && !delimited) {
+ // automatic semicolon insertion if program incomplete
+ token = ';';
+ stackToken = 0;
+ setDone(Other);
+ } else
+ setDone(Eof);
+ } else if (isLineTerminator()) {
+ yylineno++;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+ terminator = true;
+ if (restrKeyword) {
+ token = ';';
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ state = InString;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ record8(current);
+ state = InDecimal;
+#ifndef KJS_PURE_ECMA
+ // <!-- marks the beginning of a line comment (for www usage)
+ } else if (bol && current == '<' && next1 == '!' &&
+ next2 == '-' && next3 == '-') {
+ shift(3);
+ state = InSingleLineComment;
+ // same of -->
+ } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
+ shift(2);
+ state = InSingleLineComment;
+#endif
+ } else {
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ setDone(Other);
+ } else {
+ // cerr << "encountered unknown character" << endl;
+ setDone(Bad);
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) && isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ record16(singleEscape(current));
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(convertHex(current, next1));
+ shift(1);
+ } else if (current == stringType) {
+ record16('x');
+ shift(1);
+ setDone(String);
+ } else {
+ record16('x');
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16('u');
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ yylineno++;
+ terminator = true;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+ if (restrKeyword) {
+ token = ';';
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ } else if (isLineTerminator()) {
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Hex);
+ }
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else
+ setDone(Octal);
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else
+ setDone(Bad);
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else
+ setDone(Number);
+ break;
+ default:
+ assert(!"Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+#ifndef KJS_PURE_ECMA
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+#endif
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current))
+ state = Bad;
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+#ifdef KJS_DEBUG_LEX
+ fprintf(stderr, "line: %d ", lineNo());
+ fprintf(stderr, "yytext (%x): ", buffer8[0]);
+ fprintf(stderr, "%s ", buffer8);
+#endif
+
+ double dval = 0;
+ if (state == Number) {
+ dval = strtod(buffer8, 0L);
+ } else if (state == Hex) { // scan hex numbers
+ // TODO: support long unsigned int
+ unsigned int i;
+ sscanf(buffer8, "%x", &i);
+ dval = i;
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ unsigned int ui;
+ sscanf(buffer8, "%o", &ui);
+ dval = ui;
+ state = Number;
+ }
+
+#ifdef KJS_DEBUG_LEX
+ switch (state) {
+ case Eof:
+ printf("(EOF)\n");
+ break;
+ case Other:
+ printf("(Other)\n");
+ break;
+ case Identifier:
+ printf("(Identifier)/(Keyword)\n");
+ break;
+ case String:
+ printf("(String)\n");
+ break;
+ case Number:
+ printf("(Number)\n");
+ break;
+ default:
+ printf("(unknown)");
+ }
+#endif
+
+ restrKeyword = false;
+ delimited = false;
+#ifdef KJS_DEBUGGER
+ yylloc.first_line = yylineno; // ???
+ yylloc.last_line = yylineno;
+#endif
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if(token == '}' || token == ';') {
+ delimited = true;
+ }
+ return token;
+ case Identifier:
+ if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ kjsyylval.ustr = new UString(buffer16, pos16);
+ return IDENT;
+ }
+ if (token == CONTINUE || token == BREAK ||
+ token == RETURN || token == THROW)
+ restrKeyword = true;
+ return token;
+ case String:
+ kjsyylval.ustr = new UString(buffer16, pos16); return STRING;
+ case Number:
+ kjsyylval.dval = dval;
+ return NUMBER;
+ case Bad:
+ fprintf(stderr, "yylex: ERROR.\n");
+ return -1;
+ default:
+ assert(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool Lexer::isIdentLetter(unsigned short c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return (c >= 'a' && c <= 'z' ||
+ c >= 'A' && c <= 'Z' ||
+ c == '$' || c == '_');
+}
+
+bool Lexer::isDecimalDigit(unsigned short c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool Lexer::isHexDigit(unsigned short c) const
+{
+ return (c >= '0' && c <= '9' ||
+ c >= 'a' && c <= 'f' ||
+ c >= 'A' && c <= 'F');
+}
+
+bool Lexer::isOctalDigit(unsigned short c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int Lexer::matchPunctuator(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return URSHIFTEQUAL;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STREQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STRNEQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return URSHIFT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return LSHIFTEQUAL;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return RSHIFTEQUAL;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return NE;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ if (terminator) {
+ // automatic semicolon insertion
+ stackToken = PLUSPLUS;
+ return AUTO;
+ } else
+ return PLUSPLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ if (terminator) {
+ // automatic semicolon insertion
+ stackToken = MINUSMINUS;
+ return AUTO;
+ } else
+ return MINUSMINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return EQEQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return PLUSEQUAL;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return MINUSEQUAL;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return MULTEQUAL;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return DIVEQUAL;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return ANDEQUAL;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return XOREQUAL;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return MODEQUAL;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return OREQUAL;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return LSHIFT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return RSHIFT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return OR;
+ }
+
+ switch(c1) {
+ case '=':
+ case '>':
+ case '<':
+ case ',':
+ case '!':
+ case '~':
+ case '?':
+ case ':':
+ case '.':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '&':
+ case '|':
+ case '^':
+ case '%':
+ case '(':
+ case ')':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case ';':
+ shift(1);
+ return static_cast<int>(c1);
+ default:
+ return -1;
+ }
+}
+
+unsigned short Lexer::singleEscape(unsigned short c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+unsigned short Lexer::convertOctal(unsigned short c1, unsigned short c2,
+ unsigned short c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(unsigned short c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(unsigned short c1, unsigned short c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+UChar Lexer::convertUnicode(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4)
+{
+ return UChar((convertHex(c1) << 4) + convertHex(c2),
+ (convertHex(c3) << 4) + convertHex(c4));
+}
+
+void Lexer::record8(unsigned short c)
+{
+ assert(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void Lexer::record16(UChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ UChar *tmp = new UChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(UChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+bool Lexer::scanRegExp()
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ while (1) {
+ if (isLineTerminator() || current == 0)
+ return false;
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape =
+ !lastWasEscape && (current == '\\');
+ }
+ else {
+ pattern = UString(buffer16, pos16);
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ while (isIdentLetter(current)) {
+ record16(current);
+ shift(1);
+ }
+ flags = UString(buffer16, pos16);
+
+ return true;
+}
diff --git a/JavaScriptCore/kjs/lexer.h b/JavaScriptCore/kjs/lexer.h
new file mode 100644
index 0000000..0acc130
--- /dev/null
+++ b/JavaScriptCore/kjs/lexer.h
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJSLEXER_H_
+#define _KJSLEXER_H_
+
+#include "ustring.h"
+
+namespace KJS {
+
+ class RegExp;
+
+ class Lexer {
+ public:
+ Lexer();
+ ~Lexer();
+ static Lexer *curr();
+
+ void setCode(const UChar *c, unsigned int len);
+ int lex();
+
+ int lineNo() const { return yylineno + 1; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ bool scanRegExp();
+ UString pattern, flags;
+
+ private:
+ int yylineno;
+ bool done;
+ char *buffer8;
+ UChar *buffer16;
+ unsigned int size8, size16;
+ unsigned int pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ unsigned int pos;
+ void shift(unsigned int p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(unsigned short c) const;
+ bool isOctalDigit(unsigned short c) const;
+
+ int matchPunctuator(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4);
+ unsigned short singleEscape(unsigned short c) const;
+ unsigned short convertOctal(unsigned short c1, unsigned short c2,
+ unsigned short c3) const;
+ public:
+ static unsigned char convertHex(unsigned short c1);
+ static unsigned char convertHex(unsigned short c1, unsigned short c2);
+ static UChar convertUnicode(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4);
+ static bool isIdentLetter(unsigned short c);
+ static bool isDecimalDigit(unsigned short c);
+
+ private:
+
+ void record8(unsigned short c);
+ void record16(UChar c);
+
+ const UChar *code;
+ unsigned int length;
+ int yycolumn;
+#ifndef KJS_PURE_ECMA
+ int bol; // begin of line
+#endif
+
+ // current and following unicode characters
+ unsigned short current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ // for future extensions
+ class LexerPrivate;
+ LexerPrivate *priv;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/lexer.lut.h b/JavaScriptCore/kjs/lexer.lut.h
new file mode 100644
index 0000000..2ddc9d8
--- /dev/null
+++ b/JavaScriptCore/kjs/lexer.lut.h
@@ -0,0 +1,77 @@
+/* automatically generated from keywords.table. DO NOT EDIT ! */
+
+namespace KJS {
+
+const struct HashEntry2 mainTableEntries[] = {
+ { "instanceof", INSTANCEOF, 0, &mainTableEntries[63] },
+ { "var", VAR, 0, &mainTableEntries[47] },
+ { "case", CASE, 0, &mainTableEntries[41] },
+ { "default", DEFAULT, 0, &mainTableEntries[54] },
+ { "while", WHILE, 0, &mainTableEntries[46] },
+ { 0, 0, 0, 0 },
+ { "do", DO, 0, 0 },
+ { "typeof", TYPEOF, 0, 0 },
+ { "continue", CONTINUE, 0, 0 },
+ { "function", FUNCTION, 0, 0 },
+ { "in", IN, 0, 0 },
+ { "import", RESERVED, 0, 0 },
+ { "delete", DELETE, 0, 0 },
+ { "finally", FINALLY, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "else", ELSE, 0, 0 },
+ { "return", RETURN, 0, 0 },
+ { "debugger", RESERVED, 0, 0 },
+ { "const", RESERVED, 0, &mainTableEntries[48] },
+ { "package", RESERVED, 0, 0 },
+ { "double", RESERVED, 0, &mainTableEntries[53] },
+ { 0, 0, 0, 0 },
+ { "long", RESERVED, 0, 0 },
+ { "catch", CATCH, 0, &mainTableEntries[45] },
+ { "void", VOID, 0, &mainTableEntries[59] },
+ { "break", BREAK, 0, &mainTableEntries[49] },
+ { "byte", RESERVED, 0, &mainTableEntries[62] },
+ { "enum", RESERVED, 0, &mainTableEntries[58] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "this", THIS, 0, &mainTableEntries[50] },
+ { "false", FALSETOKEN, 0, &mainTableEntries[44] },
+ { "abstract", RESERVED, 0, &mainTableEntries[56] },
+ { "null", NULLTOKEN, 0, &mainTableEntries[61] },
+ { "with", WITH, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "true", TRUETOKEN, 0, 0 },
+ { "boolean", RESERVED, 0, 0 },
+ { "for", FOR, 0, 0 },
+ { "new", NEW, 0, &mainTableEntries[42] },
+ { "if", IF, 0, &mainTableEntries[43] },
+ { "switch", SWITCH, 0, &mainTableEntries[55] },
+ { "throw", THROW, 0, &mainTableEntries[52] },
+ { "try", TRY, 0, &mainTableEntries[64] },
+ { "char", RESERVED, 0, 0 },
+ { "class", RESERVED, 0, &mainTableEntries[51] },
+ { "export", RESERVED, 0, 0 },
+ { "extends", RESERVED, 0, &mainTableEntries[57] },
+ { "final", RESERVED, 0, 0 },
+ { "float", RESERVED, 0, 0 },
+ { "goto", RESERVED, 0, 0 },
+ { "implements", RESERVED, 0, 0 },
+ { "int", RESERVED, 0, &mainTableEntries[66] },
+ { "interface", RESERVED, 0, 0 },
+ { "native", RESERVED, 0, 0 },
+ { "private", RESERVED, 0, 0 },
+ { "protected", RESERVED, 0, &mainTableEntries[60] },
+ { "public", RESERVED, 0, 0 },
+ { "short", RESERVED, 0, 0 },
+ { "static", RESERVED, 0, 0 },
+ { "super", RESERVED, 0, 0 },
+ { "synchronized", RESERVED, 0, &mainTableEntries[65] },
+ { "throws", RESERVED, 0, 0 },
+ { "transient", RESERVED, 0, 0 },
+ { "volatile", RESERVED, 0, 0 }
+};
+
+const struct HashTable2 mainTable = { 2, 67, mainTableEntries, 41 };
+
+}; // namespace
diff --git a/JavaScriptCore/kjs/lookup.cpp b/JavaScriptCore/kjs/lookup.cpp
new file mode 100644
index 0000000..fcd3055
--- /dev/null
+++ b/JavaScriptCore/kjs/lookup.cpp
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lookup.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+using namespace KJS;
+
+int Lookup::find(const struct HashTable *table,
+ const UChar *c, unsigned int len)
+{
+ // we only know about version 1 so far
+ if (table->type != 1) {
+ fprintf(stderr, "Unknown hash table version.\n");
+ return -1;
+ }
+
+ int h = hash(c, len) % table->hashSize;
+ const HashEntry *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->c)
+ return -1;
+
+ do {
+ // compare strings
+#ifdef KJS_SWAPPED_CHAR
+ /* TODO: not exactly as optimized as the other version ... */
+ if (len == e->len) {
+ const UChar *u = (const UChar*)e->c;
+ const UChar *c2 = c;
+ unsigned int i;
+ for (i = 0; i < len; i++, u++, c2++)
+ if (!(*c2 == UChar(u->low(), u->high()))) // reverse byte order
+ goto next;
+ return e->value;
+ }
+next:
+#else
+ if ((len == e->len) && (memcmp(c, e->c, len * sizeof(UChar)) == 0))
+ return e->value;
+#endif
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ return -1;
+}
+
+int Lookup::find(const struct HashTable *table, const UString &s)
+{
+ return find(table, s.data(), s.size());
+}
+
+int Lookup::find(const struct HashTable2 *table,
+ const UChar *c, unsigned int len)
+{
+ if (table->type != 2) {
+ fprintf(stderr, "Unknown hash table version.\n");
+ return -1;
+ }
+
+ char *ascii = new char[len+1];
+ unsigned int i;
+ for(i = 0; i < len; i++, c++) {
+ if (!c->high())
+ ascii[i] = c->low();
+ else
+ break;
+ }
+ ascii[i] = '\0';
+
+ int h = hash(ascii) % table->hashSize;
+ const HashEntry2 *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->s) {
+ delete [] ascii;
+ return -1;
+ }
+
+ do {
+ // compare strings
+ if (strcmp(ascii, e->s) == 0) {
+ delete [] ascii;
+ return e->value;
+ }
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ delete [] ascii;
+ return -1;
+}
+
+int Lookup::find(const struct HashTable2 *table, const UString &s)
+{
+ return find(table, s.data(), s.size());
+}
+
+unsigned int Lookup::hash(const UChar *c, unsigned int len)
+{
+ unsigned int val = 0;
+ // ignoring higher byte
+ for (unsigned int i = 0; i < len; i++, c++)
+ val += c->low();
+
+ return val;
+}
+
+unsigned int Lookup::hash(const UString &key)
+{
+ return hash(key.data(), key.size());
+}
+
+unsigned int Lookup::hash(const char *s)
+{
+ unsigned int val = 0;
+ while (*s)
+ val += *s++;
+
+ return val;
+}
diff --git a/JavaScriptCore/kjs/lookup.h b/JavaScriptCore/kjs/lookup.h
new file mode 100644
index 0000000..9301ad6
--- /dev/null
+++ b/JavaScriptCore/kjs/lookup.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSLOOKUP_H_
+#define _KJSLOOKUP_H_
+
+#include "ustring.h"
+
+namespace KJS {
+
+#if 1 // obsolete version 1
+ struct HashEntry {
+ unsigned int len;
+ const void *c; // unicode data
+ int value;
+ const HashEntry *next;
+ };
+
+ struct HashTable {
+ int type;
+ int size;
+ const HashEntry *entries;
+ int hashSize;
+ };
+#endif
+
+ // version 2
+ struct HashEntry2 {
+ const char *s;
+ int value;
+ int attr;
+ const HashEntry2 *next;
+ };
+
+ struct HashTable2 {
+ int type;
+ int size;
+ const HashEntry2 *entries;
+ int hashSize;
+ };
+
+ /**
+ * @short Fast keyword lookup.
+ */
+ class Lookup {
+ public:
+#if 1 // obsolete
+ static int find(const struct HashTable *table, const UString &s);
+ static int find(const struct HashTable *table,
+ const UChar *c, unsigned int len);
+#endif
+ static int find(const struct HashTable2 *table, const UString &s);
+ static int find(const struct HashTable2 *table,
+ const UChar *c, unsigned int len);
+ static unsigned int hash(const UChar *c, unsigned int len);
+ static unsigned int hash(const UString &key);
+ static unsigned int hash(const char *s);
+ private:
+ HashTable *table;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/math_object.cpp b/JavaScriptCore/kjs/math_object.cpp
new file mode 100644
index 0000000..c9ebb79
--- /dev/null
+++ b/JavaScriptCore/kjs/math_object.cpp
@@ -0,0 +1,163 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "operations.h"
+#include "math_object.h"
+#include "lookup.h"
+
+#include "math_object.lut.h"
+
+using namespace KJS;
+
+KJSO Math::get(const UString &p) const
+{
+ int token = Lookup::find(&mathTable, p);
+
+ if (token < 0)
+ return Imp::get(p);
+
+ double d;
+ int len = 1;
+ switch (token) {
+ case Math::Euler:
+ d = exp(1.0);
+ break;
+ case Math::Ln2:
+ d = log(2.0);
+ break;
+ case Math::Ln10:
+ d = log(10.0);
+ break;
+ case Math::Log2E:
+ d = 1.0/log(2.0);
+ break;
+ case Math::Log10E:
+ d = 1.0/log(10.0);
+ break;
+ case Math::Pi:
+ d = 2.0 * asin(1.0);
+ break;
+ case Math::Sqrt1_2:
+ d = sqrt(0.5);
+ break;
+ case Math::Sqrt2:
+ d = sqrt(2.0);
+ break;
+ default:
+ if (token == Math::Min || token == Math::Max || token == Math::Pow)
+ len = 2;
+ return Function(new MathFunc(token, len));
+ };
+
+ return Number(d);
+}
+
+bool Math::hasProperty(const UString &p, bool recursive) const
+{
+ return (Lookup::find(&mathTable, p) >= 0 ||
+ (recursive && Imp::hasProperty(p, recursive)));
+}
+
+Completion MathFunc::execute(const List &args)
+{
+ KJSO v = args[0];
+ Number n = v.toNumber();
+ double arg = n.value();
+
+ KJSO v2 = args[1];
+ Number n2 = v2.toNumber();
+ double arg2 = n2.value();
+ double result;
+
+ switch (id) {
+ case Math::Abs:
+ result = ( arg < 0 ) ? (-arg) : arg;
+ break;
+ case Math::ACos:
+ result = ::acos(arg);
+ break;
+ case Math::ASin:
+ result = ::asin(arg);
+ break;
+ case Math::ATan:
+ result = ::atan(arg);
+ break;
+ case Math::ATan2:
+ result = ::atan2(arg, arg2);
+ break;
+ case Math::Ceil:
+ result = ::ceil(arg);
+ break;
+ case Math::Cos:
+ result = ::cos(arg);
+ break;
+ case Math::Exp:
+ result = ::exp(arg);
+ break;
+ case Math::Floor:
+ result = ::floor(arg);
+ break;
+ case Math::Log:
+ result = ::log(arg);
+ break;
+ case Math::Max:
+ result = ( arg > arg2 ) ? arg : arg2;
+ break;
+ case Math::Min:
+ result = ( arg < arg2 ) ? arg : arg2;
+ break;
+ case Math::Pow:
+ result = ::pow(arg, arg2);
+ break;
+ case Math::Random:
+ result = ::rand();
+ result = result / RAND_MAX;
+ break;
+ case Math::Round:
+ if (isNaN(arg))
+ result = arg;
+ if (isInf(arg) || isInf(-arg))
+ result = arg;
+ else if (arg == -0.5)
+ result = 0;
+ else
+ result = (double)(arg >= 0.0 ? int(arg + 0.5) : int(arg - 0.5));
+ break;
+ case Math::Sin:
+ result = ::sin(arg);
+ break;
+ case Math::Sqrt:
+ result = ::sqrt(arg);
+ break;
+ case Math::Tan:
+ result = ::tan(arg);
+ break;
+
+ default:
+ result = 0.0;
+ assert(0);
+ }
+
+ return Completion(ReturnValue, Number(result));
+}
diff --git a/JavaScriptCore/kjs/math_object.h b/JavaScriptCore/kjs/math_object.h
new file mode 100644
index 0000000..a04cfc1
--- /dev/null
+++ b/JavaScriptCore/kjs/math_object.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MATH_OBJECT_H_
+#define _MATH_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class Math : public ObjectImp {
+ public:
+ Math() : ObjectImp(BooleanClass) { }
+ virtual KJSO get(const UString &p) const;
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2,
+ Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Pow,
+ Exp, Floor, Log, Max, Min, Random, Round, Sin, Sqrt, Tan };
+ };
+
+ class MathFunc : public InternalFunctionImp {
+ public:
+ MathFunc(int i, int l) : InternalFunctionImp(l), id(i) { }
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/math_object.lut.h b/JavaScriptCore/kjs/math_object.lut.h
new file mode 100644
index 0000000..e422d18
--- /dev/null
+++ b/JavaScriptCore/kjs/math_object.lut.h
@@ -0,0 +1,42 @@
+/* automatically generated from math.table. DO NOT EDIT ! */
+
+namespace KJS {
+
+const struct HashEntry2 mathTableEntries[] = {
+ { "atan", Math::ATan, DontEnum|ReadOnly, &mathTableEntries[25] },
+ { 0, 0, 0, 0 },
+ { "SQRT2", Math::Sqrt2, DontEnum|ReadOnly, &mathTableEntries[23] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "E", Math::Euler, DontEnum|ReadOnly, &mathTableEntries[21] },
+ { "asin", Math::ASin, DontEnum|ReadOnly, &mathTableEntries[26] },
+ { "atan2", Math::ATan2, DontEnum|ReadOnly, &mathTableEntries[31] },
+ { "LOG2E", Math::Log2E, DontEnum|ReadOnly, &mathTableEntries[27] },
+ { "cos", Math::Cos, DontEnum|ReadOnly, 0 },
+ { "max", Math::Max, DontEnum|ReadOnly, &mathTableEntries[28] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "LOG10E", Math::Log10E, DontEnum|ReadOnly, &mathTableEntries[24] },
+ { "LN2", Math::Ln2, DontEnum|ReadOnly, &mathTableEntries[30] },
+ { "abs", Math::Abs, DontEnum|ReadOnly, 0 },
+ { "sqrt", Math::Sqrt, DontEnum|ReadOnly, 0 },
+ { "exp", Math::Exp, DontEnum|ReadOnly, 0 },
+ { 0, 0, 0, 0 },
+ { "LN10", Math::Ln10, DontEnum|ReadOnly, &mathTableEntries[22] },
+ { "PI", Math::Pi, DontEnum|ReadOnly, &mathTableEntries[29] },
+ { "SQRT1_2", Math::Sqrt1_2, DontEnum|ReadOnly, 0 },
+ { "acos", Math::ACos, DontEnum|ReadOnly, 0 },
+ { "ceil", Math::Ceil, DontEnum|ReadOnly, 0 },
+ { "floor", Math::Floor, DontEnum|ReadOnly, 0 },
+ { "log", Math::Log, DontEnum|ReadOnly, 0 },
+ { "min", Math::Min, DontEnum|ReadOnly, 0 },
+ { "random", Math::Random, DontEnum|ReadOnly, 0 },
+ { "round", Math::Round, DontEnum|ReadOnly, 0 },
+ { "sin", Math::Sin, DontEnum|ReadOnly, 0 },
+ { "tan", Math::Tan, DontEnum|ReadOnly, 0 }
+};
+
+const struct HashTable2 mathTable = { 2, 32, mathTableEntries, 21 };
+
+}; // namespace
diff --git a/JavaScriptCore/kjs/nodes.cpp b/JavaScriptCore/kjs/nodes.cpp
new file mode 100644
index 0000000..ab20d3b
--- /dev/null
+++ b/JavaScriptCore/kjs/nodes.cpp
@@ -0,0 +1,1487 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "nodes.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "kjs.h"
+#include "ustring.h"
+#include "lexer.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "regexp_object.h"
+#include "debugger.h"
+
+using namespace KJS;
+
+#ifdef KJS_DEBUGGER
+#define KJS_BREAKPOINT if (!hitStatement()) return Completion(Normal);
+#define KJS_ABORTPOINT if (abortStatement()) return Completion(Normal);
+#else
+#define KJS_BREAKPOINT
+#define KJS_ABORTPOINT
+#endif
+
+int Node::nodeCount = 0;
+Node* Node::first = 0;
+
+Node::Node()
+{
+ assert(Lexer::curr());
+ line = Lexer::curr()->lineNo();
+ nodeCount++;
+ // cout << "Node()" << endl;
+
+ // create a list of allocated objects. Makes
+ // deleting (even after a parse error) quite easy
+ next = first;
+ prev = 0L;
+ if (first)
+ first->prev = this;
+ first = this;
+}
+
+Node::~Node()
+{
+ // cout << "~Node()" << endl;
+ if (next)
+ next->prev = prev;
+ if (prev)
+ prev->next = next;
+ nodeCount--;
+}
+
+void Node::deleteAllNodes()
+{
+ Node *tmp, *n = first;
+
+ while ((tmp = n)) {
+ n = n->next;
+ delete tmp;
+ }
+ first = 0L;
+ // assert(nodeCount == 0);
+}
+
+KJSO Node::throwError(ErrorType e, const char *msg)
+{
+ return Error::create(e, msg, lineNo());
+}
+
+#ifdef KJS_DEBUGGER
+void StatementNode::setLoc(int line0, int line1)
+{
+ l0 = line0;
+ l1 = line1;
+ sid = KJScriptImp::current()->sourceId();
+}
+
+bool StatementNode::hitStatement()
+{
+ if (KJScriptImp::current()->debugger())
+ return KJScriptImp::current()->debugger()->hit(firstLine(), breakPoint);
+ else
+ return true;
+}
+
+// return true if the debugger wants us to stop at this point
+bool StatementNode::abortStatement()
+{
+ if (KJScriptImp::current()->debugger() &&
+ KJScriptImp::current()->debugger()->mode() == Debugger::Stop)
+ return true;
+
+ return false;
+}
+
+bool Node::setBreakpoint(Node *firstNode, int id, int line, bool set)
+{
+ while (firstNode) {
+ if (firstNode->setBreakpoint(id, line, set) && line >= 0) // line<0 for all
+ return true;
+ firstNode = firstNode->next;
+ }
+ return false;
+}
+
+/**
+ * Try to set or delete a breakpoint depending on the value of set.
+ * The call will return true if successful, i.e. if line is inside
+ * of the statement's range. Additionally, a breakpoint had to
+ * be set already if you tried to delete with set=false.
+ */
+bool StatementNode::setBreakpoint(int id, int line, bool set)
+{
+ // in our source unit and line range ?
+ if (id != sid || ((line < l0 || line > l1) && line >= 0))
+ return false;
+
+ if (!set && !breakPoint)
+ return false;
+
+ breakPoint = set;
+ return true;
+}
+#endif
+
+KJSO NullNode::evaluate()
+{
+ return Null();
+}
+
+KJSO BooleanNode::evaluate()
+{
+ return Boolean(value);
+}
+
+KJSO NumberNode::evaluate()
+{
+ return Number(value);
+}
+
+KJSO StringNode::evaluate()
+{
+ return String(value);
+}
+
+KJSO RegExpNode::evaluate()
+{
+ List list;
+ String p(pattern);
+ String f(flags);
+ list.append(p);
+ list.append(f);
+
+ // very ugly
+ KJSO r = Global::current().get("RegExp");
+ RegExpObject *r2 = (RegExpObject*)r.imp();
+ return r2->construct(list);
+}
+
+// ECMA 11.1.1
+KJSO ThisNode::evaluate()
+{
+ return Context::current()->thisValue();
+}
+
+// ECMA 11.1.2 & 10.1.4
+KJSO ResolveNode::evaluate()
+{
+ assert(Context::current());
+ const List *chain = Context::current()->pScopeChain();
+ assert(chain);
+ ListIterator scope = chain->begin();
+
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+// cout << "Resolve: found '" << ident.ascii() << "'"
+// << " type " << scope->get(ident).imp()->typeInfo()->name << endl;
+ return Reference(*scope, ident);
+ }
+ scope++;
+ }
+
+ // identifier not found
+// cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
+ return Reference(Null(), ident);
+}
+
+// ECMA 11.1.4
+KJSO ArrayNode::evaluate()
+{
+ KJSO array;
+ int length;
+ int elisionLen = elision ? elision->evaluate().toInt32() : 0;
+
+ if (element) {
+ array = element->evaluate();
+ length = opt ? array.get("length").toInt32() : 0;
+ } else {
+ array = Object::create(ArrayClass);
+ length = 0;
+ }
+
+ if (opt)
+ array.put("length", Number(elisionLen + length), DontEnum | DontDelete);
+
+ return array;
+}
+
+// ECMA 11.1.4
+KJSO ElementNode::evaluate()
+{
+ KJSO array, val;
+ int length = 0;
+ int elisionLen = elision ? elision->evaluate().toInt32() : 0;
+
+ if (list) {
+ array = list->evaluate();
+ val = node->evaluate().getValue();
+ length = array.get("length").toInt32();
+ } else {
+ array = Object::create(ArrayClass);
+ val = node->evaluate().getValue();
+ }
+
+ array.putArrayElement(UString::from(elisionLen + length), val);
+
+ return array;
+}
+
+// ECMA 11.1.4
+KJSO ElisionNode::evaluate()
+{
+ if (elision)
+ return Number(elision->evaluate().toNumber().value() + 1);
+ else
+ return Number(1);
+}
+
+// ECMA 11.1.5
+KJSO ObjectLiteralNode::evaluate()
+{
+ if (list)
+ return list->evaluate();
+
+ return Object::create(ObjectClass);
+}
+
+// ECMA 11.1.5
+KJSO PropertyValueNode::evaluate()
+{
+ KJSO obj;
+ if (list)
+ obj = list->evaluate();
+ else
+ obj = Object::create(ObjectClass);
+ KJSO n = name->evaluate();
+ KJSO a = assign->evaluate();
+ KJSO v = a.getValue();
+
+ obj.put(n.toString().value(), v);
+
+ return obj;
+}
+
+// ECMA 11.1.5
+KJSO PropertyNode::evaluate()
+{
+ KJSO s;
+
+ if (str.isNull()) {
+ s = String(UString::from(numeric));
+ } else
+ s = String(str);
+
+ return s;
+}
+
+// ECMA 11.1.6
+KJSO GroupNode::evaluate()
+{
+ return group->evaluate();
+}
+
+// ECMA 11.2.1a
+KJSO AccessorNode1::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+ Object o = v1.toObject();
+ String s = v2.toString();
+ return Reference(o, s.value());
+}
+
+// ECMA 11.2.1b
+KJSO AccessorNode2::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ KJSO o = v.toObject();
+ return Reference(o, ident);
+}
+
+// ECMA 11.2.2
+KJSO NewExprNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ List *argList = args ? args->evaluateList() : 0;
+
+ if (!v.isObject()) {
+ delete argList;
+ return throwError(TypeError, "Expression is no object. Cannot be new'ed");
+ }
+
+ Constructor constr = Constructor::dynamicCast(v);
+ if (constr.isNull()) {
+ delete argList;
+ return throwError(TypeError, "Expression is no constructor.");
+ }
+
+ if (!argList)
+ argList = new List;
+
+ KJSO res = constr.construct(*argList);
+
+ delete argList;
+
+ return res;
+}
+
+// ECMA 11.2.3
+KJSO FunctionCallNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+
+ List *argList = args->evaluateList();
+
+ KJSO v = e.getValue();
+
+ if (!v.isObject()) {
+#ifndef NDEBUG
+ printInfo("Failed function call attempt on", e);
+#endif
+ delete argList;
+ return throwError(TypeError, "Expression is no object. Cannot be called.");
+ }
+
+ if (!v.implementsCall()) {
+#ifndef NDEBUG
+ printInfo("Failed function call attempt on", e);
+#endif
+ delete argList;
+ return throwError(TypeError, "Expression does not allow calls.");
+ }
+
+ KJSO o;
+ if (e.isA(ReferenceType))
+ o = e.getBase();
+ else
+ o = Null();
+
+ if (o.isA(ActivationType))
+ o = Null();
+
+#ifdef KJS_DEBUGGER
+ steppingInto(true);
+#endif
+
+ KJSO result = v.executeCall(o, argList);
+
+#ifdef KJS_DEBUGGER
+ steppingInto(false);
+#endif
+
+ delete argList;
+
+ return result;
+}
+
+#ifdef KJS_DEBUGGER
+void FunctionCallNode::steppingInto(bool in)
+{
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ if (!dbg)
+ return;
+ if (in) {
+ // before entering function. Don't step inside if 'Next' is chosen.
+ previousMode = dbg->mode();
+ if (previousMode == Debugger::Next)
+ dbg->setMode(Debugger::Continue);
+ } else {
+ // restore mode after leaving function
+ dbg->setMode(previousMode);
+ }
+}
+#endif
+
+KJSO ArgumentsNode::evaluate()
+{
+ assert(0);
+ return KJSO(); // dummy, see evaluateList()
+}
+
+// ECMA 11.2.4
+List* ArgumentsNode::evaluateList()
+{
+ if (!list)
+ return new List();
+
+ return list->evaluateList();
+}
+
+KJSO ArgumentListNode::evaluate()
+{
+ assert(0);
+ return KJSO(); // dummy, see evaluateList()
+}
+
+// ECMA 11.2.4
+List* ArgumentListNode::evaluateList()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ if (!list) {
+ List *l = new List();
+ l->append(v);
+ return l;
+ }
+
+ List *l = list->evaluateList();
+ l->append(v);
+
+ return l;
+}
+
+// ECMA 11.8
+KJSO RelationalNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+
+ bool b;
+ if (oper == OpLess || oper == OpGreaterEq) {
+ int r = relation(v1, v2);
+ if (r < 0)
+ b = false;
+ else
+ b = (oper == OpLess) ? (r == 1) : (r == 0);
+ } else if (oper == OpGreater || oper == OpLessEq) {
+ int r = relation(v2, v1);
+ if (r < 0)
+ b = false;
+ else
+ b = (oper == OpGreater) ? (r == 1) : (r == 0);
+ } else if (oper == OpIn) {
+ /* Is all of this OK for host objects? */
+ if (!v2.isObject())
+ return throwError( TypeError,
+ "Shift expression not an object into IN expression." );
+ b = v2.hasProperty(v1.toString().value());
+ } else {
+ /* TODO: should apply to Function _objects_ only */
+ if (!v2.derivedFrom("Function"))
+ return throwError(TypeError,
+ "Called instanceof operator on non-function object." );
+ return hasInstance(v2, v1); /* TODO: make object member function */
+ }
+
+ return Boolean(b);
+}
+
+// ECMA 11.9
+KJSO EqualNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO e2 = expr2->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO v2 = e2.getValue();
+
+ bool result;
+ if (oper == OpEqEq || oper == OpNotEq) {
+ // == and !=
+ bool eq = equal(v1, v2);
+ result = oper == OpEqEq ? eq : !eq;
+ } else {
+ // === and !==
+ bool eq = strictEqual(v1, v2);
+ result = oper == OpStrEq ? eq : !eq;
+ }
+ return Boolean(result);
+}
+
+// ECMA 11.10
+KJSO BitOperNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+ int i1 = v1.toInt32();
+ int i2 = v2.toInt32();
+ int result;
+ if (oper == OpBitAnd)
+ result = i1 & i2;
+ else if (oper == OpBitXOr)
+ result = i1 ^ i2;
+ else
+ result = i1 | i2;
+
+ return Number(result);
+}
+
+// ECMA 11.11
+KJSO BinaryLogicalNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ Boolean b1 = v1.toBoolean();
+ if ((!b1.value() && oper == OpAnd) || (b1.value() && oper == OpOr))
+ return v1;
+
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+
+ return v2;
+}
+
+// ECMA 11.12
+KJSO ConditionalNode::evaluate()
+{
+ KJSO e = logical->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ if (b.value())
+ e = expr1->evaluate();
+ else
+ e = expr2->evaluate();
+
+ return e.getValue();
+}
+
+// ECMA 11.13
+KJSO AssignNode::evaluate()
+{
+ KJSO l, e, v;
+ ErrorType err;
+ if (oper == OpEqual) {
+ l = left->evaluate();
+ e = expr->evaluate();
+ v = e.getValue();
+ } else {
+ l = left->evaluate();
+ KJSO v1 = l.getValue();
+ e = expr->evaluate();
+ KJSO v2 = e.getValue();
+ int i1 = v1.toInt32();
+ int i2 = v2.toInt32();
+ switch (oper) {
+ case OpMultEq:
+ v = mult(v1, v2, '*');
+ break;
+ case OpDivEq:
+ v = mult(v1, v2, '/');
+ break;
+ case OpPlusEq:
+ v = add(v1, v2, '+');
+ break;
+ case OpMinusEq:
+ v = add(v1, v2, '-');
+ break;
+ case OpLShift:
+ v = Number(i1 <<= i2);
+ break;
+ case OpRShift:
+ v = Number(i1 >>= i2);
+ break;
+ case OpURShift:
+ i1 = v1.toUInt32();
+ v = Number(i1 >>= i2);
+ break;
+ case OpAndEq:
+ v = Number(i1 &= i2);
+ break;
+ case OpXOrEq:
+ v = Number(i1 ^= i2);
+ break;
+ case OpOrEq:
+ v = Number(i1 |= i2);
+ break;
+ case OpModEq:
+ v = Number(i1 %= i2);
+ break;
+ default:
+ v = Undefined();
+ }
+ err = l.putValue(v);
+ };
+
+ err = l.putValue(v);
+ if (err == NoError)
+ return v;
+ else
+ return throwError(err, "Invalid reference.");
+}
+
+// ECMA 11.3
+KJSO PostfixNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
+ KJSO n2 = Number(newValue);
+
+ e.putValue(n2);
+
+ return n;
+}
+
+// ECMA 11.4.1
+KJSO DeleteNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ if (!e.isA(ReferenceType))
+ return Boolean(true);
+ KJSO b = e.getBase();
+ UString n = e.getPropertyName();
+ bool ret = b.deleteProperty(n);
+
+ return Boolean(ret);
+}
+
+// ECMA 11.4.2
+KJSO VoidNode::evaluate()
+{
+ KJSO dummy1 = expr->evaluate();
+ KJSO dummy2 = dummy1.getValue();
+
+ return Undefined();
+}
+
+// ECMA 11.4.3
+KJSO TypeOfNode::evaluate()
+{
+ const char *s = 0L;
+ KJSO e = expr->evaluate();
+ if (e.isA(ReferenceType)) {
+ KJSO b = e.getBase();
+ if (b.isA(NullType))
+ return String("undefined");
+ }
+ KJSO v = e.getValue();
+ switch (v.type())
+ {
+ case UndefinedType:
+ s = "undefined";
+ break;
+ case NullType:
+ s = "object";
+ break;
+ case BooleanType:
+ s = "boolean";
+ break;
+ case NumberType:
+ s = "number";
+ break;
+ case StringType:
+ s = "string";
+ break;
+ default:
+ if (v.implementsCall())
+ s = "function";
+ else
+ s = "object";
+ break;
+ }
+
+ return String(s);
+}
+
+// ECMA 11.4.4 and 11.4.5
+KJSO PrefixNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
+ KJSO n2 = Number(newValue);
+
+ e.putValue(n2);
+
+ return n2;
+}
+
+// ECMA 11.4.6
+KJSO UnaryPlusNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return v.toNumber();
+}
+
+// ECMA 11.4.7
+KJSO NegateNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double d = -n.value();
+
+ return Number(d);
+}
+
+// ECMA 11.4.8
+KJSO BitwiseNotNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ int i32 = v.toInt32();
+
+ return Number(~i32);
+}
+
+// ECMA 11.4.9
+KJSO LogicalNotNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ return Boolean(!b.value());
+}
+
+// ECMA 11.5
+KJSO MultNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+
+ return mult(v1, v2, oper);
+}
+
+// ECMA 11.7
+KJSO ShiftNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+ unsigned int i2 = v2.toUInt32();
+ i2 &= 0x1f;
+
+ long result;
+ switch (oper) {
+ case OpLShift:
+ result = v1.toInt32() << i2;
+ break;
+ case OpRShift:
+ result = v1.toInt32() >> i2;
+ break;
+ case OpURShift:
+ result = v1.toUInt32() >> i2;
+ break;
+ default:
+ assert(!"ShiftNode: unhandled switch case");
+ result = 0L;
+ }
+
+ return Number(static_cast<double>(result));
+}
+
+// ECMA 11.6
+KJSO AddNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+
+ return add(v1, v2, oper);
+}
+
+// ECMA 11.14
+KJSO CommaNode::evaluate()
+{
+ KJSO e = expr1->evaluate();
+ KJSO dummy = e.getValue(); // ignore return value
+ e = expr2->evaluate();
+
+ return e.getValue();
+}
+
+// ECMA 12.1
+Completion BlockNode::execute()
+{
+ if (!statlist)
+ return Completion(Normal);
+
+ return statlist->execute();
+}
+
+// ECMA 12.1
+Completion StatListNode::execute()
+{
+ if (!list) {
+ Completion c = statement->execute();
+ KJS_ABORTPOINT
+ if (KJScriptImp::hadException()) {
+ KJSO ex = KJScriptImp::exception();
+ KJScriptImp::clearException();
+ return Completion(Throw, ex);
+ } else
+ return c;
+ }
+
+ Completion l = list->execute();
+ KJS_ABORTPOINT
+ if (l.complType() != Normal)
+ return l;
+ Completion e = statement->execute();
+ KJS_ABORTPOINT;
+ if (KJScriptImp::hadException()) {
+ KJSO ex = KJScriptImp::exception();
+ KJScriptImp::clearException();
+ return Completion(Throw, ex);
+ }
+
+ KJSO v = e.isValueCompletion() ? e.value() : l.value();
+
+ return Completion(e.complType(), v, e.target() );
+}
+
+// ECMA 12.2
+Completion VarStatementNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ (void) list->evaluate(); // returns 0L
+
+ return Completion(Normal);
+}
+
+// ECMA 12.2
+KJSO VarDeclNode::evaluate()
+{
+ KJSO variable = Context::current()->variableObject();
+
+ KJSO val, tmp;
+ if (init) {
+ tmp = init->evaluate();
+ val = tmp.getValue();
+ } else {
+ if ( variable.hasProperty( ident ) ) // already declared ?
+ return KJSO();
+ val = Undefined();
+ }
+ variable.put(ident, val, DontDelete);
+
+ // spec wants to return ident. But what for ? Will be ignored above.
+ return KJSO();
+}
+
+// ECMA 12.2
+KJSO VarDeclListNode::evaluate()
+{
+ if (list)
+ (void) list->evaluate();
+
+ (void) var->evaluate();
+
+ return KJSO();
+}
+
+// ECMA 12.2
+KJSO AssignExprNode::evaluate()
+{
+ return expr->evaluate();
+}
+
+// ECMA 12.3
+Completion EmptyStatementNode::execute()
+{
+ return Completion(Normal);
+}
+
+// ECMA 12.6.3
+Completion ForNode::execute()
+{
+ KJSO e, v, cval;
+ Boolean b;
+
+ if (expr1) {
+ e = expr1->evaluate();
+ v = e.getValue();
+ }
+ while (1) {
+ if (expr2) {
+ e = expr2->evaluate();
+ v = e.getValue();
+ b = v.toBoolean();
+ if (b.value() == false)
+ return Completion(Normal, cval);
+ }
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ Completion c = stat->execute();
+ if (c.isValueCompletion())
+ cval = c.value();
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, cval);
+ if (c.complType() != Normal)
+ return c;
+ }
+ if (expr3) {
+ e = expr3->evaluate();
+ v = e.getValue();
+ }
+ }
+}
+
+// ECMA 12.6.4
+Completion ForInNode::execute()
+{
+ KJSO e, v, retval;
+ Completion c;
+ VarDeclNode *vd = 0;
+ const PropList *lst, *curr;
+
+ // This should be done in the constructor
+ if (!lexpr) { // for( var foo = bar in baz )
+ vd = new VarDeclNode(&ident, init);
+ vd->evaluate();
+
+ lexpr = new ResolveNode(&ident);
+ }
+
+ e = expr->evaluate();
+ v = e.getValue().toObject();
+ curr = lst = v.imp()->propList();
+
+ while (curr) {
+ if (!v.hasProperty(curr->name)) {
+ curr = curr->next;
+ continue;
+ }
+
+ e = lexpr->evaluate();
+ e.putValue(String(curr->name));
+
+ c = stat->execute();
+ if (c.isValueCompletion())
+ retval = c.value();
+
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ break;
+ if (c.complType() != Normal) {
+ delete lst;
+ return c;
+ }
+ }
+
+ curr = curr->next;
+ }
+
+ delete lst;
+ return Completion(Normal, retval);
+}
+
+// ECMA 12.4
+Completion ExprStatementNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return Completion(Normal, v);
+}
+
+// ECMA 12.5
+Completion IfNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ // if ... then
+ if (b.value())
+ return statement1->execute();
+
+ // no else
+ if (!statement2)
+ return Completion(Normal);
+
+ // else
+ return statement2->execute();
+}
+
+// ECMA 12.6.1
+Completion DoWhileNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO be, bv;
+ Completion c;
+ KJSO value;
+
+ do {
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ c = statement->execute();
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, value);
+ if (c.complType() != Normal)
+ return c;
+ }
+ be = expr->evaluate();
+ bv = be.getValue();
+ } while (bv.toBoolean().value());
+
+ return Completion(Normal, value);
+}
+
+// ECMA 12.6.2
+Completion WhileNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO be, bv;
+ Completion c;
+ Boolean b(false);
+ KJSO value;
+
+ while (1) {
+ be = expr->evaluate();
+ bv = be.getValue();
+ b = bv.toBoolean();
+
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ if (!b.value())
+ return Completion(Normal, value);
+
+ c = statement->execute();
+ if (c.isValueCompletion())
+ value = c.value();
+
+ if ((c.complType() == Continue) && ls.contains(c.target()))
+ continue;
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, value);
+ if (c.complType() != Normal)
+ return c;
+ }
+}
+
+// ECMA 12.7
+Completion ContinueNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO dummy;
+ return Context::current()->seenLabels()->contains(ident) ?
+ Completion(Continue, dummy, ident) :
+ Completion(Throw,
+ throwError(SyntaxError, "Label not found in containing block"));
+}
+
+// ECMA 12.8
+Completion BreakNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO dummy;
+ return Context::current()->seenLabels()->contains(ident) ?
+ Completion(Break, dummy, ident) :
+ Completion(Throw,
+ throwError(SyntaxError, "Label not found in containing block"));
+}
+
+// ECMA 12.9
+Completion ReturnNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ if (!value)
+ return Completion(ReturnValue, Undefined());
+
+ KJSO e = value->evaluate();
+ KJSO v = e.getValue();
+
+ return Completion(ReturnValue, v);
+}
+
+// ECMA 12.10
+Completion WithNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Object o = v.toObject();
+ Context::current()->pushScope(o);
+ Completion res = stat->execute();
+ Context::current()->popScope();
+
+ return res;
+}
+
+// ECMA 12.11
+ClauseListNode* ClauseListNode::append(CaseClauseNode *c)
+{
+ ClauseListNode *l = this;
+ while (l->nx)
+ l = l->nx;
+ l->nx = new ClauseListNode(c);
+
+ return this;
+}
+
+// ECMA 12.11
+Completion SwitchNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Completion res = block->evalBlock(v);
+
+ if ((res.complType() == Break) && ls.contains(res.target()))
+ return Completion(Normal, res.value());
+ else
+ return res;
+}
+
+// ECMA 12.11
+Completion CaseBlockNode::evalBlock(const KJSO& input)
+{
+ KJSO v;
+ Completion res;
+ ClauseListNode *a = list1, *b = list2;
+ CaseClauseNode *clause;
+
+ if (a) {
+ while (a) {
+ clause = a->clause();
+ a = a->next();
+ v = clause->evaluate();
+ if (strictEqual(input, v)) {
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ while (a) {
+ res = a->clause()->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ a = a->next();
+ }
+ break;
+ }
+ }
+ }
+
+ while (b) {
+ clause = b->clause();
+ b = b->next();
+ v = clause->evaluate();
+ if (strictEqual(input, v)) {
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ goto step18;
+ }
+ }
+
+ // default clause
+ if (def) {
+ res = def->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ }
+ b = list2;
+ step18:
+ while (b) {
+ clause = b->clause();
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ b = b->next();
+ }
+
+ return Completion(Normal);
+}
+
+// ECMA 12.11
+KJSO CaseClauseNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return v;
+}
+
+// ECMA 12.11
+Completion CaseClauseNode::evalStatements()
+{
+ if (list)
+ return list->execute();
+ else
+ return Completion(Normal, Undefined());
+}
+
+// ECMA 12.12
+Completion LabelNode::execute()
+{
+ Completion e;
+
+ if (!Context::current()->seenLabels()->push(label)) {
+ return Completion( Throw,
+ throwError(SyntaxError, "Duplicated label found" ));
+ };
+ e = stat->execute();
+ Context::current()->seenLabels()->pop();
+
+ if ((e.complType() == Break) && (e.target() == label))
+ return Completion(Normal, e.value());
+ else
+ return e;
+}
+
+// ECMA 12.13
+Completion ThrowNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO v = expr->evaluate().getValue();
+
+ return Completion(Throw, v);
+}
+
+// ECMA 12.14
+Completion TryNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ Completion c, c2;
+
+ c = block->execute();
+
+ if (!_final) {
+ if (c.complType() != Throw)
+ return c;
+ return _catch->execute(c.value());
+ }
+
+ if (!_catch) {
+ c2 = _final->execute();
+ return (c2.complType() == Normal) ? c : c2;
+ }
+
+ if (c.complType() == Throw)
+ c = _catch->execute(c.value());
+
+ c2 = _final->execute();
+ return (c2.complType() == Normal) ? c : c2;
+}
+
+Completion CatchNode::execute()
+{
+ // should never be reached. execute(const KJS &arg) is used instead
+ assert(0L);
+ return Completion();
+}
+
+// ECMA 12.14
+Completion CatchNode::execute(const KJSO &arg)
+{
+ /* TODO: correct ? Not part of the spec */
+ KJScriptImp::clearException();
+
+ Object obj;
+ obj.put(ident, arg, DontDelete);
+ Context::current()->pushScope(obj);
+ Completion c = block->execute();
+ Context::current()->popScope();
+
+ return c;
+}
+
+// ECMA 12.14
+Completion FinallyNode::execute()
+{
+ return block->execute();
+}
+
+FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
+ : source(s)
+{
+#ifdef KJS_DEBUGGER
+ setLoc(-1, -1);
+#endif
+}
+
+// ECMA 13 + 14 for ProgramNode
+Completion FunctionBodyNode::execute()
+{
+ /* TODO: workaround for empty body which I don't see covered by the spec */
+ if (!source)
+ return Completion(ReturnValue, Undefined());
+
+ source->processFuncDecl();
+
+ return source->execute();
+}
+
+// ECMA 13
+void FuncDeclNode::processFuncDecl()
+{
+ const List *sc = Context::current()->pScopeChain();
+ /* TODO: let this be an object with [[Class]] property "Function" */
+ FunctionImp *fimp = new DeclaredFunctionImp(ident, body, sc);
+ Function func(fimp); // protect from GC
+ fimp->put("prototype", Object::create(ObjectClass), DontDelete);
+
+ int plen = 0;
+ for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
+ fimp->addParameter(p->ident());
+
+ fimp->setLength(plen);
+
+ Context::current()->variableObject().put(ident, func);
+}
+
+// ECMA 13
+KJSO FuncExprNode::evaluate()
+{
+ const List *sc = Context::current()->pScopeChain();
+ FunctionImp *fimp = new DeclaredFunctionImp(UString::null, body, sc->copy());
+ Function ret(fimp);
+
+ int plen = 0;
+ for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
+ fimp->addParameter(p->ident());
+ fimp->setLength(plen);
+
+ return ret;
+}
+
+ParameterNode* ParameterNode::append(const UString *i)
+{
+ ParameterNode *p = this;
+ while (p->next)
+ p = p->next;
+
+ p->next = new ParameterNode(i);
+
+ return this;
+}
+
+// ECMA 13
+KJSO ParameterNode::evaluate()
+{
+ return Undefined();
+}
+
+void ProgramNode::deleteGlobalStatements()
+{
+ source->deleteStatements();
+}
+
+// ECMA 14
+Completion SourceElementsNode::execute()
+{
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ if (!elements)
+ return element->execute();
+
+ Completion c1 = elements->execute();
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+ if (c1.complType() != Normal)
+ return c1;
+
+ Completion c2 = element->execute();
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ return c2;
+}
+
+// ECMA 14
+void SourceElementsNode::processFuncDecl()
+{
+ if (elements)
+ elements->processFuncDecl();
+
+ element->processFuncDecl();
+}
+
+void SourceElementsNode::deleteStatements()
+{
+ element->deleteStatements();
+
+ if (elements)
+ elements->deleteStatements();
+}
+
+// ECMA 14
+Completion SourceElementNode::execute()
+{
+ if (statement)
+ return statement->execute();
+
+ return Completion(Normal);
+}
+
+// ECMA 14
+void SourceElementNode::processFuncDecl()
+{
+ if (function)
+ function->processFuncDecl();
+}
+
+void SourceElementNode::deleteStatements()
+{
+ delete statement;
+}
+
+ArgumentListNode::ArgumentListNode(Node *e) : list(0L), expr(e) {}
+
+VarDeclNode::VarDeclNode(const UString *id, AssignExprNode *in)
+ : ident(*id), init(in) { }
+
+ArgumentListNode::ArgumentListNode(ArgumentListNode *l, Node *e) :
+ list(l), expr(e) {}
+
+ArgumentsNode::ArgumentsNode(ArgumentListNode *l) : list(l) {}
diff --git a/JavaScriptCore/kjs/nodes.h b/JavaScriptCore/kjs/nodes.h
new file mode 100644
index 0000000..223109a
--- /dev/null
+++ b/JavaScriptCore/kjs/nodes.h
@@ -0,0 +1,789 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _NODES_H_
+#define _NODES_H_
+
+#include "internal.h"
+#include "ustring.h"
+#include "object.h"
+#include "types.h"
+#include "debugger.h"
+
+namespace KJS {
+
+ class KJSO;
+ class RegExp;
+ class SourceElementsNode;
+ class ProgramNode;
+
+ enum Operator { OpEqual,
+ OpEqEq,
+ OpNotEq,
+ OpStrEq,
+ OpStrNEq,
+ OpPlusEq,
+ OpMinusEq,
+ OpMultEq,
+ OpDivEq,
+ OpPlusPlus,
+ OpMinusMinus,
+ OpLess,
+ OpLessEq,
+ OpGreater,
+ OpGreaterEq,
+ OpAndEq,
+ OpXOrEq,
+ OpOrEq,
+ OpModEq,
+ OpAnd,
+ OpOr,
+ OpBitAnd,
+ OpBitXOr,
+ OpBitOr,
+ OpLShift,
+ OpRShift,
+ OpURShift,
+ OpIn,
+ OpInstanceOf
+ };
+
+ class Node {
+ public:
+ Node();
+ virtual ~Node();
+ virtual KJSO evaluate() = 0;
+ int lineNo() const { return line; }
+ static Node *firstNode() { return first; }
+ static void setFirstNode(Node *n) { first = n; }
+ static void deleteAllNodes();
+#ifdef KJS_DEBUGGER
+ static bool setBreakpoint(Node *firstNode, int id, int line, bool set);
+ virtual bool setBreakpoint(int, int, bool) { return false; }
+#endif
+ protected:
+ KJSO throwError(ErrorType e, const char *msg);
+ private:
+ // disallow assignment and copy-construction
+ Node(const Node &);
+ Node& operator=(const Node&);
+ int line;
+ static int nodeCount;
+ static Node *first;
+ Node *next, *prev;
+ };
+
+ class StatementNode : public Node {
+ public:
+#ifdef KJS_DEBUGGER
+ StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false) { }
+ void setLoc(int line0, int line1);
+ int firstLine() const { return l0; }
+ int lastLine() const { return l1; }
+ int sourceId() const { return sid; }
+ bool hitStatement();
+ bool abortStatement();
+ virtual bool setBreakpoint(int id, int line, bool set);
+#endif
+ virtual Completion execute() = 0;
+ void pushLabel(const UString *id) {
+ if (id) ls.push(*id);
+ }
+ protected:
+ LabelStack ls;
+ private:
+ KJSO evaluate() { return Undefined(); }
+#ifdef KJS_DEBUGGER
+ int l0, l1;
+ int sid;
+ bool breakPoint;
+#endif
+ };
+
+ class NullNode : public Node {
+ public:
+ KJSO evaluate();
+ };
+
+ class BooleanNode : public Node {
+ public:
+ BooleanNode(bool v) : value(v) {}
+ KJSO evaluate();
+ private:
+ bool value;
+ };
+
+ class NumberNode : public Node {
+ public:
+ NumberNode(double v) : value(v) { }
+ KJSO evaluate();
+ private:
+ double value;
+ };
+
+ class StringNode : public Node {
+ public:
+ StringNode(const UString *v) { value = *v; }
+ KJSO evaluate();
+ private:
+ UString value;
+ };
+
+ class RegExpNode : public Node {
+ public:
+ RegExpNode(const UString &p, const UString &f)
+ : pattern(p), flags(f) { }
+ KJSO evaluate();
+ private:
+ UString pattern, flags;
+ };
+
+ class ThisNode : public Node {
+ public:
+ KJSO evaluate();
+ };
+
+ class ResolveNode : public Node {
+ public:
+ ResolveNode(const UString *s) : ident(*s) { }
+ KJSO evaluate();
+ private:
+ UString ident;
+ };
+
+ class GroupNode : public Node {
+ public:
+ GroupNode(Node *g) : group(g) { }
+ KJSO evaluate();
+ private:
+ Node *group;
+ };
+
+ class ElisionNode : public Node {
+ public:
+ ElisionNode(ElisionNode *e) : elision(e) { }
+ KJSO evaluate();
+ private:
+ ElisionNode *elision;
+ };
+
+ class ElementNode : public Node {
+ public:
+ ElementNode(ElisionNode *e, Node *n) : list(0l), elision(e), node(n) { }
+ ElementNode(ElementNode *l, ElisionNode *e, Node *n)
+ : list(l), elision(e), node(n) { }
+ KJSO evaluate();
+ private:
+ ElementNode *list;
+ ElisionNode *elision;
+ Node *node;
+ };
+
+ class ArrayNode : public Node {
+ public:
+ ArrayNode(ElisionNode *e) : element(0L), elision(e), opt(true) { }
+ ArrayNode(ElementNode *ele)
+ : element(ele), elision(0), opt(false) { }
+ ArrayNode(ElisionNode *eli, ElementNode *ele)
+ : element(ele), elision(eli), opt(true) { }
+ KJSO evaluate();
+ private:
+ ElementNode *element;
+ ElisionNode *elision;
+ bool opt;
+ };
+
+ class ObjectLiteralNode : public Node {
+ public:
+ ObjectLiteralNode(Node *l) : list(l) { }
+ KJSO evaluate();
+ private:
+ Node *list;
+ };
+
+ class PropertyValueNode : public Node {
+ public:
+ PropertyValueNode(Node *n, Node *a, Node *l = 0L)
+ : name(n), assign(a), list(l) { }
+ KJSO evaluate();
+ private:
+ Node *name, *assign, *list;
+ };
+
+ class PropertyNode : public Node {
+ public:
+ PropertyNode(double d) : numeric(d) { }
+ PropertyNode(const UString *s) : str(*s) { }
+ KJSO evaluate();
+ private:
+ double numeric;
+ UString str;
+ };
+
+ class AccessorNode1 : public Node {
+ public:
+ AccessorNode1(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *expr1;
+ Node *expr2;
+ };
+
+ class AccessorNode2 : public Node {
+ public:
+ AccessorNode2(Node *e, const UString *s) : expr(e), ident(*s) { }
+ KJSO evaluate();
+ private:
+ Node *expr;
+ UString ident;
+ };
+
+ class ArgumentListNode : public Node {
+ public:
+ ArgumentListNode(Node *e);
+ ArgumentListNode(ArgumentListNode *l, Node *e);
+ KJSO evaluate();
+ List *evaluateList();
+ private:
+ ArgumentListNode *list;
+ Node *expr;
+ };
+
+ class ArgumentsNode : public Node {
+ public:
+ ArgumentsNode(ArgumentListNode *l);
+ KJSO evaluate();
+ List *evaluateList();
+ private:
+ ArgumentListNode *list;
+ };
+
+ class NewExprNode : public Node {
+ public:
+ NewExprNode(Node *e) : expr(e), args(0L) {}
+ NewExprNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ ArgumentsNode *args;
+ };
+
+ class FunctionCallNode : public Node {
+ public:
+ FunctionCallNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {}
+ KJSO evaluate();
+#ifdef KJS_DEBUGGER
+ void steppingInto(bool in);
+ Debugger::Mode previousMode;
+#endif
+ private:
+ Node *expr;
+ ArgumentsNode *args;
+ };
+
+ class PostfixNode : public Node {
+ public:
+ PostfixNode(Node *e, Operator o) : expr(e), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ Operator oper;
+ };
+
+ class DeleteNode : public Node {
+ public:
+ DeleteNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class VoidNode : public Node {
+ public:
+ VoidNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class TypeOfNode : public Node {
+ public:
+ TypeOfNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class PrefixNode : public Node {
+ public:
+ PrefixNode(Operator o, Node *e) : oper(o), expr(e) {}
+ KJSO evaluate();
+ private:
+ Operator oper;
+ Node *expr;
+ };
+
+ class UnaryPlusNode : public Node {
+ public:
+ UnaryPlusNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class NegateNode : public Node {
+ public:
+ NegateNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class BitwiseNotNode : public Node {
+ public:
+ BitwiseNotNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class LogicalNotNode : public Node {
+ public:
+ LogicalNotNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class MultNode : public Node {
+ public:
+ MultNode(Node *t1, Node *t2, char op) : term1(t1), term2(t2), oper(op) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ char oper;
+ };
+
+ class AddNode : public Node {
+ public:
+ AddNode(Node *t1, Node *t2, char op) : term1(t1), term2(t2), oper(op) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ char oper;
+ };
+
+ class ShiftNode : public Node {
+ public:
+ ShiftNode(Node *t1, Operator o, Node *t2)
+ : term1(t1), term2(t2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ Operator oper;
+ };
+
+ class RelationalNode : public Node {
+ public:
+ RelationalNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class EqualNode : public Node {
+ public:
+ EqualNode(Node *e1, Operator o, Node *e2)
+ : expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class BitOperNode : public Node {
+ public:
+ BitOperNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class BinaryLogicalNode : public Node {
+ public:
+ BinaryLogicalNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class ConditionalNode : public Node {
+ public:
+ ConditionalNode(Node *l, Node *e1, Node *e2) :
+ logical(l), expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *logical, *expr1, *expr2;
+ };
+
+ class AssignNode : public Node {
+ public:
+ AssignNode(Node *l, Operator o, Node *e) : left(l), oper(o), expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *left;
+ Operator oper;
+ Node *expr;
+ };
+
+ class CommaNode : public Node {
+ public:
+ CommaNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ };
+
+ class StatListNode : public StatementNode {
+ public:
+ StatListNode(StatementNode *s) : statement(s), list(0L) { }
+ StatListNode(StatListNode *l, StatementNode *s) : statement(s), list(l) { }
+ Completion execute();
+ private:
+ StatementNode *statement;
+ StatListNode *list;
+ };
+
+ class AssignExprNode : public Node {
+ public:
+ AssignExprNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class VarDeclNode : public Node {
+ public:
+ VarDeclNode(const UString *id, AssignExprNode *in);
+ KJSO evaluate();
+ private:
+ UString ident;
+ AssignExprNode *init;
+ };
+
+ class VarDeclListNode : public Node {
+ public:
+ VarDeclListNode(VarDeclNode *v) : list(0L), var(v) {}
+ VarDeclListNode(Node *l, VarDeclNode *v) : list(l), var(v) {}
+ KJSO evaluate();
+ private:
+ Node *list;
+ VarDeclNode *var;
+ };
+
+ class VarStatementNode : public StatementNode {
+ public:
+ VarStatementNode(VarDeclListNode *l) : list(l) {}
+ Completion execute();
+ private:
+ VarDeclListNode *list;
+ };
+
+ class BlockNode : public StatementNode {
+ public:
+ BlockNode(StatListNode *s) : statlist(s) {}
+ Completion execute();
+ private:
+ StatListNode *statlist;
+ };
+
+ class EmptyStatementNode : public StatementNode {
+ public:
+ EmptyStatementNode() { } // debug
+ Completion execute();
+ };
+
+ class ExprStatementNode : public StatementNode {
+ public:
+ ExprStatementNode(Node *e) : expr(e) { }
+ Completion execute();
+ private:
+ Node *expr;
+ };
+
+ class IfNode : public StatementNode {
+ public:
+ IfNode(Node *e, StatementNode *s1, StatementNode *s2)
+ : expr(e), statement1(s1), statement2(s2) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *statement1, *statement2;
+ };
+
+ class DoWhileNode : public StatementNode {
+ public:
+ DoWhileNode(StatementNode *s, Node *e) : statement(s), expr(e) {}
+ Completion execute();
+ private:
+ StatementNode *statement;
+ Node *expr;
+ };
+
+ class WhileNode : public StatementNode {
+ public:
+ WhileNode(Node *e, StatementNode *s) : expr(e), statement(s) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *statement;
+ };
+
+ class ForNode : public StatementNode {
+ public:
+ ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) :
+ expr1(e1), expr2(e2), expr3(e3), stat(s) {}
+ Completion execute();
+ private:
+ Node *expr1, *expr2, *expr3;
+ StatementNode *stat;
+ };
+
+ class ForInNode : public StatementNode {
+ public:
+ ForInNode(Node *l, Node *e, StatementNode *s) :
+ init(0L), lexpr(l), expr(e), stat(s) {}
+ ForInNode(const UString *i, AssignExprNode *in, Node *e, StatementNode *s)
+ : ident(*i), init(in), lexpr(0L), expr(e), stat(s) {}
+ Completion execute();
+ private:
+ UString ident;
+ AssignExprNode *init;
+ Node *lexpr, *expr;
+ StatementNode *stat;
+ };
+
+ class ContinueNode : public StatementNode {
+ public:
+ ContinueNode() { }
+ ContinueNode(const UString *i) : ident(*i) { }
+ Completion execute();
+ private:
+ UString ident;
+ };
+
+ class BreakNode : public StatementNode {
+ public:
+ BreakNode() { }
+ BreakNode(const UString *i) : ident(*i) { }
+ Completion execute();
+ private:
+ UString ident;
+ };
+
+ class ReturnNode : public StatementNode {
+ public:
+ ReturnNode(Node *v) : value(v) {}
+ Completion execute();
+ private:
+ Node *value;
+ };
+
+ class WithNode : public StatementNode {
+ public:
+ WithNode(Node *e, StatementNode *s) : expr(e), stat(s) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *stat;
+ };
+
+ class CaseClauseNode: public Node {
+ public:
+ CaseClauseNode(Node *e, StatListNode *l) : expr(e), list(l) { }
+ KJSO evaluate();
+ Completion evalStatements();
+ private:
+ Node *expr;
+ StatListNode *list;
+ };
+
+ class ClauseListNode : public Node {
+ public:
+ ClauseListNode(CaseClauseNode *c) : cl(c), nx(0L) { }
+ ClauseListNode* append(CaseClauseNode *c);
+ KJSO evaluate() { /* should never be called */ return KJSO(); }
+ CaseClauseNode *clause() const { return cl; }
+ ClauseListNode *next() const { return nx; }
+ private:
+ CaseClauseNode *cl;
+ ClauseListNode *nx;
+ };
+
+ class CaseBlockNode: public Node {
+ public:
+ CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2)
+ : list1(l1), def(d), list2(l2) { }
+ KJSO evaluate() { /* should never be called */ return KJSO(); }
+ Completion evalBlock(const KJSO& input);
+ private:
+ ClauseListNode *list1;
+ CaseClauseNode *def;
+ ClauseListNode *list2;
+ };
+
+ class SwitchNode : public StatementNode {
+ public:
+ SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { }
+ Completion execute();
+ private:
+ Node *expr;
+ CaseBlockNode *block;
+ };
+
+ class LabelNode : public StatementNode {
+ public:
+ LabelNode(const UString *l, StatementNode *s) : label(*l), stat(s) { }
+ Completion execute();
+ private:
+ UString label;
+ StatementNode *stat;
+ };
+
+ class ThrowNode : public StatementNode {
+ public:
+ ThrowNode(Node *e) : expr(e) {}
+ Completion execute();
+ private:
+ Node *expr;
+ };
+
+ class CatchNode : public StatementNode {
+ public:
+ CatchNode(UString *i, StatementNode *b) : ident(*i), block(b) {}
+ Completion execute();
+ Completion execute(const KJSO &arg);
+ private:
+ UString ident;
+ StatementNode *block;
+ };
+
+ class FinallyNode : public StatementNode {
+ public:
+ FinallyNode(StatementNode *b) : block(b) {}
+ Completion execute();
+ private:
+ StatementNode *block;
+ };
+
+ class TryNode : public StatementNode {
+ public:
+ TryNode(StatementNode *b, Node *c = 0L, Node *f = 0L)
+ : block(b), _catch((CatchNode*)c), _final((FinallyNode*)f) {}
+ Completion execute();
+ private:
+ StatementNode *block;
+ CatchNode *_catch;
+ FinallyNode *_final;
+ };
+
+ class ParameterNode : public Node {
+ public:
+ ParameterNode(const UString *i) : id(*i), next(0L) { }
+ ParameterNode *append(const UString *i);
+ KJSO evaluate();
+ UString ident() { return id; }
+ ParameterNode *nextParam() { return next; }
+ private:
+ UString id;
+ ParameterNode *next;
+ };
+
+ // inherited by ProgramNode
+ class FunctionBodyNode : public StatementNode {
+ public:
+ FunctionBodyNode(SourceElementsNode *s);
+ Completion execute();
+ protected:
+ SourceElementsNode *source;
+ };
+
+ class FuncDeclNode : public StatementNode {
+ public:
+ FuncDeclNode(const UString *i, ParameterNode *p, FunctionBodyNode *b)
+ : ident(*i), param(p), body(b) { }
+ Completion execute() { /* empty */ return Completion(); }
+ void processFuncDecl();
+ private:
+ UString ident;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ };
+
+ class FuncExprNode : public Node {
+ public:
+ FuncExprNode(ParameterNode *p, FunctionBodyNode *b)
+ : param(p), body(b) { }
+ KJSO evaluate();
+ private:
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ };
+
+ class SourceElementNode : public StatementNode {
+ public:
+ SourceElementNode(StatementNode *s) { statement = s; function = 0L; }
+ SourceElementNode(FuncDeclNode *f) { function = f; statement = 0L;}
+ Completion execute();
+ virtual void processFuncDecl();
+ void deleteStatements();
+ private:
+ StatementNode *statement;
+ FuncDeclNode *function;
+ };
+
+ class SourceElementsNode : public StatementNode {
+ public:
+ SourceElementsNode(SourceElementNode *s1) { element = s1; elements = 0L; }
+ SourceElementsNode(SourceElementsNode *s1, SourceElementNode *s2)
+ { elements = s1; element = s2; }
+ Completion execute();
+ virtual void processFuncDecl();
+ void deleteStatements();
+ private:
+ SourceElementNode *element;
+ SourceElementsNode *elements;
+ };
+
+ class ProgramNode : public FunctionBodyNode {
+ public:
+ ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s) { }
+ void deleteGlobalStatements();
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/number_object.cpp b/JavaScriptCore/kjs/number_object.cpp
new file mode 100644
index 0000000..af37d48
--- /dev/null
+++ b/JavaScriptCore/kjs/number_object.cpp
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "number_object.h"
+
+using namespace KJS;
+
+NumberObject::NumberObject(const Object& funcProto, const Object &numProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // Number.Prototype
+ setPrototypeProperty(numProto);
+}
+
+// ECMA 15.7.3
+KJSO NumberObject::get(const UString &p) const
+{
+ double d;
+
+ if (p == "NaN")
+ d = NaN;
+ else if (p == "NEGATIVE_INFINITY")
+ d = -Inf;
+ else if (p == "POSITIVE_INFINITY")
+ d = Inf;
+ else
+ return Imp::get(p);
+
+ return Number(d);
+}
+
+// ECMA 15.7.1
+Completion NumberObject::execute(const List &args)
+{
+ Number n;
+ if (args.isEmpty())
+ n = Number(0);
+ else
+ n = args[0].toNumber();
+
+ return Completion(ReturnValue, n);
+}
+
+// ECMA 15.7.2
+Object NumberObject::construct(const List &args)
+{
+ Number n;
+ if (args.isEmpty())
+ n = Number(0);
+ else
+ n = args[0].toNumber();
+
+ return Object::create(NumberClass, n);
+}
+
+class NumberProtoFunc : public InternalFunctionImp {
+public:
+ NumberProtoFunc(int i) : id (i) { }
+ Completion execute(const List &);
+ enum { ToString, ToLocaleString, ValueOf };
+private:
+ int id;
+};
+
+// ECMA 15.7.4.2 - 15.7.4.7
+Completion NumberProtoFunc::execute(const List &)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // no generic function. "this" has to be a Number object
+ if (thisObj.isNull() || thisObj.getClass() != NumberClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ // execute "toString()" or "valueOf()", respectively
+ KJSO v = thisObj.internalValue();
+ switch (id) {
+ case ToString:
+ case ToLocaleString: /* TODO */
+ result = v.toString();
+ break;
+ case ValueOf:
+ result = v.toNumber();
+ break;
+ }
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.7.4
+NumberPrototype::NumberPrototype(const Object& proto)
+ : ObjectImp(NumberClass, Number(0), proto)
+{
+ // The constructor will be added later in NumberObject's constructor
+}
+
+KJSO NumberPrototype::get(const UString &p) const
+{
+ int t;
+ if (p == "toString")
+ t = NumberProtoFunc::ToString;
+ else if (p == "toLocaleString")
+ t = NumberProtoFunc::ToLocaleString;
+ else if (p == "valueOf")
+ t = NumberProtoFunc::ValueOf;
+ else
+ return Imp::get(p);
+
+ return Function(new NumberProtoFunc(t));
+}
diff --git a/JavaScriptCore/kjs/number_object.h b/JavaScriptCore/kjs/number_object.h
new file mode 100644
index 0000000..3addbdf
--- /dev/null
+++ b/JavaScriptCore/kjs/number_object.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _NUMBER_OBJECT_H_
+#define _NUMBER_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class NumberObject : public ConstructorImp {
+ public:
+ NumberObject(const Object& funcProto, const Object &numProto);
+ virtual KJSO get(const UString &p) const;
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class NumberPrototype : public ObjectImp {
+ public:
+ NumberPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/object.cpp b/JavaScriptCore/kjs/object.cpp
new file mode 100644
index 0000000..adcc0fb
--- /dev/null
+++ b/JavaScriptCore/kjs/object.cpp
@@ -0,0 +1,1062 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "object.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "collector.h"
+#include "error_object.h"
+
+namespace KJS {
+
+#ifdef WORDS_BIGENDIAN
+ unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
+ unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
+#elif defined(arm)
+ unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
+ unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
+#else
+ unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
+ unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
+#endif
+
+ const double NaN = *(const double*) NaN_Bytes;
+ const double Inf = *(const double*) Inf_Bytes;
+ const double D16 = 65536.0;
+ const double D31 = 2147483648.0; /* TODO: remove in next version */
+ const double D32 = 4294967296.0;
+
+ // TODO: -0
+};
+
+using namespace KJS;
+
+const TypeInfo Imp::info = { "Imp", AbstractType, 0, 0, 0 };
+
+namespace KJS {
+ struct Property {
+ UString name;
+ Imp *object;
+ int attribute;
+ Property *next;
+ };
+}
+
+KJSO::KJSO()
+ : rep(0)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+}
+
+KJSO::KJSO(Imp *d)
+ : rep(d)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+}
+
+KJSO::KJSO(const KJSO &o)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ rep = o.rep;
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+}
+
+KJSO& KJSO::operator=(const KJSO &o)
+{
+ if (rep)
+ rep->deref();
+ rep = o.rep;
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+
+ return *this;
+}
+
+KJSO::~KJSO()
+{
+#ifdef KJS_DEBUG_MEM
+ count--;
+#endif
+
+ if (rep)
+ rep->deref();
+}
+
+bool KJSO::isDefined() const
+{
+ return !isA(UndefinedType);
+}
+
+bool KJSO::isNull() const
+{
+ return !rep;
+}
+
+Type KJSO::type() const
+{
+#ifdef KJS_VERBOSE
+ if (!rep)
+ fprintf(stderr, "requesting type of null object\n");
+#endif
+
+ return rep ? rep->typeInfo()->type : UndefinedType;
+}
+
+bool KJSO::isObject() const
+{
+ return (type() >= ObjectType);
+}
+
+bool KJSO::isA(const char *s) const
+{
+ assert(rep);
+ const TypeInfo *info = rep->typeInfo();
+
+ if (!s || !info || !info->name)
+ return false;
+
+ if (info->type == HostType && strcmp(s, "HostObject") == 0)
+ return true;
+
+ return (strcmp(s, info->name) == 0);
+}
+
+bool KJSO::derivedFrom(const char *s) const
+{
+ if (!s)
+ return false;
+
+ assert(rep);
+ const TypeInfo *info = rep->typeInfo();
+ while (info) {
+ if (info->name && strcmp(s, info->name) == 0)
+ return true;
+ info = info->base;
+ }
+
+ return false;
+}
+
+KJSO KJSO::toPrimitive(Type preferred) const
+{
+ assert(rep);
+ return rep->toPrimitive(preferred);
+}
+
+Boolean KJSO::toBoolean() const
+{
+ assert(rep);
+ return rep->toBoolean();
+}
+
+Number KJSO::toNumber() const
+{
+ assert(rep);
+ return rep->toNumber();
+}
+
+// helper function for toInteger, toInt32, toUInt32 and toUInt16
+double KJSO::round() const
+{
+ if (isA(UndefinedType)) /* TODO: see below */
+ return 0.0;
+ Number n = toNumber();
+ if (n.value() == 0.0) /* TODO: -0, NaN, Inf */
+ return 0.0;
+ double d = floor(fabs(n.value()));
+ if (n.value() < 0)
+ d *= -1;
+
+ return d;
+}
+
+// ECMA 9.4
+Number KJSO::toInteger() const
+{
+ return Number(round());
+}
+
+// ECMA 9.5
+int KJSO::toInt32() const
+{
+ double d = round();
+ double d32 = fmod(d, D32);
+
+ if (d32 >= D32 / 2.0)
+ d32 -= D32;
+
+ return static_cast<int>(d32);
+}
+
+// ECMA 9.6
+unsigned int KJSO::toUInt32() const
+{
+ double d = round();
+ double d32 = fmod(d, D32);
+
+ return static_cast<unsigned int>(d32);
+}
+
+// ECMA 9.7
+unsigned short KJSO::toUInt16() const
+{
+ double d = round();
+ double d16 = fmod(d, D16);
+
+ return static_cast<unsigned short>(d16);
+}
+
+String KJSO::toString() const
+{
+ assert(rep);
+ return rep->toString();
+}
+
+Object KJSO::toObject() const
+{
+ assert(rep);
+ if (isObject())
+ return Object(rep);
+
+ return rep->toObject();
+}
+
+bool KJSO::implementsCall() const
+{
+ return (type() == FunctionType ||
+ type() == InternalFunctionType ||
+ type() == ConstructorType ||
+ type() == DeclaredFunctionType ||
+ type() == AnonymousFunctionType);
+}
+
+// [[call]]
+KJSO KJSO::executeCall(const KJSO &thisV, const List *args)
+{
+ assert(rep);
+ assert(implementsCall());
+ return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args);
+}
+
+KJSO KJSO::executeCall(const KJSO &thisV, const List *args, const List *extraScope) const
+{
+ assert(rep);
+ assert(implementsCall());
+ return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args, extraScope);
+}
+
+void KJSO::setConstructor(KJSO c)
+{
+ put("constructor", c, DontEnum | DontDelete | ReadOnly);
+}
+
+// ECMA 8.7.1
+KJSO KJSO::getBase() const
+{
+ if (!isA(ReferenceType))
+ return Error::create(ReferenceError, I18N_NOOP("Invalid reference base"));
+
+ return ((ReferenceImp*)rep)->getBase();
+}
+
+// ECMA 8.7.2
+UString KJSO::getPropertyName() const
+{
+ if (!isA(ReferenceType))
+ // the spec wants a runtime error here. But getValue() and putValue()
+ // will catch this case on their own earlier. When returning a Null
+ // string we should be on the safe side.
+ return UString();
+
+ return ((ReferenceImp*)rep)->getPropertyName();
+}
+
+// ECMA 8.7.1
+KJSO KJSO::getValue() const
+{
+ if (!isA(ReferenceType)) {
+ return *this;
+ }
+ KJSO o = getBase();
+ if (o.isNull() || o.isA(NullType)) {
+ UString m = I18N_NOOP("Can't find variable: ") + getPropertyName();
+ return Error::create(ReferenceError, m.ascii());
+ }
+
+ return o.get(getPropertyName());
+}
+
+/* TODO: remove in next version */
+KJSO KJSO::getValue()
+{
+ return const_cast<const KJSO*>(this)->getValue();
+}
+
+// ECMA 8.7.2
+ErrorType KJSO::putValue(const KJSO& v)
+{
+ if (!isA(ReferenceType))
+ return ReferenceError;
+
+ KJSO o = getBase();
+ if (o.isA(NullType))
+ Global::current().put(getPropertyName(), v);
+ else {
+ // are we writing into an array ?
+ if (o.isA(ObjectType) && (o.toObject().getClass() == ArrayClass))
+ o.putArrayElement(getPropertyName(), v);
+ else
+ o.put(getPropertyName(), v);
+ }
+
+ return NoError;
+}
+
+void KJSO::setPrototype(const KJSO& p)
+{
+ assert(rep);
+ rep->setPrototype(p);
+}
+
+void KJSO::setPrototypeProperty(const KJSO& p)
+{
+ assert(rep);
+ put("prototype", p, DontEnum | DontDelete | ReadOnly);
+}
+
+KJSO KJSO::prototype() const
+{
+ if (rep)
+ return KJSO(rep->proto);
+ else
+ return KJSO();
+}
+
+// ECMA 8.6.2.1
+KJSO KJSO::get(const UString &p) const
+{
+ assert(rep);
+ return rep->get(p);
+}
+
+// ECMA 8.6.2.2
+void KJSO::put(const UString &p, const KJSO& v)
+{
+ assert(rep);
+ rep->put(p, v);
+}
+
+// ECMA 8.6.2.2
+void KJSO::put(const UString &p, const KJSO& v, int attr)
+{
+ static_cast<Imp*>(rep)->put(p, v, attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, double d, int attr)
+{
+ put(p, Number(d), attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, int i, int attr)
+{
+ put(p, Number(i), attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, unsigned int u, int attr)
+{
+ put(p, Number(u), attr);
+}
+
+// ECMA 15.4.5.1
+void KJSO::putArrayElement(const UString &p, const KJSO& v)
+{
+ assert(rep);
+ rep->putArrayElement(p, v);
+}
+
+// ECMA 8.6.2.3
+bool KJSO::canPut(const UString &p) const
+{
+ assert(rep);
+ return rep->canPut(p);
+}
+
+// ECMA 8.6.2.4
+bool KJSO::hasProperty(const UString &p, bool recursive) const
+{
+ assert(rep);
+ return rep->hasProperty(p, recursive);
+}
+
+// ECMA 8.6.2.5
+bool KJSO::deleteProperty(const UString &p)
+{
+ assert(rep);
+ return rep->deleteProperty(p);
+}
+
+Object::Object(Imp *d) : KJSO(d) { }
+
+Object::Object(Class c) : KJSO(new ObjectImp(c)) { }
+
+Object::Object(Class c, const KJSO& v) : KJSO(new ObjectImp(c, v)) { }
+
+Object::Object(Class c, const KJSO& v, const Object& p)
+ : KJSO(new ObjectImp(c, v))
+{
+ setPrototype(p);
+}
+
+Object::~Object() { }
+
+void Object::setClass(Class c)
+{
+ static_cast<ObjectImp*>(rep)->cl = c;
+}
+
+Class Object::getClass() const
+{
+ assert(rep);
+ return static_cast<ObjectImp*>(rep)->cl;
+}
+
+void Object::setInternalValue(const KJSO& v)
+{
+ assert(rep);
+ static_cast<ObjectImp*>(rep)->val = v.imp();
+}
+
+KJSO Object::internalValue()
+{
+ assert(rep);
+ return KJSO(static_cast<ObjectImp*>(rep)->val);
+}
+
+Object Object::create(Class c)
+{
+ return Object::create(c, KJSO());
+}
+
+// factory
+Object Object::create(Class c, const KJSO& val)
+{
+ Global global(Global::current());
+ Object obj = Object();
+ obj.setClass(c);
+ obj.setInternalValue(val);
+
+ UString p = "[[";
+ switch (c) {
+ case UndefClass:
+ case ObjectClass:
+ p += "Object";
+ break;
+ case FunctionClass:
+ p += "Function";
+ break;
+ case ArrayClass:
+ p += "Array";
+ obj.put("length", Number(0), DontEnum | DontDelete);
+ break;
+ case StringClass:
+ p += "String";
+ obj.put("length", val.toString().value().size());
+ break;
+ case BooleanClass:
+ p += "Boolean";
+ break;
+ case NumberClass:
+ p += "Number";
+ break;
+ case DateClass:
+ p += "Date";
+ break;
+ case RegExpClass:
+ p += "RegExp";
+ break;
+ case ErrorClass:
+ p += "Error";
+ break;
+ }
+ p += ".prototype]]";
+
+ // KJSO prot = global.get(p).get("prototype");
+ KJSO prot = global.get(p);
+ assert(prot.isDefined());
+
+ obj.setPrototype(prot);
+ return obj;
+}
+
+Object Object::create(Class c, const KJSO& val, const Object& p)
+{
+ Global global(Global::current());
+ Object obj = Object();
+ Object prot;
+ obj.setClass(c);
+ obj.setInternalValue(val);
+
+ prot = p;
+ obj.setPrototype(prot);
+ return obj;
+}
+
+Object Object::dynamicCast(const KJSO &obj)
+{
+ // return null object on type mismatch
+ if (!obj.isA(ObjectType))
+ return Object(0L);
+
+ return Object(obj.imp());
+
+}
+
+#ifdef KJS_DEBUG_MEM
+int KJSO::count = 0;
+int Imp::count = 0;
+int List::count = 0;
+#endif
+
+Imp::Imp()
+ : refcount(0), prop(0), proto(0)
+{
+ setCreated(true);
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+}
+
+Imp::~Imp()
+{
+#ifdef KJS_DEBUG_MEM
+ assert(Collector::collecting);
+ count--;
+#endif
+
+// dangling pointer during garbage collection !
+// if (proto)
+// proto->deref();
+
+ // delete attached properties
+ Property *tmp, *p = prop;
+ while (p) {
+ tmp = p;
+ p = p->next;
+ delete tmp;
+ }
+}
+
+KJSO Imp::toPrimitive(Type preferred) const
+{
+ return defaultValue(preferred);
+ /* TODO: is there still any need to throw a runtime error _here_ ? */
+}
+
+Boolean Imp::toBoolean() const
+{
+ return Boolean();
+}
+
+Number Imp::toNumber() const
+{
+ return Number();
+}
+
+String Imp::toString() const
+{
+ return String();
+}
+
+Object Imp::toObject() const
+{
+ return Object(Error::create(TypeError).imp());
+}
+
+
+PropList* Imp::propList(PropList *first, PropList *last, bool recursive) const
+{
+ Property *pr = prop;
+ while(pr) {
+ if (!(pr->attribute & DontEnum) && !first->contains(pr->name)) {
+ if(last) {
+ last->next = new PropList();
+ last = last->next;
+ } else {
+ first = new PropList();
+ last = first;
+ }
+ last->name = pr->name;
+ }
+ pr = pr->next;
+ }
+ if (proto && recursive)
+ proto->propList(first, last);
+
+ return first;
+}
+
+KJSO Imp::get(const UString &p) const
+{
+ Property *pr = prop;
+ while (pr) {
+ if (pr->name == p) {
+ return pr->object;
+ }
+ pr = pr->next;
+ }
+
+ if (!proto)
+ return Undefined();
+
+ return proto->get(p);
+}
+
+// may be overriden
+void Imp::put(const UString &p, const KJSO& v)
+{
+ put(p, v, None);
+}
+
+// ECMA 8.6.2.2
+void Imp::put(const UString &p, const KJSO& v, int attr)
+{
+ /* TODO: check for write permissions directly w/o this call */
+ // putValue() is used for JS assignemnts. It passes no attribute.
+ // Assume that a C++ implementation knows what it is doing
+ // and let it override the canPut() check.
+ if (attr == None && !canPut(p))
+ return;
+
+ Property *pr;
+
+ if (prop) {
+ pr = prop;
+ while (pr) {
+ if (pr->name == p) {
+ // replace old value
+ pr->object = v.imp();
+ pr->attribute = attr;
+ return;
+ }
+ pr = pr->next;
+ }
+ }
+
+ // add new property
+ pr = new Property;
+ pr->name = p;
+ pr->object = v.imp();
+ pr->attribute = attr;
+ pr->next = prop;
+ prop = pr;
+}
+
+// ECMA 8.6.2.3
+bool Imp::canPut(const UString &p) const
+{
+ if (prop) {
+ const Property *pr = prop;
+ while (pr) {
+ if (pr->name == p)
+ return !(pr->attribute & ReadOnly);
+ pr = pr->next;
+ }
+ }
+ if (!proto)
+ return true;
+
+ return proto->canPut(p);
+}
+
+// ECMA 8.6.2.4
+bool Imp::hasProperty(const UString &p, bool recursive) const
+{
+ const Property *pr = prop;
+ while (pr) {
+ if (pr->name == p)
+ return true;
+ pr = pr->next;
+ }
+
+ if (!proto || !recursive)
+ return false;
+
+ return proto->hasProperty(p);
+}
+
+// ECMA 8.6.2.5
+bool Imp::deleteProperty(const UString &p)
+{
+ Property *pr = prop;
+ Property **prev = ∝
+ while (pr) {
+ if (pr->name == p) {
+ if ((pr->attribute & DontDelete))
+ return false;
+ *prev = pr->next;
+ delete pr;
+ return true;
+ }
+ prev = &(pr->next);
+ pr = pr->next;
+ }
+ return true;
+}
+
+// ECMA 15.4.5.1
+void Imp::putArrayElement(const UString &p, const KJSO& v)
+{
+ if (!canPut(p))
+ return;
+
+ if (hasProperty(p)) {
+ if (p == "length") {
+ KJSO len = get("length");
+ unsigned int oldLen = len.toUInt32();
+ unsigned int newLen = v.toUInt32();
+ // shrink array
+ for (unsigned int u = newLen; u < oldLen; u++) {
+ UString p = UString::from(u);
+ if (hasProperty(p, false))
+ deleteProperty(p);
+ }
+ put("length", Number(newLen), DontEnum | DontDelete);
+ return;
+ }
+ // put(p, v);
+ } // } else
+ put(p, v);
+
+ // array index ?
+ unsigned int idx;
+ if (!sscanf(p.cstring().c_str(), "%u", &idx)) /* TODO */
+ return;
+
+ // do we need to update/create the length property ?
+ if (hasProperty("length", false)) {
+ KJSO len = get("length");
+ if (idx < len.toUInt32())
+ return;
+ }
+
+ put("length", Number(idx+1), DontDelete | DontEnum);
+}
+
+bool Imp::implementsCall() const
+{
+ return (type() == FunctionType ||
+ type() == InternalFunctionType ||
+ type() == ConstructorType ||
+ type() == DeclaredFunctionType ||
+ type() == AnonymousFunctionType);
+}
+
+// ECMA 8.6.2.6 (new draft)
+KJSO Imp::defaultValue(Type hint) const
+{
+ KJSO o;
+
+ /* TODO String on Date object */
+ if (hint != StringType && hint != NumberType)
+ hint = NumberType;
+
+ if (hint == StringType)
+ o = get("toString");
+ else
+ o = get("valueOf");
+
+ Imp *that = const_cast<Imp*>(this);
+ if (o.implementsCall()) { // spec says "not primitive type" but ...
+ FunctionImp *f = static_cast<FunctionImp*>(o.imp());
+ KJSO s = f->executeCall(that, 0L);
+ if (!s.isObject())
+ return s;
+ }
+
+ if (hint == StringType)
+ o = get("valueOf");
+ else
+ o = get("toString");
+
+ if (o.implementsCall()) {
+ FunctionImp *f = static_cast<FunctionImp*>(o.imp());
+ KJSO s = f->executeCall(that, 0L);
+ if (!s.isObject())
+ return s;
+ }
+
+ return Error::create(TypeError, I18N_NOOP("No default value"));
+}
+
+void Imp::mark(Imp*)
+{
+ setMarked(true);
+
+ if (proto && !proto->marked())
+ proto->mark();
+
+ struct Property *p = prop;
+ while (p) {
+ if (p->object && !p->object->marked())
+ p->object->mark();
+ p = p->next;
+ }
+}
+
+bool Imp::marked() const
+{
+ return prev;
+}
+
+void Imp::setPrototype(const KJSO& p)
+{
+ if (proto)
+ proto->deref();
+ proto = p.imp();
+ if (proto)
+ proto->ref();
+}
+
+void Imp::setPrototypeProperty(const KJSO &p)
+{
+ put("prototype", p, DontEnum | DontDelete | ReadOnly);
+}
+
+void Imp::setConstructor(const KJSO& c)
+{
+ put("constructor", c, DontEnum | DontDelete | ReadOnly);
+}
+
+void* Imp::operator new(size_t s)
+{
+ return Collector::allocate(s);
+}
+
+void Imp::operator delete(void*, size_t)
+{
+ // deprecated. a mistake.
+}
+
+void Imp::operator delete(void*)
+{
+ // Do nothing. So far.
+}
+
+void Imp::setMarked(bool m)
+{
+ prev = m ? this : 0L;
+}
+
+void Imp::setGcAllowed(bool a)
+{
+ next = this;
+ if (a)
+ next++;
+}
+
+bool Imp::gcAllowed() const
+{
+ return (next && next != this);
+}
+
+void Imp::setCreated(bool c)
+{
+ next = c ? this : 0L;
+}
+
+bool Imp::created() const
+{
+ return next;
+}
+
+ObjectImp::ObjectImp(Class c) : cl(c), val(0L) { }
+
+ObjectImp::ObjectImp(Class c, const KJSO &v) : cl(c), val(v.imp()) { }
+
+ObjectImp::ObjectImp(Class c, const KJSO &v, const KJSO &p)
+ : cl(c), val(v.imp())
+{
+ setPrototype(p);
+}
+
+ObjectImp::~ObjectImp() { }
+
+Boolean ObjectImp::toBoolean() const
+{
+ return Boolean(true);
+}
+
+Number ObjectImp::toNumber() const
+{
+ return toPrimitive(NumberType).toNumber();
+}
+
+String ObjectImp::toString() const
+{
+ KJSO tmp;
+ String res;
+
+ if (hasProperty("toString") && (tmp = get("toString")).implementsCall()) {
+ // TODO live w/o hack
+ res = tmp.executeCall(KJSO(const_cast<ObjectImp*>(this)), 0L).toString();
+ } else {
+ tmp = toPrimitive(StringType);
+ res = tmp.toString();
+ }
+
+ return res;
+}
+
+const TypeInfo ObjectImp::info = { "Object", ObjectType, 0, 0, 0 };
+
+Object ObjectImp::toObject() const
+{
+ return Object(const_cast<ObjectImp*>(this));
+}
+
+KJSO ObjectImp::toPrimitive(Type preferred) const
+{
+ // ### Imp already does that now. Remove in KDE 3.0.
+ return defaultValue(preferred);
+ /* TODO: is there still any need to throw a runtime error _here_ ? */
+}
+
+void ObjectImp::mark(Imp*)
+{
+ // mark objects from the base
+ Imp::mark();
+
+ // mark internal value, if any and it has not been visited yet
+ if (val && !val->marked())
+ val->mark();
+}
+
+HostImp::HostImp()
+{
+ setPrototype(Global::current().objectPrototype());
+ //printf("HostImp::HostImp() %p\n",this);
+}
+
+HostImp::~HostImp() { }
+
+Boolean HostImp::toBoolean() const
+{
+ return Boolean(true);
+}
+
+String HostImp::toString() const
+{
+ // Exact copy of ObjectImp::toString....
+ KJSO tmp;
+ String res;
+
+ if (hasProperty("toString") && (tmp = get("toString")).implementsCall()) {
+ // TODO live w/o hack
+ res = tmp.executeCall(KJSO(const_cast<HostImp*>(this)), 0L).toString();
+ } else {
+ tmp = toPrimitive(StringType);
+ res = tmp.toString();
+ }
+
+ return res;
+}
+
+const TypeInfo HostImp::info = { "HostObject", HostType, 0, 0, 0 };
+
+Object Error::createObject(ErrorType e, const char *m, int l)
+{
+ Context *context = Context::current();
+ if (!context)
+ return Object();
+
+ Object err = ErrorObject::create(e, m, l);
+
+ if (!KJScriptImp::hadException())
+ KJScriptImp::setException(err.imp());
+
+ const struct ErrorStruct {
+ ErrorType e;
+ const char *s;
+ } errtab[] = {
+ { GeneralError, I18N_NOOP("General error") },
+ { EvalError, I18N_NOOP("Evaluation error") },
+ { RangeError, I18N_NOOP("Range error") },
+ { ReferenceError, I18N_NOOP("Reference error") },
+ { SyntaxError, I18N_NOOP("Syntax error") },
+ { TypeError, I18N_NOOP("Type error") },
+ { URIError, I18N_NOOP("URI error") },
+ { (ErrorType)0, 0 }
+ };
+
+ const char *estr = I18N_NOOP("Unknown error");
+ const ErrorStruct *estruct = errtab;
+ while (estruct->e) {
+ if (estruct->e == e) {
+ estr = estruct->s;
+ break;
+ }
+ estruct++;
+ }
+
+#ifndef NDEBUG
+ const char *msg = err.get("message").toString().value().ascii();
+ if (l >= 0)
+ fprintf(stderr, "JS: %s at line %d. %s\n", estr, l, msg);
+ else
+ fprintf(stderr, "JS: %s. %s\n", estr, msg);
+#endif
+
+ return err;
+}
+
+KJSO Error::create(ErrorType e, const char *m, int l)
+{
+ return KJSO(createObject(e, m, l).imp());
+}
diff --git a/JavaScriptCore/kjs/object.h b/JavaScriptCore/kjs/object.h
new file mode 100644
index 0000000..7daee7e
--- /dev/null
+++ b/JavaScriptCore/kjs/object.h
@@ -0,0 +1,640 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_OBJECT_H_
+#define _KJS_OBJECT_H_
+
+#include <stdlib.h>
+
+#include "ustring.h"
+
+/**
+ * @short Main namespace
+ */
+namespace KJS {
+
+ /**
+ * Types of classes derived from KJSO
+ */
+ enum Type { // main types
+ AbstractType = 1,
+ UndefinedType,
+ NullType,
+ BooleanType,
+ NumberType,
+ StringType,
+ ObjectType,
+ HostType,
+ ReferenceType,
+ CompletionType,
+ // extended types
+ FunctionType,
+ InternalFunctionType,
+ DeclaredFunctionType,
+ AnonymousFunctionType,
+ ConstructorType,
+ ActivationType
+ };
+
+ /**
+ * Property attributes.
+ */
+ enum Attribute { None = 0,
+ ReadOnly = 1 << 1,
+ DontEnum = 1 << 2,
+ DontDelete = 1 << 3,
+ Internal = 1 << 4 };
+
+ /**
+ * Types of classes derived from @ref Object.
+ */
+ enum Class { UndefClass,
+ ArrayClass,
+ StringClass,
+ BooleanClass,
+ NumberClass,
+ ObjectClass,
+ DateClass,
+ RegExpClass,
+ ErrorClass,
+ FunctionClass };
+
+ /**
+ * Completion types.
+ */
+ enum Compl { Normal, Break, Continue, ReturnValue, Throw };
+
+ /**
+ * Error codes.
+ */
+ enum ErrorType { NoError = 0,
+ GeneralError,
+ EvalError,
+ RangeError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ URIError };
+
+ extern const double NaN;
+ extern const double Inf;
+
+ // forward declarations
+ class Imp;
+ class Boolean;
+ class Number;
+ class String;
+ class Object;
+ struct Property;
+ class PropList;
+ class List;
+
+ /**
+ * @short Type information.
+ */
+ struct TypeInfo {
+ /**
+ * A string denoting the type name. Example: "Number".
+ */
+ const char *name;
+ /**
+ * One of the @ref KJS::Type enums.
+ */
+ Type type;
+ /**
+ * Pointer to the type information of the base class.
+ * NULL if there is none.
+ */
+ const TypeInfo *base;
+ /**
+ * Additional specifier for your own use.
+ */
+ int extra;
+ /**
+ * Reserved for future extensions (internal).
+ */
+ void *dummy;
+ };
+
+ /**
+ * @short Main base class for every KJS object.
+ */
+ class KJSO {
+ friend class ElementNode;
+ public:
+ /**
+ * Constructor.
+ */
+ KJSO();
+ /**
+ * @internal
+ */
+ KJSO(Imp *d);
+ /**
+ * Copy constructor.
+ */
+ KJSO(const KJSO &);
+ /*
+ * Assignment operator
+ */
+ KJSO& operator=(const KJSO &);
+ /**
+ * Destructor.
+ */
+ virtual ~KJSO();
+ /**
+ * @return True if this object is null, i.e. if there is no data attached
+ * to this object. Don't confuse this with the Null object.
+ */
+ bool isNull() const;
+ /**
+ * @return True if this objects is of any other value than Undefined.
+ */
+ bool isDefined() const;
+ /**
+ * @return the type of the object. One of the @ref KJS::Type enums.
+ */
+ Type type() const;
+ /**
+ * Check whether object is of a certain type
+ * @param t type to check for
+ */
+ bool isA(Type t) const { return (type() == t); }
+ /**
+ * Check whether object is of a certain type. Allows checking of
+ * host objects, too.
+ * @param type name (Number, Boolean etc.)
+ */
+ bool isA(const char *s) const;
+ /**
+ * Use this method when checking for objects. It's safer than checking
+ * for a single object type with @ref isA().
+ */
+ bool isObject() const;
+ /**
+ * Examine the inheritance structure of this object.
+ * @param t Name of the base class.
+ * @return True if object is of type t or a derived from such a type.
+ */
+ bool derivedFrom(const char *s) const;
+
+ /**
+ * @return Conversion to primitive type (Undefined, Boolean, Number
+ * or String)
+ * @param preferred Optional hint. Either StringType or NumberType.
+ */
+ KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
+ /**
+ * @return Conversion to Boolean type.
+ */
+ Boolean toBoolean() const; // ECMA 9.2
+ /**
+ * @return Conversion to Number type.
+ */
+ Number toNumber() const; // ECMA 9.3
+ /**
+ * @return Conversion to double. 0.0 if conversion failed.
+ */
+ double round() const;
+ /**
+ * @return Conversion to Number type containing an integer value.
+ */
+ Number toInteger() const; // ECMA 9.4
+ /**
+ * @return Conversion to signed integer value.
+ */
+ int toInt32() const; // ECMA 9.5
+ /**
+ * @return Conversion to unsigned integer value.
+ */
+ unsigned int toUInt32() const; // ECMA 9.6
+ /**
+ * @return Conversion to unsigned short value.
+ */
+ unsigned short toUInt16() const; // ECMA 9.7
+ /**
+ * @return Conversion to String type.
+ */
+ String toString() const; // ECMA 9.8
+ /**
+ * @return Conversion to Object type.
+ */
+ Object toObject() const; // ECMA 9.9
+
+ // Properties
+ /**
+ * Set the internal [[Prototype]] property of this object.
+ * @param p A prototype object.
+ */
+ void setPrototype(const KJSO &p);
+ /**
+ * Set the "prototype" property of this object. Different from
+ * the internal [[Prototype]] property.
+ * @param p A prototype object.
+ */
+ void setPrototypeProperty(const KJSO &p);
+ /**
+ * @return The internal [[prototype]] property.
+ */
+ KJSO prototype() const;
+ /**
+ * The internal [[Get]] method.
+ * @return The value of property p.
+ */
+ KJSO get(const UString &p) const;
+ /**
+ * The internal [[HasProperty]] method.
+ * @param p Property name.
+ * @param recursive Indicates whether prototypes are searched as well.
+ * @return Boolean value indicating whether the object already has a
+ * member with the given name p.
+ */
+ bool hasProperty(const UString &p, bool recursive = true) const;
+ /**
+ * The internal [[Put]] method. Sets the specified property to the value v.
+ * @param p Property name.
+ * @param v Value.
+ */
+ void put(const UString &p, const KJSO& v);
+ /**
+ * The internal [[CanPut]] method.
+ * @param p Property name.
+ * @return A boolean value indicating whether a [[Put]] operation with
+ * p succeed.
+ */
+ bool canPut(const UString &p) const;
+ /**
+ * The internal [[Delete]] method. Removes the specified property from
+ * the object.
+ * @param p Property name.
+ * @return True if the property was deleted successfully or didn't exist
+ * in the first place. False if the DontDelete attribute was set.
+ */
+ bool deleteProperty(const UString &p);
+ /**
+ * Same as above put() method except the additional attribute. Right now,
+ * this only works with native types as Host Objects don't reimplement
+ * this method.
+ * @param attr One of @ref KJS::Attribute.
+ */
+ void put(const UString &p, const KJSO& v, int attr);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * a double value.
+ */
+ void put(const UString &p, double d, int attr = None);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * an integer value.
+ */
+ void put(const UString &p, int i, int attr = None);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * an unsigned integer value.
+ */
+ void put(const UString &p, unsigned int u, int attr = None);
+
+ /**
+ * Reference method.
+ * @return Reference base if object is a reference. Throws
+ * a ReferenceError otherwise.
+ */
+ KJSO getBase() const;
+ /**
+ * Reference method.
+ * @return Property name of a reference. Null string if object is not
+ * a reference.
+ */
+ UString getPropertyName() const;
+ /**
+ * Reference method.
+ * @return Referenced value. This object if no reference.
+ */
+ KJSO getValue() const;
+ KJSO getValue(); /* TODO: remove in next version */
+ /**
+ * Reference method. Set referenced value to v.
+ */
+ ErrorType putValue(const KJSO& v);
+
+ /**
+ * @return True if object supports @ref executeCall() method. That's the
+ * case for all objects derived from FunctionType.
+ */
+ bool implementsCall() const;
+ /**
+ * Execute function implemented via the @ref Function::execute() method.
+ *
+ * Note: check availability via @ref implementsCall() beforehand.
+ * @param thisV Object serving as the 'this' value.
+ * @param args Pointer to the list of arguments or null.
+ * @return Result of the function call.
+ */
+ KJSO executeCall(const KJSO &thisV, const List *args);
+ KJSO executeCall(const KJSO &thisV, const List *args, const List *extraScope) const;
+
+ /**
+ * Set this object's constructor.
+ */
+ void setConstructor(KJSO c);
+
+ /**
+ * @return A Pointer to the internal implementation.
+ */
+ Imp *imp() const { return rep; }
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ protected:
+ /**
+ * Pointer to the internal implementation.
+ */
+ Imp *rep;
+
+ private:
+ void putArrayElement(const UString &p, const KJSO &v);
+ }; // end of KJSO
+
+ /**
+ * @short Base for all implementation classes.
+ */
+ class Imp {
+ friend class KJSO;
+ friend class Collector;
+ friend class ForInNode;
+ friend class Debugger;
+ public:
+ Imp();
+ public:
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
+ virtual Boolean toBoolean() const; // ECMA 9.2
+ virtual Number toNumber() const; // ECMA 9.3
+ virtual String toString() const; // ECMA 9.8
+ virtual Object toObject() const; // ECMA 9.9
+
+ // properties
+ virtual KJSO get(const UString &p) const;
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ virtual void put(const UString &p, const KJSO& v);
+ void put(const UString &p, const KJSO& v, int attr);
+ virtual bool canPut(const UString &p) const;
+ virtual bool deleteProperty(const UString &p);
+ virtual KJSO defaultValue(Type hint) const;
+
+ bool implementsCall() const;
+
+ /**
+ * @internal Reserved for mark & sweep garbage collection
+ */
+ virtual void mark(Imp *imp = 0L);
+ bool marked() const;
+
+ Type type() const { return typeInfo()->type; }
+ /**
+ * @return The TypeInfo struct describing this object.
+ */
+ virtual const TypeInfo* typeInfo() const { return &info; }
+
+ void setPrototype(const KJSO& p);
+ Imp* prototype() const { return proto; }
+ void setPrototypeProperty(const KJSO &p);
+ void setConstructor(const KJSO& c);
+
+ void* operator new(size_t);
+ void operator delete(void*);
+ /**
+ * @deprecated
+ */
+ void operator delete(void*, size_t);
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ protected:
+ virtual ~Imp();
+ private:
+ Imp(const Imp&);
+ Imp& operator=(const Imp&);
+ void putArrayElement(const UString &p, const KJSO& v);
+
+ /**
+ * Get the property names for this object. To be used by for .. in loops
+ * @return The (pointer to the) first element of a PropList, to be deleted
+ * by the caller, or 0 if there are no enumerable properties
+ */
+ PropList *propList(PropList *first = 0L, PropList *last = 0L,
+ bool recursive = true) const;
+
+ public:
+ // reference counting mechanism
+ inline Imp* ref() { refcount++; return this; }
+ inline bool deref() { return (!--refcount); }
+ unsigned int refcount;
+
+ private:
+ Property *prop;
+ Imp *proto;
+ static const TypeInfo info;
+
+ // reserved for memory managment - currently used as flags for garbage collection
+ // (prev != 0) = marked, (next != 0) = created, (next != this) = created and gc allowed
+ Imp *prev, *next;
+ // for future extensions
+ class ImpInternal;
+ ImpInternal *internal;
+
+ void setMarked(bool m);
+ void setGcAllowed(bool a);
+ bool gcAllowed() const;
+ void setCreated(bool c);
+ bool created() const;
+ };
+
+ /**
+ * @short General implementation class for Objects
+ */
+ class ObjectImp : public Imp {
+ friend class Object;
+ public:
+ ObjectImp(Class c);
+ ObjectImp(Class c, const KJSO &v);
+ ObjectImp(Class c, const KJSO &v, const KJSO &p);
+ virtual ~ObjectImp();
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ /**
+ * @internal Reimplemenation of @ref Imp::mark().
+ */
+ virtual void mark(Imp *imp = 0L);
+ private:
+ Class cl;
+ Imp *val;
+ };
+
+ /**
+ * @short Object class encapsulating an internal value.
+ */
+ class Object : public KJSO {
+ public:
+ Object(Imp *d);
+ Object(Class c = UndefClass);
+ Object(Class c, const KJSO& v);
+ Object(Class c, const KJSO& v, const Object& p);
+ virtual ~Object();
+ void setClass(Class c);
+ Class getClass() const;
+ void setInternalValue(const KJSO& v);
+ KJSO internalValue();
+ static Object create(Class c);
+ static Object create(Class c, const KJSO& val);
+ static Object create(Class c, const KJSO& val, const Object &p);
+ static Object dynamicCast(const KJSO &obj);
+ };
+
+ /**
+ * @short Implementation base class for Host Objects.
+ */
+ class HostImp : public Imp {
+ public:
+ HostImp();
+ virtual ~HostImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+
+ virtual Boolean toBoolean() const;
+ virtual String toString() const;
+
+ static const TypeInfo info;
+ };
+
+ class KJScriptImp;
+ /**
+ * The Global object represents the global namespace. It holds the native
+ * objects like String and functions like eval().
+ *
+ * It also serves as a container for variables created by the user, i.e.
+ * the statement
+ * <pre>
+ * var i = 2;
+ * </pre>
+ * will basically perform a Global::current().put("i", Number(2)); operation.
+ *
+ * @short Unique global object containing initial native properties.
+ */
+ class Global : public Object {
+ friend class KJScriptImp;
+ public:
+ /**
+ * Constructs a Global object. This is done by the interpreter once and
+ * there should be no need to create an instance on your own. Usually,
+ * you'll just want to access the current instance.
+ * For example like this:
+ * <pre>
+ * Global global(Global::current());
+ * KJSO proto = global.objectPrototype();
+ * </pre>
+ */
+ Global();
+ /**
+ * Destruct the Global object.
+ */
+ virtual ~Global();
+ /**
+ * @return A reference to the Global object belonging to the current
+ * interpreter instance.
+ */
+ static Global current();
+ /**
+ * @return A handle to Object.prototype.
+ */
+ KJSO objectPrototype() const;
+ /**
+ * @return A handle to Function.prototype.
+ */
+ KJSO functionPrototype() const;
+ /**
+ * Set a filter object that will intercept all put() and get() calls
+ * to the global object. If this object returns Undefined on get() the
+ * request will be passed on the global object.
+ * @deprecated
+ */
+ void setFilter(const KJSO &f);
+ /**
+ * Return a handle to the filter object (see @ref setFilter()).
+ * Null if no filter has been installed.
+ * @deprecated
+ */
+ KJSO filter() const;
+ /**
+ * Returns the extra user data set for this global object. Null by default.
+ * Typical usage if you need to query any info related to the currently
+ * running interpreter:
+ *
+ * MyMainWindow *m = (MyMainWindow*)Global::current().extra();
+ */
+ void *extra() const;
+ /**
+ * Set the extra user data for this global object. It's not used by the
+ * interpreter itself and can therefore be used to bind arbitrary data
+ * to each interpreter instance.
+ */
+ void setExtra(void *e);
+ private:
+ Global(void *);
+ void init();
+ void clear();
+ };
+
+ /**
+ * @short Factory methods for error objects.
+ */
+ class Error {
+ public:
+ /**
+ * Factory method for error objects. The error will be registered globally
+ * and the execution will continue as if a "throw" statement was
+ * encountered.
+ * @param e Type of error.
+ * @param m Optional error message.
+ * @param l Optional line number.
+ */
+ static KJSO create(ErrorType e, const char *m = 0, int l = -1);
+ /**
+ * Same as above except the different return type (which is not casted
+ * here).
+ */
+ static Object createObject(ErrorType e, const char *m = 0, int l = -1);
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/object_object.cpp b/JavaScriptCore/kjs/object_object.cpp
new file mode 100644
index 0000000..80f98ed
--- /dev/null
+++ b/JavaScriptCore/kjs/object_object.cpp
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "object_object.h"
+#include "types.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+ObjectObject::ObjectObject(const Object &funcProto, const Object &objProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.2.3.1
+ setPrototypeProperty(objProto);
+}
+
+Completion ObjectObject::execute(const List &args)
+{
+ KJSO result;
+
+ List argList;
+ if (args.isEmpty()) {
+ result = construct(argList);
+ } else {
+ KJSO arg = args[0];
+ if (arg.isA(NullType) || arg.isA(UndefinedType)) {
+ argList.append(arg);
+ result = construct(argList);
+ } else
+ result = arg.toObject();
+ }
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.2.2
+Object ObjectObject::construct(const List &args)
+{
+ // if no arguments have been passed ...
+ if (args.isEmpty())
+ return Object::create(ObjectClass);
+
+ KJSO arg = *args.begin();
+ Object obj = Object::dynamicCast(arg);
+ if (!obj.isNull()) {
+ /* TODO: handle host objects */
+ return obj;
+ }
+
+ switch (arg.type()) {
+ case StringType:
+ case BooleanType:
+ case NumberType:
+ return arg.toObject();
+ default:
+ assert(!"unhandled switch case in ObjectConstructor");
+ case NullType:
+ case UndefinedType:
+ return Object::create(ObjectClass);
+ }
+}
+
+ObjectPrototype::ObjectPrototype()
+ : ObjectImp(ObjectClass)
+{
+ // the spec says that [[Property]] should be `null'.
+ // Not sure if Null or C's NULL is needed.
+}
+
+bool ObjectPrototype::hasProperty(const UString &p, bool recursive) const
+{
+ if ( p == "toString" || p == "valueOf" )
+ return true;
+ return /*recursive &&*/ ObjectImp::hasProperty(p, recursive);
+}
+
+KJSO ObjectPrototype::get(const UString &p) const
+{
+ if (p == "toString")
+ return Function(new ObjectProtoFunc(ToString));
+ else if (p == "valueOf")
+ return Function(new ObjectProtoFunc(ValueOf));
+ else
+ return Imp::get(p);
+}
+
+ObjectProtoFunc::ObjectProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.2.4.2 + 15.2.4.3
+Completion ObjectProtoFunc::execute(const List &)
+{
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ /* TODO: what to do with non-objects. Is this possible at all ? */
+ // Yes, this happens with Host Object at least (David)
+ if (thisObj.isNull()) {
+ UString str = "[object ";
+ str += thisValue().isNull() ? "null" : thisValue().imp()->typeInfo()->name;
+ str += "]";
+ return Completion(ReturnValue, String(str));
+ }
+
+ // valueOf()
+ if (id == ObjectPrototype::ValueOf)
+ /* TODO: host objects*/
+ return Completion(ReturnValue, thisObj);
+
+ // toString()
+ UString str;
+ switch(thisObj.getClass()) {
+ case StringClass:
+ str = "[object String]";
+ break;
+ case BooleanClass:
+ str = "[object Boolean]";
+ break;
+ case NumberClass:
+ str = "[object Number]";
+ break;
+ case ObjectClass:
+ {
+ str = "[object ";
+ str += thisValue().isNull() ? "Object" : thisValue().imp()->typeInfo()->name;
+ str += "]";
+ break;
+ }
+ default:
+ str = "[undefined object]";
+ }
+
+ return Completion(ReturnValue, String(str));
+}
diff --git a/JavaScriptCore/kjs/object_object.h b/JavaScriptCore/kjs/object_object.h
new file mode 100644
index 0000000..7f8703e
--- /dev/null
+++ b/JavaScriptCore/kjs/object_object.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _OBJECT_OBJECT_H_
+#define _OBJECT_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ObjectObject : public ConstructorImp {
+ public:
+ ObjectObject(const Object &funcProto, const Object &objProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class ObjectPrototype : public ObjectImp {
+ public:
+ ObjectPrototype();
+ bool hasProperty(const UString &p, bool recursive) const;
+ KJSO get(const UString &p) const;
+ enum { ToString, ValueOf };
+ };
+
+ class ObjectProtoFunc : public InternalFunctionImp {
+ public:
+ ObjectProtoFunc(int i);
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/operations.cpp b/JavaScriptCore/kjs/operations.cpp
new file mode 100644
index 0000000..95e6022
--- /dev/null
+++ b/JavaScriptCore/kjs/operations.cpp
@@ -0,0 +1,224 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifndef HAVE_FLOAT_H /* just for !Windows */
+#define HAVE_FLOAT_H 0
+#define HAVE_FUNC__FINITE 0
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+
+#ifndef HAVE_FUNC_ISINF
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#endif /* HAVE_FUNC_ISINF */
+
+#if HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+#include "object.h"
+#include "types.h"
+#include "operations.h"
+
+using namespace KJS;
+
+bool KJS::isNaN(double d)
+{
+#ifdef HAVE_FUNC_ISNAN
+ return isnan(d);
+#elif defined HAVE_FLOAT_H
+ return _isnan(d) != 0;
+#else
+ return !(d == d);
+#endif
+}
+
+bool KJS::isInf(double d)
+{
+#if defined(HAVE_FUNC_ISINF)
+ return isinf(d);
+#elif HAVE_FUNC_FINITE
+ return finite(d) == 0 && d == d;
+#elif HAVE_FUNC__FINITE
+ return _finite(d) == 0 && d == d;
+#else
+ return false;
+#endif
+}
+
+// ECMA 11.9.3
+bool KJS::equal(const KJSO& v1, const KJSO& v2)
+{
+ Type t1 = v1.type();
+ Type t2 = v2.type();
+
+ if (t1 == t2) {
+ if (t1 == UndefinedType || t1 == NullType)
+ return true;
+ if (t1 == NumberType)
+ return (v1.toNumber().value() == v2.toNumber().value()); /* TODO: NaN, -0 ? */
+ if (t1 == StringType)
+ return (v1.toString().value() == v2.toString().value());
+ if (t1 == BooleanType)
+ return (v1.toBoolean().value() == v2.toBoolean().value());
+ if (t1 == HostType) {
+ KJSO h1 = v1.get("[[==]]");
+ KJSO h2 = v2.get("[[==]]");
+ if (!h1.isA(UndefinedType) && !h2.isA(UndefinedType))
+ return equal(h1, h2);
+ }
+ return (v1.imp() == v2.imp());
+ }
+
+ // different types
+ if ((t1 == NullType && t2 == UndefinedType) || (t1 == UndefinedType && t2 == NullType))
+ return true;
+ if (t1 == NumberType && t2 == StringType) {
+ Number n2 = v2.toNumber();
+ return equal(v1, n2);
+ }
+ if ((t1 == StringType && t2 == NumberType) || t1 == BooleanType) {
+ Number n1 = v1.toNumber();
+ return equal(n1, v2);
+ }
+ if (t2 == BooleanType) {
+ Number n2 = v2.toNumber();
+ return equal(v1, n2);
+ }
+ if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType) {
+ KJSO p2 = v2.toPrimitive();
+ return equal(v1, p2);
+ }
+ if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType)) {
+ KJSO p1 = v1.toPrimitive();
+ return equal(p1, v2);
+ }
+
+ return false;
+}
+
+bool KJS::strictEqual(const KJSO &v1, const KJSO &v2)
+{
+ Type t1 = v1.type();
+ Type t2 = v2.type();
+
+ if (t1 != t2)
+ return false;
+ if (t1 == UndefinedType || t1 == NullType)
+ return true;
+ if (t1 == NumberType) {
+ double n1 = v1.toNumber().value();
+ double n2 = v2.toNumber().value();
+ if (isNaN(n1) || isNaN(n2))
+ return false;
+ if (n1 == n2)
+ return true;
+ /* TODO: +0 and -0 */
+ return false;
+ } else if (t1 == StringType) {
+ return v1.toString().value() == v2.toString().value();
+ } else if (t2 == BooleanType) {
+ return v1.toBoolean().value() == v2.toBoolean().value();
+ }
+ if (v1.imp() == v2.imp())
+ return true;
+ /* TODO: joined objects */
+
+ return false;
+}
+
+int KJS::relation(const KJSO& v1, const KJSO& v2)
+{
+ KJSO p1 = v1.toPrimitive(NumberType);
+ KJSO p2 = v2.toPrimitive(NumberType);
+
+ if (p1.isA(StringType) && p2.isA(StringType))
+ return p1.toString().value() < p2.toString().value() ? 1 : 0;
+
+ Number n1 = p1.toNumber();
+ Number n2 = p2.toNumber();
+ /* TODO: check for NaN */
+ if (n1.value() == n2.value())
+ return 0;
+ /* TODO: +0, -0 and Infinity */
+ return (n1.value() < n2.value());
+}
+
+double KJS::max(double d1, double d2)
+{
+ /* TODO: check for NaN */
+ return (d1 > d2) ? d1 : d2;
+}
+
+double KJS::min(double d1, double d2)
+{
+ /* TODO: check for NaN */
+ return (d1 < d2) ? d1 : d2;
+}
+
+// ECMA 11.6
+KJSO KJS::add(const KJSO &v1, const KJSO &v2, char oper)
+{
+ KJSO p1 = v1.toPrimitive();
+ KJSO p2 = v2.toPrimitive();
+
+ if ((p1.isA(StringType) || p2.isA(StringType)) && oper == '+') {
+ String s1 = p1.toString();
+ String s2 = p2.toString();
+
+ UString s = s1.value() + s2.value();
+
+ return String(s);
+ }
+
+ Number n1 = p1.toNumber();
+ Number n2 = p2.toNumber();
+
+ if (oper == '+')
+ return Number(n1.value() + n2.value());
+ else
+ return Number(n1.value() - n2.value());
+}
+
+// ECMA 11.5
+KJSO KJS::mult(const KJSO &v1, const KJSO &v2, char oper)
+{
+ Number n1 = v1.toNumber();
+ Number n2 = v2.toNumber();
+
+ double result;
+
+ if (oper == '*')
+ result = n1.value() * n2.value();
+ else if (oper == '/')
+ result = n1.value() / n2.value();
+ else
+ result = fmod(n1.value(), n2.value());
+
+ return Number(result);
+}
diff --git a/JavaScriptCore/kjs/operations.h b/JavaScriptCore/kjs/operations.h
new file mode 100644
index 0000000..d3b0246
--- /dev/null
+++ b/JavaScriptCore/kjs/operations.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_OPERATIONS_H_
+#define _KJS_OPERATIONS_H_
+
+#include "object.h"
+
+namespace KJS {
+
+ /**
+ * @return True if d is not a number (platform support required).
+ */
+ bool isNaN(double d);
+ /**
+ * @return True if d is infinite (platform support required).
+ */
+ bool isInf(double d);
+ bool equal(const KJSO& v1, const KJSO& v2);
+ bool strictEqual(const KJSO &v1, const KJSO &v2);
+ /**
+ * This operator performs an abstract relational comparision of the two
+ * arguments that can be of arbitrary type. If possible, conversions to the
+ * string or number type will take place before the comparison.
+ *
+ * @return 1 if v1 is "less-than" v2, 0 if the relation is "greater-than-or-
+ * equal". -1 if the result is undefined.
+ */
+ int relation(const KJSO& v1, const KJSO& v2);
+ double max(double d1, double d2);
+ double min(double d1, double d2);
+ /**
+ * Additive operator. Either performs an addition or substraction of v1
+ * and v2.
+ * @param oper '+' or '-' for an addition or substraction, respectively.
+ * @return The result of the operation.
+ */
+ KJSO add(const KJSO &v1, const KJSO &v2, char oper);
+ /**
+ * Multiplicative operator. Either multiplies/divides v1 and v2 or
+ * calculates the remainder from an division.
+ * @param oper '*', '/' or '%' for a multiplication, division or
+ * modulo operation.
+ * @return The result of the operation.
+ */
+ KJSO mult(const KJSO &v1, const KJSO &v2, char oper);
+
+};
+
+#endif
diff --git a/JavaScriptCore/kjs/regexp.cpp b/JavaScriptCore/kjs/regexp.cpp
new file mode 100644
index 0000000..84368e7
--- /dev/null
+++ b/JavaScriptCore/kjs/regexp.cpp
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+
+#include "object.h"
+#include "regexp.h"
+
+using namespace KJS;
+
+RegExp::RegExp(const UString &p, int f)
+ : pattern(p), flags(f)
+{
+#ifdef REG_EXTENDED
+ regcomp(&preg, p.ascii(), REG_EXTENDED);
+#else
+ regcomp(&preg, p.ascii(), 0);
+#endif
+ /* TODO use flags, check for errors */
+}
+
+RegExp::~RegExp()
+{
+ /* TODO: is this really okay after an error ? */
+ regfree(&preg);
+}
+
+UString RegExp::match(const UString &s, int i, int *pos)
+{
+ regmatch_t rmatch[10];
+
+ if (i < 0)
+ i = 0;
+
+ if (i > s.size() || s.isNull() ||
+ regexec(&preg, s.ascii() + i, 10, rmatch, 0)) {
+ if (pos)
+ *pos = -1;
+ return UString::null;
+ }
+
+ if (pos)
+ *pos = rmatch[0].rm_so + i;
+ return s.substr(rmatch[0].rm_so + i, rmatch[0].rm_eo - rmatch[0].rm_so);
+}
+
+bool RegExp::test(const UString &s, int)
+{
+ int r = regexec(&preg, s.ascii(), 0, 0, 0);
+
+ return r == 0;
+}
diff --git a/JavaScriptCore/kjs/regexp.h b/JavaScriptCore/kjs/regexp.h
new file mode 100644
index 0000000..9a4b2b2
--- /dev/null
+++ b/JavaScriptCore/kjs/regexp.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJS_REGEXP_H_
+#define _KJS_REGEXP_H_
+
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef HAVE_PCREPOSIX
+#include <pcreposix.h>
+#else // POSIX regex - not so good...
+extern "C" { // bug with some libc5 distributions
+#include <regex.h>
+}
+#endif //HAVE_PCREPOSIX
+
+#include "ustring.h"
+
+namespace KJS {
+
+ class RegExp {
+ public:
+ enum { None, Global, IgnoreCase, Multiline };
+ RegExp(const UString &p, int f = None);
+ ~RegExp();
+ UString match(const UString &s, int i = -1, int *pos = 0L);
+ bool test(const UString &s, int i = -1);
+ private:
+ const UString &pattern;
+ int flags;
+ regex_t preg;
+
+ RegExp();
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/regexp_object.cpp b/JavaScriptCore/kjs/regexp_object.cpp
new file mode 100644
index 0000000..b7e6b12
--- /dev/null
+++ b/JavaScriptCore/kjs/regexp_object.cpp
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "internal.h"
+#include "regexp.h"
+#include "regexp_object.h"
+
+using namespace KJS;
+
+RegExpObject::RegExpObject(const Object& funcProto, const Object ®Proto)
+ : ConstructorImp(funcProto, 2)
+{
+ // ECMA 15.10.5.1 RegExp.prototype
+ setPrototypeProperty(regProto);
+}
+
+// ECMA 15.9.2
+Completion RegExpObject::execute(const List &)
+{
+ return Completion(ReturnValue, Undefined());
+}
+
+// ECMA 15.9.3
+Object RegExpObject::construct(const List &args)
+{
+ /* TODO: regexp arguments */
+ String p = args[0].toString();
+ String f = args[1].toString();
+ UString flags = f.value();
+
+ RegExpImp *dat = new RegExpImp();
+ Object obj(dat); // protect from GC
+
+ bool global = (flags.find("g") >= 0);
+ bool ignoreCase = (flags.find("i") >= 0);
+ bool multiline = (flags.find("m") >= 0);
+ /* TODO: throw an error on invalid flags */
+
+ dat->put("global", Boolean(global));
+ dat->put("ignoreCase", Boolean(ignoreCase));
+ dat->put("multiline", Boolean(multiline));
+
+ dat->put("source", String(p.value()));
+ dat->put("lastIndex", 0, DontDelete | DontEnum);
+
+ dat->setRegExp(new RegExp(p.value() /* TODO flags */));
+ obj.setClass(RegExpClass);
+ obj.setPrototype(Global::current().get("[[RegExp.prototype]]"));
+
+ return obj;
+}
+
+// ECMA 15.9.4
+RegExpPrototype::RegExpPrototype(const Object& proto)
+ : ObjectImp(RegExpClass, String(""), proto)
+{
+ // The constructor will be added later in RegExpObject's constructor
+}
+
+KJSO RegExpPrototype::get(const UString &p) const
+{
+ int id = -1;
+ if (p == "exec")
+ id = RegExpProtoFunc::Exec;
+ else if (p == "test")
+ id = RegExpProtoFunc::Test;
+ else if (p == "toString")
+ id = RegExpProtoFunc::ToString;
+
+ if (id >= 0)
+ return Function(new RegExpProtoFunc(id));
+ else
+ return Imp::get(p);
+}
+
+Completion RegExpProtoFunc::execute(const List &args)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ if (thisObj.getClass() != RegExpClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ RegExp *re = static_cast<RegExpImp*>(thisObj.imp())->regExp();
+ String s;
+ KJSO lastIndex, tmp;
+ UString str;
+ int length, i;
+ switch (id) {
+ case Exec:
+ case Test:
+ s = args[0].toString();
+ length = s.value().size();
+ lastIndex = thisObj.get("lastIndex");
+ i = lastIndex.toInt32();
+ tmp = thisObj.get("global");
+ if (tmp.toBoolean().value() == false)
+ i = 0;
+ if (i < 0 || i > length) {
+ thisObj.put("lastIndex", 0);
+ result = Null();
+ break;
+ }
+ str = re->match(s.value(), i);
+ if (id == Test) {
+ result = Boolean(str.size() != 0);
+ break;
+ }
+ /* TODO complete */
+ result = String(str);
+ break;
+ case ToString:
+ s = thisObj.get("source").toString();
+ str = "/";
+ str += s.value();
+ str += "/";
+ result = String(str);
+ break;
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/JavaScriptCore/kjs/regexp_object.h b/JavaScriptCore/kjs/regexp_object.h
new file mode 100644
index 0000000..a5af288
--- /dev/null
+++ b/JavaScriptCore/kjs/regexp_object.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _REGEXP_OBJECT_H_
+#define _REGEXP_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class RegExpObject : public ConstructorImp {
+ public:
+ RegExpObject(const Object& funcProto, const Object ®Proto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class RegExpPrototype : public ObjectImp {
+ public:
+ RegExpPrototype(const Object& proto);
+ KJSO get(const UString &p) const;
+ };
+
+ class RegExpProtoFunc : public InternalFunctionImp {
+ public:
+ RegExpProtoFunc(int i) : id(i) { }
+ Completion execute(const List &);
+ enum { Exec, Test, ToString };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp
new file mode 100644
index 0000000..8e088bc
--- /dev/null
+++ b/JavaScriptCore/kjs/string_object.cpp
@@ -0,0 +1,419 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "regexp.h"
+#include "string_object.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+StringObject::StringObject(const Object &funcProto, const Object &stringProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.5.3.1 String.prototype
+ setPrototypeProperty(stringProto);
+}
+
+KJSO StringObject::get(const UString &p) const
+{
+ if (p == "fromCharCode")
+ return Function(new StringObjectFunc());
+ else
+ return Imp::get(p);
+}
+
+// ECMA 15.5.1
+Completion StringObject::execute(const List &args)
+{
+ KJSO v;
+ String s;
+
+ if (args.isEmpty())
+ s = String("");
+ else {
+ v = args[0];
+ s = v.toString();
+ }
+
+ return Completion(ReturnValue, s);
+}
+
+// ECMA 15.5.2
+Object StringObject::construct(const List &args)
+{
+ String s;
+ if (args.size() > 0)
+ s = args.begin()->toString();
+ else
+ s = String("");
+
+ return Object::create(StringClass, s);
+}
+
+// ECMA 15.5.3.2 fromCharCode()
+Completion StringObjectFunc::execute(const List &args)
+{
+ UString s;
+ if (args.size()) {
+ UChar *buf = new UChar[args.size()];
+ UChar *p = buf;
+ ListIterator it = args.begin();
+ while (it != args.end()) {
+ unsigned short u = it->toUInt16();
+ *p++ = UChar(u);
+ it++;
+ }
+ s = UString(buf, args.size(), false);
+ } else
+ s = "";
+
+ return Completion(ReturnValue, String(s));
+}
+
+// ECMA 15.5.4
+StringPrototype::StringPrototype(const Object& proto)
+ : ObjectImp(StringClass, String(""), proto)
+{
+ // The constructor will be added later in StringObject's constructor
+}
+
+KJSO StringPrototype::get(const UString &p) const
+{
+ int id;
+
+ if (p == "toString")
+ id = StringProtoFunc::ToString;
+ else if (p == "valueOf")
+ id = StringProtoFunc::ValueOf;
+ else if (p == "charAt")
+ id = StringProtoFunc::CharAt;
+ else if (p == "charCodeAt")
+ id = StringProtoFunc::CharCodeAt;
+ else if (p == "indexOf")
+ id = StringProtoFunc::IndexOf;
+ else if (p == "lastIndexOf")
+ id = StringProtoFunc::LastIndexOf;
+ else if (p == "match")
+ id = StringProtoFunc::Match;
+ else if (p == "replace")
+ id = StringProtoFunc::Replace;
+ else if (p == "search")
+ id = StringProtoFunc::Search;
+ else if (p == "split")
+ id = StringProtoFunc::Split;
+ else if (p == "substr")
+ id = StringProtoFunc::Substr;
+ else if (p == "substring")
+ id = StringProtoFunc::Substring;
+ else if (p == "toLowerCase")
+ id = StringProtoFunc::ToLowerCase;
+ else if (p == "toUpperCase")
+ id = StringProtoFunc::ToUpperCase;
+#ifndef KJS_PURE_ECMA
+ else if (p == "big")
+ id = StringProtoFunc::Big;
+ else if (p == "small")
+ id = StringProtoFunc::Small;
+ else if (p == "blink")
+ id = StringProtoFunc::Blink;
+ else if (p == "bold")
+ id = StringProtoFunc::Bold;
+ else if (p == "fixed")
+ id = StringProtoFunc::Fixed;
+ else if (p == "italics")
+ id = StringProtoFunc::Italics;
+ else if (p == "strike")
+ id = StringProtoFunc::Strike;
+ else if (p == "sub")
+ id = StringProtoFunc::Sub;
+ else if (p == "sup")
+ id = StringProtoFunc::Sup;
+ else if (p == "fontcolor")
+ id = StringProtoFunc::Fontcolor;
+ else if (p == "fontsize")
+ id = StringProtoFunc::Fontsize;
+ else if (p == "anchor")
+ id = StringProtoFunc::Anchor;
+ else if (p == "link")
+ id = StringProtoFunc::Link;
+#endif
+ else
+ return Imp::get(p);
+
+ return Function(new StringProtoFunc(id));
+}
+
+StringProtoFunc::StringProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.5.4.2 - 15.5.4.20
+Completion StringProtoFunc::execute(const List &args)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // toString and valueOf are no generic function.
+ if (id == ToString || id == ValueOf) {
+ if (thisObj.isNull() || thisObj.getClass() != StringClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+ }
+
+ String s2;
+ Number n, m;
+ UString u, u2, u3;
+ int pos, p0, i;
+ double d, d2;
+ KJSO v = thisObj.internalValue();
+ String s = v.toString();
+ int len = s.value().size();
+ KJSO a0 = args[0];
+ KJSO a1 = args[1];
+
+ switch (id) {
+ case ToString:
+ case ValueOf:
+ result = v.toString();
+ break;
+ case CharAt:
+ n = a0.toInteger();
+ pos = (int) n.value();
+ if (pos < 0 || pos >= len)
+ u = "";
+ else
+ u = s.value().substr(pos, 1);
+ result = String(u);
+ break;
+ case CharCodeAt:
+ n = a0.toInteger();
+ pos = (int) n.value();
+ if (pos < 0 || pos >= len)
+ d = NaN;
+ else {
+ UChar c = s.value()[pos];
+ d = (c.high() << 8) + c.low();
+ }
+ result = Number(d);
+ break;
+ case IndexOf:
+ s2 = a0.toString();
+ if (a1.isA(UndefinedType))
+ pos = 0;
+ else
+ pos = a1.toInteger().intValue();
+ d = s.value().find(s2.value(), pos);
+ result = Number(d);
+ break;
+ case LastIndexOf:
+ s2 = a0.toString();
+ if (a1.isA(UndefinedType))
+ pos = len;
+ else
+ pos = a1.toInteger().intValue();
+ d = s.value().rfind(s2.value(), pos);
+ result = Number(d);
+ break;
+ case Match:
+ case Search:
+ u = s.value();
+ if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
+ s2 = a0.get("source").toString();
+ RegExp reg(s2.value());
+ UString mstr = reg.match(u, -1, &pos);
+ if (id == Search) {
+ result = Number(pos);
+ break;
+ }
+ if (mstr.isNull()) {
+ result = Null();
+ break;
+ }
+ /* TODO return an array, with the matches, etc. */
+ result = String(mstr);
+ } else
+ {
+ printf("Match/Search. Argument is not a RegExp - returning Undefined\n");
+ result = Undefined(); // No idea what to do here
+ }
+ break;
+ case Replace:
+ /* TODO: this is just a hack to get the most common cases going */
+ u = s.value();
+ if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
+ s2 = a0.get("source").toString();
+ RegExp reg(s2.value());
+ UString mstr = reg.match(u, -1, &pos);
+ len = mstr.size();
+ } else {
+ s2 = a0.toString();
+ u2 = s2.value();
+ pos = u.find(u2);
+ len = u2.size();
+ }
+ if (pos == -1)
+ result = s;
+ else {
+ u3 = u.substr(0, pos) + a1.toString().value() +
+ u.substr(pos + len);
+ result = String(u3);
+ }
+ break;
+ case Split:
+ result = Object::create(ArrayClass);
+ u = s.value();
+ i = p0 = 0;
+ d = a1.isDefined() ? a1.toInteger().intValue() : -1; // optional max number
+ if (a0.isA(ObjectType) && Object(a0.imp()).getClass() == RegExpClass) {
+ RegExp reg(a0.get("source").toString().value());
+ if (u.isEmpty() && !reg.match(u, 0).isNull()) {
+ // empty string matched by regexp -> empty array
+ result.put("length", 0);
+ break;
+ }
+ int mpos;
+ pos = 0;
+ while (1) {
+ /* TODO: back references */
+ UString mstr = reg.match(u, pos, &mpos);
+ if (mpos < 0)
+ break;
+ pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
+ if (mpos != p0 || !mstr.isEmpty()) {
+ result.put(UString::from(i), String(u.substr(p0, mpos-p0)));
+ p0 = mpos + mstr.size();
+ i++;
+ }
+ }
+ } else if (a0.isDefined()) {
+ u2 = a0.toString().value();
+ if (u2.isEmpty()) {
+ if (u.isEmpty()) {
+ // empty separator matches empty string -> empty array
+ put("length", 0);
+ break;
+ } else {
+ while (i != d && i < u.size())
+ result.put(UString::from(i++), String(u.substr(p0++, 1)));
+ }
+ } else {
+ while (i != d && (pos = u.find(u2, p0)) >= 0) {
+ result.put(UString::from(i), String(u.substr(p0, pos-p0)));
+ p0 = pos + u2.size();
+ i++;
+ }
+ }
+ }
+ // add remaining string, if any
+ if (i != d && (p0 < len || i == 0))
+ result.put(UString::from(i++), String(u.substr(p0)));
+ result.put("length", i);
+ break;
+ case Substr:
+ n = a0.toInteger();
+ m = a1.toInteger();
+ if (n.value() >= 0)
+ d = n.value();
+ else
+ d = max(len + n.value(), 0);
+ if (a1.isA(UndefinedType))
+ d2 = len - d;
+ else
+ d2 = min(max(m.value(), 0), len - d);
+ result = String(s.value().substr((int)d, (int)d2));
+ break;
+ case Substring:
+ n = a0.toInteger();
+ m = a1.toInteger();
+ d = min(max(n.value(), 0), len);
+ if (a1.isA(UndefinedType))
+ d2 = len - d;
+ else {
+ d2 = min(max(m.value(), 0), len);
+ d2 = max(d2-d, 0);
+ }
+ result = String(s.value().substr((int)d, (int)d2));
+ break;
+ case ToLowerCase:
+ u = UString(s.value());
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toLower();
+ result = String(u);
+ break;
+ case ToUpperCase:
+ u = UString(s.value());
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toUpper();
+ result = String(u);
+ break;
+#ifndef KJS_PURE_ECMA
+ case Big:
+ result = String("<BIG>" + s.value() + "</BIG>");
+ break;
+ case Small:
+ result = String("<SMALL>" + s.value() + "</SMALL>");
+ break;
+ case Blink:
+ result = String("<BLINK>" + s.value() + "</BLINK>");
+ break;
+ case Bold:
+ result = String("<B>" + s.value() + "</B>");
+ break;
+ case Fixed:
+ result = String("<TT>" + s.value() + "</TT>");
+ break;
+ case Italics:
+ result = String("<I>" + s.value() + "</I>");
+ break;
+ case Strike:
+ result = String("<STRIKE>" + s.value() + "</STRIKE>");
+ break;
+ case Sub:
+ result = String("<SUB>" + s.value() + "</SUB>");
+ break;
+ case Sup:
+ result = String("<SUP>" + s.value() + "</SUP>");
+ break;
+ case Fontcolor:
+ result = String("<FONT COLOR=" + a0.toString().value() + ">"
+ + s.value() + "</FONT>");
+ break;
+ case Fontsize:
+ result = String("<FONT SIZE=" + a0.toString().value() + ">"
+ + s.value() + "</FONT>");
+ break;
+ case Anchor:
+ result = String("<a name=" + a0.toString().value() + ">"
+ + s.value() + "</a>");
+ break;
+ case Link:
+ result = String("<a href=" + a0.toString().value() + ">"
+ + s.value() + "</a>");
+ break;
+#endif
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/JavaScriptCore/kjs/string_object.h b/JavaScriptCore/kjs/string_object.h
new file mode 100644
index 0000000..5396750
--- /dev/null
+++ b/JavaScriptCore/kjs/string_object.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _STRING_OBJECT_H_
+#define _STRING_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class StringObject : public ConstructorImp {
+ public:
+ StringObject(const Object &funcProto, const Object &stringProto);
+ KJSO get(const UString &p) const;
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class StringObjectFunc : public InternalFunctionImp {
+ public:
+ Completion execute(const List &);
+ };
+
+ class StringPrototype : public ObjectImp {
+ public:
+ StringPrototype(const Object& proto);
+ KJSO get(const UString &p) const;
+ };
+
+ class StringProtoFunc : public InternalFunctionImp {
+ public:
+ StringProtoFunc(int i);
+ Completion execute(const List &);
+
+ enum { ToString, ValueOf, CharAt, CharCodeAt, IndexOf, LastIndexOf,
+ Match, Replace, Search, Slice, Split,
+ Substr, Substring, FromCharCode, ToLowerCase, ToUpperCase
+#ifndef KJS_PURE_ECMA
+ , Big, Small, Blink, Bold, Fixed, Italics, Strike, Sub, Sup,
+ Fontcolor, Fontsize, Anchor, Link
+#endif
+ };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/JavaScriptCore/kjs/test.js b/JavaScriptCore/kjs/test.js
new file mode 100644
index 0000000..f5bbf5b
--- /dev/null
+++ b/JavaScriptCore/kjs/test.js
@@ -0,0 +1,29 @@
+var i = 0;
+
+function sum(a, b)
+{
+ debug("inside test()");
+ i = i + 1;
+ debug(a);
+ debug(b);
+ return a + b;
+}
+
+s = sum(10, sum(20, 30));
+debug("s = " + s);
+debug("i = " + i);
+
+var a = new Array(11, 22, 33, 44);
+a.length = 2;
+a[4] = 'apple';
+
+for(i = 0; i != a.length; i++)
+ debug("a[" + i + "] = " + a[i]);
+
+var b = new Boolean(1==1);
+b.toString=Object.prototype.toString;
+debug("b = " + b.toString());
+
+// regular expression
+rx = /b*c/;
+debug(rx.exec("abbbcd"));
diff --git a/JavaScriptCore/kjs/testkjs.cpp b/JavaScriptCore/kjs/testkjs.cpp
new file mode 100644
index 0000000..afb04b0d
--- /dev/null
+++ b/JavaScriptCore/kjs/testkjs.cpp
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+
+#include "object.h"
+#include "types.h"
+#include "internal.h"
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ // create interpreter
+ KJScript *kjs = new KJScript();
+
+ // add debug() function
+ kjs->enableDebug();
+
+ const int BufferSize = 100000;
+ char code[BufferSize];
+
+ bool ret = true;
+ for (int i = 1; i < argc; i++) {
+ const char *file = argv[i];
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return -1;
+ }
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ // run
+ ret = ret && kjs->evaluate(code);
+ if (kjs->errorType() != 0)
+ printf("%s returned: %s\n", file, kjs->errorMsg());
+ else if (kjs->returnValue())
+ printf("returned a value\n");
+
+ fclose(f);
+ }
+
+ delete kjs;
+
+#ifdef KJS_DEBUG_MEM
+ printf("List::count = %d\n", KJS::List::count);
+ assert(KJS::List::count == 0);
+ printf("Imp::count = %d\n", KJS::Imp::count);
+ assert(KJS::Imp::count == 0);
+#endif
+
+ fprintf(stderr, "OK.\n");
+ return ret;
+}
diff --git a/JavaScriptCore/kjs/types.cpp b/JavaScriptCore/kjs/types.cpp
new file mode 100644
index 0000000..682e607
--- /dev/null
+++ b/JavaScriptCore/kjs/types.cpp
@@ -0,0 +1,299 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "nodes.h"
+
+using namespace KJS;
+
+Undefined::Undefined() : KJSO(UndefinedImp::staticUndefined) { }
+
+Undefined::~Undefined() { }
+
+Null::Null() : KJSO(NullImp::staticNull) { }
+
+Null::~Null() { }
+
+Boolean::Boolean(bool b)
+ : KJSO(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
+{
+}
+
+Boolean::Boolean(BooleanImp *i) : KJSO(i) { }
+
+Boolean::~Boolean() { }
+
+bool Boolean::value() const
+{
+ assert(rep);
+ return ((BooleanImp*)rep)->value();
+}
+
+Number::Number(int i)
+ : KJSO(new NumberImp(static_cast<double>(i))) { }
+
+Number::Number(unsigned int u)
+ : KJSO(new NumberImp(static_cast<double>(u))) { }
+
+Number::Number(double d)
+ : KJSO(new NumberImp(d)) { }
+
+Number::Number(long int l)
+ : KJSO(new NumberImp(static_cast<double>(l))) { }
+
+Number::Number(long unsigned int l)
+ : KJSO(new NumberImp(static_cast<double>(l))) { }
+
+Number::Number(NumberImp *i)
+ : KJSO(i) { }
+
+Number::~Number() { }
+
+double Number::value() const
+{
+ assert(rep);
+ return ((NumberImp*)rep)->value();
+}
+
+int Number::intValue() const
+{
+ assert(rep);
+ return (int)((NumberImp*)rep)->value();
+}
+
+bool Number::isNaN() const
+{
+ return KJS::isNaN(((NumberImp*)rep)->value());
+}
+
+bool Number::isInf() const
+{
+ return KJS::isInf(((NumberImp*)rep)->value());
+}
+
+String::String(const UString &s) : KJSO(new StringImp(UString(s))) { }
+
+String::String(StringImp *i) : KJSO(i) { }
+
+String::~String() { }
+
+UString String::value() const
+{
+ assert(rep);
+ return ((StringImp*)rep)->value();
+}
+
+Reference::Reference(const KJSO& b, const UString &p)
+ : KJSO(new ReferenceImp(b, p))
+{
+}
+
+Reference::~Reference()
+{
+}
+
+Completion::Completion(Imp *d) : KJSO(d) { }
+
+Completion::Completion(Compl c)
+ : KJSO(new CompletionImp(c, KJSO(), UString::null))
+{
+ if (c == Throw)
+ KJScriptImp::setException(new UndefinedImp());
+}
+
+Completion::Completion(Compl c, const KJSO& v, const UString &t)
+ : KJSO(new CompletionImp(c, v, t))
+{
+ if (c == Throw)
+ KJScriptImp::setException(v.imp());
+}
+
+Completion::~Completion() { }
+
+Compl Completion::complType() const
+{
+ assert(rep);
+ return ((CompletionImp*)rep)->completion();
+}
+
+bool Completion::isValueCompletion() const
+{
+ assert(rep);
+ return !((CompletionImp*)rep)->value().isNull();
+}
+
+KJSO Completion::value() const
+{
+ assert(isA(CompletionType));
+ return ((CompletionImp*)rep)->value();
+}
+
+UString Completion::target() const
+{
+ assert(rep);
+ return ((CompletionImp*)rep)->target();
+}
+
+ListIterator::ListIterator(const List &l)
+ : node(l.hook->next)
+{
+}
+
+List::List()
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ static KJSO *null = 0;
+ if (!null)
+ null = new KJSO();
+
+ hook = new ListNode(*null, 0L, 0L);
+ hook->next = hook;
+ hook->prev = hook;
+}
+
+List::~List()
+{
+#ifdef KJS_DEBUG_MEM
+ count--;
+#endif
+
+ clear();
+ delete hook;
+}
+
+void List::append(const KJSO& obj)
+{
+ ListNode *n = new ListNode(obj, hook->prev, hook);
+ hook->prev->next = n;
+ hook->prev = n;
+}
+
+void List::prepend(const KJSO& obj)
+{
+ ListNode *n = new ListNode(obj, hook, hook->next);
+ hook->next->prev = n;
+ hook->next = n;
+}
+
+void List::removeFirst()
+{
+ erase(hook->next);
+}
+
+void List::removeLast()
+{
+ erase(hook->prev);
+}
+
+void List::remove(const KJSO &obj)
+{
+ if (obj.isNull())
+ return;
+ ListNode *n = hook->next;
+ while (n != hook) {
+ if (n->member.imp() == obj.imp()) {
+ erase(n);
+ return;
+ }
+ n = n->next;
+ }
+}
+
+void List::clear()
+{
+ ListNode *n = hook->next;
+ while (n != hook) {
+ n = n->next;
+ delete n->prev;
+ }
+
+ hook->next = hook;
+ hook->prev = hook;
+}
+
+List *List::copy() const
+{
+ List *newList = new List();
+ ListIterator e = end();
+ ListIterator it = begin();
+
+ while(it != e) {
+ newList->append(*it);
+ ++it;
+ }
+
+ return newList;
+}
+
+void List::erase(ListNode *n)
+{
+ if (n != hook) {
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+ delete n;
+ }
+}
+
+int List::size() const
+{
+ int s = 0;
+ ListNode *node = hook;
+ while ((node = node->next) != hook)
+ s++;
+
+ return s;
+}
+
+KJSO List::at(int i) const
+{
+ if (i < 0 || i >= size())
+ return Undefined();
+
+ ListIterator it = begin();
+ int j = 0;
+ while ((j++ < i))
+ it++;
+
+ return *it;
+}
+
+List *List::emptyList = 0L;
+
+const List *List::empty()
+{
+ if (!emptyList)
+ emptyList = new List;
+#ifdef KJS_DEBUG_MEM
+ else
+ count++;
+#endif
+
+
+ return emptyList;
+}
diff --git a/JavaScriptCore/kjs/types.h b/JavaScriptCore/kjs/types.h
new file mode 100644
index 0000000..c1bfac6
--- /dev/null
+++ b/JavaScriptCore/kjs/types.h
@@ -0,0 +1,355 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include "object.h"
+
+namespace KJS {
+
+ /**
+ * @short Handle for an Undefined type.
+ */
+ class Undefined : public KJSO {
+ public:
+ Undefined();
+ virtual ~Undefined();
+ };
+
+ /**
+ * @short Handle for a Null type.
+ */
+ class Null : public KJSO {
+ public:
+ Null();
+ virtual ~Null();
+ };
+
+ class BooleanImp;
+ class NumberImp;
+ class StringImp;
+
+ /**
+ * @short Handle for a Boolean type.
+ */
+ class Boolean : public KJSO {
+ friend class BooleanImp;
+ public:
+ Boolean(bool b = false);
+ virtual ~Boolean();
+ bool value() const;
+ private:
+ Boolean(BooleanImp *i);
+ };
+
+ /**
+ * @short Handle for a Number type.
+ *
+ * Number is a handle for a number value. @ref KJSO::toPrimitive(),
+ * @ref KJSO::toBoolean(), @ref KJSO::toNumber(), @ref KJSO::toString() and
+ * @ref KJSO::toString() are re-implemented internally according to the
+ * specification.
+ *
+ * Example usage:
+ * <pre>
+ * Number a(2), b(3.0), c; // c defaults to 0.0
+ *
+ * c = a.value() * b.value(); // c will be 6.0 now
+ *
+ * String s = c.toString(); // s holds "6"
+ * </pre>
+ *
+ * Note the following implementation detail: Internally, the value is stored
+ * as a double and will be casted from and to other types when needed.
+ * This won't be noticable within a certain range of values but might produce
+ * unpredictable results when crossing these limits. In case this turns out
+ * to be a real problem for an application we might have to extend this class
+ * to behave more intelligently.
+ */
+ class Number : public KJSO {
+ friend class NumberImp;
+ public:
+ /**
+ * Construct a Number type from an integer.
+ */
+ Number(int i);
+ /**
+ * Construct a Number type from an unsigned integer.
+ */
+ Number(unsigned int u);
+ /**
+ * Construct a Number type from a double.
+ */
+ Number(double d = 0.0);
+ /**
+ * Construct a Number type from a long int.
+ */
+ Number(long int l);
+ /**
+ * Construct a Number type from a long unsigned int.
+ */
+ Number(long unsigned int l);
+ /**
+ * Destructor.
+ */
+ virtual ~Number();
+ /**
+ * @return The internally stored value.
+ */
+ double value() const;
+ /**
+ * Convenience function.
+ * @return The internally stored value converted to an int.
+ */
+ int intValue() const;
+ /**
+ * @return True is this is not a number (NaN).
+ */
+ bool isNaN() const;
+ /**
+ * @return True if Number is either +Infinity or -Infinity.
+ */
+ bool isInf() const;
+ private:
+ Number(NumberImp *i);
+ };
+
+ /**
+ * @short Handle for a String type.
+ */
+ class String : public KJSO {
+ friend class StringImp;
+ public:
+ String(const UString &s = "");
+ virtual ~String();
+ UString value() const;
+ private:
+ String(StringImp *i);
+ };
+
+ /**
+ * Completion objects are used to convey the return status and value
+ * from functions.
+ *
+ * See @ref FunctionImp::execute()
+ *
+ * @see FunctionImp
+ *
+ * @short Handle for a Completion type.
+ */
+ class Completion : public KJSO {
+ public:
+ Completion(Imp *d = 0L);
+ Completion(Compl c);
+ Completion(Compl c, const KJSO& v, const UString &t = UString::null);
+ virtual ~Completion();
+ Compl complType() const;
+ bool isValueCompletion() const;
+ KJSO value() const;
+ UString target() const;
+ };
+
+ class List;
+ class ListIterator;
+
+ /**
+ * @internal
+ */
+ class ListNode {
+ friend class List;
+ friend class ListIterator;
+ ListNode(KJSO obj, ListNode *p, ListNode *n)
+ : member(obj), prev(p), next(n) {};
+ KJSO member;
+ ListNode *prev, *next;
+ };
+
+ /**
+ * @short Iterator for @ref KJS::List objects.
+ */
+ class ListIterator {
+ friend class List;
+ ListIterator();
+ ListIterator(ListNode *n) : node(n) { }
+ public:
+ /**
+ * Construct an iterator that points to the first element of the list.
+ * @param l The list the iterator will operate on.
+ */
+ ListIterator(const List &list);
+ /**
+ * Assignment constructor.
+ */
+ ListIterator& operator=(const ListIterator &iterator)
+ { node=iterator.node; return *this; }
+ /**
+ * Copy constructor.
+ */
+ ListIterator(const ListIterator &i) : node(i.node) { }
+ /**
+ * Dereference the iterator.
+ * @return A pointer to the element the iterator operates on.
+ */
+ KJSO* operator->() const { return &node->member; }
+ // operator KJSO* () const { return node->member; }
+ KJSO operator*() const { return node->member; }
+ /**
+ * Conversion to @ref KJS::KJSO*
+ * @return A pointer to the element the iterator operates on.
+ */
+ // operator KJSO*() const { return node->member; }
+ /**
+ * Postfix increment operator.
+ * @return The element after the increment.
+ */
+ KJSO operator++() { node = node->next; return node->member; }
+ /**
+ * Prefix increment operator.
+ */
+ KJSO operator++(int) { const ListNode *n = node; ++*this; return n->member; }
+ /**
+ * Postfix decrement operator.
+ */
+ KJSO operator--() { node = node->prev; return node->member; }
+ /**
+ * Prefix decrement operator.
+ */
+ KJSO operator--(int) { const ListNode *n = node; --*this; return n->member; }
+ /**
+ * Compare the iterator with another one.
+ * @return True if the two iterators operate on the same list element.
+ * False otherwise.
+ */
+ bool operator==(const ListIterator &it) const { return (node==it.node); }
+ /**
+ * Check for inequality with another iterator.
+ * @return True if the two iterators operate on different list elements.
+ */
+ bool operator!=(const ListIterator &it) const { return (node!=it.node); }
+ private:
+ ListNode *node;
+ };
+
+ /**
+ * @short Native list type.
+ *
+ * List is a native ECMAScript type. List values are only used for
+ * intermediate results of expression evaluation and cannot be stored
+ * as properties of objects.
+ *
+ * The list is explicitly shared. Note that while copy() returns a deep
+ * copy of the list the referenced objects are still shared.
+ */
+ class List {
+ friend class ListIterator;
+ public:
+ /**
+ * Constructor.
+ */
+ List();
+ /**
+ * Destructor.
+ */
+ ~List();
+ /**
+ * Append an object to the end of the list.
+ *
+ * @param obj Pointer to object.
+ */
+ void append(const KJSO& obj);
+ /**
+ * Insert an object at the beginning of the list.
+ *
+ * @param obj Pointer to object.
+ */
+ void prepend(const KJSO& obj);
+ /**
+ * Remove the element at the beginning of the list.
+ */
+ void removeFirst();
+ /**
+ * Remove the element at the end of the list.
+ */
+ void removeLast();
+ /*
+ * Remove obj from list.
+ */
+ void remove(const KJSO &obj);
+ /**
+ * Remove all elements from the list.
+ */
+ void clear();
+ /**
+ * Returns a deep copy of the list. Ownership is passed to the user
+ * who is responsible for deleting the list then.
+ */
+ List *copy() const;
+ /**
+ * @return A @ref KJS::ListIterator pointing to the first element.
+ */
+ ListIterator begin() const { return ListIterator(hook->next); }
+ /**
+ * @return A @ref KJS::ListIterator pointing to the last element.
+ */
+ ListIterator end() const { return ListIterator(hook); }
+ /**
+ * @return true if the list is empty. false otherwise.
+ */
+ bool isEmpty() const { return (hook->prev == hook); }
+ /**
+ * @return the current size of the list.
+ */
+ int size() const;
+ /**
+ * Retrieve an element at an indexed position. If you want to iterate
+ * trough the whole list using @ref KJS::ListIterator will be faster.
+ *
+ * @param i List index.
+ * @return Return the element at position i. @ref KJS::Undefined if the
+ * index is out of range.
+ */
+ KJSO at(int i) const;
+ /**
+ * Equivalent to @ref at.
+ */
+ KJSO operator[](int i) const { return at(i); }
+ /**
+ * Returns a pointer to a static instance of an empty list. Useful if a
+ * function has a @ref KJS::List parameter.
+ */
+ static const List *empty();
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ private:
+ void erase(ListNode *n);
+ ListNode *hook;
+ static List *emptyList;
+ };
+
+}; // namespace
+
+
+#endif
diff --git a/JavaScriptCore/kjs/ustring.cpp b/JavaScriptCore/kjs/ustring.cpp
new file mode 100644
index 0000000..d547a04
--- /dev/null
+++ b/JavaScriptCore/kjs/ustring.cpp
@@ -0,0 +1,539 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include "ustring.h"
+#include "operations.h"
+
+namespace KJS {
+ extern const double NaN;
+ extern const double Inf;
+};
+
+using namespace KJS;
+
+CString::CString(const char *c)
+{
+ data = new char[strlen(c)+1];
+ strcpy(data, c);
+}
+
+CString::CString(const CString &b)
+{
+ data = new char[b.size()+1];
+ strcpy(data, b.c_str());
+}
+
+CString::~CString()
+{
+ delete [] data;
+}
+
+CString &CString::append(const CString &t)
+{
+ char *n;
+ if (data) {
+ n = new char[strlen(data)+t.size()+1];
+ strcpy(n, data);
+ } else {
+ n = new char[t.size()+1];
+ n[0] = '\0';
+ }
+ strcat(n, t.c_str());
+
+ delete [] data;
+ data = n;
+
+ return *this;
+}
+
+CString &CString::operator=(const char *c)
+{
+ if (data)
+ delete [] data;
+ data = new char[strlen(c)+1];
+ strcpy(data, c);
+
+ return *this;
+}
+
+CString &CString::operator=(const CString &str)
+{
+ if (this == &str)
+ return *this;
+
+ if (data)
+ delete [] data;
+ data = new char[str.size()+1];
+ strcpy(data, str.c_str());
+
+ return *this;
+}
+
+CString &CString::operator+=(const CString &str)
+{
+ return append(str.c_str());
+}
+
+int CString::size() const
+{
+ return strlen(data);
+}
+
+bool KJS::operator==(const KJS::CString& c1, const KJS::CString& c2)
+{
+ return (strcmp(c1.c_str(), c2.c_str()) == 0);
+}
+
+UChar UChar::null;
+UString::Rep UString::Rep::null = { 0, 0, 1 };
+UString UString::null;
+static char *statBuffer = 0L;
+
+UChar::UChar(const UCharReference &c)
+#ifdef KJS_SWAPPED_CHAR
+ : lo(c.low()), hi(c.high())
+#else
+ : hi(c.high()), lo(c.low())
+#endif
+{
+}
+
+UChar UChar::toLower() const
+{
+ if (islower(lo) && hi == 0)
+ return *this;
+
+ return UChar(0, tolower(lo));
+}
+
+UChar UChar::toUpper() const
+{
+ if (isupper(lo) && hi == 0)
+ return *this;
+
+ return UChar(0, toupper(lo));
+}
+
+UCharReference& UCharReference::operator=(UChar c)
+{
+ str->detach();
+ if (offset < str->rep->len)
+ *(str->rep->dat + offset) = c;
+ /* TODO: lengthen string ? */
+ return *this;
+}
+
+UChar& UCharReference::ref() const
+{
+ if (offset < str->rep->len)
+ return *(str->rep->dat + offset);
+ else
+ return UChar::null;
+}
+
+UString::Rep *UString::Rep::create(UChar *d, int l)
+{
+ Rep *r = new Rep;
+ r->dat = d;
+ r->len = l;
+ r->rc = 1;
+
+ return r;
+}
+
+UString::UString()
+{
+ null.rep = &Rep::null;
+ attach(&Rep::null);
+}
+
+UString::UString(char c)
+{
+ rep = Rep::create(new UChar(0, c), 1);
+}
+
+UString::UString(const char *c)
+{
+ attach(&Rep::null);
+ operator=(c);
+}
+
+UString::UString(const UChar *c, int length)
+{
+ UChar *d = new UChar[length];
+ memcpy(d, c, length * sizeof(UChar));
+ rep = Rep::create(d, length);
+}
+
+UString::UString(UChar *c, int length, bool copy)
+{
+ UChar *d;
+ if (copy) {
+ d = new UChar[length];
+ memcpy(d, c, length * sizeof(UChar));
+ } else
+ d = c;
+ rep = Rep::create(d, length);
+}
+
+UString::UString(const UString &b)
+{
+ attach(b.rep);
+}
+
+UString::~UString()
+{
+ release();
+}
+
+UString UString::from(int i)
+{
+ char buf[40];
+ sprintf(buf, "%d", i);
+
+ return UString(buf);
+}
+
+UString UString::from(unsigned int u)
+{
+ char buf[40];
+ sprintf(buf, "%u", u);
+
+ return UString(buf);
+}
+
+UString UString::from(double d)
+{
+ char buf[40];
+ sprintf(buf, "%.16g", d); // does the right thing
+ return UString(buf);
+}
+
+UString &UString::append(const UString &t)
+{
+ int l = size();
+ UChar *n = new UChar[l+t.size()];
+ memcpy(n, data(), l * sizeof(UChar));
+ memcpy(n+l, t.data(), t.size() * sizeof(UChar));
+ release();
+ rep = Rep::create(n, l + t.size());
+
+ return *this;
+}
+
+CString UString::cstring() const
+{
+ return CString(ascii());
+}
+
+char *UString::ascii() const
+{
+ if (statBuffer)
+ delete [] statBuffer;
+
+ statBuffer = new char[size()+1];
+ for(int i = 0; i < size(); i++)
+ statBuffer[i] = data()[i].lo;
+ statBuffer[size()] = '\0';
+
+ return statBuffer;
+}
+
+UString &UString::operator=(const char *c)
+{
+ release();
+ int l = c ? strlen(c) : 0;
+ UChar *d = new UChar[l];
+ for (int i = 0; i < l; i++)
+ d[i].lo = c[i];
+ rep = Rep::create(d, l);
+
+ return *this;
+}
+
+UString &UString::operator=(const UString &str)
+{
+ str.rep->ref();
+ release();
+ rep = str.rep;
+
+ return *this;
+}
+
+UString &UString::operator+=(const UString &s)
+{
+ return append(s);
+}
+
+bool UString::is8Bit() const
+{
+ const UChar *u = data();
+ for(int i = 0; i < size(); i++, u++)
+ if (u->hi)
+ return false;
+
+ return true;
+}
+
+UChar UString::operator[](int pos) const
+{
+ if (pos >= size())
+ return UChar::null;
+
+ return ((UChar *)data())[pos];
+}
+
+UCharReference UString::operator[](int pos)
+{
+ /* TODO: boundary check */
+ return UCharReference(this, pos);
+}
+
+double UString::toDouble() const
+{
+ double d;
+
+ if (!is8Bit())
+ return NaN;
+
+ CString str = cstring();
+ const char *c = str.c_str();
+
+ // skip leading white space
+ while (isspace(*c))
+ c++;
+
+ // empty string ?
+ if (*c == '\0')
+ return 0.0;
+
+ // hex number ?
+ if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
+ c++;
+ d = 0.0;
+ while (*(++c)) {
+ if (*c >= '0' && *c <= '9')
+ d = d * 16.0 + *c - '0';
+ else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
+ d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
+ else
+ break;
+ }
+ } else {
+ // regular number ?
+ char *end;
+ d = strtod(c, &end);
+ if (d != 0.0 || end != c) {
+ c = end;
+ } else {
+ // infinity ?
+ d = 1.0;
+ if (*c == '+')
+ c++;
+ else if (*c == '-') {
+ d = -1.0;
+ c++;
+ }
+ if (strncmp(c, "Infinity", 8) != 0)
+ return NaN;
+ d = d * Inf;
+ c += 8;
+ }
+ }
+
+ // allow trailing white space
+ while (isspace(*c))
+ c++;
+ if (*c != '\0')
+ d = NaN;
+
+ return d;
+}
+
+unsigned long UString::toULong(bool *ok) const
+{
+ double d = toDouble();
+ bool b = true;
+
+ if (isNaN(d) || d != static_cast<unsigned long>(d)) {
+ b = false;
+ d = 0;
+ }
+
+ if (ok)
+ *ok = b;
+
+ return static_cast<unsigned long>(d);
+}
+
+int UString::find(const UString &f, int pos) const
+{
+ if (isNull())
+ return -1;
+ long fsize = f.size() * sizeof(UChar);
+ if (pos < 0)
+ pos = 0;
+ const UChar *end = data() + size() - f.size();
+ for (const UChar *c = data() + pos; c <= end; c++)
+ if (!memcmp((void*)c, (void*)f.data(), fsize))
+ return (c-data());
+
+ return -1;
+}
+
+int UString::rfind(const UString &f, int pos) const
+{
+ if (isNull())
+ return -1;
+ if (pos + f.size() >= size())
+ pos = size() - f.size();
+ long fsize = f.size() * sizeof(UChar);
+ for (const UChar *c = data() + pos; c >= data(); c--) {
+ if (!memcmp((void*)c, (void*)f.data(), fsize))
+ return (c-data());
+ }
+
+ return -1;
+}
+
+UString UString::substr(int pos, int len) const
+{
+ if (isNull())
+ return UString();
+ if (pos < 0)
+ pos = 0;
+ else if (pos >= (int) size())
+ pos = size();
+ if (len < 0)
+ len = size();
+ if (pos + len >= (int) size())
+ len = size() - pos;
+
+ UChar *tmp = new UChar[len];
+ memcpy(tmp, data()+pos, len * sizeof(UChar));
+ UString result(tmp, len);
+ delete [] tmp;
+
+ return result;
+}
+
+void UString::attach(Rep *r)
+{
+ rep = r;
+ rep->ref();
+}
+
+void UString::detach()
+{
+ if (rep->rc > 1) {
+ int l = size();
+ UChar *n = new UChar[l];
+ memcpy(n, data(), l * sizeof(UChar));
+ release();
+ rep = Rep::create(n, l);
+ }
+}
+
+void UString::release()
+{
+ if (!rep->deref()) {
+ delete [] rep->dat;
+ delete rep;
+ }
+}
+
+bool KJS::operator==(const UChar &c1, const UChar &c2)
+{
+ return ((c1.lo == c2.lo) & (c1.hi == c2.hi));
+}
+
+bool KJS::operator==(const UString& s1, const UString& s2)
+{
+ if (s1.rep->len != s2.rep->len)
+ return false;
+
+ return (memcmp(s1.rep->dat, s2.rep->dat,
+ s1.rep->len * sizeof(UChar)) == 0);
+}
+
+bool KJS::operator==(const UString& s1, const char *s2)
+{
+ if (s2 == 0L && s1.isNull())
+ return true;
+
+ if (s1.size() != (int) strlen(s2))
+ return false;
+
+ const UChar *u = s1.data();
+ while (*s2) {
+ if (u->lo != *s2 || u->hi != 0)
+ return false;
+ s2++;
+ u++;
+ }
+
+ return true;
+}
+
+bool KJS::operator==(const char *s1, const UString& s2)
+{
+ return operator==(s2, s1);
+}
+
+bool KJS::operator<(const UString& s1, const UString& s2)
+{
+ int l1 = s1.size();
+ int l2 = s2.size();
+ const UChar *c1 = s1.data();
+ const UChar *c2 = s2.data();
+ int l = 0;
+ int le = l1 < l2 ? l1 : l2;
+ while (l < le && *c1 == *c2) {
+ c1++;
+ c2++;
+ l++;
+ }
+ if (l != le)
+ return (c1->unicode() < c2->unicode());
+
+ return (l1 < l2 && !(*c1 == *c2));
+}
+
+UString KJS::operator+(const UString& s1, const UString& s2)
+{
+ UString tmp(s1);
+ tmp.append(s2);
+
+ return tmp;
+}
diff --git a/JavaScriptCore/kjs/ustring.h b/JavaScriptCore/kjs/ustring.h
new file mode 100644
index 0000000..e897a34
--- /dev/null
+++ b/JavaScriptCore/kjs/ustring.h
@@ -0,0 +1,419 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_STRING_H_
+#define _KJS_STRING_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * @internal
+ */
+namespace DOM {
+ class DOMString;
+};
+class KJScript;
+class QString;
+class QConstString;
+
+#if defined(__GNUC__)
+#define KJS_PACKED __attribute__((__packed__))
+#else
+#define KJS_PACKED
+#endif
+
+namespace KJS {
+
+ class UCharReference;
+ class UString;
+
+ /**
+ * @short Unicode character.
+ *
+ * UChar represents a 16 bit Unicode character. It's internal data
+ * representation is compatible to XChar2b and QChar. It's therefore
+ * possible to exchange data with X and Qt with shallow copies.
+ */
+ struct UChar {
+ /**
+ * Construct a character with value 0.
+ */
+ UChar();
+ /**
+ * Construct a character with the value denoted by the arguments.
+ * @param h higher byte
+ * @param l lower byte
+ */
+ UChar(unsigned char h , unsigned char l);
+ /**
+ * Construct a character with the given value.
+ * @param u 16 bit Unicode value
+ */
+ UChar(unsigned short u);
+ UChar(const UCharReference &c);
+ /**
+ * @return The higher byte of the character.
+ */
+ unsigned char high() const { return hi; }
+ /**
+ * @return The lower byte of the character.
+ */
+ unsigned char low() const { return lo; }
+ /**
+ * @return the 16 bit Unicode value of the character
+ */
+ unsigned short unicode() const { return hi << 8 | lo; }
+ public:
+ /**
+ * @return The character converted to lower case.
+ */
+ UChar toLower() const;
+ /**
+ * @return The character converted to upper case.
+ */
+ UChar toUpper() const;
+ /**
+ * A static instance of UChar(0).
+ */
+ static UChar null;
+ private:
+ friend class UCharReference;
+ friend class UString;
+ friend bool operator==(const UChar &c1, const UChar &c2);
+ friend bool operator==(const UString& s1, const char *s2);
+ friend bool operator<(const UString& s1, const UString& s2);
+#ifdef KJS_SWAPPED_CHAR
+ unsigned char lo;
+ unsigned char hi;
+#else
+ unsigned char hi;
+ unsigned char lo;
+#endif
+ } KJS_PACKED;
+
+
+#ifdef KJS_SWAPPED_CHAR // to avoid reorder warnings
+ inline UChar::UChar() : lo(0), hi(0) { }
+ inline UChar::UChar(unsigned char h , unsigned char l) : lo(l), hi(h) { }
+ inline UChar::UChar(unsigned short u) : lo(u & 0x00ff), hi(u >> 8) { }
+#else
+ inline UChar::UChar() : hi(0), lo(0) { }
+ inline UChar::UChar(unsigned char h , unsigned char l) : hi(h), lo(l) { }
+ inline UChar::UChar(unsigned short u) : hi(u >> 8), lo(u & 0x00ff) { }
+#endif
+
+ /**
+ * @short Dynamic reference to a string character.
+ *
+ * UCharReference is the dynamic counterpart of @ref UChar. It's used when
+ * characters retrieved via index from a @ref UString are used in an
+ * assignment expression (and therefore can't be treated as being const):
+ * <pre>
+ * UString s("hello world");
+ * s[0] = 'H';
+ * </pre>
+ *
+ * If that sounds confusing your best bet is to simply forget about the
+ * existance of this class and treat is as being identical to @ref UChar.
+ */
+ class UCharReference {
+ friend class UString;
+ UCharReference(UString *s, unsigned int off) : str(s), offset(off) { }
+ public:
+ /**
+ * Set the referenced character to c.
+ */
+ UCharReference& operator=(UChar c);
+ /**
+ * Same operator as above except the argument that it takes.
+ */
+ UCharReference& operator=(char c) { return operator=(UChar(c)); }
+ /**
+ * @return Unicode value.
+ */
+ unsigned short unicode() const { return ref().unicode(); }
+ /**
+ * @return Lower byte.
+ */
+ unsigned char& low() const { return ref().lo; }
+ /**
+ * @return Higher byte.
+ */
+ unsigned char& high() const { return ref().hi; }
+ /**
+ * @return Character converted to lower case.
+ */
+ UChar toLower() const { return ref().toLower(); }
+ /**
+ * @return Character converted to upper case.
+ */
+ UChar toUpper() const { return ref().toUpper(); }
+ private:
+ // not implemented, can only be constructed from UString
+ UCharReference();
+
+ UChar& ref() const;
+ UString *str;
+ int offset;
+ };
+
+ /**
+ * @short 8 bit char based string class
+ */
+ class CString {
+ public:
+ CString() : data(0L) { }
+ CString(const char *c);
+ CString(const CString &);
+
+ ~CString();
+
+ CString &append(const CString &);
+ CString &operator=(const char *c);
+ CString &operator=(const CString &);
+ CString &operator+=(const CString &);
+
+ int size() const;
+ const char *c_str() const { return data; }
+ private:
+ char *data;
+ };
+
+ /**
+ * @short Unicode string class
+ */
+ class UString {
+ friend bool operator==(const UString&, const UString&);
+ friend class UCharReference;
+ /**
+ * @internal
+ */
+ struct Rep {
+ friend class UString;
+ friend bool operator==(const UString&, const UString&);
+ static Rep *create(UChar *d, int l);
+ inline UChar *data() const { return dat; }
+ inline int size() const { return len; }
+
+ inline void ref() { rc++; }
+ inline int deref() { return --rc; }
+
+ UChar *dat;
+ int len;
+ int rc;
+ static Rep null;
+ };
+
+ public:
+ /**
+ * Constructs a null string.
+ */
+ UString();
+ /**
+ * Constructs a string from the single character c.
+ */
+ UString(char c);
+ /**
+ * Constructs a string from a classical zero determined char string.
+ */
+ UString(const char *c);
+ /**
+ * Constructs a string from an array of Unicode characters of the specified
+ * length.
+ */
+ UString(const UChar *c, int length);
+ /**
+ * If copy is false a shallow copy of the string will be created. That
+ * means that the data will NOT be copied and you'll have to guarantee that
+ * it doesn't get deleted during the lifetime of the UString object.
+ * Behaviour defaults to a deep copy if copy is true.
+ */
+ UString(UChar *c, int length, bool copy);
+ /**
+ * Copy constructor. Makes a shallow copy only.
+ */
+ UString(const UString &);
+ /**
+ * Convenience declaration only ! You'll be on your own to write the
+ * implementation for a construction from QString.
+ *
+ * Note: feel free to contact me if you want to see a dummy header for
+ * your favourite FooString class here !
+ */
+ UString(const QString &);
+ /**
+ * Convenience declaration only ! See @ref UString(const QString&).
+ */
+ UString(const DOM::DOMString &);
+ /**
+ * Destructor. If this handle was the only one holding a reference to the
+ * string the data will be freed.
+ */
+ ~UString();
+
+ /**
+ * Constructs a string from an int.
+ */
+ static UString from(int i);
+ /**
+ * Constructs a string from an unsigned int.
+ */
+ static UString from(unsigned int u);
+ /**
+ * Constructs a string from a double.
+ */
+ static UString from(double d);
+
+ /**
+ * Append another string.
+ */
+ UString &append(const UString &);
+
+ /**
+ * @return The string converted to the 8-bit string type @ref CString().
+ */
+ CString cstring() const;
+ /**
+ * Convert the Unicode string to plain ASCII chars chopping of any higher
+ * bytes. This method should only be used for *debugging* purposes as it
+ * is neither Unicode safe nor free from side effects. In order not to
+ * waste any memory the char buffer is static and *shared* by all UString
+ * instances.
+ */
+ char *ascii() const;
+ /**
+ * @see UString(const QString&).
+ */
+ DOM::DOMString string() const;
+ /**
+ * @see UString(const QString&).
+ */
+ QString qstring() const;
+ /**
+ * @see UString(const QString&).
+ */
+ QConstString qconststring() const;
+
+ /**
+ * Assignment operator.
+ */
+ UString &operator=(const char *c);
+ /**
+ * Assignment operator.
+ */
+ UString &operator=(const UString &);
+ /**
+ * Appends the specified string.
+ */
+ UString &operator+=(const UString &s);
+
+ /**
+ * @return A pointer to the internal Unicode data.
+ */
+ const UChar* data() const { return rep->data(); }
+ /**
+ * @return True if null.
+ */
+ bool isNull() const { return (rep == &Rep::null); }
+ /**
+ * @return True if null or zero length.
+ */
+ bool isEmpty() const { return (!rep->len); }
+ /**
+ * Use this if you want to make sure that this string is a plain ASCII
+ * string. For example, if you don't want to lose any information when
+ * using @ref cstring() or @ref ascii().
+ *
+ * @return True if the string doesn't contain any non-ASCII characters.
+ */
+ bool is8Bit() const;
+ /**
+ * @return The length of the string.
+ */
+ int size() const { return rep->size(); }
+ /**
+ * Const character at specified position.
+ */
+ UChar operator[](int pos) const;
+ /**
+ * Writable reference to character at specified position.
+ */
+ UCharReference operator[](int pos);
+
+ /**
+ * Attempts an conversion to a number. Apart from floating point numbers,
+ * the algorithm will recognize hexadecimal representations (as
+ * indicated by a 0x or 0X prefix) and +/- Infinity.
+ * Returns NaN if the conversion failed.
+ */
+ double toDouble() const;
+ /**
+ * Attempts an conversion to an unsigned long integer. ok will be set
+ * according to the success.
+ */
+ unsigned long toULong(bool *ok = 0L) const;
+ /**
+ * @return Position of first occurence of f starting at position pos.
+ * -1 if the search was not successful.
+ */
+ int find(const UString &f, int pos = 0) const;
+ /**
+ * @return Position of first occurence of f searching backwards from
+ * position pos.
+ * -1 if the search was not successful.
+ */
+ int rfind(const UString &f, int pos) const;
+ /**
+ * @return The sub string starting at position pos and length len.
+ */
+ UString substr(int pos = 0, int len = -1) const;
+ /**
+ * Static instance of a null string.
+ */
+ static UString null;
+ private:
+ void attach(Rep *r);
+ void detach();
+ void release();
+ Rep *rep;
+ };
+
+ bool operator==(const UChar &c1, const UChar &c2);
+ bool operator==(const UString& s1, const UString& s2);
+ inline bool operator!=(const UString& s1, const UString& s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator<(const UString& s1, const UString& s2);
+ bool operator==(const UString& s1, const char *s2);
+ inline bool operator!=(const UString& s1, const char *s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator==(const char *s1, const UString& s2);
+ inline bool operator!=(const char *s1, const UString& s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator==(const CString& s1, const CString& s2);
+ UString operator+(const UString& s1, const UString& s2);
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/.cvsignore b/WebCore/src/kdelibs/kjs/.cvsignore
new file mode 100644
index 0000000..e2a42ee
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+testkjs
+libkjs_la.all_cpp.cpp
+SunWS_cache
diff --git a/WebCore/src/kdelibs/kjs/ChangeLog b/WebCore/src/kdelibs/kjs/ChangeLog
new file mode 100644
index 0000000..8176cf4
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/ChangeLog
@@ -0,0 +1,24 @@
+2001-01-04 Harri Porten <harri@trolltech.com>
+
+ * ustring.h: pack bytes to avoid alignment problems (ARM) reported
+ by Stefan Hanske <sh990154@mail.uni-greifswald.de>
+ * nodes.cpp: typeof fix by Emmeran Seehuber <the_emmy@gmx.de>
+ * nodes.cpp: fixed order of function declaration proccessing
+
+2000-12-18 Harri Porten <harri@trolltech.com>
+
+ * string_object.cpp: fixed out-of-bounds error in fromCharCode()
+
+2000-12-11 Harri Porten <harri@trolltech.com>
+
+ * regexp.h: compile fix for buggy libc
+ * ustring.cpp: format string conversion of numbers with %g
+
+2000-12-10 Harri Porten <harri@trolltech.com>
+
+ * lexer.cpp: parsing != was broken, added \v escape in strings,
+ fixed "\u" and "\x" and \x with non hex chars following.
+ * nodes.cpp: implemented <<=, >>=, >>>=, &=, ^=, |= and %=
+ * internal.cpp: create error message including line no on parse errors
+
+
diff --git a/WebCore/src/kdelibs/kjs/Makefile.am b/WebCore/src/kdelibs/kjs/Makefile.am
new file mode 100644
index 0000000..1cd1be0
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/Makefile.am
@@ -0,0 +1,66 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1999 Harri Porten (porten@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library 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. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+YACC = bison
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkjs.la
+
+libkjs_la_SOURCES = kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp \
+ operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp \
+ internal.cpp regexp.cpp global_object.cpp math_object.cpp \
+ bool_object.cpp object_object.cpp error_object.cpp \
+ array_object.cpp string_object.cpp number_object.cpp \
+ date_object.cpp regexp_object.cpp collector.cpp function_object.cpp \
+ debugger.cpp
+
+kjsincludedir = $(includedir)/kjs
+kjsinclude_HEADERS = kjs.h object.h operations.h ustring.h \
+ function.h lookup.h types.h
+
+noinst_HEADERS = nodes.h lexer.h regexp.h internal.h collector.h \
+ grammar.h object_object.h function_object.h function_object.h \
+ bool_object.h math_object.h array_object.h string_object.h \
+ number_object.h date_object.h regexp_object.h error_object.h \
+ debugger.h
+
+libkjs_la_LDFLAGS = -version-info 1:0 -no-undefined $(USER_LDFLAGS)
+libkjs_la_LIBADD = -lm $(LIBPCRE)
+
+parser: $(srcdir)/grammar.y
+ cd $(srcdir); \
+ $(YACC) -d -p kjsyy grammar.y && mv grammar.tab.c grammar.cpp; \
+ if test -f grammar.tab.h; then \
+ if cmp -s grammar.tab.h grammar.h; then rm -f grammar.tab.h; \
+ else mv grammar.tab.h grammar.h; fi \
+ else :; fi
+
+## with debugger interface
+debugger: $(libkjs_la_SOURCES) $(kjsinclude_HEADERS) $(noinst_HEADERS)
+ $(MAKE) DEFS="-DKJS_DEBUGGER $(DEFS)" libkjs.la
+
+## test program (in one program for easier profiling/memory debugging)
+EXTRA_PROGRAMS = testkjs_static
+testkjs_static_SOURCES = testkjs.cpp $(libkjs_la_SOURCES)
+testkjs_static_LDADD = $(LIBPCRE)
+
+## test program (linked to libkjs)
+check_PROGRAMS = testkjs
+testkjs_SOURCES = testkjs.cpp
+testkjs_LDADD = libkjs.la
+
diff --git a/WebCore/src/kdelibs/kjs/Makefile.in b/WebCore/src/kdelibs/kjs/Makefile.in
new file mode 100644
index 0000000..dd601f3
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/Makefile.in
@@ -0,0 +1,738 @@
+# KDE tags expanded automatically by am_edit - $Revision$
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# This file is part of the KDE libraries
+# Copyright (C) 1999 Harri Porten (porten@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library 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. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+#>-
+bindir = @bindir@
+#>+ 3
+DEPDIR = .deps
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+ARTSCCONFIG = @ARTSCCONFIG@
+ARTS_BUILD_GMCOP = @ARTS_BUILD_GMCOP@
+ARTS_BUILD_KDE = @ARTS_BUILD_KDE@
+ARTS_MAJOR_VERSION = @ARTS_MAJOR_VERSION@
+ARTS_MICRO_VERSION = @ARTS_MICRO_VERSION@
+ARTS_MINOR_VERSION = @ARTS_MINOR_VERSION@
+ARTS_VERSION = @ARTS_VERSION@
+AS = @AS@
+AUTODIRS = @AUTODIRS@
+BZIP2DIR = @BZIP2DIR@
+BZIP2_FILTER = @BZIP2_FILTER@
+CC = @CC@
+CONF_FILES = @CONF_FILES@
+CPP = @CPP@
+CUPSSUBDIR = @CUPSSUBDIR@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+DCOPIDL = @DCOPIDL@
+DCOPIDL2CPP = @DCOPIDL2CPP@
+DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@
+DLLTOOL = @DLLTOOL@
+DPMSINC = @DPMSINC@
+DPMSLIB = @DPMSLIB@
+EXEEXT = @EXEEXT@
+EXTRA_SUBDIRS = @EXTRA_SUBDIRS@
+GCJ = @GCJ@
+GCJFLAGS = @GCJFLAGS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_DEPLIBS = @GLIB_DEPLIBS@
+GLIB_LIBS = @GLIB_LIBS@
+GLINC = @GLINC@
+GLLIB = @GLLIB@
+GMSGFMT = @GMSGFMT@
+HAVE_MITSHM = @HAVE_MITSHM@
+HELP_SUBDIR = @HELP_SUBDIR@
+ICE_RLIB = @ICE_RLIB@
+ICE_SUBDIR = @ICE_SUBDIR@
+IDL = @IDL@
+IDL_DEPENDENCIES = @IDL_DEPENDENCIES@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVAH = @JAVAH@
+JVMLIBS = @JVMLIBS@
+KDECONFIG = @KDECONFIG@
+KDE_CXXFLAGS = @KDE_CXXFLAGS@
+KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@
+KDE_INCLUDES = @KDE_INCLUDES@
+KDE_LDFLAGS = @KDE_LDFLAGS@
+KDE_PLUGIN = @KDE_PLUGIN@
+KDE_RPATH = @KDE_RPATH@
+KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@
+KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@
+KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@
+KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@
+KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@
+LIBASOUND = @LIBASOUND@
+LIBAUDIOFILE = @LIBAUDIOFILE@
+LIBAUDIOIO = @LIBAUDIOIO@
+LIBAUDIONAS = @LIBAUDIONAS@
+LIBBZ2 = @LIBBZ2@
+LIBCOMPAT = @LIBCOMPAT@
+LIBCRYPT = @LIBCRYPT@
+LIBDL = @LIBDL@
+LIBFAM = @LIBFAM@
+LIBGEN = @LIBGEN@
+LIBICE = @LIBICE@
+LIBJPEG = @LIBJPEG@
+LIBMICO = @LIBMICO@
+LIBOBJS = @LIBOBJS@
+LIBOSSAUDIO = @LIBOSSAUDIO@
+LIBPCRE = @LIBPCRE@
+LIBPNG = @LIBPNG@
+LIBPOSIX1E = @LIBPOSIX1E@
+LIBPTHREAD = @LIBPTHREAD@
+LIBPYTHON = @LIBPYTHON@
+LIBQIMGIO = @LIBQIMGIO@
+LIBRESOLV = @LIBRESOLV@
+LIBSHADOW = @LIBSHADOW@
+LIBSM = @LIBSM@
+LIBSOCKET = @LIBSOCKET@
+LIBSSL = @LIBSSL@
+LIBTIFF = @LIBTIFF@
+LIBTOOL = @LIBTOOL@
+LIBUCB = @LIBUCB@
+LIBUTIL = @LIBUTIL@
+LIBVOLMGT = @LIBVOLMGT@
+LIBXINERAMA = @LIBXINERAMA@
+LIBXML_CFLAGS = @LIBXML_CFLAGS@
+LIBXML_LIBS = @LIBXML_LIBS@
+LIBXML_RPATH = @LIBXML_RPATH@
+LIBXSLT_MAJOR_VERSION = @LIBXSLT_MAJOR_VERSION@
+LIBXSLT_MICRO_VERSION = @LIBXSLT_MICRO_VERSION@
+LIBXSLT_MINOR_VERSION = @LIBXSLT_MINOR_VERSION@
+LIBXSLT_VERSION = @LIBXSLT_VERSION@
+LIBXSLT_VERSION_INFO = @LIBXSLT_VERSION_INFO@
+LIBXSLT_VERSION_NUMBER = @LIBXSLT_VERSION_NUMBER@
+LIBZ = @LIBZ@
+LIB_CUPS = @LIB_CUPS@
+LIB_DCOP = @LIB_DCOP@
+LIB_DMALLOC = @LIB_DMALLOC@
+LIB_KAB = @LIB_KAB@
+LIB_KDECORE = @LIB_KDECORE@
+LIB_KDEUI = @LIB_KDEUI@
+LIB_KFILE = @LIB_KFILE@
+LIB_KFM = @LIB_KFM@
+LIB_KFORMULA = @LIB_KFORMULA@
+LIB_KHTML = @LIB_KHTML@
+LIB_KIMGIO = @LIB_KIMGIO@
+LIB_KIO = @LIB_KIO@
+LIB_KPARTS = @LIB_KPARTS@
+LIB_KSPELL = @LIB_KSPELL@
+LIB_KSSL = @LIB_KSSL@
+LIB_KSYCOCA = @LIB_KSYCOCA@
+LIB_KWRITE = @LIB_KWRITE@
+LIB_QT = @LIB_QT@
+LIB_SMB = @LIB_SMB@
+LIB_X11 = @LIB_X11@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MCOPIDL = @MCOPIDL@
+MEINPROC = @MEINPROC@
+MICO_INCLUDES = @MICO_INCLUDES@
+MICO_LDFLAGS = @MICO_LDFLAGS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+M_LIBS = @M_LIBS@
+NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@
+NOREPO = @NOREPO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PAMLIBS = @PAMLIBS@
+PASSWDLIBS = @PASSWDLIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHONINC = @PYTHONINC@
+PYTHONLIB = @PYTHONLIB@
+PYTHONMODDIR = @PYTHONMODDIR@
+QNAMESPACE_H = @QNAMESPACE_H@
+QTDOCDIR = @QTDOCDIR@
+QT_INCLUDES = @QT_INCLUDES@
+QT_LDFLAGS = @QT_LDFLAGS@
+RANLIB = @RANLIB@
+REPO = @REPO@
+SETUIDFLAGS = @SETUIDFLAGS@
+SSL_INCLUDES = @SSL_INCLUDES@
+SSL_LDFLAGS = @SSL_LDFLAGS@
+STRIP = @STRIP@
+TOPSUBDIRS = @TOPSUBDIRS@
+UIC = @UIC@
+USER_INCLUDES = @USER_INCLUDES@
+USER_LDFLAGS = @USER_LDFLAGS@
+USE_EXCEPTIONS = @USE_EXCEPTIONS@
+USE_RTTI = @USE_RTTI@
+USE_THREADS = @USE_THREADS@
+VERSION = @VERSION@
+WITH_MEM_DEBUG = @WITH_MEM_DEBUG@
+WITH_XSLT_DEBUG = @WITH_XSLT_DEBUG@
+XGETTEXT = @XGETTEXT@
+XPMINC = @XPMINC@
+XPMLIB = @XPMLIB@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_INCLUDES = @X_INCLUDES@
+X_LDFLAGS = @X_LDFLAGS@
+X_PRE_LIBS = @X_PRE_LIBS@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+idldir = @idldir@
+jni_includes = @jni_includes@
+kde_appsdir = @kde_appsdir@
+kde_bindir = @kde_bindir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_includes = @kde_includes@
+kde_libraries = @kde_libraries@
+kde_libs_htmldir = @kde_libs_htmldir@
+kde_libs_prefix = @kde_libs_prefix@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_moduledir = @kde_moduledir@
+kde_servicesdir = @kde_servicesdir@
+kde_servicetypesdir = @kde_servicetypesdir@
+kde_sounddir = @kde_sounddir@
+kde_templatesdir = @kde_templatesdir@
+kde_wallpaperdir = @kde_wallpaperdir@
+micodir = @micodir@
+path_su = @path_su@
+qt_includes = @qt_includes@
+qt_libraries = @qt_libraries@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+
+YACC = bison
+INCLUDES = $(all_includes)
+
+lib_LTLIBRARIES = libkjs.la
+
+libkjs_la_SOURCES = kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp internal.cpp regexp.cpp global_object.cpp math_object.cpp bool_object.cpp object_object.cpp error_object.cpp array_object.cpp string_object.cpp number_object.cpp date_object.cpp regexp_object.cpp collector.cpp function_object.cpp debugger.cpp
+
+
+kjsincludedir = $(includedir)/kjs
+kjsinclude_HEADERS = kjs.h object.h operations.h ustring.h function.h lookup.h types.h
+
+
+noinst_HEADERS = nodes.h lexer.h regexp.h internal.h collector.h grammar.h object_object.h function_object.h function_object.h bool_object.h math_object.h array_object.h string_object.h number_object.h date_object.h regexp_object.h error_object.h debugger.h
+
+
+libkjs_la_LDFLAGS = -version-info 1:0 -no-undefined $(USER_LDFLAGS)
+libkjs_la_LIBADD = -lm $(LIBPCRE)
+
+EXTRA_PROGRAMS = testkjs_static
+testkjs_static_SOURCES = testkjs.cpp $(libkjs_la_SOURCES)
+testkjs_static_LDADD = $(LIBPCRE)
+
+check_PROGRAMS = testkjs
+testkjs_SOURCES = testkjs.cpp
+testkjs_LDADD = libkjs.la
+mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(lib_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libkjs_la_DEPENDENCIES =
+#>- libkjs_la_OBJECTS = kjs.lo grammar.lo lexer.lo nodes.lo object.lo \
+#>- operations.lo ustring.lo function.lo types.lo lookup.lo internal.lo \
+#>- regexp.lo global_object.lo math_object.lo bool_object.lo \
+#>- object_object.lo error_object.lo array_object.lo string_object.lo \
+#>- number_object.lo date_object.lo regexp_object.lo collector.lo \
+#>- function_object.lo debugger.lo
+#>+ 9
+libkjs_la_final_OBJECTS = libkjs_la.all_cpp.lo
+libkjs_la_nofinal_OBJECTS = kjs.lo grammar.lo lexer.lo nodes.lo object.lo \
+operations.lo ustring.lo function.lo types.lo lookup.lo internal.lo \
+regexp.lo global_object.lo math_object.lo bool_object.lo \
+object_object.lo error_object.lo array_object.lo string_object.lo \
+number_object.lo date_object.lo regexp_object.lo collector.lo \
+function_object.lo debugger.lo
+@KDE_USE_FINAL_FALSE@libkjs_la_OBJECTS = $(libkjs_la_nofinal_OBJECTS)
+@KDE_USE_FINAL_TRUE@libkjs_la_OBJECTS = $(libkjs_la_final_OBJECTS)
+check_PROGRAMS = testkjs$(EXEEXT)
+#>- testkjs_static_OBJECTS = testkjs.$(OBJEXT) kjs.$(OBJEXT) \
+#>- grammar.$(OBJEXT) lexer.$(OBJEXT) nodes.$(OBJEXT) object.$(OBJEXT) \
+#>- operations.$(OBJEXT) ustring.$(OBJEXT) function.$(OBJEXT) \
+#>- types.$(OBJEXT) lookup.$(OBJEXT) internal.$(OBJEXT) regexp.$(OBJEXT) \
+#>- global_object.$(OBJEXT) math_object.$(OBJEXT) bool_object.$(OBJEXT) \
+#>- object_object.$(OBJEXT) error_object.$(OBJEXT) array_object.$(OBJEXT) \
+#>- string_object.$(OBJEXT) number_object.$(OBJEXT) date_object.$(OBJEXT) \
+#>- regexp_object.$(OBJEXT) collector.$(OBJEXT) function_object.$(OBJEXT) \
+#>- debugger.$(OBJEXT)
+#>+ 9
+testkjs_static_OBJECTS = testkjs.$(OBJEXT) kjs.$(OBJEXT) \
+grammar.$(OBJEXT) lexer.$(OBJEXT) nodes.$(OBJEXT) object.$(OBJEXT) \
+operations.$(OBJEXT) ustring.$(OBJEXT) function.$(OBJEXT) \
+types.$(OBJEXT) lookup.$(OBJEXT) internal.$(OBJEXT) regexp.$(OBJEXT) \
+global_object.$(OBJEXT) math_object.$(OBJEXT) bool_object.$(OBJEXT) \
+object_object.$(OBJEXT) error_object.$(OBJEXT) array_object.$(OBJEXT) \
+string_object.$(OBJEXT) number_object.$(OBJEXT) date_object.$(OBJEXT) \
+regexp_object.$(OBJEXT) collector.$(OBJEXT) function_object.$(OBJEXT) \
+debugger.$(OBJEXT)
+testkjs_static_DEPENDENCIES =
+testkjs_static_LDFLAGS =
+#>- testkjs_OBJECTS = testkjs.$(OBJEXT)
+#>+ 1
+testkjs_OBJECTS = testkjs.$(OBJEXT)
+testkjs_DEPENDENCIES = libkjs.la
+testkjs_LDFLAGS =
+CXXFLAGS = @CXXFLAGS@
+#>- CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 1
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+#>- LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+#>+ 1
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile --tag=CXX $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS)
+CXXLD = $(CXX)
+#>- CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+#>+ 1
+CXXLINK = $(LIBTOOL) --mode=link --tag=CXX $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(KDE_CXXFLAGS) $(LDFLAGS) -o $@
+HEADERS = $(kjsinclude_HEADERS) $(noinst_HEADERS)
+
+DIST_COMMON = README ChangeLog Makefile.am Makefile.in THANKS
+
+
+#>- DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+#>+ 4
+KDE_DIST=configure.in.in grammar.y keywords.table math_object.lut.h test.js create_hash_table lexer.lut.h
+
+DISTFILES= $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST)
+
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(libkjs_la_SOURCES) $(testkjs_static_SOURCES) $(testkjs_SOURCES)
+OBJECTS = $(libkjs_la_OBJECTS) $(testkjs_static_OBJECTS) $(testkjs_OBJECTS)
+
+#>- all: all-redirect
+#>+ 1
+all: docs-am all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cpp .lo .o .obj .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+#>- cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+#>+ 2
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+ cd $(top_srcdir) && perl admin/am_edit kjs/Makefile.in
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-libLTLIBRARIES:
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+
+distclean-libLTLIBRARIES:
+
+maintainer-clean-libLTLIBRARIES:
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \
+ $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+#>- libkjs.la: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+#>+ 2
+@KDE_USE_CLOSURE_TRUE@libkjs.la: libkjs.la.closure $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+@KDE_USE_CLOSURE_FALSE@libkjs.la: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libkjs_la_LDFLAGS) $(libkjs_la_OBJECTS) $(libkjs_la_LIBADD) $(LIBS)
+
+mostlyclean-checkPROGRAMS:
+
+clean-checkPROGRAMS:
+ -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+
+distclean-checkPROGRAMS:
+
+maintainer-clean-checkPROGRAMS:
+
+testkjs_static$(EXEEXT): $(testkjs_static_OBJECTS) $(testkjs_static_DEPENDENCIES)
+ @rm -f testkjs_static$(EXEEXT)
+ $(CXXLINK) $(testkjs_static_LDFLAGS) $(testkjs_static_OBJECTS) $(testkjs_static_LDADD) $(LIBS)
+
+testkjs$(EXEEXT): $(testkjs_OBJECTS) $(testkjs_DEPENDENCIES)
+ @rm -f testkjs$(EXEEXT)
+ $(CXXLINK) $(testkjs_LDFLAGS) $(testkjs_OBJECTS) $(testkjs_LDADD) $(LIBS)
+.cpp.o:
+ $(CXXCOMPILE) -c $<
+.cpp.obj:
+ $(CXXCOMPILE) -c `cygpath -w $<`
+.cpp.lo:
+ $(LTCXXCOMPILE) -c $<
+
+install-kjsincludeHEADERS: $(kjsinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(kjsincludedir)
+ @list='$(kjsinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(kjsincludedir)/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(kjsincludedir)/$$p; \
+ done
+
+uninstall-kjsincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ list='$(kjsinclude_HEADERS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(kjsincludedir)/$$p; \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = kjs
+
+distdir: $(DISTFILES)
+#>- @for file in $(DISTFILES); do \
+#>- d=$(srcdir); \
+#>- if test -d $$d/$$file; then \
+#>- cp -pr $$/$$file $(distdir)/$$file; \
+#>- else \
+#>- test -f $(distdir)/$$file \
+#>- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+#>- || cp -p $$d/$$file $(distdir)/$$file || :; \
+#>- fi; \
+#>- done
+#>+ 10
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-libLTLIBRARIES
+install-exec: install-exec-am
+
+install-data-am: install-kjsincludeHEADERS
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-libLTLIBRARIES uninstall-kjsincludeHEADERS
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(kjsincludedir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-checkPROGRAMS \
+ mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+#>- clean-am: clean-libLTLIBRARIES clean-compile clean-libtool \
+#>- clean-checkPROGRAMS clean-tags clean-generic \
+#>- mostlyclean-am
+#>+ 3
+clean-am: clean-closures clean-final clean-libLTLIBRARIES clean-compile clean-libtool \
+ clean-checkPROGRAMS clean-tags clean-generic \
+ mostlyclean-am
+
+#>- clean: clean-am
+#>+ 1
+clean: kde-rpo-clean clean-am
+
+distclean-am: distclean-libLTLIBRARIES distclean-compile \
+ distclean-libtool distclean-checkPROGRAMS \
+ distclean-tags distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-checkPROGRAMS maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
+clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
+uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool mostlyclean-checkPROGRAMS \
+distclean-checkPROGRAMS clean-checkPROGRAMS \
+maintainer-clean-checkPROGRAMS uninstall-kjsincludeHEADERS \
+install-kjsincludeHEADERS tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+parser: $(srcdir)/grammar.y
+ cd $(srcdir); \
+ $(YACC) -d -p kjsyy grammar.y && mv grammar.tab.c grammar.cpp; \
+ if test -f grammar.tab.h; then \
+ if cmp -s grammar.tab.h grammar.h; then rm -f grammar.tab.h; \
+ else mv grammar.tab.h grammar.h; fi \
+ else :; fi
+
+debugger: $(libkjs_la_SOURCES) $(kjsinclude_HEADERS) $(noinst_HEADERS)
+ $(MAKE) DEFS="-DKJS_DEBUGGER $(DEFS)" libkjs.la
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+#>+ 8
+libkjs.la.closure: $(libkjs_la_OBJECTS) $(libkjs_la_DEPENDENCIES)
+ @echo "int main() {return 0;}" > libkjs_la_closure.cpp
+ @$(LTCXXCOMPILE) -c libkjs_la_closure.cpp
+ @$(CXXLINK) libkjs_la_closure.lo $(libkjs_la_LDFLAGS) $(libkjs_la_OBJECTS) $(libkjs_la_LIBADD) $(LIBS)
+ @rm -f libkjs_la_closure.* libkjs.la.closure
+ @echo "timestamp" > libkjs.la.closure
+
+
+#>+ 3
+clean-closures:
+ -rm -f libkjs.la.closure
+
+#>+ 2
+docs-am:
+
+#>+ 5
+force-reedit:
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps kjs/Makefile
+ cd $(top_srcdir) && perl admin/am_edit kjs/Makefile.in
+
+
+#>+ 11
+libkjs_la.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/kjs.cpp $(srcdir)/grammar.cpp $(srcdir)/lexer.cpp $(srcdir)/nodes.cpp $(srcdir)/object.cpp $(srcdir)/operations.cpp $(srcdir)/ustring.cpp $(srcdir)/function.cpp $(srcdir)/types.cpp $(srcdir)/lookup.cpp $(srcdir)/internal.cpp $(srcdir)/regexp.cpp $(srcdir)/global_object.cpp $(srcdir)/math_object.cpp $(srcdir)/bool_object.cpp $(srcdir)/object_object.cpp $(srcdir)/error_object.cpp $(srcdir)/array_object.cpp $(srcdir)/string_object.cpp $(srcdir)/number_object.cpp $(srcdir)/date_object.cpp $(srcdir)/regexp_object.cpp $(srcdir)/collector.cpp $(srcdir)/function_object.cpp $(srcdir)/debugger.cpp
+ @echo 'creating libkjs_la.all_cpp.cpp ...'; \
+ rm -f libkjs_la.all_cpp.files libkjs_la.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> libkjs_la.all_cpp.final; \
+ for file in kjs.cpp grammar.cpp lexer.cpp nodes.cpp object.cpp operations.cpp ustring.cpp function.cpp types.cpp lookup.cpp internal.cpp regexp.cpp global_object.cpp math_object.cpp bool_object.cpp object_object.cpp error_object.cpp array_object.cpp string_object.cpp number_object.cpp date_object.cpp regexp_object.cpp collector.cpp function_object.cpp debugger.cpp ; do \
+ echo "#include \"$$file\"" >> libkjs_la.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> libkjs_la.all_cpp.final; \
+ done; \
+ cat libkjs_la.all_cpp.final libkjs_la.all_cpp.files > libkjs_la.all_cpp.cpp; \
+ rm -f libkjs_la.all_cpp.final libkjs_la.all_cpp.files
+
+#>+ 11
+testkjs.all_cpp.cpp: $(srcdir)/Makefile.in $(srcdir)/testkjs.cpp
+ @echo 'creating testkjs.all_cpp.cpp ...'; \
+ rm -f testkjs.all_cpp.files testkjs.all_cpp.final; \
+ echo "#define KDE_USE_FINAL 1" >> testkjs.all_cpp.final; \
+ for file in testkjs.cpp ; do \
+ echo "#include \"$$file\"" >> testkjs.all_cpp.files; \
+ test ! -f $(srcdir)/$$file || egrep '^#pragma +implementation' $(srcdir)/$$file >> testkjs.all_cpp.final; \
+ done; \
+ cat testkjs.all_cpp.final testkjs.all_cpp.files > testkjs.all_cpp.cpp; \
+ rm -f testkjs.all_cpp.final testkjs.all_cpp.files
+
+#>+ 3
+clean-final:
+ -rm -f libkjs_la.all_cpp.cpp testkjs.all_cpp.cpp
+
+#>+ 2
+final:
+ $(MAKE) libkjs_la_OBJECTS="$(libkjs_la_final_OBJECTS)" all-am
+#>+ 2
+no-final:
+ $(MAKE) libkjs_la_OBJECTS="$(libkjs_la_nofinal_OBJECTS)" all-am
+#>+ 3
+cvs-clean:
+ $(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean
+
+#>+ 3
+kde-rpo-clean:
+ -rm -f *.rpo
diff --git a/WebCore/src/kdelibs/kjs/README b/WebCore/src/kdelibs/kjs/README
new file mode 100644
index 0000000..b4a0fcc
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/README
@@ -0,0 +1,25 @@
+This library provides an ECMAScript compatible interpreter. The ECMA standard
+is based on well known scripting languages such as Netscape's JavaScript and
+Microsoft's JScript.
+
+I'm currently pursuing to be compliant with Edition 3 of ECMA-262. Postscript
+and pdf versions of the standard are avaiable at:
+
+http://www.ecma.ch
+
+About 90% of the required features should be covered by now. Note that this
+number covers the core language elements only. Features like the famous
+roll-over buttons on the www are NOT part of the standard. Those extensions
+are added via a module loaded dynamically by the KHTML Widget.
+
+I'll provide some examples of how to extend this library for various needs at
+a later point in time. Feel free to contact me via mail if you have any
+questions on how to provide scripting capabilites for your application.
+
+A debugger is being worked on. To compile it, add -DKJS_DEBUGGER to the CXXFLAGS
+section in the Makefile.am of kdelibs/kjs and kdelibs/khtml/ecma.
+
+Bug reports, patches or feedback of any kind is very welcome.
+
+Harri Porten <porten@kde.org>
+
diff --git a/WebCore/src/kdelibs/kjs/THANKS b/WebCore/src/kdelibs/kjs/THANKS
new file mode 100644
index 0000000..036e5e7
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/THANKS
@@ -0,0 +1,7 @@
+I would like to thank the following people for their help:
+
+Richard Moore <rich@kde.org> - for filling the Math object with some life
+Daegeun Lee <realking@mizi.com> - for pointing out some bugs and providing
+ much code for the String and Date object.
+Marco Pinelli <pinmc@libero.it> - for his patches
+Christian Kirsch <ck@held.mind.de> - for his contribution to the Date object
diff --git a/WebCore/src/kdelibs/kjs/array_object.cpp b/WebCore/src/kdelibs/kjs/array_object.cpp
new file mode 100644
index 0000000..cc97dff
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/array_object.cpp
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "array_object.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+ArrayObject::ArrayObject(const Object &funcProto,
+ const Object &arrayProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.4.3.1 Array.prototype
+ setPrototypeProperty(arrayProto);
+}
+
+// ECMA 15.6.1
+Completion ArrayObject::execute(const List &args)
+{
+ // equivalent to 'new Array(....)'
+ KJSO result = construct(args);
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.6.2
+Object ArrayObject::construct(const List &args)
+{
+ Object result = Object::create(ArrayClass);
+
+ unsigned int len;
+ ListIterator it = args.begin();
+ // a single argument might denote the array size
+ if (args.size() == 1 && it->isA(NumberType))
+ len = it->toUInt32();
+ else {
+ // initialize array
+ len = args.size();
+ for (unsigned int u = 0; it != args.end(); it++, u++)
+ result.put(UString::from(u), *it);
+ }
+
+ // array size
+ result.put("length", len, DontEnum | DontDelete);
+
+ return result;
+}
+
+// ECMA 15.6.4
+ArrayPrototype::ArrayPrototype(const Object& proto)
+ : ObjectImp(ArrayClass, Null(), proto)
+{
+ // The constructor will be added later in ArrayObject's constructor
+
+ put("length", 0u, DontEnum | DontDelete);
+}
+
+KJSO ArrayPrototype::get(const UString &p) const
+{
+ int id;
+ if(p == "toString")
+ id = ArrayProtoFunc::ToString;
+ else if(p == "toLocaleString")
+ id = ArrayProtoFunc::ToLocaleString;
+ else if(p == "concat")
+ id = ArrayProtoFunc::Concat;
+ else if (p == "join")
+ id = ArrayProtoFunc::Join;
+ else if(p == "pop")
+ id = ArrayProtoFunc::Pop;
+ else if(p == "push")
+ id = ArrayProtoFunc::Push;
+ else if(p == "reverse")
+ id = ArrayProtoFunc::Reverse;
+ else if(p == "shift")
+ id = ArrayProtoFunc::Shift;
+ else if(p == "slice")
+ id = ArrayProtoFunc::Slice;
+ else if(p == "sort")
+ id = ArrayProtoFunc::Sort;
+ else if(p == "splice")
+ id = ArrayProtoFunc::Splice;
+ else if(p == "unshift")
+ id = ArrayProtoFunc::UnShift;
+ else
+ return Imp::get(p);
+
+ return Function(new ArrayProtoFunc(id));
+}
+
+// ECMA 15.4.4
+Completion ArrayProtoFunc::execute(const List &args)
+{
+ KJSO result, obj, obj2;
+ Object thisObj = Object::dynamicCast(thisValue());
+ unsigned int length = thisObj.get("length").toUInt32();
+ unsigned int middle;
+ UString str = "", str2;
+ UString separator = ",";
+
+ switch (id) {
+ case ToLocaleString:
+ /* TODO */
+ // fall trough
+ case ToString:
+ if (!thisObj.getClass() == ArrayClass) {
+ result = Error::create(TypeError);
+ break;
+ }
+ // fall trough
+ case Join:
+ {
+ if (!args[0].isA(UndefinedType))
+ separator = args[0].toString().value();
+ for (unsigned int k = 0; k < length; k++) {
+ if (k >= 1)
+ str += separator;
+ obj = thisObj.get(UString::from(k));
+ if (!obj.isA(UndefinedType) && !obj.isA(NullType))
+ str += obj.toString().value();
+ }
+ }
+ result = String(str);
+ break;
+ case Concat: {
+ result = Object::create(ArrayClass);
+ int n = 0;
+ obj = thisObj;
+ ListIterator it = args.begin();
+ for (;;) {
+ if (obj.isA(ObjectType) &&
+ static_cast<Object&>(obj).getClass() == ArrayClass) {
+ unsigned int k = 0;
+ if (n > 0)
+ length = obj.get("length").toUInt32();
+ while (k < length) {
+ UString p = UString::from(k);
+ if (obj.hasProperty(p))
+ result.put(UString::from(n), obj.get(p));
+ n++;
+ k++;
+ }
+ } else {
+ result.put(UString::from(n), obj);
+ n++;
+ }
+ if (it == args.end())
+ break;
+ obj = it++;
+ }
+ result.put("length", Number(n), DontEnum | DontDelete);
+ }
+ break;
+ case Pop:
+ if (length == 0) {
+ thisObj.put("length", Number(length), DontEnum | DontDelete);
+ result = Undefined();
+ } else {
+ str = UString::from(length - 1);
+ result = thisObj.get(str);
+ thisObj.deleteProperty(str);
+ thisObj.put("length", length - 1, DontEnum | DontDelete);
+ }
+ break;
+ case Push:
+ {
+ for (int n = 0; n < args.size(); n++)
+ thisObj.put(UString::from(length + n), args[n]);
+ length += args.size();
+ thisObj.put("length", length, DontEnum | DontDelete);
+ result = Number(length);
+ }
+ break;
+ case Reverse:
+ {
+ middle = length / 2;
+ for (unsigned int k = 0; k < middle; k++) {
+ str = UString::from(k);
+ str2 = UString::from(length - k - 1);
+ obj = thisObj.get(str);
+ obj2 = thisObj.get(str2);
+ if (thisObj.hasProperty(str2)) {
+ if (thisObj.hasProperty(str)) {
+ thisObj.put(str, obj2);
+ thisObj.put(str2, obj);
+ } else {
+ thisObj.put(str, obj2);
+ thisObj.deleteProperty(str2);
+ }
+ } else {
+ if (thisObj.hasProperty(str)) {
+ thisObj.deleteProperty(str);
+ thisObj.put(str2, obj);
+ } else {
+ // why delete something that's not there ? Strange.
+ thisObj.deleteProperty(str);
+ thisObj.deleteProperty(str2);
+ }
+ }
+ }
+ }
+ result = thisObj;
+ break;
+ case Shift:
+ if (length == 0) {
+ thisObj.put("length", Number(length), DontEnum | DontDelete);
+ result = Undefined();
+ } else {
+ result = thisObj.get("0");
+ for(unsigned int k = 1; k < length; k++) {
+ str = UString::from(k);
+ str2 = UString::from(k-1);
+ if (thisObj.hasProperty(str)) {
+ obj = thisObj.get(str);
+ thisObj.put(str2, obj);
+ } else
+ thisObj.deleteProperty(str2);
+ }
+ thisObj.deleteProperty(UString::from(length - 1));
+ thisObj.put("length", length - 1, DontEnum | DontDelete);
+ }
+ break;
+ case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713
+ {
+ result = Object::create(ArrayClass); // We return a new array
+ int begin = args[0].toUInt32();
+ int end = length;
+ if (!args[1].isA(UndefinedType))
+ {
+ end = args[1].toUInt32();
+ if ( end < 0 )
+ end += length;
+ }
+ // safety tests
+ if ( begin < 0 || end < 0 || begin >= end ) {
+ result.put("length", Number(0), DontEnum | DontDelete);
+ break;
+ }
+ //printf( "Slicing from %d to %d \n", begin, end );
+ for(unsigned int k = 0; k < (unsigned int) end-begin; k++) {
+ str = UString::from(k+begin);
+ str2 = UString::from(k);
+ if (thisObj.hasProperty(str)) {
+ obj = thisObj.get(str);
+ result.put(str2, obj);
+ }
+ }
+ result.put("length", end - begin, DontEnum | DontDelete);
+ break;
+ }
+ case Sort:
+ {
+#if 0
+ printf("KJS Array::Sort length=%d\n", length);
+ for ( unsigned int i = 0 ; i<length ; ++i )
+ printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );
+#endif
+ Object sortFunction;
+ bool useSortFunction = !args[0].isA(UndefinedType);
+ if (useSortFunction)
+ {
+ sortFunction = args[0].toObject();
+ if (!sortFunction.implementsCall())
+ useSortFunction = false;
+ }
+
+ if (length == 0) {
+ thisObj.put("length", Number(0), DontEnum | DontDelete);
+ result = Undefined();
+ break;
+ }
+
+ // "Min" sort. Not the fastest, but definitely less code than heapsort
+ // or quicksort, and much less swapping than bubblesort/insertionsort.
+ for ( unsigned int i = 0 ; i<length-1 ; ++i )
+ {
+ KJSO iObj = thisObj.get(UString::from(i));
+ unsigned int themin = i;
+ KJSO minObj = iObj;
+ for ( unsigned int j = i+1 ; j<length ; ++j )
+ {
+ KJSO jObj = thisObj.get(UString::from(j));
+ int cmp;
+ if ( useSortFunction )
+ {
+ List l;
+ l.append(jObj);
+ l.append(minObj);
+ cmp = sortFunction.executeCall( Global::current(), &l ).toInt32();
+ }
+ else
+ cmp = ( jObj.toString().value() < minObj.toString().value() ) ? -1 : 1;
+ if ( cmp < 0 )
+ {
+ themin = j;
+ minObj = jObj;
+ }
+ }
+ // Swap themin and i
+ if ( themin > i )
+ {
+ //printf("KJS Array::Sort: swapping %d and %d\n", i, themin );
+ thisObj.put( UString::from(i), minObj );
+ thisObj.put( UString::from(themin), iObj );
+ }
+ }
+#if 0
+ printf("KJS Array::Sort -- Resulting array:\n");
+ for ( unsigned int i = 0 ; i<length ; ++i )
+ printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );
+#endif
+ result = thisObj;
+ break;
+ }
+ // TODO Splice
+ // TODO Unshift
+ default:
+ result = Undefined();
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/WebCore/src/kdelibs/kjs/array_object.h b/WebCore/src/kdelibs/kjs/array_object.h
new file mode 100644
index 0000000..f4d56e4
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/array_object.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ARRAY_OBJECT_H_
+#define _ARRAY_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ArrayObject : public ConstructorImp {
+ public:
+ ArrayObject(const Object &funcProto, const Object &arrayProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class ArrayPrototype : public ObjectImp {
+ public:
+ ArrayPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+ class ArrayProtoFunc : public InternalFunctionImp {
+ public:
+ ArrayProtoFunc(int i) : id(i) { }
+ Completion execute(const List &);
+ enum { ToString, ToLocaleString, Concat, Join, Pop, Push,
+ Reverse, Shift, Slice, Sort, Splice, UnShift };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/bool_object.cpp b/WebCore/src/kdelibs/kjs/bool_object.cpp
new file mode 100644
index 0000000..08fcc5c
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/bool_object.cpp
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "bool_object.h"
+#include "error_object.h"
+
+using namespace KJS;
+
+BooleanObject::BooleanObject(const KJSO& funcProto, const KJSO &booleanProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // Boolean.prototype
+ setPrototypeProperty(booleanProto);
+}
+
+// ECMA 15.6.1
+Completion BooleanObject::execute(const List &args)
+{
+ Boolean b;
+
+ if (args.isEmpty())
+ b = Boolean(false);
+ else
+ b = args[0].toBoolean();
+
+ return Completion(ReturnValue, b);
+}
+
+// ECMA 15.6.2
+Object BooleanObject::construct(const List &args)
+{
+ Boolean b;
+ if (args.size() > 0)
+ b = args.begin()->toBoolean();
+ else
+ b = Boolean(false);
+
+ return Object::create(BooleanClass, b);
+}
+
+// ECMA 15.6.4
+BooleanPrototype::BooleanPrototype(const Object& proto)
+ : ObjectImp(BooleanClass, Boolean(false), proto)
+{
+ // The constructor will be added later in BooleanObject's constructor
+}
+
+KJSO BooleanPrototype::get(const UString &p) const
+{
+ if (p == "toString")
+ return Function(new BooleanProtoFunc(ToString));
+ else if (p == "valueOf")
+ return Function(new BooleanProtoFunc(ValueOf));
+ else
+ return Imp::get(p);
+}
+
+BooleanProtoFunc::BooleanProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.6.4.2 + 15.6.4.3
+Completion BooleanProtoFunc::execute(const List &)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // no generic function. "this" has to be a Boolean object
+ if (thisObj.isNull() || thisObj.getClass() != BooleanClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ // execute "toString()" or "valueOf()", respectively
+ KJSO v = thisObj.internalValue();
+ if (id == BooleanPrototype::ToString)
+ result = v.toString();
+ else
+ result = v.toBoolean();
+
+ return Completion(ReturnValue, result);
+}
diff --git a/WebCore/src/kdelibs/kjs/bool_object.h b/WebCore/src/kdelibs/kjs/bool_object.h
new file mode 100644
index 0000000..89dc451
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/bool_object.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _BOOL_OBJECT_H_
+#define _BOOL_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class BooleanObject : public ConstructorImp {
+ public:
+ BooleanObject(const KJSO& funcProto, const KJSO &booleanProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class BooleanPrototype : public ObjectImp {
+ public:
+ BooleanPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ enum { ToString, ValueOf };
+ };
+
+ class BooleanProtoFunc : public InternalFunctionImp {
+ public:
+ BooleanProtoFunc(int i);
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/collector.cpp b/WebCore/src/kdelibs/kjs/collector.cpp
new file mode 100644
index 0000000..df79038
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/collector.cpp
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "collector.h"
+#include "object.h"
+#include "internal.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+namespace KJS {
+
+ class CollectorBlock {
+ public:
+ CollectorBlock(int s);
+ ~CollectorBlock();
+ int size;
+ int filled;
+ void** mem;
+ CollectorBlock *prev, *next;
+ };
+
+}; // namespace
+
+using namespace KJS;
+
+CollectorBlock::CollectorBlock(int s)
+ : size(s),
+ filled(0),
+ prev(0L),
+ next(0L)
+{
+ mem = new void*[size];
+ memset(mem, 0, size * sizeof(void*));
+}
+
+CollectorBlock::~CollectorBlock()
+{
+ delete [] mem;
+ mem = 0L;
+}
+
+CollectorBlock* Collector::root = 0L;
+CollectorBlock* Collector::currentBlock = 0L;
+unsigned long Collector::filled = 0;
+unsigned long Collector::softLimit = KJS_MEM_INCREMENT;
+#ifdef KJS_DEBUG_MEM
+bool Collector::collecting = false;
+#endif
+
+void* Collector::allocate(size_t s)
+{
+ if (s == 0)
+ return 0L;
+
+ if (filled >= softLimit) {
+ collect();
+ if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) // we are actually using all this memory
+ softLimit *= 2;
+ }
+
+ void *m = malloc(s);
+
+ // hack to ensure obj is protected from GC before any constructors are run
+ // (prev = marked, next = gcallowed)
+ static_cast<Imp*>(m)->prev = 0;
+ static_cast<Imp*>(m)->next = 0;
+
+ if (!root) {
+ root = new CollectorBlock(BlockSize);
+ currentBlock = root;
+ }
+
+ CollectorBlock *block = currentBlock;
+ if (!block)
+ block = root;
+
+ // search for a block with space left
+ while (block->next && block->filled == block->size)
+ block = block->next;
+
+ if (block->filled >= block->size) {
+#ifdef KJS_DEBUG_MEM
+ printf("allocating new block of size %d\n", block->size);
+#endif
+ CollectorBlock *tmp = new CollectorBlock(BlockSize);
+ block->next = tmp;
+ tmp->prev = block;
+ block = tmp;
+ }
+ currentBlock = block;
+ // look for a free spot in the block
+ void **r = block->mem;
+ while (*r)
+ r++;
+ *r = m;
+ filled++;
+ block->filled++;
+
+ if (softLimit >= KJS_MEM_LIMIT) {
+ KJScriptImp::setException("Out of memory");
+ }
+
+ return m;
+}
+
+/**
+ * Mark-sweep garbage collection.
+ */
+void Collector::collect()
+{
+#ifdef KJS_DEBUG_MEM
+ printf("collecting %d objects total\n", Imp::count);
+ collecting = true;
+#endif
+
+ // MARK: first set all ref counts to 0 ....
+ CollectorBlock *block = root;
+ while (block) {
+#ifdef KJS_DEBUG_MEM
+ printf("cleaning block filled %d out of %d\n", block->filled, block->size);
+#endif
+ Imp **r = (Imp**)block->mem;
+ assert(r);
+ for (int i = 0; i < block->size; i++, r++)
+ if (*r) {
+ (*r)->setMarked(false);
+ }
+ block = block->next;
+ }
+
+ // ... increase counter for all referenced objects recursively
+ // starting out from the set of root objects
+ if (KJScriptImp::hook) {
+ KJScriptImp *scr = KJScriptImp::hook;
+ do {
+ scr->mark();
+ scr = scr->next;
+ } while (scr != KJScriptImp::hook);
+ }
+
+ // mark any other objects that we wouldn't delete anyway
+ block = root;
+ while (block) {
+ Imp **r = (Imp**)block->mem;
+ assert(r);
+ for (int i = 0; i < block->size; i++, r++)
+ if (*r && (*r)->created() && ((*r)->refcount || !(*r)->gcAllowed()) && !(*r)->marked())
+ (*r)->mark();
+ block = block->next;
+ }
+
+ // SWEEP: delete everything with a zero refcount (garbage)
+ block = root;
+ while (block) {
+ Imp **r = (Imp**)block->mem;
+ int del = 0;
+ for (int i = 0; i < block->size; i++, r++) {
+ if (*r && ((*r)->refcount == 0) && !(*r)->marked() && (*r)->gcAllowed()) {
+ // emulate destructing part of 'operator delete()'
+ (*r)->~Imp();
+ free(*r);
+ *r = 0L;
+ del++;
+ }
+ }
+ filled -= del;
+ block->filled -= del;
+ block = block->next;
+ }
+
+ // delete the emtpy containers
+ block = root;
+ while (block) {
+ CollectorBlock *next = block->next;
+ if (block->filled == 0) {
+ if (block->prev)
+ block->prev->next = next;
+ if (block == root)
+ root = next;
+ if (next)
+ next->prev = block->prev;
+ if (block == currentBlock) // we don't want a dangling pointer
+ currentBlock = 0L;
+ assert(block != root);
+ delete block;
+ }
+ block = next;
+ }
+
+#ifdef KJS_DEBUG_MEM
+ collecting = false;
+#endif
+}
diff --git a/WebCore/src/kdelibs/kjs/collector.h b/WebCore/src/kdelibs/kjs/collector.h
new file mode 100644
index 0000000..7e88e7f
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/collector.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSCOLLECTOR_H_
+#define _KJSCOLLECTOR_H_
+
+// KJS_MEM_LIMIT and KJS_MEM_INCREMENT can be tweaked to adjust how the
+// garbage collector allocates memory. KJS_MEM_LIMIT is the largest # of objects
+// the collector will allow to be present in memory. Once this limit is reached,
+// a running script will get an "out of memory" exception.
+//
+// KJS_MEM_INCREMENT specifies the amount by which the "soft limit" on memory is
+// increased when the memory gets filled up. The soft limit is the amount after
+// which the GC will run and delete unused objects.
+//
+// If you are debugging seemingly random crashes where an object has been deleted,
+// try setting KJS_MEM_INCREMENT to something small, e.g. 300, to force garbage
+// collection to happen more often, and disable the softLimit increase &
+// out-of-memory testing code in Collector::allocate()
+
+#define KJS_MEM_LIMIT 500000
+#define KJS_MEM_INCREMENT 1000
+
+#include <stdlib.h>
+
+namespace KJS {
+
+ class Imp;
+ class CollectorBlock;
+
+ /**
+ * @short Garbage collector.
+ */
+ class Collector {
+ // disallow direct construction/destruction
+ Collector();
+ public:
+ /**
+ * Register an object with the collector. The following assumptions are
+ * made:
+ * @li the operator new() of the object class is overloaded.
+ * @li operator delete() has been overloaded as well and does not free
+ * the memory on its own.
+ *
+ * @param s Size of the memory to be registered.
+ * @return A pointer to the allocated memory.
+ */
+ static void* allocate(size_t s);
+ /**
+ * Run the garbage collection. This involves calling the delete operator
+ * on each object and freeing the used memory.
+ * In the current implemenation this will basically free all registered
+ * object regardless whether they are still references by others or not.
+ *
+ */
+ static void collect();
+ static int size() { return filled; }
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static bool collecting;
+#endif
+ private:
+ static CollectorBlock* root;
+ static CollectorBlock* currentBlock;
+ static unsigned long filled;
+ static unsigned long softLimit;
+ enum { BlockSize = 100 };
+ };
+
+};
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/configure.in.in b/WebCore/src/kdelibs/kjs/configure.in.in
new file mode 100644
index 0000000..d789ce3
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/configure.in.in
@@ -0,0 +1,51 @@
+dnl KDE JavaScript specific configure tests
+
+AC_CHECK_HEADERS(ieeefp.h float.h)
+AC_CHECK_LIB(m, isinf, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_ISINF, 1, [Define if you have isinf])
+])
+AC_CHECK_LIB(m, finite, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_FINITE, 1, [Define if you have finite])
+])
+AC_CHECK_LIB(m, _finite, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC__FINITE, 1, [Define if you have _finite])
+])
+AC_CHECK_LIB(m, isnan, [
+ AC_DEFINE_UNQUOTED(HAVE_FUNC_ISNAN, 1, [Define if you have isnan])
+])
+
+AC_DEFUN(AC_CHECK_PCREPOSIX,
+[
+ AC_MSG_CHECKING([for pcreposix])
+ AC_CACHE_VAL(ac_cv_have_pcreposix,
+ [
+ ac_save_libs="$LIBS"
+ KDE_FIND_PATH(pcre-config, PCRE_CONFIG, [${prefix}/bin /usr/local/bin /opt/local/bin], [PCRE_CONFIG="" ])
+ if test -n "$PCRE_CONFIG" && $PCRE_CONFIG --libs >/dev/null 2>&1; then
+ LIBS=`$PCRE_CONFIG --libs --libs-posix`
+ CPPFLAGS="$CPPFLAGS `$PCRE_CONFIG --cflags`"
+ else
+ LIBS="-lpcre -lpcreposix"
+ fi
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+ ac_LDFLAGS_save="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $all_libraries"
+ AC_TRY_LINK(
+ [#include <pcreposix.h>],
+ [regfree(0);],
+ [ac_cv_have_pcreposix="yes"],
+ [ac_cv_have_pcreposix="no"]
+ )
+ LIBS="$ac_save_libs"
+ LDFLAGS="$ac_LDFLAGS_save"
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ ])
+ AC_MSG_RESULT($ac_cv_have_pcreposix)
+ if test "$ac_cv_have_pcreposix" = "yes"; then
+ LIBPCRE="-lpcre -lpcreposix"
+ AC_DEFINE(HAVE_PCREPOSIX, 1, [Define if you have pcreposix libraries and header files.])
+ fi
+])
+AC_CHECK_PCREPOSIX
+AC_SUBST(LIBPCRE)
diff --git a/WebCore/src/kdelibs/kjs/create_hash_table b/WebCore/src/kdelibs/kjs/create_hash_table
new file mode 100755
index 0000000..85c6744
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/create_hash_table
@@ -0,0 +1,116 @@
+#! /usr/bin/perl
+
+$file = $ARGV[0];
+open(IN, $file) or die "No such file $file";
+
+@keys = ();
+@values = ();
+@attrs = ();
+
+my $inside = 0;
+my $name;
+my $size;
+my $hashsize;
+my $banner = 0;
+
+while (<IN>) {
+ chop;
+ s/^\s*//g;
+ if (/^\#|^$/) {
+ # comment. do nothing
+ } elsif (/^\@begin\s*(\w+)\s*(\d+)\s*$/ && !$inside) {
+ $inside = 1;
+ $name = $1;
+ $hashsize = $2;
+ } elsif (/^\@end\s*$/ && $inside) {
+ calcTable();
+ output();
+ @keys = ();
+ @values = ();
+ @attrs = ();
+ $inside = 0;
+ } elsif (/^(\w+)\s*([\w\:]+)\s*([\w\|]*)\s*$/ && $inside) {
+ push(@keys, $1);
+ push(@values, $2);
+ push(@attrs, length($3) > 0 ? $3 : "0");
+ } else {
+ die "invalid data";
+ }
+}
+
+die "missing closing \@end" if ($inside);
+
+sub calcTable() {
+ @table = ();
+ @links = ();
+ $size = $hashsize;
+ my $collisions = 0;
+ my $i = 0;
+ foreach $key (@keys) {
+ my $h = hashValue($key) % $hashsize;
+ while (defined($table[$h])) {
+ if (defined($links[$h])) {
+ $h = $links[$h];
+ } else {
+ $collisions++;
+ $links[$h] = $size;
+ $h = $size;
+ $size++;
+ }
+ }
+ $table[$h] = $i;
+ $i++;
+ }
+
+# print "// Number of collisions: $collisions\n";
+# printf "total size: $size\n";
+# my $i = 0;
+# foreach $entry (@table) {
+# print "$i " . $entry;
+# print " -> " . $links[$i] if (defined($links[$i]));
+# print "\n";
+# $i++;
+# }
+}
+
+sub hashValue {
+ @chars = split(/ */, @_[0]);
+ my $val = 0;
+ foreach $c (@chars) {
+ $val += ord($c);
+ }
+ return $val;
+}
+
+sub output {
+ if (!$banner) {
+ $banner = 1;
+ print "/* automatically generated from $file. DO NOT EDIT ! */\n";
+ }
+
+ print "\nnamespace KJS {\n";
+ print "\nconst struct HashEntry2 ${name}Entries[] = {\n";
+ my $i = 0;
+ foreach $entry (@table) {
+ if (defined($entry)) {
+ my $key = $keys[$entry];
+ print " \{ \"" . $key . "\"";
+ print ", " . $values[$entry];
+ print ", " . $attrs[$entry] . ", ";
+ if (defined($links[$i])) {
+ print "&${name}Entries[$links[$i]]" . " \}";
+ } else {
+ print "0 \}"
+ }
+ } else {
+ print " \{ 0, 0, 0, 0 \}";
+ }
+ print "," unless ($i == $size - 1);
+ print "\n";
+ $i++;
+ }
+ print "};\n";
+ print "\nconst struct HashTable2 $name = ";
+ print "\{ 2, $size, ${name}Entries, $hashsize \};\n\n";
+ print "}; // namespace\n";
+}
diff --git a/WebCore/src/kdelibs/kjs/date_object.cpp b/WebCore/src/kdelibs/kjs/date_object.cpp
new file mode 100644
index 0000000..ab81504
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/date_object.cpp
@@ -0,0 +1,466 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifndef HAVE_SYS_TIMEB_H
+#define HAVE_SYS_TIMEB_H 0
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+# include <time.h>
+# endif
+#endif
+#if HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif // HAVE_SYS_PARAM_H
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <locale.h>
+
+#include "kjs.h"
+#include "date_object.h"
+
+namespace KJS {
+
+ class DateObjectFunc : public InternalFunctionImp {
+ public:
+ DateObjectFunc(int i) : id(i) { };
+ Completion execute(const List &);
+ enum { Parse, UTC };
+ private:
+ int id;
+ };
+
+ class DateProtoFunc : public InternalFunctionImp {
+ public:
+ DateProtoFunc(int i, bool u);
+ Completion execute(const List &);
+ enum { ToString, ToDateString, ToTimeString, ToLocaleString,
+ ToLocaleDateString, ToLocaleTimeString, ValueOf, GetTime,
+ GetFullYear, GetMonth, GetDate, GetDay, GetHours, GetMinutes,
+ GetSeconds, GetMilliSeconds, GetTimezoneOffset, SetTime,
+ SetMilliSeconds, SetSeconds, SetMinutes, SetHours, SetDate,
+ SetMonth, SetFullYear, ToUTCString,
+ // non-normative properties (Appendix B)
+ GetYear, SetYear, ToGMTString };
+ private:
+ int id;
+ bool utc;
+ };
+
+ // helper functions
+ KJSO parseDate(const String &s);
+ KJSO timeClip(const KJSO &t);
+};
+
+using namespace KJS;
+
+KJSO KJS::parseDate(const String &s)
+{
+ UString u = s.value();
+ int firstSlash = u.find('/');
+ if ( firstSlash == -1 )
+ {
+ /* TODO parse dates like "December 25, 1995 23:15:00"*/
+ fprintf(stderr,"KJS::parseDate parsing for this format isn't implemented\n%s", u.ascii());
+ return Number(0);
+ }
+ else
+ {
+ // Found 12/31/2099 on some website -> obviously MM/DD/YYYY
+ int month = u.substr(0,firstSlash).toULong();
+ int secondSlash = u.find('/',firstSlash+1);
+ //fprintf(stdout,"KJS::parseDate firstSlash=%d, secondSlash=%d\n", firstSlash, secondSlash);
+ if ( secondSlash == -1 )
+ {
+ fprintf(stderr,"KJS::parseDate parsing for this format isn't implemented\n%s", u.ascii());
+ return Number(0);
+ }
+ int day = u.substr(firstSlash+1,secondSlash-firstSlash-1).toULong();
+ int year = u.substr(secondSlash+1).toULong();
+ //fprintf(stdout,"KJS::parseDate day=%d, month=%d, year=%d\n", day, month, year);
+ struct tm t;
+ memset( &t, 0, sizeof(t) );
+ year = (year > 2037) ? 2037 : year; // mktime is limited to 2037 !!!
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = month-1; // mktime wants 0-11 for some reason
+ t.tm_mday = day;
+ time_t seconds = mktime(&t);
+ if ( seconds == -1 )
+ {
+ fprintf(stderr,"KJS::parseDate mktime returned -1.\n%s", u.ascii());
+ return Undefined();
+ }
+ else
+ return Number(seconds * 1000.0);
+ }
+}
+
+KJSO KJS::timeClip(const KJSO &t)
+{
+ /* TODO */
+ return t;
+}
+
+DateObject::DateObject(const Object& funcProto, const Object &dateProto)
+ : ConstructorImp(funcProto, 7)
+{
+ // ECMA 15.9.4.1 Date.prototype
+ setPrototypeProperty(dateProto);
+}
+
+// ECMA 15.9.2
+Completion DateObject::execute(const List &)
+{
+ time_t t = time(0L);
+ UString s(ctime(&t));
+
+ // return formatted string minus trailing \n
+ return Completion(ReturnValue, String(s.substr(0, s.size() - 1)));
+}
+
+// ECMA 15.9.3
+Object DateObject::construct(const List &args)
+{
+ KJSO value;
+
+ int numArgs = args.size();
+
+ if (numArgs == 0) { // new Date() ECMA 15.9.3.3
+#if HAVE_SYS_TIMEB_H
+# if defined(__BORLANDC__)
+ struct timeb timebuffer;
+ ftime(&timebuffer);
+# else
+ struct _timeb timebuffer;
+ _ftime(&timebuffer);
+# endif
+ double utc = floor((double)timebuffer.time * 1000.0 + (double)timebuffer.millitm);
+#else
+ struct timeval tv;
+ gettimeofday(&tv, 0L);
+ double utc = floor((double)tv.tv_sec * 1000.0 + (double)tv.tv_usec / 1000.0);
+#endif
+ value = Number(utc);
+ } else if (numArgs == 1) {
+ KJSO p = args[0].toPrimitive();
+ if (p.isA(StringType))
+ value = parseDate(p.toString());
+ else
+ value = p.toNumber();
+ } else {
+ struct tm t;
+ memset(&t, 0, sizeof(t));
+ Number y = args[0].toNumber();
+ /* TODO: check for NaN */
+ int year = y.toInt32();
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = args[1].toInt32();
+ t.tm_mday = (numArgs >= 3) ? args[2].toInt32() : 1;
+ t.tm_hour = (numArgs >= 4) ? args[3].toInt32() : 0;
+ t.tm_min = (numArgs >= 5) ? args[4].toInt32() : 0;
+ t.tm_sec = (numArgs >= 6) ? args[5].toInt32() : 0;
+ t.tm_isdst = -1;
+ int ms = (numArgs >= 7) ? args[6].toInt32() : 0;
+ value = Number(mktime(&t) * 1000.0 + ms);
+ }
+
+ return Object::create(DateClass, timeClip(value));
+}
+
+KJSO DateObject::get(const UString &p) const
+{
+ int id;
+
+ if (p == "parse")
+ id = DateObjectFunc::Parse;
+ else if (p == "UTC")
+ id = DateObjectFunc::UTC;
+ else
+ return Imp::get(p);
+
+ return Function(new DateObjectFunc(id));
+}
+
+// ECMA 15.9.4.2 - 3
+Completion DateObjectFunc::execute(const List &args)
+{
+ KJSO result;
+
+ if (id == Parse)
+ if (args[0].isA(StringType))
+ result = parseDate(args[0].toString());
+ else
+ result = Undefined();
+ else {
+ struct tm t;
+ memset(&t, 0, sizeof(t));
+ int n = args.size();
+ Number y = args[0].toNumber();
+ /* TODO: check for NaN */
+ int year = y.toInt32();
+ t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.tm_mon = args[1].toInt32();
+ t.tm_mday = (n >= 3) ? args[2].toInt32() : 1;
+ t.tm_hour = (n >= 4) ? args[3].toInt32() : 0;
+ t.tm_min = (n >= 5) ? args[4].toInt32() : 0;
+ t.tm_sec = (n >= 6) ? args[5].toInt32() : 0;
+ int ms = (n >= 7) ? args[6].toInt32() : 0;
+ result = Number(mktime(&t) * 1000.0 + ms);
+ }
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.9.4
+DatePrototype::DatePrototype(const Object& proto)
+ : ObjectImp(DateClass, Number(NaN), proto)
+{
+ // The constructor will be added later in DateObject's constructor
+}
+
+KJSO DatePrototype::get(const UString &p) const
+{
+ int id;
+
+ if (p == "toString" || p == "toUTCString")
+ id = DateProtoFunc::ToString;
+ else if (p == "toDateString")
+ id = DateProtoFunc::ToDateString;
+ else if (p == "toTimeString")
+ id = DateProtoFunc::ToTimeString;
+ else if (p == "toLocaleString")
+ id = DateProtoFunc::ToLocaleString;
+ else if (p == "toLocaleDateString")
+ id = DateProtoFunc::ToLocaleDateString;
+ else if (p == "toLocaleTimeString")
+ id = DateProtoFunc::ToLocaleTimeString;
+ else if (p == "valueOf")
+ id = DateProtoFunc::ValueOf;
+ else if (p == "getTime")
+ id = DateProtoFunc::GetTime;
+ else if (p == "getFullYear" || p == "getUTCFullYear")
+ id = DateProtoFunc::GetFullYear;
+ else if (p == "toGMTString")
+ id = DateProtoFunc::ToGMTString;
+ else if (p == "getMonth" || p == "getUTCMonth")
+ id = DateProtoFunc::GetMonth;
+ else if (p == "getDate" || p == "getUTCDate")
+ id = DateProtoFunc::GetDate;
+ else if (p == "getDay" || p == "getUTCDay")
+ id = DateProtoFunc::GetDay;
+ else if (p == "getHours" || p == "getUTCHours")
+ id = DateProtoFunc::GetHours;
+ else if (p == "getMinutes" || p == "getUTCMinutes")
+ id = DateProtoFunc::GetMinutes;
+ else if (p == "getSeconds" || p == "getUTCSeconds")
+ id = DateProtoFunc::GetSeconds;
+ else if (p == "getMilliseconds" || p == "getUTCMilliseconds")
+ id = DateProtoFunc::GetMilliSeconds;
+ else if (p == "getTimezoneOffset")
+ id = DateProtoFunc::GetTimezoneOffset;
+ else if (p == "setTime")
+ id = DateProtoFunc::SetTime;
+ else if (p == "setMilliseconds" || p == "setUTCMilliseconds")
+ id = DateProtoFunc::SetMilliSeconds;
+ else if (p == "setSeconds" || p == "setUTCSeconds")
+ id = DateProtoFunc::SetSeconds;
+ else if (p == "setMinutes" || p == "setUTCMinutes")
+ id = DateProtoFunc::SetMinutes;
+ else if (p == "setHours" || p == "setUTCHours")
+ id = DateProtoFunc::SetHours;
+ else if (p == "setDate" || p == "setUTCDate")
+ id = DateProtoFunc::SetDate;
+ else if (p == "setMonth" || p == "setUTCMonth")
+ id = DateProtoFunc::SetMonth;
+ else if (p == "setFullYear" || p == "setUTCFullYear")
+ id = DateProtoFunc::SetFullYear;
+ else if (p == "setYear" )
+ id = DateProtoFunc::SetYear;
+ // non-normative
+ else if (p == "getYear")
+ id = DateProtoFunc::GetYear;
+ else if (p == "toGMTString")
+ id = DateProtoFunc::ToGMTString;
+ else
+ return Undefined();
+
+ bool utc = (p.find("UTC") >= 0) ? true : false;
+ return Function(new DateProtoFunc(id, utc));
+}
+
+DateProtoFunc::DateProtoFunc(int i, bool u) : id(i), utc(u)
+{
+}
+
+Completion DateProtoFunc::execute(const List &args)
+{
+ KJSO result;
+ UString s;
+ const int bufsize=100;
+ char timebuffer[bufsize];
+ char *oldlocale = setlocale(LC_TIME,NULL);
+ if (!oldlocale)
+ oldlocale = setlocale(LC_ALL, NULL);
+ Object thisObj = Object::dynamicCast(thisValue());
+ KJSO v = thisObj.internalValue();
+ double milli = v.toNumber().value();
+ time_t tv = (time_t) floor(milli / 1000.0);
+ int ms = int(milli - tv * 1000.0);
+
+ struct tm *t;
+ if (utc)
+ t = gmtime(&tv);
+ else
+ t = localtime(&tv);
+
+ switch (id) {
+ case ToString:
+ s = ctime(&tv);
+ result = String(s.substr(0, s.size() - 1));
+ break;
+ case ToDateString:
+ case ToTimeString:
+ case ToGMTString:
+ setlocale(LC_TIME,"C");
+ if (id == DateProtoFunc::ToDateString) {
+ strftime(timebuffer, bufsize, "%x",t);
+ } else if (id == DateProtoFunc::ToTimeString) {
+ strftime(timebuffer, bufsize, "%X",t);
+ } else {
+ t = gmtime(&tv);
+ strftime(timebuffer, bufsize, "%a, %d-%b-%y %H:%M:%S %Z", t);
+ }
+ setlocale(LC_TIME,oldlocale);
+ result = String(timebuffer);
+ break;
+ case ToLocaleString:
+ strftime(timebuffer, bufsize, "%c", t);
+ result = String(timebuffer);
+ break;
+ case ToLocaleDateString:
+ strftime(timebuffer, bufsize, "%x", t);
+ result = String(timebuffer);
+ break;
+ case ToLocaleTimeString:
+ strftime(timebuffer, bufsize, "%X", t);
+ result = String(timebuffer);
+ break;
+ case ValueOf:
+ result = Number(milli);
+ break;
+ case GetTime:
+ if (thisObj.getClass() == DateClass)
+ result = Number(milli);
+ else
+ result = Error::create(TypeError);
+ break;
+ case GetYear:
+ result = Number(t->tm_year);
+ break;
+ case GetFullYear:
+ result = Number(1900 + t->tm_year);
+ break;
+ case GetMonth:
+ result = Number(t->tm_mon);
+ break;
+ case GetDate:
+ result = Number(t->tm_mday);
+ break;
+ case GetDay:
+ result = Number(t->tm_wday);
+ break;
+ case GetHours:
+ result = Number(t->tm_hour);
+ break;
+ case GetMinutes:
+ result = Number(t->tm_min);
+ break;
+ case GetSeconds:
+ result = Number(t->tm_sec);
+ break;
+ case GetMilliSeconds:
+ result = Undefined();
+ break;
+ case GetTimezoneOffset:
+#if defined BSD || defined(__APPLE__)
+ result = Number(-( t->tm_gmtoff / 60 ) + ( t->tm_isdst ? 60 : 0 ));
+#else
+# if defined(__BORLANDC__)
+#error please add daylight savings offset here!
+ result = Number(_timezone / 60 - (_daylight ? 60 : 0));
+# else
+ result = Number(( timezone / 60 - ( daylight ? 60 : 0 )));
+# endif
+#endif
+ break;
+ case SetTime:
+ milli = args[0].round();
+ result = Number(milli);
+ thisObj.setInternalValue(result);
+ break;
+ case SetMilliSeconds:
+ ms = args[0].toInt32();
+ break;
+ case SetSeconds:
+ t->tm_sec = args[0].toInt32();
+ break;
+ case SetMinutes:
+ t->tm_min = args[0].toInt32();
+ break;
+ case SetHours:
+ t->tm_hour = args[0].toInt32();
+ break;
+ case SetDate:
+ t->tm_mday = args[0].toInt32();
+ break;
+ case SetMonth:
+ t->tm_mon = args[0].toInt32();
+ break;
+ case SetFullYear:
+ t->tm_year = args[0].toInt32() - 1900;
+ break;
+ case SetYear:
+ t->tm_year = args[0].toInt32() >= 1900 ? args[0].toInt32() - 1900 : args[0].toInt32();
+ break;
+ }
+
+ if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
+ id == SetMinutes || id == SetHours || id == SetDate ||
+ id == SetMonth || id == SetFullYear ) {
+ result = Number(mktime(t) * 1000.0 + ms);
+ thisObj.setInternalValue(result);
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/WebCore/src/kdelibs/kjs/date_object.h b/WebCore/src/kdelibs/kjs/date_object.h
new file mode 100644
index 0000000..5eed675
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/date_object.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _DATE_OBJECT_H_
+#define _DATE_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class DateObject : public ConstructorImp {
+ public:
+ DateObject(const Object& funcProto, const Object &dateProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ KJSO get(const UString &p) const;
+ };
+
+ class DatePrototype : public ObjectImp {
+ public:
+ DatePrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/debugger.cpp b/WebCore/src/kdelibs/kjs/debugger.cpp
new file mode 100644
index 0000000..e0f3859
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/debugger.cpp
@@ -0,0 +1,229 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef KJS_DEBUGGER
+
+#include "debugger.h"
+#include "kjs.h"
+#include "internal.h"
+#include "ustring.h"
+
+using namespace KJS;
+
+Debugger::Debugger(KJScript *engine)
+ : eng(0L),
+ sid(-1)
+{
+ attach(engine);
+}
+
+Debugger::~Debugger()
+{
+ detach();
+}
+
+void Debugger::attach(KJScript *e)
+{
+ dmode = Disabled;
+ if (e) {
+ if (!eng || e->rep != eng->rep) {
+ eng = e;
+ eng->rep->attachDebugger(this);
+ }
+ } else {
+ eng = 0L;
+ }
+ reset();
+}
+
+KJScript *Debugger::engine() const
+{
+ return eng;
+}
+
+void Debugger::detach()
+{
+ reset();
+ if (!eng)
+ return;
+ eng->rep->attachDebugger(0L);
+ eng = 0L;
+}
+
+void Debugger::setMode(Mode m)
+{
+ dmode = m;
+}
+
+Debugger::Mode Debugger::mode() const
+{
+ return dmode;
+}
+
+// supposed to be overriden by the user
+bool Debugger::stopEvent()
+{
+ return true;
+}
+
+void Debugger::callEvent(const UString &, const UString &)
+{
+}
+
+void Debugger::returnEvent()
+{
+}
+
+void Debugger::reset()
+{
+ l = -1;
+}
+
+int Debugger::freeSourceId() const
+{
+ return eng ? eng->rep->sourceId()+1 : -1;
+}
+
+bool Debugger::setBreakpoint(int id, int line)
+{
+ if (!eng)
+ return false;
+ return eng->rep->setBreakpoint(id, line, true);
+}
+
+bool Debugger::deleteBreakpoint(int id, int line)
+{
+ if (!eng)
+ return false;
+ return eng->rep->setBreakpoint(id, line, false);
+}
+
+void Debugger::clearAllBreakpoints(int id)
+{
+ if (!eng)
+ return;
+ eng->rep->setBreakpoint(id, -1, false);
+}
+
+UString Debugger::varInfo(const UString &ident)
+{
+ if (!eng)
+ return UString();
+
+ int dot = ident.find('.');
+ if (dot < 0)
+ dot = ident.size();
+ UString sub = ident.substr(0, dot);
+ KJSO obj;
+ // resolve base
+ if (sub == "this") {
+ obj = Context::current()->thisValue();
+ } else {
+ const List *chain = Context::current()->pScopeChain();
+ ListIterator scope = chain->begin();
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+ obj = scope->get(ident);
+ break;
+ }
+ scope++;
+ }
+ if (scope == chain->end())
+ return UString();
+ }
+ // look up each part of a.b.c.
+ while (dot < ident.size()) {
+ int olddot = dot;
+ dot = ident.find('.', olddot+1);
+ if (dot < 0)
+ dot = ident.size();
+ sub = ident.substr(olddot+1, dot-olddot-1);
+ obj = obj.get(sub);
+ if (!obj.isDefined())
+ break;
+ }
+
+ return sub + "=" + objInfo(obj) + ":" + UString(obj.imp()->typeInfo()->name);
+}
+
+// called by varInfo() and recursively by itself on each properties
+UString Debugger::objInfo(const KJSO &obj) const
+{
+ const char *cnames[] = { "Undefined", "Array", "String", "Boolean",
+ "Number", "Object", "Date", "RegExp",
+ "Error", "Function" };
+ PropList *plist = obj.imp()->propList(0, 0, false);
+ if (!plist)
+ return obj.toString().value();
+ else {
+ UString result = "{";
+ while (1) {
+ result += plist->name + "=";
+ KJSO p = obj.get(plist->name);
+ result += objInfo(p) + ":";
+ Object obj = Object::dynamicCast(p);
+ if (obj.isNull())
+ result += p.imp()->typeInfo()->name;
+ else
+ result += cnames[int(obj.getClass())];
+ plist = plist->next;
+ if (!plist)
+ break;
+ result += ",";
+ }
+ result += "}";
+ return result;
+ }
+}
+
+bool Debugger::setVar(const UString &ident, const KJSO &value)
+{
+ if (!eng)
+ return false;
+ const List *chain = Context::current()->pScopeChain();
+ ListIterator scope = chain->begin();
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+ if (!scope->canPut(ident))
+ return false;
+ scope->put(ident, value);
+ return true;
+ }
+ scope++;
+ }
+ // didn't find variable
+ return false;
+}
+
+// called from the scripting engine each time a statement node is hit.
+bool Debugger::hit(int line, bool breakPoint)
+{
+ l = line;
+ if (!eng)
+ return true;
+
+ if (!breakPoint && ( mode() == Continue || mode() == Disabled ) )
+ return true;
+
+ bool ret = stopEvent();
+ eng->init(); // in case somebody used a different interpreter meanwhile
+ return ret;
+}
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/debugger.h b/WebCore/src/kdelibs/kjs/debugger.h
new file mode 100644
index 0000000..b0e97fe
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/debugger.h
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSDEBUGGER_H_
+#define _KJSDEBUGGER_H_
+
+#include "internal.h"
+
+namespace KJS {
+
+ //
+ // NOTE: this interface is not ready, yet. Do not use unless you
+ // don't mind source and binary incompatible changes that may arise
+ // before the final version is released.
+ //
+
+#ifdef KJS_DEBUGGER
+ class Debugger {
+ friend class KJScriptImp;
+ friend class StatementNode;
+ friend class DeclaredFunctionImp;
+ friend class FunctionImp;
+ public:
+ /**
+ * Available modes of the debugger.
+ */
+ enum Mode { Disabled = 0, Next, Step, Continue, Stop };
+ /**
+ * Construct a debugger and attach it to the scripting engine s.
+ */
+ Debugger(KJScript *s);
+ /**
+ * Destruct the debugger and detach from the scripting engine we
+ * might have been attached to.
+ */
+ virtual ~Debugger();
+ /**
+ * Attaches the debugger to specified scripting engine.
+ */
+ void attach(KJScript *e);
+ /**
+ * Returns the engine the interpreter is currently attached to. Null
+ * if there isn't any.
+ */
+ KJScript* engine() const;
+ /**
+ * Detach the debugger from any scripting engine.
+ */
+ void detach();
+ /**
+ * Set debugger into specified mode. This will influence further behaviour
+ * if execution of the programm is started or continued.
+ */
+ virtual void setMode(Mode m);
+ /**
+ * Returns the current operation mode.
+ */
+ Mode mode() const;
+ /**
+ * Returns the line number the debugger currently has stopped at.
+ * -1 if the debugger is not in a break status.
+ */
+ int lineNumber() const { return l; }
+ /**
+ * Returns the source id the debugger currently has stopped at.
+ * -1 if the debugger is not in a break status.
+ */
+ int sourceId() const { return sid; }
+ /**
+ * Sets a breakpoint in the first statement where line lies in between
+ * the statements range. Returns true if sucessfull, false if no
+ * matching statement could be found.
+ */
+ bool setBreakpoint(int id, int line);
+ bool deleteBreakpoint(int id, int line);
+ void clearAllBreakpoints(int id=-1);
+ /**
+ * Returns the value of ident out of the current context in string form
+ */
+ UString varInfo(const UString &ident);
+ /**
+ * Set variable ident to value. Returns true if successful, false if
+ * the specified variable doesn't exist or isn't writable.
+ */
+ bool setVar(const UString &ident, const KJSO &value);
+
+ protected:
+ /**
+ * Invoked in case a breakpoint or the next statement is reached in step
+ * mode. The return value decides whether execution will continue. True
+ * denotes continuation, false an abortion, respectively.
+ *
+ * The default implementation does nothing. Overload this method if
+ * you want to process this event.
+ */
+ virtual bool stopEvent();
+ /**
+ * Returns an integer that will be assigned to the code passed
+ * next to one of the KJScript::evaluate() methods. It's basically
+ * a counter to will only be reset to 0 on KJScript::clear().
+ *
+ * This information is useful in case you evaluate multiple blocks of
+ * code containing some function declarations. Keep a map of source id/
+ * code pairs, query sourceId() in case of a stopEvent() and update
+ * your debugger window with the matching source code.
+ */
+ int freeSourceId() const;
+ /**
+ * Invoked on each function call. Use together with @ref returnEvent
+ * if you want to keep track of the call stack.
+ */
+ virtual void callEvent(const UString &fn = UString::null,
+ const UString &s = UString::null);
+ /**
+ * Invoked on each function exit.
+ */
+ virtual void returnEvent();
+
+ private:
+ void reset();
+ bool hit(int line, bool breakPoint);
+ void setSourceId(int i) { sid = i; }
+ UString objInfo(const KJSO &obj) const;
+
+ KJScript *eng;
+ Mode dmode;
+ int l;
+ int sid;
+ };
+#endif
+
+};
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/error_object.cpp b/WebCore/src/kdelibs/kjs/error_object.cpp
new file mode 100644
index 0000000..a5aa6d8
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/error_object.cpp
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "internal.h"
+#include "error_object.h"
+#include "debugger.h"
+
+using namespace KJS;
+
+const char *ErrorObject::errName[] = {
+ "No Error",
+ "Error",
+ "EvalError",
+ "RangeError",
+ "ReferenceError",
+ "SyntaxError",
+ "TypeError",
+ "URIError"
+};
+
+ErrorObject::ErrorObject(const Object &funcProto, const Object &errProto,
+ ErrorType t)
+ : ConstructorImp(funcProto, 1), errType(t)
+{
+ // ECMA 15.11.3.1 Error.prototype
+ setPrototypeProperty(errProto);
+ const char *n = errName[errType];
+
+ put("name", String(n));
+}
+
+ErrorObject::ErrorObject(const Object& proto, ErrorType t,
+ const char *m, int l)
+ : ConstructorImp(proto, 1), errType(t)
+{
+ const char *n = errName[errType];
+
+ put("name", String(n));
+ put("message", String(m));
+ put("line", Number(l));
+#ifdef KJS_DEBUGGER
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ if (dbg)
+ put("sid", Number(dbg->sourceId()));
+#endif
+}
+
+// ECMA 15.9.2
+Completion ErrorObject::execute(const List &args)
+{
+ // "Error()" gives the sames result as "new Error()"
+ return Completion(ReturnValue, construct(args));
+}
+
+// ECMA 15.9.3
+Object ErrorObject::construct(const List &args)
+{
+ if (args.isEmpty() == 1 || !args[0].isDefined())
+ return Object::create(ErrorClass, Undefined());
+
+ String message = args[0].toString();
+ return Object::create(ErrorClass, message);
+}
+
+Object ErrorObject::create(ErrorType e, const char *m, int l)
+{
+ Global global(Global::current());
+ KJSO prot = Global::current().get("[[Error.prototype]]");
+ assert(prot.isObject());
+ Imp *d = new ErrorObject(Object(prot.imp()), e, m, l);
+
+ return Object(d);
+}
+
+// ECMA 15.9.4
+ErrorPrototype::ErrorPrototype(const Object& proto)
+ : ObjectImp(ErrorClass, Undefined(), proto)
+{
+ // The constructor will be added later in ErrorObject's constructor
+}
+
+KJSO ErrorPrototype::get(const UString &p) const
+{
+ const char *s;
+
+ /* TODO: are these properties dynamic, i.e. should we put() them ? */
+ if (p == "name")
+ s = "Error";
+ else if (p == "message")
+ s = "Error message.";
+ else if (p == "toString")
+ return Function(new ErrorProtoFunc());
+ else
+ return Imp::get(p);
+
+ return String(s);
+}
+
+Completion ErrorProtoFunc::execute(const List &)
+{
+ // toString()
+ const char *s = "Error message.";
+
+ return Completion(ReturnValue, String(s));
+}
+
diff --git a/WebCore/src/kdelibs/kjs/error_object.h b/WebCore/src/kdelibs/kjs/error_object.h
new file mode 100644
index 0000000..8e515f0
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/error_object.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ERROR_OBJECT_H_
+#define _ERROR_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ErrorObject : public ConstructorImp {
+ public:
+ ErrorObject(const Object &funcProto, const Object &errProto,
+ ErrorType t = GeneralError);
+ ErrorObject(const Object& proto, ErrorType t, const char *m, int l = -1);
+ Completion execute(const List &);
+ Object construct(const List &);
+ static Object create(ErrorType e, const char *m, int ln);
+ private:
+ ErrorType errType;
+ static const char *errName[];
+ };
+
+ class ErrorPrototype : public ObjectImp {
+ public:
+ ErrorPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+ class ErrorProtoFunc : public InternalFunctionImp {
+ public:
+ ErrorProtoFunc() { }
+ Completion execute(const List &);
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/function.cpp b/WebCore/src/kdelibs/kjs/function.cpp
new file mode 100644
index 0000000..22db1d2
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/function.cpp
@@ -0,0 +1,355 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "function.h"
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "nodes.h"
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace KJS;
+
+const TypeInfo FunctionImp::info = { "Function", FunctionType,
+ &ObjectImp::info, 0, 0 };
+const TypeInfo InternalFunctionImp::info = { "InternalFunction",
+ InternalFunctionType,
+ &FunctionImp::info, 0, 0 };
+const TypeInfo ConstructorImp::info = { "Function", ConstructorType,
+ &InternalFunctionImp::info, 0, 0 };
+
+namespace KJS {
+
+ class Parameter {
+ public:
+ Parameter(const UString &n) : name(n), next(0L) { }
+ ~Parameter() { delete next; }
+ UString name;
+ Parameter *next;
+ };
+
+};
+
+FunctionImp::FunctionImp()
+ : ObjectImp(/*TODO*/BooleanClass), param(0L)
+{
+}
+
+FunctionImp::FunctionImp(const UString &n)
+ : ObjectImp(/*TODO*/BooleanClass), ident(n), param(0L)
+{
+}
+
+FunctionImp::~FunctionImp()
+{
+ delete param;
+}
+
+KJSO FunctionImp::thisValue() const
+{
+ return KJSO(Context::current()->thisValue());
+}
+
+void FunctionImp::addParameter(const UString &n)
+{
+ Parameter **p = ¶m;
+ while (*p)
+ p = &(*p)->next;
+
+ *p = new Parameter(n);
+}
+
+void FunctionImp::setLength(int l)
+{
+ put("length", Number(l), ReadOnly|DontDelete|DontEnum);
+}
+
+// ECMA 10.1.3
+void FunctionImp::processParameters(const List *args)
+{
+ KJSO variable = Context::current()->variableObject();
+
+ assert(args);
+
+#ifdef KJS_VERBOSE
+ fprintf(stderr, "---------------------------------------------------\n"
+ "processing parameters for %s call\n",
+ name().isEmpty() ? "(internal)" : name().ascii());
+#endif
+
+ if (param) {
+ ListIterator it = args->begin();
+ Parameter **p = ¶m;
+ while (*p) {
+ if (it != args->end()) {
+#ifdef KJS_VERBOSE
+ fprintf(stderr, "setting parameter %s ", (*p)->name.ascii());
+ printInfo("to", *it);
+#endif
+ variable.put((*p)->name, *it);
+ it++;
+ } else
+ variable.put((*p)->name, Undefined());
+ p = &(*p)->next;
+ }
+ }
+#ifdef KJS_VERBOSE
+ else {
+ for (int i = 0; i < args->size(); i++)
+ printInfo("setting argument", (*args)[i]);
+ }
+#endif
+#ifdef KJS_DEBUGGER
+ if (KJScriptImp::current()->debugger()) {
+ UString argStr;
+ for (int i = 0; i < args->size(); i++) {
+ if (i > 0)
+ argStr += ", ";
+ Imp *a = (*args)[i].imp();
+ argStr += a->toString().value() + " : " + UString(a->typeInfo()->name);
+ }
+ UString n = name().isEmpty() ? UString( "(internal)" ) : name();
+ KJScriptImp::current()->debugger()->callEvent(n, argStr);
+ }
+#endif
+}
+
+// ECMA 13.2.1
+KJSO FunctionImp::executeCall(Imp *thisV, const List *args)
+{
+ return executeCall(thisV,args,0);
+}
+
+KJSO FunctionImp::executeCall(Imp *thisV, const List *args, const List *extraScope)
+{
+ bool dummyList = false;
+ if (!args) {
+ args = new List();
+ dummyList = true;
+ }
+
+ KJScriptImp *curr = KJScriptImp::current();
+ Context *save = curr->context();
+
+ Context *ctx = new Context(codeType(), save, this, args, thisV);
+ curr->setContext(ctx);
+
+ int numScopes = 0;
+ if (extraScope) {
+ ListIterator scopeIt = extraScope->begin();
+ for (; scopeIt != extraScope->end(); scopeIt++) {
+ KJSO obj(*scopeIt);
+ ctx->pushScope(obj);
+ numScopes++;
+ }
+ }
+
+ // assign user supplied arguments to parameters
+ processParameters(args);
+
+ Completion comp = execute(*args);
+
+ if (dummyList)
+ delete args;
+
+ int i;
+ for (i = 0; i < numScopes; i++)
+ ctx->popScope();
+
+ put("arguments", Null());
+ delete ctx;
+ curr->setContext(save);
+
+#ifdef KJS_VERBOSE
+ if (comp.complType() == Throw)
+ printInfo("throwing", comp.value());
+ else if (comp.complType() == ReturnValue)
+ printInfo("returning", comp.value());
+ else
+ fprintf(stderr, "returning: undefined\n");
+#endif
+#ifdef KJS_DEBUGGER
+ if (KJScriptImp::current()->debugger())
+ KJScriptImp::current()->debugger()->returnEvent();
+#endif
+
+ if (comp.complType() == Throw)
+ return comp.value();
+ else if (comp.complType() == ReturnValue)
+ return comp.value();
+ else
+ return Undefined();
+}
+
+UString FunctionImp::name() const
+{
+ return ident;
+}
+
+InternalFunctionImp::InternalFunctionImp()
+{
+}
+
+InternalFunctionImp::InternalFunctionImp(int l)
+{
+ if (l >= 0)
+ setLength(l);
+}
+
+InternalFunctionImp::InternalFunctionImp(const UString &n)
+ : FunctionImp(n)
+{
+}
+
+String InternalFunctionImp::toString() const
+{
+ if (name().isNull())
+ return UString("(Internal function)");
+ else
+ return UString("function " + name() + "()");
+}
+
+Completion InternalFunctionImp::execute(const List &)
+{
+ return Completion(ReturnValue, Undefined());
+}
+
+ConstructorImp::ConstructorImp() {
+ setPrototype(Global::current().functionPrototype());
+ // TODO ??? put("constructor", this);
+ setLength(1);
+}
+
+ConstructorImp::ConstructorImp(const UString &n)
+ : InternalFunctionImp(n)
+{
+}
+
+ConstructorImp::ConstructorImp(const KJSO &p, int len)
+{
+ setPrototype(p);
+ // TODO ??? put("constructor", *this);
+ setLength(len);
+}
+
+ConstructorImp::ConstructorImp(const UString &n, const KJSO &p, int len)
+ : InternalFunctionImp(n)
+{
+ setPrototype(p);
+ // TODO ??? put("constructor", *this);
+ setLength(len);
+}
+
+ConstructorImp::~ConstructorImp() { }
+
+Completion ConstructorImp::execute(const List &)
+{
+ /* TODO */
+ return Completion(ReturnValue, Null());
+}
+
+Function::Function(Imp *d)
+ : KJSO(d)
+{
+ if (d) {
+ static_cast<FunctionImp*>(rep)->attr = ImplicitNone;
+ assert(Global::current().hasProperty("[[Function.prototype]]"));
+ setPrototype(Global::current().functionPrototype());
+ }
+}
+
+Completion Function::execute(const List &args)
+{
+ assert(rep);
+ return static_cast<FunctionImp*>(rep)->execute(args);
+}
+
+bool Function::hasAttribute(FunctionAttribute a) const
+{
+ assert(rep);
+ return static_cast<FunctionImp*>(rep)->hasAttribute(a);
+}
+
+#if 0
+InternalFunction::InternalFunction(Imp *d)
+ : Function(d)
+{
+ param = 0L;
+}
+
+InternalFunction::~InternalFunction()
+{
+}
+#endif
+
+Constructor::Constructor(Imp *d)
+ : Function(d)
+{
+ if (d) {
+ assert(Global::current().hasProperty("[[Function.prototype]]"));
+ setPrototype(Global::current().get("[[Function.prototype]]"));
+ put("constructor", *this);
+ KJSO tmp(d); // protect from GC
+ ((FunctionImp*)d)->setLength(1);
+ }
+}
+
+#if 0
+Constructor::Constructor(const Object& proto, int len)
+{
+ setPrototype(proto);
+ put("constructor", *this);
+ put("length", len, DontEnum);
+}
+#endif
+
+Constructor::~Constructor()
+{
+}
+
+Completion Constructor::execute(const List &)
+{
+ /* TODO: call construct instead ? */
+ return Completion(ReturnValue, Undefined());
+}
+
+Object Constructor::construct(const List &args)
+{
+ assert(rep && rep->type() == ConstructorType);
+ return ((ConstructorImp*)rep)->construct(args);
+}
+
+Constructor Constructor::dynamicCast(const KJSO &obj)
+{
+ // return null object on type mismatch
+ if (!obj.isA(ConstructorType))
+ return Constructor(0L);
+
+ return Constructor(obj.imp());
+}
+
+KJSO Function::thisValue() const
+{
+ return KJSO(Context::current()->thisValue());
+}
diff --git a/WebCore/src/kdelibs/kjs/function.h b/WebCore/src/kdelibs/kjs/function.h
new file mode 100644
index 0000000..70c1f3a
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/function.h
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_FUNCTION_H_
+#define _KJS_FUNCTION_H_
+
+#include <assert.h>
+
+#include "object.h"
+#include "types.h"
+
+namespace KJS {
+
+ enum CodeType { GlobalCode,
+ EvalCode,
+ FunctionCode,
+ AnonymousCode,
+ HostCode };
+
+ enum FunctionAttribute { ImplicitNone, ImplicitThis, ImplicitParents };
+
+ class Function;
+ class Parameter;
+
+ /**
+ * @short Implementation class for Functions.
+ */
+ class FunctionImp : public ObjectImp {
+ friend class Function;
+ public:
+ FunctionImp();
+ FunctionImp(const UString &n);
+ virtual ~FunctionImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &) = 0;
+ bool hasAttribute(FunctionAttribute a) const { return (attr & a) != 0; }
+ virtual CodeType codeType() const = 0;
+ KJSO thisValue() const;
+ void addParameter(const UString &n);
+ void setLength(int l);
+ KJSO executeCall(Imp *thisV, const List *args);
+ KJSO executeCall(Imp *thisV, const List *args, const List *extraScope);
+ UString name() const;
+ protected:
+ UString ident;
+ FunctionAttribute attr;
+ Parameter *param;
+ private:
+ void processParameters(const List *);
+ };
+
+ /**
+ * @short Abstract base class for internal functions.
+ */
+ class InternalFunctionImp : public FunctionImp {
+ public:
+ InternalFunctionImp();
+ InternalFunctionImp(int l);
+ InternalFunctionImp(const UString &n);
+ virtual ~InternalFunctionImp() { }
+ virtual String toString() const;
+ virtual KJSO toPrimitive(Type) const { return toString(); }
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &);
+ virtual CodeType codeType() const { return HostCode; }
+ };
+
+ /**
+ * @short Base class for Function objects.
+ */
+ class Function : public KJSO {
+ public:
+ Function(Imp *);
+ virtual ~Function() { }
+ Completion execute(const List &);
+ bool hasAttribute(FunctionAttribute a) const;
+ CodeType codeType() const { return HostCode; }
+ KJSO thisValue() const;
+ };
+
+ /**
+ * @short Implementation class for Constructors.
+ */
+ class ConstructorImp : public InternalFunctionImp {
+ public:
+ ConstructorImp();
+ ConstructorImp(const UString &n); /* TODO: add length */
+ ConstructorImp(const KJSO &, int);
+ ConstructorImp(const UString &n, const KJSO &p, int len);
+ virtual ~ConstructorImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ virtual Completion execute(const List &);
+ virtual Object construct(const List &) = 0;
+ };
+
+ /**
+ * @short Constructor object for use with the 'new' operator
+ */
+ class Constructor : public Function {
+ public:
+ Constructor(Imp *);
+ virtual ~Constructor();
+ // Constructor(const Object& proto, int len);
+ /**
+ * @return @ref ConstructorType
+ */
+ Completion execute(const List &);
+ Object construct(const List &args);
+ static Constructor dynamicCast(const KJSO &obj);
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/function_object.cpp b/WebCore/src/kdelibs/kjs/function_object.cpp
new file mode 100644
index 0000000..63b8b63
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/function_object.cpp
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "function_object.h"
+
+#include "lexer.h"
+#include "nodes.h"
+#include "error_object.h"
+
+extern int kjsyyparse();
+
+using namespace KJS;
+
+FunctionObject::FunctionObject(const Object& funcProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.3.3.1 Function.prototype
+ setPrototypeProperty(funcProto);
+}
+
+// ECMA 15.3.1 The Function Constructor Called as a Function
+Completion FunctionObject::execute(const List &args)
+{
+ return Completion(ReturnValue, construct(args));
+}
+
+// ECMA 15.3.2 The Function Constructor
+Object FunctionObject::construct(const List &args)
+{
+ UString p("");
+ UString body;
+ int argsSize = args.size();
+ if (argsSize == 0) {
+ body = "";
+ } else if (argsSize == 1) {
+ body = args[0].toString().value();
+ } else {
+ p = args[0].toString().value();
+ for (int k = 1; k < argsSize - 1; k++)
+ p += "," + args[k].toString().value();
+ body = args[argsSize-1].toString().value();
+ }
+
+ Lexer::curr()->setCode(body.data(), body.size());
+
+ KJScriptImp::current()->pushStack();
+ int yp = kjsyyparse();
+ ProgramNode *progNode = KJScriptImp::current()->progNode();
+ KJScriptImp::current()->popStack();
+ if (yp) {
+ /* TODO: free nodes */
+ return ErrorObject::create(SyntaxError,
+ I18N_NOOP("Syntax error in function body"), -1);
+ }
+
+ List scopeChain;
+ scopeChain.append(Global::current());
+ FunctionBodyNode *bodyNode = progNode;
+ FunctionImp *fimp = new DeclaredFunctionImp(UString::null, bodyNode,
+ &scopeChain);
+ Object ret(fimp); // protect from GC
+
+ // parse parameter list. throw syntax error on illegal identifiers
+ int len = p.size();
+ const UChar *c = p.data();
+ int i = 0, params = 0;
+ UString param;
+ while (i < len) {
+ while (*c == ' ' && i < len)
+ c++, i++;
+ if (Lexer::isIdentLetter(c->unicode())) { // else error
+ param = UString(c, 1);
+ c++, i++;
+ while (i < len && (Lexer::isIdentLetter(c->unicode()) ||
+ Lexer::isDecimalDigit(c->unicode()))) {
+ param += UString(c, 1);
+ c++, i++;
+ }
+ while (i < len && *c == ' ')
+ c++, i++;
+ if (i == len) {
+ fimp->addParameter(param);
+ params++;
+ break;
+ } else if (*c == ',') {
+ fimp->addParameter(param);
+ params++;
+ c++, i++;
+ continue;
+ } // else error
+ }
+ return ErrorObject::create(SyntaxError,
+ I18N_NOOP("Syntax error in parameter list"),
+ -1);
+ }
+
+ fimp->setLength(params);
+ fimp->setPrototypeProperty(Global::current().functionPrototype());
+ return ret;
+}
+
+FunctionPrototype::FunctionPrototype(const Object &p)
+ : ObjectImp(FunctionClass, Null(), p)
+{
+}
diff --git a/WebCore/src/kdelibs/kjs/function_object.h b/WebCore/src/kdelibs/kjs/function_object.h
new file mode 100644
index 0000000..9617ac0
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/function_object.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _FUNCTION_OBJECT_H_
+#define _FUNCTION_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class FunctionPrototype : public ObjectImp {
+ public:
+ FunctionPrototype(const Object &p);
+ };
+
+ class FunctionObject : public ConstructorImp {
+ public:
+ FunctionObject(const Object &funcProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/global_object.cpp b/WebCore/src/kdelibs/kjs/global_object.cpp
new file mode 100644
index 0000000..c5bb3ed9
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/global_object.cpp
@@ -0,0 +1,373 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "operations.h"
+#include "internal.h"
+#include "types.h"
+#include "lexer.h"
+#include "nodes.h"
+#include "lexer.h"
+
+#include "object_object.h"
+#include "function_object.h"
+#include "array_object.h"
+#include "bool_object.h"
+#include "string_object.h"
+#include "number_object.h"
+#include "math_object.h"
+#include "date_object.h"
+#include "regexp_object.h"
+#include "error_object.h"
+
+extern int kjsyyparse();
+
+namespace KJS {
+
+ class GlobalImp : public ObjectImp {
+ public:
+ GlobalImp();
+ virtual ~GlobalImp();
+ virtual void mark(Imp*);
+ void init();
+ virtual KJSO get(const UString &p) const;
+ virtual void put(const UString &p, const KJSO& v);
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ Imp *filter;
+ void *extraData;
+ private:
+ class GlobalInternal;
+ GlobalInternal *internal;
+ };
+
+};
+
+using namespace KJS;
+
+class GlobalFunc : public InternalFunctionImp {
+public:
+ GlobalFunc(int i) : id(i) { }
+ Completion execute(const List &c);
+ virtual CodeType codeType() const;
+ enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape };
+private:
+ int id;
+};
+
+Global::Global()
+ : Object(0L)
+{
+ rep = 0;
+ init();
+}
+
+Global::Global(void *)
+ : Object(0L)
+{
+}
+
+Global::~Global()
+{
+}
+
+void Global::init()
+{
+ if (rep)
+ rep->deref();
+ GlobalImp *g = new GlobalImp();
+ rep = g;
+ rep->ref();
+ g->init();
+}
+
+void Global::clear()
+{
+// if (rep && rep->deref())
+// delete rep;
+// rep = 0L;
+}
+
+Global Global::current()
+{
+ assert(KJScriptImp::current());
+ return KJScriptImp::current()->glob;
+}
+
+KJSO Global::objectPrototype() const
+{
+ return get("[[Object.prototype]]");
+}
+
+KJSO Global::functionPrototype() const
+{
+ return get("[[Function.prototype]]");
+}
+
+void Global::setFilter(const KJSO &f)
+{
+ static_cast<GlobalImp*>(rep)->filter = f.imp();
+}
+
+KJSO Global::filter() const
+{
+ Imp *f = static_cast<GlobalImp*>(rep)->filter;
+ return f ? KJSO(f) : KJSO(Null());
+}
+
+void *Global::extra() const
+{
+ return static_cast<GlobalImp*>(rep)->extraData;
+}
+
+void Global::setExtra(void *e)
+{
+ static_cast<GlobalImp*>(rep)->extraData = e;
+}
+
+GlobalImp::GlobalImp()
+ : ObjectImp(ObjectClass),
+ filter(0L),
+ extraData(0L)
+{
+ // constructor properties. prototypes as Global's member variables first.
+ Object objProto(new ObjectPrototype());
+ Object funcProto(new FunctionPrototype(objProto));
+ Object arrayProto(new ArrayPrototype(objProto));
+ Object stringProto(new StringPrototype(objProto));
+ Object booleanProto(new BooleanPrototype(objProto));
+ Object numberProto(new NumberPrototype(objProto));
+ Object dateProto(new DatePrototype(objProto));
+ Object regexpProto(new RegExpPrototype(objProto));
+ Object errorProto(new ErrorPrototype(objProto));
+
+ put("[[Object.prototype]]", objProto);
+ put("[[Function.prototype]]", funcProto);
+ put("[[Array.prototype]]", arrayProto);
+ put("[[String.prototype]]", stringProto);
+ put("[[Boolean.prototype]]", booleanProto);
+ put("[[Number.prototype]]", numberProto);
+ put("[[Date.prototype]]", dateProto);
+ put("[[RegExp.prototype]]", regexpProto);
+ put("[[Error.prototype]]", errorProto);
+
+ Object objectObj(new ObjectObject(funcProto, objProto));
+ Object funcObj(new FunctionObject(funcProto));
+ Object arrayObj(new ArrayObject(funcProto, arrayProto));
+ Object stringObj(new StringObject(funcProto, stringProto));
+ Object boolObj(new BooleanObject(funcProto, booleanProto));
+ Object numObj(new NumberObject(funcProto, numberProto));
+ Object dateObj(new DateObject(funcProto, dateProto));
+ Object regObj(new RegExpObject(funcProto, regexpProto));
+ Object errObj(new ErrorObject(funcProto, errorProto));
+
+ Imp::put("Object", objectObj, DontEnum);
+ Imp::put("Function", funcObj, DontEnum);
+ Imp::put("Array", arrayObj, DontEnum);
+ Imp::put("Boolean", boolObj, DontEnum);
+ Imp::put("String", stringObj, DontEnum);
+ Imp::put("Number", numObj, DontEnum);
+ Imp::put("Date", dateObj, DontEnum);
+ Imp::put("RegExp", regObj, DontEnum);
+ Imp::put("Error", errObj, DontEnum);
+
+ objProto.setConstructor(objectObj);
+ funcProto.setConstructor(funcObj);
+ arrayProto.setConstructor(arrayObj);
+ booleanProto.setConstructor(boolObj);
+ stringProto.setConstructor(stringObj);
+ numberProto.setConstructor(numObj);
+ dateProto.setConstructor(dateObj);
+ regexpProto.setConstructor(regObj);
+ errorProto.setConstructor(errObj);
+};
+
+void GlobalImp::init()
+{
+ Imp::put("eval", Function(new GlobalFunc(GlobalFunc::Eval)));
+ Imp::put("parseInt", Function(new GlobalFunc(GlobalFunc::ParseInt)));
+ Imp::put("parseFloat", Function(new GlobalFunc(GlobalFunc::ParseFloat)));
+ Imp::put("isNaN", Function(new GlobalFunc(GlobalFunc::IsNaN)));
+ Imp::put("isFinite", Function(new GlobalFunc(GlobalFunc::IsFinite)));
+ Imp::put("escape", Function(new GlobalFunc(GlobalFunc::Escape)));
+ Imp::put("unescape", Function(new GlobalFunc(GlobalFunc::UnEscape)));
+
+ // other properties
+ Imp::put("Math", Object(new Math()), DontEnum);
+}
+
+GlobalImp::~GlobalImp() { }
+
+void GlobalImp::mark(Imp*)
+{
+ ObjectImp::mark();
+ /* TODO: remove in next version */
+ if (filter && !filter->marked())
+ filter->mark();
+}
+
+KJSO GlobalImp::get(const UString &p) const
+{
+ if (p == "NaN")
+ return Number(NaN);
+ else if (p == "Infinity")
+ return Number(Inf);
+ else if (p == "undefined")
+ return Undefined();
+
+ return Imp::get(p);
+}
+
+void GlobalImp::put(const UString &p, const KJSO& v)
+{
+ // if we already have this property (added by init() or a variable
+ // declaration) overwrite it. Otherwise pass it to the prototype.
+ // Needed to get something like a browser's window object working.
+ if (!prototype() || hasProperty(p, false) || Imp::hasProperty(p, false))
+ Imp::put(p, v);
+ else
+ prototype()->put(p, v);
+#if 0
+ if (filter)
+ filter->put(p, v); /* TODO: remove in next version */
+ else
+ Imp::put(p, v);
+#endif
+}
+
+bool GlobalImp::hasProperty(const UString &p, bool recursive) const
+{
+ if (p == "NaN" || p == "Infinity" || p == "undefined")
+ return true;
+ return (recursive && Imp::hasProperty(p, recursive));
+}
+
+CodeType GlobalFunc::codeType() const
+{
+ return id == Eval ? EvalCode : InternalFunctionImp::codeType();
+}
+
+Completion GlobalFunc::execute(const List &args)
+{
+ KJSO res;
+
+ static const char non_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789@*_+-./";
+
+ if (id == Eval) { // eval()
+ KJSO x = args[0];
+ if (x.type() != StringType)
+ return Completion(ReturnValue, x);
+ else {
+ UString s = x.toString().value();
+ Lexer::curr()->setCode(s.data(), s.size());
+ Node::setFirstNode(KJScriptImp::current()->firstNode());
+ int yp = kjsyyparse();
+ KJScriptImp::current()->setFirstNode(Node::firstNode());
+ if (yp) {
+ // TODO: stop this from growing (will be deleted at end of global eval)
+ // KJS::Node::deleteAllNodes();
+ return Completion(ReturnValue, Error::create(SyntaxError));
+ }
+
+ Completion c = KJScriptImp::current()->progNode()->execute();
+ if (c.complType() == ReturnValue)
+ return c;
+ else if (c.complType() == Normal) {
+ if (c.isValueCompletion())
+ return Completion(ReturnValue, c.value());
+ else
+ return Completion(ReturnValue, Undefined());
+ } else
+ return c;
+
+ // if (KJS::Node::progNode())
+ // KJS::Node::progNode()->deleteStatements();
+ }
+ } else if (id == ParseInt) {
+ String str = args[0].toString();
+ int radix = args[1].toInt32();
+ if (radix == 0)
+ radix = 10;
+ else if (radix < 2 || radix > 36) {
+ res = Number(NaN);
+ return Completion(ReturnValue, res);
+ }
+ /* TODO: use radix */
+ int i = 0;
+ sscanf(str.value().ascii(), "%d", &i);
+ res = Number(i);
+ } else if (id == ParseFloat) {
+ String str = args[0].toString();
+ double d = 0.0;
+ sscanf(str.value().ascii(), "%lf", &d);
+ res = Number(d);
+ } else if (id == IsNaN) {
+ res = Boolean(args[0].toNumber().isNaN());
+ } else if (id == IsFinite) {
+ Number n = args[0].toNumber();
+ res = Boolean(!n.isNaN() && !n.isInf());
+ } else if (id == Escape) {
+ UString r = "", s, str = args[0].toString().value();
+ const UChar *c = str.data();
+ for (int k = 0; k < str.size(); k++, c++) {
+ int u = c->unicode();
+ if (u > 255) {
+ char tmp[7];
+ sprintf(tmp, "%%u%04x", u);
+ s = UString(tmp);
+ } else if (strchr(non_escape, (char)u)) {
+ s = UString(c, 1);
+ } else {
+ char tmp[4];
+ sprintf(tmp, "%%%02x", u);
+ s = UString(tmp);
+ }
+ r += s;
+ }
+ res = String(r);
+ } else if (id == UnEscape) {
+ UString s, str = args[0].toString().value();
+ int k = 0, len = str.size();
+ while (k < len) {
+ const UChar *c = str.data() + k;
+ UChar u;
+ if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
+ u = Lexer::convertUnicode((c+2)->unicode(), (c+3)->unicode(),
+ (c+4)->unicode(), (c+5)->unicode());
+ c = &u;
+ k += 5;
+ } else if (*c == UChar('%') && k <= len - 3) {
+ u = UChar(Lexer::convertHex((c+1)->unicode(), (c+2)->unicode()));
+ c = &u;
+ k += 2;
+ }
+ k++;
+ s += UString(c, 1);
+ }
+ res = String(s);
+ }
+
+ return Completion(ReturnValue, res);
+}
diff --git a/WebCore/src/kdelibs/kjs/grammar.cpp b/WebCore/src/kdelibs/kjs/grammar.cpp
new file mode 100644
index 0000000..9639e01
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/grammar.cpp
@@ -0,0 +1,2220 @@
+
+/* A Bison parser, made from grammar.y
+ by GNU Bison version 1.28 */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define yyparse kjsyyparse
+#define yylex kjsyylex
+#define yyerror kjsyyerror
+#define yylval kjsyylval
+#define yychar kjsyychar
+#define yydebug kjsyydebug
+#define yynerrs kjsyynerrs
+#define YYLSP_NEEDED
+
+#define NULLTOKEN 257
+#define TRUETOKEN 258
+#define FALSETOKEN 259
+#define STRING 260
+#define NUMBER 261
+#define BREAK 262
+#define CASE 263
+#define DEFAULT 264
+#define FOR 265
+#define NEW 266
+#define VAR 267
+#define CONTINUE 268
+#define FUNCTION 269
+#define RETURN 270
+#define VOID 271
+#define DELETE 272
+#define IF 273
+#define THIS 274
+#define DO 275
+#define WHILE 276
+#define ELSE 277
+#define IN 278
+#define INSTANCEOF 279
+#define TYPEOF 280
+#define SWITCH 281
+#define WITH 282
+#define RESERVED 283
+#define THROW 284
+#define TRY 285
+#define CATCH 286
+#define FINALLY 287
+#define EQEQ 288
+#define NE 289
+#define STREQ 290
+#define STRNEQ 291
+#define LE 292
+#define GE 293
+#define OR 294
+#define AND 295
+#define PLUSPLUS 296
+#define MINUSMINUS 297
+#define LSHIFT 298
+#define RSHIFT 299
+#define URSHIFT 300
+#define PLUSEQUAL 301
+#define MINUSEQUAL 302
+#define MULTEQUAL 303
+#define DIVEQUAL 304
+#define LSHIFTEQUAL 305
+#define RSHIFTEQUAL 306
+#define URSHIFTEQUAL 307
+#define ANDEQUAL 308
+#define MODEQUAL 309
+#define XOREQUAL 310
+#define OREQUAL 311
+#define IDENT 312
+#define AUTO 313
+
+#line 1 "grammar.y"
+
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+
+/* default values for bison */
+#define YYDEBUG 0
+#define YYMAXDEPTH 0
+#ifdef KJS_DEBUGGER
+#define YYERROR_VERBOSE
+#define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line); } // location
+#else
+#undef YYLSP_NEEDED
+#define DBG(l, s, e)
+#endif
+
+extern int yylex();
+int yyerror (const char *);
+bool automatic();
+
+using namespace KJS;
+
+
+#line 49 "grammar.y"
+typedef union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+} YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 358
+#define YYFLAG -32768
+#define YYNTBASE 84
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 313 ? yytranslate[x] : 148)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 73, 2, 2, 2, 75, 78, 2, 61,
+ 62, 74, 70, 67, 71, 69, 60, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 68, 83, 76,
+ 82, 77, 81, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 65, 2, 66, 79, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 63, 80, 64, 72, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 24, 27, 31, 35, 39, 45, 48, 53, 54,
+ 56, 58, 61, 65, 71, 73, 75, 77, 79, 81,
+ 86, 90, 94, 96, 99, 102, 105, 110, 114, 117,
+ 121, 123, 127, 129, 131, 133, 136, 139, 141, 144,
+ 147, 150, 153, 157, 160, 164, 167, 170, 173, 176,
+ 178, 182, 186, 190, 192, 196, 200, 202, 206, 210,
+ 214, 216, 220, 224, 228, 232, 236, 240, 242, 246,
+ 250, 254, 258, 260, 264, 266, 270, 272, 276, 278,
+ 282, 284, 288, 290, 296, 298, 302, 304, 306, 308,
+ 310, 312, 314, 316, 318, 320, 322, 324, 326, 328,
+ 332, 334, 336, 338, 340, 342, 344, 346, 348, 350,
+ 352, 354, 356, 358, 360, 363, 367, 369, 372, 376,
+ 380, 382, 386, 388, 391, 394, 396, 399, 402, 408,
+ 416, 423, 429, 439, 450, 458, 467, 477, 478, 480,
+ 483, 486, 490, 494, 497, 500, 504, 508, 511, 514,
+ 518, 522, 528, 534, 538, 544, 545, 547, 549, 552,
+ 556, 561, 564, 568, 572, 576, 580, 584, 589, 595,
+ 598, 604, 611, 616, 622, 624, 628, 631, 635, 637,
+ 639, 642, 644
+};
+
+static const short yyrhs[] = { 3,
+ 0, 4, 0, 5, 0, 7, 0, 6, 0, 60,
+ 0, 20, 0, 58, 0, 84, 0, 86, 0, 61,
+ 113, 62, 0, 63, 64, 0, 63, 90, 64, 0,
+ 65, 88, 66, 0, 65, 87, 66, 0, 65, 87,
+ 67, 88, 66, 0, 88, 111, 0, 87, 67, 88,
+ 111, 0, 0, 89, 0, 67, 0, 89, 67, 0,
+ 91, 68, 111, 0, 90, 67, 91, 68, 111, 0,
+ 58, 0, 6, 0, 7, 0, 85, 0, 142, 0,
+ 92, 65, 113, 66, 0, 92, 69, 58, 0, 12,
+ 92, 95, 0, 92, 0, 12, 93, 0, 92, 95,
+ 0, 94, 95, 0, 94, 65, 113, 66, 0, 94,
+ 69, 58, 0, 61, 62, 0, 61, 96, 62, 0,
+ 111, 0, 96, 67, 111, 0, 93, 0, 94, 0,
+ 97, 0, 97, 42, 0, 97, 43, 0, 98, 0,
+ 18, 99, 0, 17, 99, 0, 26, 99, 0, 42,
+ 99, 0, 59, 42, 99, 0, 43, 99, 0, 59,
+ 43, 99, 0, 70, 99, 0, 71, 99, 0, 72,
+ 99, 0, 73, 99, 0, 99, 0, 100, 74, 99,
+ 0, 100, 60, 99, 0, 100, 75, 99, 0, 100,
+ 0, 101, 70, 100, 0, 101, 71, 100, 0, 101,
+ 0, 102, 44, 101, 0, 102, 45, 101, 0, 102,
+ 46, 101, 0, 102, 0, 103, 76, 102, 0, 103,
+ 77, 102, 0, 103, 38, 102, 0, 103, 39, 102,
+ 0, 103, 25, 102, 0, 103, 24, 102, 0, 103,
+ 0, 104, 34, 103, 0, 104, 35, 103, 0, 104,
+ 36, 103, 0, 104, 37, 103, 0, 104, 0, 105,
+ 78, 104, 0, 105, 0, 106, 79, 104, 0, 106,
+ 0, 107, 80, 104, 0, 107, 0, 108, 41, 107,
+ 0, 108, 0, 109, 40, 108, 0, 109, 0, 109,
+ 81, 111, 68, 111, 0, 110, 0, 97, 112, 111,
+ 0, 82, 0, 47, 0, 48, 0, 49, 0, 50,
+ 0, 51, 0, 52, 0, 53, 0, 54, 0, 56,
+ 0, 57, 0, 55, 0, 111, 0, 113, 67, 111,
+ 0, 115, 0, 117, 0, 121, 0, 122, 0, 123,
+ 0, 124, 0, 126, 0, 127, 0, 128, 0, 129,
+ 0, 130, 0, 136, 0, 137, 0, 138, 0, 63,
+ 64, 0, 63, 116, 64, 0, 114, 0, 116, 114,
+ 0, 13, 118, 83, 0, 13, 118, 1, 0, 119,
+ 0, 118, 67, 119, 0, 58, 0, 58, 120, 0,
+ 82, 111, 0, 83, 0, 113, 83, 0, 113, 1,
+ 0, 19, 61, 113, 62, 114, 0, 19, 61, 113,
+ 62, 114, 23, 114, 0, 21, 114, 22, 61, 113,
+ 62, 0, 22, 61, 113, 62, 114, 0, 11, 61,
+ 125, 83, 125, 83, 125, 62, 114, 0, 11, 61,
+ 13, 118, 83, 125, 83, 125, 62, 114, 0, 11,
+ 61, 97, 24, 113, 62, 114, 0, 11, 61, 13,
+ 58, 24, 113, 62, 114, 0, 11, 61, 13, 58,
+ 120, 24, 113, 62, 114, 0, 0, 113, 0, 14,
+ 83, 0, 14, 1, 0, 14, 58, 83, 0, 14,
+ 58, 1, 0, 8, 83, 0, 8, 1, 0, 8,
+ 58, 83, 0, 8, 58, 1, 0, 16, 83, 0,
+ 16, 1, 0, 16, 113, 83, 0, 16, 113, 1,
+ 0, 28, 61, 113, 62, 114, 0, 27, 61, 113,
+ 62, 131, 0, 63, 132, 64, 0, 63, 132, 135,
+ 132, 64, 0, 0, 133, 0, 134, 0, 133, 134,
+ 0, 9, 113, 68, 0, 9, 113, 68, 116, 0,
+ 10, 68, 0, 10, 68, 116, 0, 58, 68, 114,
+ 0, 30, 113, 83, 0, 31, 115, 139, 0, 31,
+ 115, 140, 0, 31, 115, 139, 140, 0, 32, 61,
+ 58, 62, 115, 0, 33, 115, 0, 15, 58, 61,
+ 62, 144, 0, 15, 58, 61, 143, 62, 144, 0,
+ 15, 61, 62, 144, 0, 15, 61, 143, 62, 144,
+ 0, 58, 0, 143, 67, 58, 0, 63, 64, 0,
+ 63, 146, 64, 0, 146, 0, 147, 0, 146, 147,
+ 0, 114, 0, 141, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 156, 158, 159, 160, 161, 162, 167, 169, 171, 172,
+ 173, 174, 175, 178, 180, 181, 184, 186, 190, 192,
+ 195, 197, 200, 202, 206, 209, 210, 213, 215, 216,
+ 217, 219, 222, 224, 227, 229, 230, 231, 234, 236,
+ 239, 241, 244, 246, 249, 251, 252, 255, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 270,
+ 272, 273, 274, 277, 279, 280, 283, 285, 286, 287,
+ 290, 292, 294, 296, 298, 300, 302, 306, 308, 309,
+ 310, 311, 314, 316, 319, 321, 324, 326, 329, 331,
+ 335, 337, 341, 343, 347, 349, 353, 355, 356, 357,
+ 358, 359, 360, 361, 362, 363, 364, 365, 368, 370,
+ 373, 375, 376, 377, 378, 379, 380, 381, 382, 383,
+ 384, 385, 386, 387, 390, 392, 395, 397, 400, 403,
+ 412, 414, 418, 420, 423, 427, 431, 434, 441, 443,
+ 447, 449, 450, 453, 456, 459, 463, 469, 471, 474,
+ 476, 480, 482, 489, 491, 495, 497, 505, 507, 511,
+ 512, 518, 523, 528, 530, 534, 536, 539, 541, 544,
+ 546, 549, 551, 554, 560, 564, 566, 567, 570, 574,
+ 578, 581, 585, 587, 592, 594, 598, 600, 603, 608,
+ 610, 613, 615
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = { "$","error","$undefined.","NULLTOKEN",
+"TRUETOKEN","FALSETOKEN","STRING","NUMBER","BREAK","CASE","DEFAULT","FOR","NEW",
+"VAR","CONTINUE","FUNCTION","RETURN","VOID","DELETE","IF","THIS","DO","WHILE",
+"ELSE","IN","INSTANCEOF","TYPEOF","SWITCH","WITH","RESERVED","THROW","TRY","CATCH",
+"FINALLY","EQEQ","NE","STREQ","STRNEQ","LE","GE","OR","AND","PLUSPLUS","MINUSMINUS",
+"LSHIFT","RSHIFT","URSHIFT","PLUSEQUAL","MINUSEQUAL","MULTEQUAL","DIVEQUAL",
+"LSHIFTEQUAL","RSHIFTEQUAL","URSHIFTEQUAL","ANDEQUAL","MODEQUAL","XOREQUAL",
+"OREQUAL","IDENT","AUTO","'/'","'('","')'","'{'","'}'","'['","']'","','","':'",
+"'.'","'+'","'-'","'~'","'!'","'*'","'%'","'<'","'>'","'&'","'^'","'|'","'?'",
+"'='","';'","Literal","PrimaryExpr","ArrayLiteral","ElementList","ElisionOpt",
+"Elision","PropertyNameAndValueList","PropertyName","MemberExpr","NewExpr","CallExpr",
+"Arguments","ArgumentList","LeftHandSideExpr","PostfixExpr","UnaryExpr","MultiplicativeExpr",
+"AdditiveExpr","ShiftExpr","RelationalExpr","EqualityExpr","BitwiseANDExpr",
+"BitwiseXORExpr","BitwiseORExpr","LogicalANDExpr","LogicalORExpr","ConditionalExpr",
+"AssignmentExpr","AssignmentOperator","Expr","Statement","Block","StatementList",
+"VariableStatement","VariableDeclarationList","VariableDeclaration","Initializer",
+"EmptyStatement","ExprStatement","IfStatement","IterationStatement","ExprOpt",
+"ContinueStatement","BreakStatement","ReturnStatement","WithStatement","SwitchStatement",
+"CaseBlock","CaseClausesOpt","CaseClauses","CaseClause","DefaultClause","LabelledStatement",
+"ThrowStatement","TryStatement","Catch","Finally","FunctionDeclaration","FunctionExpr",
+"FormalParameterList","FunctionBody","Program","SourceElements","SourceElement", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 84, 84, 84, 84, 84, 84, 85, 85, 85, 85,
+ 85, 85, 85, 86, 86, 86, 87, 87, 88, 88,
+ 89, 89, 90, 90, 91, 91, 91, 92, 92, 92,
+ 92, 92, 93, 93, 94, 94, 94, 94, 95, 95,
+ 96, 96, 97, 97, 98, 98, 98, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 100,
+ 100, 100, 100, 101, 101, 101, 102, 102, 102, 102,
+ 103, 103, 103, 103, 103, 103, 103, 104, 104, 104,
+ 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
+ 109, 109, 110, 110, 111, 111, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112, 112, 113, 113,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 115, 115, 116, 116, 117, 117,
+ 118, 118, 119, 119, 120, 121, 122, 122, 123, 123,
+ 124, 124, 124, 124, 124, 124, 124, 125, 125, 126,
+ 126, 126, 126, 127, 127, 127, 127, 128, 128, 128,
+ 128, 129, 130, 131, 131, 132, 132, 133, 133, 134,
+ 134, 135, 135, 136, 137, 138, 138, 138, 139, 140,
+ 141, 141, 142, 142, 143, 143, 144, 144, 145, 146,
+ 146, 147, 147
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 2, 3, 3, 3, 5, 2, 4, 0, 1,
+ 1, 2, 3, 5, 1, 1, 1, 1, 1, 4,
+ 3, 3, 1, 2, 2, 2, 4, 3, 2, 3,
+ 1, 3, 1, 1, 1, 2, 2, 1, 2, 2,
+ 2, 2, 3, 2, 3, 2, 2, 2, 2, 1,
+ 3, 3, 3, 1, 3, 3, 1, 3, 3, 3,
+ 1, 3, 3, 3, 3, 3, 3, 1, 3, 3,
+ 3, 3, 1, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 5, 1, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 3, 1, 2, 3, 3,
+ 1, 3, 1, 2, 2, 1, 2, 2, 5, 7,
+ 6, 5, 9, 10, 7, 8, 9, 0, 1, 2,
+ 2, 3, 3, 2, 2, 3, 3, 2, 2, 3,
+ 3, 5, 5, 3, 5, 0, 1, 1, 2, 3,
+ 4, 2, 3, 3, 3, 3, 3, 4, 5, 2,
+ 5, 6, 4, 5, 1, 3, 2, 3, 1, 1,
+ 2, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 1, 2, 3, 5, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 6, 0, 0,
+ 19, 0, 0, 0, 0, 136, 9, 28, 10, 33,
+ 43, 44, 45, 48, 60, 64, 67, 71, 78, 83,
+ 85, 87, 89, 91, 93, 95, 109, 0, 192, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 193, 29, 189, 190, 155, 0, 154,
+ 148, 0, 8, 0, 33, 34, 133, 0, 131, 151,
+ 0, 150, 0, 0, 159, 158, 0, 45, 50, 49,
+ 0, 0, 0, 51, 0, 0, 0, 0, 0, 52,
+ 54, 0, 0, 0, 0, 5, 4, 8, 12, 0,
+ 0, 127, 0, 21, 0, 0, 20, 56, 57, 58,
+ 59, 0, 0, 0, 35, 0, 0, 36, 46, 47,
+ 98, 99, 100, 101, 102, 103, 104, 105, 108, 106,
+ 107, 97, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 138, 0, 137,
+ 191, 157, 156, 0, 45, 149, 0, 26, 27, 25,
+ 12, 32, 0, 134, 130, 0, 129, 153, 152, 0,
+ 185, 0, 0, 161, 160, 0, 0, 0, 0, 0,
+ 175, 125, 0, 0, 176, 177, 174, 53, 55, 11,
+ 13, 0, 0, 126, 128, 15, 19, 14, 17, 22,
+ 39, 0, 41, 0, 31, 0, 38, 96, 62, 61,
+ 63, 65, 66, 68, 69, 70, 77, 76, 74, 75,
+ 72, 73, 79, 80, 81, 82, 84, 86, 88, 90,
+ 92, 0, 110, 133, 0, 0, 148, 135, 132, 0,
+ 0, 0, 183, 0, 0, 0, 0, 0, 0, 0,
+ 0, 180, 178, 0, 23, 0, 40, 0, 30, 37,
+ 0, 0, 134, 148, 0, 0, 181, 0, 187, 0,
+ 184, 186, 139, 0, 142, 166, 163, 162, 0, 0,
+ 16, 18, 42, 94, 0, 0, 0, 0, 148, 182,
+ 188, 0, 141, 0, 0, 167, 168, 0, 24, 0,
+ 0, 148, 145, 0, 140, 0, 0, 164, 166, 169,
+ 179, 146, 0, 0, 0, 170, 172, 0, 147, 0,
+ 143, 171, 173, 165, 144, 0, 0, 0
+};
+
+static const short yydefgoto[] = { 37,
+ 38, 39, 125, 126, 127, 120, 121, 40, 41, 42,
+ 135, 232, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 153, 58, 59,
+ 60, 123, 61, 88, 89, 194, 62, 63, 64, 65,
+ 187, 66, 67, 68, 69, 70, 307, 325, 326, 327,
+ 339, 71, 72, 73, 215, 216, 74, 75, 203, 273,
+ 356, 76, 77
+};
+
+static const short yypact[] = { 699,
+-32768,-32768,-32768,-32768,-32768, 2, -29, 121, 34, 4,
+ 129, 227, 1171, 1171, 42,-32768, 772, 89, 1171, 107,
+ 128, 1171, -7, 1171, 1171, 62, -2,-32768, 1171, 334,
+ 124, 1171, 1171, 1171, 1171,-32768,-32768,-32768,-32768, 51,
+-32768, 73, 769,-32768,-32768, 69, 90, 210, 72, 201,
+ 115, 60, 145, 186, -13,-32768,-32768, 11,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768, 699,-32768,-32768, 5,-32768,
+ 887, 168,-32768, 101, 51,-32768, 161, 15,-32768,-32768,
+ 6,-32768, 185, 28,-32768,-32768, 16, 27,-32768,-32768,
+ 1171, 230, 1171,-32768, 1171, 1171, -59, 407, 144,-32768,
+-32768, 772, 1171, 1171, -4, 192, 194, 62, 853, 157,
+ 196,-32768, 480,-32768, 153, 958, 215,-32768,-32768,-32768,
+-32768, 1029, 1171, 225,-32768, 1171, 226,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1171, 1171, 1171, 1171, 1171, 1171,-32768, 1171,-32768,
+-32768,-32768,-32768, 231, -5, 228, 211,-32768,-32768,-32768,
+-32768,-32768, 1171,-32768,-32768, 34,-32768,-32768,-32768, 61,
+-32768, 233, 17,-32768,-32768, 55, 241, 78, 84, 85,
+-32768,-32768, 242, -7, 271,-32768,-32768,-32768,-32768,-32768,
+-32768, 23, 1171,-32768,-32768,-32768, 124,-32768,-32768,-32768,
+-32768, 96,-32768, 174,-32768, 191,-32768,-32768,-32768,-32768,
+-32768, 69, 69, 90, 90, 90, 210, 210, 210, 210,
+ 210, 210, 72, 72, 72, 72, 201, 201, 201, 145,
+ 186, 239,-32768, -15, -44, 1171, 1171,-32768,-32768, 233,
+ 100, 553,-32768, 233, 250, 772, 1171, 772, 246, 772,
+ 253,-32768,-32768, 244,-32768, 1100,-32768, 1171,-32768,-32768,
+ 1171, 1171, 290, 1171, 116, 234,-32768, 233,-32768, 626,
+-32768,-32768, 293, 118,-32768, 310,-32768,-32768, 258, 1171,
+-32768,-32768,-32768,-32768, 155, 1171, 238, 772, 1171,-32768,
+-32768, 772,-32768, 1171, 12, 310,-32768, -7,-32768, 772,
+ 156, 1171,-32768, 260,-32768, 200, 256,-32768, 310,-32768,
+-32768,-32768, 772, 263, 772, 772, 772, 268,-32768, 772,
+-32768, 772, 772,-32768,-32768, 327, 343,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,-32768,-32768, 130,-32768,-32768, 122, 326, 350,-32768,
+ -24,-32768, 40,-32768, 1, 117, 112, 8, 80, 105,
+-32768,-32768, 184, 187,-32768,-32768, -122,-32768, -1, -17,
+ -22, -66,-32768, 182, 171, 104,-32768,-32768,-32768,-32768,
+ -201,-32768,-32768,-32768,-32768,-32768,-32768, 30,-32768, 44,
+-32768,-32768,-32768,-32768,-32768, 158,-32768,-32768, 172, -161,
+-32768, 99, -74
+};
+
+
+#define YYLAST 1244
+
+
+static const short yytable[] = { 102,
+ 109, 181, 78, 229, 90, 182, 198, 179, 292, 233,
+ 97, 178, 122, 99, 100, 195, 204, 138, 266, 104,
+ 107, 337, 196, 211, 110, 111, 176, 115, 188, 189,
+ 238, 81, 128, 129, 130, 131, 139, 140, 294, 113,
+ 114, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 98, 98, 262, 108, 263, 220, 98, 79,
+ 192, 91, 179, 98, 98, 296, 193, 177, 139, 140,
+ 268, 98, 98, 98, 98, 338, 152, 179, 274, 186,
+ 190, 196, 179, 275, 80, 201, 92, 183, 199, 202,
+ 122, 87, 317, 180, 217, 162, 163, 197, 205, 206,
+ 285, 208, 101, 209, 210, 225, 188, 189, 297, 164,
+ 165, 132, 301, 218, 219, 133, 276, 334, 201, 134,
+ 185, 179, 270, 1, 2, 3, 4, 5, 154, 112,
+ 344, 234, 8, 132, 236, 82, 320, 136, 173, 278,
+ 16, 137, 155, 156, 179, 279, 280, 166, 167, 103,
+ 179, 179, 98, 98, 239, 240, 241, 287, 190, 157,
+ 158, 298, 288, 312, 191, 313, 275, 105, 314, 247,
+ 248, 249, 250, 251, 252, 213, 214, 318, 83, 323,
+ 28, 29, 179, 84, 179, 31, 93, 329, 106, 94,
+ 124, 282, 172, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 330, 343, 226, 227,
+ 221, 179, 179, 222, 174, 181, 175, 95, 94, 1,
+ 2, 3, 4, 5, 168, 169, 170, 171, 8, 289,
+ 179, 82, 193, 13, 14, 200, 16, 253, 254, 255,
+ 256, 207, 19, 159, 160, 161, 290, 179, 303, -26,
+ 305, -27, 308, 223, 295, 186, 179, 346, 24, 25,
+ 244, 245, 246, 242, 243, 304, 257, 258, 259, 352,
+ 353, 230, 235, 237, 83, 27, 28, 29, 264, 84,
+ 315, 31, 186, 267, 179, 272, 32, 33, 34, 35,
+ 333, 277, 281, 214, 335, 341, 291, 302, 306, 96,
+ 309, 310, 342, 316, 331, 322, 319, 186, 324, 328,
+ 332, 345, 336, 347, 350, 349, 357, 351, 122, 122,
+ 186, 354, 355, 85, 225, 225, 1, 2, 3, 116,
+ 117, 6, 358, 284, 7, 8, 9, 10, 82, 12,
+ 13, 14, 15, 16, 17, 18, 286, 86, 260, 19,
+ 20, 21, 261, 22, 23, 265, 269, 293, 348, 340,
+ 300, 271, 283, 0, 0, 24, 25, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 118, 27, 28, 29, 0, 30, 119, 31, 0,
+ 0, 0, 0, 32, 33, 34, 35, 0, 0, 1,
+ 2, 3, 4, 5, 6, 0, 36, 7, 8, 9,
+ 10, 82, 12, 13, 14, 15, 16, 17, 18, 0,
+ 0, 0, 19, 20, 21, 0, 22, 23, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 26, 27, 28, 29, 0, 30,
+ 212, 31, 0, 0, 0, 0, 32, 33, 34, 35,
+ 0, 0, 1, 2, 3, 4, 5, 6, 0, 36,
+ 7, 8, 9, 10, 82, 12, 13, 14, 15, 16,
+ 17, 18, 0, 0, 0, 19, 20, 21, 0, 22,
+ 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 24, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26, 27, 28,
+ 29, 0, 30, 224, 31, 0, 0, 0, 0, 32,
+ 33, 34, 35, 0, 0, 1, 2, 3, 4, 5,
+ 6, 0, 36, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 0, 0, 0, 19, 20,
+ 21, 0, 22, 23, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 24, 25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 26, 27, 28, 29, 0, 30, 299, 31, 0, 0,
+ 0, 0, 32, 33, 34, 35, 0, 0, 1, 2,
+ 3, 4, 5, 6, 0, 36, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 0, 0,
+ 0, 19, 20, 21, 0, 22, 23, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 24, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 27, 28, 29, 0, 30, 321,
+ 31, 0, 0, 0, 0, 32, 33, 34, 35, 0,
+ 0, 1, 2, 3, 4, 5, 6, 0, 36, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 0, 0, 0, 19, 20, 21, 0, 22, 23,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 24, 25, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 26, 27, 28, 29,
+ 0, 30, 0, 31, 0, 0, 0, 0, 32, 33,
+ 34, 35, 0, 0, 1, 2, 3, 4, 5, 6,
+ 0, 36, 7, 8, 9, 10, 82, 12, 13, 14,
+ 15, 16, 17, 18, 0, 0, 0, 19, 20, 21,
+ 0, 22, 23, 0, 0, 0, 0, 0, 0, 0,
+ 139, 140, 0, 24, 25, 141, 142, 143, 144, 145,
+ 146, 147, 148, 149, 150, 151, 0, 0, 0, 26,
+ 27, 28, 29, 0, 30, 0, 31, 0, 0, 0,
+ 0, 32, 33, 34, 35, 0, 0, 0, 0, 0,
+ 152, 0, -125, 0, 36, -125, -125, -125, -125, -125,
+ -125, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+ -125, -125, -125, -125, -125, -125, 0, 0, -125, -125,
+ -125, 0, -125, -125, 0, 0, 0, 0, 0, 1,
+ 2, 3, 4, 5, 0, 0, 0, 0, 8, 184,
+ 0, 82, 0, 13, 14, 0, 16, 0, 0, 0,
+ -125, -125, 19, 0, 0, -125, -125, 0, 0, 0,
+ 0, 0, 0, 0, -125, -125, 0, 0, 24, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 83, 27, 28, 29, 0, 84,
+ 0, 31, 0, 0, 0, 0, 32, 33, 34, 35,
+ 1, 2, 3, 4, 5, 0, 0, 0, 0, 8,
+ 0, 0, 82, 0, 13, 14, 0, 16, 0, 0,
+ 0, 0, 0, 19, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 83, 27, 28, 29, 0,
+ 84, 0, 31, 228, 0, 0, 0, 32, 33, 34,
+ 35, 1, 2, 3, 4, 5, 0, 0, 0, 0,
+ 8, 0, 0, 82, 0, 13, 14, 0, 16, 0,
+ 0, 0, 0, 0, 19, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 24, 25, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 83, 27, 28, 29,
+ 231, 84, 0, 31, 0, 0, 0, 0, 32, 33,
+ 34, 35, 1, 2, 3, 4, 5, 0, 0, 0,
+ 0, 8, 0, 0, 82, 0, 13, 14, 0, 16,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 24, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 83, 27, 28,
+ 29, 0, 84, 0, 31, 311, 0, 0, 0, 32,
+ 33, 34, 35, 1, 2, 3, 4, 5, 0, 0,
+ 0, 0, 8, 0, 0, 82, 0, 13, 14, 0,
+ 16, 0, 0, 0, 0, 0, 19, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 24, 25, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 27,
+ 28, 29, 0, 84, 0, 31, 0, 0, 0, 0,
+ 32, 33, 34, 35
+};
+
+static const short yycheck[] = { 17,
+ 23, 76, 1, 126, 1, 1, 1, 67, 24, 132,
+ 12, 1, 30, 13, 14, 1, 1, 42, 24, 19,
+ 22, 10, 67, 83, 24, 25, 40, 29, 6, 7,
+ 153, 61, 32, 33, 34, 35, 42, 43, 83, 42,
+ 43, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 13, 14, 177, 63, 179, 62, 19, 58,
+ 85, 58, 67, 24, 25, 267, 82, 81, 42, 43,
+ 193, 32, 33, 34, 35, 64, 82, 67, 62, 81,
+ 58, 67, 67, 67, 83, 58, 83, 83, 83, 62,
+ 108, 58, 294, 83, 112, 24, 25, 83, 83, 101,
+ 223, 103, 61, 105, 106, 123, 6, 7, 270, 38,
+ 39, 61, 274, 113, 114, 65, 62, 319, 58, 69,
+ 81, 67, 62, 3, 4, 5, 6, 7, 60, 68,
+ 332, 133, 12, 61, 136, 15, 298, 65, 79, 62,
+ 20, 69, 74, 75, 67, 62, 62, 76, 77, 61,
+ 67, 67, 113, 114, 154, 155, 156, 62, 58, 70,
+ 71, 62, 67, 286, 64, 288, 67, 61, 291, 162,
+ 163, 164, 165, 166, 167, 32, 33, 62, 58, 62,
+ 60, 61, 67, 63, 67, 65, 58, 310, 61, 61,
+ 67, 214, 78, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 62, 62, 66, 67,
+ 64, 67, 67, 67, 80, 300, 41, 1, 61, 3,
+ 4, 5, 6, 7, 34, 35, 36, 37, 12, 66,
+ 67, 15, 82, 17, 18, 61, 20, 168, 169, 170,
+ 171, 22, 26, 44, 45, 46, 66, 67, 276, 68,
+ 278, 68, 280, 68, 266, 267, 67, 68, 42, 43,
+ 159, 160, 161, 157, 158, 277, 172, 173, 174, 346,
+ 347, 67, 58, 58, 58, 59, 60, 61, 58, 63,
+ 292, 65, 294, 83, 67, 63, 70, 71, 72, 73,
+ 318, 61, 61, 33, 322, 328, 68, 58, 63, 83,
+ 58, 68, 330, 24, 316, 23, 83, 319, 9, 62,
+ 83, 62, 324, 68, 62, 343, 0, 345, 346, 347,
+ 332, 64, 350, 8, 352, 353, 3, 4, 5, 6,
+ 7, 8, 0, 222, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 227, 8, 175, 26,
+ 27, 28, 176, 30, 31, 184, 196, 264, 339, 326,
+ 272, 200, 215, -1, -1, 42, 43, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 58, 59, 60, 61, -1, 63, 64, 65, -1,
+ -1, -1, -1, 70, 71, 72, 73, -1, -1, 3,
+ 4, 5, 6, 7, 8, -1, 83, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, -1,
+ -1, -1, 26, 27, 28, -1, 30, 31, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 42, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 58, 59, 60, 61, -1, 63,
+ 64, 65, -1, -1, -1, -1, 70, 71, 72, 73,
+ -1, -1, 3, 4, 5, 6, 7, 8, -1, 83,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, -1, -1, -1, 26, 27, 28, -1, 30,
+ 31, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 42, 43, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 58, 59, 60,
+ 61, -1, 63, 64, 65, -1, -1, -1, -1, 70,
+ 71, 72, 73, -1, -1, 3, 4, 5, 6, 7,
+ 8, -1, 83, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, -1, -1, -1, 26, 27,
+ 28, -1, 30, 31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 42, 43, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 58, 59, 60, 61, -1, 63, 64, 65, -1, -1,
+ -1, -1, 70, 71, 72, 73, -1, -1, 3, 4,
+ 5, 6, 7, 8, -1, 83, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, -1, -1,
+ -1, 26, 27, 28, -1, 30, 31, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 42, 43, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 58, 59, 60, 61, -1, 63, 64,
+ 65, -1, -1, -1, -1, 70, 71, 72, 73, -1,
+ -1, 3, 4, 5, 6, 7, 8, -1, 83, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, -1, -1, -1, 26, 27, 28, -1, 30, 31,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 58, 59, 60, 61,
+ -1, 63, -1, 65, -1, -1, -1, -1, 70, 71,
+ 72, 73, -1, -1, 3, 4, 5, 6, 7, 8,
+ -1, 83, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, -1, -1, -1, 26, 27, 28,
+ -1, 30, 31, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, 42, 43, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, -1, -1, -1, 58,
+ 59, 60, 61, -1, 63, -1, 65, -1, -1, -1,
+ -1, 70, 71, 72, 73, -1, -1, -1, -1, -1,
+ 82, -1, 0, -1, 83, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, -1, -1, 26, 27,
+ 28, -1, 30, 31, -1, -1, -1, -1, -1, 3,
+ 4, 5, 6, 7, -1, -1, -1, -1, 12, 13,
+ -1, 15, -1, 17, 18, -1, 20, -1, -1, -1,
+ 58, 59, 26, -1, -1, 63, 64, -1, -1, -1,
+ -1, -1, -1, -1, 72, 73, -1, -1, 42, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 58, 59, 60, 61, -1, 63,
+ -1, 65, -1, -1, -1, -1, 70, 71, 72, 73,
+ 3, 4, 5, 6, 7, -1, -1, -1, -1, 12,
+ -1, -1, 15, -1, 17, 18, -1, 20, -1, -1,
+ -1, -1, -1, 26, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 42,
+ 43, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 58, 59, 60, 61, -1,
+ 63, -1, 65, 66, -1, -1, -1, 70, 71, 72,
+ 73, 3, 4, 5, 6, 7, -1, -1, -1, -1,
+ 12, -1, -1, 15, -1, 17, 18, -1, 20, -1,
+ -1, -1, -1, -1, 26, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 43, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 58, 59, 60, 61,
+ 62, 63, -1, 65, -1, -1, -1, -1, 70, 71,
+ 72, 73, 3, 4, 5, 6, 7, -1, -1, -1,
+ -1, 12, -1, -1, 15, -1, 17, 18, -1, 20,
+ -1, -1, -1, -1, -1, 26, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 42, 43, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 58, 59, 60,
+ 61, -1, 63, -1, 65, 66, -1, -1, -1, 70,
+ 71, 72, 73, 3, 4, 5, 6, 7, -1, -1,
+ -1, -1, 12, -1, -1, 15, -1, 17, 18, -1,
+ 20, -1, -1, -1, -1, -1, 26, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 42, 43, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 58, 59,
+ 60, 61, -1, 63, -1, 65, -1, -1, -1, -1,
+ 70, 71, 72, 73
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/misc/bison.simple"
+/* This file comes from bison-1.28. */
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ 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. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
+/* #include <malloc.h> */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ unsigned int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+ register char *t = to;
+ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 217 "/usr/share/misc/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 1:
+#line 157 "grammar.y"
+{ yyval.node = new NullNode(); ;
+ break;}
+case 2:
+#line 158 "grammar.y"
+{ yyval.node = new BooleanNode(true); ;
+ break;}
+case 3:
+#line 159 "grammar.y"
+{ yyval.node = new BooleanNode(false); ;
+ break;}
+case 4:
+#line 160 "grammar.y"
+{ yyval.node = new NumberNode(yyvsp[0].dval); ;
+ break;}
+case 5:
+#line 161 "grammar.y"
+{ yyval.node = new StringNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 6:
+#line 162 "grammar.y"
+{ Lexer *l = Lexer::curr();
+ if (!l->scanRegExp()) YYABORT;
+ yyval.node = new RegExpNode(l->pattern,l->flags);;
+ break;}
+case 7:
+#line 168 "grammar.y"
+{ yyval.node = new ThisNode(); ;
+ break;}
+case 8:
+#line 169 "grammar.y"
+{ yyval.node = new ResolveNode(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 11:
+#line 173 "grammar.y"
+{ yyval.node = new GroupNode(yyvsp[-1].node); ;
+ break;}
+case 12:
+#line 174 "grammar.y"
+{ yyval.node = new ObjectLiteralNode(0L); ;
+ break;}
+case 13:
+#line 175 "grammar.y"
+{ yyval.node = new ObjectLiteralNode(yyvsp[-1].node); ;
+ break;}
+case 14:
+#line 179 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].eli); ;
+ break;}
+case 15:
+#line 180 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].elm); ;
+ break;}
+case 16:
+#line 181 "grammar.y"
+{ yyval.node = new ArrayNode(yyvsp[-1].eli, yyvsp[-3].elm); ;
+ break;}
+case 17:
+#line 185 "grammar.y"
+{ yyval.elm = new ElementNode(yyvsp[-1].eli, yyvsp[0].node); ;
+ break;}
+case 18:
+#line 187 "grammar.y"
+{ yyval.elm = new ElementNode(yyvsp[-3].elm, yyvsp[-1].eli, yyvsp[0].node); ;
+ break;}
+case 19:
+#line 191 "grammar.y"
+{ yyval.eli = 0L; ;
+ break;}
+case 21:
+#line 196 "grammar.y"
+{ yyval.eli = new ElisionNode(0L); ;
+ break;}
+case 22:
+#line 197 "grammar.y"
+{ yyval.eli = new ElisionNode(yyvsp[-1].eli); ;
+ break;}
+case 23:
+#line 201 "grammar.y"
+{ yyval.node = new PropertyValueNode(yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 24:
+#line 203 "grammar.y"
+{ yyval.node = new PropertyValueNode(yyvsp[-2].node, yyvsp[0].node, yyvsp[-4].node); ;
+ break;}
+case 25:
+#line 207 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 26:
+#line 209 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 27:
+#line 210 "grammar.y"
+{ yyval.node = new PropertyNode(yyvsp[0].dval); ;
+ break;}
+case 30:
+#line 216 "grammar.y"
+{ yyval.node = new AccessorNode1(yyvsp[-3].node, yyvsp[-1].node); ;
+ break;}
+case 31:
+#line 217 "grammar.y"
+{ yyval.node = new AccessorNode2(yyvsp[-2].node, yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 32:
+#line 219 "grammar.y"
+{ yyval.node = new NewExprNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 34:
+#line 224 "grammar.y"
+{ yyval.node = new NewExprNode(yyvsp[0].node); ;
+ break;}
+case 35:
+#line 228 "grammar.y"
+{ yyval.node = new FunctionCallNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 36:
+#line 229 "grammar.y"
+{ yyval.node = new FunctionCallNode(yyvsp[-1].node, yyvsp[0].args); ;
+ break;}
+case 37:
+#line 230 "grammar.y"
+{ yyval.node = new AccessorNode1(yyvsp[-3].node, yyvsp[-1].node); ;
+ break;}
+case 38:
+#line 231 "grammar.y"
+{ yyval.node = new AccessorNode2(yyvsp[-2].node, yyvsp[0].ustr); ;
+ break;}
+case 39:
+#line 235 "grammar.y"
+{ yyval.args = new ArgumentsNode(0L); ;
+ break;}
+case 40:
+#line 236 "grammar.y"
+{ yyval.args = new ArgumentsNode(yyvsp[-1].alist); ;
+ break;}
+case 41:
+#line 240 "grammar.y"
+{ yyval.alist = new ArgumentListNode(yyvsp[0].node); ;
+ break;}
+case 42:
+#line 241 "grammar.y"
+{ yyval.alist = new ArgumentListNode(yyvsp[-2].alist, yyvsp[0].node); ;
+ break;}
+case 46:
+#line 251 "grammar.y"
+{ yyval.node = new PostfixNode(yyvsp[-1].node, OpPlusPlus); ;
+ break;}
+case 47:
+#line 252 "grammar.y"
+{ yyval.node = new PostfixNode(yyvsp[-1].node, OpMinusMinus); ;
+ break;}
+case 49:
+#line 257 "grammar.y"
+{ yyval.node = new DeleteNode(yyvsp[0].node); ;
+ break;}
+case 50:
+#line 258 "grammar.y"
+{ yyval.node = new VoidNode(yyvsp[0].node); ;
+ break;}
+case 51:
+#line 259 "grammar.y"
+{ yyval.node = new TypeOfNode(yyvsp[0].node); ;
+ break;}
+case 52:
+#line 260 "grammar.y"
+{ yyval.node = new PrefixNode(OpPlusPlus, yyvsp[0].node); ;
+ break;}
+case 53:
+#line 261 "grammar.y"
+{ yyval.node = new PrefixNode(OpPlusPlus, yyvsp[0].node); ;
+ break;}
+case 54:
+#line 262 "grammar.y"
+{ yyval.node = new PrefixNode(OpMinusMinus, yyvsp[0].node); ;
+ break;}
+case 55:
+#line 263 "grammar.y"
+{ yyval.node = new PrefixNode(OpMinusMinus, yyvsp[0].node); ;
+ break;}
+case 56:
+#line 264 "grammar.y"
+{ yyval.node = new UnaryPlusNode(yyvsp[0].node); ;
+ break;}
+case 57:
+#line 265 "grammar.y"
+{ yyval.node = new NegateNode(yyvsp[0].node); ;
+ break;}
+case 58:
+#line 266 "grammar.y"
+{ yyval.node = new BitwiseNotNode(yyvsp[0].node); ;
+ break;}
+case 59:
+#line 267 "grammar.y"
+{ yyval.node = new LogicalNotNode(yyvsp[0].node); ;
+ break;}
+case 61:
+#line 272 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node, yyvsp[0].node, '*'); ;
+ break;}
+case 62:
+#line 273 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node, yyvsp[0].node, '/'); ;
+ break;}
+case 63:
+#line 274 "grammar.y"
+{ yyval.node = new MultNode(yyvsp[-2].node,yyvsp[0].node,'%'); ;
+ break;}
+case 65:
+#line 279 "grammar.y"
+{ yyval.node = new AddNode(yyvsp[-2].node, yyvsp[0].node, '+'); ;
+ break;}
+case 66:
+#line 280 "grammar.y"
+{ yyval.node = new AddNode(yyvsp[-2].node, yyvsp[0].node, '-'); ;
+ break;}
+case 68:
+#line 285 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpLShift, yyvsp[0].node); ;
+ break;}
+case 69:
+#line 286 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpRShift, yyvsp[0].node); ;
+ break;}
+case 70:
+#line 287 "grammar.y"
+{ yyval.node = new ShiftNode(yyvsp[-2].node, OpURShift, yyvsp[0].node); ;
+ break;}
+case 72:
+#line 293 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpLess, yyvsp[0].node); ;
+ break;}
+case 73:
+#line 295 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpGreater, yyvsp[0].node); ;
+ break;}
+case 74:
+#line 297 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpLessEq, yyvsp[0].node); ;
+ break;}
+case 75:
+#line 299 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpGreaterEq, yyvsp[0].node); ;
+ break;}
+case 76:
+#line 301 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpInstanceOf, yyvsp[0].node); ;
+ break;}
+case 77:
+#line 303 "grammar.y"
+{ yyval.node = new RelationalNode(yyvsp[-2].node, OpIn, yyvsp[0].node); ;
+ break;}
+case 79:
+#line 308 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpEqEq, yyvsp[0].node); ;
+ break;}
+case 80:
+#line 309 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpNotEq, yyvsp[0].node); ;
+ break;}
+case 81:
+#line 310 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpStrEq, yyvsp[0].node); ;
+ break;}
+case 82:
+#line 311 "grammar.y"
+{ yyval.node = new EqualNode(yyvsp[-2].node, OpStrNEq, yyvsp[0].node);;
+ break;}
+case 84:
+#line 316 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitAnd, yyvsp[0].node); ;
+ break;}
+case 86:
+#line 321 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitXOr, yyvsp[0].node); ;
+ break;}
+case 88:
+#line 326 "grammar.y"
+{ yyval.node = new BitOperNode(yyvsp[-2].node, OpBitOr, yyvsp[0].node); ;
+ break;}
+case 90:
+#line 332 "grammar.y"
+{ yyval.node = new BinaryLogicalNode(yyvsp[-2].node, OpAnd, yyvsp[0].node); ;
+ break;}
+case 92:
+#line 338 "grammar.y"
+{ yyval.node = new BinaryLogicalNode(yyvsp[-2].node, OpOr, yyvsp[0].node); ;
+ break;}
+case 94:
+#line 344 "grammar.y"
+{ yyval.node = new ConditionalNode(yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 96:
+#line 350 "grammar.y"
+{ yyval.node = new AssignNode(yyvsp[-2].node, yyvsp[-1].op, yyvsp[0].node);;
+ break;}
+case 97:
+#line 354 "grammar.y"
+{ yyval.op = OpEqual; ;
+ break;}
+case 98:
+#line 355 "grammar.y"
+{ yyval.op = OpPlusEq; ;
+ break;}
+case 99:
+#line 356 "grammar.y"
+{ yyval.op = OpMinusEq; ;
+ break;}
+case 100:
+#line 357 "grammar.y"
+{ yyval.op = OpMultEq; ;
+ break;}
+case 101:
+#line 358 "grammar.y"
+{ yyval.op = OpDivEq; ;
+ break;}
+case 102:
+#line 359 "grammar.y"
+{ yyval.op = OpLShift; ;
+ break;}
+case 103:
+#line 360 "grammar.y"
+{ yyval.op = OpRShift; ;
+ break;}
+case 104:
+#line 361 "grammar.y"
+{ yyval.op = OpURShift; ;
+ break;}
+case 105:
+#line 362 "grammar.y"
+{ yyval.op = OpAndEq; ;
+ break;}
+case 106:
+#line 363 "grammar.y"
+{ yyval.op = OpXOrEq; ;
+ break;}
+case 107:
+#line 364 "grammar.y"
+{ yyval.op = OpOrEq; ;
+ break;}
+case 108:
+#line 365 "grammar.y"
+{ yyval.op = OpModEq; ;
+ break;}
+case 110:
+#line 370 "grammar.y"
+{ yyval.node = new CommaNode(yyvsp[-2].node, yyvsp[0].node); ;
+ break;}
+case 125:
+#line 391 "grammar.y"
+{ yyval.stat = new BlockNode(0L); DBG(yyval.stat, yylsp[0], yylsp[0]); ;
+ break;}
+case 126:
+#line 392 "grammar.y"
+{ yyval.stat = new BlockNode(yyvsp[-1].slist); DBG(yyval.stat, yylsp[0], yylsp[0]); ;
+ break;}
+case 127:
+#line 396 "grammar.y"
+{ yyval.slist = new StatListNode(yyvsp[0].stat); ;
+ break;}
+case 128:
+#line 397 "grammar.y"
+{ yyval.slist = new StatListNode(yyvsp[-1].slist, yyvsp[0].stat); ;
+ break;}
+case 129:
+#line 401 "grammar.y"
+{ yyval.stat = new VarStatementNode(yyvsp[-1].vlist);
+ DBG(yyval.stat, yylsp[-2], yylsp[0]); ;
+ break;}
+case 130:
+#line 403 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new VarStatementNode(yyvsp[-1].vlist);
+ DBG(yyval.stat, yylsp[-2], yylsp[-1]);
+ } else {
+ YYABORT;
+ }
+ ;
+ break;}
+case 131:
+#line 413 "grammar.y"
+{ yyval.vlist = new VarDeclListNode(yyvsp[0].decl); ;
+ break;}
+case 132:
+#line 415 "grammar.y"
+{ yyval.vlist = new VarDeclListNode(yyvsp[-2].vlist, yyvsp[0].decl); ;
+ break;}
+case 133:
+#line 419 "grammar.y"
+{ yyval.decl = new VarDeclNode(yyvsp[0].ustr, 0); delete yyvsp[0].ustr; ;
+ break;}
+case 134:
+#line 420 "grammar.y"
+{ yyval.decl = new VarDeclNode(yyvsp[-1].ustr, yyvsp[0].init); delete yyvsp[-1].ustr; ;
+ break;}
+case 135:
+#line 424 "grammar.y"
+{ yyval.init = new AssignExprNode(yyvsp[0].node); ;
+ break;}
+case 136:
+#line 428 "grammar.y"
+{ yyval.stat = new EmptyStatementNode(); ;
+ break;}
+case 137:
+#line 432 "grammar.y"
+{ yyval.stat = new ExprStatementNode(yyvsp[-1].node);
+ DBG(yyval.stat, yylsp[-1], yylsp[0]); ;
+ break;}
+case 138:
+#line 434 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ExprStatementNode(yyvsp[-1].node);
+ DBG(yyval.stat, yylsp[-1], yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 139:
+#line 442 "grammar.y"
+{ yyval.stat = new IfNode(yyvsp[-2].node,yyvsp[0].stat,0L);DBG(yyval.stat,yylsp[-4],yylsp[-1]); ;
+ break;}
+case 140:
+#line 444 "grammar.y"
+{ yyval.stat = new IfNode(yyvsp[-4].node,yyvsp[-2].stat,yyvsp[0].stat);DBG(yyval.stat,yylsp[-6],yylsp[-3]); ;
+ break;}
+case 141:
+#line 448 "grammar.y"
+{ yyval.stat=new DoWhileNode(yyvsp[-4].stat,yyvsp[-1].node);DBG(yyval.stat,yylsp[-5],yylsp[-3]);;
+ break;}
+case 142:
+#line 449 "grammar.y"
+{ yyval.stat = new WhileNode(yyvsp[-2].node,yyvsp[0].stat);DBG(yyval.stat,yylsp[-4],yylsp[-1]); ;
+ break;}
+case 143:
+#line 451 "grammar.y"
+{ yyval.stat = new ForNode(yyvsp[-6].node,yyvsp[-4].node,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-8],yylsp[-1]); ;
+ break;}
+case 144:
+#line 454 "grammar.y"
+{ yyval.stat = new ForNode(yyvsp[-6].vlist,yyvsp[-4].node,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-9],yylsp[-1]); ;
+ break;}
+case 145:
+#line 457 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-4].node, yyvsp[-2].node, yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-6],yylsp[-1]); ;
+ break;}
+case 146:
+#line 460 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-4].ustr,0L,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-7],yylsp[-1]);
+ delete yyvsp[-4].ustr; ;
+ break;}
+case 147:
+#line 464 "grammar.y"
+{ yyval.stat = new ForInNode(yyvsp[-5].ustr,yyvsp[-4].init,yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat,yylsp[-8],yylsp[-1]);
+ delete yyvsp[-5].ustr; ;
+ break;}
+case 148:
+#line 470 "grammar.y"
+{ yyval.node = 0L; ;
+ break;}
+case 150:
+#line 475 "grammar.y"
+{ yyval.stat = new ContinueNode(); DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 151:
+#line 476 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ContinueNode(); DBG(yyval.stat,yylsp[-1],yylsp[0]);
+ } else
+ YYABORT; ;
+ break;}
+case 152:
+#line 480 "grammar.y"
+{ yyval.stat = new ContinueNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[0]);
+ delete yyvsp[-1].ustr; ;
+ break;}
+case 153:
+#line 482 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ContinueNode(yyvsp[-1].ustr);DBG(yyval.stat,yylsp[-2],yylsp[-1]);
+ delete yyvsp[-1].ustr;
+ } else
+ YYABORT; ;
+ break;}
+case 154:
+#line 490 "grammar.y"
+{ yyval.stat = new BreakNode();DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 155:
+#line 491 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new BreakNode(); DBG(yyval.stat,yylsp[-1],yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 156:
+#line 495 "grammar.y"
+{ yyval.stat = new BreakNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[0]);
+ delete yyvsp[-1].ustr; ;
+ break;}
+case 157:
+#line 497 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new BreakNode(yyvsp[-1].ustr); DBG(yyval.stat,yylsp[-2],yylsp[-1]);
+ delete yyvsp[-1].ustr;
+ } else
+ YYABORT;
+ ;
+ break;}
+case 158:
+#line 506 "grammar.y"
+{ yyval.stat = new ReturnNode(0L); DBG(yyval.stat,yylsp[-1],yylsp[0]); ;
+ break;}
+case 159:
+#line 507 "grammar.y"
+{ if (automatic()) {
+ yyval.stat = new ReturnNode(0L); DBG(yyval.stat,yylsp[-1],yylsp[-1]);
+ } else
+ YYABORT; ;
+ break;}
+case 160:
+#line 511 "grammar.y"
+{ yyval.stat = new ReturnNode(yyvsp[-1].node); ;
+ break;}
+case 161:
+#line 512 "grammar.y"
+{ if (automatic())
+ yyval.stat = new ReturnNode(yyvsp[-1].node);
+ else
+ YYABORT; ;
+ break;}
+case 162:
+#line 519 "grammar.y"
+{ yyval.stat = new WithNode(yyvsp[-2].node,yyvsp[0].stat);
+ DBG(yyval.stat, yylsp[-4], yylsp[-1]); ;
+ break;}
+case 163:
+#line 524 "grammar.y"
+{ yyval.stat = new SwitchNode(yyvsp[-2].node, yyvsp[0].cblk);
+ DBG(yyval.stat, yylsp[-4], yylsp[-1]); ;
+ break;}
+case 164:
+#line 529 "grammar.y"
+{ yyval.cblk = new CaseBlockNode(yyvsp[-1].clist, 0L, 0L); ;
+ break;}
+case 165:
+#line 531 "grammar.y"
+{ yyval.cblk = new CaseBlockNode(yyvsp[-3].clist, yyvsp[-2].ccl, yyvsp[-1].clist); ;
+ break;}
+case 166:
+#line 535 "grammar.y"
+{ yyval.clist = 0L; ;
+ break;}
+case 168:
+#line 540 "grammar.y"
+{ yyval.clist = new ClauseListNode(yyvsp[0].ccl); ;
+ break;}
+case 169:
+#line 541 "grammar.y"
+{ yyval.clist = yyvsp[-1].clist->append(yyvsp[0].ccl); ;
+ break;}
+case 170:
+#line 545 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(yyvsp[-1].node, 0L); ;
+ break;}
+case 171:
+#line 546 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(yyvsp[-2].node, yyvsp[0].slist); ;
+ break;}
+case 172:
+#line 550 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(0L, 0L);; ;
+ break;}
+case 173:
+#line 551 "grammar.y"
+{ yyval.ccl = new CaseClauseNode(0L, yyvsp[0].slist); ;
+ break;}
+case 174:
+#line 555 "grammar.y"
+{ yyvsp[0].stat->pushLabel(yyvsp[-2].ustr);
+ yyval.stat = new LabelNode(yyvsp[-2].ustr, yyvsp[0].stat);
+ delete yyvsp[-2].ustr; ;
+ break;}
+case 175:
+#line 561 "grammar.y"
+{ yyval.stat = new ThrowNode(yyvsp[-1].node); ;
+ break;}
+case 176:
+#line 565 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-1].stat, yyvsp[0].node); ;
+ break;}
+case 177:
+#line 566 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-1].stat, 0L, yyvsp[0].node); ;
+ break;}
+case 178:
+#line 567 "grammar.y"
+{ yyval.stat = new TryNode(yyvsp[-2].stat, yyvsp[-1].node, yyvsp[0].node); ;
+ break;}
+case 179:
+#line 571 "grammar.y"
+{ yyval.node = new CatchNode(yyvsp[-2].ustr, yyvsp[0].stat); delete yyvsp[-2].ustr; ;
+ break;}
+case 180:
+#line 575 "grammar.y"
+{ yyval.node = new FinallyNode(yyvsp[0].stat); ;
+ break;}
+case 181:
+#line 579 "grammar.y"
+{ yyval.func = new FuncDeclNode(yyvsp[-3].ustr, 0L, yyvsp[0].body);
+ delete yyvsp[-3].ustr; ;
+ break;}
+case 182:
+#line 582 "grammar.y"
+{ yyval.func = new FuncDeclNode(yyvsp[-4].ustr, yyvsp[-2].param, yyvsp[0].body);
+ delete yyvsp[-4].ustr; ;
+ break;}
+case 183:
+#line 586 "grammar.y"
+{ yyval.node = new FuncExprNode(0L, yyvsp[0].body); ;
+ break;}
+case 184:
+#line 588 "grammar.y"
+{ yyval.node = new FuncExprNode(yyvsp[-2].param, yyvsp[0].body); ;
+ break;}
+case 185:
+#line 593 "grammar.y"
+{ yyval.param = new ParameterNode(yyvsp[0].ustr); delete yyvsp[0].ustr; ;
+ break;}
+case 186:
+#line 594 "grammar.y"
+{ yyval.param = yyvsp[-2].param->append(yyvsp[0].ustr);
+ delete yyvsp[0].ustr; ;
+ break;}
+case 187:
+#line 599 "grammar.y"
+{ yyval.body = new FunctionBodyNode(0L); ;
+ break;}
+case 188:
+#line 600 "grammar.y"
+{ yyval.body = new FunctionBodyNode(yyvsp[-1].srcs); ;
+ break;}
+case 189:
+#line 604 "grammar.y"
+{ yyval.prog = new ProgramNode(yyvsp[0].srcs);
+ KJScriptImp::current()->setProgNode(yyval.prog); ;
+ break;}
+case 190:
+#line 609 "grammar.y"
+{ yyval.srcs = new SourceElementsNode(yyvsp[0].src); ;
+ break;}
+case 191:
+#line 610 "grammar.y"
+{ yyval.srcs = new SourceElementsNode(yyvsp[-1].srcs, yyvsp[0].src); ;
+ break;}
+case 192:
+#line 614 "grammar.y"
+{ yyval.src = new SourceElementNode(yyvsp[0].stat); ;
+ break;}
+case 193:
+#line 615 "grammar.y"
+{ yyval.src = new SourceElementNode(yyvsp[0].func); ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/share/misc/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
+}
+#line 618 "grammar.y"
+
+
+int yyerror (const char *) /* Called by yyparse on error */
+{
+// fprintf(stderr, "ERROR: %s at line %d\n",
+// s, KJScript::lexer()->lineNo());
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+bool automatic()
+{
+ if (yychar == '}' || yychar == 0)
+ return true;
+ else if (Lexer::curr()->prevTerminator())
+ return true;
+
+ return false;
+}
diff --git a/WebCore/src/kdelibs/kjs/grammar.h b/WebCore/src/kdelibs/kjs/grammar.h
new file mode 100644
index 0000000..38eb0ba
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/grammar.h
@@ -0,0 +1,102 @@
+typedef union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+} YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#define NULLTOKEN 257
+#define TRUETOKEN 258
+#define FALSETOKEN 259
+#define STRING 260
+#define NUMBER 261
+#define BREAK 262
+#define CASE 263
+#define DEFAULT 264
+#define FOR 265
+#define NEW 266
+#define VAR 267
+#define CONTINUE 268
+#define FUNCTION 269
+#define RETURN 270
+#define VOID 271
+#define DELETE 272
+#define IF 273
+#define THIS 274
+#define DO 275
+#define WHILE 276
+#define ELSE 277
+#define IN 278
+#define INSTANCEOF 279
+#define TYPEOF 280
+#define SWITCH 281
+#define WITH 282
+#define RESERVED 283
+#define THROW 284
+#define TRY 285
+#define CATCH 286
+#define FINALLY 287
+#define EQEQ 288
+#define NE 289
+#define STREQ 290
+#define STRNEQ 291
+#define LE 292
+#define GE 293
+#define OR 294
+#define AND 295
+#define PLUSPLUS 296
+#define MINUSMINUS 297
+#define LSHIFT 298
+#define RSHIFT 299
+#define URSHIFT 300
+#define PLUSEQUAL 301
+#define MINUSEQUAL 302
+#define MULTEQUAL 303
+#define DIVEQUAL 304
+#define LSHIFTEQUAL 305
+#define RSHIFTEQUAL 306
+#define URSHIFTEQUAL 307
+#define ANDEQUAL 308
+#define MODEQUAL 309
+#define XOREQUAL 310
+#define OREQUAL 311
+#define IDENT 312
+#define AUTO 313
+
+
+extern YYSTYPE kjsyylval;
diff --git a/WebCore/src/kdelibs/kjs/grammar.y b/WebCore/src/kdelibs/kjs/grammar.y
new file mode 100644
index 0000000..cf07456
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/grammar.y
@@ -0,0 +1,636 @@
+%{
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+
+/* default values for bison */
+#define YYDEBUG 0
+#define YYMAXDEPTH 0
+#ifdef KJS_DEBUGGER
+#define YYERROR_VERBOSE
+#define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line); } // location
+#else
+#undef YYLSP_NEEDED
+#define DBG(l, s, e)
+#endif
+
+extern int yylex();
+int yyerror (const char *);
+bool automatic();
+
+using namespace KJS;
+
+%}
+
+%union {
+ int ival;
+ double dval;
+ UString *ustr;
+ Node *node;
+ StatementNode *stat;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ FuncDeclNode *func;
+ ProgramNode *prog;
+ AssignExprNode *init;
+ SourceElementNode *src;
+ SourceElementsNode *srcs;
+ StatListNode *slist;
+ ArgumentsNode *args;
+ ArgumentListNode *alist;
+ VarDeclNode *decl;
+ VarDeclListNode *vlist;
+ CaseBlockNode *cblk;
+ ClauseListNode *clist;
+ CaseClauseNode *ccl;
+ ElementNode *elm;
+ ElisionNode *eli;
+ Operator op;
+}
+
+%start Program
+
+/* expect a shift/reduce conflict from the "dangling else" problem
+ when using bison the warning can be supressed */
+// %expect 1
+
+/* literals */
+%token NULLTOKEN TRUETOKEN FALSETOKEN
+%token STRING NUMBER
+
+/* keywords */
+%token BREAK CASE DEFAULT FOR NEW VAR CONTINUE
+%token FUNCTION RETURN VOID DELETE
+%token IF THIS DO WHILE ELSE IN INSTANCEOF TYPEOF
+%token SWITCH WITH RESERVED
+%token THROW TRY CATCH FINALLY
+
+/* punctuators */
+%token EQEQ NE /* == and != */
+%token STREQ STRNEQ /* === and !== */
+%token LE GE /* < and > */
+%token OR AND /* || and && */
+%token PLUSPLUS MINUSMINUS /* ++ and -- */
+%token LSHIFT /* << */
+%token RSHIFT URSHIFT /* >> and >>> */
+%token PLUSEQUAL MINUSEQUAL /* += and -= */
+%token MULTEQUAL DIVEQUAL /* *= and /= */
+%token LSHIFTEQUAL /* <<= */
+%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
+%token ANDEQUAL MODEQUAL /* &= and %= */
+%token XOREQUAL OREQUAL /* ^= and |= */
+
+/* terminal types */
+%token <dval> NUMBER
+%token <ustr> STRING
+%token <ustr> IDENT
+
+/* automatically inserted semicolon */
+%token AUTO
+
+/* non-terminal types */
+%type <node> Literal PrimaryExpr Expr MemberExpr FunctionExpr NewExpr CallExpr
+%type <node> ArrayLiteral PropertyName PropertyNameAndValueList
+%type <node> LeftHandSideExpr PostfixExpr UnaryExpr
+%type <node> MultiplicativeExpr AdditiveExpr
+%type <node> ShiftExpr RelationalExpr EqualityExpr
+%type <node> BitwiseANDExpr BitwiseXORExpr BitwiseORExpr
+%type <node> LogicalANDExpr LogicalORExpr
+%type <node> ConditionalExpr AssignmentExpr
+%type <node> ExprOpt
+%type <node> CallExpr
+%type <node> Catch Finally
+
+%type <stat> Statement Block
+%type <stat> VariableStatement EmptyStatement ExprStatement
+%type <stat> IfStatement IterationStatement ContinueStatement
+%type <stat> BreakStatement ReturnStatement WithStatement
+%type <stat> SwitchStatement LabelledStatement
+%type <stat> ThrowStatement TryStatement
+
+%type <slist> StatementList
+%type <init> Initializer
+%type <func> FunctionDeclaration
+%type <body> FunctionBody
+%type <src> SourceElement
+%type <srcs> SourceElements
+%type <param> FormalParameterList
+%type <op> AssignmentOperator
+%type <prog> Program
+%type <args> Arguments
+%type <alist> ArgumentList
+%type <vlist> VariableDeclarationList
+%type <decl> VariableDeclaration
+%type <cblk> CaseBlock
+%type <ccl> CaseClause DefaultClause
+%type <clist> CaseClauses CaseClausesOpt
+%type <eli> Elision ElisionOpt
+%type <elm> ElementList
+
+%%
+
+Literal:
+ NULLTOKEN { $$ = new NullNode(); }
+ | TRUETOKEN { $$ = new BooleanNode(true); }
+ | FALSETOKEN { $$ = new BooleanNode(false); }
+ | NUMBER { $$ = new NumberNode($1); }
+ | STRING { $$ = new StringNode($1); delete $1; }
+ | '/' /* a RegExp ? */ { Lexer *l = Lexer::curr();
+ if (!l->scanRegExp()) YYABORT;
+ $$ = new RegExpNode(l->pattern,l->flags);}
+;
+
+PrimaryExpr:
+ THIS { $$ = new ThisNode(); }
+ | IDENT { $$ = new ResolveNode($1);
+ delete $1; }
+ | Literal
+ | ArrayLiteral
+ | '(' Expr ')' { $$ = new GroupNode($2); }
+ | '{' '}' { $$ = new ObjectLiteralNode(0L); }
+ | '{' PropertyNameAndValueList '}' { $$ = new ObjectLiteralNode($2); }
+;
+
+ArrayLiteral:
+ '[' ElisionOpt ']' { $$ = new ArrayNode($2); }
+ | '[' ElementList ']' { $$ = new ArrayNode($2); }
+ | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
+;
+
+ElementList:
+ ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $2); }
+ | ElementList ',' ElisionOpt AssignmentExpr
+ { $$ = new ElementNode($1, $3, $4); }
+;
+
+ElisionOpt:
+ /* nothing */ { $$ = 0L; }
+ | Elision
+;
+
+Elision:
+ ',' { $$ = new ElisionNode(0L); }
+ | Elision ',' { $$ = new ElisionNode($1); }
+;
+
+PropertyNameAndValueList:
+ PropertyName ':' AssignmentExpr { $$ = new PropertyValueNode($1, $3); }
+ | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
+ { $$ = new PropertyValueNode($3, $5, $1); }
+;
+
+PropertyName:
+ IDENT { $$ = new PropertyNode($1);
+ delete $1; }
+ | STRING { $$ = new PropertyNode($1); delete $1; }
+ | NUMBER { $$ = new PropertyNode($1); }
+;
+
+MemberExpr:
+ PrimaryExpr
+ | FunctionExpr
+ | MemberExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
+ | MemberExpr '.' IDENT { $$ = new AccessorNode2($1, $3);
+ delete $3; }
+ | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
+;
+
+NewExpr:
+ MemberExpr
+ | NEW NewExpr { $$ = new NewExprNode($2); }
+;
+
+CallExpr:
+ MemberExpr Arguments { $$ = new FunctionCallNode($1, $2); }
+ | CallExpr Arguments { $$ = new FunctionCallNode($1, $2); }
+ | CallExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
+ | CallExpr '.' IDENT { $$ = new AccessorNode2($1, $3); }
+;
+
+Arguments:
+ '(' ')' { $$ = new ArgumentsNode(0L); }
+ | '(' ArgumentList ')' { $$ = new ArgumentsNode($2); }
+;
+
+ArgumentList:
+ AssignmentExpr { $$ = new ArgumentListNode($1); }
+ | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
+;
+
+LeftHandSideExpr:
+ NewExpr
+ | CallExpr
+;
+
+PostfixExpr: /* TODO: no line terminator here */
+ LeftHandSideExpr
+ | LeftHandSideExpr PLUSPLUS { $$ = new PostfixNode($1, OpPlusPlus); }
+ | LeftHandSideExpr MINUSMINUS { $$ = new PostfixNode($1, OpMinusMinus); }
+;
+
+UnaryExpr:
+ PostfixExpr
+ | DELETE UnaryExpr { $$ = new DeleteNode($2); }
+ | VOID UnaryExpr { $$ = new VoidNode($2); }
+ | TYPEOF UnaryExpr { $$ = new TypeOfNode($2); }
+ | PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
+ | AUTO PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $3); }
+ | MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
+ | AUTO MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $3); }
+ | '+' UnaryExpr { $$ = new UnaryPlusNode($2); }
+ | '-' UnaryExpr { $$ = new NegateNode($2); }
+ | '~' UnaryExpr { $$ = new BitwiseNotNode($2); }
+ | '!' UnaryExpr { $$ = new LogicalNotNode($2); }
+;
+
+MultiplicativeExpr:
+ UnaryExpr
+ | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
+ | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
+ | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
+;
+
+AdditiveExpr:
+ MultiplicativeExpr
+ | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
+ | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
+;
+
+ShiftExpr:
+ AdditiveExpr
+ | ShiftExpr LSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpLShift, $3); }
+ | ShiftExpr RSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpRShift, $3); }
+ | ShiftExpr URSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpURShift, $3); }
+;
+
+RelationalExpr:
+ ShiftExpr
+ | RelationalExpr '<' ShiftExpr
+ { $$ = new RelationalNode($1, OpLess, $3); }
+ | RelationalExpr '>' ShiftExpr
+ { $$ = new RelationalNode($1, OpGreater, $3); }
+ | RelationalExpr LE ShiftExpr
+ { $$ = new RelationalNode($1, OpLessEq, $3); }
+ | RelationalExpr GE ShiftExpr
+ { $$ = new RelationalNode($1, OpGreaterEq, $3); }
+ | RelationalExpr INSTANCEOF ShiftExpr
+ { $$ = new RelationalNode($1, OpInstanceOf, $3); }
+ | RelationalExpr IN ShiftExpr
+ { $$ = new RelationalNode($1, OpIn, $3); }
+;
+
+EqualityExpr:
+ RelationalExpr
+ | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, OpEqEq, $3); }
+ | EqualityExpr NE RelationalExpr { $$ = new EqualNode($1, OpNotEq, $3); }
+ | EqualityExpr STREQ RelationalExpr { $$ = new EqualNode($1, OpStrEq, $3); }
+ | EqualityExpr STRNEQ RelationalExpr { $$ = new EqualNode($1, OpStrNEq, $3);}
+;
+
+BitwiseANDExpr:
+ EqualityExpr
+ | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
+;
+
+BitwiseXORExpr:
+ BitwiseANDExpr
+ | BitwiseXORExpr '^' EqualityExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
+;
+
+BitwiseORExpr:
+ BitwiseXORExpr
+ | BitwiseORExpr '|' EqualityExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
+;
+
+LogicalANDExpr:
+ BitwiseORExpr
+ | LogicalANDExpr AND BitwiseORExpr
+ { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
+;
+
+LogicalORExpr:
+ LogicalANDExpr
+ | LogicalORExpr OR LogicalANDExpr
+ { $$ = new BinaryLogicalNode($1, OpOr, $3); }
+;
+
+ConditionalExpr:
+ LogicalORExpr
+ | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = new ConditionalNode($1, $3, $5); }
+;
+
+AssignmentExpr:
+ ConditionalExpr
+ | LeftHandSideExpr AssignmentOperator AssignmentExpr
+ { $$ = new AssignNode($1, $2, $3);}
+;
+
+AssignmentOperator:
+ '=' { $$ = OpEqual; }
+ | PLUSEQUAL { $$ = OpPlusEq; }
+ | MINUSEQUAL { $$ = OpMinusEq; }
+ | MULTEQUAL { $$ = OpMultEq; }
+ | DIVEQUAL { $$ = OpDivEq; }
+ | LSHIFTEQUAL { $$ = OpLShift; }
+ | RSHIFTEQUAL { $$ = OpRShift; }
+ | URSHIFTEQUAL { $$ = OpURShift; }
+ | ANDEQUAL { $$ = OpAndEq; }
+ | XOREQUAL { $$ = OpXOrEq; }
+ | OREQUAL { $$ = OpOrEq; }
+ | MODEQUAL { $$ = OpModEq; }
+;
+
+Expr:
+ AssignmentExpr
+ | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
+;
+
+Statement:
+ Block
+ | VariableStatement
+ | EmptyStatement
+ | ExprStatement
+ | IfStatement
+ | IterationStatement
+ | ContinueStatement
+ | BreakStatement
+ | ReturnStatement
+ | WithStatement
+ | SwitchStatement
+ | LabelledStatement
+ | ThrowStatement
+ | TryStatement
+;
+
+Block:
+ '{' '}' { $$ = new BlockNode(0L); DBG($$, @2, @2); }
+ | '{' StatementList '}' { $$ = new BlockNode($2); DBG($$, @3, @3); }
+;
+
+StatementList:
+ Statement { $$ = new StatListNode($1); }
+ | StatementList Statement { $$ = new StatListNode($1, $2); }
+;
+
+VariableStatement:
+ VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
+ DBG($$, @1, @3); }
+ | VAR VariableDeclarationList error { if (automatic()) {
+ $$ = new VarStatementNode($2);
+ DBG($$, @1, @2);
+ } else {
+ YYABORT;
+ }
+ }
+;
+
+VariableDeclarationList:
+ VariableDeclaration { $$ = new VarDeclListNode($1); }
+ | VariableDeclarationList ',' VariableDeclaration
+ { $$ = new VarDeclListNode($1, $3); }
+;
+
+VariableDeclaration:
+ IDENT { $$ = new VarDeclNode($1, 0); delete $1; }
+ | IDENT Initializer { $$ = new VarDeclNode($1, $2); delete $1; }
+;
+
+Initializer:
+ '=' AssignmentExpr { $$ = new AssignExprNode($2); }
+;
+
+EmptyStatement:
+ ';' { $$ = new EmptyStatementNode(); }
+;
+
+ExprStatement:
+ Expr ';' { $$ = new ExprStatementNode($1);
+ DBG($$, @1, @2); }
+ | Expr error { if (automatic()) {
+ $$ = new ExprStatementNode($1);
+ DBG($$, @1, @1);
+ } else
+ YYABORT; }
+;
+
+IfStatement: /* shift/reduce conflict due to dangling else */
+ IF '(' Expr ')' Statement { $$ = new IfNode($3,$5,0L);DBG($$,@1,@4); }
+ | IF '(' Expr ')' Statement ELSE Statement
+ { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
+;
+
+IterationStatement:
+ DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
+ | WHILE '(' Expr ')' Statement { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
+ | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
+ Statement { $$ = new ForNode($3,$5,$7,$9);
+ DBG($$,@1,@8); }
+ | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
+ Statement { $$ = new ForNode($4,$6,$8,$10);
+ DBG($$,@1,@9); }
+ | FOR '(' LeftHandSideExpr IN Expr ')'
+ Statement { $$ = new ForInNode($3, $5, $7);
+ DBG($$,@1,@6); }
+ | FOR '(' VAR IDENT IN Expr ')'
+ Statement { $$ = new ForInNode($4,0L,$6,$8);
+ DBG($$,@1,@7);
+ delete $4; }
+ | FOR '(' VAR IDENT Initializer IN Expr ')'
+ Statement { $$ = new ForInNode($4,$5,$7,$9);
+ DBG($$,@1,@8);
+ delete $4; }
+;
+
+ExprOpt:
+ /* nothing */ { $$ = 0L; }
+ | Expr
+;
+
+ContinueStatement:
+ CONTINUE ';' { $$ = new ContinueNode(); DBG($$,@1,@2); }
+ | CONTINUE error { if (automatic()) {
+ $$ = new ContinueNode(); DBG($$,@1,@2);
+ } else
+ YYABORT; }
+ | CONTINUE IDENT ';' { $$ = new ContinueNode($2); DBG($$,@1,@3);
+ delete $2; }
+ | CONTINUE IDENT error { if (automatic()) {
+ $$ = new ContinueNode($2);DBG($$,@1,@2);
+ delete $2;
+ } else
+ YYABORT; }
+;
+
+BreakStatement:
+ BREAK ';' { $$ = new BreakNode();DBG($$,@1,@2); }
+ | BREAK error { if (automatic()) {
+ $$ = new BreakNode(); DBG($$,@1,@1);
+ } else
+ YYABORT; }
+ | BREAK IDENT ';' { $$ = new BreakNode($2); DBG($$,@1,@3);
+ delete $2; }
+ | BREAK IDENT error { if (automatic()) {
+ $$ = new BreakNode($2); DBG($$,@1,@2);
+ delete $2;
+ } else
+ YYABORT;
+ }
+;
+
+ReturnStatement:
+ RETURN ';' { $$ = new ReturnNode(0L); DBG($$,@1,@2); }
+ | RETURN error { if (automatic()) {
+ $$ = new ReturnNode(0L); DBG($$,@1,@1);
+ } else
+ YYABORT; }
+ | RETURN Expr ';' { $$ = new ReturnNode($2); }
+ | RETURN Expr error { if (automatic())
+ $$ = new ReturnNode($2);
+ else
+ YYABORT; }
+;
+
+WithStatement:
+ WITH '(' Expr ')' Statement { $$ = new WithNode($3,$5);
+ DBG($$, @1, @4); }
+;
+
+SwitchStatement:
+ SWITCH '(' Expr ')' CaseBlock { $$ = new SwitchNode($3, $5);
+ DBG($$, @1, @4); }
+;
+
+CaseBlock:
+ '{' CaseClausesOpt '}' { $$ = new CaseBlockNode($2, 0L, 0L); }
+ | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
+ { $$ = new CaseBlockNode($2, $3, $4); }
+;
+
+CaseClausesOpt:
+ /* nothing */ { $$ = 0L; }
+ | CaseClauses
+;
+
+CaseClauses:
+ CaseClause { $$ = new ClauseListNode($1); }
+ | CaseClauses CaseClause { $$ = $1->append($2); }
+;
+
+CaseClause:
+ CASE Expr ':' { $$ = new CaseClauseNode($2, 0L); }
+ | CASE Expr ':' StatementList { $$ = new CaseClauseNode($2, $4); }
+;
+
+DefaultClause:
+ DEFAULT ':' { $$ = new CaseClauseNode(0L, 0L);; }
+ | DEFAULT ':' StatementList { $$ = new CaseClauseNode(0L, $3); }
+;
+
+LabelledStatement:
+ IDENT ':' Statement { $3->pushLabel($1);
+ $$ = new LabelNode($1, $3);
+ delete $1; }
+;
+
+ThrowStatement:
+ THROW Expr ';' { $$ = new ThrowNode($2); }
+;
+
+TryStatement:
+ TRY Block Catch { $$ = new TryNode($2, $3); }
+ | TRY Block Finally { $$ = new TryNode($2, 0L, $3); }
+ | TRY Block Catch Finally { $$ = new TryNode($2, $3, $4); }
+;
+
+Catch:
+ CATCH '(' IDENT ')' Block { $$ = new CatchNode($3, $5); delete $3; }
+;
+
+Finally:
+ FINALLY Block { $$ = new FinallyNode($2); }
+;
+
+FunctionDeclaration:
+ FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode($2, 0L, $5);
+ delete $2; }
+ | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
+ { $$ = new FuncDeclNode($2, $4, $6);
+ delete $2; }
+
+FunctionExpr:
+ FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode(0L, $4); }
+ | FUNCTION '(' FormalParameterList ')' FunctionBody
+ { $$ = new FuncExprNode($3, $5); }
+
+;
+
+FormalParameterList:
+ IDENT { $$ = new ParameterNode($1); delete $1; }
+ | FormalParameterList ',' IDENT { $$ = $1->append($3);
+ delete $3; }
+;
+
+FunctionBody:
+ '{' '}' /* TODO: spec ??? */ { $$ = new FunctionBodyNode(0L); }
+ | '{' SourceElements '}' { $$ = new FunctionBodyNode($2); }
+;
+
+Program:
+ SourceElements { $$ = new ProgramNode($1);
+ KJScriptImp::current()->setProgNode($$); }
+;
+
+SourceElements:
+ SourceElement { $$ = new SourceElementsNode($1); }
+ | SourceElements SourceElement { $$ = new SourceElementsNode($1, $2); }
+;
+
+SourceElement:
+ Statement { $$ = new SourceElementNode($1); }
+ | FunctionDeclaration { $$ = new SourceElementNode($1); }
+;
+
+%%
+
+int yyerror (const char *) /* Called by yyparse on error */
+{
+// fprintf(stderr, "ERROR: %s at line %d\n",
+// s, KJScript::lexer()->lineNo());
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+bool automatic()
+{
+ if (yychar == '}' || yychar == 0)
+ return true;
+ else if (Lexer::curr()->prevTerminator())
+ return true;
+
+ return false;
+}
diff --git a/WebCore/src/kdelibs/kjs/internal.cpp b/WebCore/src/kdelibs/kjs/internal.cpp
new file mode 100644
index 0000000..9fc40fa
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/internal.cpp
@@ -0,0 +1,912 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "internal.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "types.h"
+#include "operations.h"
+#include "regexp.h"
+#include "nodes.h"
+#include "lexer.h"
+#include "collector.h"
+#include "debugger.h"
+
+#define I18N_NOOP(s) s
+
+extern int kjsyyparse();
+
+using namespace KJS;
+
+const TypeInfo UndefinedImp::info = { "Undefined", UndefinedType, 0, 0, 0 };
+const TypeInfo NullImp::info = { "Null", NullType, 0, 0, 0 };
+const TypeInfo NumberImp::info = { "Number", NumberType, 0, 0,0 };
+const TypeInfo StringImp::info = { "String", StringType, 0, 0, 0 };
+const TypeInfo BooleanImp::info = { "Boolean", BooleanType, 0, 0, 0 };
+const TypeInfo CompletionImp::info = { "Completion", CompletionType, 0, 0, 0 };
+const TypeInfo ReferenceImp::info = { "Reference", ReferenceType, 0, 0, 0 };
+
+UndefinedImp *UndefinedImp::staticUndefined = 0;
+
+UndefinedImp::UndefinedImp()
+{
+}
+
+KJSO UndefinedImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean UndefinedImp::toBoolean() const
+{
+ return Boolean(false);
+}
+
+Number UndefinedImp::toNumber() const
+{
+ return Number(NaN);
+}
+
+String UndefinedImp::toString() const
+{
+ return String("undefined");
+}
+
+Object UndefinedImp::toObject() const
+{
+ return Error::createObject(TypeError, I18N_NOOP("Undefined value"));
+}
+
+NullImp *NullImp::staticNull = 0;
+
+NullImp::NullImp()
+{
+}
+
+KJSO NullImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean NullImp::toBoolean() const
+{
+ return Boolean(false);
+}
+
+Number NullImp::toNumber() const
+{
+ return Number(0);
+}
+
+String NullImp::toString() const
+{
+ return String("null");
+}
+
+Object NullImp::toObject() const
+{
+ return Error::createObject(TypeError, I18N_NOOP("Null value"));
+}
+
+BooleanImp* BooleanImp::staticTrue = 0;
+BooleanImp* BooleanImp::staticFalse = 0;
+
+KJSO BooleanImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean BooleanImp::toBoolean() const
+{
+ return Boolean((BooleanImp*)this);
+}
+
+Number BooleanImp::toNumber() const
+{
+ return Number(val ? 1 : 0);
+}
+
+String BooleanImp::toString() const
+{
+ return String(val ? "true" : "false");
+}
+
+Object BooleanImp::toObject() const
+{
+ return Object::create(BooleanClass, Boolean((BooleanImp*)this));
+}
+
+NumberImp::NumberImp(double v)
+ : val(v)
+{
+}
+
+KJSO NumberImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean NumberImp::toBoolean() const
+{
+ bool b = !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
+
+ return Boolean(b);
+}
+
+Number NumberImp::toNumber() const
+{
+ return Number((NumberImp*)this);
+}
+
+String NumberImp::toString() const
+{
+ return String(UString::from(val));
+}
+
+Object NumberImp::toObject() const
+{
+ return Object::create(NumberClass, Number((NumberImp*)this));
+}
+
+StringImp::StringImp(const UString& v)
+ : val(v)
+{
+}
+
+KJSO StringImp::toPrimitive(Type) const
+{
+ return (Imp*)this;
+}
+
+Boolean StringImp::toBoolean() const
+{
+ return Boolean(val.size() > 0);
+}
+
+Number StringImp::toNumber() const
+{
+ return Number(val.toDouble());
+}
+
+String StringImp::toString() const
+{
+ return String((StringImp*)this);
+}
+
+Object StringImp::toObject() const
+{
+ return Object::create(StringClass, String((StringImp*)this));
+}
+
+ReferenceImp::ReferenceImp(const KJSO& b, const UString& p)
+ : base(b), prop(p)
+{
+}
+
+void ReferenceImp::mark(Imp*)
+{
+ Imp::mark();
+ Imp *im = base.imp();
+ if (im && !im->marked())
+ im->mark();
+}
+
+CompletionImp::CompletionImp(Compl c, const KJSO& v, const UString& t)
+ : comp(c), val(v), tar(t)
+{
+}
+
+void CompletionImp::mark(Imp*)
+{
+ Imp::mark();
+ Imp *im = val.imp();
+ if (im && !im->marked())
+ im->mark();
+}
+
+RegExpImp::RegExpImp()
+ : ObjectImp(RegExpClass), reg(0L)
+{
+}
+
+RegExpImp::~RegExpImp()
+{
+ delete reg;
+}
+
+// ECMA 10.2
+Context::Context(CodeType type, Context *callingContext,
+ FunctionImp *func, const List *args, Imp *thisV)
+{
+ Global glob(Global::current());
+
+ // create and initialize activation object (ECMA 10.1.6)
+ if (type == FunctionCode || type == AnonymousCode || type == HostCode) {
+ activation = new ActivationImp(func, args);
+ variable = activation;
+ } else {
+ activation = KJSO();
+ variable = glob;
+ }
+
+ // ECMA 10.2
+ switch(type) {
+ case EvalCode:
+ if (callingContext) {
+ scopeChain = callingContext->copyOfChain();
+ variable = callingContext->variableObject();
+ thisVal = callingContext->thisValue();
+ break;
+ } // else same as GlobalCode
+ case GlobalCode:
+ scopeChain = new List();
+ scopeChain->append(glob);
+ thisVal = glob.imp();
+ break;
+ case FunctionCode:
+ case AnonymousCode:
+ if (type == FunctionCode) {
+ scopeChain = ((DeclaredFunctionImp*)func)->scopeChain()->copy();
+ scopeChain->prepend(activation);
+ } else {
+ scopeChain = new List();
+ scopeChain->append(activation);
+ scopeChain->append(glob);
+ }
+ variable = activation; /* TODO: DontDelete ? (ECMA 10.2.3) */
+ if (thisV->type() >= ObjectType) {
+ thisVal = thisV;
+ }
+ else
+ thisVal = glob.imp();
+ break;
+ case HostCode:
+ if (thisV->type() >= ObjectType)
+ thisVal = thisV;
+ else
+ thisVal = glob;
+ variable = activation; /* TODO: DontDelete (ECMA 10.2.4) */
+ scopeChain = new List();
+ scopeChain->append(activation);
+ if (func->hasAttribute(ImplicitThis))
+ scopeChain->append(KJSO(thisVal));
+ if (func->hasAttribute(ImplicitParents)) {
+ /* TODO ??? */
+ }
+ scopeChain->append(glob);
+ break;
+ }
+}
+
+Context::~Context()
+{
+ delete scopeChain;
+}
+
+Context *Context::current()
+{
+ return KJScriptImp::curr ? KJScriptImp::curr->con : 0L;
+}
+
+void Context::setCurrent(Context *c)
+{
+ KJScriptImp::current()->con = c;
+}
+
+void Context::pushScope(const KJSO &s)
+{
+ scopeChain->prepend(s);
+}
+
+void Context::popScope()
+{
+ scopeChain->removeFirst();
+}
+
+List* Context::copyOfChain()
+{
+ return scopeChain->copy();
+}
+
+
+AnonymousFunction::AnonymousFunction()
+ : Function(0L)
+{
+ /* TODO */
+}
+
+DeclaredFunctionImp::DeclaredFunctionImp(const UString &n,
+ FunctionBodyNode *b, const List *sc)
+ : ConstructorImp(n), body(b), scopes(sc->copy())
+{
+}
+
+DeclaredFunctionImp::~DeclaredFunctionImp()
+{
+ delete scopes;
+}
+
+// step 2 of ECMA 13.2.1. rest in FunctionImp::executeCall()
+Completion DeclaredFunctionImp::execute(const List &)
+{
+ /* TODO */
+
+#ifdef KJS_DEBUGGER
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ int oldSourceId = -1;
+ if (dbg) {
+ oldSourceId = dbg->sourceId();
+ dbg->setSourceId(body->sourceId());
+ }
+#endif
+
+ Completion result = body->execute();
+
+#ifdef KJS_DEBUGGER
+ if (dbg) {
+ dbg->setSourceId(oldSourceId);
+ }
+#endif
+
+ if (result.complType() == Throw || result.complType() == ReturnValue)
+ return result;
+ return Completion(Normal, Undefined()); /* TODO: or ReturnValue ? */
+}
+
+// ECMA 13.2.2 [[Construct]]
+Object DeclaredFunctionImp::construct(const List &args)
+{
+ Object obj(ObjectClass);
+ KJSO p = get("prototype");
+ if (p.isObject())
+ obj.setPrototype(p);
+ else
+ obj.setPrototype(Global::current().objectPrototype());
+
+ KJSO res = executeCall(obj.imp(), &args);
+
+ Object v = Object::dynamicCast(res);
+ if (v.isNull())
+ return obj;
+ else
+ return v;
+}
+
+Completion AnonymousFunction::execute(const List &)
+{
+ /* TODO */
+ return Completion(Normal, Null());
+}
+
+// ECMA 10.1.8
+class ArgumentsObject : public ObjectImp {
+public:
+ ArgumentsObject(FunctionImp *func, const List *args);
+};
+
+ArgumentsObject::ArgumentsObject(FunctionImp *func, const List *args)
+ : ObjectImp(UndefClass)
+{
+ put("callee", Function(func), DontEnum);
+ if (args) {
+ put("length", Number(args->size()), DontEnum);
+ ListIterator arg = args->begin();
+ for (int i = 0; arg != args->end(); arg++, i++) {
+ put(UString::from(i), *arg, DontEnum);
+ }
+ }
+}
+
+const TypeInfo ActivationImp::info = { "Activation", ActivationType, 0, 0, 0 };
+
+// ECMA 10.1.6
+ActivationImp::ActivationImp(FunctionImp *f, const List *args)
+{
+ KJSO aobj(new ArgumentsObject(f, args));
+ put("arguments", aobj, DontDelete);
+ /* TODO: this is here to get myFunc.arguments and myFunc.a1 going.
+ I can't see this described in the spec but it's possible in browsers. */
+ if (!f->name().isNull())
+ f->put("arguments", aobj);
+}
+
+ExecutionStack::ExecutionStack()
+ : progNode(0L), firstNode(0L), prev(0)
+{
+}
+
+ExecutionStack* ExecutionStack::push()
+{
+ ExecutionStack *s = new ExecutionStack();
+ s->prev = this;
+
+ return s;
+}
+
+ExecutionStack* ExecutionStack::pop()
+{
+ ExecutionStack *s = prev;
+ delete this;
+
+ return s;
+}
+
+KJScriptImp* KJScriptImp::curr = 0L;
+KJScriptImp* KJScriptImp::hook = 0L;
+int KJScriptImp::instances = 0;
+int KJScriptImp::running = 0;
+
+KJScriptImp::KJScriptImp(KJScript *s)
+ : scr(s),
+ initialized(false),
+ glob(0L),
+#ifdef KJS_DEBUGGER
+ dbg(0L),
+#endif
+ retVal(0L)
+{
+ instances++;
+ KJScriptImp::curr = this;
+ // are we the first interpreter instance ? Initialize some stuff
+ if (instances == 1)
+ globalInit();
+ stack = new ExecutionStack();
+ clearException();
+ lex = new Lexer();
+}
+
+KJScriptImp::~KJScriptImp()
+{
+ KJScriptImp::curr = this;
+
+#ifdef KJS_DEBUGGER
+ attachDebugger(0L);
+#endif
+
+ clear();
+
+ delete lex;
+ lex = 0L;
+
+ delete stack;
+ stack = 0L;
+
+ KJScriptImp::curr = 0L;
+ // are we the last of our kind ? Free global stuff.
+ if (instances == 1)
+ globalClear();
+ instances--;
+}
+
+void KJScriptImp::globalInit()
+{
+ UndefinedImp::staticUndefined = new UndefinedImp();
+ UndefinedImp::staticUndefined->ref();
+ NullImp::staticNull = new NullImp();
+ NullImp::staticNull->ref();
+ BooleanImp::staticTrue = new BooleanImp(true);
+ BooleanImp::staticTrue->ref();
+ BooleanImp::staticFalse = new BooleanImp(false);
+ BooleanImp::staticFalse->ref();
+}
+
+void KJScriptImp::globalClear()
+{
+ UndefinedImp::staticUndefined->deref();
+ UndefinedImp::staticUndefined = 0L;
+ NullImp::staticNull->deref();
+ NullImp::staticNull = 0L;
+ BooleanImp::staticTrue->deref();
+ BooleanImp::staticTrue = 0L;
+ BooleanImp::staticFalse->deref();
+ BooleanImp::staticFalse = 0L;
+}
+
+void KJScriptImp::mark()
+{
+ if (exVal && !exVal->marked())
+ exVal->mark();
+ if (retVal && !retVal->marked())
+ retVal->mark();
+ UndefinedImp::staticUndefined->mark();
+ NullImp::staticNull->mark();
+ BooleanImp::staticTrue->mark();
+ BooleanImp::staticFalse->mark();
+}
+
+void KJScriptImp::init()
+{
+ KJScriptImp::curr = this;
+
+ clearException();
+ retVal = 0L;
+
+ if (!initialized) {
+ // add this interpreter to the global chain
+ // as a root set for garbage collection
+ if (hook) {
+ prev = hook;
+ next = hook->next;
+ hook->next->prev = this;
+ hook->next = this;
+ } else {
+ hook = next = prev = this;
+ }
+
+ glob.init();
+ con = new Context();
+ firstN = 0L;
+ progN = 0L;
+ recursion = 0;
+ errMsg = "";
+ initialized = true;
+#ifdef KJS_DEBUGGER
+ sid = -1;
+#endif
+ }
+}
+
+void KJScriptImp::clear()
+{
+ if ( recursion ) {
+#ifndef NDEBUG
+ fprintf(stderr, "KJS: ignoring clear() while running\n");
+#endif
+ return;
+ }
+ KJScriptImp *old = curr;
+ if (initialized) {
+ KJScriptImp::curr = this;
+
+ Node::setFirstNode(firstNode());
+ Node::deleteAllNodes();
+ setFirstNode(0L);
+ setProgNode(0L);
+
+ clearException();
+ retVal = 0L;
+
+ delete con; con = 0L;
+ glob.clear();
+
+ Collector::collect();
+
+ // remove from global chain (see init())
+ next->prev = prev;
+ prev->next = next;
+ hook = next;
+ if (hook == this)
+ hook = 0L;
+
+#ifdef KJS_DEBUGGER
+ sid = -1;
+#endif
+
+ initialized = false;
+ }
+ if (old != this)
+ KJScriptImp::curr = old;
+}
+
+bool KJScriptImp::evaluate(const UChar *code, unsigned int length, const KJSO &thisV,
+ bool onlyCheckSyntax)
+{
+ init();
+
+#ifdef KJS_DEBUGGER
+ sid++;
+ if (debugger())
+ debugger()->setSourceId(sid);
+#endif
+ if (recursion > 7) {
+ fprintf(stderr, "KJS: breaking out of recursion\n");
+ return true;
+ } else if (recursion > 0) {
+#ifndef NDEBUG
+ fprintf(stderr, "KJS: entering recursion level %d\n", recursion);
+#endif
+ pushStack();
+ }
+
+ assert(Lexer::curr());
+ Lexer::curr()->setCode(code, length);
+ Node::setFirstNode(firstNode());
+ int parseError = kjsyyparse();
+ setFirstNode(Node::firstNode());
+
+ if (parseError) {
+ errType = 99; /* TODO */
+ errLine = Lexer::curr()->lineNo();
+ errMsg = "Parse error at line " + UString::from(errLine);
+#ifndef NDEBUG
+ fprintf(stderr, "JavaScript parse error at line %d.\n", errLine);
+#endif
+ /* TODO: either clear everything or keep previously
+ parsed function definitions */
+ // Node::deleteAllNodes();
+ return false;
+ }
+
+ if (onlyCheckSyntax)
+ return true;
+
+ clearException();
+
+ KJSO oldVar;
+ if (!thisV.isNull()) {
+ context()->setThisValue(thisV);
+ context()->pushScope(thisV);
+ oldVar = context()->variableObject();
+ context()->setVariableObject(thisV);
+ }
+
+ running++;
+ recursion++;
+ assert(progNode());
+ Completion res = progNode()->execute();
+ recursion--;
+ running--;
+
+ if (hadException()) {
+ KJSO err = exception();
+ errType = 99; /* TODO */
+ errLine = err.get("line").toInt32();
+ errMsg = err.get("name").toString().value() + ". ";
+ errMsg += err.get("message").toString().value();
+#ifdef KJS_DEBUGGER
+ if (dbg)
+ dbg->setSourceId(err.get("sid").toInt32());
+#endif
+ clearException();
+ } else {
+ errType = 0;
+ errLine = -1;
+ errMsg = "";
+
+ // catch return value
+ retVal = 0L;
+ if (res.complType() == ReturnValue || !thisV.isNull())
+ retVal = res.value().imp();
+ }
+
+ if (!thisV.isNull()) {
+ context()->popScope();
+ context()->setVariableObject(oldVar);
+ }
+
+ if (progNode())
+ progNode()->deleteGlobalStatements();
+
+ if (recursion > 0) {
+ popStack();
+ }
+
+ return !errType;
+}
+
+void KJScriptImp::pushStack()
+{
+ stack = stack->push();
+}
+
+void KJScriptImp::popStack()
+{
+ stack = stack->pop();
+ assert(stack);
+}
+
+bool KJScriptImp::call(const KJSO &scope, const UString &func, const List &args)
+{
+ init();
+ KJSO callScope(scope);
+ if (callScope.isNull())
+ callScope = Global::current().imp();
+ if (!callScope.hasProperty(func)) {
+#ifndef NDEBUG
+ fprintf(stderr, "couldn't resolve function name %s. call() failed\n",
+ func.ascii());
+#endif
+ return false;
+ }
+ KJSO v = callScope.get(func);
+ if (!v.isA(ConstructorType)) {
+#ifndef NDEBUG
+ fprintf(stderr, "%s is not a function. call() failed.\n", func.ascii());
+#endif
+ return false;
+ }
+ running++;
+ recursion++;
+ static_cast<ConstructorImp*>(v.imp())->executeCall(scope.imp(), &args);
+ recursion--;
+ running--;
+ return !hadException();
+}
+
+bool KJScriptImp::call(const KJSO &func, const KJSO &thisV,
+ const List &args, const List &extraScope)
+{
+ init();
+ if(!func.implementsCall())
+ return false;
+
+ running++;
+ recursion++;
+ retVal = func.executeCall(thisV, &args, &extraScope).imp();
+ recursion--;
+ running--;
+
+ return !hadException();
+}
+
+void KJScriptImp::setException(Imp *e)
+{
+ assert(curr);
+ curr->exVal = e;
+ curr->exMsg = "Exception"; // not very meaningful but we use !0L to test
+}
+
+void KJScriptImp::setException(const char *msg)
+{
+ assert(curr);
+ curr->exVal = 0L; // will be created later on exception()
+ curr->exMsg = msg;
+}
+
+KJSO KJScriptImp::exception()
+{
+ assert(curr);
+ if (!curr->exMsg)
+ return Undefined();
+ if (curr->exVal)
+ return curr->exVal;
+ return Error::create(GeneralError, curr->exMsg);
+}
+
+void KJScriptImp::clearException()
+{
+ assert(curr);
+ curr->exMsg = 0L;
+ curr->exVal = 0L;
+}
+
+#ifdef KJS_DEBUGGER
+void KJScriptImp::attachDebugger(Debugger *d)
+{
+ static bool detaching = false;
+ if (detaching) // break circular detaching
+ return;
+
+ if (dbg) {
+ detaching = true;
+ dbg->detach();
+ detaching = false;
+ }
+
+ dbg = d;
+}
+
+bool KJScriptImp::setBreakpoint(int id, int line, bool set)
+{
+ init();
+ return Node::setBreakpoint(firstNode(), id, line, set);
+}
+
+#endif
+
+bool PropList::contains(const UString &name)
+{
+ PropList *p = this;
+ while (p) {
+ if (name == p->name)
+ return true;
+ p = p->next;
+ }
+ return false;
+}
+
+bool LabelStack::push(const UString &id)
+{
+ if (id.isEmpty() || contains(id))
+ return false;
+
+ StackElm *newtos = new StackElm;
+ newtos->id = id;
+ newtos->prev = tos;
+ tos = newtos;
+ return true;
+}
+
+bool LabelStack::contains(const UString &id) const
+{
+ if (id.isEmpty())
+ return true;
+
+ for (StackElm *curr = tos; curr; curr = curr->prev)
+ if (curr->id == id)
+ return true;
+
+ return false;
+}
+
+void LabelStack::pop()
+{
+ if (tos) {
+ StackElm *prev = tos->prev;
+ delete tos;
+ tos = prev;
+ }
+}
+
+LabelStack::~LabelStack()
+{
+ StackElm *prev;
+
+ while (tos) {
+ prev = tos->prev;
+ delete tos;
+ tos = prev;
+ }
+}
+
+// ECMA 15.3.5.3 [[HasInstance]]
+// see comment in header file
+KJSO KJS::hasInstance(const KJSO &F, const KJSO &V)
+{
+ if (V.isObject()) {
+ KJSO prot = F.get("prototype");
+ if (!prot.isObject())
+ return Error::create(TypeError, "Invalid prototype encountered "
+ "in instanceof operation.");
+ Imp *v = V.imp();
+ while ((v = v->prototype())) {
+ if (v == prot.imp())
+ return Boolean(true);
+ }
+ }
+ return Boolean(false);
+}
+
+#ifndef NDEBUG
+#include <stdio.h>
+void KJS::printInfo( const char *s, const KJSO &o )
+{
+ if (o.isNull())
+ fprintf(stderr, "%s: (null)\n", s);
+ else {
+ KJSO v = o;
+ if (o.isA(ReferenceType))
+ v = o.getValue();
+ fprintf(stderr, "JS: %s: %s : %s (%p)\n",
+ s,
+ v.toString().value().ascii(),
+ v.imp()->typeInfo()->name,
+ (void*)v.imp());
+ if (o.isA(ReferenceType)) {
+ fprintf(stderr, "JS: Was property '%s'\n", o.getPropertyName().ascii());
+ printInfo("of", o.getBase());
+ }
+ }
+}
+#endif
diff --git a/WebCore/src/kdelibs/kjs/internal.h b/WebCore/src/kdelibs/kjs/internal.h
new file mode 100644
index 0000000..51a8ece
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/internal.h
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _INTERNAL_H_
+#define _INTERNAL_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kjs.h"
+#include "object.h"
+#include "function.h"
+
+#define I18N_NOOP(s) s
+
+namespace KJS {
+
+ class Boolean;
+ class Number;
+ class String;
+ class Object;
+ class RegExp;
+ class Node;
+ class FunctionBodyNode;
+ class ProgramNode;
+#ifdef KJS_DEBUGGER
+ class Debugger;
+#endif
+
+ class UndefinedImp : public Imp {
+ public:
+ UndefinedImp();
+ virtual ~UndefinedImp() { }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static UndefinedImp *staticUndefined;
+ };
+
+ class NullImp : public Imp {
+ public:
+ NullImp();
+ virtual ~NullImp() { }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static NullImp *staticNull;
+ };
+
+ class BooleanImp : public Imp {
+ public:
+ virtual ~BooleanImp() { }
+ BooleanImp(bool v = false) : val(v) { }
+ bool value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+
+ static BooleanImp *staticTrue, *staticFalse;
+ private:
+ bool val;
+ };
+
+ class NumberImp : public Imp {
+ public:
+ NumberImp(double v);
+ virtual ~NumberImp() { }
+ double value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ double val;
+ };
+
+ class StringImp : public Imp {
+ public:
+ StringImp(const UString& v);
+ virtual ~StringImp() { }
+ UString value() const { return val; }
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ UString val;
+ };
+
+ class ReferenceImp : public Imp {
+ public:
+ ReferenceImp(const KJSO& b, const UString& p);
+ virtual ~ReferenceImp() { }
+ virtual void mark(Imp*);
+ KJSO getBase() const { return base; }
+ UString getPropertyName() const { return prop; }
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ KJSO base;
+ UString prop;
+ };
+
+ class CompletionImp : public Imp {
+ public:
+ CompletionImp(Compl c, const KJSO& v, const UString& t);
+ virtual ~CompletionImp() { }
+ virtual void mark(Imp*);
+ Compl completion() const { return comp; }
+ KJSO value() const { return val; }
+ UString target() const { return tar; }
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ private:
+ Compl comp;
+ KJSO val;
+ UString tar;
+ };
+
+ class RegExpImp : public ObjectImp {
+ public:
+ RegExpImp();
+ ~RegExpImp();
+ void setRegExp(RegExp *r) { reg = r; }
+ RegExp* regExp() const { return reg; }
+ private:
+ RegExp *reg;
+ };
+
+ class StatementNode;
+ class UString;
+
+ class Reference : public KJSO {
+ public:
+ Reference(const KJSO& b, const UString &p);
+ virtual ~Reference();
+ };
+
+ /**
+ * @short The "label set" in Ecma-262 spec
+ */
+ class LabelStack {
+ public:
+ LabelStack(): tos(0L) {}
+ ~LabelStack();
+
+ /**
+ * If id is not empty and is not in the stack already, puts it on top of
+ * the stack and returns true, otherwise returns false
+ */
+ bool push(const UString &id);
+ /**
+ * Is the id in the stack?
+ */
+ bool contains(const UString &id) const;
+ /**
+ * Removes from the stack the last pushed id (what else?)
+ */
+ void pop();
+ private:
+ struct StackElm {
+ UString id;
+ StackElm *prev;
+ };
+
+ StackElm *tos;
+ };
+
+ /**
+ * @short Execution context.
+ */
+ class Context {
+ public:
+ Context(CodeType type = GlobalCode, Context *callingContext = 0L,
+ FunctionImp *func = 0L, const List *args = 0L, Imp *thisV = 0L);
+ virtual ~Context();
+ static Context *current();
+ static void setCurrent(Context *c);
+ const List *pScopeChain() const { return scopeChain; }
+ void pushScope(const KJSO &s);
+ void popScope();
+ List *copyOfChain();
+ KJSO variableObject() const { return variable; }
+ void setVariableObject( const KJSO &obj ) { variable = obj; }
+ KJSO thisValue() const { return thisVal; }
+ void setThisValue(const KJSO &t) { thisVal = t; }
+ LabelStack *seenLabels() { return &ls; }
+ private:
+ LabelStack ls;
+ KJSO thisVal;
+ KJSO activation;
+ KJSO variable;
+ List *scopeChain;
+ };
+
+ class DeclaredFunctionImp : public ConstructorImp {
+ public:
+ DeclaredFunctionImp(const UString &n, FunctionBodyNode *b,
+ const List *sc);
+ ~DeclaredFunctionImp();
+ Completion execute(const List &);
+ Object construct(const List &);
+ CodeType codeType() const { return FunctionCode; }
+ List *scopeChain() const { return scopes; }
+ private:
+ FunctionBodyNode *body;
+ List *scopes;
+ };
+
+ class AnonymousFunction : public Function {
+ public:
+ AnonymousFunction();
+ Completion execute(const List &);
+ CodeType codeType() const { return AnonymousCode; }
+ };
+
+ class ActivationImp : public Imp {
+ public:
+ ActivationImp(FunctionImp *f, const List *args);
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ };
+
+ class ExecutionStack {
+ public:
+ ExecutionStack();
+ ExecutionStack *push();
+ ExecutionStack *pop();
+
+ ProgramNode *progNode;
+ Node *firstNode;
+ private:
+ ExecutionStack *prev;
+ };
+
+ class KJScriptImp {
+ friend class ::KJScript;
+ friend class Lexer;
+ friend class Context;
+ friend class Global;
+ friend class Collector;
+ public:
+ KJScriptImp(KJScript *s);
+ ~KJScriptImp();
+ void mark();
+ static KJScriptImp *current() { return curr; }
+ static void setException(Imp *e);
+ static void setException(const char *msg);
+ static bool hadException();
+ static KJSO exception();
+ static void clearException();
+
+ Context *context() const { return con; }
+ void setContext(Context *c) { con = c; }
+
+#ifdef KJS_DEBUGGER
+ /**
+ * Attach debugger d to this engine. If there already was another instance
+ * attached it will be detached.
+ */
+ void attachDebugger(Debugger *d);
+ Debugger *debugger() const { return dbg; }
+ int sourceId() const { return sid; }
+ bool setBreakpoint(int id, int line, bool set);
+#endif
+ private:
+ /**
+ * Initialize global object and context. For internal use only.
+ */
+ void init();
+ void clear();
+ /**
+ * Called when the first interpreter is instanciated. Initializes
+ * global pointers.
+ */
+ void globalInit();
+ /**
+ * Called when the last interpreter instance is destroyed. Frees
+ * globally allocated memory.
+ */
+ void globalClear();
+ bool evaluate(const UChar *code, unsigned int length, const KJSO &thisV = KJSO(),
+ bool onlyCheckSyntax = false);
+ bool call(const KJSO &scope, const UString &func, const List &args);
+ bool call(const KJSO &func, const KJSO &thisV,
+ const List &args, const List &extraScope);
+
+ public:
+ ProgramNode *progNode() const { return stack->progNode; }
+ void setProgNode(ProgramNode *p) { stack->progNode = p; }
+ Node *firstNode() const { return stack->firstNode; }
+ void setFirstNode(Node *n) { stack->firstNode = n; }
+ void pushStack();
+ void popStack();
+ KJScriptImp *next, *prev;
+ KJScript *scr;
+ ExecutionStack *stack;
+
+ private:
+ ProgramNode *progN;
+ Node *firstN;
+
+ static KJScriptImp *curr, *hook;
+ static int instances; // total number of instances
+ static int running; // total number running
+ bool initialized;
+ Lexer *lex;
+ Context *con;
+ Global glob;
+ int errType, errLine;
+ UString errMsg;
+#ifdef KJS_DEBUGGER
+ Debugger *dbg;
+ int sid;
+#endif
+ const char *exMsg;
+ Imp *exVal;
+ Imp *retVal;
+ int recursion;
+ };
+
+ inline bool KJScriptImp::hadException()
+ {
+ assert(curr);
+ return curr->exMsg;
+ }
+
+ /**
+ * @short Struct used to return the property names of an object
+ */
+ class PropList {
+ public:
+ PropList(UString nm = UString::null, PropList *nx = 0) :
+ name(nm), next(nx) {};
+ ~PropList() {
+ if(next) delete next;
+ }
+ /**
+ * The property name
+ */
+ UString name;
+ /**
+ * The next property
+ */
+ PropList *next;
+ bool contains(const UString &name);
+ };
+
+ /* TODO just temporary until functions are objects and this becomes
+ a member function. Called by RelationNode for 'instanceof' operator. */
+ KJSO hasInstance(const KJSO &F, const KJSO &V);
+
+// #define KJS_VERBOSE
+#ifndef NDEBUG
+ void printInfo( const char *s, const KJSO &o );
+#endif
+
+}; // namespace
+
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/keywords.table b/WebCore/src/kdelibs/kjs/keywords.table
new file mode 100644
index 0000000..391aa34
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/keywords.table
@@ -0,0 +1,66 @@
+# main keywords
+@begin mainTable 41
+# types
+null NULLTOKEN
+true TRUETOKEN
+false FALSETOKEN
+# keywords
+break BREAK
+case CASE
+catch CATCH
+default DEFAULT
+finally FINALLY
+for FOR
+instanceof INSTANCEOF
+new NEW
+var VAR
+continue CONTINUE
+function FUNCTION
+return RETURN
+void VOID
+delete DELETE
+if IF
+this THIS
+do DO
+while WHILE
+else ELSE
+in IN
+switch SWITCH
+throw THROW
+try TRY
+typeof TYPEOF
+with WITH
+# reserved for future use
+abstract RESERVED
+boolean RESERVED
+byte RESERVED
+char RESERVED
+class RESERVED
+const RESERVED
+debugger RESERVED
+double RESERVED
+enum RESERVED
+export RESERVED
+extends RESERVED
+final RESERVED
+float RESERVED
+goto RESERVED
+implements RESERVED
+import RESERVED
+int RESERVED
+interface RESERVED
+long RESERVED
+native RESERVED
+package RESERVED
+private RESERVED
+protected RESERVED
+public RESERVED
+short RESERVED
+static RESERVED
+super RESERVED
+synchronized RESERVED
+throws RESERVED
+transient RESERVED
+volatile RESERVED
+@end
+
diff --git a/WebCore/src/kdelibs/kjs/kjs.cpp b/WebCore/src/kdelibs/kjs/kjs.cpp
new file mode 100644
index 0000000..d6c0260
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/kjs.cpp
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "collector.h"
+
+using namespace KJS;
+
+KJScript::KJScript()
+{
+ rep = new KJScriptImp(this);
+ rep->init();
+}
+
+KJScript::~KJScript()
+{
+ delete rep;
+
+#ifdef KJS_DEBUG_MEM
+ //printf("Imp::count: %d\n", Imp::count);
+ // assert(Imp::count == 0);
+#endif
+}
+
+void KJScript::init()
+{
+ rep->init();
+}
+
+Imp *KJScript::globalObject() const
+{
+ return rep->glob.imp();
+}
+
+void KJScript::setCurrent( KJScript *newCurr )
+{
+ KJScriptImp::curr = newCurr ? newCurr->rep : 0L;
+}
+
+KJScript *KJScript::current()
+{
+ return KJScriptImp::current() ? KJScriptImp::current()->scr : 0L;
+}
+
+int KJScript::recursion() const
+{
+ return rep->recursion;
+}
+
+bool KJScript::evaluate(const char *code)
+{
+ return rep->evaluate(UString(code).data(), strlen(code));
+}
+
+bool KJScript::evaluate(const UString &code)
+{
+ return rep->evaluate(code.data(), code.size());
+}
+
+bool KJScript::evaluate(const KJSO &thisV,
+ const QChar *code, unsigned int length)
+{
+ return rep->evaluate((UChar*)code, length, thisV);
+}
+
+bool KJScript::call(const KJS::UString &func, const List &args)
+{
+ return rep->call(0, func, args);
+}
+
+bool KJScript::call(const KJSO &scope, const KJS::UString &func,
+ const KJS::List &args)
+{
+ return rep->call(scope.imp(), func, args);
+}
+
+bool KJScript::call(const KJS::KJSO &func, const KJSO &thisV,
+ const KJS::List &args, const KJS::List &extraScope)
+{
+ return rep->call(func, thisV, args, extraScope);
+}
+
+void KJScript::clear()
+{
+ rep->clear();
+}
+
+Imp *KJScript::returnValue() const
+{
+ return rep->retVal;
+}
+
+int KJScript::errorType() const
+{
+ return rep->errType;
+}
+
+int KJScript::errorLine() const
+{
+ return rep->errLine;
+}
+
+const char* KJScript::errorMsg() const
+{
+ return rep->errMsg.ascii();
+}
+
+bool KJScript::checkSyntax(const KJS::UString &code )
+{
+ return rep->evaluate(code.data(), code.size(), 0, true);
+}
+
+/**
+ * @short Print to stderr for debugging purposes.
+ */
+namespace KJS {
+ class DebugPrint : public InternalFunctionImp {
+ public:
+ Completion execute(const List &args)
+ {
+ KJSO v = args[0];
+ String s = v.toString();
+ fprintf(stderr, "---> %s\n", s.value().cstring().c_str());
+
+ return Completion(Normal);
+ }
+ };
+};
+
+void KJScript::enableDebug()
+{
+ rep->init();
+ Global::current().put("debug", Function(new DebugPrint()));
+}
diff --git a/WebCore/src/kdelibs/kjs/kjs.h b/WebCore/src/kdelibs/kjs/kjs.h
new file mode 100644
index 0000000..42a866d
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/kjs.h
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_H_
+#define _KJS_H_
+
+class QChar;
+
+namespace KJS {
+ class UString;
+ class Lexer;
+ class Context;
+ class Global;
+ class KJSO;
+ class Object;
+ class Imp;
+ class List;
+ class KJScriptImp;
+#ifdef KJS_DEBUGGER
+ class Debugger;
+#endif
+};
+
+/**
+ * @libdoc ECMAScript interpreter
+ *
+ * This library provides an interpreter for ECMAScript aka JavaScript.
+ * It currently aims at compliance with Edition 3 of the standard.
+ */
+
+/**
+ * @short ECMAScript interpreter
+ */
+class KJScript {
+ friend class KJS::KJScriptImp;
+ friend class KJS::KJSO;
+ friend class KJS::Context;
+ friend class KJS::Lexer;
+ friend class KJS::Global;
+public:
+ /**
+ * Create a new ECMAScript interpreter. You can later ask it to interprete
+ * code by passing it via @ref #evaluate.
+ */
+ KJScript();
+ /**
+ * Destructor
+ */
+ ~KJScript();
+ /**
+ * Force a "context switch". You usually do not need to do that,
+ * evaluate() does it too.
+ */
+ void init();
+ /**
+ * Returns a pointer to the Global object.
+ */
+ KJS::Imp *globalObject() const;
+ /**
+ * Don't use. May disappear.
+ */
+ static KJScript *current();
+ /**
+ * Don't use. May disappear.
+ */
+ static void setCurrent( KJScript *newCurr );
+
+ /**
+ * Current level of recursive calls to this interpreter. 0 initially.
+ */
+ int recursion() const;
+ /**
+ * Asks the interpreter to evaluate a piece of code. If called more than
+ * once the state (global variables, functions etc.) will be preserved
+ * between each call.
+ * @param code is a string containing the code to be executed.
+ * @return True if the code was evaluated successfully, false if an error
+ * occured.
+ */
+ bool evaluate(const char *code);
+ /**
+ * Same as above. Only differing in the arguments accepted.
+ * @param code is a pointer to an Unicode string containing the code to
+ * be executed.
+ * @param length number of characters.
+ */
+ bool evaluate(const KJS::KJSO &thisV,
+ const QChar *code, unsigned int length);
+ /**
+ * Added for convenience in case you have the code in available in
+ * internal representation already.
+ * @param code is an Unicode string containing the code to be executed.
+ */
+ bool evaluate(const KJS::UString &code);
+ /**
+ * Call the specified function directly, optionally passing args as a
+ * list of arguments. Return value and treatment of errors is analog
+ * to the evaluate() calls.
+ */
+ bool call(const KJS::UString &func, const KJS::List &args);
+ bool call(const KJS::KJSO &scope, const KJS::UString &func,
+ const KJS::List &args);
+ bool call(const KJS::KJSO &func, const KJS::KJSO &thisV,
+ const KJS::List &args, const KJS::List &extraScope );
+ /**
+ * Clear the interpreter's memory. Otherwise, function declarations
+ * and global variables will be remembered after each invokation of
+ * @ref KJScript::evaluate.
+ */
+ void clear();
+ /**
+ * @return Return value from the last call to @ref evaluate(). Null if there
+ * hasn't been any.
+ */
+ KJS::Imp *returnValue() const;
+ /**
+ * @return Return code from last call to @ref evaluate(). 0 on success.
+ */
+ int errorType() const;
+ /**
+ * @return Return line of last error. -1 if last call didn't have an error.
+ */
+ int errorLine() const;
+ /**
+ * @return Error message from last call to @ref evaluate(). Empty string
+ * if no error occured.
+ */
+ const char *errorMsg() const;
+ /**
+ * Check the syntax of a piece of code. Return true if the code could be
+ * parsed without errors, false otherwise. @ref errorLine() will tell you
+ * approximately where the syntax error happened.
+ */
+ bool checkSyntax(const KJS::UString &code);
+ /**
+ * Adds a debug() function to the set of pre-defined properties.
+ * debug(arg) tries to convert 'arg' to a string and prints the result
+ * to stderr. If you want to debug self defined Host Objects this way
+ * you should provide them with a toString() method that returns a string.
+ */
+ void enableDebug();
+private:
+ KJS::KJScriptImp *rep;
+ // not implemented
+ KJScript(const KJScript&);
+ KJScript operator=(const KJScript&);
+
+#ifdef KJS_DEBUGGER
+ friend class KJS::Debugger;
+#endif
+};
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/lexer.cpp b/WebCore/src/kdelibs/kjs/lexer.cpp
new file mode 100644
index 0000000..7ce1a3d
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/lexer.cpp
@@ -0,0 +1,744 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "kjs.h"
+#include "nodes.h"
+#include "lexer.h"
+#include "ustring.h"
+#include "lookup.h"
+#include "internal.h"
+
+// we can't specify the namespace in yacc's C output, so do it here
+using namespace KJS;
+
+#ifndef KDE_USE_FINAL
+#include "grammar.h"
+#endif
+
+#include "lexer.lut.h"
+
+#ifdef KJS_DEBUGGER
+extern YYLTYPE yylloc; // global bison variable holding token info
+#endif
+
+// a bridge for yacc from the C world to C++
+int kjsyylex()
+{
+ return Lexer::curr()->lex();
+}
+
+Lexer::Lexer()
+ : yylineno(0),
+ size8(128), size16(128), restrKeyword(false),
+ stackToken(-1), pos(0),
+ code(0), length(0),
+#ifndef KJS_PURE_ECMA
+ bol(true),
+#endif
+ current(0), next1(0), next2(0), next3(0)
+{
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new UChar[size16];
+
+}
+
+Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+Lexer *Lexer::curr()
+{
+ assert(KJScriptImp::current());
+ return KJScriptImp::current()->lex;
+}
+
+void Lexer::setCode(const UChar *c, unsigned int len)
+{
+ yylineno = 0;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c;
+ length = len;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void Lexer::shift(unsigned int p)
+{
+ while (p--) {
+ pos++;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ unsigned short stringType = 0; // either single or double quotes
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = 0;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ if (!terminator && !delimited) {
+ // automatic semicolon insertion if program incomplete
+ token = ';';
+ stackToken = 0;
+ setDone(Other);
+ } else
+ setDone(Eof);
+ } else if (isLineTerminator()) {
+ yylineno++;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+ terminator = true;
+ if (restrKeyword) {
+ token = ';';
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ state = InString;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ record8(current);
+ state = InDecimal;
+#ifndef KJS_PURE_ECMA
+ // <!-- marks the beginning of a line comment (for www usage)
+ } else if (bol && current == '<' && next1 == '!' &&
+ next2 == '-' && next3 == '-') {
+ shift(3);
+ state = InSingleLineComment;
+ // same of -->
+ } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
+ shift(2);
+ state = InSingleLineComment;
+#endif
+ } else {
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ setDone(Other);
+ } else {
+ // cerr << "encountered unknown character" << endl;
+ setDone(Bad);
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) && isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ record16(singleEscape(current));
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(convertHex(current, next1));
+ shift(1);
+ } else if (current == stringType) {
+ record16('x');
+ shift(1);
+ setDone(String);
+ } else {
+ record16('x');
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16('u');
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ yylineno++;
+ terminator = true;
+#ifndef KJS_PURE_ECMA
+ bol = true;
+#endif
+ if (restrKeyword) {
+ token = ';';
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ } else if (isLineTerminator()) {
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Hex);
+ }
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else
+ setDone(Octal);
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else
+ setDone(Bad);
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else
+ setDone(Number);
+ break;
+ default:
+ assert(!"Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+#ifndef KJS_PURE_ECMA
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+#endif
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current))
+ state = Bad;
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+#ifdef KJS_DEBUG_LEX
+ fprintf(stderr, "line: %d ", lineNo());
+ fprintf(stderr, "yytext (%x): ", buffer8[0]);
+ fprintf(stderr, "%s ", buffer8);
+#endif
+
+ double dval = 0;
+ if (state == Number) {
+ dval = strtod(buffer8, 0L);
+ } else if (state == Hex) { // scan hex numbers
+ // TODO: support long unsigned int
+ unsigned int i;
+ sscanf(buffer8, "%x", &i);
+ dval = i;
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ unsigned int ui;
+ sscanf(buffer8, "%o", &ui);
+ dval = ui;
+ state = Number;
+ }
+
+#ifdef KJS_DEBUG_LEX
+ switch (state) {
+ case Eof:
+ printf("(EOF)\n");
+ break;
+ case Other:
+ printf("(Other)\n");
+ break;
+ case Identifier:
+ printf("(Identifier)/(Keyword)\n");
+ break;
+ case String:
+ printf("(String)\n");
+ break;
+ case Number:
+ printf("(Number)\n");
+ break;
+ default:
+ printf("(unknown)");
+ }
+#endif
+
+ restrKeyword = false;
+ delimited = false;
+#ifdef KJS_DEBUGGER
+ yylloc.first_line = yylineno; // ???
+ yylloc.last_line = yylineno;
+#endif
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if(token == '}' || token == ';') {
+ delimited = true;
+ }
+ return token;
+ case Identifier:
+ if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ kjsyylval.ustr = new UString(buffer16, pos16);
+ return IDENT;
+ }
+ if (token == CONTINUE || token == BREAK ||
+ token == RETURN || token == THROW)
+ restrKeyword = true;
+ return token;
+ case String:
+ kjsyylval.ustr = new UString(buffer16, pos16); return STRING;
+ case Number:
+ kjsyylval.dval = dval;
+ return NUMBER;
+ case Bad:
+ fprintf(stderr, "yylex: ERROR.\n");
+ return -1;
+ default:
+ assert(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool Lexer::isIdentLetter(unsigned short c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return (c >= 'a' && c <= 'z' ||
+ c >= 'A' && c <= 'Z' ||
+ c == '$' || c == '_');
+}
+
+bool Lexer::isDecimalDigit(unsigned short c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool Lexer::isHexDigit(unsigned short c) const
+{
+ return (c >= '0' && c <= '9' ||
+ c >= 'a' && c <= 'f' ||
+ c >= 'A' && c <= 'F');
+}
+
+bool Lexer::isOctalDigit(unsigned short c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int Lexer::matchPunctuator(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return URSHIFTEQUAL;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STREQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STRNEQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return URSHIFT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return LSHIFTEQUAL;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return RSHIFTEQUAL;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return NE;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ if (terminator) {
+ // automatic semicolon insertion
+ stackToken = PLUSPLUS;
+ return AUTO;
+ } else
+ return PLUSPLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ if (terminator) {
+ // automatic semicolon insertion
+ stackToken = MINUSMINUS;
+ return AUTO;
+ } else
+ return MINUSMINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return EQEQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return PLUSEQUAL;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return MINUSEQUAL;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return MULTEQUAL;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return DIVEQUAL;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return ANDEQUAL;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return XOREQUAL;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return MODEQUAL;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return OREQUAL;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return LSHIFT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return RSHIFT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return OR;
+ }
+
+ switch(c1) {
+ case '=':
+ case '>':
+ case '<':
+ case ',':
+ case '!':
+ case '~':
+ case '?':
+ case ':':
+ case '.':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '&':
+ case '|':
+ case '^':
+ case '%':
+ case '(':
+ case ')':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case ';':
+ shift(1);
+ return static_cast<int>(c1);
+ default:
+ return -1;
+ }
+}
+
+unsigned short Lexer::singleEscape(unsigned short c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+unsigned short Lexer::convertOctal(unsigned short c1, unsigned short c2,
+ unsigned short c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(unsigned short c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(unsigned short c1, unsigned short c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+UChar Lexer::convertUnicode(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4)
+{
+ return UChar((convertHex(c1) << 4) + convertHex(c2),
+ (convertHex(c3) << 4) + convertHex(c4));
+}
+
+void Lexer::record8(unsigned short c)
+{
+ assert(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void Lexer::record16(UChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ UChar *tmp = new UChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(UChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+bool Lexer::scanRegExp()
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ while (1) {
+ if (isLineTerminator() || current == 0)
+ return false;
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape =
+ !lastWasEscape && (current == '\\');
+ }
+ else {
+ pattern = UString(buffer16, pos16);
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ while (isIdentLetter(current)) {
+ record16(current);
+ shift(1);
+ }
+ flags = UString(buffer16, pos16);
+
+ return true;
+}
diff --git a/WebCore/src/kdelibs/kjs/lexer.h b/WebCore/src/kdelibs/kjs/lexer.h
new file mode 100644
index 0000000..0acc130
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/lexer.h
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJSLEXER_H_
+#define _KJSLEXER_H_
+
+#include "ustring.h"
+
+namespace KJS {
+
+ class RegExp;
+
+ class Lexer {
+ public:
+ Lexer();
+ ~Lexer();
+ static Lexer *curr();
+
+ void setCode(const UChar *c, unsigned int len);
+ int lex();
+
+ int lineNo() const { return yylineno + 1; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ bool scanRegExp();
+ UString pattern, flags;
+
+ private:
+ int yylineno;
+ bool done;
+ char *buffer8;
+ UChar *buffer16;
+ unsigned int size8, size16;
+ unsigned int pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ unsigned int pos;
+ void shift(unsigned int p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(unsigned short c) const;
+ bool isOctalDigit(unsigned short c) const;
+
+ int matchPunctuator(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4);
+ unsigned short singleEscape(unsigned short c) const;
+ unsigned short convertOctal(unsigned short c1, unsigned short c2,
+ unsigned short c3) const;
+ public:
+ static unsigned char convertHex(unsigned short c1);
+ static unsigned char convertHex(unsigned short c1, unsigned short c2);
+ static UChar convertUnicode(unsigned short c1, unsigned short c2,
+ unsigned short c3, unsigned short c4);
+ static bool isIdentLetter(unsigned short c);
+ static bool isDecimalDigit(unsigned short c);
+
+ private:
+
+ void record8(unsigned short c);
+ void record16(UChar c);
+
+ const UChar *code;
+ unsigned int length;
+ int yycolumn;
+#ifndef KJS_PURE_ECMA
+ int bol; // begin of line
+#endif
+
+ // current and following unicode characters
+ unsigned short current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ // for future extensions
+ class LexerPrivate;
+ LexerPrivate *priv;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/lexer.lut.h b/WebCore/src/kdelibs/kjs/lexer.lut.h
new file mode 100644
index 0000000..2ddc9d8
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/lexer.lut.h
@@ -0,0 +1,77 @@
+/* automatically generated from keywords.table. DO NOT EDIT ! */
+
+namespace KJS {
+
+const struct HashEntry2 mainTableEntries[] = {
+ { "instanceof", INSTANCEOF, 0, &mainTableEntries[63] },
+ { "var", VAR, 0, &mainTableEntries[47] },
+ { "case", CASE, 0, &mainTableEntries[41] },
+ { "default", DEFAULT, 0, &mainTableEntries[54] },
+ { "while", WHILE, 0, &mainTableEntries[46] },
+ { 0, 0, 0, 0 },
+ { "do", DO, 0, 0 },
+ { "typeof", TYPEOF, 0, 0 },
+ { "continue", CONTINUE, 0, 0 },
+ { "function", FUNCTION, 0, 0 },
+ { "in", IN, 0, 0 },
+ { "import", RESERVED, 0, 0 },
+ { "delete", DELETE, 0, 0 },
+ { "finally", FINALLY, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "else", ELSE, 0, 0 },
+ { "return", RETURN, 0, 0 },
+ { "debugger", RESERVED, 0, 0 },
+ { "const", RESERVED, 0, &mainTableEntries[48] },
+ { "package", RESERVED, 0, 0 },
+ { "double", RESERVED, 0, &mainTableEntries[53] },
+ { 0, 0, 0, 0 },
+ { "long", RESERVED, 0, 0 },
+ { "catch", CATCH, 0, &mainTableEntries[45] },
+ { "void", VOID, 0, &mainTableEntries[59] },
+ { "break", BREAK, 0, &mainTableEntries[49] },
+ { "byte", RESERVED, 0, &mainTableEntries[62] },
+ { "enum", RESERVED, 0, &mainTableEntries[58] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "this", THIS, 0, &mainTableEntries[50] },
+ { "false", FALSETOKEN, 0, &mainTableEntries[44] },
+ { "abstract", RESERVED, 0, &mainTableEntries[56] },
+ { "null", NULLTOKEN, 0, &mainTableEntries[61] },
+ { "with", WITH, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "true", TRUETOKEN, 0, 0 },
+ { "boolean", RESERVED, 0, 0 },
+ { "for", FOR, 0, 0 },
+ { "new", NEW, 0, &mainTableEntries[42] },
+ { "if", IF, 0, &mainTableEntries[43] },
+ { "switch", SWITCH, 0, &mainTableEntries[55] },
+ { "throw", THROW, 0, &mainTableEntries[52] },
+ { "try", TRY, 0, &mainTableEntries[64] },
+ { "char", RESERVED, 0, 0 },
+ { "class", RESERVED, 0, &mainTableEntries[51] },
+ { "export", RESERVED, 0, 0 },
+ { "extends", RESERVED, 0, &mainTableEntries[57] },
+ { "final", RESERVED, 0, 0 },
+ { "float", RESERVED, 0, 0 },
+ { "goto", RESERVED, 0, 0 },
+ { "implements", RESERVED, 0, 0 },
+ { "int", RESERVED, 0, &mainTableEntries[66] },
+ { "interface", RESERVED, 0, 0 },
+ { "native", RESERVED, 0, 0 },
+ { "private", RESERVED, 0, 0 },
+ { "protected", RESERVED, 0, &mainTableEntries[60] },
+ { "public", RESERVED, 0, 0 },
+ { "short", RESERVED, 0, 0 },
+ { "static", RESERVED, 0, 0 },
+ { "super", RESERVED, 0, 0 },
+ { "synchronized", RESERVED, 0, &mainTableEntries[65] },
+ { "throws", RESERVED, 0, 0 },
+ { "transient", RESERVED, 0, 0 },
+ { "volatile", RESERVED, 0, 0 }
+};
+
+const struct HashTable2 mainTable = { 2, 67, mainTableEntries, 41 };
+
+}; // namespace
diff --git a/WebCore/src/kdelibs/kjs/lookup.cpp b/WebCore/src/kdelibs/kjs/lookup.cpp
new file mode 100644
index 0000000..fcd3055
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/lookup.cpp
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lookup.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+using namespace KJS;
+
+int Lookup::find(const struct HashTable *table,
+ const UChar *c, unsigned int len)
+{
+ // we only know about version 1 so far
+ if (table->type != 1) {
+ fprintf(stderr, "Unknown hash table version.\n");
+ return -1;
+ }
+
+ int h = hash(c, len) % table->hashSize;
+ const HashEntry *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->c)
+ return -1;
+
+ do {
+ // compare strings
+#ifdef KJS_SWAPPED_CHAR
+ /* TODO: not exactly as optimized as the other version ... */
+ if (len == e->len) {
+ const UChar *u = (const UChar*)e->c;
+ const UChar *c2 = c;
+ unsigned int i;
+ for (i = 0; i < len; i++, u++, c2++)
+ if (!(*c2 == UChar(u->low(), u->high()))) // reverse byte order
+ goto next;
+ return e->value;
+ }
+next:
+#else
+ if ((len == e->len) && (memcmp(c, e->c, len * sizeof(UChar)) == 0))
+ return e->value;
+#endif
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ return -1;
+}
+
+int Lookup::find(const struct HashTable *table, const UString &s)
+{
+ return find(table, s.data(), s.size());
+}
+
+int Lookup::find(const struct HashTable2 *table,
+ const UChar *c, unsigned int len)
+{
+ if (table->type != 2) {
+ fprintf(stderr, "Unknown hash table version.\n");
+ return -1;
+ }
+
+ char *ascii = new char[len+1];
+ unsigned int i;
+ for(i = 0; i < len; i++, c++) {
+ if (!c->high())
+ ascii[i] = c->low();
+ else
+ break;
+ }
+ ascii[i] = '\0';
+
+ int h = hash(ascii) % table->hashSize;
+ const HashEntry2 *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->s) {
+ delete [] ascii;
+ return -1;
+ }
+
+ do {
+ // compare strings
+ if (strcmp(ascii, e->s) == 0) {
+ delete [] ascii;
+ return e->value;
+ }
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ delete [] ascii;
+ return -1;
+}
+
+int Lookup::find(const struct HashTable2 *table, const UString &s)
+{
+ return find(table, s.data(), s.size());
+}
+
+unsigned int Lookup::hash(const UChar *c, unsigned int len)
+{
+ unsigned int val = 0;
+ // ignoring higher byte
+ for (unsigned int i = 0; i < len; i++, c++)
+ val += c->low();
+
+ return val;
+}
+
+unsigned int Lookup::hash(const UString &key)
+{
+ return hash(key.data(), key.size());
+}
+
+unsigned int Lookup::hash(const char *s)
+{
+ unsigned int val = 0;
+ while (*s)
+ val += *s++;
+
+ return val;
+}
diff --git a/WebCore/src/kdelibs/kjs/lookup.h b/WebCore/src/kdelibs/kjs/lookup.h
new file mode 100644
index 0000000..9301ad6
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/lookup.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJSLOOKUP_H_
+#define _KJSLOOKUP_H_
+
+#include "ustring.h"
+
+namespace KJS {
+
+#if 1 // obsolete version 1
+ struct HashEntry {
+ unsigned int len;
+ const void *c; // unicode data
+ int value;
+ const HashEntry *next;
+ };
+
+ struct HashTable {
+ int type;
+ int size;
+ const HashEntry *entries;
+ int hashSize;
+ };
+#endif
+
+ // version 2
+ struct HashEntry2 {
+ const char *s;
+ int value;
+ int attr;
+ const HashEntry2 *next;
+ };
+
+ struct HashTable2 {
+ int type;
+ int size;
+ const HashEntry2 *entries;
+ int hashSize;
+ };
+
+ /**
+ * @short Fast keyword lookup.
+ */
+ class Lookup {
+ public:
+#if 1 // obsolete
+ static int find(const struct HashTable *table, const UString &s);
+ static int find(const struct HashTable *table,
+ const UChar *c, unsigned int len);
+#endif
+ static int find(const struct HashTable2 *table, const UString &s);
+ static int find(const struct HashTable2 *table,
+ const UChar *c, unsigned int len);
+ static unsigned int hash(const UChar *c, unsigned int len);
+ static unsigned int hash(const UString &key);
+ static unsigned int hash(const char *s);
+ private:
+ HashTable *table;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/math_object.cpp b/WebCore/src/kdelibs/kjs/math_object.cpp
new file mode 100644
index 0000000..c9ebb79
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/math_object.cpp
@@ -0,0 +1,163 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "operations.h"
+#include "math_object.h"
+#include "lookup.h"
+
+#include "math_object.lut.h"
+
+using namespace KJS;
+
+KJSO Math::get(const UString &p) const
+{
+ int token = Lookup::find(&mathTable, p);
+
+ if (token < 0)
+ return Imp::get(p);
+
+ double d;
+ int len = 1;
+ switch (token) {
+ case Math::Euler:
+ d = exp(1.0);
+ break;
+ case Math::Ln2:
+ d = log(2.0);
+ break;
+ case Math::Ln10:
+ d = log(10.0);
+ break;
+ case Math::Log2E:
+ d = 1.0/log(2.0);
+ break;
+ case Math::Log10E:
+ d = 1.0/log(10.0);
+ break;
+ case Math::Pi:
+ d = 2.0 * asin(1.0);
+ break;
+ case Math::Sqrt1_2:
+ d = sqrt(0.5);
+ break;
+ case Math::Sqrt2:
+ d = sqrt(2.0);
+ break;
+ default:
+ if (token == Math::Min || token == Math::Max || token == Math::Pow)
+ len = 2;
+ return Function(new MathFunc(token, len));
+ };
+
+ return Number(d);
+}
+
+bool Math::hasProperty(const UString &p, bool recursive) const
+{
+ return (Lookup::find(&mathTable, p) >= 0 ||
+ (recursive && Imp::hasProperty(p, recursive)));
+}
+
+Completion MathFunc::execute(const List &args)
+{
+ KJSO v = args[0];
+ Number n = v.toNumber();
+ double arg = n.value();
+
+ KJSO v2 = args[1];
+ Number n2 = v2.toNumber();
+ double arg2 = n2.value();
+ double result;
+
+ switch (id) {
+ case Math::Abs:
+ result = ( arg < 0 ) ? (-arg) : arg;
+ break;
+ case Math::ACos:
+ result = ::acos(arg);
+ break;
+ case Math::ASin:
+ result = ::asin(arg);
+ break;
+ case Math::ATan:
+ result = ::atan(arg);
+ break;
+ case Math::ATan2:
+ result = ::atan2(arg, arg2);
+ break;
+ case Math::Ceil:
+ result = ::ceil(arg);
+ break;
+ case Math::Cos:
+ result = ::cos(arg);
+ break;
+ case Math::Exp:
+ result = ::exp(arg);
+ break;
+ case Math::Floor:
+ result = ::floor(arg);
+ break;
+ case Math::Log:
+ result = ::log(arg);
+ break;
+ case Math::Max:
+ result = ( arg > arg2 ) ? arg : arg2;
+ break;
+ case Math::Min:
+ result = ( arg < arg2 ) ? arg : arg2;
+ break;
+ case Math::Pow:
+ result = ::pow(arg, arg2);
+ break;
+ case Math::Random:
+ result = ::rand();
+ result = result / RAND_MAX;
+ break;
+ case Math::Round:
+ if (isNaN(arg))
+ result = arg;
+ if (isInf(arg) || isInf(-arg))
+ result = arg;
+ else if (arg == -0.5)
+ result = 0;
+ else
+ result = (double)(arg >= 0.0 ? int(arg + 0.5) : int(arg - 0.5));
+ break;
+ case Math::Sin:
+ result = ::sin(arg);
+ break;
+ case Math::Sqrt:
+ result = ::sqrt(arg);
+ break;
+ case Math::Tan:
+ result = ::tan(arg);
+ break;
+
+ default:
+ result = 0.0;
+ assert(0);
+ }
+
+ return Completion(ReturnValue, Number(result));
+}
diff --git a/WebCore/src/kdelibs/kjs/math_object.h b/WebCore/src/kdelibs/kjs/math_object.h
new file mode 100644
index 0000000..a04cfc1
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/math_object.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MATH_OBJECT_H_
+#define _MATH_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class Math : public ObjectImp {
+ public:
+ Math() : ObjectImp(BooleanClass) { }
+ virtual KJSO get(const UString &p) const;
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2,
+ Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Pow,
+ Exp, Floor, Log, Max, Min, Random, Round, Sin, Sqrt, Tan };
+ };
+
+ class MathFunc : public InternalFunctionImp {
+ public:
+ MathFunc(int i, int l) : InternalFunctionImp(l), id(i) { }
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/math_object.lut.h b/WebCore/src/kdelibs/kjs/math_object.lut.h
new file mode 100644
index 0000000..e422d18
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/math_object.lut.h
@@ -0,0 +1,42 @@
+/* automatically generated from math.table. DO NOT EDIT ! */
+
+namespace KJS {
+
+const struct HashEntry2 mathTableEntries[] = {
+ { "atan", Math::ATan, DontEnum|ReadOnly, &mathTableEntries[25] },
+ { 0, 0, 0, 0 },
+ { "SQRT2", Math::Sqrt2, DontEnum|ReadOnly, &mathTableEntries[23] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "E", Math::Euler, DontEnum|ReadOnly, &mathTableEntries[21] },
+ { "asin", Math::ASin, DontEnum|ReadOnly, &mathTableEntries[26] },
+ { "atan2", Math::ATan2, DontEnum|ReadOnly, &mathTableEntries[31] },
+ { "LOG2E", Math::Log2E, DontEnum|ReadOnly, &mathTableEntries[27] },
+ { "cos", Math::Cos, DontEnum|ReadOnly, 0 },
+ { "max", Math::Max, DontEnum|ReadOnly, &mathTableEntries[28] },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { "LOG10E", Math::Log10E, DontEnum|ReadOnly, &mathTableEntries[24] },
+ { "LN2", Math::Ln2, DontEnum|ReadOnly, &mathTableEntries[30] },
+ { "abs", Math::Abs, DontEnum|ReadOnly, 0 },
+ { "sqrt", Math::Sqrt, DontEnum|ReadOnly, 0 },
+ { "exp", Math::Exp, DontEnum|ReadOnly, 0 },
+ { 0, 0, 0, 0 },
+ { "LN10", Math::Ln10, DontEnum|ReadOnly, &mathTableEntries[22] },
+ { "PI", Math::Pi, DontEnum|ReadOnly, &mathTableEntries[29] },
+ { "SQRT1_2", Math::Sqrt1_2, DontEnum|ReadOnly, 0 },
+ { "acos", Math::ACos, DontEnum|ReadOnly, 0 },
+ { "ceil", Math::Ceil, DontEnum|ReadOnly, 0 },
+ { "floor", Math::Floor, DontEnum|ReadOnly, 0 },
+ { "log", Math::Log, DontEnum|ReadOnly, 0 },
+ { "min", Math::Min, DontEnum|ReadOnly, 0 },
+ { "random", Math::Random, DontEnum|ReadOnly, 0 },
+ { "round", Math::Round, DontEnum|ReadOnly, 0 },
+ { "sin", Math::Sin, DontEnum|ReadOnly, 0 },
+ { "tan", Math::Tan, DontEnum|ReadOnly, 0 }
+};
+
+const struct HashTable2 mathTable = { 2, 32, mathTableEntries, 21 };
+
+}; // namespace
diff --git a/WebCore/src/kdelibs/kjs/nodes.cpp b/WebCore/src/kdelibs/kjs/nodes.cpp
new file mode 100644
index 0000000..ab20d3b
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/nodes.cpp
@@ -0,0 +1,1487 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "nodes.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "kjs.h"
+#include "ustring.h"
+#include "lexer.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "regexp_object.h"
+#include "debugger.h"
+
+using namespace KJS;
+
+#ifdef KJS_DEBUGGER
+#define KJS_BREAKPOINT if (!hitStatement()) return Completion(Normal);
+#define KJS_ABORTPOINT if (abortStatement()) return Completion(Normal);
+#else
+#define KJS_BREAKPOINT
+#define KJS_ABORTPOINT
+#endif
+
+int Node::nodeCount = 0;
+Node* Node::first = 0;
+
+Node::Node()
+{
+ assert(Lexer::curr());
+ line = Lexer::curr()->lineNo();
+ nodeCount++;
+ // cout << "Node()" << endl;
+
+ // create a list of allocated objects. Makes
+ // deleting (even after a parse error) quite easy
+ next = first;
+ prev = 0L;
+ if (first)
+ first->prev = this;
+ first = this;
+}
+
+Node::~Node()
+{
+ // cout << "~Node()" << endl;
+ if (next)
+ next->prev = prev;
+ if (prev)
+ prev->next = next;
+ nodeCount--;
+}
+
+void Node::deleteAllNodes()
+{
+ Node *tmp, *n = first;
+
+ while ((tmp = n)) {
+ n = n->next;
+ delete tmp;
+ }
+ first = 0L;
+ // assert(nodeCount == 0);
+}
+
+KJSO Node::throwError(ErrorType e, const char *msg)
+{
+ return Error::create(e, msg, lineNo());
+}
+
+#ifdef KJS_DEBUGGER
+void StatementNode::setLoc(int line0, int line1)
+{
+ l0 = line0;
+ l1 = line1;
+ sid = KJScriptImp::current()->sourceId();
+}
+
+bool StatementNode::hitStatement()
+{
+ if (KJScriptImp::current()->debugger())
+ return KJScriptImp::current()->debugger()->hit(firstLine(), breakPoint);
+ else
+ return true;
+}
+
+// return true if the debugger wants us to stop at this point
+bool StatementNode::abortStatement()
+{
+ if (KJScriptImp::current()->debugger() &&
+ KJScriptImp::current()->debugger()->mode() == Debugger::Stop)
+ return true;
+
+ return false;
+}
+
+bool Node::setBreakpoint(Node *firstNode, int id, int line, bool set)
+{
+ while (firstNode) {
+ if (firstNode->setBreakpoint(id, line, set) && line >= 0) // line<0 for all
+ return true;
+ firstNode = firstNode->next;
+ }
+ return false;
+}
+
+/**
+ * Try to set or delete a breakpoint depending on the value of set.
+ * The call will return true if successful, i.e. if line is inside
+ * of the statement's range. Additionally, a breakpoint had to
+ * be set already if you tried to delete with set=false.
+ */
+bool StatementNode::setBreakpoint(int id, int line, bool set)
+{
+ // in our source unit and line range ?
+ if (id != sid || ((line < l0 || line > l1) && line >= 0))
+ return false;
+
+ if (!set && !breakPoint)
+ return false;
+
+ breakPoint = set;
+ return true;
+}
+#endif
+
+KJSO NullNode::evaluate()
+{
+ return Null();
+}
+
+KJSO BooleanNode::evaluate()
+{
+ return Boolean(value);
+}
+
+KJSO NumberNode::evaluate()
+{
+ return Number(value);
+}
+
+KJSO StringNode::evaluate()
+{
+ return String(value);
+}
+
+KJSO RegExpNode::evaluate()
+{
+ List list;
+ String p(pattern);
+ String f(flags);
+ list.append(p);
+ list.append(f);
+
+ // very ugly
+ KJSO r = Global::current().get("RegExp");
+ RegExpObject *r2 = (RegExpObject*)r.imp();
+ return r2->construct(list);
+}
+
+// ECMA 11.1.1
+KJSO ThisNode::evaluate()
+{
+ return Context::current()->thisValue();
+}
+
+// ECMA 11.1.2 & 10.1.4
+KJSO ResolveNode::evaluate()
+{
+ assert(Context::current());
+ const List *chain = Context::current()->pScopeChain();
+ assert(chain);
+ ListIterator scope = chain->begin();
+
+ while (scope != chain->end()) {
+ if (scope->hasProperty(ident)) {
+// cout << "Resolve: found '" << ident.ascii() << "'"
+// << " type " << scope->get(ident).imp()->typeInfo()->name << endl;
+ return Reference(*scope, ident);
+ }
+ scope++;
+ }
+
+ // identifier not found
+// cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
+ return Reference(Null(), ident);
+}
+
+// ECMA 11.1.4
+KJSO ArrayNode::evaluate()
+{
+ KJSO array;
+ int length;
+ int elisionLen = elision ? elision->evaluate().toInt32() : 0;
+
+ if (element) {
+ array = element->evaluate();
+ length = opt ? array.get("length").toInt32() : 0;
+ } else {
+ array = Object::create(ArrayClass);
+ length = 0;
+ }
+
+ if (opt)
+ array.put("length", Number(elisionLen + length), DontEnum | DontDelete);
+
+ return array;
+}
+
+// ECMA 11.1.4
+KJSO ElementNode::evaluate()
+{
+ KJSO array, val;
+ int length = 0;
+ int elisionLen = elision ? elision->evaluate().toInt32() : 0;
+
+ if (list) {
+ array = list->evaluate();
+ val = node->evaluate().getValue();
+ length = array.get("length").toInt32();
+ } else {
+ array = Object::create(ArrayClass);
+ val = node->evaluate().getValue();
+ }
+
+ array.putArrayElement(UString::from(elisionLen + length), val);
+
+ return array;
+}
+
+// ECMA 11.1.4
+KJSO ElisionNode::evaluate()
+{
+ if (elision)
+ return Number(elision->evaluate().toNumber().value() + 1);
+ else
+ return Number(1);
+}
+
+// ECMA 11.1.5
+KJSO ObjectLiteralNode::evaluate()
+{
+ if (list)
+ return list->evaluate();
+
+ return Object::create(ObjectClass);
+}
+
+// ECMA 11.1.5
+KJSO PropertyValueNode::evaluate()
+{
+ KJSO obj;
+ if (list)
+ obj = list->evaluate();
+ else
+ obj = Object::create(ObjectClass);
+ KJSO n = name->evaluate();
+ KJSO a = assign->evaluate();
+ KJSO v = a.getValue();
+
+ obj.put(n.toString().value(), v);
+
+ return obj;
+}
+
+// ECMA 11.1.5
+KJSO PropertyNode::evaluate()
+{
+ KJSO s;
+
+ if (str.isNull()) {
+ s = String(UString::from(numeric));
+ } else
+ s = String(str);
+
+ return s;
+}
+
+// ECMA 11.1.6
+KJSO GroupNode::evaluate()
+{
+ return group->evaluate();
+}
+
+// ECMA 11.2.1a
+KJSO AccessorNode1::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+ Object o = v1.toObject();
+ String s = v2.toString();
+ return Reference(o, s.value());
+}
+
+// ECMA 11.2.1b
+KJSO AccessorNode2::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ KJSO o = v.toObject();
+ return Reference(o, ident);
+}
+
+// ECMA 11.2.2
+KJSO NewExprNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ List *argList = args ? args->evaluateList() : 0;
+
+ if (!v.isObject()) {
+ delete argList;
+ return throwError(TypeError, "Expression is no object. Cannot be new'ed");
+ }
+
+ Constructor constr = Constructor::dynamicCast(v);
+ if (constr.isNull()) {
+ delete argList;
+ return throwError(TypeError, "Expression is no constructor.");
+ }
+
+ if (!argList)
+ argList = new List;
+
+ KJSO res = constr.construct(*argList);
+
+ delete argList;
+
+ return res;
+}
+
+// ECMA 11.2.3
+KJSO FunctionCallNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+
+ List *argList = args->evaluateList();
+
+ KJSO v = e.getValue();
+
+ if (!v.isObject()) {
+#ifndef NDEBUG
+ printInfo("Failed function call attempt on", e);
+#endif
+ delete argList;
+ return throwError(TypeError, "Expression is no object. Cannot be called.");
+ }
+
+ if (!v.implementsCall()) {
+#ifndef NDEBUG
+ printInfo("Failed function call attempt on", e);
+#endif
+ delete argList;
+ return throwError(TypeError, "Expression does not allow calls.");
+ }
+
+ KJSO o;
+ if (e.isA(ReferenceType))
+ o = e.getBase();
+ else
+ o = Null();
+
+ if (o.isA(ActivationType))
+ o = Null();
+
+#ifdef KJS_DEBUGGER
+ steppingInto(true);
+#endif
+
+ KJSO result = v.executeCall(o, argList);
+
+#ifdef KJS_DEBUGGER
+ steppingInto(false);
+#endif
+
+ delete argList;
+
+ return result;
+}
+
+#ifdef KJS_DEBUGGER
+void FunctionCallNode::steppingInto(bool in)
+{
+ Debugger *dbg = KJScriptImp::current()->debugger();
+ if (!dbg)
+ return;
+ if (in) {
+ // before entering function. Don't step inside if 'Next' is chosen.
+ previousMode = dbg->mode();
+ if (previousMode == Debugger::Next)
+ dbg->setMode(Debugger::Continue);
+ } else {
+ // restore mode after leaving function
+ dbg->setMode(previousMode);
+ }
+}
+#endif
+
+KJSO ArgumentsNode::evaluate()
+{
+ assert(0);
+ return KJSO(); // dummy, see evaluateList()
+}
+
+// ECMA 11.2.4
+List* ArgumentsNode::evaluateList()
+{
+ if (!list)
+ return new List();
+
+ return list->evaluateList();
+}
+
+KJSO ArgumentListNode::evaluate()
+{
+ assert(0);
+ return KJSO(); // dummy, see evaluateList()
+}
+
+// ECMA 11.2.4
+List* ArgumentListNode::evaluateList()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ if (!list) {
+ List *l = new List();
+ l->append(v);
+ return l;
+ }
+
+ List *l = list->evaluateList();
+ l->append(v);
+
+ return l;
+}
+
+// ECMA 11.8
+KJSO RelationalNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+
+ bool b;
+ if (oper == OpLess || oper == OpGreaterEq) {
+ int r = relation(v1, v2);
+ if (r < 0)
+ b = false;
+ else
+ b = (oper == OpLess) ? (r == 1) : (r == 0);
+ } else if (oper == OpGreater || oper == OpLessEq) {
+ int r = relation(v2, v1);
+ if (r < 0)
+ b = false;
+ else
+ b = (oper == OpGreater) ? (r == 1) : (r == 0);
+ } else if (oper == OpIn) {
+ /* Is all of this OK for host objects? */
+ if (!v2.isObject())
+ return throwError( TypeError,
+ "Shift expression not an object into IN expression." );
+ b = v2.hasProperty(v1.toString().value());
+ } else {
+ /* TODO: should apply to Function _objects_ only */
+ if (!v2.derivedFrom("Function"))
+ return throwError(TypeError,
+ "Called instanceof operator on non-function object." );
+ return hasInstance(v2, v1); /* TODO: make object member function */
+ }
+
+ return Boolean(b);
+}
+
+// ECMA 11.9
+KJSO EqualNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO e2 = expr2->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO v2 = e2.getValue();
+
+ bool result;
+ if (oper == OpEqEq || oper == OpNotEq) {
+ // == and !=
+ bool eq = equal(v1, v2);
+ result = oper == OpEqEq ? eq : !eq;
+ } else {
+ // === and !==
+ bool eq = strictEqual(v1, v2);
+ result = oper == OpStrEq ? eq : !eq;
+ }
+ return Boolean(result);
+}
+
+// ECMA 11.10
+KJSO BitOperNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+ int i1 = v1.toInt32();
+ int i2 = v2.toInt32();
+ int result;
+ if (oper == OpBitAnd)
+ result = i1 & i2;
+ else if (oper == OpBitXOr)
+ result = i1 ^ i2;
+ else
+ result = i1 | i2;
+
+ return Number(result);
+}
+
+// ECMA 11.11
+KJSO BinaryLogicalNode::evaluate()
+{
+ KJSO e1 = expr1->evaluate();
+ KJSO v1 = e1.getValue();
+ Boolean b1 = v1.toBoolean();
+ if ((!b1.value() && oper == OpAnd) || (b1.value() && oper == OpOr))
+ return v1;
+
+ KJSO e2 = expr2->evaluate();
+ KJSO v2 = e2.getValue();
+
+ return v2;
+}
+
+// ECMA 11.12
+KJSO ConditionalNode::evaluate()
+{
+ KJSO e = logical->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ if (b.value())
+ e = expr1->evaluate();
+ else
+ e = expr2->evaluate();
+
+ return e.getValue();
+}
+
+// ECMA 11.13
+KJSO AssignNode::evaluate()
+{
+ KJSO l, e, v;
+ ErrorType err;
+ if (oper == OpEqual) {
+ l = left->evaluate();
+ e = expr->evaluate();
+ v = e.getValue();
+ } else {
+ l = left->evaluate();
+ KJSO v1 = l.getValue();
+ e = expr->evaluate();
+ KJSO v2 = e.getValue();
+ int i1 = v1.toInt32();
+ int i2 = v2.toInt32();
+ switch (oper) {
+ case OpMultEq:
+ v = mult(v1, v2, '*');
+ break;
+ case OpDivEq:
+ v = mult(v1, v2, '/');
+ break;
+ case OpPlusEq:
+ v = add(v1, v2, '+');
+ break;
+ case OpMinusEq:
+ v = add(v1, v2, '-');
+ break;
+ case OpLShift:
+ v = Number(i1 <<= i2);
+ break;
+ case OpRShift:
+ v = Number(i1 >>= i2);
+ break;
+ case OpURShift:
+ i1 = v1.toUInt32();
+ v = Number(i1 >>= i2);
+ break;
+ case OpAndEq:
+ v = Number(i1 &= i2);
+ break;
+ case OpXOrEq:
+ v = Number(i1 ^= i2);
+ break;
+ case OpOrEq:
+ v = Number(i1 |= i2);
+ break;
+ case OpModEq:
+ v = Number(i1 %= i2);
+ break;
+ default:
+ v = Undefined();
+ }
+ err = l.putValue(v);
+ };
+
+ err = l.putValue(v);
+ if (err == NoError)
+ return v;
+ else
+ return throwError(err, "Invalid reference.");
+}
+
+// ECMA 11.3
+KJSO PostfixNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
+ KJSO n2 = Number(newValue);
+
+ e.putValue(n2);
+
+ return n;
+}
+
+// ECMA 11.4.1
+KJSO DeleteNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ if (!e.isA(ReferenceType))
+ return Boolean(true);
+ KJSO b = e.getBase();
+ UString n = e.getPropertyName();
+ bool ret = b.deleteProperty(n);
+
+ return Boolean(ret);
+}
+
+// ECMA 11.4.2
+KJSO VoidNode::evaluate()
+{
+ KJSO dummy1 = expr->evaluate();
+ KJSO dummy2 = dummy1.getValue();
+
+ return Undefined();
+}
+
+// ECMA 11.4.3
+KJSO TypeOfNode::evaluate()
+{
+ const char *s = 0L;
+ KJSO e = expr->evaluate();
+ if (e.isA(ReferenceType)) {
+ KJSO b = e.getBase();
+ if (b.isA(NullType))
+ return String("undefined");
+ }
+ KJSO v = e.getValue();
+ switch (v.type())
+ {
+ case UndefinedType:
+ s = "undefined";
+ break;
+ case NullType:
+ s = "object";
+ break;
+ case BooleanType:
+ s = "boolean";
+ break;
+ case NumberType:
+ s = "number";
+ break;
+ case StringType:
+ s = "string";
+ break;
+ default:
+ if (v.implementsCall())
+ s = "function";
+ else
+ s = "object";
+ break;
+ }
+
+ return String(s);
+}
+
+// ECMA 11.4.4 and 11.4.5
+KJSO PrefixNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
+ KJSO n2 = Number(newValue);
+
+ e.putValue(n2);
+
+ return n2;
+}
+
+// ECMA 11.4.6
+KJSO UnaryPlusNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return v.toNumber();
+}
+
+// ECMA 11.4.7
+KJSO NegateNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Number n = v.toNumber();
+
+ double d = -n.value();
+
+ return Number(d);
+}
+
+// ECMA 11.4.8
+KJSO BitwiseNotNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ int i32 = v.toInt32();
+
+ return Number(~i32);
+}
+
+// ECMA 11.4.9
+KJSO LogicalNotNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ return Boolean(!b.value());
+}
+
+// ECMA 11.5
+KJSO MultNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+
+ return mult(v1, v2, oper);
+}
+
+// ECMA 11.7
+KJSO ShiftNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+ unsigned int i2 = v2.toUInt32();
+ i2 &= 0x1f;
+
+ long result;
+ switch (oper) {
+ case OpLShift:
+ result = v1.toInt32() << i2;
+ break;
+ case OpRShift:
+ result = v1.toInt32() >> i2;
+ break;
+ case OpURShift:
+ result = v1.toUInt32() >> i2;
+ break;
+ default:
+ assert(!"ShiftNode: unhandled switch case");
+ result = 0L;
+ }
+
+ return Number(static_cast<double>(result));
+}
+
+// ECMA 11.6
+KJSO AddNode::evaluate()
+{
+ KJSO t1 = term1->evaluate();
+ KJSO v1 = t1.getValue();
+
+ KJSO t2 = term2->evaluate();
+ KJSO v2 = t2.getValue();
+
+ return add(v1, v2, oper);
+}
+
+// ECMA 11.14
+KJSO CommaNode::evaluate()
+{
+ KJSO e = expr1->evaluate();
+ KJSO dummy = e.getValue(); // ignore return value
+ e = expr2->evaluate();
+
+ return e.getValue();
+}
+
+// ECMA 12.1
+Completion BlockNode::execute()
+{
+ if (!statlist)
+ return Completion(Normal);
+
+ return statlist->execute();
+}
+
+// ECMA 12.1
+Completion StatListNode::execute()
+{
+ if (!list) {
+ Completion c = statement->execute();
+ KJS_ABORTPOINT
+ if (KJScriptImp::hadException()) {
+ KJSO ex = KJScriptImp::exception();
+ KJScriptImp::clearException();
+ return Completion(Throw, ex);
+ } else
+ return c;
+ }
+
+ Completion l = list->execute();
+ KJS_ABORTPOINT
+ if (l.complType() != Normal)
+ return l;
+ Completion e = statement->execute();
+ KJS_ABORTPOINT;
+ if (KJScriptImp::hadException()) {
+ KJSO ex = KJScriptImp::exception();
+ KJScriptImp::clearException();
+ return Completion(Throw, ex);
+ }
+
+ KJSO v = e.isValueCompletion() ? e.value() : l.value();
+
+ return Completion(e.complType(), v, e.target() );
+}
+
+// ECMA 12.2
+Completion VarStatementNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ (void) list->evaluate(); // returns 0L
+
+ return Completion(Normal);
+}
+
+// ECMA 12.2
+KJSO VarDeclNode::evaluate()
+{
+ KJSO variable = Context::current()->variableObject();
+
+ KJSO val, tmp;
+ if (init) {
+ tmp = init->evaluate();
+ val = tmp.getValue();
+ } else {
+ if ( variable.hasProperty( ident ) ) // already declared ?
+ return KJSO();
+ val = Undefined();
+ }
+ variable.put(ident, val, DontDelete);
+
+ // spec wants to return ident. But what for ? Will be ignored above.
+ return KJSO();
+}
+
+// ECMA 12.2
+KJSO VarDeclListNode::evaluate()
+{
+ if (list)
+ (void) list->evaluate();
+
+ (void) var->evaluate();
+
+ return KJSO();
+}
+
+// ECMA 12.2
+KJSO AssignExprNode::evaluate()
+{
+ return expr->evaluate();
+}
+
+// ECMA 12.3
+Completion EmptyStatementNode::execute()
+{
+ return Completion(Normal);
+}
+
+// ECMA 12.6.3
+Completion ForNode::execute()
+{
+ KJSO e, v, cval;
+ Boolean b;
+
+ if (expr1) {
+ e = expr1->evaluate();
+ v = e.getValue();
+ }
+ while (1) {
+ if (expr2) {
+ e = expr2->evaluate();
+ v = e.getValue();
+ b = v.toBoolean();
+ if (b.value() == false)
+ return Completion(Normal, cval);
+ }
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ Completion c = stat->execute();
+ if (c.isValueCompletion())
+ cval = c.value();
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, cval);
+ if (c.complType() != Normal)
+ return c;
+ }
+ if (expr3) {
+ e = expr3->evaluate();
+ v = e.getValue();
+ }
+ }
+}
+
+// ECMA 12.6.4
+Completion ForInNode::execute()
+{
+ KJSO e, v, retval;
+ Completion c;
+ VarDeclNode *vd = 0;
+ const PropList *lst, *curr;
+
+ // This should be done in the constructor
+ if (!lexpr) { // for( var foo = bar in baz )
+ vd = new VarDeclNode(&ident, init);
+ vd->evaluate();
+
+ lexpr = new ResolveNode(&ident);
+ }
+
+ e = expr->evaluate();
+ v = e.getValue().toObject();
+ curr = lst = v.imp()->propList();
+
+ while (curr) {
+ if (!v.hasProperty(curr->name)) {
+ curr = curr->next;
+ continue;
+ }
+
+ e = lexpr->evaluate();
+ e.putValue(String(curr->name));
+
+ c = stat->execute();
+ if (c.isValueCompletion())
+ retval = c.value();
+
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ break;
+ if (c.complType() != Normal) {
+ delete lst;
+ return c;
+ }
+ }
+
+ curr = curr->next;
+ }
+
+ delete lst;
+ return Completion(Normal, retval);
+}
+
+// ECMA 12.4
+Completion ExprStatementNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return Completion(Normal, v);
+}
+
+// ECMA 12.5
+Completion IfNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Boolean b = v.toBoolean();
+
+ // if ... then
+ if (b.value())
+ return statement1->execute();
+
+ // no else
+ if (!statement2)
+ return Completion(Normal);
+
+ // else
+ return statement2->execute();
+}
+
+// ECMA 12.6.1
+Completion DoWhileNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO be, bv;
+ Completion c;
+ KJSO value;
+
+ do {
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ c = statement->execute();
+ if (!((c.complType() == Continue) && ls.contains(c.target()))) {
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, value);
+ if (c.complType() != Normal)
+ return c;
+ }
+ be = expr->evaluate();
+ bv = be.getValue();
+ } while (bv.toBoolean().value());
+
+ return Completion(Normal, value);
+}
+
+// ECMA 12.6.2
+Completion WhileNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO be, bv;
+ Completion c;
+ Boolean b(false);
+ KJSO value;
+
+ while (1) {
+ be = expr->evaluate();
+ bv = be.getValue();
+ b = bv.toBoolean();
+
+ // bail out on error
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ if (!b.value())
+ return Completion(Normal, value);
+
+ c = statement->execute();
+ if (c.isValueCompletion())
+ value = c.value();
+
+ if ((c.complType() == Continue) && ls.contains(c.target()))
+ continue;
+ if ((c.complType() == Break) && ls.contains(c.target()))
+ return Completion(Normal, value);
+ if (c.complType() != Normal)
+ return c;
+ }
+}
+
+// ECMA 12.7
+Completion ContinueNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO dummy;
+ return Context::current()->seenLabels()->contains(ident) ?
+ Completion(Continue, dummy, ident) :
+ Completion(Throw,
+ throwError(SyntaxError, "Label not found in containing block"));
+}
+
+// ECMA 12.8
+Completion BreakNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO dummy;
+ return Context::current()->seenLabels()->contains(ident) ?
+ Completion(Break, dummy, ident) :
+ Completion(Throw,
+ throwError(SyntaxError, "Label not found in containing block"));
+}
+
+// ECMA 12.9
+Completion ReturnNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ if (!value)
+ return Completion(ReturnValue, Undefined());
+
+ KJSO e = value->evaluate();
+ KJSO v = e.getValue();
+
+ return Completion(ReturnValue, v);
+}
+
+// ECMA 12.10
+Completion WithNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Object o = v.toObject();
+ Context::current()->pushScope(o);
+ Completion res = stat->execute();
+ Context::current()->popScope();
+
+ return res;
+}
+
+// ECMA 12.11
+ClauseListNode* ClauseListNode::append(CaseClauseNode *c)
+{
+ ClauseListNode *l = this;
+ while (l->nx)
+ l = l->nx;
+ l->nx = new ClauseListNode(c);
+
+ return this;
+}
+
+// ECMA 12.11
+Completion SwitchNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+ Completion res = block->evalBlock(v);
+
+ if ((res.complType() == Break) && ls.contains(res.target()))
+ return Completion(Normal, res.value());
+ else
+ return res;
+}
+
+// ECMA 12.11
+Completion CaseBlockNode::evalBlock(const KJSO& input)
+{
+ KJSO v;
+ Completion res;
+ ClauseListNode *a = list1, *b = list2;
+ CaseClauseNode *clause;
+
+ if (a) {
+ while (a) {
+ clause = a->clause();
+ a = a->next();
+ v = clause->evaluate();
+ if (strictEqual(input, v)) {
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ while (a) {
+ res = a->clause()->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ a = a->next();
+ }
+ break;
+ }
+ }
+ }
+
+ while (b) {
+ clause = b->clause();
+ b = b->next();
+ v = clause->evaluate();
+ if (strictEqual(input, v)) {
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ goto step18;
+ }
+ }
+
+ // default clause
+ if (def) {
+ res = def->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ }
+ b = list2;
+ step18:
+ while (b) {
+ clause = b->clause();
+ res = clause->evalStatements();
+ if (res.complType() != Normal)
+ return res;
+ b = b->next();
+ }
+
+ return Completion(Normal);
+}
+
+// ECMA 12.11
+KJSO CaseClauseNode::evaluate()
+{
+ KJSO e = expr->evaluate();
+ KJSO v = e.getValue();
+
+ return v;
+}
+
+// ECMA 12.11
+Completion CaseClauseNode::evalStatements()
+{
+ if (list)
+ return list->execute();
+ else
+ return Completion(Normal, Undefined());
+}
+
+// ECMA 12.12
+Completion LabelNode::execute()
+{
+ Completion e;
+
+ if (!Context::current()->seenLabels()->push(label)) {
+ return Completion( Throw,
+ throwError(SyntaxError, "Duplicated label found" ));
+ };
+ e = stat->execute();
+ Context::current()->seenLabels()->pop();
+
+ if ((e.complType() == Break) && (e.target() == label))
+ return Completion(Normal, e.value());
+ else
+ return e;
+}
+
+// ECMA 12.13
+Completion ThrowNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ KJSO v = expr->evaluate().getValue();
+
+ return Completion(Throw, v);
+}
+
+// ECMA 12.14
+Completion TryNode::execute()
+{
+ KJS_BREAKPOINT;
+
+ Completion c, c2;
+
+ c = block->execute();
+
+ if (!_final) {
+ if (c.complType() != Throw)
+ return c;
+ return _catch->execute(c.value());
+ }
+
+ if (!_catch) {
+ c2 = _final->execute();
+ return (c2.complType() == Normal) ? c : c2;
+ }
+
+ if (c.complType() == Throw)
+ c = _catch->execute(c.value());
+
+ c2 = _final->execute();
+ return (c2.complType() == Normal) ? c : c2;
+}
+
+Completion CatchNode::execute()
+{
+ // should never be reached. execute(const KJS &arg) is used instead
+ assert(0L);
+ return Completion();
+}
+
+// ECMA 12.14
+Completion CatchNode::execute(const KJSO &arg)
+{
+ /* TODO: correct ? Not part of the spec */
+ KJScriptImp::clearException();
+
+ Object obj;
+ obj.put(ident, arg, DontDelete);
+ Context::current()->pushScope(obj);
+ Completion c = block->execute();
+ Context::current()->popScope();
+
+ return c;
+}
+
+// ECMA 12.14
+Completion FinallyNode::execute()
+{
+ return block->execute();
+}
+
+FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
+ : source(s)
+{
+#ifdef KJS_DEBUGGER
+ setLoc(-1, -1);
+#endif
+}
+
+// ECMA 13 + 14 for ProgramNode
+Completion FunctionBodyNode::execute()
+{
+ /* TODO: workaround for empty body which I don't see covered by the spec */
+ if (!source)
+ return Completion(ReturnValue, Undefined());
+
+ source->processFuncDecl();
+
+ return source->execute();
+}
+
+// ECMA 13
+void FuncDeclNode::processFuncDecl()
+{
+ const List *sc = Context::current()->pScopeChain();
+ /* TODO: let this be an object with [[Class]] property "Function" */
+ FunctionImp *fimp = new DeclaredFunctionImp(ident, body, sc);
+ Function func(fimp); // protect from GC
+ fimp->put("prototype", Object::create(ObjectClass), DontDelete);
+
+ int plen = 0;
+ for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
+ fimp->addParameter(p->ident());
+
+ fimp->setLength(plen);
+
+ Context::current()->variableObject().put(ident, func);
+}
+
+// ECMA 13
+KJSO FuncExprNode::evaluate()
+{
+ const List *sc = Context::current()->pScopeChain();
+ FunctionImp *fimp = new DeclaredFunctionImp(UString::null, body, sc->copy());
+ Function ret(fimp);
+
+ int plen = 0;
+ for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
+ fimp->addParameter(p->ident());
+ fimp->setLength(plen);
+
+ return ret;
+}
+
+ParameterNode* ParameterNode::append(const UString *i)
+{
+ ParameterNode *p = this;
+ while (p->next)
+ p = p->next;
+
+ p->next = new ParameterNode(i);
+
+ return this;
+}
+
+// ECMA 13
+KJSO ParameterNode::evaluate()
+{
+ return Undefined();
+}
+
+void ProgramNode::deleteGlobalStatements()
+{
+ source->deleteStatements();
+}
+
+// ECMA 14
+Completion SourceElementsNode::execute()
+{
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ if (!elements)
+ return element->execute();
+
+ Completion c1 = elements->execute();
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+ if (c1.complType() != Normal)
+ return c1;
+
+ Completion c2 = element->execute();
+ if (KJScriptImp::hadException())
+ return Completion(Throw, KJScriptImp::exception());
+
+ return c2;
+}
+
+// ECMA 14
+void SourceElementsNode::processFuncDecl()
+{
+ if (elements)
+ elements->processFuncDecl();
+
+ element->processFuncDecl();
+}
+
+void SourceElementsNode::deleteStatements()
+{
+ element->deleteStatements();
+
+ if (elements)
+ elements->deleteStatements();
+}
+
+// ECMA 14
+Completion SourceElementNode::execute()
+{
+ if (statement)
+ return statement->execute();
+
+ return Completion(Normal);
+}
+
+// ECMA 14
+void SourceElementNode::processFuncDecl()
+{
+ if (function)
+ function->processFuncDecl();
+}
+
+void SourceElementNode::deleteStatements()
+{
+ delete statement;
+}
+
+ArgumentListNode::ArgumentListNode(Node *e) : list(0L), expr(e) {}
+
+VarDeclNode::VarDeclNode(const UString *id, AssignExprNode *in)
+ : ident(*id), init(in) { }
+
+ArgumentListNode::ArgumentListNode(ArgumentListNode *l, Node *e) :
+ list(l), expr(e) {}
+
+ArgumentsNode::ArgumentsNode(ArgumentListNode *l) : list(l) {}
diff --git a/WebCore/src/kdelibs/kjs/nodes.h b/WebCore/src/kdelibs/kjs/nodes.h
new file mode 100644
index 0000000..223109a
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/nodes.h
@@ -0,0 +1,789 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _NODES_H_
+#define _NODES_H_
+
+#include "internal.h"
+#include "ustring.h"
+#include "object.h"
+#include "types.h"
+#include "debugger.h"
+
+namespace KJS {
+
+ class KJSO;
+ class RegExp;
+ class SourceElementsNode;
+ class ProgramNode;
+
+ enum Operator { OpEqual,
+ OpEqEq,
+ OpNotEq,
+ OpStrEq,
+ OpStrNEq,
+ OpPlusEq,
+ OpMinusEq,
+ OpMultEq,
+ OpDivEq,
+ OpPlusPlus,
+ OpMinusMinus,
+ OpLess,
+ OpLessEq,
+ OpGreater,
+ OpGreaterEq,
+ OpAndEq,
+ OpXOrEq,
+ OpOrEq,
+ OpModEq,
+ OpAnd,
+ OpOr,
+ OpBitAnd,
+ OpBitXOr,
+ OpBitOr,
+ OpLShift,
+ OpRShift,
+ OpURShift,
+ OpIn,
+ OpInstanceOf
+ };
+
+ class Node {
+ public:
+ Node();
+ virtual ~Node();
+ virtual KJSO evaluate() = 0;
+ int lineNo() const { return line; }
+ static Node *firstNode() { return first; }
+ static void setFirstNode(Node *n) { first = n; }
+ static void deleteAllNodes();
+#ifdef KJS_DEBUGGER
+ static bool setBreakpoint(Node *firstNode, int id, int line, bool set);
+ virtual bool setBreakpoint(int, int, bool) { return false; }
+#endif
+ protected:
+ KJSO throwError(ErrorType e, const char *msg);
+ private:
+ // disallow assignment and copy-construction
+ Node(const Node &);
+ Node& operator=(const Node&);
+ int line;
+ static int nodeCount;
+ static Node *first;
+ Node *next, *prev;
+ };
+
+ class StatementNode : public Node {
+ public:
+#ifdef KJS_DEBUGGER
+ StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false) { }
+ void setLoc(int line0, int line1);
+ int firstLine() const { return l0; }
+ int lastLine() const { return l1; }
+ int sourceId() const { return sid; }
+ bool hitStatement();
+ bool abortStatement();
+ virtual bool setBreakpoint(int id, int line, bool set);
+#endif
+ virtual Completion execute() = 0;
+ void pushLabel(const UString *id) {
+ if (id) ls.push(*id);
+ }
+ protected:
+ LabelStack ls;
+ private:
+ KJSO evaluate() { return Undefined(); }
+#ifdef KJS_DEBUGGER
+ int l0, l1;
+ int sid;
+ bool breakPoint;
+#endif
+ };
+
+ class NullNode : public Node {
+ public:
+ KJSO evaluate();
+ };
+
+ class BooleanNode : public Node {
+ public:
+ BooleanNode(bool v) : value(v) {}
+ KJSO evaluate();
+ private:
+ bool value;
+ };
+
+ class NumberNode : public Node {
+ public:
+ NumberNode(double v) : value(v) { }
+ KJSO evaluate();
+ private:
+ double value;
+ };
+
+ class StringNode : public Node {
+ public:
+ StringNode(const UString *v) { value = *v; }
+ KJSO evaluate();
+ private:
+ UString value;
+ };
+
+ class RegExpNode : public Node {
+ public:
+ RegExpNode(const UString &p, const UString &f)
+ : pattern(p), flags(f) { }
+ KJSO evaluate();
+ private:
+ UString pattern, flags;
+ };
+
+ class ThisNode : public Node {
+ public:
+ KJSO evaluate();
+ };
+
+ class ResolveNode : public Node {
+ public:
+ ResolveNode(const UString *s) : ident(*s) { }
+ KJSO evaluate();
+ private:
+ UString ident;
+ };
+
+ class GroupNode : public Node {
+ public:
+ GroupNode(Node *g) : group(g) { }
+ KJSO evaluate();
+ private:
+ Node *group;
+ };
+
+ class ElisionNode : public Node {
+ public:
+ ElisionNode(ElisionNode *e) : elision(e) { }
+ KJSO evaluate();
+ private:
+ ElisionNode *elision;
+ };
+
+ class ElementNode : public Node {
+ public:
+ ElementNode(ElisionNode *e, Node *n) : list(0l), elision(e), node(n) { }
+ ElementNode(ElementNode *l, ElisionNode *e, Node *n)
+ : list(l), elision(e), node(n) { }
+ KJSO evaluate();
+ private:
+ ElementNode *list;
+ ElisionNode *elision;
+ Node *node;
+ };
+
+ class ArrayNode : public Node {
+ public:
+ ArrayNode(ElisionNode *e) : element(0L), elision(e), opt(true) { }
+ ArrayNode(ElementNode *ele)
+ : element(ele), elision(0), opt(false) { }
+ ArrayNode(ElisionNode *eli, ElementNode *ele)
+ : element(ele), elision(eli), opt(true) { }
+ KJSO evaluate();
+ private:
+ ElementNode *element;
+ ElisionNode *elision;
+ bool opt;
+ };
+
+ class ObjectLiteralNode : public Node {
+ public:
+ ObjectLiteralNode(Node *l) : list(l) { }
+ KJSO evaluate();
+ private:
+ Node *list;
+ };
+
+ class PropertyValueNode : public Node {
+ public:
+ PropertyValueNode(Node *n, Node *a, Node *l = 0L)
+ : name(n), assign(a), list(l) { }
+ KJSO evaluate();
+ private:
+ Node *name, *assign, *list;
+ };
+
+ class PropertyNode : public Node {
+ public:
+ PropertyNode(double d) : numeric(d) { }
+ PropertyNode(const UString *s) : str(*s) { }
+ KJSO evaluate();
+ private:
+ double numeric;
+ UString str;
+ };
+
+ class AccessorNode1 : public Node {
+ public:
+ AccessorNode1(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *expr1;
+ Node *expr2;
+ };
+
+ class AccessorNode2 : public Node {
+ public:
+ AccessorNode2(Node *e, const UString *s) : expr(e), ident(*s) { }
+ KJSO evaluate();
+ private:
+ Node *expr;
+ UString ident;
+ };
+
+ class ArgumentListNode : public Node {
+ public:
+ ArgumentListNode(Node *e);
+ ArgumentListNode(ArgumentListNode *l, Node *e);
+ KJSO evaluate();
+ List *evaluateList();
+ private:
+ ArgumentListNode *list;
+ Node *expr;
+ };
+
+ class ArgumentsNode : public Node {
+ public:
+ ArgumentsNode(ArgumentListNode *l);
+ KJSO evaluate();
+ List *evaluateList();
+ private:
+ ArgumentListNode *list;
+ };
+
+ class NewExprNode : public Node {
+ public:
+ NewExprNode(Node *e) : expr(e), args(0L) {}
+ NewExprNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ ArgumentsNode *args;
+ };
+
+ class FunctionCallNode : public Node {
+ public:
+ FunctionCallNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {}
+ KJSO evaluate();
+#ifdef KJS_DEBUGGER
+ void steppingInto(bool in);
+ Debugger::Mode previousMode;
+#endif
+ private:
+ Node *expr;
+ ArgumentsNode *args;
+ };
+
+ class PostfixNode : public Node {
+ public:
+ PostfixNode(Node *e, Operator o) : expr(e), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ Operator oper;
+ };
+
+ class DeleteNode : public Node {
+ public:
+ DeleteNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class VoidNode : public Node {
+ public:
+ VoidNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class TypeOfNode : public Node {
+ public:
+ TypeOfNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class PrefixNode : public Node {
+ public:
+ PrefixNode(Operator o, Node *e) : oper(o), expr(e) {}
+ KJSO evaluate();
+ private:
+ Operator oper;
+ Node *expr;
+ };
+
+ class UnaryPlusNode : public Node {
+ public:
+ UnaryPlusNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class NegateNode : public Node {
+ public:
+ NegateNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class BitwiseNotNode : public Node {
+ public:
+ BitwiseNotNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class LogicalNotNode : public Node {
+ public:
+ LogicalNotNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class MultNode : public Node {
+ public:
+ MultNode(Node *t1, Node *t2, char op) : term1(t1), term2(t2), oper(op) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ char oper;
+ };
+
+ class AddNode : public Node {
+ public:
+ AddNode(Node *t1, Node *t2, char op) : term1(t1), term2(t2), oper(op) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ char oper;
+ };
+
+ class ShiftNode : public Node {
+ public:
+ ShiftNode(Node *t1, Operator o, Node *t2)
+ : term1(t1), term2(t2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *term1, *term2;
+ Operator oper;
+ };
+
+ class RelationalNode : public Node {
+ public:
+ RelationalNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class EqualNode : public Node {
+ public:
+ EqualNode(Node *e1, Operator o, Node *e2)
+ : expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class BitOperNode : public Node {
+ public:
+ BitOperNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class BinaryLogicalNode : public Node {
+ public:
+ BinaryLogicalNode(Node *e1, Operator o, Node *e2) :
+ expr1(e1), expr2(e2), oper(o) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ Operator oper;
+ };
+
+ class ConditionalNode : public Node {
+ public:
+ ConditionalNode(Node *l, Node *e1, Node *e2) :
+ logical(l), expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *logical, *expr1, *expr2;
+ };
+
+ class AssignNode : public Node {
+ public:
+ AssignNode(Node *l, Operator o, Node *e) : left(l), oper(o), expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *left;
+ Operator oper;
+ Node *expr;
+ };
+
+ class CommaNode : public Node {
+ public:
+ CommaNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
+ KJSO evaluate();
+ private:
+ Node *expr1, *expr2;
+ };
+
+ class StatListNode : public StatementNode {
+ public:
+ StatListNode(StatementNode *s) : statement(s), list(0L) { }
+ StatListNode(StatListNode *l, StatementNode *s) : statement(s), list(l) { }
+ Completion execute();
+ private:
+ StatementNode *statement;
+ StatListNode *list;
+ };
+
+ class AssignExprNode : public Node {
+ public:
+ AssignExprNode(Node *e) : expr(e) {}
+ KJSO evaluate();
+ private:
+ Node *expr;
+ };
+
+ class VarDeclNode : public Node {
+ public:
+ VarDeclNode(const UString *id, AssignExprNode *in);
+ KJSO evaluate();
+ private:
+ UString ident;
+ AssignExprNode *init;
+ };
+
+ class VarDeclListNode : public Node {
+ public:
+ VarDeclListNode(VarDeclNode *v) : list(0L), var(v) {}
+ VarDeclListNode(Node *l, VarDeclNode *v) : list(l), var(v) {}
+ KJSO evaluate();
+ private:
+ Node *list;
+ VarDeclNode *var;
+ };
+
+ class VarStatementNode : public StatementNode {
+ public:
+ VarStatementNode(VarDeclListNode *l) : list(l) {}
+ Completion execute();
+ private:
+ VarDeclListNode *list;
+ };
+
+ class BlockNode : public StatementNode {
+ public:
+ BlockNode(StatListNode *s) : statlist(s) {}
+ Completion execute();
+ private:
+ StatListNode *statlist;
+ };
+
+ class EmptyStatementNode : public StatementNode {
+ public:
+ EmptyStatementNode() { } // debug
+ Completion execute();
+ };
+
+ class ExprStatementNode : public StatementNode {
+ public:
+ ExprStatementNode(Node *e) : expr(e) { }
+ Completion execute();
+ private:
+ Node *expr;
+ };
+
+ class IfNode : public StatementNode {
+ public:
+ IfNode(Node *e, StatementNode *s1, StatementNode *s2)
+ : expr(e), statement1(s1), statement2(s2) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *statement1, *statement2;
+ };
+
+ class DoWhileNode : public StatementNode {
+ public:
+ DoWhileNode(StatementNode *s, Node *e) : statement(s), expr(e) {}
+ Completion execute();
+ private:
+ StatementNode *statement;
+ Node *expr;
+ };
+
+ class WhileNode : public StatementNode {
+ public:
+ WhileNode(Node *e, StatementNode *s) : expr(e), statement(s) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *statement;
+ };
+
+ class ForNode : public StatementNode {
+ public:
+ ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) :
+ expr1(e1), expr2(e2), expr3(e3), stat(s) {}
+ Completion execute();
+ private:
+ Node *expr1, *expr2, *expr3;
+ StatementNode *stat;
+ };
+
+ class ForInNode : public StatementNode {
+ public:
+ ForInNode(Node *l, Node *e, StatementNode *s) :
+ init(0L), lexpr(l), expr(e), stat(s) {}
+ ForInNode(const UString *i, AssignExprNode *in, Node *e, StatementNode *s)
+ : ident(*i), init(in), lexpr(0L), expr(e), stat(s) {}
+ Completion execute();
+ private:
+ UString ident;
+ AssignExprNode *init;
+ Node *lexpr, *expr;
+ StatementNode *stat;
+ };
+
+ class ContinueNode : public StatementNode {
+ public:
+ ContinueNode() { }
+ ContinueNode(const UString *i) : ident(*i) { }
+ Completion execute();
+ private:
+ UString ident;
+ };
+
+ class BreakNode : public StatementNode {
+ public:
+ BreakNode() { }
+ BreakNode(const UString *i) : ident(*i) { }
+ Completion execute();
+ private:
+ UString ident;
+ };
+
+ class ReturnNode : public StatementNode {
+ public:
+ ReturnNode(Node *v) : value(v) {}
+ Completion execute();
+ private:
+ Node *value;
+ };
+
+ class WithNode : public StatementNode {
+ public:
+ WithNode(Node *e, StatementNode *s) : expr(e), stat(s) {}
+ Completion execute();
+ private:
+ Node *expr;
+ StatementNode *stat;
+ };
+
+ class CaseClauseNode: public Node {
+ public:
+ CaseClauseNode(Node *e, StatListNode *l) : expr(e), list(l) { }
+ KJSO evaluate();
+ Completion evalStatements();
+ private:
+ Node *expr;
+ StatListNode *list;
+ };
+
+ class ClauseListNode : public Node {
+ public:
+ ClauseListNode(CaseClauseNode *c) : cl(c), nx(0L) { }
+ ClauseListNode* append(CaseClauseNode *c);
+ KJSO evaluate() { /* should never be called */ return KJSO(); }
+ CaseClauseNode *clause() const { return cl; }
+ ClauseListNode *next() const { return nx; }
+ private:
+ CaseClauseNode *cl;
+ ClauseListNode *nx;
+ };
+
+ class CaseBlockNode: public Node {
+ public:
+ CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2)
+ : list1(l1), def(d), list2(l2) { }
+ KJSO evaluate() { /* should never be called */ return KJSO(); }
+ Completion evalBlock(const KJSO& input);
+ private:
+ ClauseListNode *list1;
+ CaseClauseNode *def;
+ ClauseListNode *list2;
+ };
+
+ class SwitchNode : public StatementNode {
+ public:
+ SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { }
+ Completion execute();
+ private:
+ Node *expr;
+ CaseBlockNode *block;
+ };
+
+ class LabelNode : public StatementNode {
+ public:
+ LabelNode(const UString *l, StatementNode *s) : label(*l), stat(s) { }
+ Completion execute();
+ private:
+ UString label;
+ StatementNode *stat;
+ };
+
+ class ThrowNode : public StatementNode {
+ public:
+ ThrowNode(Node *e) : expr(e) {}
+ Completion execute();
+ private:
+ Node *expr;
+ };
+
+ class CatchNode : public StatementNode {
+ public:
+ CatchNode(UString *i, StatementNode *b) : ident(*i), block(b) {}
+ Completion execute();
+ Completion execute(const KJSO &arg);
+ private:
+ UString ident;
+ StatementNode *block;
+ };
+
+ class FinallyNode : public StatementNode {
+ public:
+ FinallyNode(StatementNode *b) : block(b) {}
+ Completion execute();
+ private:
+ StatementNode *block;
+ };
+
+ class TryNode : public StatementNode {
+ public:
+ TryNode(StatementNode *b, Node *c = 0L, Node *f = 0L)
+ : block(b), _catch((CatchNode*)c), _final((FinallyNode*)f) {}
+ Completion execute();
+ private:
+ StatementNode *block;
+ CatchNode *_catch;
+ FinallyNode *_final;
+ };
+
+ class ParameterNode : public Node {
+ public:
+ ParameterNode(const UString *i) : id(*i), next(0L) { }
+ ParameterNode *append(const UString *i);
+ KJSO evaluate();
+ UString ident() { return id; }
+ ParameterNode *nextParam() { return next; }
+ private:
+ UString id;
+ ParameterNode *next;
+ };
+
+ // inherited by ProgramNode
+ class FunctionBodyNode : public StatementNode {
+ public:
+ FunctionBodyNode(SourceElementsNode *s);
+ Completion execute();
+ protected:
+ SourceElementsNode *source;
+ };
+
+ class FuncDeclNode : public StatementNode {
+ public:
+ FuncDeclNode(const UString *i, ParameterNode *p, FunctionBodyNode *b)
+ : ident(*i), param(p), body(b) { }
+ Completion execute() { /* empty */ return Completion(); }
+ void processFuncDecl();
+ private:
+ UString ident;
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ };
+
+ class FuncExprNode : public Node {
+ public:
+ FuncExprNode(ParameterNode *p, FunctionBodyNode *b)
+ : param(p), body(b) { }
+ KJSO evaluate();
+ private:
+ ParameterNode *param;
+ FunctionBodyNode *body;
+ };
+
+ class SourceElementNode : public StatementNode {
+ public:
+ SourceElementNode(StatementNode *s) { statement = s; function = 0L; }
+ SourceElementNode(FuncDeclNode *f) { function = f; statement = 0L;}
+ Completion execute();
+ virtual void processFuncDecl();
+ void deleteStatements();
+ private:
+ StatementNode *statement;
+ FuncDeclNode *function;
+ };
+
+ class SourceElementsNode : public StatementNode {
+ public:
+ SourceElementsNode(SourceElementNode *s1) { element = s1; elements = 0L; }
+ SourceElementsNode(SourceElementsNode *s1, SourceElementNode *s2)
+ { elements = s1; element = s2; }
+ Completion execute();
+ virtual void processFuncDecl();
+ void deleteStatements();
+ private:
+ SourceElementNode *element;
+ SourceElementsNode *elements;
+ };
+
+ class ProgramNode : public FunctionBodyNode {
+ public:
+ ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s) { }
+ void deleteGlobalStatements();
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/number_object.cpp b/WebCore/src/kdelibs/kjs/number_object.cpp
new file mode 100644
index 0000000..af37d48
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/number_object.cpp
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "number_object.h"
+
+using namespace KJS;
+
+NumberObject::NumberObject(const Object& funcProto, const Object &numProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // Number.Prototype
+ setPrototypeProperty(numProto);
+}
+
+// ECMA 15.7.3
+KJSO NumberObject::get(const UString &p) const
+{
+ double d;
+
+ if (p == "NaN")
+ d = NaN;
+ else if (p == "NEGATIVE_INFINITY")
+ d = -Inf;
+ else if (p == "POSITIVE_INFINITY")
+ d = Inf;
+ else
+ return Imp::get(p);
+
+ return Number(d);
+}
+
+// ECMA 15.7.1
+Completion NumberObject::execute(const List &args)
+{
+ Number n;
+ if (args.isEmpty())
+ n = Number(0);
+ else
+ n = args[0].toNumber();
+
+ return Completion(ReturnValue, n);
+}
+
+// ECMA 15.7.2
+Object NumberObject::construct(const List &args)
+{
+ Number n;
+ if (args.isEmpty())
+ n = Number(0);
+ else
+ n = args[0].toNumber();
+
+ return Object::create(NumberClass, n);
+}
+
+class NumberProtoFunc : public InternalFunctionImp {
+public:
+ NumberProtoFunc(int i) : id (i) { }
+ Completion execute(const List &);
+ enum { ToString, ToLocaleString, ValueOf };
+private:
+ int id;
+};
+
+// ECMA 15.7.4.2 - 15.7.4.7
+Completion NumberProtoFunc::execute(const List &)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // no generic function. "this" has to be a Number object
+ if (thisObj.isNull() || thisObj.getClass() != NumberClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ // execute "toString()" or "valueOf()", respectively
+ KJSO v = thisObj.internalValue();
+ switch (id) {
+ case ToString:
+ case ToLocaleString: /* TODO */
+ result = v.toString();
+ break;
+ case ValueOf:
+ result = v.toNumber();
+ break;
+ }
+
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.7.4
+NumberPrototype::NumberPrototype(const Object& proto)
+ : ObjectImp(NumberClass, Number(0), proto)
+{
+ // The constructor will be added later in NumberObject's constructor
+}
+
+KJSO NumberPrototype::get(const UString &p) const
+{
+ int t;
+ if (p == "toString")
+ t = NumberProtoFunc::ToString;
+ else if (p == "toLocaleString")
+ t = NumberProtoFunc::ToLocaleString;
+ else if (p == "valueOf")
+ t = NumberProtoFunc::ValueOf;
+ else
+ return Imp::get(p);
+
+ return Function(new NumberProtoFunc(t));
+}
diff --git a/WebCore/src/kdelibs/kjs/number_object.h b/WebCore/src/kdelibs/kjs/number_object.h
new file mode 100644
index 0000000..3addbdf
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/number_object.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _NUMBER_OBJECT_H_
+#define _NUMBER_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class NumberObject : public ConstructorImp {
+ public:
+ NumberObject(const Object& funcProto, const Object &numProto);
+ virtual KJSO get(const UString &p) const;
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class NumberPrototype : public ObjectImp {
+ public:
+ NumberPrototype(const Object& proto);
+ virtual KJSO get(const UString &p) const;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/object.cpp b/WebCore/src/kdelibs/kjs/object.cpp
new file mode 100644
index 0000000..adcc0fb
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/object.cpp
@@ -0,0 +1,1062 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "object.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "kjs.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "collector.h"
+#include "error_object.h"
+
+namespace KJS {
+
+#ifdef WORDS_BIGENDIAN
+ unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
+ unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
+#elif defined(arm)
+ unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
+ unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
+#else
+ unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
+ unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
+#endif
+
+ const double NaN = *(const double*) NaN_Bytes;
+ const double Inf = *(const double*) Inf_Bytes;
+ const double D16 = 65536.0;
+ const double D31 = 2147483648.0; /* TODO: remove in next version */
+ const double D32 = 4294967296.0;
+
+ // TODO: -0
+};
+
+using namespace KJS;
+
+const TypeInfo Imp::info = { "Imp", AbstractType, 0, 0, 0 };
+
+namespace KJS {
+ struct Property {
+ UString name;
+ Imp *object;
+ int attribute;
+ Property *next;
+ };
+}
+
+KJSO::KJSO()
+ : rep(0)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+}
+
+KJSO::KJSO(Imp *d)
+ : rep(d)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+}
+
+KJSO::KJSO(const KJSO &o)
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ rep = o.rep;
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+}
+
+KJSO& KJSO::operator=(const KJSO &o)
+{
+ if (rep)
+ rep->deref();
+ rep = o.rep;
+ if (rep) {
+ rep->ref();
+ rep->setGcAllowed(true);
+ }
+
+ return *this;
+}
+
+KJSO::~KJSO()
+{
+#ifdef KJS_DEBUG_MEM
+ count--;
+#endif
+
+ if (rep)
+ rep->deref();
+}
+
+bool KJSO::isDefined() const
+{
+ return !isA(UndefinedType);
+}
+
+bool KJSO::isNull() const
+{
+ return !rep;
+}
+
+Type KJSO::type() const
+{
+#ifdef KJS_VERBOSE
+ if (!rep)
+ fprintf(stderr, "requesting type of null object\n");
+#endif
+
+ return rep ? rep->typeInfo()->type : UndefinedType;
+}
+
+bool KJSO::isObject() const
+{
+ return (type() >= ObjectType);
+}
+
+bool KJSO::isA(const char *s) const
+{
+ assert(rep);
+ const TypeInfo *info = rep->typeInfo();
+
+ if (!s || !info || !info->name)
+ return false;
+
+ if (info->type == HostType && strcmp(s, "HostObject") == 0)
+ return true;
+
+ return (strcmp(s, info->name) == 0);
+}
+
+bool KJSO::derivedFrom(const char *s) const
+{
+ if (!s)
+ return false;
+
+ assert(rep);
+ const TypeInfo *info = rep->typeInfo();
+ while (info) {
+ if (info->name && strcmp(s, info->name) == 0)
+ return true;
+ info = info->base;
+ }
+
+ return false;
+}
+
+KJSO KJSO::toPrimitive(Type preferred) const
+{
+ assert(rep);
+ return rep->toPrimitive(preferred);
+}
+
+Boolean KJSO::toBoolean() const
+{
+ assert(rep);
+ return rep->toBoolean();
+}
+
+Number KJSO::toNumber() const
+{
+ assert(rep);
+ return rep->toNumber();
+}
+
+// helper function for toInteger, toInt32, toUInt32 and toUInt16
+double KJSO::round() const
+{
+ if (isA(UndefinedType)) /* TODO: see below */
+ return 0.0;
+ Number n = toNumber();
+ if (n.value() == 0.0) /* TODO: -0, NaN, Inf */
+ return 0.0;
+ double d = floor(fabs(n.value()));
+ if (n.value() < 0)
+ d *= -1;
+
+ return d;
+}
+
+// ECMA 9.4
+Number KJSO::toInteger() const
+{
+ return Number(round());
+}
+
+// ECMA 9.5
+int KJSO::toInt32() const
+{
+ double d = round();
+ double d32 = fmod(d, D32);
+
+ if (d32 >= D32 / 2.0)
+ d32 -= D32;
+
+ return static_cast<int>(d32);
+}
+
+// ECMA 9.6
+unsigned int KJSO::toUInt32() const
+{
+ double d = round();
+ double d32 = fmod(d, D32);
+
+ return static_cast<unsigned int>(d32);
+}
+
+// ECMA 9.7
+unsigned short KJSO::toUInt16() const
+{
+ double d = round();
+ double d16 = fmod(d, D16);
+
+ return static_cast<unsigned short>(d16);
+}
+
+String KJSO::toString() const
+{
+ assert(rep);
+ return rep->toString();
+}
+
+Object KJSO::toObject() const
+{
+ assert(rep);
+ if (isObject())
+ return Object(rep);
+
+ return rep->toObject();
+}
+
+bool KJSO::implementsCall() const
+{
+ return (type() == FunctionType ||
+ type() == InternalFunctionType ||
+ type() == ConstructorType ||
+ type() == DeclaredFunctionType ||
+ type() == AnonymousFunctionType);
+}
+
+// [[call]]
+KJSO KJSO::executeCall(const KJSO &thisV, const List *args)
+{
+ assert(rep);
+ assert(implementsCall());
+ return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args);
+}
+
+KJSO KJSO::executeCall(const KJSO &thisV, const List *args, const List *extraScope) const
+{
+ assert(rep);
+ assert(implementsCall());
+ return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args, extraScope);
+}
+
+void KJSO::setConstructor(KJSO c)
+{
+ put("constructor", c, DontEnum | DontDelete | ReadOnly);
+}
+
+// ECMA 8.7.1
+KJSO KJSO::getBase() const
+{
+ if (!isA(ReferenceType))
+ return Error::create(ReferenceError, I18N_NOOP("Invalid reference base"));
+
+ return ((ReferenceImp*)rep)->getBase();
+}
+
+// ECMA 8.7.2
+UString KJSO::getPropertyName() const
+{
+ if (!isA(ReferenceType))
+ // the spec wants a runtime error here. But getValue() and putValue()
+ // will catch this case on their own earlier. When returning a Null
+ // string we should be on the safe side.
+ return UString();
+
+ return ((ReferenceImp*)rep)->getPropertyName();
+}
+
+// ECMA 8.7.1
+KJSO KJSO::getValue() const
+{
+ if (!isA(ReferenceType)) {
+ return *this;
+ }
+ KJSO o = getBase();
+ if (o.isNull() || o.isA(NullType)) {
+ UString m = I18N_NOOP("Can't find variable: ") + getPropertyName();
+ return Error::create(ReferenceError, m.ascii());
+ }
+
+ return o.get(getPropertyName());
+}
+
+/* TODO: remove in next version */
+KJSO KJSO::getValue()
+{
+ return const_cast<const KJSO*>(this)->getValue();
+}
+
+// ECMA 8.7.2
+ErrorType KJSO::putValue(const KJSO& v)
+{
+ if (!isA(ReferenceType))
+ return ReferenceError;
+
+ KJSO o = getBase();
+ if (o.isA(NullType))
+ Global::current().put(getPropertyName(), v);
+ else {
+ // are we writing into an array ?
+ if (o.isA(ObjectType) && (o.toObject().getClass() == ArrayClass))
+ o.putArrayElement(getPropertyName(), v);
+ else
+ o.put(getPropertyName(), v);
+ }
+
+ return NoError;
+}
+
+void KJSO::setPrototype(const KJSO& p)
+{
+ assert(rep);
+ rep->setPrototype(p);
+}
+
+void KJSO::setPrototypeProperty(const KJSO& p)
+{
+ assert(rep);
+ put("prototype", p, DontEnum | DontDelete | ReadOnly);
+}
+
+KJSO KJSO::prototype() const
+{
+ if (rep)
+ return KJSO(rep->proto);
+ else
+ return KJSO();
+}
+
+// ECMA 8.6.2.1
+KJSO KJSO::get(const UString &p) const
+{
+ assert(rep);
+ return rep->get(p);
+}
+
+// ECMA 8.6.2.2
+void KJSO::put(const UString &p, const KJSO& v)
+{
+ assert(rep);
+ rep->put(p, v);
+}
+
+// ECMA 8.6.2.2
+void KJSO::put(const UString &p, const KJSO& v, int attr)
+{
+ static_cast<Imp*>(rep)->put(p, v, attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, double d, int attr)
+{
+ put(p, Number(d), attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, int i, int attr)
+{
+ put(p, Number(i), attr);
+}
+
+// provided for convenience.
+void KJSO::put(const UString &p, unsigned int u, int attr)
+{
+ put(p, Number(u), attr);
+}
+
+// ECMA 15.4.5.1
+void KJSO::putArrayElement(const UString &p, const KJSO& v)
+{
+ assert(rep);
+ rep->putArrayElement(p, v);
+}
+
+// ECMA 8.6.2.3
+bool KJSO::canPut(const UString &p) const
+{
+ assert(rep);
+ return rep->canPut(p);
+}
+
+// ECMA 8.6.2.4
+bool KJSO::hasProperty(const UString &p, bool recursive) const
+{
+ assert(rep);
+ return rep->hasProperty(p, recursive);
+}
+
+// ECMA 8.6.2.5
+bool KJSO::deleteProperty(const UString &p)
+{
+ assert(rep);
+ return rep->deleteProperty(p);
+}
+
+Object::Object(Imp *d) : KJSO(d) { }
+
+Object::Object(Class c) : KJSO(new ObjectImp(c)) { }
+
+Object::Object(Class c, const KJSO& v) : KJSO(new ObjectImp(c, v)) { }
+
+Object::Object(Class c, const KJSO& v, const Object& p)
+ : KJSO(new ObjectImp(c, v))
+{
+ setPrototype(p);
+}
+
+Object::~Object() { }
+
+void Object::setClass(Class c)
+{
+ static_cast<ObjectImp*>(rep)->cl = c;
+}
+
+Class Object::getClass() const
+{
+ assert(rep);
+ return static_cast<ObjectImp*>(rep)->cl;
+}
+
+void Object::setInternalValue(const KJSO& v)
+{
+ assert(rep);
+ static_cast<ObjectImp*>(rep)->val = v.imp();
+}
+
+KJSO Object::internalValue()
+{
+ assert(rep);
+ return KJSO(static_cast<ObjectImp*>(rep)->val);
+}
+
+Object Object::create(Class c)
+{
+ return Object::create(c, KJSO());
+}
+
+// factory
+Object Object::create(Class c, const KJSO& val)
+{
+ Global global(Global::current());
+ Object obj = Object();
+ obj.setClass(c);
+ obj.setInternalValue(val);
+
+ UString p = "[[";
+ switch (c) {
+ case UndefClass:
+ case ObjectClass:
+ p += "Object";
+ break;
+ case FunctionClass:
+ p += "Function";
+ break;
+ case ArrayClass:
+ p += "Array";
+ obj.put("length", Number(0), DontEnum | DontDelete);
+ break;
+ case StringClass:
+ p += "String";
+ obj.put("length", val.toString().value().size());
+ break;
+ case BooleanClass:
+ p += "Boolean";
+ break;
+ case NumberClass:
+ p += "Number";
+ break;
+ case DateClass:
+ p += "Date";
+ break;
+ case RegExpClass:
+ p += "RegExp";
+ break;
+ case ErrorClass:
+ p += "Error";
+ break;
+ }
+ p += ".prototype]]";
+
+ // KJSO prot = global.get(p).get("prototype");
+ KJSO prot = global.get(p);
+ assert(prot.isDefined());
+
+ obj.setPrototype(prot);
+ return obj;
+}
+
+Object Object::create(Class c, const KJSO& val, const Object& p)
+{
+ Global global(Global::current());
+ Object obj = Object();
+ Object prot;
+ obj.setClass(c);
+ obj.setInternalValue(val);
+
+ prot = p;
+ obj.setPrototype(prot);
+ return obj;
+}
+
+Object Object::dynamicCast(const KJSO &obj)
+{
+ // return null object on type mismatch
+ if (!obj.isA(ObjectType))
+ return Object(0L);
+
+ return Object(obj.imp());
+
+}
+
+#ifdef KJS_DEBUG_MEM
+int KJSO::count = 0;
+int Imp::count = 0;
+int List::count = 0;
+#endif
+
+Imp::Imp()
+ : refcount(0), prop(0), proto(0)
+{
+ setCreated(true);
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+}
+
+Imp::~Imp()
+{
+#ifdef KJS_DEBUG_MEM
+ assert(Collector::collecting);
+ count--;
+#endif
+
+// dangling pointer during garbage collection !
+// if (proto)
+// proto->deref();
+
+ // delete attached properties
+ Property *tmp, *p = prop;
+ while (p) {
+ tmp = p;
+ p = p->next;
+ delete tmp;
+ }
+}
+
+KJSO Imp::toPrimitive(Type preferred) const
+{
+ return defaultValue(preferred);
+ /* TODO: is there still any need to throw a runtime error _here_ ? */
+}
+
+Boolean Imp::toBoolean() const
+{
+ return Boolean();
+}
+
+Number Imp::toNumber() const
+{
+ return Number();
+}
+
+String Imp::toString() const
+{
+ return String();
+}
+
+Object Imp::toObject() const
+{
+ return Object(Error::create(TypeError).imp());
+}
+
+
+PropList* Imp::propList(PropList *first, PropList *last, bool recursive) const
+{
+ Property *pr = prop;
+ while(pr) {
+ if (!(pr->attribute & DontEnum) && !first->contains(pr->name)) {
+ if(last) {
+ last->next = new PropList();
+ last = last->next;
+ } else {
+ first = new PropList();
+ last = first;
+ }
+ last->name = pr->name;
+ }
+ pr = pr->next;
+ }
+ if (proto && recursive)
+ proto->propList(first, last);
+
+ return first;
+}
+
+KJSO Imp::get(const UString &p) const
+{
+ Property *pr = prop;
+ while (pr) {
+ if (pr->name == p) {
+ return pr->object;
+ }
+ pr = pr->next;
+ }
+
+ if (!proto)
+ return Undefined();
+
+ return proto->get(p);
+}
+
+// may be overriden
+void Imp::put(const UString &p, const KJSO& v)
+{
+ put(p, v, None);
+}
+
+// ECMA 8.6.2.2
+void Imp::put(const UString &p, const KJSO& v, int attr)
+{
+ /* TODO: check for write permissions directly w/o this call */
+ // putValue() is used for JS assignemnts. It passes no attribute.
+ // Assume that a C++ implementation knows what it is doing
+ // and let it override the canPut() check.
+ if (attr == None && !canPut(p))
+ return;
+
+ Property *pr;
+
+ if (prop) {
+ pr = prop;
+ while (pr) {
+ if (pr->name == p) {
+ // replace old value
+ pr->object = v.imp();
+ pr->attribute = attr;
+ return;
+ }
+ pr = pr->next;
+ }
+ }
+
+ // add new property
+ pr = new Property;
+ pr->name = p;
+ pr->object = v.imp();
+ pr->attribute = attr;
+ pr->next = prop;
+ prop = pr;
+}
+
+// ECMA 8.6.2.3
+bool Imp::canPut(const UString &p) const
+{
+ if (prop) {
+ const Property *pr = prop;
+ while (pr) {
+ if (pr->name == p)
+ return !(pr->attribute & ReadOnly);
+ pr = pr->next;
+ }
+ }
+ if (!proto)
+ return true;
+
+ return proto->canPut(p);
+}
+
+// ECMA 8.6.2.4
+bool Imp::hasProperty(const UString &p, bool recursive) const
+{
+ const Property *pr = prop;
+ while (pr) {
+ if (pr->name == p)
+ return true;
+ pr = pr->next;
+ }
+
+ if (!proto || !recursive)
+ return false;
+
+ return proto->hasProperty(p);
+}
+
+// ECMA 8.6.2.5
+bool Imp::deleteProperty(const UString &p)
+{
+ Property *pr = prop;
+ Property **prev = ∝
+ while (pr) {
+ if (pr->name == p) {
+ if ((pr->attribute & DontDelete))
+ return false;
+ *prev = pr->next;
+ delete pr;
+ return true;
+ }
+ prev = &(pr->next);
+ pr = pr->next;
+ }
+ return true;
+}
+
+// ECMA 15.4.5.1
+void Imp::putArrayElement(const UString &p, const KJSO& v)
+{
+ if (!canPut(p))
+ return;
+
+ if (hasProperty(p)) {
+ if (p == "length") {
+ KJSO len = get("length");
+ unsigned int oldLen = len.toUInt32();
+ unsigned int newLen = v.toUInt32();
+ // shrink array
+ for (unsigned int u = newLen; u < oldLen; u++) {
+ UString p = UString::from(u);
+ if (hasProperty(p, false))
+ deleteProperty(p);
+ }
+ put("length", Number(newLen), DontEnum | DontDelete);
+ return;
+ }
+ // put(p, v);
+ } // } else
+ put(p, v);
+
+ // array index ?
+ unsigned int idx;
+ if (!sscanf(p.cstring().c_str(), "%u", &idx)) /* TODO */
+ return;
+
+ // do we need to update/create the length property ?
+ if (hasProperty("length", false)) {
+ KJSO len = get("length");
+ if (idx < len.toUInt32())
+ return;
+ }
+
+ put("length", Number(idx+1), DontDelete | DontEnum);
+}
+
+bool Imp::implementsCall() const
+{
+ return (type() == FunctionType ||
+ type() == InternalFunctionType ||
+ type() == ConstructorType ||
+ type() == DeclaredFunctionType ||
+ type() == AnonymousFunctionType);
+}
+
+// ECMA 8.6.2.6 (new draft)
+KJSO Imp::defaultValue(Type hint) const
+{
+ KJSO o;
+
+ /* TODO String on Date object */
+ if (hint != StringType && hint != NumberType)
+ hint = NumberType;
+
+ if (hint == StringType)
+ o = get("toString");
+ else
+ o = get("valueOf");
+
+ Imp *that = const_cast<Imp*>(this);
+ if (o.implementsCall()) { // spec says "not primitive type" but ...
+ FunctionImp *f = static_cast<FunctionImp*>(o.imp());
+ KJSO s = f->executeCall(that, 0L);
+ if (!s.isObject())
+ return s;
+ }
+
+ if (hint == StringType)
+ o = get("valueOf");
+ else
+ o = get("toString");
+
+ if (o.implementsCall()) {
+ FunctionImp *f = static_cast<FunctionImp*>(o.imp());
+ KJSO s = f->executeCall(that, 0L);
+ if (!s.isObject())
+ return s;
+ }
+
+ return Error::create(TypeError, I18N_NOOP("No default value"));
+}
+
+void Imp::mark(Imp*)
+{
+ setMarked(true);
+
+ if (proto && !proto->marked())
+ proto->mark();
+
+ struct Property *p = prop;
+ while (p) {
+ if (p->object && !p->object->marked())
+ p->object->mark();
+ p = p->next;
+ }
+}
+
+bool Imp::marked() const
+{
+ return prev;
+}
+
+void Imp::setPrototype(const KJSO& p)
+{
+ if (proto)
+ proto->deref();
+ proto = p.imp();
+ if (proto)
+ proto->ref();
+}
+
+void Imp::setPrototypeProperty(const KJSO &p)
+{
+ put("prototype", p, DontEnum | DontDelete | ReadOnly);
+}
+
+void Imp::setConstructor(const KJSO& c)
+{
+ put("constructor", c, DontEnum | DontDelete | ReadOnly);
+}
+
+void* Imp::operator new(size_t s)
+{
+ return Collector::allocate(s);
+}
+
+void Imp::operator delete(void*, size_t)
+{
+ // deprecated. a mistake.
+}
+
+void Imp::operator delete(void*)
+{
+ // Do nothing. So far.
+}
+
+void Imp::setMarked(bool m)
+{
+ prev = m ? this : 0L;
+}
+
+void Imp::setGcAllowed(bool a)
+{
+ next = this;
+ if (a)
+ next++;
+}
+
+bool Imp::gcAllowed() const
+{
+ return (next && next != this);
+}
+
+void Imp::setCreated(bool c)
+{
+ next = c ? this : 0L;
+}
+
+bool Imp::created() const
+{
+ return next;
+}
+
+ObjectImp::ObjectImp(Class c) : cl(c), val(0L) { }
+
+ObjectImp::ObjectImp(Class c, const KJSO &v) : cl(c), val(v.imp()) { }
+
+ObjectImp::ObjectImp(Class c, const KJSO &v, const KJSO &p)
+ : cl(c), val(v.imp())
+{
+ setPrototype(p);
+}
+
+ObjectImp::~ObjectImp() { }
+
+Boolean ObjectImp::toBoolean() const
+{
+ return Boolean(true);
+}
+
+Number ObjectImp::toNumber() const
+{
+ return toPrimitive(NumberType).toNumber();
+}
+
+String ObjectImp::toString() const
+{
+ KJSO tmp;
+ String res;
+
+ if (hasProperty("toString") && (tmp = get("toString")).implementsCall()) {
+ // TODO live w/o hack
+ res = tmp.executeCall(KJSO(const_cast<ObjectImp*>(this)), 0L).toString();
+ } else {
+ tmp = toPrimitive(StringType);
+ res = tmp.toString();
+ }
+
+ return res;
+}
+
+const TypeInfo ObjectImp::info = { "Object", ObjectType, 0, 0, 0 };
+
+Object ObjectImp::toObject() const
+{
+ return Object(const_cast<ObjectImp*>(this));
+}
+
+KJSO ObjectImp::toPrimitive(Type preferred) const
+{
+ // ### Imp already does that now. Remove in KDE 3.0.
+ return defaultValue(preferred);
+ /* TODO: is there still any need to throw a runtime error _here_ ? */
+}
+
+void ObjectImp::mark(Imp*)
+{
+ // mark objects from the base
+ Imp::mark();
+
+ // mark internal value, if any and it has not been visited yet
+ if (val && !val->marked())
+ val->mark();
+}
+
+HostImp::HostImp()
+{
+ setPrototype(Global::current().objectPrototype());
+ //printf("HostImp::HostImp() %p\n",this);
+}
+
+HostImp::~HostImp() { }
+
+Boolean HostImp::toBoolean() const
+{
+ return Boolean(true);
+}
+
+String HostImp::toString() const
+{
+ // Exact copy of ObjectImp::toString....
+ KJSO tmp;
+ String res;
+
+ if (hasProperty("toString") && (tmp = get("toString")).implementsCall()) {
+ // TODO live w/o hack
+ res = tmp.executeCall(KJSO(const_cast<HostImp*>(this)), 0L).toString();
+ } else {
+ tmp = toPrimitive(StringType);
+ res = tmp.toString();
+ }
+
+ return res;
+}
+
+const TypeInfo HostImp::info = { "HostObject", HostType, 0, 0, 0 };
+
+Object Error::createObject(ErrorType e, const char *m, int l)
+{
+ Context *context = Context::current();
+ if (!context)
+ return Object();
+
+ Object err = ErrorObject::create(e, m, l);
+
+ if (!KJScriptImp::hadException())
+ KJScriptImp::setException(err.imp());
+
+ const struct ErrorStruct {
+ ErrorType e;
+ const char *s;
+ } errtab[] = {
+ { GeneralError, I18N_NOOP("General error") },
+ { EvalError, I18N_NOOP("Evaluation error") },
+ { RangeError, I18N_NOOP("Range error") },
+ { ReferenceError, I18N_NOOP("Reference error") },
+ { SyntaxError, I18N_NOOP("Syntax error") },
+ { TypeError, I18N_NOOP("Type error") },
+ { URIError, I18N_NOOP("URI error") },
+ { (ErrorType)0, 0 }
+ };
+
+ const char *estr = I18N_NOOP("Unknown error");
+ const ErrorStruct *estruct = errtab;
+ while (estruct->e) {
+ if (estruct->e == e) {
+ estr = estruct->s;
+ break;
+ }
+ estruct++;
+ }
+
+#ifndef NDEBUG
+ const char *msg = err.get("message").toString().value().ascii();
+ if (l >= 0)
+ fprintf(stderr, "JS: %s at line %d. %s\n", estr, l, msg);
+ else
+ fprintf(stderr, "JS: %s. %s\n", estr, msg);
+#endif
+
+ return err;
+}
+
+KJSO Error::create(ErrorType e, const char *m, int l)
+{
+ return KJSO(createObject(e, m, l).imp());
+}
diff --git a/WebCore/src/kdelibs/kjs/object.h b/WebCore/src/kdelibs/kjs/object.h
new file mode 100644
index 0000000..7daee7e
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/object.h
@@ -0,0 +1,640 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_OBJECT_H_
+#define _KJS_OBJECT_H_
+
+#include <stdlib.h>
+
+#include "ustring.h"
+
+/**
+ * @short Main namespace
+ */
+namespace KJS {
+
+ /**
+ * Types of classes derived from KJSO
+ */
+ enum Type { // main types
+ AbstractType = 1,
+ UndefinedType,
+ NullType,
+ BooleanType,
+ NumberType,
+ StringType,
+ ObjectType,
+ HostType,
+ ReferenceType,
+ CompletionType,
+ // extended types
+ FunctionType,
+ InternalFunctionType,
+ DeclaredFunctionType,
+ AnonymousFunctionType,
+ ConstructorType,
+ ActivationType
+ };
+
+ /**
+ * Property attributes.
+ */
+ enum Attribute { None = 0,
+ ReadOnly = 1 << 1,
+ DontEnum = 1 << 2,
+ DontDelete = 1 << 3,
+ Internal = 1 << 4 };
+
+ /**
+ * Types of classes derived from @ref Object.
+ */
+ enum Class { UndefClass,
+ ArrayClass,
+ StringClass,
+ BooleanClass,
+ NumberClass,
+ ObjectClass,
+ DateClass,
+ RegExpClass,
+ ErrorClass,
+ FunctionClass };
+
+ /**
+ * Completion types.
+ */
+ enum Compl { Normal, Break, Continue, ReturnValue, Throw };
+
+ /**
+ * Error codes.
+ */
+ enum ErrorType { NoError = 0,
+ GeneralError,
+ EvalError,
+ RangeError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ URIError };
+
+ extern const double NaN;
+ extern const double Inf;
+
+ // forward declarations
+ class Imp;
+ class Boolean;
+ class Number;
+ class String;
+ class Object;
+ struct Property;
+ class PropList;
+ class List;
+
+ /**
+ * @short Type information.
+ */
+ struct TypeInfo {
+ /**
+ * A string denoting the type name. Example: "Number".
+ */
+ const char *name;
+ /**
+ * One of the @ref KJS::Type enums.
+ */
+ Type type;
+ /**
+ * Pointer to the type information of the base class.
+ * NULL if there is none.
+ */
+ const TypeInfo *base;
+ /**
+ * Additional specifier for your own use.
+ */
+ int extra;
+ /**
+ * Reserved for future extensions (internal).
+ */
+ void *dummy;
+ };
+
+ /**
+ * @short Main base class for every KJS object.
+ */
+ class KJSO {
+ friend class ElementNode;
+ public:
+ /**
+ * Constructor.
+ */
+ KJSO();
+ /**
+ * @internal
+ */
+ KJSO(Imp *d);
+ /**
+ * Copy constructor.
+ */
+ KJSO(const KJSO &);
+ /*
+ * Assignment operator
+ */
+ KJSO& operator=(const KJSO &);
+ /**
+ * Destructor.
+ */
+ virtual ~KJSO();
+ /**
+ * @return True if this object is null, i.e. if there is no data attached
+ * to this object. Don't confuse this with the Null object.
+ */
+ bool isNull() const;
+ /**
+ * @return True if this objects is of any other value than Undefined.
+ */
+ bool isDefined() const;
+ /**
+ * @return the type of the object. One of the @ref KJS::Type enums.
+ */
+ Type type() const;
+ /**
+ * Check whether object is of a certain type
+ * @param t type to check for
+ */
+ bool isA(Type t) const { return (type() == t); }
+ /**
+ * Check whether object is of a certain type. Allows checking of
+ * host objects, too.
+ * @param type name (Number, Boolean etc.)
+ */
+ bool isA(const char *s) const;
+ /**
+ * Use this method when checking for objects. It's safer than checking
+ * for a single object type with @ref isA().
+ */
+ bool isObject() const;
+ /**
+ * Examine the inheritance structure of this object.
+ * @param t Name of the base class.
+ * @return True if object is of type t or a derived from such a type.
+ */
+ bool derivedFrom(const char *s) const;
+
+ /**
+ * @return Conversion to primitive type (Undefined, Boolean, Number
+ * or String)
+ * @param preferred Optional hint. Either StringType or NumberType.
+ */
+ KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
+ /**
+ * @return Conversion to Boolean type.
+ */
+ Boolean toBoolean() const; // ECMA 9.2
+ /**
+ * @return Conversion to Number type.
+ */
+ Number toNumber() const; // ECMA 9.3
+ /**
+ * @return Conversion to double. 0.0 if conversion failed.
+ */
+ double round() const;
+ /**
+ * @return Conversion to Number type containing an integer value.
+ */
+ Number toInteger() const; // ECMA 9.4
+ /**
+ * @return Conversion to signed integer value.
+ */
+ int toInt32() const; // ECMA 9.5
+ /**
+ * @return Conversion to unsigned integer value.
+ */
+ unsigned int toUInt32() const; // ECMA 9.6
+ /**
+ * @return Conversion to unsigned short value.
+ */
+ unsigned short toUInt16() const; // ECMA 9.7
+ /**
+ * @return Conversion to String type.
+ */
+ String toString() const; // ECMA 9.8
+ /**
+ * @return Conversion to Object type.
+ */
+ Object toObject() const; // ECMA 9.9
+
+ // Properties
+ /**
+ * Set the internal [[Prototype]] property of this object.
+ * @param p A prototype object.
+ */
+ void setPrototype(const KJSO &p);
+ /**
+ * Set the "prototype" property of this object. Different from
+ * the internal [[Prototype]] property.
+ * @param p A prototype object.
+ */
+ void setPrototypeProperty(const KJSO &p);
+ /**
+ * @return The internal [[prototype]] property.
+ */
+ KJSO prototype() const;
+ /**
+ * The internal [[Get]] method.
+ * @return The value of property p.
+ */
+ KJSO get(const UString &p) const;
+ /**
+ * The internal [[HasProperty]] method.
+ * @param p Property name.
+ * @param recursive Indicates whether prototypes are searched as well.
+ * @return Boolean value indicating whether the object already has a
+ * member with the given name p.
+ */
+ bool hasProperty(const UString &p, bool recursive = true) const;
+ /**
+ * The internal [[Put]] method. Sets the specified property to the value v.
+ * @param p Property name.
+ * @param v Value.
+ */
+ void put(const UString &p, const KJSO& v);
+ /**
+ * The internal [[CanPut]] method.
+ * @param p Property name.
+ * @return A boolean value indicating whether a [[Put]] operation with
+ * p succeed.
+ */
+ bool canPut(const UString &p) const;
+ /**
+ * The internal [[Delete]] method. Removes the specified property from
+ * the object.
+ * @param p Property name.
+ * @return True if the property was deleted successfully or didn't exist
+ * in the first place. False if the DontDelete attribute was set.
+ */
+ bool deleteProperty(const UString &p);
+ /**
+ * Same as above put() method except the additional attribute. Right now,
+ * this only works with native types as Host Objects don't reimplement
+ * this method.
+ * @param attr One of @ref KJS::Attribute.
+ */
+ void put(const UString &p, const KJSO& v, int attr);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * a double value.
+ */
+ void put(const UString &p, double d, int attr = None);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * an integer value.
+ */
+ void put(const UString &p, int i, int attr = None);
+ /**
+ * Convenience function for adding a Number property constructed from
+ * an unsigned integer value.
+ */
+ void put(const UString &p, unsigned int u, int attr = None);
+
+ /**
+ * Reference method.
+ * @return Reference base if object is a reference. Throws
+ * a ReferenceError otherwise.
+ */
+ KJSO getBase() const;
+ /**
+ * Reference method.
+ * @return Property name of a reference. Null string if object is not
+ * a reference.
+ */
+ UString getPropertyName() const;
+ /**
+ * Reference method.
+ * @return Referenced value. This object if no reference.
+ */
+ KJSO getValue() const;
+ KJSO getValue(); /* TODO: remove in next version */
+ /**
+ * Reference method. Set referenced value to v.
+ */
+ ErrorType putValue(const KJSO& v);
+
+ /**
+ * @return True if object supports @ref executeCall() method. That's the
+ * case for all objects derived from FunctionType.
+ */
+ bool implementsCall() const;
+ /**
+ * Execute function implemented via the @ref Function::execute() method.
+ *
+ * Note: check availability via @ref implementsCall() beforehand.
+ * @param thisV Object serving as the 'this' value.
+ * @param args Pointer to the list of arguments or null.
+ * @return Result of the function call.
+ */
+ KJSO executeCall(const KJSO &thisV, const List *args);
+ KJSO executeCall(const KJSO &thisV, const List *args, const List *extraScope) const;
+
+ /**
+ * Set this object's constructor.
+ */
+ void setConstructor(KJSO c);
+
+ /**
+ * @return A Pointer to the internal implementation.
+ */
+ Imp *imp() const { return rep; }
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ protected:
+ /**
+ * Pointer to the internal implementation.
+ */
+ Imp *rep;
+
+ private:
+ void putArrayElement(const UString &p, const KJSO &v);
+ }; // end of KJSO
+
+ /**
+ * @short Base for all implementation classes.
+ */
+ class Imp {
+ friend class KJSO;
+ friend class Collector;
+ friend class ForInNode;
+ friend class Debugger;
+ public:
+ Imp();
+ public:
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
+ virtual Boolean toBoolean() const; // ECMA 9.2
+ virtual Number toNumber() const; // ECMA 9.3
+ virtual String toString() const; // ECMA 9.8
+ virtual Object toObject() const; // ECMA 9.9
+
+ // properties
+ virtual KJSO get(const UString &p) const;
+ virtual bool hasProperty(const UString &p, bool recursive = true) const;
+ virtual void put(const UString &p, const KJSO& v);
+ void put(const UString &p, const KJSO& v, int attr);
+ virtual bool canPut(const UString &p) const;
+ virtual bool deleteProperty(const UString &p);
+ virtual KJSO defaultValue(Type hint) const;
+
+ bool implementsCall() const;
+
+ /**
+ * @internal Reserved for mark & sweep garbage collection
+ */
+ virtual void mark(Imp *imp = 0L);
+ bool marked() const;
+
+ Type type() const { return typeInfo()->type; }
+ /**
+ * @return The TypeInfo struct describing this object.
+ */
+ virtual const TypeInfo* typeInfo() const { return &info; }
+
+ void setPrototype(const KJSO& p);
+ Imp* prototype() const { return proto; }
+ void setPrototypeProperty(const KJSO &p);
+ void setConstructor(const KJSO& c);
+
+ void* operator new(size_t);
+ void operator delete(void*);
+ /**
+ * @deprecated
+ */
+ void operator delete(void*, size_t);
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ protected:
+ virtual ~Imp();
+ private:
+ Imp(const Imp&);
+ Imp& operator=(const Imp&);
+ void putArrayElement(const UString &p, const KJSO& v);
+
+ /**
+ * Get the property names for this object. To be used by for .. in loops
+ * @return The (pointer to the) first element of a PropList, to be deleted
+ * by the caller, or 0 if there are no enumerable properties
+ */
+ PropList *propList(PropList *first = 0L, PropList *last = 0L,
+ bool recursive = true) const;
+
+ public:
+ // reference counting mechanism
+ inline Imp* ref() { refcount++; return this; }
+ inline bool deref() { return (!--refcount); }
+ unsigned int refcount;
+
+ private:
+ Property *prop;
+ Imp *proto;
+ static const TypeInfo info;
+
+ // reserved for memory managment - currently used as flags for garbage collection
+ // (prev != 0) = marked, (next != 0) = created, (next != this) = created and gc allowed
+ Imp *prev, *next;
+ // for future extensions
+ class ImpInternal;
+ ImpInternal *internal;
+
+ void setMarked(bool m);
+ void setGcAllowed(bool a);
+ bool gcAllowed() const;
+ void setCreated(bool c);
+ bool created() const;
+ };
+
+ /**
+ * @short General implementation class for Objects
+ */
+ class ObjectImp : public Imp {
+ friend class Object;
+ public:
+ ObjectImp(Class c);
+ ObjectImp(Class c, const KJSO &v);
+ ObjectImp(Class c, const KJSO &v, const KJSO &p);
+ virtual ~ObjectImp();
+ virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
+ virtual Boolean toBoolean() const;
+ virtual Number toNumber() const;
+ virtual String toString() const;
+ virtual Object toObject() const;
+
+ virtual const TypeInfo* typeInfo() const { return &info; }
+ static const TypeInfo info;
+ /**
+ * @internal Reimplemenation of @ref Imp::mark().
+ */
+ virtual void mark(Imp *imp = 0L);
+ private:
+ Class cl;
+ Imp *val;
+ };
+
+ /**
+ * @short Object class encapsulating an internal value.
+ */
+ class Object : public KJSO {
+ public:
+ Object(Imp *d);
+ Object(Class c = UndefClass);
+ Object(Class c, const KJSO& v);
+ Object(Class c, const KJSO& v, const Object& p);
+ virtual ~Object();
+ void setClass(Class c);
+ Class getClass() const;
+ void setInternalValue(const KJSO& v);
+ KJSO internalValue();
+ static Object create(Class c);
+ static Object create(Class c, const KJSO& val);
+ static Object create(Class c, const KJSO& val, const Object &p);
+ static Object dynamicCast(const KJSO &obj);
+ };
+
+ /**
+ * @short Implementation base class for Host Objects.
+ */
+ class HostImp : public Imp {
+ public:
+ HostImp();
+ virtual ~HostImp();
+ virtual const TypeInfo* typeInfo() const { return &info; }
+
+ virtual Boolean toBoolean() const;
+ virtual String toString() const;
+
+ static const TypeInfo info;
+ };
+
+ class KJScriptImp;
+ /**
+ * The Global object represents the global namespace. It holds the native
+ * objects like String and functions like eval().
+ *
+ * It also serves as a container for variables created by the user, i.e.
+ * the statement
+ * <pre>
+ * var i = 2;
+ * </pre>
+ * will basically perform a Global::current().put("i", Number(2)); operation.
+ *
+ * @short Unique global object containing initial native properties.
+ */
+ class Global : public Object {
+ friend class KJScriptImp;
+ public:
+ /**
+ * Constructs a Global object. This is done by the interpreter once and
+ * there should be no need to create an instance on your own. Usually,
+ * you'll just want to access the current instance.
+ * For example like this:
+ * <pre>
+ * Global global(Global::current());
+ * KJSO proto = global.objectPrototype();
+ * </pre>
+ */
+ Global();
+ /**
+ * Destruct the Global object.
+ */
+ virtual ~Global();
+ /**
+ * @return A reference to the Global object belonging to the current
+ * interpreter instance.
+ */
+ static Global current();
+ /**
+ * @return A handle to Object.prototype.
+ */
+ KJSO objectPrototype() const;
+ /**
+ * @return A handle to Function.prototype.
+ */
+ KJSO functionPrototype() const;
+ /**
+ * Set a filter object that will intercept all put() and get() calls
+ * to the global object. If this object returns Undefined on get() the
+ * request will be passed on the global object.
+ * @deprecated
+ */
+ void setFilter(const KJSO &f);
+ /**
+ * Return a handle to the filter object (see @ref setFilter()).
+ * Null if no filter has been installed.
+ * @deprecated
+ */
+ KJSO filter() const;
+ /**
+ * Returns the extra user data set for this global object. Null by default.
+ * Typical usage if you need to query any info related to the currently
+ * running interpreter:
+ *
+ * MyMainWindow *m = (MyMainWindow*)Global::current().extra();
+ */
+ void *extra() const;
+ /**
+ * Set the extra user data for this global object. It's not used by the
+ * interpreter itself and can therefore be used to bind arbitrary data
+ * to each interpreter instance.
+ */
+ void setExtra(void *e);
+ private:
+ Global(void *);
+ void init();
+ void clear();
+ };
+
+ /**
+ * @short Factory methods for error objects.
+ */
+ class Error {
+ public:
+ /**
+ * Factory method for error objects. The error will be registered globally
+ * and the execution will continue as if a "throw" statement was
+ * encountered.
+ * @param e Type of error.
+ * @param m Optional error message.
+ * @param l Optional line number.
+ */
+ static KJSO create(ErrorType e, const char *m = 0, int l = -1);
+ /**
+ * Same as above except the different return type (which is not casted
+ * here).
+ */
+ static Object createObject(ErrorType e, const char *m = 0, int l = -1);
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/object_object.cpp b/WebCore/src/kdelibs/kjs/object_object.cpp
new file mode 100644
index 0000000..80f98ed
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/object_object.cpp
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "object_object.h"
+#include "types.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+ObjectObject::ObjectObject(const Object &funcProto, const Object &objProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.2.3.1
+ setPrototypeProperty(objProto);
+}
+
+Completion ObjectObject::execute(const List &args)
+{
+ KJSO result;
+
+ List argList;
+ if (args.isEmpty()) {
+ result = construct(argList);
+ } else {
+ KJSO arg = args[0];
+ if (arg.isA(NullType) || arg.isA(UndefinedType)) {
+ argList.append(arg);
+ result = construct(argList);
+ } else
+ result = arg.toObject();
+ }
+ return Completion(ReturnValue, result);
+}
+
+// ECMA 15.2.2
+Object ObjectObject::construct(const List &args)
+{
+ // if no arguments have been passed ...
+ if (args.isEmpty())
+ return Object::create(ObjectClass);
+
+ KJSO arg = *args.begin();
+ Object obj = Object::dynamicCast(arg);
+ if (!obj.isNull()) {
+ /* TODO: handle host objects */
+ return obj;
+ }
+
+ switch (arg.type()) {
+ case StringType:
+ case BooleanType:
+ case NumberType:
+ return arg.toObject();
+ default:
+ assert(!"unhandled switch case in ObjectConstructor");
+ case NullType:
+ case UndefinedType:
+ return Object::create(ObjectClass);
+ }
+}
+
+ObjectPrototype::ObjectPrototype()
+ : ObjectImp(ObjectClass)
+{
+ // the spec says that [[Property]] should be `null'.
+ // Not sure if Null or C's NULL is needed.
+}
+
+bool ObjectPrototype::hasProperty(const UString &p, bool recursive) const
+{
+ if ( p == "toString" || p == "valueOf" )
+ return true;
+ return /*recursive &&*/ ObjectImp::hasProperty(p, recursive);
+}
+
+KJSO ObjectPrototype::get(const UString &p) const
+{
+ if (p == "toString")
+ return Function(new ObjectProtoFunc(ToString));
+ else if (p == "valueOf")
+ return Function(new ObjectProtoFunc(ValueOf));
+ else
+ return Imp::get(p);
+}
+
+ObjectProtoFunc::ObjectProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.2.4.2 + 15.2.4.3
+Completion ObjectProtoFunc::execute(const List &)
+{
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ /* TODO: what to do with non-objects. Is this possible at all ? */
+ // Yes, this happens with Host Object at least (David)
+ if (thisObj.isNull()) {
+ UString str = "[object ";
+ str += thisValue().isNull() ? "null" : thisValue().imp()->typeInfo()->name;
+ str += "]";
+ return Completion(ReturnValue, String(str));
+ }
+
+ // valueOf()
+ if (id == ObjectPrototype::ValueOf)
+ /* TODO: host objects*/
+ return Completion(ReturnValue, thisObj);
+
+ // toString()
+ UString str;
+ switch(thisObj.getClass()) {
+ case StringClass:
+ str = "[object String]";
+ break;
+ case BooleanClass:
+ str = "[object Boolean]";
+ break;
+ case NumberClass:
+ str = "[object Number]";
+ break;
+ case ObjectClass:
+ {
+ str = "[object ";
+ str += thisValue().isNull() ? "Object" : thisValue().imp()->typeInfo()->name;
+ str += "]";
+ break;
+ }
+ default:
+ str = "[undefined object]";
+ }
+
+ return Completion(ReturnValue, String(str));
+}
diff --git a/WebCore/src/kdelibs/kjs/object_object.h b/WebCore/src/kdelibs/kjs/object_object.h
new file mode 100644
index 0000000..7f8703e
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/object_object.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _OBJECT_OBJECT_H_
+#define _OBJECT_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class ObjectObject : public ConstructorImp {
+ public:
+ ObjectObject(const Object &funcProto, const Object &objProto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class ObjectPrototype : public ObjectImp {
+ public:
+ ObjectPrototype();
+ bool hasProperty(const UString &p, bool recursive) const;
+ KJSO get(const UString &p) const;
+ enum { ToString, ValueOf };
+ };
+
+ class ObjectProtoFunc : public InternalFunctionImp {
+ public:
+ ObjectProtoFunc(int i);
+ Completion execute(const List &);
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/operations.cpp b/WebCore/src/kdelibs/kjs/operations.cpp
new file mode 100644
index 0000000..95e6022
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/operations.cpp
@@ -0,0 +1,224 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifndef HAVE_FLOAT_H /* just for !Windows */
+#define HAVE_FLOAT_H 0
+#define HAVE_FUNC__FINITE 0
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+
+#ifndef HAVE_FUNC_ISINF
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#endif /* HAVE_FUNC_ISINF */
+
+#if HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+#include "object.h"
+#include "types.h"
+#include "operations.h"
+
+using namespace KJS;
+
+bool KJS::isNaN(double d)
+{
+#ifdef HAVE_FUNC_ISNAN
+ return isnan(d);
+#elif defined HAVE_FLOAT_H
+ return _isnan(d) != 0;
+#else
+ return !(d == d);
+#endif
+}
+
+bool KJS::isInf(double d)
+{
+#if defined(HAVE_FUNC_ISINF)
+ return isinf(d);
+#elif HAVE_FUNC_FINITE
+ return finite(d) == 0 && d == d;
+#elif HAVE_FUNC__FINITE
+ return _finite(d) == 0 && d == d;
+#else
+ return false;
+#endif
+}
+
+// ECMA 11.9.3
+bool KJS::equal(const KJSO& v1, const KJSO& v2)
+{
+ Type t1 = v1.type();
+ Type t2 = v2.type();
+
+ if (t1 == t2) {
+ if (t1 == UndefinedType || t1 == NullType)
+ return true;
+ if (t1 == NumberType)
+ return (v1.toNumber().value() == v2.toNumber().value()); /* TODO: NaN, -0 ? */
+ if (t1 == StringType)
+ return (v1.toString().value() == v2.toString().value());
+ if (t1 == BooleanType)
+ return (v1.toBoolean().value() == v2.toBoolean().value());
+ if (t1 == HostType) {
+ KJSO h1 = v1.get("[[==]]");
+ KJSO h2 = v2.get("[[==]]");
+ if (!h1.isA(UndefinedType) && !h2.isA(UndefinedType))
+ return equal(h1, h2);
+ }
+ return (v1.imp() == v2.imp());
+ }
+
+ // different types
+ if ((t1 == NullType && t2 == UndefinedType) || (t1 == UndefinedType && t2 == NullType))
+ return true;
+ if (t1 == NumberType && t2 == StringType) {
+ Number n2 = v2.toNumber();
+ return equal(v1, n2);
+ }
+ if ((t1 == StringType && t2 == NumberType) || t1 == BooleanType) {
+ Number n1 = v1.toNumber();
+ return equal(n1, v2);
+ }
+ if (t2 == BooleanType) {
+ Number n2 = v2.toNumber();
+ return equal(v1, n2);
+ }
+ if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType) {
+ KJSO p2 = v2.toPrimitive();
+ return equal(v1, p2);
+ }
+ if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType)) {
+ KJSO p1 = v1.toPrimitive();
+ return equal(p1, v2);
+ }
+
+ return false;
+}
+
+bool KJS::strictEqual(const KJSO &v1, const KJSO &v2)
+{
+ Type t1 = v1.type();
+ Type t2 = v2.type();
+
+ if (t1 != t2)
+ return false;
+ if (t1 == UndefinedType || t1 == NullType)
+ return true;
+ if (t1 == NumberType) {
+ double n1 = v1.toNumber().value();
+ double n2 = v2.toNumber().value();
+ if (isNaN(n1) || isNaN(n2))
+ return false;
+ if (n1 == n2)
+ return true;
+ /* TODO: +0 and -0 */
+ return false;
+ } else if (t1 == StringType) {
+ return v1.toString().value() == v2.toString().value();
+ } else if (t2 == BooleanType) {
+ return v1.toBoolean().value() == v2.toBoolean().value();
+ }
+ if (v1.imp() == v2.imp())
+ return true;
+ /* TODO: joined objects */
+
+ return false;
+}
+
+int KJS::relation(const KJSO& v1, const KJSO& v2)
+{
+ KJSO p1 = v1.toPrimitive(NumberType);
+ KJSO p2 = v2.toPrimitive(NumberType);
+
+ if (p1.isA(StringType) && p2.isA(StringType))
+ return p1.toString().value() < p2.toString().value() ? 1 : 0;
+
+ Number n1 = p1.toNumber();
+ Number n2 = p2.toNumber();
+ /* TODO: check for NaN */
+ if (n1.value() == n2.value())
+ return 0;
+ /* TODO: +0, -0 and Infinity */
+ return (n1.value() < n2.value());
+}
+
+double KJS::max(double d1, double d2)
+{
+ /* TODO: check for NaN */
+ return (d1 > d2) ? d1 : d2;
+}
+
+double KJS::min(double d1, double d2)
+{
+ /* TODO: check for NaN */
+ return (d1 < d2) ? d1 : d2;
+}
+
+// ECMA 11.6
+KJSO KJS::add(const KJSO &v1, const KJSO &v2, char oper)
+{
+ KJSO p1 = v1.toPrimitive();
+ KJSO p2 = v2.toPrimitive();
+
+ if ((p1.isA(StringType) || p2.isA(StringType)) && oper == '+') {
+ String s1 = p1.toString();
+ String s2 = p2.toString();
+
+ UString s = s1.value() + s2.value();
+
+ return String(s);
+ }
+
+ Number n1 = p1.toNumber();
+ Number n2 = p2.toNumber();
+
+ if (oper == '+')
+ return Number(n1.value() + n2.value());
+ else
+ return Number(n1.value() - n2.value());
+}
+
+// ECMA 11.5
+KJSO KJS::mult(const KJSO &v1, const KJSO &v2, char oper)
+{
+ Number n1 = v1.toNumber();
+ Number n2 = v2.toNumber();
+
+ double result;
+
+ if (oper == '*')
+ result = n1.value() * n2.value();
+ else if (oper == '/')
+ result = n1.value() / n2.value();
+ else
+ result = fmod(n1.value(), n2.value());
+
+ return Number(result);
+}
diff --git a/WebCore/src/kdelibs/kjs/operations.h b/WebCore/src/kdelibs/kjs/operations.h
new file mode 100644
index 0000000..d3b0246
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/operations.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_OPERATIONS_H_
+#define _KJS_OPERATIONS_H_
+
+#include "object.h"
+
+namespace KJS {
+
+ /**
+ * @return True if d is not a number (platform support required).
+ */
+ bool isNaN(double d);
+ /**
+ * @return True if d is infinite (platform support required).
+ */
+ bool isInf(double d);
+ bool equal(const KJSO& v1, const KJSO& v2);
+ bool strictEqual(const KJSO &v1, const KJSO &v2);
+ /**
+ * This operator performs an abstract relational comparision of the two
+ * arguments that can be of arbitrary type. If possible, conversions to the
+ * string or number type will take place before the comparison.
+ *
+ * @return 1 if v1 is "less-than" v2, 0 if the relation is "greater-than-or-
+ * equal". -1 if the result is undefined.
+ */
+ int relation(const KJSO& v1, const KJSO& v2);
+ double max(double d1, double d2);
+ double min(double d1, double d2);
+ /**
+ * Additive operator. Either performs an addition or substraction of v1
+ * and v2.
+ * @param oper '+' or '-' for an addition or substraction, respectively.
+ * @return The result of the operation.
+ */
+ KJSO add(const KJSO &v1, const KJSO &v2, char oper);
+ /**
+ * Multiplicative operator. Either multiplies/divides v1 and v2 or
+ * calculates the remainder from an division.
+ * @param oper '*', '/' or '%' for a multiplication, division or
+ * modulo operation.
+ * @return The result of the operation.
+ */
+ KJSO mult(const KJSO &v1, const KJSO &v2, char oper);
+
+};
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/regexp.cpp b/WebCore/src/kdelibs/kjs/regexp.cpp
new file mode 100644
index 0000000..84368e7
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/regexp.cpp
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+
+#include "object.h"
+#include "regexp.h"
+
+using namespace KJS;
+
+RegExp::RegExp(const UString &p, int f)
+ : pattern(p), flags(f)
+{
+#ifdef REG_EXTENDED
+ regcomp(&preg, p.ascii(), REG_EXTENDED);
+#else
+ regcomp(&preg, p.ascii(), 0);
+#endif
+ /* TODO use flags, check for errors */
+}
+
+RegExp::~RegExp()
+{
+ /* TODO: is this really okay after an error ? */
+ regfree(&preg);
+}
+
+UString RegExp::match(const UString &s, int i, int *pos)
+{
+ regmatch_t rmatch[10];
+
+ if (i < 0)
+ i = 0;
+
+ if (i > s.size() || s.isNull() ||
+ regexec(&preg, s.ascii() + i, 10, rmatch, 0)) {
+ if (pos)
+ *pos = -1;
+ return UString::null;
+ }
+
+ if (pos)
+ *pos = rmatch[0].rm_so + i;
+ return s.substr(rmatch[0].rm_so + i, rmatch[0].rm_eo - rmatch[0].rm_so);
+}
+
+bool RegExp::test(const UString &s, int)
+{
+ int r = regexec(&preg, s.ascii(), 0, 0, 0);
+
+ return r == 0;
+}
diff --git a/WebCore/src/kdelibs/kjs/regexp.h b/WebCore/src/kdelibs/kjs/regexp.h
new file mode 100644
index 0000000..9a4b2b2
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/regexp.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KJS_REGEXP_H_
+#define _KJS_REGEXP_H_
+
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef HAVE_PCREPOSIX
+#include <pcreposix.h>
+#else // POSIX regex - not so good...
+extern "C" { // bug with some libc5 distributions
+#include <regex.h>
+}
+#endif //HAVE_PCREPOSIX
+
+#include "ustring.h"
+
+namespace KJS {
+
+ class RegExp {
+ public:
+ enum { None, Global, IgnoreCase, Multiline };
+ RegExp(const UString &p, int f = None);
+ ~RegExp();
+ UString match(const UString &s, int i = -1, int *pos = 0L);
+ bool test(const UString &s, int i = -1);
+ private:
+ const UString &pattern;
+ int flags;
+ regex_t preg;
+
+ RegExp();
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/regexp_object.cpp b/WebCore/src/kdelibs/kjs/regexp_object.cpp
new file mode 100644
index 0000000..b7e6b12
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/regexp_object.cpp
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "internal.h"
+#include "regexp.h"
+#include "regexp_object.h"
+
+using namespace KJS;
+
+RegExpObject::RegExpObject(const Object& funcProto, const Object ®Proto)
+ : ConstructorImp(funcProto, 2)
+{
+ // ECMA 15.10.5.1 RegExp.prototype
+ setPrototypeProperty(regProto);
+}
+
+// ECMA 15.9.2
+Completion RegExpObject::execute(const List &)
+{
+ return Completion(ReturnValue, Undefined());
+}
+
+// ECMA 15.9.3
+Object RegExpObject::construct(const List &args)
+{
+ /* TODO: regexp arguments */
+ String p = args[0].toString();
+ String f = args[1].toString();
+ UString flags = f.value();
+
+ RegExpImp *dat = new RegExpImp();
+ Object obj(dat); // protect from GC
+
+ bool global = (flags.find("g") >= 0);
+ bool ignoreCase = (flags.find("i") >= 0);
+ bool multiline = (flags.find("m") >= 0);
+ /* TODO: throw an error on invalid flags */
+
+ dat->put("global", Boolean(global));
+ dat->put("ignoreCase", Boolean(ignoreCase));
+ dat->put("multiline", Boolean(multiline));
+
+ dat->put("source", String(p.value()));
+ dat->put("lastIndex", 0, DontDelete | DontEnum);
+
+ dat->setRegExp(new RegExp(p.value() /* TODO flags */));
+ obj.setClass(RegExpClass);
+ obj.setPrototype(Global::current().get("[[RegExp.prototype]]"));
+
+ return obj;
+}
+
+// ECMA 15.9.4
+RegExpPrototype::RegExpPrototype(const Object& proto)
+ : ObjectImp(RegExpClass, String(""), proto)
+{
+ // The constructor will be added later in RegExpObject's constructor
+}
+
+KJSO RegExpPrototype::get(const UString &p) const
+{
+ int id = -1;
+ if (p == "exec")
+ id = RegExpProtoFunc::Exec;
+ else if (p == "test")
+ id = RegExpProtoFunc::Test;
+ else if (p == "toString")
+ id = RegExpProtoFunc::ToString;
+
+ if (id >= 0)
+ return Function(new RegExpProtoFunc(id));
+ else
+ return Imp::get(p);
+}
+
+Completion RegExpProtoFunc::execute(const List &args)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ if (thisObj.getClass() != RegExpClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+
+ RegExp *re = static_cast<RegExpImp*>(thisObj.imp())->regExp();
+ String s;
+ KJSO lastIndex, tmp;
+ UString str;
+ int length, i;
+ switch (id) {
+ case Exec:
+ case Test:
+ s = args[0].toString();
+ length = s.value().size();
+ lastIndex = thisObj.get("lastIndex");
+ i = lastIndex.toInt32();
+ tmp = thisObj.get("global");
+ if (tmp.toBoolean().value() == false)
+ i = 0;
+ if (i < 0 || i > length) {
+ thisObj.put("lastIndex", 0);
+ result = Null();
+ break;
+ }
+ str = re->match(s.value(), i);
+ if (id == Test) {
+ result = Boolean(str.size() != 0);
+ break;
+ }
+ /* TODO complete */
+ result = String(str);
+ break;
+ case ToString:
+ s = thisObj.get("source").toString();
+ str = "/";
+ str += s.value();
+ str += "/";
+ result = String(str);
+ break;
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/WebCore/src/kdelibs/kjs/regexp_object.h b/WebCore/src/kdelibs/kjs/regexp_object.h
new file mode 100644
index 0000000..a5af288
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/regexp_object.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _REGEXP_OBJECT_H_
+#define _REGEXP_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class RegExpObject : public ConstructorImp {
+ public:
+ RegExpObject(const Object& funcProto, const Object ®Proto);
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class RegExpPrototype : public ObjectImp {
+ public:
+ RegExpPrototype(const Object& proto);
+ KJSO get(const UString &p) const;
+ };
+
+ class RegExpProtoFunc : public InternalFunctionImp {
+ public:
+ RegExpProtoFunc(int i) : id(i) { }
+ Completion execute(const List &);
+ enum { Exec, Test, ToString };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/string_object.cpp b/WebCore/src/kdelibs/kjs/string_object.cpp
new file mode 100644
index 0000000..8e088bc
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/string_object.cpp
@@ -0,0 +1,419 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kjs.h"
+#include "operations.h"
+#include "types.h"
+#include "regexp.h"
+#include "string_object.h"
+#include <stdio.h>
+
+using namespace KJS;
+
+StringObject::StringObject(const Object &funcProto, const Object &stringProto)
+ : ConstructorImp(funcProto, 1)
+{
+ // ECMA 15.5.3.1 String.prototype
+ setPrototypeProperty(stringProto);
+}
+
+KJSO StringObject::get(const UString &p) const
+{
+ if (p == "fromCharCode")
+ return Function(new StringObjectFunc());
+ else
+ return Imp::get(p);
+}
+
+// ECMA 15.5.1
+Completion StringObject::execute(const List &args)
+{
+ KJSO v;
+ String s;
+
+ if (args.isEmpty())
+ s = String("");
+ else {
+ v = args[0];
+ s = v.toString();
+ }
+
+ return Completion(ReturnValue, s);
+}
+
+// ECMA 15.5.2
+Object StringObject::construct(const List &args)
+{
+ String s;
+ if (args.size() > 0)
+ s = args.begin()->toString();
+ else
+ s = String("");
+
+ return Object::create(StringClass, s);
+}
+
+// ECMA 15.5.3.2 fromCharCode()
+Completion StringObjectFunc::execute(const List &args)
+{
+ UString s;
+ if (args.size()) {
+ UChar *buf = new UChar[args.size()];
+ UChar *p = buf;
+ ListIterator it = args.begin();
+ while (it != args.end()) {
+ unsigned short u = it->toUInt16();
+ *p++ = UChar(u);
+ it++;
+ }
+ s = UString(buf, args.size(), false);
+ } else
+ s = "";
+
+ return Completion(ReturnValue, String(s));
+}
+
+// ECMA 15.5.4
+StringPrototype::StringPrototype(const Object& proto)
+ : ObjectImp(StringClass, String(""), proto)
+{
+ // The constructor will be added later in StringObject's constructor
+}
+
+KJSO StringPrototype::get(const UString &p) const
+{
+ int id;
+
+ if (p == "toString")
+ id = StringProtoFunc::ToString;
+ else if (p == "valueOf")
+ id = StringProtoFunc::ValueOf;
+ else if (p == "charAt")
+ id = StringProtoFunc::CharAt;
+ else if (p == "charCodeAt")
+ id = StringProtoFunc::CharCodeAt;
+ else if (p == "indexOf")
+ id = StringProtoFunc::IndexOf;
+ else if (p == "lastIndexOf")
+ id = StringProtoFunc::LastIndexOf;
+ else if (p == "match")
+ id = StringProtoFunc::Match;
+ else if (p == "replace")
+ id = StringProtoFunc::Replace;
+ else if (p == "search")
+ id = StringProtoFunc::Search;
+ else if (p == "split")
+ id = StringProtoFunc::Split;
+ else if (p == "substr")
+ id = StringProtoFunc::Substr;
+ else if (p == "substring")
+ id = StringProtoFunc::Substring;
+ else if (p == "toLowerCase")
+ id = StringProtoFunc::ToLowerCase;
+ else if (p == "toUpperCase")
+ id = StringProtoFunc::ToUpperCase;
+#ifndef KJS_PURE_ECMA
+ else if (p == "big")
+ id = StringProtoFunc::Big;
+ else if (p == "small")
+ id = StringProtoFunc::Small;
+ else if (p == "blink")
+ id = StringProtoFunc::Blink;
+ else if (p == "bold")
+ id = StringProtoFunc::Bold;
+ else if (p == "fixed")
+ id = StringProtoFunc::Fixed;
+ else if (p == "italics")
+ id = StringProtoFunc::Italics;
+ else if (p == "strike")
+ id = StringProtoFunc::Strike;
+ else if (p == "sub")
+ id = StringProtoFunc::Sub;
+ else if (p == "sup")
+ id = StringProtoFunc::Sup;
+ else if (p == "fontcolor")
+ id = StringProtoFunc::Fontcolor;
+ else if (p == "fontsize")
+ id = StringProtoFunc::Fontsize;
+ else if (p == "anchor")
+ id = StringProtoFunc::Anchor;
+ else if (p == "link")
+ id = StringProtoFunc::Link;
+#endif
+ else
+ return Imp::get(p);
+
+ return Function(new StringProtoFunc(id));
+}
+
+StringProtoFunc::StringProtoFunc(int i)
+ : id(i)
+{
+}
+
+// ECMA 15.5.4.2 - 15.5.4.20
+Completion StringProtoFunc::execute(const List &args)
+{
+ KJSO result;
+
+ Object thisObj = Object::dynamicCast(thisValue());
+
+ // toString and valueOf are no generic function.
+ if (id == ToString || id == ValueOf) {
+ if (thisObj.isNull() || thisObj.getClass() != StringClass) {
+ result = Error::create(TypeError);
+ return Completion(ReturnValue, result);
+ }
+ }
+
+ String s2;
+ Number n, m;
+ UString u, u2, u3;
+ int pos, p0, i;
+ double d, d2;
+ KJSO v = thisObj.internalValue();
+ String s = v.toString();
+ int len = s.value().size();
+ KJSO a0 = args[0];
+ KJSO a1 = args[1];
+
+ switch (id) {
+ case ToString:
+ case ValueOf:
+ result = v.toString();
+ break;
+ case CharAt:
+ n = a0.toInteger();
+ pos = (int) n.value();
+ if (pos < 0 || pos >= len)
+ u = "";
+ else
+ u = s.value().substr(pos, 1);
+ result = String(u);
+ break;
+ case CharCodeAt:
+ n = a0.toInteger();
+ pos = (int) n.value();
+ if (pos < 0 || pos >= len)
+ d = NaN;
+ else {
+ UChar c = s.value()[pos];
+ d = (c.high() << 8) + c.low();
+ }
+ result = Number(d);
+ break;
+ case IndexOf:
+ s2 = a0.toString();
+ if (a1.isA(UndefinedType))
+ pos = 0;
+ else
+ pos = a1.toInteger().intValue();
+ d = s.value().find(s2.value(), pos);
+ result = Number(d);
+ break;
+ case LastIndexOf:
+ s2 = a0.toString();
+ if (a1.isA(UndefinedType))
+ pos = len;
+ else
+ pos = a1.toInteger().intValue();
+ d = s.value().rfind(s2.value(), pos);
+ result = Number(d);
+ break;
+ case Match:
+ case Search:
+ u = s.value();
+ if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
+ s2 = a0.get("source").toString();
+ RegExp reg(s2.value());
+ UString mstr = reg.match(u, -1, &pos);
+ if (id == Search) {
+ result = Number(pos);
+ break;
+ }
+ if (mstr.isNull()) {
+ result = Null();
+ break;
+ }
+ /* TODO return an array, with the matches, etc. */
+ result = String(mstr);
+ } else
+ {
+ printf("Match/Search. Argument is not a RegExp - returning Undefined\n");
+ result = Undefined(); // No idea what to do here
+ }
+ break;
+ case Replace:
+ /* TODO: this is just a hack to get the most common cases going */
+ u = s.value();
+ if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
+ s2 = a0.get("source").toString();
+ RegExp reg(s2.value());
+ UString mstr = reg.match(u, -1, &pos);
+ len = mstr.size();
+ } else {
+ s2 = a0.toString();
+ u2 = s2.value();
+ pos = u.find(u2);
+ len = u2.size();
+ }
+ if (pos == -1)
+ result = s;
+ else {
+ u3 = u.substr(0, pos) + a1.toString().value() +
+ u.substr(pos + len);
+ result = String(u3);
+ }
+ break;
+ case Split:
+ result = Object::create(ArrayClass);
+ u = s.value();
+ i = p0 = 0;
+ d = a1.isDefined() ? a1.toInteger().intValue() : -1; // optional max number
+ if (a0.isA(ObjectType) && Object(a0.imp()).getClass() == RegExpClass) {
+ RegExp reg(a0.get("source").toString().value());
+ if (u.isEmpty() && !reg.match(u, 0).isNull()) {
+ // empty string matched by regexp -> empty array
+ result.put("length", 0);
+ break;
+ }
+ int mpos;
+ pos = 0;
+ while (1) {
+ /* TODO: back references */
+ UString mstr = reg.match(u, pos, &mpos);
+ if (mpos < 0)
+ break;
+ pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
+ if (mpos != p0 || !mstr.isEmpty()) {
+ result.put(UString::from(i), String(u.substr(p0, mpos-p0)));
+ p0 = mpos + mstr.size();
+ i++;
+ }
+ }
+ } else if (a0.isDefined()) {
+ u2 = a0.toString().value();
+ if (u2.isEmpty()) {
+ if (u.isEmpty()) {
+ // empty separator matches empty string -> empty array
+ put("length", 0);
+ break;
+ } else {
+ while (i != d && i < u.size())
+ result.put(UString::from(i++), String(u.substr(p0++, 1)));
+ }
+ } else {
+ while (i != d && (pos = u.find(u2, p0)) >= 0) {
+ result.put(UString::from(i), String(u.substr(p0, pos-p0)));
+ p0 = pos + u2.size();
+ i++;
+ }
+ }
+ }
+ // add remaining string, if any
+ if (i != d && (p0 < len || i == 0))
+ result.put(UString::from(i++), String(u.substr(p0)));
+ result.put("length", i);
+ break;
+ case Substr:
+ n = a0.toInteger();
+ m = a1.toInteger();
+ if (n.value() >= 0)
+ d = n.value();
+ else
+ d = max(len + n.value(), 0);
+ if (a1.isA(UndefinedType))
+ d2 = len - d;
+ else
+ d2 = min(max(m.value(), 0), len - d);
+ result = String(s.value().substr((int)d, (int)d2));
+ break;
+ case Substring:
+ n = a0.toInteger();
+ m = a1.toInteger();
+ d = min(max(n.value(), 0), len);
+ if (a1.isA(UndefinedType))
+ d2 = len - d;
+ else {
+ d2 = min(max(m.value(), 0), len);
+ d2 = max(d2-d, 0);
+ }
+ result = String(s.value().substr((int)d, (int)d2));
+ break;
+ case ToLowerCase:
+ u = UString(s.value());
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toLower();
+ result = String(u);
+ break;
+ case ToUpperCase:
+ u = UString(s.value());
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toUpper();
+ result = String(u);
+ break;
+#ifndef KJS_PURE_ECMA
+ case Big:
+ result = String("<BIG>" + s.value() + "</BIG>");
+ break;
+ case Small:
+ result = String("<SMALL>" + s.value() + "</SMALL>");
+ break;
+ case Blink:
+ result = String("<BLINK>" + s.value() + "</BLINK>");
+ break;
+ case Bold:
+ result = String("<B>" + s.value() + "</B>");
+ break;
+ case Fixed:
+ result = String("<TT>" + s.value() + "</TT>");
+ break;
+ case Italics:
+ result = String("<I>" + s.value() + "</I>");
+ break;
+ case Strike:
+ result = String("<STRIKE>" + s.value() + "</STRIKE>");
+ break;
+ case Sub:
+ result = String("<SUB>" + s.value() + "</SUB>");
+ break;
+ case Sup:
+ result = String("<SUP>" + s.value() + "</SUP>");
+ break;
+ case Fontcolor:
+ result = String("<FONT COLOR=" + a0.toString().value() + ">"
+ + s.value() + "</FONT>");
+ break;
+ case Fontsize:
+ result = String("<FONT SIZE=" + a0.toString().value() + ">"
+ + s.value() + "</FONT>");
+ break;
+ case Anchor:
+ result = String("<a name=" + a0.toString().value() + ">"
+ + s.value() + "</a>");
+ break;
+ case Link:
+ result = String("<a href=" + a0.toString().value() + ">"
+ + s.value() + "</a>");
+ break;
+#endif
+ }
+
+ return Completion(ReturnValue, result);
+}
diff --git a/WebCore/src/kdelibs/kjs/string_object.h b/WebCore/src/kdelibs/kjs/string_object.h
new file mode 100644
index 0000000..5396750
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/string_object.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _STRING_OBJECT_H_
+#define _STRING_OBJECT_H_
+
+#include "object.h"
+#include "function.h"
+
+namespace KJS {
+
+ class StringObject : public ConstructorImp {
+ public:
+ StringObject(const Object &funcProto, const Object &stringProto);
+ KJSO get(const UString &p) const;
+ Completion execute(const List &);
+ Object construct(const List &);
+ };
+
+ class StringObjectFunc : public InternalFunctionImp {
+ public:
+ Completion execute(const List &);
+ };
+
+ class StringPrototype : public ObjectImp {
+ public:
+ StringPrototype(const Object& proto);
+ KJSO get(const UString &p) const;
+ };
+
+ class StringProtoFunc : public InternalFunctionImp {
+ public:
+ StringProtoFunc(int i);
+ Completion execute(const List &);
+
+ enum { ToString, ValueOf, CharAt, CharCodeAt, IndexOf, LastIndexOf,
+ Match, Replace, Search, Slice, Split,
+ Substr, Substring, FromCharCode, ToLowerCase, ToUpperCase
+#ifndef KJS_PURE_ECMA
+ , Big, Small, Blink, Bold, Fixed, Italics, Strike, Sub, Sup,
+ Fontcolor, Fontsize, Anchor, Link
+#endif
+ };
+ private:
+ int id;
+ };
+
+}; // namespace
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/test.js b/WebCore/src/kdelibs/kjs/test.js
new file mode 100644
index 0000000..f5bbf5b
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/test.js
@@ -0,0 +1,29 @@
+var i = 0;
+
+function sum(a, b)
+{
+ debug("inside test()");
+ i = i + 1;
+ debug(a);
+ debug(b);
+ return a + b;
+}
+
+s = sum(10, sum(20, 30));
+debug("s = " + s);
+debug("i = " + i);
+
+var a = new Array(11, 22, 33, 44);
+a.length = 2;
+a[4] = 'apple';
+
+for(i = 0; i != a.length; i++)
+ debug("a[" + i + "] = " + a[i]);
+
+var b = new Boolean(1==1);
+b.toString=Object.prototype.toString;
+debug("b = " + b.toString());
+
+// regular expression
+rx = /b*c/;
+debug(rx.exec("abbbcd"));
diff --git a/WebCore/src/kdelibs/kjs/testkjs.cpp b/WebCore/src/kdelibs/kjs/testkjs.cpp
new file mode 100644
index 0000000..afb04b0d
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/testkjs.cpp
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+
+#include "object.h"
+#include "types.h"
+#include "internal.h"
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ // create interpreter
+ KJScript *kjs = new KJScript();
+
+ // add debug() function
+ kjs->enableDebug();
+
+ const int BufferSize = 100000;
+ char code[BufferSize];
+
+ bool ret = true;
+ for (int i = 1; i < argc; i++) {
+ const char *file = argv[i];
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return -1;
+ }
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ // run
+ ret = ret && kjs->evaluate(code);
+ if (kjs->errorType() != 0)
+ printf("%s returned: %s\n", file, kjs->errorMsg());
+ else if (kjs->returnValue())
+ printf("returned a value\n");
+
+ fclose(f);
+ }
+
+ delete kjs;
+
+#ifdef KJS_DEBUG_MEM
+ printf("List::count = %d\n", KJS::List::count);
+ assert(KJS::List::count == 0);
+ printf("Imp::count = %d\n", KJS::Imp::count);
+ assert(KJS::Imp::count == 0);
+#endif
+
+ fprintf(stderr, "OK.\n");
+ return ret;
+}
diff --git a/WebCore/src/kdelibs/kjs/types.cpp b/WebCore/src/kdelibs/kjs/types.cpp
new file mode 100644
index 0000000..682e607
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/types.cpp
@@ -0,0 +1,299 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "kjs.h"
+#include "object.h"
+#include "types.h"
+#include "internal.h"
+#include "operations.h"
+#include "nodes.h"
+
+using namespace KJS;
+
+Undefined::Undefined() : KJSO(UndefinedImp::staticUndefined) { }
+
+Undefined::~Undefined() { }
+
+Null::Null() : KJSO(NullImp::staticNull) { }
+
+Null::~Null() { }
+
+Boolean::Boolean(bool b)
+ : KJSO(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
+{
+}
+
+Boolean::Boolean(BooleanImp *i) : KJSO(i) { }
+
+Boolean::~Boolean() { }
+
+bool Boolean::value() const
+{
+ assert(rep);
+ return ((BooleanImp*)rep)->value();
+}
+
+Number::Number(int i)
+ : KJSO(new NumberImp(static_cast<double>(i))) { }
+
+Number::Number(unsigned int u)
+ : KJSO(new NumberImp(static_cast<double>(u))) { }
+
+Number::Number(double d)
+ : KJSO(new NumberImp(d)) { }
+
+Number::Number(long int l)
+ : KJSO(new NumberImp(static_cast<double>(l))) { }
+
+Number::Number(long unsigned int l)
+ : KJSO(new NumberImp(static_cast<double>(l))) { }
+
+Number::Number(NumberImp *i)
+ : KJSO(i) { }
+
+Number::~Number() { }
+
+double Number::value() const
+{
+ assert(rep);
+ return ((NumberImp*)rep)->value();
+}
+
+int Number::intValue() const
+{
+ assert(rep);
+ return (int)((NumberImp*)rep)->value();
+}
+
+bool Number::isNaN() const
+{
+ return KJS::isNaN(((NumberImp*)rep)->value());
+}
+
+bool Number::isInf() const
+{
+ return KJS::isInf(((NumberImp*)rep)->value());
+}
+
+String::String(const UString &s) : KJSO(new StringImp(UString(s))) { }
+
+String::String(StringImp *i) : KJSO(i) { }
+
+String::~String() { }
+
+UString String::value() const
+{
+ assert(rep);
+ return ((StringImp*)rep)->value();
+}
+
+Reference::Reference(const KJSO& b, const UString &p)
+ : KJSO(new ReferenceImp(b, p))
+{
+}
+
+Reference::~Reference()
+{
+}
+
+Completion::Completion(Imp *d) : KJSO(d) { }
+
+Completion::Completion(Compl c)
+ : KJSO(new CompletionImp(c, KJSO(), UString::null))
+{
+ if (c == Throw)
+ KJScriptImp::setException(new UndefinedImp());
+}
+
+Completion::Completion(Compl c, const KJSO& v, const UString &t)
+ : KJSO(new CompletionImp(c, v, t))
+{
+ if (c == Throw)
+ KJScriptImp::setException(v.imp());
+}
+
+Completion::~Completion() { }
+
+Compl Completion::complType() const
+{
+ assert(rep);
+ return ((CompletionImp*)rep)->completion();
+}
+
+bool Completion::isValueCompletion() const
+{
+ assert(rep);
+ return !((CompletionImp*)rep)->value().isNull();
+}
+
+KJSO Completion::value() const
+{
+ assert(isA(CompletionType));
+ return ((CompletionImp*)rep)->value();
+}
+
+UString Completion::target() const
+{
+ assert(rep);
+ return ((CompletionImp*)rep)->target();
+}
+
+ListIterator::ListIterator(const List &l)
+ : node(l.hook->next)
+{
+}
+
+List::List()
+{
+#ifdef KJS_DEBUG_MEM
+ count++;
+#endif
+
+ static KJSO *null = 0;
+ if (!null)
+ null = new KJSO();
+
+ hook = new ListNode(*null, 0L, 0L);
+ hook->next = hook;
+ hook->prev = hook;
+}
+
+List::~List()
+{
+#ifdef KJS_DEBUG_MEM
+ count--;
+#endif
+
+ clear();
+ delete hook;
+}
+
+void List::append(const KJSO& obj)
+{
+ ListNode *n = new ListNode(obj, hook->prev, hook);
+ hook->prev->next = n;
+ hook->prev = n;
+}
+
+void List::prepend(const KJSO& obj)
+{
+ ListNode *n = new ListNode(obj, hook, hook->next);
+ hook->next->prev = n;
+ hook->next = n;
+}
+
+void List::removeFirst()
+{
+ erase(hook->next);
+}
+
+void List::removeLast()
+{
+ erase(hook->prev);
+}
+
+void List::remove(const KJSO &obj)
+{
+ if (obj.isNull())
+ return;
+ ListNode *n = hook->next;
+ while (n != hook) {
+ if (n->member.imp() == obj.imp()) {
+ erase(n);
+ return;
+ }
+ n = n->next;
+ }
+}
+
+void List::clear()
+{
+ ListNode *n = hook->next;
+ while (n != hook) {
+ n = n->next;
+ delete n->prev;
+ }
+
+ hook->next = hook;
+ hook->prev = hook;
+}
+
+List *List::copy() const
+{
+ List *newList = new List();
+ ListIterator e = end();
+ ListIterator it = begin();
+
+ while(it != e) {
+ newList->append(*it);
+ ++it;
+ }
+
+ return newList;
+}
+
+void List::erase(ListNode *n)
+{
+ if (n != hook) {
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+ delete n;
+ }
+}
+
+int List::size() const
+{
+ int s = 0;
+ ListNode *node = hook;
+ while ((node = node->next) != hook)
+ s++;
+
+ return s;
+}
+
+KJSO List::at(int i) const
+{
+ if (i < 0 || i >= size())
+ return Undefined();
+
+ ListIterator it = begin();
+ int j = 0;
+ while ((j++ < i))
+ it++;
+
+ return *it;
+}
+
+List *List::emptyList = 0L;
+
+const List *List::empty()
+{
+ if (!emptyList)
+ emptyList = new List;
+#ifdef KJS_DEBUG_MEM
+ else
+ count++;
+#endif
+
+
+ return emptyList;
+}
diff --git a/WebCore/src/kdelibs/kjs/types.h b/WebCore/src/kdelibs/kjs/types.h
new file mode 100644
index 0000000..c1bfac6
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/types.h
@@ -0,0 +1,355 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include "object.h"
+
+namespace KJS {
+
+ /**
+ * @short Handle for an Undefined type.
+ */
+ class Undefined : public KJSO {
+ public:
+ Undefined();
+ virtual ~Undefined();
+ };
+
+ /**
+ * @short Handle for a Null type.
+ */
+ class Null : public KJSO {
+ public:
+ Null();
+ virtual ~Null();
+ };
+
+ class BooleanImp;
+ class NumberImp;
+ class StringImp;
+
+ /**
+ * @short Handle for a Boolean type.
+ */
+ class Boolean : public KJSO {
+ friend class BooleanImp;
+ public:
+ Boolean(bool b = false);
+ virtual ~Boolean();
+ bool value() const;
+ private:
+ Boolean(BooleanImp *i);
+ };
+
+ /**
+ * @short Handle for a Number type.
+ *
+ * Number is a handle for a number value. @ref KJSO::toPrimitive(),
+ * @ref KJSO::toBoolean(), @ref KJSO::toNumber(), @ref KJSO::toString() and
+ * @ref KJSO::toString() are re-implemented internally according to the
+ * specification.
+ *
+ * Example usage:
+ * <pre>
+ * Number a(2), b(3.0), c; // c defaults to 0.0
+ *
+ * c = a.value() * b.value(); // c will be 6.0 now
+ *
+ * String s = c.toString(); // s holds "6"
+ * </pre>
+ *
+ * Note the following implementation detail: Internally, the value is stored
+ * as a double and will be casted from and to other types when needed.
+ * This won't be noticable within a certain range of values but might produce
+ * unpredictable results when crossing these limits. In case this turns out
+ * to be a real problem for an application we might have to extend this class
+ * to behave more intelligently.
+ */
+ class Number : public KJSO {
+ friend class NumberImp;
+ public:
+ /**
+ * Construct a Number type from an integer.
+ */
+ Number(int i);
+ /**
+ * Construct a Number type from an unsigned integer.
+ */
+ Number(unsigned int u);
+ /**
+ * Construct a Number type from a double.
+ */
+ Number(double d = 0.0);
+ /**
+ * Construct a Number type from a long int.
+ */
+ Number(long int l);
+ /**
+ * Construct a Number type from a long unsigned int.
+ */
+ Number(long unsigned int l);
+ /**
+ * Destructor.
+ */
+ virtual ~Number();
+ /**
+ * @return The internally stored value.
+ */
+ double value() const;
+ /**
+ * Convenience function.
+ * @return The internally stored value converted to an int.
+ */
+ int intValue() const;
+ /**
+ * @return True is this is not a number (NaN).
+ */
+ bool isNaN() const;
+ /**
+ * @return True if Number is either +Infinity or -Infinity.
+ */
+ bool isInf() const;
+ private:
+ Number(NumberImp *i);
+ };
+
+ /**
+ * @short Handle for a String type.
+ */
+ class String : public KJSO {
+ friend class StringImp;
+ public:
+ String(const UString &s = "");
+ virtual ~String();
+ UString value() const;
+ private:
+ String(StringImp *i);
+ };
+
+ /**
+ * Completion objects are used to convey the return status and value
+ * from functions.
+ *
+ * See @ref FunctionImp::execute()
+ *
+ * @see FunctionImp
+ *
+ * @short Handle for a Completion type.
+ */
+ class Completion : public KJSO {
+ public:
+ Completion(Imp *d = 0L);
+ Completion(Compl c);
+ Completion(Compl c, const KJSO& v, const UString &t = UString::null);
+ virtual ~Completion();
+ Compl complType() const;
+ bool isValueCompletion() const;
+ KJSO value() const;
+ UString target() const;
+ };
+
+ class List;
+ class ListIterator;
+
+ /**
+ * @internal
+ */
+ class ListNode {
+ friend class List;
+ friend class ListIterator;
+ ListNode(KJSO obj, ListNode *p, ListNode *n)
+ : member(obj), prev(p), next(n) {};
+ KJSO member;
+ ListNode *prev, *next;
+ };
+
+ /**
+ * @short Iterator for @ref KJS::List objects.
+ */
+ class ListIterator {
+ friend class List;
+ ListIterator();
+ ListIterator(ListNode *n) : node(n) { }
+ public:
+ /**
+ * Construct an iterator that points to the first element of the list.
+ * @param l The list the iterator will operate on.
+ */
+ ListIterator(const List &list);
+ /**
+ * Assignment constructor.
+ */
+ ListIterator& operator=(const ListIterator &iterator)
+ { node=iterator.node; return *this; }
+ /**
+ * Copy constructor.
+ */
+ ListIterator(const ListIterator &i) : node(i.node) { }
+ /**
+ * Dereference the iterator.
+ * @return A pointer to the element the iterator operates on.
+ */
+ KJSO* operator->() const { return &node->member; }
+ // operator KJSO* () const { return node->member; }
+ KJSO operator*() const { return node->member; }
+ /**
+ * Conversion to @ref KJS::KJSO*
+ * @return A pointer to the element the iterator operates on.
+ */
+ // operator KJSO*() const { return node->member; }
+ /**
+ * Postfix increment operator.
+ * @return The element after the increment.
+ */
+ KJSO operator++() { node = node->next; return node->member; }
+ /**
+ * Prefix increment operator.
+ */
+ KJSO operator++(int) { const ListNode *n = node; ++*this; return n->member; }
+ /**
+ * Postfix decrement operator.
+ */
+ KJSO operator--() { node = node->prev; return node->member; }
+ /**
+ * Prefix decrement operator.
+ */
+ KJSO operator--(int) { const ListNode *n = node; --*this; return n->member; }
+ /**
+ * Compare the iterator with another one.
+ * @return True if the two iterators operate on the same list element.
+ * False otherwise.
+ */
+ bool operator==(const ListIterator &it) const { return (node==it.node); }
+ /**
+ * Check for inequality with another iterator.
+ * @return True if the two iterators operate on different list elements.
+ */
+ bool operator!=(const ListIterator &it) const { return (node!=it.node); }
+ private:
+ ListNode *node;
+ };
+
+ /**
+ * @short Native list type.
+ *
+ * List is a native ECMAScript type. List values are only used for
+ * intermediate results of expression evaluation and cannot be stored
+ * as properties of objects.
+ *
+ * The list is explicitly shared. Note that while copy() returns a deep
+ * copy of the list the referenced objects are still shared.
+ */
+ class List {
+ friend class ListIterator;
+ public:
+ /**
+ * Constructor.
+ */
+ List();
+ /**
+ * Destructor.
+ */
+ ~List();
+ /**
+ * Append an object to the end of the list.
+ *
+ * @param obj Pointer to object.
+ */
+ void append(const KJSO& obj);
+ /**
+ * Insert an object at the beginning of the list.
+ *
+ * @param obj Pointer to object.
+ */
+ void prepend(const KJSO& obj);
+ /**
+ * Remove the element at the beginning of the list.
+ */
+ void removeFirst();
+ /**
+ * Remove the element at the end of the list.
+ */
+ void removeLast();
+ /*
+ * Remove obj from list.
+ */
+ void remove(const KJSO &obj);
+ /**
+ * Remove all elements from the list.
+ */
+ void clear();
+ /**
+ * Returns a deep copy of the list. Ownership is passed to the user
+ * who is responsible for deleting the list then.
+ */
+ List *copy() const;
+ /**
+ * @return A @ref KJS::ListIterator pointing to the first element.
+ */
+ ListIterator begin() const { return ListIterator(hook->next); }
+ /**
+ * @return A @ref KJS::ListIterator pointing to the last element.
+ */
+ ListIterator end() const { return ListIterator(hook); }
+ /**
+ * @return true if the list is empty. false otherwise.
+ */
+ bool isEmpty() const { return (hook->prev == hook); }
+ /**
+ * @return the current size of the list.
+ */
+ int size() const;
+ /**
+ * Retrieve an element at an indexed position. If you want to iterate
+ * trough the whole list using @ref KJS::ListIterator will be faster.
+ *
+ * @param i List index.
+ * @return Return the element at position i. @ref KJS::Undefined if the
+ * index is out of range.
+ */
+ KJSO at(int i) const;
+ /**
+ * Equivalent to @ref at.
+ */
+ KJSO operator[](int i) const { return at(i); }
+ /**
+ * Returns a pointer to a static instance of an empty list. Useful if a
+ * function has a @ref KJS::List parameter.
+ */
+ static const List *empty();
+
+#ifdef KJS_DEBUG_MEM
+ /**
+ * @internal
+ */
+ static int count;
+#endif
+ private:
+ void erase(ListNode *n);
+ ListNode *hook;
+ static List *emptyList;
+ };
+
+}; // namespace
+
+
+#endif
diff --git a/WebCore/src/kdelibs/kjs/ustring.cpp b/WebCore/src/kdelibs/kjs/ustring.cpp
new file mode 100644
index 0000000..d547a04
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/ustring.cpp
@@ -0,0 +1,539 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include "ustring.h"
+#include "operations.h"
+
+namespace KJS {
+ extern const double NaN;
+ extern const double Inf;
+};
+
+using namespace KJS;
+
+CString::CString(const char *c)
+{
+ data = new char[strlen(c)+1];
+ strcpy(data, c);
+}
+
+CString::CString(const CString &b)
+{
+ data = new char[b.size()+1];
+ strcpy(data, b.c_str());
+}
+
+CString::~CString()
+{
+ delete [] data;
+}
+
+CString &CString::append(const CString &t)
+{
+ char *n;
+ if (data) {
+ n = new char[strlen(data)+t.size()+1];
+ strcpy(n, data);
+ } else {
+ n = new char[t.size()+1];
+ n[0] = '\0';
+ }
+ strcat(n, t.c_str());
+
+ delete [] data;
+ data = n;
+
+ return *this;
+}
+
+CString &CString::operator=(const char *c)
+{
+ if (data)
+ delete [] data;
+ data = new char[strlen(c)+1];
+ strcpy(data, c);
+
+ return *this;
+}
+
+CString &CString::operator=(const CString &str)
+{
+ if (this == &str)
+ return *this;
+
+ if (data)
+ delete [] data;
+ data = new char[str.size()+1];
+ strcpy(data, str.c_str());
+
+ return *this;
+}
+
+CString &CString::operator+=(const CString &str)
+{
+ return append(str.c_str());
+}
+
+int CString::size() const
+{
+ return strlen(data);
+}
+
+bool KJS::operator==(const KJS::CString& c1, const KJS::CString& c2)
+{
+ return (strcmp(c1.c_str(), c2.c_str()) == 0);
+}
+
+UChar UChar::null;
+UString::Rep UString::Rep::null = { 0, 0, 1 };
+UString UString::null;
+static char *statBuffer = 0L;
+
+UChar::UChar(const UCharReference &c)
+#ifdef KJS_SWAPPED_CHAR
+ : lo(c.low()), hi(c.high())
+#else
+ : hi(c.high()), lo(c.low())
+#endif
+{
+}
+
+UChar UChar::toLower() const
+{
+ if (islower(lo) && hi == 0)
+ return *this;
+
+ return UChar(0, tolower(lo));
+}
+
+UChar UChar::toUpper() const
+{
+ if (isupper(lo) && hi == 0)
+ return *this;
+
+ return UChar(0, toupper(lo));
+}
+
+UCharReference& UCharReference::operator=(UChar c)
+{
+ str->detach();
+ if (offset < str->rep->len)
+ *(str->rep->dat + offset) = c;
+ /* TODO: lengthen string ? */
+ return *this;
+}
+
+UChar& UCharReference::ref() const
+{
+ if (offset < str->rep->len)
+ return *(str->rep->dat + offset);
+ else
+ return UChar::null;
+}
+
+UString::Rep *UString::Rep::create(UChar *d, int l)
+{
+ Rep *r = new Rep;
+ r->dat = d;
+ r->len = l;
+ r->rc = 1;
+
+ return r;
+}
+
+UString::UString()
+{
+ null.rep = &Rep::null;
+ attach(&Rep::null);
+}
+
+UString::UString(char c)
+{
+ rep = Rep::create(new UChar(0, c), 1);
+}
+
+UString::UString(const char *c)
+{
+ attach(&Rep::null);
+ operator=(c);
+}
+
+UString::UString(const UChar *c, int length)
+{
+ UChar *d = new UChar[length];
+ memcpy(d, c, length * sizeof(UChar));
+ rep = Rep::create(d, length);
+}
+
+UString::UString(UChar *c, int length, bool copy)
+{
+ UChar *d;
+ if (copy) {
+ d = new UChar[length];
+ memcpy(d, c, length * sizeof(UChar));
+ } else
+ d = c;
+ rep = Rep::create(d, length);
+}
+
+UString::UString(const UString &b)
+{
+ attach(b.rep);
+}
+
+UString::~UString()
+{
+ release();
+}
+
+UString UString::from(int i)
+{
+ char buf[40];
+ sprintf(buf, "%d", i);
+
+ return UString(buf);
+}
+
+UString UString::from(unsigned int u)
+{
+ char buf[40];
+ sprintf(buf, "%u", u);
+
+ return UString(buf);
+}
+
+UString UString::from(double d)
+{
+ char buf[40];
+ sprintf(buf, "%.16g", d); // does the right thing
+ return UString(buf);
+}
+
+UString &UString::append(const UString &t)
+{
+ int l = size();
+ UChar *n = new UChar[l+t.size()];
+ memcpy(n, data(), l * sizeof(UChar));
+ memcpy(n+l, t.data(), t.size() * sizeof(UChar));
+ release();
+ rep = Rep::create(n, l + t.size());
+
+ return *this;
+}
+
+CString UString::cstring() const
+{
+ return CString(ascii());
+}
+
+char *UString::ascii() const
+{
+ if (statBuffer)
+ delete [] statBuffer;
+
+ statBuffer = new char[size()+1];
+ for(int i = 0; i < size(); i++)
+ statBuffer[i] = data()[i].lo;
+ statBuffer[size()] = '\0';
+
+ return statBuffer;
+}
+
+UString &UString::operator=(const char *c)
+{
+ release();
+ int l = c ? strlen(c) : 0;
+ UChar *d = new UChar[l];
+ for (int i = 0; i < l; i++)
+ d[i].lo = c[i];
+ rep = Rep::create(d, l);
+
+ return *this;
+}
+
+UString &UString::operator=(const UString &str)
+{
+ str.rep->ref();
+ release();
+ rep = str.rep;
+
+ return *this;
+}
+
+UString &UString::operator+=(const UString &s)
+{
+ return append(s);
+}
+
+bool UString::is8Bit() const
+{
+ const UChar *u = data();
+ for(int i = 0; i < size(); i++, u++)
+ if (u->hi)
+ return false;
+
+ return true;
+}
+
+UChar UString::operator[](int pos) const
+{
+ if (pos >= size())
+ return UChar::null;
+
+ return ((UChar *)data())[pos];
+}
+
+UCharReference UString::operator[](int pos)
+{
+ /* TODO: boundary check */
+ return UCharReference(this, pos);
+}
+
+double UString::toDouble() const
+{
+ double d;
+
+ if (!is8Bit())
+ return NaN;
+
+ CString str = cstring();
+ const char *c = str.c_str();
+
+ // skip leading white space
+ while (isspace(*c))
+ c++;
+
+ // empty string ?
+ if (*c == '\0')
+ return 0.0;
+
+ // hex number ?
+ if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
+ c++;
+ d = 0.0;
+ while (*(++c)) {
+ if (*c >= '0' && *c <= '9')
+ d = d * 16.0 + *c - '0';
+ else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
+ d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
+ else
+ break;
+ }
+ } else {
+ // regular number ?
+ char *end;
+ d = strtod(c, &end);
+ if (d != 0.0 || end != c) {
+ c = end;
+ } else {
+ // infinity ?
+ d = 1.0;
+ if (*c == '+')
+ c++;
+ else if (*c == '-') {
+ d = -1.0;
+ c++;
+ }
+ if (strncmp(c, "Infinity", 8) != 0)
+ return NaN;
+ d = d * Inf;
+ c += 8;
+ }
+ }
+
+ // allow trailing white space
+ while (isspace(*c))
+ c++;
+ if (*c != '\0')
+ d = NaN;
+
+ return d;
+}
+
+unsigned long UString::toULong(bool *ok) const
+{
+ double d = toDouble();
+ bool b = true;
+
+ if (isNaN(d) || d != static_cast<unsigned long>(d)) {
+ b = false;
+ d = 0;
+ }
+
+ if (ok)
+ *ok = b;
+
+ return static_cast<unsigned long>(d);
+}
+
+int UString::find(const UString &f, int pos) const
+{
+ if (isNull())
+ return -1;
+ long fsize = f.size() * sizeof(UChar);
+ if (pos < 0)
+ pos = 0;
+ const UChar *end = data() + size() - f.size();
+ for (const UChar *c = data() + pos; c <= end; c++)
+ if (!memcmp((void*)c, (void*)f.data(), fsize))
+ return (c-data());
+
+ return -1;
+}
+
+int UString::rfind(const UString &f, int pos) const
+{
+ if (isNull())
+ return -1;
+ if (pos + f.size() >= size())
+ pos = size() - f.size();
+ long fsize = f.size() * sizeof(UChar);
+ for (const UChar *c = data() + pos; c >= data(); c--) {
+ if (!memcmp((void*)c, (void*)f.data(), fsize))
+ return (c-data());
+ }
+
+ return -1;
+}
+
+UString UString::substr(int pos, int len) const
+{
+ if (isNull())
+ return UString();
+ if (pos < 0)
+ pos = 0;
+ else if (pos >= (int) size())
+ pos = size();
+ if (len < 0)
+ len = size();
+ if (pos + len >= (int) size())
+ len = size() - pos;
+
+ UChar *tmp = new UChar[len];
+ memcpy(tmp, data()+pos, len * sizeof(UChar));
+ UString result(tmp, len);
+ delete [] tmp;
+
+ return result;
+}
+
+void UString::attach(Rep *r)
+{
+ rep = r;
+ rep->ref();
+}
+
+void UString::detach()
+{
+ if (rep->rc > 1) {
+ int l = size();
+ UChar *n = new UChar[l];
+ memcpy(n, data(), l * sizeof(UChar));
+ release();
+ rep = Rep::create(n, l);
+ }
+}
+
+void UString::release()
+{
+ if (!rep->deref()) {
+ delete [] rep->dat;
+ delete rep;
+ }
+}
+
+bool KJS::operator==(const UChar &c1, const UChar &c2)
+{
+ return ((c1.lo == c2.lo) & (c1.hi == c2.hi));
+}
+
+bool KJS::operator==(const UString& s1, const UString& s2)
+{
+ if (s1.rep->len != s2.rep->len)
+ return false;
+
+ return (memcmp(s1.rep->dat, s2.rep->dat,
+ s1.rep->len * sizeof(UChar)) == 0);
+}
+
+bool KJS::operator==(const UString& s1, const char *s2)
+{
+ if (s2 == 0L && s1.isNull())
+ return true;
+
+ if (s1.size() != (int) strlen(s2))
+ return false;
+
+ const UChar *u = s1.data();
+ while (*s2) {
+ if (u->lo != *s2 || u->hi != 0)
+ return false;
+ s2++;
+ u++;
+ }
+
+ return true;
+}
+
+bool KJS::operator==(const char *s1, const UString& s2)
+{
+ return operator==(s2, s1);
+}
+
+bool KJS::operator<(const UString& s1, const UString& s2)
+{
+ int l1 = s1.size();
+ int l2 = s2.size();
+ const UChar *c1 = s1.data();
+ const UChar *c2 = s2.data();
+ int l = 0;
+ int le = l1 < l2 ? l1 : l2;
+ while (l < le && *c1 == *c2) {
+ c1++;
+ c2++;
+ l++;
+ }
+ if (l != le)
+ return (c1->unicode() < c2->unicode());
+
+ return (l1 < l2 && !(*c1 == *c2));
+}
+
+UString KJS::operator+(const UString& s1, const UString& s2)
+{
+ UString tmp(s1);
+ tmp.append(s2);
+
+ return tmp;
+}
diff --git a/WebCore/src/kdelibs/kjs/ustring.h b/WebCore/src/kdelibs/kjs/ustring.h
new file mode 100644
index 0000000..e897a34
--- /dev/null
+++ b/WebCore/src/kdelibs/kjs/ustring.h
@@ -0,0 +1,419 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KJS_STRING_H_
+#define _KJS_STRING_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * @internal
+ */
+namespace DOM {
+ class DOMString;
+};
+class KJScript;
+class QString;
+class QConstString;
+
+#if defined(__GNUC__)
+#define KJS_PACKED __attribute__((__packed__))
+#else
+#define KJS_PACKED
+#endif
+
+namespace KJS {
+
+ class UCharReference;
+ class UString;
+
+ /**
+ * @short Unicode character.
+ *
+ * UChar represents a 16 bit Unicode character. It's internal data
+ * representation is compatible to XChar2b and QChar. It's therefore
+ * possible to exchange data with X and Qt with shallow copies.
+ */
+ struct UChar {
+ /**
+ * Construct a character with value 0.
+ */
+ UChar();
+ /**
+ * Construct a character with the value denoted by the arguments.
+ * @param h higher byte
+ * @param l lower byte
+ */
+ UChar(unsigned char h , unsigned char l);
+ /**
+ * Construct a character with the given value.
+ * @param u 16 bit Unicode value
+ */
+ UChar(unsigned short u);
+ UChar(const UCharReference &c);
+ /**
+ * @return The higher byte of the character.
+ */
+ unsigned char high() const { return hi; }
+ /**
+ * @return The lower byte of the character.
+ */
+ unsigned char low() const { return lo; }
+ /**
+ * @return the 16 bit Unicode value of the character
+ */
+ unsigned short unicode() const { return hi << 8 | lo; }
+ public:
+ /**
+ * @return The character converted to lower case.
+ */
+ UChar toLower() const;
+ /**
+ * @return The character converted to upper case.
+ */
+ UChar toUpper() const;
+ /**
+ * A static instance of UChar(0).
+ */
+ static UChar null;
+ private:
+ friend class UCharReference;
+ friend class UString;
+ friend bool operator==(const UChar &c1, const UChar &c2);
+ friend bool operator==(const UString& s1, const char *s2);
+ friend bool operator<(const UString& s1, const UString& s2);
+#ifdef KJS_SWAPPED_CHAR
+ unsigned char lo;
+ unsigned char hi;
+#else
+ unsigned char hi;
+ unsigned char lo;
+#endif
+ } KJS_PACKED;
+
+
+#ifdef KJS_SWAPPED_CHAR // to avoid reorder warnings
+ inline UChar::UChar() : lo(0), hi(0) { }
+ inline UChar::UChar(unsigned char h , unsigned char l) : lo(l), hi(h) { }
+ inline UChar::UChar(unsigned short u) : lo(u & 0x00ff), hi(u >> 8) { }
+#else
+ inline UChar::UChar() : hi(0), lo(0) { }
+ inline UChar::UChar(unsigned char h , unsigned char l) : hi(h), lo(l) { }
+ inline UChar::UChar(unsigned short u) : hi(u >> 8), lo(u & 0x00ff) { }
+#endif
+
+ /**
+ * @short Dynamic reference to a string character.
+ *
+ * UCharReference is the dynamic counterpart of @ref UChar. It's used when
+ * characters retrieved via index from a @ref UString are used in an
+ * assignment expression (and therefore can't be treated as being const):
+ * <pre>
+ * UString s("hello world");
+ * s[0] = 'H';
+ * </pre>
+ *
+ * If that sounds confusing your best bet is to simply forget about the
+ * existance of this class and treat is as being identical to @ref UChar.
+ */
+ class UCharReference {
+ friend class UString;
+ UCharReference(UString *s, unsigned int off) : str(s), offset(off) { }
+ public:
+ /**
+ * Set the referenced character to c.
+ */
+ UCharReference& operator=(UChar c);
+ /**
+ * Same operator as above except the argument that it takes.
+ */
+ UCharReference& operator=(char c) { return operator=(UChar(c)); }
+ /**
+ * @return Unicode value.
+ */
+ unsigned short unicode() const { return ref().unicode(); }
+ /**
+ * @return Lower byte.
+ */
+ unsigned char& low() const { return ref().lo; }
+ /**
+ * @return Higher byte.
+ */
+ unsigned char& high() const { return ref().hi; }
+ /**
+ * @return Character converted to lower case.
+ */
+ UChar toLower() const { return ref().toLower(); }
+ /**
+ * @return Character converted to upper case.
+ */
+ UChar toUpper() const { return ref().toUpper(); }
+ private:
+ // not implemented, can only be constructed from UString
+ UCharReference();
+
+ UChar& ref() const;
+ UString *str;
+ int offset;
+ };
+
+ /**
+ * @short 8 bit char based string class
+ */
+ class CString {
+ public:
+ CString() : data(0L) { }
+ CString(const char *c);
+ CString(const CString &);
+
+ ~CString();
+
+ CString &append(const CString &);
+ CString &operator=(const char *c);
+ CString &operator=(const CString &);
+ CString &operator+=(const CString &);
+
+ int size() const;
+ const char *c_str() const { return data; }
+ private:
+ char *data;
+ };
+
+ /**
+ * @short Unicode string class
+ */
+ class UString {
+ friend bool operator==(const UString&, const UString&);
+ friend class UCharReference;
+ /**
+ * @internal
+ */
+ struct Rep {
+ friend class UString;
+ friend bool operator==(const UString&, const UString&);
+ static Rep *create(UChar *d, int l);
+ inline UChar *data() const { return dat; }
+ inline int size() const { return len; }
+
+ inline void ref() { rc++; }
+ inline int deref() { return --rc; }
+
+ UChar *dat;
+ int len;
+ int rc;
+ static Rep null;
+ };
+
+ public:
+ /**
+ * Constructs a null string.
+ */
+ UString();
+ /**
+ * Constructs a string from the single character c.
+ */
+ UString(char c);
+ /**
+ * Constructs a string from a classical zero determined char string.
+ */
+ UString(const char *c);
+ /**
+ * Constructs a string from an array of Unicode characters of the specified
+ * length.
+ */
+ UString(const UChar *c, int length);
+ /**
+ * If copy is false a shallow copy of the string will be created. That
+ * means that the data will NOT be copied and you'll have to guarantee that
+ * it doesn't get deleted during the lifetime of the UString object.
+ * Behaviour defaults to a deep copy if copy is true.
+ */
+ UString(UChar *c, int length, bool copy);
+ /**
+ * Copy constructor. Makes a shallow copy only.
+ */
+ UString(const UString &);
+ /**
+ * Convenience declaration only ! You'll be on your own to write the
+ * implementation for a construction from QString.
+ *
+ * Note: feel free to contact me if you want to see a dummy header for
+ * your favourite FooString class here !
+ */
+ UString(const QString &);
+ /**
+ * Convenience declaration only ! See @ref UString(const QString&).
+ */
+ UString(const DOM::DOMString &);
+ /**
+ * Destructor. If this handle was the only one holding a reference to the
+ * string the data will be freed.
+ */
+ ~UString();
+
+ /**
+ * Constructs a string from an int.
+ */
+ static UString from(int i);
+ /**
+ * Constructs a string from an unsigned int.
+ */
+ static UString from(unsigned int u);
+ /**
+ * Constructs a string from a double.
+ */
+ static UString from(double d);
+
+ /**
+ * Append another string.
+ */
+ UString &append(const UString &);
+
+ /**
+ * @return The string converted to the 8-bit string type @ref CString().
+ */
+ CString cstring() const;
+ /**
+ * Convert the Unicode string to plain ASCII chars chopping of any higher
+ * bytes. This method should only be used for *debugging* purposes as it
+ * is neither Unicode safe nor free from side effects. In order not to
+ * waste any memory the char buffer is static and *shared* by all UString
+ * instances.
+ */
+ char *ascii() const;
+ /**
+ * @see UString(const QString&).
+ */
+ DOM::DOMString string() const;
+ /**
+ * @see UString(const QString&).
+ */
+ QString qstring() const;
+ /**
+ * @see UString(const QString&).
+ */
+ QConstString qconststring() const;
+
+ /**
+ * Assignment operator.
+ */
+ UString &operator=(const char *c);
+ /**
+ * Assignment operator.
+ */
+ UString &operator=(const UString &);
+ /**
+ * Appends the specified string.
+ */
+ UString &operator+=(const UString &s);
+
+ /**
+ * @return A pointer to the internal Unicode data.
+ */
+ const UChar* data() const { return rep->data(); }
+ /**
+ * @return True if null.
+ */
+ bool isNull() const { return (rep == &Rep::null); }
+ /**
+ * @return True if null or zero length.
+ */
+ bool isEmpty() const { return (!rep->len); }
+ /**
+ * Use this if you want to make sure that this string is a plain ASCII
+ * string. For example, if you don't want to lose any information when
+ * using @ref cstring() or @ref ascii().
+ *
+ * @return True if the string doesn't contain any non-ASCII characters.
+ */
+ bool is8Bit() const;
+ /**
+ * @return The length of the string.
+ */
+ int size() const { return rep->size(); }
+ /**
+ * Const character at specified position.
+ */
+ UChar operator[](int pos) const;
+ /**
+ * Writable reference to character at specified position.
+ */
+ UCharReference operator[](int pos);
+
+ /**
+ * Attempts an conversion to a number. Apart from floating point numbers,
+ * the algorithm will recognize hexadecimal representations (as
+ * indicated by a 0x or 0X prefix) and +/- Infinity.
+ * Returns NaN if the conversion failed.
+ */
+ double toDouble() const;
+ /**
+ * Attempts an conversion to an unsigned long integer. ok will be set
+ * according to the success.
+ */
+ unsigned long toULong(bool *ok = 0L) const;
+ /**
+ * @return Position of first occurence of f starting at position pos.
+ * -1 if the search was not successful.
+ */
+ int find(const UString &f, int pos = 0) const;
+ /**
+ * @return Position of first occurence of f searching backwards from
+ * position pos.
+ * -1 if the search was not successful.
+ */
+ int rfind(const UString &f, int pos) const;
+ /**
+ * @return The sub string starting at position pos and length len.
+ */
+ UString substr(int pos = 0, int len = -1) const;
+ /**
+ * Static instance of a null string.
+ */
+ static UString null;
+ private:
+ void attach(Rep *r);
+ void detach();
+ void release();
+ Rep *rep;
+ };
+
+ bool operator==(const UChar &c1, const UChar &c2);
+ bool operator==(const UString& s1, const UString& s2);
+ inline bool operator!=(const UString& s1, const UString& s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator<(const UString& s1, const UString& s2);
+ bool operator==(const UString& s1, const char *s2);
+ inline bool operator!=(const UString& s1, const char *s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator==(const char *s1, const UString& s2);
+ inline bool operator!=(const char *s1, const UString& s2) {
+ return !KJS::operator==(s1, s2);
+ }
+ bool operator==(const CString& s1, const CString& s2);
+ UString operator+(const UString& s1, const UString& s2);
+
+}; // namespace
+
+#endif