mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Merge with http://elinks.cz/elinks.git
This commit is contained in:
commit
b1f8756c59
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@ depcomp
|
||||
autom4te.cache
|
||||
stamp-h1
|
||||
.deps
|
||||
.vimrc
|
||||
elinks
|
||||
*.swp
|
||||
*.patch
|
||||
|
6
.vimrc
6
.vimrc
@ -1,6 +0,0 @@
|
||||
:set shiftwidth=8
|
||||
:set tabstop=8
|
||||
:set softtabstop=0
|
||||
:set noexpandtab
|
||||
|
||||
au BufNewFile,BufRead *.inc setf c
|
3
AUTHORS
3
AUTHORS
@ -161,6 +161,9 @@ Doug Kearns <djkea2@mugca.its.monash.edu.au>
|
||||
Edwin Groothuis <edwin@mavetju.org>
|
||||
Dump-width option
|
||||
|
||||
Eric Wald <eswald@gmail.com>
|
||||
Vim ftplugin to set ELinks coding style
|
||||
|
||||
Evan Hughes <hughes@lab43.org>
|
||||
Bookmarks
|
||||
|
||||
|
2
INSTALL
2
INSTALL
@ -26,9 +26,7 @@ from GIT in it, use the command:
|
||||
$ cg clone -s check_file_SITES_for_value_of_this
|
||||
|
||||
Note that if you obtained the sources directly from GIT, you NEED to run
|
||||
|
||||
./autogen.sh! (It should be enough to do it once - however, if you have build
|
||||
|
||||
problems, try running this first.) Also, you obviously need GNU make and
|
||||
autoconf installed on your system (note that autoconf-2.13 is supported, newer
|
||||
ones may cause problems thanks to the autoconf developers who don't know how to
|
||||
|
@ -43,12 +43,10 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
|
||||
TEST_LIB=$(top_srcdir)/test/libtest.sh
|
||||
export TEST_LIB
|
||||
|
||||
host = @host@
|
||||
|
||||
ASCIIDOC = @ASCIIDOC@
|
||||
ASCIIDOC_FLAGS = @ASCIIDOC_FLAGS@
|
||||
AWK = @AWK@
|
||||
CATALOGS = @CATALOGS@
|
||||
CC = @CC@
|
||||
@ -114,7 +112,9 @@ CONFIG_EXMODE = @CONFIG_EXMODE@
|
||||
CONFIG_FASTMEM = @CONFIG_FASTMEM@
|
||||
CONFIG_FINGER = @CONFIG_FINGER@
|
||||
CONFIG_FORMHIST = @CONFIG_FORMHIST@
|
||||
CONFIG_FSP = @CONFIG_FSP@
|
||||
CONFIG_FTP = @CONFIG_FTP@
|
||||
CONFIG_GC = @CONFIG_GC@
|
||||
CONFIG_GLOBHIST = @CONFIG_GLOBHIST@
|
||||
CONFIG_GNUTLS = @CONFIG_GNUTLS@
|
||||
CONFIG_GNUTLS_OPENSSL_COMPAT = @CONFIG_GNUTLS_OPENSSL_COMPAT@
|
||||
@ -130,7 +130,6 @@ CONFIG_LEDS = @CONFIG_LEDS@
|
||||
CONFIG_MAILCAP = @CONFIG_MAILCAP@
|
||||
CONFIG_MANUAL = @CONFIG_MANUAL@
|
||||
CONFIG_MARKS = @CONFIG_MARKS@
|
||||
CONFIG_MD5 = @CONFIG_MD5@
|
||||
CONFIG_MIMETYPES = @CONFIG_MIMETYPES@
|
||||
CONFIG_MOUSE = @CONFIG_MOUSE@
|
||||
CONFIG_NNTP = @CONFIG_NNTP@
|
||||
@ -143,7 +142,6 @@ CONFIG_OS_UNIX = @CONFIG_OS_UNIX@
|
||||
CONFIG_OS_WIN32 = @CONFIG_OS_WIN32@
|
||||
CONFIG_OWN_LIBC = @CONFIG_OWN_LIBC@
|
||||
CONFIG_POD2HTML = @CONFIG_POD2HTML@
|
||||
CONFIG_SCANNER = @CONFIG_SCANNER@
|
||||
CONFIG_SCRIPTING = @CONFIG_SCRIPTING@
|
||||
CONFIG_SCRIPTING_GUILE = @CONFIG_SCRIPTING_GUILE@
|
||||
CONFIG_SCRIPTING_LUA = @CONFIG_SCRIPTING_LUA@
|
||||
@ -151,7 +149,6 @@ CONFIG_SCRIPTING_PERL = @CONFIG_SCRIPTING_PERL@
|
||||
CONFIG_SCRIPTING_PYTHON = @CONFIG_SCRIPTING_PYTHON@
|
||||
CONFIG_SCRIPTING_RUBY = @CONFIG_SCRIPTING_RUBY@
|
||||
CONFIG_SCRIPTING_SPIDERMONKEY = @CONFIG_SCRIPTING_SPIDERMONKEY@
|
||||
CONFIG_SHA1 = @CONFIG_SHA1@
|
||||
CONFIG_SMALL = @CONFIG_SMALL@
|
||||
CONFIG_SMB = @CONFIG_SMB@
|
||||
CONFIG_SPIDERMONKEY = @CONFIG_SPIDERMONKEY@
|
||||
|
31
Makefile.lib
31
Makefile.lib
@ -48,7 +48,7 @@ quiet_cmd_ld_objs = " [$(LD_COLOR)LD$(END_COLOR)] $(RELPATH)$@"
|
||||
`test -e $(subdir)/$(LIB_O_NAME) && echo $(subdir)/$(LIB_O_NAME)`)
|
||||
|
||||
quiet_cmd_link = ' [$(LINK_COLOR)LINK$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(2) $(LIBS)
|
||||
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
quiet_cmd_sparse = ' [SPARSE] $(RELPATH)$(2)'
|
||||
cmd_sparse = $(SPARSE) $(DEFS) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) $(SPARSE_FLAGS) $(2)
|
||||
@ -78,9 +78,10 @@ INCLUDE_ALL=1
|
||||
endif
|
||||
|
||||
ifneq ($(findstring init,$(MAKECMDGOALS)),)
|
||||
# FIXME: Detect when $(subdir)/Makefile is $(srcdir)/$(subdir)/Makefile
|
||||
# and error out so the user won't overwrite the 'master' Makefiles.
|
||||
INCLUDE_ALL=1
|
||||
ifndef SRC
|
||||
SRC = $(shell cd $(top_srcdir) && pwd)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_ALL
|
||||
@ -92,7 +93,8 @@ endif
|
||||
#############################################################################
|
||||
# Internal build rules
|
||||
|
||||
# All files in $(OBJS) and any $(subdir)/lib.o are linked into lib.o
|
||||
# All files in $(OBJS) and any $(subdir)/lib.o are linked into lib.o.
|
||||
# Sort them to filter out duplicated and get uniform order.
|
||||
LIB_O_DEPS = \
|
||||
$(sort $(filter-out $(LIB_O_NAME),$(OBJS))) \
|
||||
$(foreach subdir,$(sort $(SUBDIRS)),$(wildcard $(subdir)/$(LIB_O_NAME)))
|
||||
@ -106,7 +108,7 @@ DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
|
||||
|
||||
ifneq ($(strip $(OBJS)),)
|
||||
-include $(DEP_FILES)
|
||||
OBJS += $(LIB_O_NAME)
|
||||
ALL_OBJS = $(LIB_O_DEPS) $(LIB_O_NAME)
|
||||
endif
|
||||
|
||||
%.o: $(srcdir)%.c
|
||||
@ -125,7 +127,7 @@ CLEAN += $(PROG) $(OBJS)
|
||||
#############################################################################
|
||||
# The main default rules
|
||||
|
||||
all-default: $(OBJS) $(PROGS) $(MAN1) $(MAN5)
|
||||
all-default: $(ALL_OBJS) $(PROGS) $(MAN1) $(MAN5)
|
||||
|
||||
# Ensure that Makefiles in subdirs are created before we recursive into them
|
||||
init-recursive: init-default
|
||||
@ -133,7 +135,8 @@ init-recursive: init-default
|
||||
init-default:
|
||||
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
||||
$(MKINSTALLDIRS) $(subdir) >/dev/null; \
|
||||
echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
|
||||
test -e "$(subdir)/Makefile" \
|
||||
|| echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
|
||||
|
||||
clean-default cleanall-default:
|
||||
@-test -z "$(CLEAN)" || $(RM) $(CLEAN)
|
||||
@ -161,7 +164,6 @@ ifdef MAN5
|
||||
$(call ncmd,installdata,$(file),$(DESTDIR)$(mandir)/man5);)
|
||||
endif
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Auto-testing infrastructure
|
||||
|
||||
@ -171,13 +173,16 @@ ifdef TEST_PROGS
|
||||
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
|
||||
TESTDEPS += $(TESTDEPS-yes)
|
||||
|
||||
TEST_LIB=$(top_srcdir)/test/libtest.sh
|
||||
export TEST_LIB
|
||||
|
||||
# This is a very general rule but as long as we don't put test programs in src/
|
||||
# it should work.
|
||||
%: %.o $(TESTDEPS)
|
||||
$(call cmd,link)
|
||||
|
||||
TESTS = $(wildcard $(srcdir)test-*)
|
||||
|
||||
$(TEST_PROGS): $(TESTDEPS)
|
||||
$(call cmd,link,$@.o)
|
||||
|
||||
# We cannot use $$@.o in the rule above so ensure that all test programs are
|
||||
# built before linking.
|
||||
$(TESTS): $(addsuffix .o,$(TEST_PROGS)) $(TEST_PROGS)
|
||||
@echo "*** $(notdir $@) ***"; \
|
||||
$(call shellquote,$(SHELL)) $@ $(TEST_OPTS)
|
||||
|
7
NEWS
7
NEWS
@ -5,6 +5,13 @@ You can see the complete list of recent changes, bugfixes and new features in
|
||||
the link:http://pasky.or.cz/gitweb.cgi[gitweb interface]. See the ChangeLog
|
||||
file for details.
|
||||
|
||||
ELinks now:
|
||||
-----------
|
||||
|
||||
* Native FSP protocol support (replaces CGI program in contrib/fsp/)
|
||||
* SEE Ecmascript backend
|
||||
* Minimalistic RSS renderer
|
||||
|
||||
ELinks 0.11.0 (Elated):
|
||||
-----------------------
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -90,16 +90,17 @@ if test "$CONFIG_SCRIPTING_RUBY" = "yes"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
EL_RESTORE_FLAGS
|
||||
|
||||
if test "$CONFIG_SCRIPTING_RUBY" != "yes"; then
|
||||
if test -n "$CONFIG_SCRIPTING_RUBY_WITHVAL" &&
|
||||
test "$CONFIG_SCRIPTING_RUBY_WITHVAL" != no; then
|
||||
AC_MSG_ERROR([Ruby not found])
|
||||
fi
|
||||
EL_RESTORE_FLAGS
|
||||
else
|
||||
EL_CONFIG(CONFIG_SCRIPTING_RUBY, [Ruby])
|
||||
|
||||
CFLAGS="$CFLAGS_X"
|
||||
LIBS="$LIBS $RUBY_LIBS"
|
||||
AC_SUBST(RUBY_CFLAGS)
|
||||
AC_SUBST(RUBY_LIBS)
|
||||
fi
|
||||
|
168
configure.in
168
configure.in
@ -66,6 +66,12 @@ if test "x$CONFIG_DOC" != xno; then
|
||||
EL_CONFIG(CONFIG_ASCIIDOC, [AsciiDoc])
|
||||
EL_CONFIG(MANUAL_ASCIIDOC, [HTML (one file)])
|
||||
EL_CONFIG(MAN_ASCIIDOC, [HTML])
|
||||
|
||||
echo > config.asciidoc-unsafe.txt
|
||||
if "$ASCIIDOC" --unsafe config.asciidoc-unsafe.txt >&/dev/null; then
|
||||
ASCIIDOC_FLAGS=--unsafe
|
||||
fi
|
||||
rm config.asciidoc-unsafe.*
|
||||
fi
|
||||
|
||||
AC_PATH_PROGS(XMLTO, "xmlto")
|
||||
@ -87,6 +93,7 @@ if test "x$CONFIG_DOC" != xno; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(ASCIIDOC_FLAGS)
|
||||
AC_SUBST(CONFIG_ASCIIDOC)
|
||||
AC_SUBST(CONFIG_POD2HTML)
|
||||
AC_SUBST(CONFIG_XMLTO)
|
||||
@ -388,9 +395,22 @@ AC_DEFUN([EL_CHECK_OPTIONAL_LIBRARY],
|
||||
AC_MSG_RESULT(yes)
|
||||
EL_SAVE_FLAGS
|
||||
if test -n "$withval" && test -d "$withval"; then
|
||||
CFLAGS="$CFLAGS -I$withval/include";
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include";
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib";
|
||||
# Be a little more careful when setting
|
||||
# include and lib directories. This way
|
||||
# $withval will work when includes are
|
||||
# there but the library is in the common
|
||||
# /usr/lib ... Does the right thing when
|
||||
# looking for gc on Debian.
|
||||
if test -d "$withval/include"; then
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
else
|
||||
CFLAGS="$CFLAGS -I$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"
|
||||
fi
|
||||
if test -d "$withval/lib"; then
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([$3], [$1=yes], [$1=no; break;])
|
||||
@ -439,6 +459,11 @@ EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_BZIP2, bzlib, bzlib.h, bz2, BZ2_bzReadOpen,
|
||||
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_IDN, idn, idna.h, idn, stringprep_check_version,
|
||||
[ --without-idn disable international domain names support])
|
||||
|
||||
if test "x{with_gc}" != xno; then
|
||||
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GC, gc, gc.h, gc, GC_init,
|
||||
[ --with-gc enable Boehm's garbage collector])
|
||||
fi
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Bookmark and XBEL support
|
||||
dnl ===================================================================
|
||||
@ -507,6 +532,8 @@ AC_ARG_WITH(see, [ --with-see enable Simple Ecmascript Engine (SEE
|
||||
|
||||
AC_MSG_CHECKING([for SEE])
|
||||
|
||||
CONFIG_ECMASCRIPT_SEE=no
|
||||
|
||||
if test "$enable_see" = "yes"; then
|
||||
AC_MSG_RESULT(yes);
|
||||
## Based on the SEE_FLAGS macro.
|
||||
@ -529,7 +556,6 @@ if test "$enable_see" = "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS $SEE_CFLAGS"
|
||||
EL_CONFIG(CONFIG_ECMASCRIPT_SEE, [SEE])
|
||||
AC_SUBST(SEE_CFLAGS)
|
||||
AC_SUBST(CONFIG_ECMASCRIPT_SEE)
|
||||
else
|
||||
if test -n "$withval" && test "x$withval" != xno; then
|
||||
AC_MSG_ERROR([SEE not found])
|
||||
@ -583,26 +609,19 @@ if test -z "$disable_spidermonkey"; then
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT($cf_result)
|
||||
CONFIG_SPIDERMONKEY="$cf_result"
|
||||
EL_RESTORE_FLAGS
|
||||
|
||||
if test "$cf_result" != yes; then
|
||||
EL_RESTORE_FLAGS
|
||||
else
|
||||
EL_CONFIG(CONFIG_SPIDERMONKEY, [SpiderMonkey])
|
||||
|
||||
CFLAGS="$CFLAGS_X"
|
||||
AC_SUBST(SPIDERMONKEY_LIBS)
|
||||
AC_SUBST(SPIDERMONKEY_CFLAGS)
|
||||
fi
|
||||
|
||||
if test "$CONFIG_SPIDERMONKEY" = yes &&
|
||||
test "$CONFIG_ECMASCRIPT_SEE" != yes; then
|
||||
if test "x$CONFIG_SPIDERMONKEY" = xyes &&
|
||||
test "x$CONFIG_ECMASCRIPT_SEE" != xyes; then
|
||||
EL_CONFIG(CONFIG_ECMASCRIPT_SMJS, [SpiderMonkey document scripting])
|
||||
else
|
||||
CONFIG_ECMASCRIPT_SMJS=no
|
||||
fi
|
||||
|
||||
AC_SUBST(CONFIG_SPIDERMONKEY)
|
||||
AC_SUBST(CONFIG_ECMASCRIPT_SMJS)
|
||||
|
||||
EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_ECMASCRIPT_SEE CONFIG_ECMASCRIPT_SMJS], [ECMAScript (JavaScript)])
|
||||
AC_SUBST(CONFIG_ECMASCRIPT_SEE)
|
||||
AC_SUBST(CONFIG_ECMASCRIPT_SMJS)
|
||||
|
||||
|
||||
dnl ===================================================================
|
||||
@ -621,6 +640,13 @@ else
|
||||
CONFIG_SCRIPTING_SPIDERMONKEY=no
|
||||
fi
|
||||
|
||||
if test "x$CONFIG_ECMASCRIPT_SMJS" = xyes ||
|
||||
test "x$CONFIG_SCRIPTING_SPIDERMONKEY" = xyes; then
|
||||
LIBS="$LIBS $SPIDERMONKEY_LIBS"
|
||||
AC_SUBST(SPIDERMONKEY_LIBS)
|
||||
AC_SUBST(SPIDERMONKEY_CFLAGS)
|
||||
AC_SUBST(CONFIG_SPIDERMONKEY)
|
||||
fi
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Check for Guile, optional even if installed.
|
||||
@ -732,13 +758,17 @@ dnl Check for Python
|
||||
dnl ===================================================================
|
||||
enable_python="no";
|
||||
|
||||
AC_ARG_WITH(python, [ --with-python enable Python support],
|
||||
AC_ARG_WITH(python, [ --with-python=[prefix] enable Python support],
|
||||
[
|
||||
if test "$withval" = yes; then
|
||||
if test "$withval" != no; then
|
||||
# FIXME: If withval is a valid directory append it to PATH
|
||||
# so that you can specify one of several Python installations.
|
||||
withval="";
|
||||
enable_python=yes;
|
||||
if test "$withval" != yes; then
|
||||
python_prefix="$withval"
|
||||
else
|
||||
python_prefix=""
|
||||
fi
|
||||
enable_python=yes
|
||||
cat <<EOF
|
||||
***********************************************************************
|
||||
The Python support is incomplete and not so well integrated to ELinks
|
||||
@ -750,35 +780,46 @@ EOF
|
||||
fi
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([for Python])
|
||||
|
||||
cf_result=no
|
||||
|
||||
EL_SAVE_FLAGS
|
||||
|
||||
if test "$enable_python" = "yes"; then
|
||||
if test -n "$python_prefix" && test -d "$python_prefix/bin"; then
|
||||
PYTHON_PATH="$python_prefix/bin:$PATH"
|
||||
else
|
||||
PYTHON_PATH="$PATH"
|
||||
fi
|
||||
AC_PATH_PROG(PYTHON, python, no, $PYTHON_PATH)
|
||||
if test "$PYTHON" = "no" ; then
|
||||
cf_result=no
|
||||
else
|
||||
PYTHON_CFLAGS="-I`$PYTHON -c 'from distutils import sysconfig; print sysconfig.get_python_inc()' 2> /dev/null`"
|
||||
if test -n "$python_prefix" && test -d "$python_prefix/lib"; then
|
||||
PYTHON_LIBS="-L$python_prefix/lib -lpython"
|
||||
else
|
||||
PYTHON_LIBS="-lpython"
|
||||
PYTHON_CFLAGS="-I`python -c 'from distutils import sysconfig; print sysconfig.get_python_inc()' 2> /dev/null`"
|
||||
fi
|
||||
LIBS="$PYTHON_LIBS $LIBS"
|
||||
CFLAGS="$PYTHON_CFLAGS $CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CFLAGS"
|
||||
AC_TRY_LINK([
|
||||
#include <Python.h>
|
||||
],
|
||||
AC_TRY_LINK([#include <Python.h>],
|
||||
[Py_Initialize();],
|
||||
cf_result=yes, cf_result=no)
|
||||
fi
|
||||
|
||||
if test "$cf_result" != "yes"; then
|
||||
if test "$cf_result" != "yes"; then
|
||||
EL_RESTORE_FLAGS
|
||||
else
|
||||
else
|
||||
EL_CONFIG(CONFIG_SCRIPTING_PYTHON, [Python])
|
||||
|
||||
CFLAGS="$CFLAGS_X"
|
||||
AC_SUBST(PYTHON_LIBS)
|
||||
AC_SUBST(PYTHON_CFLAGS)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for Python])
|
||||
if test "$cf_result"; then AC_MSG_RESULT($cf_result); fi
|
||||
|
||||
|
||||
@ -947,6 +988,7 @@ fi
|
||||
|
||||
AC_MSG_RESULT($cf_result)
|
||||
|
||||
CONFIG_GNUTLS_OPENSSL_COMPAT=no
|
||||
dnl ---- GNU TLS
|
||||
dnl We can't have AC_MSG_CHECKING here, because AC_PATH_PROG prints its own and
|
||||
dnl it looks ugly then.
|
||||
@ -1132,6 +1174,34 @@ EL_ARG_DEPEND(CONFIG_CGI, cgi, [HAVE_SETENV_OR_PUTENV:yes], [Local CGI],
|
||||
EL_ARG_ENABLE(CONFIG_FINGER, finger, [Finger protocol],
|
||||
[ --enable-finger enable finger protocol support])
|
||||
|
||||
dnl ===================================================================
|
||||
dnl FSP protocol
|
||||
dnl ===================================================================
|
||||
EL_SAVE_FLAGS
|
||||
|
||||
if test "x${enable_fsp}" != xno; then
|
||||
AC_CHECK_HEADERS(fsplib.h, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
|
||||
|
||||
if test "$HAVE_FSPLIB" = yes; then
|
||||
AC_CHECK_LIB(fsplib, fsp_open_session, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
|
||||
if test "$HAVE_FSPLIB" = yes; then
|
||||
LIBS="$LIBS -lfsplib"
|
||||
else
|
||||
AC_CHECK_LIB(fsp, fsp_open_session, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
|
||||
if test "$HAVE_FSPLIB" = yes; then
|
||||
LIBS="$LIBS -lfsp"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
EL_ARG_DEPEND(CONFIG_FSP, fsp, [HAVE_FSPLIB:yes], [FSP protocol],
|
||||
[ --enable-fsp enable FSP protocol support])
|
||||
|
||||
if test "x$CONFIG_FSP" = xno; then
|
||||
EL_RESTORE_FLAGS
|
||||
fi
|
||||
|
||||
EL_ARG_ENABLE(CONFIG_FTP, ftp, [FTP protocol],
|
||||
[ --disable-ftp disable ftp protocol support])
|
||||
|
||||
@ -1201,35 +1271,6 @@ EL_ARG_ENABLE(CONFIG_OWN_LIBC, own-libc, [Own libc stubs],
|
||||
EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary],
|
||||
[ --enable-small reduce binary size as far as possible (but see the bottom of doc/small.txt!)])
|
||||
|
||||
if test "$CONFIG_OPENSSL" != yes &&
|
||||
test "$CONFIG_GNUTLS_OPENSSL_COMPAT" != yes ||
|
||||
test "$CONFIG_OWN_LIBC" = yes;
|
||||
then
|
||||
AC_MSG_CHECKING(for built-in MD5 support)
|
||||
AC_MSG_RESULT(yes)
|
||||
EL_CONFIG(CONFIG_MD5, [Built-in MD5])
|
||||
fi
|
||||
|
||||
AC_SUBST(CONFIG_MD5)
|
||||
|
||||
if test "$CONFIG_BITTORRENT" = yes; then
|
||||
if test "$CONFIG_OPENSSL" != yes ||
|
||||
test "$CONFIG_OWN_LIBC" = yes;
|
||||
then
|
||||
AC_MSG_CHECKING(for built-in SHA1 support)
|
||||
AC_MSG_RESULT(yes)
|
||||
EL_CONFIG(CONFIG_SHA1, [Built-in SHA1])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(CONFIG_SHA1)
|
||||
|
||||
if test "$CONFIG_CSS" = yes || test "$CONFIG_DOM" = yes;
|
||||
then
|
||||
EL_CONFIG(CONFIG_SCANNER, [Built-in scanner])
|
||||
fi
|
||||
AC_SUBST(CONFIG_SCANNER)
|
||||
|
||||
AC_ARG_ENABLE(weehoofooboomookerchoo,
|
||||
[
|
||||
Also check out the features.conf file for more information about features!
|
||||
@ -1347,10 +1388,13 @@ AC_OUTPUT([ \
|
||||
abs_srcdir="$(cd "$srcdir" && pwd)"
|
||||
# builddir is always absolute!
|
||||
if test "$abs_srcdir" != "$builddir"; then
|
||||
# Bootstrap the Makefile creation
|
||||
echo "include $abs_srcdir/Makefile" > "$builddir/Makefile"
|
||||
"$MAKE" "SRC=$abs_srcdir" init
|
||||
fi
|
||||
|
||||
# Make cg-status ignore this build directory
|
||||
echo "*" > "$builddir/.gitignore"
|
||||
fi
|
||||
|
||||
dnl ===================================================================
|
||||
dnl Configuration summary
|
||||
|
@ -1,2 +0,0 @@
|
||||
fspcgi: fspcgi.o
|
||||
$(CC) -o $@ $< -lfsplib
|
@ -1,8 +0,0 @@
|
||||
To use this CGI script you need to build fspcgi and copy the executable
|
||||
to your cgi directory. In ELinks, you can then use this URL:
|
||||
|
||||
file:///"path_to_fspcgi"?host:port/path_to_file_or_directory
|
||||
|
||||
You can find more info about the FSP protocol at
|
||||
|
||||
http://fsp.sourceforge.net/
|
@ -1,172 +0,0 @@
|
||||
/* CGI script for FSP protocol support */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fsplib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char *pname, *query;
|
||||
|
||||
struct fq {
|
||||
char *password;
|
||||
char *host;
|
||||
char *path;
|
||||
unsigned short port;
|
||||
} data;
|
||||
|
||||
static void
|
||||
error(const char *str)
|
||||
{
|
||||
printf("Content-Type: text/plain\r\nConnection: close\r\n\r\n");
|
||||
puts(str);
|
||||
printf("%s\n", query);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
process_directory(FSP_SESSION *ses)
|
||||
{
|
||||
char buf[1024];
|
||||
FSP_DIR *dir;
|
||||
/* TODO: password */
|
||||
|
||||
snprintf(buf, sizeof(buf), "file://%s?%s:%d%s/", pname, data.host,
|
||||
data.port, data.path);
|
||||
printf("Content-Type: text/html\r\n\r\n");
|
||||
printf("<html><head><title>%s</title></head><body>\n", buf);
|
||||
dir = fsp_opendir(ses, data.path);
|
||||
if (dir) {
|
||||
FSP_RDENTRY fentry, *fresult;
|
||||
|
||||
while (!fsp_readdir_native(dir, &fentry, &fresult)) {
|
||||
if (!fresult) break;
|
||||
printf("<a href=\"%s%s\">%s</a><br>\n", buf, fentry.name, fentry.name);
|
||||
}
|
||||
fsp_closedir(dir);
|
||||
}
|
||||
puts("</body></html>");
|
||||
fsp_close_session(ses);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
process_data(void)
|
||||
{
|
||||
FSP_SESSION *ses = fsp_open_session(data.host, data.port, data.password);
|
||||
struct stat sb;
|
||||
|
||||
if (!ses) error("Session initialization failed.");
|
||||
if (fsp_stat(ses, data.path, &sb)) error("File not found.");
|
||||
if (S_ISDIR(sb.st_mode)) process_directory(ses);
|
||||
else { /* regular file */
|
||||
char buf[4096];
|
||||
FSP_FILE *file = fsp_fopen(ses, data.path, "r");
|
||||
int r;
|
||||
|
||||
if (!file) error("fsp_fopen error.");
|
||||
printf("Content-Type: application/octet-stream\r\nContent-Length: %d\r\n"
|
||||
"Connection: close\r\n\r\n", sb.st_size);
|
||||
while ((r = fsp_fread(buf, 1, 4096, file)) > 0) fwrite(buf, 1, r, stdout);
|
||||
fsp_fclose(file);
|
||||
fsp_close_session(ses);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_query(void)
|
||||
{
|
||||
char *at = strchr(query, '@');
|
||||
char *colon;
|
||||
char *slash;
|
||||
|
||||
if (at) {
|
||||
*at = '\0';
|
||||
data.password = strdup(query);
|
||||
query = at + 1;
|
||||
}
|
||||
colon = strchr(query, ':');
|
||||
if (colon) {
|
||||
*colon = '\0';
|
||||
data.host = strdup(query);
|
||||
data.port = atoi(colon + 1);
|
||||
slash = strchr(colon + 1, '/');
|
||||
if (slash) {
|
||||
data.path = strdup(slash);
|
||||
} else {
|
||||
data.path = "/";
|
||||
}
|
||||
} else {
|
||||
data.port = 21;
|
||||
slash = strchr(query, '/');
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
data.host = strdup(query);
|
||||
*slash = '/';
|
||||
data.path = strdup(slash);
|
||||
} else {
|
||||
data.host = strdup(query);
|
||||
data.path = "/";
|
||||
}
|
||||
}
|
||||
process_data();
|
||||
}
|
||||
|
||||
static inline int
|
||||
unhx(register unsigned char a)
|
||||
{
|
||||
if (isdigit(a)) return a - '0';
|
||||
if (a >= 'a' && a <= 'f') return a - 'a' + 10;
|
||||
if (a >= 'A' && a <= 'F') return a - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_query(char *src)
|
||||
{
|
||||
char *dst = src;
|
||||
char c;
|
||||
|
||||
do {
|
||||
c = *src++;
|
||||
|
||||
if (c == '%') {
|
||||
int x1 = unhx(*src);
|
||||
|
||||
if (x1 >= 0) {
|
||||
int x2 = unhx(*(src + 1));
|
||||
|
||||
if (x2 >= 0) {
|
||||
x1 = (x1 << 4) + x2;
|
||||
if (x1 != 0) { /* don't allow %00 */
|
||||
c = (unsigned char) x1;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (c == '+') {
|
||||
c = ' ';
|
||||
}
|
||||
|
||||
*dst++ = c;
|
||||
} while (c != '\0');
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *q = getenv("QUERY_STRING");
|
||||
|
||||
if (!q) return 1;
|
||||
pname = argv[0];
|
||||
query = strdup(q);
|
||||
if (!query) return 2;
|
||||
decode_query(query);
|
||||
process_query();
|
||||
return 0;
|
||||
}
|
13
contrib/python/README.Python
Normal file
13
contrib/python/README.Python
Normal file
@ -0,0 +1,13 @@
|
||||
If you want to use Python scripting with ELinks add
|
||||
--with-python to the configure invocation copy hooks.py to ~/.elinks
|
||||
When your Python installation is your own build, you could give prefix
|
||||
to the configure, eg.
|
||||
--with-python=/usr/local when Python binary is placed in /usr/local/bin, etc.
|
||||
|
||||
When 'configure' cannot find -lpython make symbolic link to the appropriate
|
||||
library, eg.
|
||||
# cd /usr/local/lib
|
||||
# ln -s libpython2.4.so.1.0 libpython.so
|
||||
|
||||
For the present hooks.py is not very usable. You are welcome to make it better.
|
||||
Good Luck!
|
@ -1,10 +1,41 @@
|
||||
def goto_url_hook(url):
|
||||
import re
|
||||
|
||||
dumbprefixes = {
|
||||
"7th" : "http://7thguard.net/",
|
||||
"b" : "http://babelfish.altavista.com/babelfish/tr",
|
||||
"bz" : "http://bugzilla.elinks.cz",
|
||||
"bug" : "http://bugzilla.elinks.cz",
|
||||
"d" : "http://www.dict.org",
|
||||
"g" : "http://www.google.com/",
|
||||
"gg" : "http://www.google.com/",
|
||||
"go" : "http://www.google.com/",
|
||||
"fm" : "http://www.freshmeat.net/",
|
||||
"sf" : "http://www.sourceforge.net/",
|
||||
"dbug" : "http://bugs.debian.org/",
|
||||
"dpkg" : "http://packages.debian.org/",
|
||||
"pycur" : "http://www.python.org/doc/current/",
|
||||
"pydev" : "http://www.python.org/dev/doc/devel/",
|
||||
"pyhelp" : "http://starship.python.net/crew/theller/pyhelp.cgi",
|
||||
"pyvault" : "http://www.vex.net/parnassus/",
|
||||
"e2" : "http://www.everything2.org/",
|
||||
"sd" : "http://www.slashdot.org/"
|
||||
}
|
||||
|
||||
def goto_url_hook(url, current_url):
|
||||
global dumbprefixes
|
||||
|
||||
if dumbprefixes.has_key(url):
|
||||
return dumbprefixes[url];
|
||||
else:
|
||||
return None
|
||||
|
||||
def follow_url_hook(url):
|
||||
return None
|
||||
|
||||
def pre_format_html_hook(url, html):
|
||||
if re.search("cygwin\.com", url):
|
||||
html2 = re.sub("<body bgcolor=\"#000000\" color=\"#000000\"", "<body bgcolor=\"#ffffff\" color=\"#000000\"", html)
|
||||
return html2
|
||||
return None
|
||||
|
||||
def proxy_for_hook(url):
|
||||
|
17
contrib/smjs/google_video.js
Normal file
17
contrib/smjs/google_video.js
Normal file
@ -0,0 +1,17 @@
|
||||
/* Play videos at video.google.com with minimal niggling. Just follow the link
|
||||
* from the front page or the search page, and the video will automatically
|
||||
* be loaded. */
|
||||
function load_google_video(cached, vs) {
|
||||
if (!cached.uri.match(/^http:\/\/video.google.com\/videoplay/))
|
||||
return true;
|
||||
|
||||
var re = /(<object data="\/googleplayer.swf\?videoUrl=)(.*?)(\&.*?<\/object>)/;
|
||||
var match = cached.content.match(re);
|
||||
var url = unescape(match[2]);
|
||||
var meta = '<meta http-equiv="refresh" content="1; url=' + url + '" />';
|
||||
|
||||
cached.content = cached.content.replace(/<head>/, "<head>" + meta);
|
||||
|
||||
return true;
|
||||
}
|
||||
elinks.preformat_html_hooks.push(load_google_video);
|
@ -8,9 +8,9 @@ elinks.keymaps.main["@"] = function () {
|
||||
};
|
||||
|
||||
elinks.preformat_html_hooks = new Array();
|
||||
elinks.preformat_html = function (cached) {
|
||||
elinks.preformat_html = function (cached, vs) {
|
||||
for (var i in elinks.preformat_html_hooks)
|
||||
if (!elinks.preformat_html_hooks[i](cached))
|
||||
if (!elinks.preformat_html_hooks[i](cached, vs))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -36,13 +36,13 @@ elinks.follow_url_hook = function (url) {
|
||||
return url;
|
||||
};
|
||||
|
||||
function root_w00t(cached) {
|
||||
function root_w00t(cached, vs) {
|
||||
cached.content = cached.content.replace(/root/g, "w00t");
|
||||
return true;
|
||||
};
|
||||
elinks.preformat_html_hooks.push(root_w00t);
|
||||
|
||||
function mangle_deb_bugnumbers(cached) {
|
||||
function mangle_deb_bugnumbers(cached, vs) {
|
||||
if (!cached.uri.match(/^[a-z0-9]+:\/\/[a-z0-9A-Z.-]+debian\.org/)
|
||||
&& !cached.uri.match(/changelog\.Debian/))
|
||||
return true;
|
||||
@ -55,7 +55,14 @@ function mangle_deb_bugnumbers(cached) {
|
||||
/* Debian Policy Manual 4.4 footnote 16 */
|
||||
var closes_re = /closes:\s*(?:bug)?\#?\s?\d+(?:,\s*(?:bug)?\#?\s?\d+)*/gi;
|
||||
|
||||
cached.content = cached.content.replace(closes_re, rewrite_closes_fn);
|
||||
var new_content = cached.content.replace(closes_re, rewrite_closes_fn);
|
||||
if (cached.type == 'text/plain') {
|
||||
cached.content = '<pre>' + new_content + '</pre>';
|
||||
vs.plain = "0";
|
||||
} else {
|
||||
cached.content = new_content;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ function cvsweb (base, project, url)
|
||||
/* javascript:gitweb("http://pasky.or.cz/gitweb.cgi", "elinks.git", "%s"); */
|
||||
function gitweb(base, project, url)
|
||||
{
|
||||
var parts = url.match(/^(search|summary|shortlog|log|commit|commitdiff|tree|tag)(\s(.*))?/);
|
||||
var parts = url.match(/^(search|summary|shortlog|log|blob|commit|commitdiff|history|tree|tag)(\s(.*))?/);
|
||||
var query = '?p=' + project;
|
||||
|
||||
if (parts) {
|
||||
@ -67,6 +67,8 @@ function gitweb(base, project, url)
|
||||
/* If the extra arg is not for searching assume it is an ID. */
|
||||
if (parts[1] == 'search' && parts[3])
|
||||
query += ';s=' + escape(parts[3]);
|
||||
else if ((parts[1] == 'blob' || parts[1] == 'history' || parts[1] == 'tree') && parts[3])
|
||||
query += ';f=' + escape(parts[3]);
|
||||
else if (parts[3])
|
||||
query += ';h=' + escape(parts[3]);
|
||||
|
||||
|
15
contrib/vim/c_elinks.vim
Normal file
15
contrib/vim/c_elinks.vim
Normal file
@ -0,0 +1,15 @@
|
||||
" Setting Vim to support the ELinks coding style
|
||||
"
|
||||
" To use this file, drop it in ~/.vim/ftplugin and set filetype plugin on.
|
||||
" Finally, make sure the path to the source directory contains the word
|
||||
" 'elinks', for example ~/src/elinks/.
|
||||
"
|
||||
" For .h files, link it as cpp_elinks.vim or define c_syntax_for_h in ~/.vimrc.
|
||||
" For .inc files, let g:filetype_inc = 'c' in ~/.vimrc.
|
||||
|
||||
if expand('%:p:h') =~ '.*elinks.*'
|
||||
setlocal shiftwidth=8
|
||||
setlocal tabstop=8
|
||||
setlocal softtabstop=0
|
||||
setlocal noexpandtab
|
||||
endif
|
2
debian/.vimrc
vendored
2
debian/.vimrc
vendored
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../.vimrc
|
32
doc/Makefile
32
doc/Makefile
@ -12,6 +12,9 @@ docdir = $(datadir)/doc
|
||||
HTML_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/html
|
||||
PDF_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/pdf
|
||||
|
||||
ASCIIDOC_CONF = $(srcdir)asciidoc.conf
|
||||
ASCIIDOC_FLAGS += -f $(ASCIIDOC_CONF) -a "builddir=$(CURDIR)/"
|
||||
|
||||
#############################################################################
|
||||
# Build files
|
||||
|
||||
@ -108,11 +111,14 @@ quiet_cmd_help2doc = ' [$(LINK_COLOR)HELP2DOC$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_help2doc = $(LOCALES) $(HELP2DOC) $(ELINKS) $@ > $@
|
||||
|
||||
quiet_cmd_conf2doc = ' [$(LINK_COLOR)CONF2DOC$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_conf2doc = $(LOCALES) $(CONF2DOC) > $@
|
||||
cmd_conf2doc = $(LOCALES) $(CONF2DOC) $(FEATURES) > $@
|
||||
|
||||
quiet_cmd_keys2doc = ' [$(LINK_COLOR)KEYS2DOC$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_keys2doc = $(LOCALES) $(KEYS2DOC) $(KBDBIND) $@ > $@
|
||||
|
||||
quiet_cmd_code2doc = ' [$(LINK_COLOR)CODE2DOC$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_code2doc = $(LOCALES) $(CODE2DOC) $< > $@
|
||||
|
||||
features.txt: $(FEATURES) $(CONF2DOC)
|
||||
$(call cmd,conf2doc)
|
||||
|
||||
@ -130,10 +136,10 @@ API = $(shell find $(top_srcdir)/src/ -name '*.h' -exec grep -q 'API Doc' \{\} \
|
||||
endif
|
||||
|
||||
define api_doc
|
||||
API_TXT += api/$(2).txt
|
||||
api/$(2).txt: $(1) $(CODE2DOC)
|
||||
@test -d api || $(MKINSTALLDIRS) api
|
||||
@$(CODE2DOC) $(1) > $$@
|
||||
API_TXT += api/$(2).txt
|
||||
$$(call cmd,code2doc)
|
||||
endef
|
||||
|
||||
api_name = $(shell sed -n 's/.*API Doc\s*::\s*\([^ ]*\).*/\1/p' < $(1))
|
||||
@ -149,25 +155,27 @@ api: $(patsubst %.txt,%.html,$(API_TXT))
|
||||
cmd_jw = $(JW) -b $(2) $<
|
||||
|
||||
quiet_cmd_xmlto = ' [$(LINK_COLOR)XMLTO$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_xmlto = $(XMLTO) $(3) $(2) $<
|
||||
cmd_xmlto = $(XMLTO) -o $(call outdir) $(3) $(2) $<
|
||||
|
||||
quiet_cmd_pod2html = ' [$(LINK_COLOR)POD2HTML$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_pod2html = $(POD2HTML) --outfile=$@ < $<
|
||||
|
||||
quiet_cmd_asciidoc = ' [$(LINK_COLOR)ASCIIDOC$(END_COLOR)] $(RELPATH)$@'
|
||||
cmd_asciidoc = $(ASCIIDOC) -f asciidoc.conf -b $(2) -d $(call doctype,$<) -o $@ $<
|
||||
cmd_asciidoc = $(ASCIIDOC) $(ASCIIDOC_FLAGS) -b $(call backend) -d $(call doctype) -o $@ $<
|
||||
|
||||
# Based on filename in $(1) find out asciidoc doctype.
|
||||
doctype = $(if $(findstring .1.,$(1)),manpage,$(if $(findstring .5.,$(1)),manpage,book))
|
||||
# Based on $@ find out asciidoc doctype or backend + xmlto output dir.
|
||||
doctype = $(if $(findstring .1.,$@)$(findstring .5.,$@),manpage,book)
|
||||
backend = $(if $(findstring .xml,$@),docbook,xhtml11)
|
||||
outdir = $(if $(findstring -chunked,$@),$@,.)
|
||||
|
||||
# Loosely track dependencies via asciidoc includes.
|
||||
asciidoc_dep = sed -n 's@include::\(.*\)\[.*@$@: \1@p' < $< > .deps/$(@F).asciidoc
|
||||
asciidoc_dep = sed -n 's/[{]builddir}//g;s@include::\(.*\)\[.*@$@: $< \1@p' < $< > .deps/$(@F).asciidoc
|
||||
|
||||
-include .deps/*.asciidoc
|
||||
|
||||
# Do a little post-processing of man pages. Inserting title headers and date.
|
||||
MAN_DATE = $(shell date -I)
|
||||
man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(subst .xml,.txt,$<)`
|
||||
man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(srcdir)$(subst .xml,.txt,$(<F))`
|
||||
man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\" \"$(1)\"/" < $@ | \
|
||||
sed "s/@squote@/\\\\'/g" > $@.tmp && mv $@.tmp $@
|
||||
|
||||
@ -175,11 +183,11 @@ man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\"
|
||||
#############################################################################
|
||||
# Build recipies
|
||||
|
||||
%.html: %.txt asciidoc.conf
|
||||
%.html: %.txt $(ASCIIDOC_CONF)
|
||||
$(call cmd,asciidoc,xhtml11)
|
||||
@-$(call asciidoc_dep)
|
||||
|
||||
%.xml: %.txt asciidoc.conf
|
||||
%.xml: %.txt $(ASCIIDOC_CONF)
|
||||
$(call cmd,asciidoc,docbook)
|
||||
@-$(call asciidoc_dep)
|
||||
|
||||
@ -192,7 +200,7 @@ man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\"
|
||||
@$(call man_hack,$(call man_desc))
|
||||
|
||||
%.html-chunked: %.xml
|
||||
$(call cmd,xmlto,html,-o $@)
|
||||
$(call cmd,xmlto,html)
|
||||
|
||||
%.pdf: %.xml
|
||||
$(call cmd,jw,pdf)
|
||||
|
45
doc/README
45
doc/README
@ -57,7 +57,8 @@ in this directory or it's children.
|
||||
submitting patches etc., thus every aspiring developer should take the
|
||||
pains to read through it, do not forget to also look for README and similar
|
||||
text files in the subdirectories containing the relevant sources for
|
||||
detailed notes regarding given modules/subsystems.
|
||||
detailed notes regarding given modules/subsystems. Additionally, it is
|
||||
possible to build API docs. More about this below.
|
||||
|
||||
The Lua Scripting Book ...................... lua-scripting.txt
|
||||
Events Reference Sheet ...................... events.txt
|
||||
@ -94,7 +95,10 @@ and the following man page formats:
|
||||
- HTML (asciidoc)
|
||||
- man / groff (asciidoc + xmlto)
|
||||
|
||||
Note: You do not need to build manpages. They are shipped with ELinks.
|
||||
Note: You do not need to build manpages. They are shipped with ELinks. However,
|
||||
if you want to have the manpages to match your local configuration and changes
|
||||
you can rebuild them (this is mostly an issue with elinks.conf(5) which might
|
||||
otherwise contain options that is not supported by the version you install.
|
||||
|
||||
Note: You must first build the ELinks binary for "make all-docs" to work
|
||||
successfully. The binary is used for getting option documentation.
|
||||
@ -103,6 +107,43 @@ The documentation can be installed with:
|
||||
|
||||
$ make install-doc
|
||||
|
||||
Building API documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There is some starting effort to make it possible to build HTML documentation
|
||||
of the APIs presented by the different modules and subsystems in ELinks. To
|
||||
build API documentation run:
|
||||
|
||||
$ make api
|
||||
|
||||
in the doc/ directory. The API documentation can then be found in the doc/api/
|
||||
directory.
|
||||
|
||||
NOTE: Currently only few files provides API docs and there is no over-all
|
||||
structure of the various APIs.
|
||||
|
||||
The API toolchain uses a Perl script (doc/tools/code2doc) to extract info from
|
||||
header files and generate text files with AsciiDoc markup. The text files are
|
||||
then converted to HTML with AsciiDoc.
|
||||
|
||||
To get an idea of how the code markup works take a look at src/dom/stack.h.
|
||||
It has a small tag saying that it provides API docs for the dom-stack module:
|
||||
|
||||
/* API Doc :: dom-stack */
|
||||
|
||||
The API doc markup should be pretty straight forward. Here is an example of the
|
||||
basic structure:
|
||||
|
||||
/** <title>
|
||||
*
|
||||
* <content>
|
||||
*/
|
||||
|
||||
Only text in comments starting with '/**' are used. If the comment immediately
|
||||
preceeds a declaration of some struct, enum, typedef, function, or macro, the
|
||||
name of the declared identifier will be used when creating the output to create
|
||||
anchors which can be referred to using ref:[].
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
@ -35,7 +35,7 @@ Most options can be set in the user interface or config file, so usually you
|
||||
do not need to care about them. Note that this list is roughly equivalent to
|
||||
the output of running ELinks with the option `--long-help`.
|
||||
|
||||
include::option-command.txt[]
|
||||
include::{builddir}option-command.txt[]
|
||||
|
||||
ENVIRONMENT VARIABLES
|
||||
---------------------
|
||||
|
@ -56,7 +56,7 @@ Some sample settings:
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
include::option-config.txt[]
|
||||
include::{builddir}option-config.txt[]
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
@ -93,7 +93,7 @@ FIXME:
|
||||
KEYMAP ACTIONS
|
||||
--------------
|
||||
|
||||
include::keymap-actions.txt[]
|
||||
include::{builddir}keymap-actions.txt[]
|
||||
|
||||
DEFAULT BINDINGS
|
||||
----------------
|
||||
@ -101,7 +101,7 @@ DEFAULT BINDINGS
|
||||
The default bindings are shown below. Any bindings in `~/.elinks/elinks.conf`
|
||||
will override these.
|
||||
|
||||
include::keymap-defaults.txt[]
|
||||
include::{builddir}keymap-defaults.txt[]
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
|
@ -71,6 +71,6 @@ include::small.txt[]
|
||||
|
||||
include::ecmascript.txt[]
|
||||
|
||||
include::features.txt[]
|
||||
include::{builddir}features.txt[]
|
||||
|
||||
endif::installation-webpage[]
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -17,7 +17,7 @@
|
||||
.el .ne 3
|
||||
.IP "\\$1" \\$2
|
||||
..
|
||||
.TH "ELINKS" 1 "The Elinks text-browser" "2006-01-14" "The Elinks text-browser"
|
||||
.TH "ELINKS" 1 "The Elinks text-browser" "2006-01-31" "The Elinks text-browser"
|
||||
.SH NAME
|
||||
elinks \- lynx-like alternative character mode WWW browser
|
||||
.SH "SYNOPSIS"
|
||||
@ -279,7 +279,7 @@ History file containing most recently visited URLs\&.
|
||||
GoTo URL dialog history file\&.
|
||||
|
||||
.TP
|
||||
~/\&.elinks/hooks\&.{js,lua,pl,py,pl,scm}
|
||||
~/\&.elinks/hooks\&.{js,lua,pl,py,rb,scm}
|
||||
Browser scripting hooks\&.
|
||||
|
||||
.TP
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -17,7 +17,7 @@
|
||||
.el .ne 3
|
||||
.IP "\\$1" \\$2
|
||||
..
|
||||
.TH "ELINKS.CONF" 5 "ELinks configuration file" "2006-01-14" "ELinks configuration file"
|
||||
.TH "ELINKS.CONF" 5 "ELinks configuration file" "2006-01-31" "ELinks configuration file"
|
||||
.SH NAME
|
||||
elinks.conf \- ELinks configuration file
|
||||
.SH "SYNOPSIS"
|
||||
@ -1156,6 +1156,18 @@ Allow blacklisting of buggy peers\&.
|
||||
protocol\&.file
|
||||
Options specific to local browsing\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.allow_special_files [0|1] (default: 0)
|
||||
Whether to allow reading from non\-regular files\&. Note this can be dangerous; reading /dev/urandom or /dev/zero can ruin your day!
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.show_hidden_files [0|1] (default: 1)
|
||||
When set to false, files with name starting with a dot will be hidden in local directories listing\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.try_encoding_extensions [0|1] (default: 1)
|
||||
When set, if we can't open a file named 'filename', we'll try to open 'filename' with some encoding extension appended (ie\&. 'filename\&.gz'); it depends on the supported encodings\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.cgi
|
||||
Local CGI specific options\&.
|
||||
@ -1169,16 +1181,12 @@ protocol\&.file\&.cgi\&.policy [0|1] (default: 0)
|
||||
Whether to execute local CGI scripts\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.allow_special_files [0|1] (default: 0)
|
||||
Whether to allow reading from non\-regular files\&. Note this can be dangerous; reading /dev/urandom or /dev/zero can ruin your day!
|
||||
protocol\&.fsp
|
||||
FSP specific options\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.show_hidden_files [0|1] (default: 1)
|
||||
When set to false, files with name starting with a dot will be hidden in local directories listing\&.
|
||||
|
||||
.TP
|
||||
protocol\&.file\&.try_encoding_extensions [0|1] (default: 1)
|
||||
When set, if we can't open a file named 'filename', we'll try to open 'filename' with some encoding extension appended (ie\&. 'filename\&.gz'); it depends on the supported encodings\&.
|
||||
protocol\&.fsp\&.sort [0|1] (default: 1)
|
||||
Whether to sort entries in directory listings\&.
|
||||
|
||||
.TP
|
||||
protocol\&.ftp
|
||||
|
@ -14,7 +14,7 @@ command-line arguments. The built-in documentation is sure to be up-to-date.
|
||||
There was a complete (or, for the most part complete) manual for Links 0.82 at
|
||||
one time, and you can still find it at:
|
||||
|
||||
http://links.sourceforge.net/docs/manual-0.82-en/index.html
|
||||
- http://links.sourceforge.net/docs/manual-0.82-en/index.html[]
|
||||
|
||||
While large parts of it do not apply anymore, you may still find some relevant
|
||||
information there.
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -21,14 +21,12 @@ usage($HELP) if $opt_h or @ARGV < 1;
|
||||
sub put_section {
|
||||
if ($title) {
|
||||
print "\n$title\n";
|
||||
$_ = $title;
|
||||
s/[^-]/-/g;
|
||||
print "$_\n" if not $indent;
|
||||
$title =~ s/[^-]/-/g;
|
||||
print "$title\n" if not $indent;
|
||||
}
|
||||
if ($body) {
|
||||
$_ = $body;
|
||||
s/#newline#/$indent/g;
|
||||
print "$_\n";
|
||||
$body =~ s/#newline#/$indent/g;
|
||||
print "$body\n";
|
||||
}
|
||||
$title = $body = undef;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
# Copyright (c) Jonas Fonseca <fonseca@diku.dk>, 2005
|
||||
#
|
||||
|
||||
CONFFILE="$1"
|
||||
TMPFILE=$(mktemp import-features.conf.XXXXXX) || exit 1
|
||||
|
||||
strip_comment()
|
||||
@ -53,7 +54,7 @@ __END__
|
||||
fi
|
||||
}
|
||||
|
||||
cat ../features.conf | while read line; do
|
||||
cat "$CONFFILE" | while read line; do
|
||||
case "$line" in
|
||||
"### "*)
|
||||
print_section
|
||||
|
@ -297,6 +297,21 @@ CONFIG_DATA=yes
|
||||
|
||||
CONFIG_FINGER=no
|
||||
|
||||
### File Service Protocol
|
||||
#
|
||||
# File Service Protocol (FSP) is a very lightweight UDP based protocol for
|
||||
# transferring files. FSP has many benefits over FTP, mainly for running
|
||||
# anonymous archives. FSP protocol is valuable in all kinds of environments
|
||||
# because it is one of the only TCP/IP protocols that is not aggressive about
|
||||
# bandwidth, while still being sufficiently fault tolerant.
|
||||
#
|
||||
# FSP is what anonymous FTP *should* be!
|
||||
#
|
||||
# See http://fsp.sourceforge.net/ for more info.
|
||||
#
|
||||
# Default: disabled
|
||||
|
||||
CONFIG_FSP=no
|
||||
|
||||
### File Transfer Protocol Support
|
||||
#
|
||||
|
238
po/fr.po
238
po/fr.po
@ -6,8 +6,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ELinks 0.12.GIT\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-01-10 23:00+0100\n"
|
||||
"PO-Revision-Date: 2006-01-10 23:01+0100\n"
|
||||
"POT-Creation-Date: 2006-01-30 23:26+0100\n"
|
||||
"PO-Revision-Date: 2006-01-30 23:28+0100\n"
|
||||
"Last-Translator: Laurent Monin <zas@norz.org>\n"
|
||||
"Language-Team: French <zas@norz.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -33,7 +33,7 @@ msgstr "Pressez espace pour d
|
||||
#: src/bfu/msgbox.c:189 src/config/dialogs.c:57 src/config/dialogs.c:391
|
||||
#: src/cookies/dialogs.c:354 src/dialogs/edit.c:97 src/dialogs/info.c:133
|
||||
#: src/dialogs/options.c:210 src/dialogs/options.c:290 src/mime/dialogs.c:129
|
||||
#: src/protocol/auth/dialogs.c:110 src/protocol/protocol.c:231
|
||||
#: src/protocol/auth/dialogs.c:110 src/protocol/protocol.c:234
|
||||
#: src/scripting/lua/core.c:377 src/scripting/lua/core.c:457
|
||||
#: src/session/session.c:792 src/viewer/text/search.c:1593
|
||||
msgid "~OK"
|
||||
@ -187,7 +187,7 @@ msgid "Digital clock in the status bar."
|
||||
msgstr "Horloge digitale dans la barre de status."
|
||||
|
||||
#: src/bfu/leds.c:77 src/bfu/leds.c:94 src/config/options.inc:1118
|
||||
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:39
|
||||
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:41
|
||||
#: src/globhist/globhist.c:63 src/mime/backend/mailcap.c:93
|
||||
#: src/mime/backend/mimetypes.c:52 src/network/ssl/ssl.c:80
|
||||
msgid "Enable"
|
||||
@ -1796,7 +1796,7 @@ msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: src/config/dialogs.c:320 src/protocol/bittorrent/dialogs.c:594
|
||||
#: src/protocol/protocol.c:225 src/session/session.c:282
|
||||
#: src/protocol/protocol.c:228 src/session/session.c:282
|
||||
#: src/session/session.c:954 src/viewer/text/textarea.c:331
|
||||
#: src/viewer/text/textarea.c:338
|
||||
msgid "Error"
|
||||
@ -3747,7 +3747,7 @@ msgstr "Texte"
|
||||
msgid "Dialog text colors."
|
||||
msgstr "Couleurs du texte des dialogues."
|
||||
|
||||
#: src/config/options.inc:978 src/viewer/text/form.c:1460
|
||||
#: src/config/options.inc:978 src/viewer/text/form.c:1462
|
||||
msgid "Checkbox"
|
||||
msgstr "Case à cocher"
|
||||
|
||||
@ -3795,7 +3795,7 @@ msgstr "Raccourci du bouton"
|
||||
msgid "Selected button shortcut"
|
||||
msgstr "Raccourci du bouton sélectionné"
|
||||
|
||||
#: src/config/options.inc:1006 src/viewer/text/form.c:1464
|
||||
#: src/config/options.inc:1006 src/viewer/text/form.c:1466
|
||||
msgid "Text field"
|
||||
msgstr "Champ texte"
|
||||
|
||||
@ -4400,7 +4400,7 @@ msgid "Domain"
|
||||
msgstr "Domaine"
|
||||
|
||||
#: src/cookies/dialogs.c:37 src/mime/backend/mailcap.c:97
|
||||
#: src/mime/backend/mimetypes.c:56 src/protocol/file/file.c:47
|
||||
#: src/mime/backend/mimetypes.c:56 src/protocol/file/cgi.c:43
|
||||
msgid "Path"
|
||||
msgstr "Chemin"
|
||||
|
||||
@ -5358,31 +5358,31 @@ msgstr ""
|
||||
"Laisser à \"\" pour utiliser le style initial du document."
|
||||
|
||||
#. name:
|
||||
#: src/ecmascript/ecmascript.c:35 src/ecmascript/ecmascript.c:137
|
||||
#: src/ecmascript/ecmascript.c:37 src/ecmascript/ecmascript.c:247
|
||||
msgid "ECMAScript"
|
||||
msgstr "ECMAScript"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:37
|
||||
#: src/ecmascript/ecmascript.c:39
|
||||
msgid "ECMAScript options."
|
||||
msgstr "Options d'ECMAScript."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:41
|
||||
#: src/ecmascript/ecmascript.c:43
|
||||
msgid "Whether to run those scripts inside of documents."
|
||||
msgstr "Exécuter ou non ces scripts présents dans les documents."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:43
|
||||
#: src/ecmascript/ecmascript.c:45
|
||||
msgid "Script error reporting"
|
||||
msgstr "Rapport d'erreur de script"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:45
|
||||
#: src/ecmascript/ecmascript.c:47
|
||||
msgid "Open a message box when a script reports an error."
|
||||
msgstr "Ouvrir une boîte de message quand un script produit une erreur."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:47
|
||||
#: src/ecmascript/ecmascript.c:49
|
||||
msgid "Ignore <noscript> content"
|
||||
msgstr "Ignorer le contenu de <noscript>"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:49
|
||||
#: src/ecmascript/ecmascript.c:51
|
||||
msgid ""
|
||||
"Whether to ignore content enclosed by the <noscript> tag\n"
|
||||
"when ECMAScript is enabled."
|
||||
@ -5390,29 +5390,29 @@ msgstr ""
|
||||
"Ignorer ou non le contenu du tag <noscript> quand ECMAScript\n"
|
||||
"est actif."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:52
|
||||
#: src/ecmascript/ecmascript.c:54
|
||||
msgid "Maximum execution time"
|
||||
msgstr "Temps maximal d'exécution"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:54
|
||||
#: src/ecmascript/ecmascript.c:56
|
||||
msgid "Maximum execution time in seconds for a script."
|
||||
msgstr "Temps maximal pour l'exécution d'un script, en secondes."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:56
|
||||
#: src/ecmascript/ecmascript.c:58
|
||||
msgid "Pop-up window blocking"
|
||||
msgstr "Blocage des fenêtres Javascript (popups)"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:58
|
||||
#: src/ecmascript/ecmascript.c:60
|
||||
msgid "Whether to disallow scripts to open new windows or tabs."
|
||||
msgstr ""
|
||||
"Interdire ou non l'ouverture de fenêtres ou d'onglets\n"
|
||||
"par les scripts."
|
||||
|
||||
#: src/ecmascript/ecmascript.c:126
|
||||
#: src/ecmascript/ecmascript.c:226
|
||||
msgid "JavaScript Emergency"
|
||||
msgstr "Alerte JavaScript"
|
||||
|
||||
#: src/ecmascript/ecmascript.c:128
|
||||
#: src/ecmascript/ecmascript.c:228
|
||||
#, c-format
|
||||
msgid ""
|
||||
"A script embedded in the current document was running\n"
|
||||
@ -5425,16 +5425,16 @@ msgstr ""
|
||||
"qu'il y a un bogue dans ce script et que cela aurait pû\n"
|
||||
"bloquer ELinks, l'exécution du script a donc été interrompue."
|
||||
|
||||
#: src/ecmascript/see/window.c:242 src/ecmascript/spidermonkey/window.c:286
|
||||
#: src/ecmascript/see/window.c:216 src/ecmascript/spidermonkey/window.c:286
|
||||
msgid "JavaScript Alert"
|
||||
msgstr "Alerte JavaScript"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:162
|
||||
#: src/ecmascript/spidermonkey.c:88
|
||||
#, c-format
|
||||
msgid "A script embedded in the current document raised the following%s%s%s%s"
|
||||
msgstr "Un script contenu dans le document courant a provoqué%s%s%s%s"
|
||||
|
||||
#: src/ecmascript/spidermonkey.c:178
|
||||
#: src/ecmascript/spidermonkey.c:104
|
||||
msgid "JavaScript Error"
|
||||
msgstr "Erreur Javascript"
|
||||
|
||||
@ -5784,7 +5784,7 @@ msgstr "Turque"
|
||||
msgid "Ukrainian"
|
||||
msgstr "Ukrainien"
|
||||
|
||||
#: src/main/interlink.c:325 src/main/select.c:255
|
||||
#: src/main/interlink.c:329 src/main/select.c:255
|
||||
#, c-format
|
||||
msgid "The call to %s failed: %d (%s)"
|
||||
msgstr "L'appel à %s a échoué: %d (%s)"
|
||||
@ -7140,40 +7140,45 @@ msgstr "A~fficher"
|
||||
msgid "Show ~header"
|
||||
msgstr "~Montrer les en-têtes"
|
||||
|
||||
#: src/protocol/file/file.c:38
|
||||
msgid "Local files"
|
||||
msgstr "Fichiers locaux"
|
||||
|
||||
#: src/protocol/file/file.c:40
|
||||
msgid "Options specific to local browsing."
|
||||
msgstr "Options pour la navigation locale."
|
||||
|
||||
#: src/protocol/file/file.c:43
|
||||
#: src/protocol/file/cgi.c:39
|
||||
msgid "Local CGI"
|
||||
msgstr "Scripts CGI locaux"
|
||||
|
||||
#: src/protocol/file/file.c:45
|
||||
#: src/protocol/file/cgi.c:41
|
||||
msgid "Local CGI specific options."
|
||||
msgstr "Options des scripts CGI locaux."
|
||||
|
||||
#: src/protocol/file/file.c:49
|
||||
#: src/protocol/file/cgi.c:45
|
||||
msgid "Colon separated list of directories, where CGI scripts are stored."
|
||||
msgstr ""
|
||||
"Liste des répertoires où sont les scripts CGI (séparée par des virgules)."
|
||||
|
||||
#: src/protocol/file/file.c:51
|
||||
#: src/protocol/file/cgi.c:47
|
||||
msgid "Allow local CGI"
|
||||
msgstr "Autoriser les scripts CGI locaux"
|
||||
|
||||
#: src/protocol/file/file.c:53
|
||||
#: src/protocol/file/cgi.c:49
|
||||
msgid "Whether to execute local CGI scripts."
|
||||
msgstr "Exécuter ou non les scripts CGI locaux."
|
||||
|
||||
#: src/protocol/file/file.c:56
|
||||
#. name:
|
||||
#: src/protocol/file/cgi.c:54
|
||||
msgid "CGI"
|
||||
msgstr "CGI"
|
||||
|
||||
#: src/protocol/file/file.c:39
|
||||
msgid "Local files"
|
||||
msgstr "Fichiers locaux"
|
||||
|
||||
#: src/protocol/file/file.c:41
|
||||
msgid "Options specific to local browsing."
|
||||
msgstr "Options pour la navigation locale."
|
||||
|
||||
#: src/protocol/file/file.c:43
|
||||
msgid "Allow reading special files"
|
||||
msgstr "Autoriser la lecture des fichiers spéciaux"
|
||||
|
||||
#: src/protocol/file/file.c:58
|
||||
#: src/protocol/file/file.c:45
|
||||
msgid ""
|
||||
"Whether to allow reading from non-regular files.\n"
|
||||
"Note this can be dangerous; reading /dev/urandom or\n"
|
||||
@ -7183,11 +7188,11 @@ msgstr ""
|
||||
"Notez que cela peut être dangereux; lire /dev/urandom\n"
|
||||
"ou /dev/zero peut ruiner votre journée !"
|
||||
|
||||
#: src/protocol/file/file.c:62
|
||||
#: src/protocol/file/file.c:49
|
||||
msgid "Show hidden files in directory listing"
|
||||
msgstr "Montrer les fichiers cachés"
|
||||
|
||||
#: src/protocol/file/file.c:64
|
||||
#: src/protocol/file/file.c:51
|
||||
msgid ""
|
||||
"When set to false, files with name starting with a dot will be\n"
|
||||
"hidden in local directories listing."
|
||||
@ -7196,11 +7201,11 @@ msgstr ""
|
||||
"seront cachés lors de la visualisation du contenu d'un répertoire\n"
|
||||
"local."
|
||||
|
||||
#: src/protocol/file/file.c:67
|
||||
#: src/protocol/file/file.c:54
|
||||
msgid "Try encoding extensions"
|
||||
msgstr "Deviner l'extension des fichiers encodés"
|
||||
|
||||
#: src/protocol/file/file.c:69
|
||||
#: src/protocol/file/file.c:56
|
||||
msgid ""
|
||||
"When set, if we can't open a file named 'filename', we'll try\n"
|
||||
"to open 'filename' with some encoding extension appended\n"
|
||||
@ -7211,7 +7216,7 @@ msgstr ""
|
||||
"'un_nom.gz'); cela dépend des encodages supportés."
|
||||
|
||||
#. name:
|
||||
#: src/protocol/file/file.c:77
|
||||
#: src/protocol/file/file.c:64
|
||||
msgid "File"
|
||||
msgstr "File"
|
||||
|
||||
@ -7221,29 +7226,46 @@ msgid "Finger"
|
||||
msgstr "Finger"
|
||||
|
||||
#. name:
|
||||
#: src/protocol/ftp/ftp.c:55 src/protocol/ftp/ftp.c:85
|
||||
#: src/protocol/fsp/fsp.c:44 src/protocol/fsp/fsp.c:56
|
||||
msgid "FSP"
|
||||
msgstr "FSP"
|
||||
|
||||
#: src/protocol/fsp/fsp.c:46
|
||||
msgid "FSP specific options."
|
||||
msgstr "Options du protocole FSP."
|
||||
|
||||
#: src/protocol/fsp/fsp.c:48
|
||||
msgid "Sort entries"
|
||||
msgstr "Trier les entrées"
|
||||
|
||||
#: src/protocol/fsp/fsp.c:50
|
||||
msgid "Whether to sort entries in directory listings."
|
||||
msgstr "Trier ou non les entrées des répertoires."
|
||||
|
||||
#. name:
|
||||
#: src/protocol/ftp/ftp.c:56 src/protocol/ftp/ftp.c:86
|
||||
msgid "FTP"
|
||||
msgstr "FTP"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:57
|
||||
#: src/protocol/ftp/ftp.c:58
|
||||
msgid "FTP specific options."
|
||||
msgstr "Options du protocole FTP."
|
||||
|
||||
#: src/protocol/ftp/ftp.c:59 src/protocol/http/http.c:124
|
||||
#: src/protocol/ftp/ftp.c:60 src/protocol/http/http.c:124
|
||||
#: src/protocol/http/http.c:206
|
||||
msgid "Proxy configuration"
|
||||
msgstr "Configuration proxy"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:61
|
||||
#: src/protocol/ftp/ftp.c:62
|
||||
msgid "FTP proxy configuration."
|
||||
msgstr "Configuration proxy FTP."
|
||||
|
||||
#: src/protocol/ftp/ftp.c:63 src/protocol/http/http.c:128
|
||||
#: src/protocol/ftp/ftp.c:64 src/protocol/http/http.c:128
|
||||
#: src/protocol/http/http.c:210
|
||||
msgid "Host and port-number"
|
||||
msgstr "Hôte et numéro de port"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:65
|
||||
#: src/protocol/ftp/ftp.c:66
|
||||
msgid ""
|
||||
"Host and port-number (host:port) of the FTP proxy, or blank.\n"
|
||||
"If it's blank, FTP_PROXY environment variable is checked as well."
|
||||
@ -7251,36 +7273,36 @@ msgstr ""
|
||||
"Hôte et numéro de port (hôte:port) du proxy FTP, ou rien.\n"
|
||||
"Si rien, la variable d'environnement FTP_PROXY sera utilisée."
|
||||
|
||||
#: src/protocol/ftp/ftp.c:68
|
||||
#: src/protocol/ftp/ftp.c:69
|
||||
msgid "Anonymous password"
|
||||
msgstr "Mot de passe anonyme"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:70
|
||||
#: src/protocol/ftp/ftp.c:71
|
||||
msgid "FTP anonymous password to be sent."
|
||||
msgstr "Mot de passe pour l'accès FTP anonyme."
|
||||
|
||||
#: src/protocol/ftp/ftp.c:72
|
||||
#: src/protocol/ftp/ftp.c:73
|
||||
msgid "Use passive mode (IPv4)"
|
||||
msgstr "Utiliser le mode passif (IPv4)"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:74
|
||||
#: src/protocol/ftp/ftp.c:75
|
||||
msgid "Use PASV instead of PORT (passive vs active mode, IPv4 only)."
|
||||
msgstr ""
|
||||
"Utiliser PASV au lieu de PORT (mode passif contre mode actif, IPv4\n"
|
||||
"seulement)."
|
||||
|
||||
#: src/protocol/ftp/ftp.c:76
|
||||
#: src/protocol/ftp/ftp.c:77
|
||||
msgid "Use passive mode (IPv6)"
|
||||
msgstr "Utiliser le mode passif (IPv6)"
|
||||
|
||||
#: src/protocol/ftp/ftp.c:78
|
||||
#: src/protocol/ftp/ftp.c:79
|
||||
msgid "Use EPSV instead of EPRT (passive vs active mode, IPv6 only)."
|
||||
msgstr ""
|
||||
"Utiliser EPSV au lieu de EPRT (mode passif contre mode actif, IPv6\n"
|
||||
"seulement)."
|
||||
|
||||
#. name:
|
||||
#: src/protocol/gopher/gopher.c:46
|
||||
#: src/protocol/gopher/gopher.c:47
|
||||
msgid "Gopher"
|
||||
msgstr "Gopher"
|
||||
|
||||
@ -7573,25 +7595,25 @@ msgstr ""
|
||||
"Toutes les entrées possibles peuvent être lues dans le dialogue\n"
|
||||
"Info. En-têtes."
|
||||
|
||||
#: src/protocol/protocol.c:227
|
||||
#: src/protocol/protocol.c:230
|
||||
#, c-format
|
||||
msgid "This version of ELinks does not contain %s protocol support"
|
||||
msgstr ""
|
||||
"Cette version de ELinks ne contient pas le support pour le protocole %s"
|
||||
|
||||
#: src/protocol/protocol.c:258
|
||||
#: src/protocol/protocol.c:261
|
||||
msgid "Protocols"
|
||||
msgstr "Protocoles"
|
||||
|
||||
#: src/protocol/protocol.c:260
|
||||
#: src/protocol/protocol.c:263
|
||||
msgid "Protocol specific options."
|
||||
msgstr "Options des protocoles."
|
||||
|
||||
#: src/protocol/protocol.c:262
|
||||
#: src/protocol/protocol.c:265
|
||||
msgid "No-proxy domains"
|
||||
msgstr "Domaines ignorés en ce qui concerne les proxys"
|
||||
|
||||
#: src/protocol/protocol.c:264
|
||||
#: src/protocol/protocol.c:267
|
||||
msgid ""
|
||||
"Comma separated list of domains for which the proxy (HTTP/FTP)\n"
|
||||
"should be disabled. Optionally, a port can be specified for some\n"
|
||||
@ -7604,7 +7626,7 @@ msgstr ""
|
||||
"NO_PROXY sera utilisé."
|
||||
|
||||
#. name:
|
||||
#: src/protocol/protocol.c:300
|
||||
#: src/protocol/protocol.c:309
|
||||
msgid "Protocol"
|
||||
msgstr "Protocole"
|
||||
|
||||
@ -7731,19 +7753,19 @@ msgid "URI rewrite"
|
||||
msgstr "Ré-écriture d'URI"
|
||||
|
||||
#. name:
|
||||
#: src/protocol/smb/smb.c:72 src/protocol/smb/smb.c:84
|
||||
#: src/protocol/smb/smb.c:67 src/protocol/smb/smb.c:79
|
||||
msgid "SMB"
|
||||
msgstr "SMB"
|
||||
|
||||
#: src/protocol/smb/smb.c:74
|
||||
#: src/protocol/smb/smb.c:69
|
||||
msgid "SAMBA specific options."
|
||||
msgstr "Options spécifiques de SAMBA."
|
||||
|
||||
#: src/protocol/smb/smb.c:76
|
||||
#: src/protocol/smb/smb.c:71
|
||||
msgid "Credentials"
|
||||
msgstr "Authentification"
|
||||
|
||||
#: src/protocol/smb/smb.c:78
|
||||
#: src/protocol/smb/smb.c:73
|
||||
msgid "Credentials file passed to smbclient via -A option."
|
||||
msgstr "Fichier d'authentification passé à smbclient via l'option -A."
|
||||
|
||||
@ -8092,167 +8114,167 @@ msgstr "Erreur lors de l'envoi du formulaire"
|
||||
msgid "Could not load file %s: %s"
|
||||
msgstr "Impossible de charger le fichier %s: %s"
|
||||
|
||||
#: src/viewer/text/form.c:1445
|
||||
#: src/viewer/text/form.c:1447
|
||||
msgid "Reset form"
|
||||
msgstr "Réinitialiser le formulaire"
|
||||
|
||||
#: src/viewer/text/form.c:1447
|
||||
#: src/viewer/text/form.c:1449
|
||||
msgid "Harmless button"
|
||||
msgstr "Bouton sans impact"
|
||||
|
||||
#: src/viewer/text/form.c:1455
|
||||
#: src/viewer/text/form.c:1457
|
||||
msgid "Submit form to"
|
||||
msgstr "Envoi du formulaire à"
|
||||
|
||||
#: src/viewer/text/form.c:1456
|
||||
#: src/viewer/text/form.c:1458
|
||||
msgid "Post form to"
|
||||
msgstr "Transfert du formulaire à"
|
||||
|
||||
#: src/viewer/text/form.c:1458
|
||||
#: src/viewer/text/form.c:1460
|
||||
msgid "Radio button"
|
||||
msgstr "Bouton radio"
|
||||
|
||||
#: src/viewer/text/form.c:1462
|
||||
#: src/viewer/text/form.c:1464
|
||||
msgid "Select field"
|
||||
msgstr "Liste"
|
||||
|
||||
#: src/viewer/text/form.c:1466
|
||||
#: src/viewer/text/form.c:1468
|
||||
msgid "Text area"
|
||||
msgstr "Champ texte multiligne"
|
||||
|
||||
#: src/viewer/text/form.c:1468
|
||||
#: src/viewer/text/form.c:1470
|
||||
msgid "File upload"
|
||||
msgstr "Envoi de fichier"
|
||||
|
||||
#: src/viewer/text/form.c:1470
|
||||
#: src/viewer/text/form.c:1472
|
||||
msgid "Password field"
|
||||
msgstr "Champ mot de passe"
|
||||
|
||||
#: src/viewer/text/form.c:1508
|
||||
#: src/viewer/text/form.c:1510
|
||||
msgid "name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: src/viewer/text/form.c:1520
|
||||
#: src/viewer/text/form.c:1522
|
||||
msgid "value"
|
||||
msgstr "Valeur"
|
||||
|
||||
#: src/viewer/text/form.c:1533
|
||||
#: src/viewer/text/form.c:1535
|
||||
msgid "read only"
|
||||
msgstr "lecture seule"
|
||||
|
||||
#: src/viewer/text/form.c:1544
|
||||
#: src/viewer/text/form.c:1546
|
||||
#, c-format
|
||||
msgid "press %s to navigate"
|
||||
msgstr "pressez %s pour naviguer"
|
||||
|
||||
#: src/viewer/text/form.c:1546
|
||||
#: src/viewer/text/form.c:1548
|
||||
#, c-format
|
||||
msgid "press %s to edit"
|
||||
msgstr "pressez %s pour éditer"
|
||||
|
||||
#: src/viewer/text/form.c:1582
|
||||
#: src/viewer/text/form.c:1584
|
||||
#, c-format
|
||||
msgid "press %s to submit to %s"
|
||||
msgstr "pressez %s pour soumettre à %s"
|
||||
|
||||
#: src/viewer/text/form.c:1584
|
||||
#: src/viewer/text/form.c:1586
|
||||
#, c-format
|
||||
msgid "press %s to post to %s"
|
||||
msgstr "pressez %s pour poster à %s"
|
||||
|
||||
#: src/viewer/text/form.c:1686
|
||||
#: src/viewer/text/form.c:1688
|
||||
msgid "Useless button"
|
||||
msgstr "Bouton inutile"
|
||||
|
||||
#: src/viewer/text/form.c:1688
|
||||
#: src/viewer/text/form.c:1690
|
||||
msgid "Submit button"
|
||||
msgstr "Bouton Soumettre"
|
||||
|
||||
#: src/viewer/text/link.c:1166
|
||||
#: src/viewer/text/link.c:1209
|
||||
msgid "Display ~usemap"
|
||||
msgstr "Afficher ~usemap"
|
||||
|
||||
#: src/viewer/text/link.c:1169
|
||||
#: src/viewer/text/link.c:1212
|
||||
msgid "~Follow link"
|
||||
msgstr "~Suivre le lien"
|
||||
|
||||
#: src/viewer/text/link.c:1171
|
||||
#: src/viewer/text/link.c:1214
|
||||
msgid "Follow link and r~eload"
|
||||
msgstr "Suivre le lien et ~recharger"
|
||||
|
||||
#: src/viewer/text/link.c:1175
|
||||
#: src/viewer/text/link.c:1218
|
||||
msgid "Open in new ~window"
|
||||
msgstr "Ouvrir dans une nouvelle ~fenêtre"
|
||||
|
||||
#: src/viewer/text/link.c:1177
|
||||
#: src/viewer/text/link.c:1220
|
||||
msgid "Open in new ~tab"
|
||||
msgstr "Ouvrir dans un nouvel ongle~t"
|
||||
|
||||
#: src/viewer/text/link.c:1179
|
||||
#: src/viewer/text/link.c:1222
|
||||
msgid "Open in new tab in ~background"
|
||||
msgstr "Ouvrir dans un nouvel onglet en arrière-~plan"
|
||||
|
||||
#: src/viewer/text/link.c:1184
|
||||
#: src/viewer/text/link.c:1227
|
||||
msgid "~Download link"
|
||||
msgstr "~Enregistrer le lien"
|
||||
|
||||
#: src/viewer/text/link.c:1187
|
||||
#: src/viewer/text/link.c:1230
|
||||
msgid "~Add link to bookmarks"
|
||||
msgstr "~Ajouter ce lien aux signets"
|
||||
|
||||
#: src/viewer/text/link.c:1199 src/viewer/text/link.c:1235
|
||||
#: src/viewer/text/link.c:1242 src/viewer/text/link.c:1278
|
||||
msgid "~Reset form"
|
||||
msgstr "Remettre à ~zéro le formulaire"
|
||||
|
||||
#: src/viewer/text/link.c:1212
|
||||
#: src/viewer/text/link.c:1255
|
||||
msgid "Open in ~external editor"
|
||||
msgstr "Ouvrir dans un ~éditeur externe"
|
||||
|
||||
#: src/viewer/text/link.c:1218
|
||||
#: src/viewer/text/link.c:1261
|
||||
msgid "~Submit form"
|
||||
msgstr "~Envoyer le formulaire"
|
||||
|
||||
#: src/viewer/text/link.c:1219
|
||||
#: src/viewer/text/link.c:1262
|
||||
msgid "Submit form and rel~oad"
|
||||
msgstr "Envoyer le formulaire et ~recharger"
|
||||
|
||||
#: src/viewer/text/link.c:1223
|
||||
#: src/viewer/text/link.c:1266
|
||||
msgid "Submit form and open in new ~window"
|
||||
msgstr "Envoyer le formulaire et ouvrir dans une nouvelle ~fenêtre"
|
||||
|
||||
#: src/viewer/text/link.c:1225
|
||||
#: src/viewer/text/link.c:1268
|
||||
msgid "Submit form and open in new ~tab"
|
||||
msgstr "Envoyer le formulaire et ouvrir un ~onglet"
|
||||
|
||||
#: src/viewer/text/link.c:1228
|
||||
#: src/viewer/text/link.c:1271
|
||||
msgid "Submit form and open in new tab in ~background"
|
||||
msgstr "Envoyer le formulaire et ouvrir un onglet en ~arrière-plan"
|
||||
|
||||
#: src/viewer/text/link.c:1233
|
||||
#: src/viewer/text/link.c:1276
|
||||
msgid "Submit form and ~download"
|
||||
msgstr "Envoyer le formulaire et ~télécharger"
|
||||
|
||||
#: src/viewer/text/link.c:1238
|
||||
#: src/viewer/text/link.c:1281
|
||||
msgid "Form f~ields"
|
||||
msgstr "Champs de formula~ire"
|
||||
|
||||
#: src/viewer/text/link.c:1243
|
||||
#: src/viewer/text/link.c:1286
|
||||
msgid "V~iew image"
|
||||
msgstr "~Voir l'image"
|
||||
|
||||
#: src/viewer/text/link.c:1245
|
||||
#: src/viewer/text/link.c:1288
|
||||
msgid "Download ima~ge"
|
||||
msgstr "Enregistrer l'~image"
|
||||
|
||||
#: src/viewer/text/link.c:1253
|
||||
#: src/viewer/text/link.c:1296
|
||||
msgid "No link selected"
|
||||
msgstr "Aucun lien sélectionné"
|
||||
|
||||
#: src/viewer/text/link.c:1301
|
||||
#: src/viewer/text/link.c:1344
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/viewer/text/link.c:1306
|
||||
#: src/viewer/text/link.c:1349
|
||||
msgid "Usemap"
|
||||
msgstr "Usemap"
|
||||
|
||||
|
16
po/pl.po
16
po/pl.po
@ -2546,7 +2546,7 @@ msgstr "Numerowanie odno
|
||||
|
||||
#: src/config/options.inc:306
|
||||
msgid "Display numbers next to the links."
|
||||
msgstr "Czy wyświetlać liczby z prawej strony odnośników."
|
||||
msgstr "Czy wyświetlać numery odnośników."
|
||||
|
||||
#: src/config/options.inc:308
|
||||
msgid "Handling of target=_blank"
|
||||
@ -3274,7 +3274,7 @@ msgstr "Czy pami
|
||||
#
|
||||
#: src/config/options.inc:670
|
||||
msgid "HTML rendering"
|
||||
msgstr "Renderowanie HTML-a"
|
||||
msgstr "Formatowanie HTML-a"
|
||||
|
||||
#: src/config/options.inc:672
|
||||
msgid "Options concerning the display of HTML pages."
|
||||
@ -3320,7 +3320,7 @@ msgstr "Pokazuj indeks g
|
||||
|
||||
#: src/config/options.inc:690
|
||||
msgid "Rendering of html link element"
|
||||
msgstr "Renderowanie elementu odnośnika html"
|
||||
msgstr "Wyświetlanie elementu odnośnika html"
|
||||
|
||||
#: src/config/options.inc:692
|
||||
msgid ""
|
||||
@ -3332,7 +3332,7 @@ msgid ""
|
||||
"4 is type in addition\n"
|
||||
"5 is everything"
|
||||
msgstr ""
|
||||
"W jaki sposób renderować znaczniki <link> w nagłówku HTML:\n"
|
||||
"W jaki sposób pokazywać znaczniki <link> w nagłówku HTML:\n"
|
||||
"0 - w ogóle\n"
|
||||
"1 - tytu³\n"
|
||||
"2 - dodatkowo nazwa\n"
|
||||
@ -3365,7 +3365,7 @@ msgstr ""
|
||||
#
|
||||
#: src/config/options.inc:711
|
||||
msgid "Plain rendering"
|
||||
msgstr "Renderowanie zwykłego tekstu"
|
||||
msgstr "Formatowanie zwykłego tekstu"
|
||||
|
||||
#: src/config/options.inc:713
|
||||
msgid "Options concerning the display of plain text pages."
|
||||
@ -4388,7 +4388,7 @@ msgstr "Cykliczne zapisywanie"
|
||||
#. name:
|
||||
#: src/config/urlhist.c:61
|
||||
msgid "Goto URL History"
|
||||
msgstr "Historia globalna"
|
||||
msgstr "Historia \"Przejdź do URL-a\""
|
||||
|
||||
#. name:
|
||||
#: src/cookies/cookies.c:80 src/cookies/cookies.c:827
|
||||
@ -5716,7 +5716,7 @@ msgstr "Czy na pewno chcesz skasowa
|
||||
|
||||
#: src/globhist/dialogs.c:169
|
||||
msgid "Search history"
|
||||
msgstr "Przeszukaj historię"
|
||||
msgstr "Szukanie w historii"
|
||||
|
||||
#
|
||||
#: src/globhist/dialogs.c:226
|
||||
@ -8468,7 +8468,7 @@ msgstr "Szukaj wstecz"
|
||||
#. name:
|
||||
#: src/viewer/text/search.c:1654
|
||||
msgid "Search History"
|
||||
msgstr "Przeszukaj historię"
|
||||
msgstr "Szukanie w historii"
|
||||
|
||||
#: src/viewer/text/textarea.c:332
|
||||
msgid "You cannot launch an external editor in the anonymous mode."
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -386,7 +386,7 @@ xbeltree_to_bookmarks_list(struct tree_node *node,
|
||||
|
||||
tmp = add_bookmark(current_parent, 0,
|
||||
/* The <title> element is optional */
|
||||
title ? title->text
|
||||
title && title->text ? title->text
|
||||
: (unsigned char *) gettext("No title"),
|
||||
/* XXX: The href attribute isn't optional but
|
||||
* we don't validate the source XML yet, so
|
||||
@ -407,7 +407,7 @@ xbeltree_to_bookmarks_list(struct tree_node *node,
|
||||
title = get_child(node, "title");
|
||||
|
||||
tmp = add_bookmark(current_parent, 0,
|
||||
title ? title->text
|
||||
title && title->text ? title->text
|
||||
: (unsigned char *) gettext("No title"),
|
||||
NULL);
|
||||
|
||||
|
2
src/cache/.vimrc
vendored
2
src/cache/.vimrc
vendored
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -11,6 +11,7 @@
|
||||
|
||||
struct cache_entry;
|
||||
struct document_refresh;
|
||||
struct document_view;
|
||||
struct form_control;
|
||||
struct frame_desc;
|
||||
struct frameset_desc;
|
||||
@ -147,6 +148,8 @@ struct document {
|
||||
* dependencies between the various entries so nothing gets removed
|
||||
* unneeded. */
|
||||
struct uri_list ecmascript_imports;
|
||||
/* For ecmascript access */
|
||||
struct document_view *doc_view;
|
||||
#endif
|
||||
#ifdef CONFIG_CSS
|
||||
/* FIXME: We should externally maybe using cache_entry store the
|
||||
@ -185,6 +188,7 @@ struct document {
|
||||
color_T bgcolor;
|
||||
|
||||
enum cp_status cp_status;
|
||||
unsigned int links_sorted:1; /* whether links are already sorted */
|
||||
};
|
||||
|
||||
#define document_has_frames(document_) ((document_) && (document_)->frame_desc)
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -22,8 +22,10 @@
|
||||
#include "document/document.h"
|
||||
#include "document/dom/renderer.h"
|
||||
#include "document/renderer.h"
|
||||
#include "dom/configuration.h"
|
||||
#include "dom/scanner.h"
|
||||
#include "dom/sgml/parser.h"
|
||||
#include "dom/sgml/html/html.h"
|
||||
#include "dom/sgml/rss/rss.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/stack.h"
|
||||
@ -39,11 +41,14 @@
|
||||
|
||||
|
||||
struct dom_renderer {
|
||||
enum sgml_document_type doctype;
|
||||
struct document *document;
|
||||
|
||||
struct conv_table *convert_table;
|
||||
enum convert_string_mode convert_mode;
|
||||
|
||||
struct uri *base_uri;
|
||||
|
||||
unsigned char *source;
|
||||
unsigned char *end;
|
||||
|
||||
@ -108,6 +113,7 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
|
||||
renderer->source = buffer->source;
|
||||
renderer->end = buffer->source + buffer->length;
|
||||
renderer->position = renderer->source;
|
||||
renderer->base_uri = get_uri_reference(document->uri);
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (renderer->document->options.plain_display_links) {
|
||||
@ -367,7 +373,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
|
||||
CSM_DEFAULT, NULL, NULL, NULL);
|
||||
if (!uristring) return NULL;
|
||||
|
||||
where = join_urls(document->uri, uristring);
|
||||
where = join_urls(renderer->base_uri, uristring);
|
||||
|
||||
mem_free(uristring);
|
||||
|
||||
@ -402,6 +408,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
|
||||
}
|
||||
|
||||
document->nlinks++;
|
||||
document->links_sorted = 0;
|
||||
|
||||
return link;
|
||||
}
|
||||
@ -500,7 +507,7 @@ render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *no
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -513,15 +520,15 @@ render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *dat
|
||||
|| node->type == DOM_NODE_CDATA_SECTION
|
||||
|| node->type == DOM_NODE_COMMENT)) {
|
||||
render_dom_node_enhanced_text(renderer, node);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
render_dom_node_text(renderer, &renderer->styles[node->type], node);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
/* This callback is also used for rendering processing instruction nodes. */
|
||||
static void
|
||||
static enum dom_code
|
||||
render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -529,9 +536,11 @@ render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
render_dom_node_text(renderer, &renderer->styles[node->type], node);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -544,7 +553,7 @@ render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, vo
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
if (!string || !length)
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
if (check_dom_node_source(renderer, string, length)) {
|
||||
render_dom_flush(renderer, string);
|
||||
@ -553,9 +562,32 @@ render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, vo
|
||||
}
|
||||
|
||||
render_dom_text(renderer, &renderer->styles[node->type], string, length);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
set_base_uri(struct dom_renderer *renderer, unsigned char *value, size_t valuelen)
|
||||
{
|
||||
unsigned char *href = memacpy(value, valuelen);
|
||||
unsigned char *uristring;
|
||||
struct uri *uri;
|
||||
|
||||
if (!href) return;
|
||||
uristring = join_urls(renderer->base_uri, href);
|
||||
mem_free(href);
|
||||
|
||||
if (!uristring) return;
|
||||
uri = get_uri(uristring, 0);
|
||||
mem_free(uristring);
|
||||
|
||||
if (!uri) return;
|
||||
|
||||
done_uri(renderer->base_uri);
|
||||
renderer->base_uri = uri;
|
||||
}
|
||||
|
||||
enum dom_code
|
||||
render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -609,6 +641,12 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
|
||||
break;
|
||||
}
|
||||
|
||||
if (renderer->doctype == SGML_DOCTYPE_HTML
|
||||
&& node->data.attribute.type == HTML_ATTRIBUTE_HREF
|
||||
&& node->parent->data.element.type == HTML_ELEMENT_BASE) {
|
||||
set_base_uri(renderer, value, valuelen - skips);
|
||||
}
|
||||
|
||||
add_dom_link(renderer, value, valuelen - skips,
|
||||
value, valuelen - skips);
|
||||
|
||||
@ -620,9 +658,11 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
|
||||
render_dom_text(renderer, template, value, valuelen);
|
||||
}
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -639,9 +679,11 @@ render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
}
|
||||
|
||||
render_dom_node_text(renderer, &renderer->styles[node->type], node);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -652,6 +694,8 @@ render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
if (check_dom_node_source(renderer, renderer->position, 0)) {
|
||||
render_dom_flush(renderer, renderer->end);
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static struct dom_stack_context_info dom_source_renderer_context_info = {
|
||||
@ -693,7 +737,10 @@ static struct dom_stack_context_info dom_source_renderer_context_info = {
|
||||
|
||||
/* DOM RSS Renderer */
|
||||
|
||||
static void
|
||||
#define RSS_CONFIG_FLAGS \
|
||||
(DOM_CONFIG_NORMALIZE_WHITESPACE | DOM_CONFIG_NORMALIZE_CHARACTERS)
|
||||
|
||||
enum dom_code
|
||||
dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -735,9 +782,11 @@ dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
|
||||
renderer->node = node;
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
@ -776,74 +825,21 @@ dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dom_rss_push_content(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
unsigned char *string = node->string.string;
|
||||
int length = node->string.length;
|
||||
|
||||
assert(node && renderer && renderer->document);
|
||||
|
||||
if (!renderer->node)
|
||||
return;
|
||||
|
||||
if (node->type == DOM_NODE_ENTITY_REFERENCE) {
|
||||
string -= 1;
|
||||
length += 2;
|
||||
}
|
||||
|
||||
if (!is_dom_string_set(&renderer->text)) {
|
||||
init_dom_string(&renderer->text, string, length);
|
||||
} else {
|
||||
add_to_dom_string(&renderer->text, string, length);
|
||||
}
|
||||
}
|
||||
|
||||
static struct dom_string *
|
||||
get_rss_node_text(struct dom_node *node)
|
||||
{
|
||||
struct dom_node *child;
|
||||
int index;
|
||||
|
||||
if (!node->data.element.children)
|
||||
return NULL;
|
||||
|
||||
foreach_dom_node (node->data.element.children, child, index) {
|
||||
if (child->type == DOM_NODE_TEXT)
|
||||
return &child->string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dom_node *
|
||||
get_rss_child(struct dom_node *parent, enum rss_element_type type)
|
||||
{
|
||||
struct dom_node *node;
|
||||
int index;
|
||||
|
||||
if (!parent->data.element.children)
|
||||
return NULL;
|
||||
|
||||
foreach_dom_node (parent->data.element.children, node, index) {
|
||||
if (node->type == DOM_NODE_ELEMENT
|
||||
&& type == node->data.element.type)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
|
||||
static struct dom_string *
|
||||
get_rss_text(struct dom_node *node, enum rss_element_type type)
|
||||
{
|
||||
node = get_rss_child(node, type);
|
||||
node = get_dom_node_child(node, DOM_NODE_ELEMENT, type);
|
||||
|
||||
return node ? get_rss_node_text(node) : NULL;
|
||||
if (!node) return NULL;
|
||||
|
||||
node = get_dom_node_child(node, DOM_NODE_TEXT, 0);
|
||||
|
||||
return node ? &node->string: NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -901,13 +897,13 @@ render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *data)
|
||||
{
|
||||
struct dom_renderer *renderer = stack->current->data;
|
||||
|
||||
if (!renderer->channel)
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
render_rss_item(renderer, renderer->channel);
|
||||
|
||||
@ -927,6 +923,8 @@ dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *data)
|
||||
mem_free_if(renderer->items);
|
||||
|
||||
done_dom_node(root);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -937,9 +935,9 @@ static struct dom_stack_context_info dom_rss_renderer_context_info = {
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ dom_rss_push_element,
|
||||
/* DOM_NODE_ATTRIBUTE */ NULL,
|
||||
/* DOM_NODE_TEXT */ dom_rss_push_content,
|
||||
/* DOM_NODE_CDATA_SECTION */ dom_rss_push_content,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ dom_rss_push_content,
|
||||
/* DOM_NODE_TEXT */ NULL,
|
||||
/* DOM_NODE_CDATA_SECTION */ NULL,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
|
||||
/* DOM_NODE_ENTITY */ NULL,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||
/* DOM_NODE_COMMENT */ NULL,
|
||||
@ -976,12 +974,11 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
struct dom_renderer renderer;
|
||||
struct conv_table *convert_table;
|
||||
struct sgml_parser *parser;
|
||||
enum sgml_document_type doctype;
|
||||
enum sgml_parser_type parser_type;
|
||||
unsigned char *string = struri(cached->uri);
|
||||
size_t length = strlen(string);
|
||||
struct dom_string uri = INIT_DOM_STRING(string, length);
|
||||
enum sgml_parser_code code;
|
||||
enum dom_code code;
|
||||
|
||||
convert_table = get_convert_table(head, document->options.cp,
|
||||
document->options.assume_cp,
|
||||
@ -1000,34 +997,35 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
|
||||
/* FIXME: Refactor the doctype lookup. */
|
||||
if (!strcasecmp("application/rss+xml", cached->content_type)) {
|
||||
doctype = SGML_DOCTYPE_RSS;
|
||||
renderer.doctype = SGML_DOCTYPE_RSS;
|
||||
|
||||
} else if (!strcasecmp("application/docbook+xml", cached->content_type)) {
|
||||
doctype = SGML_DOCTYPE_DOCBOOK;
|
||||
renderer.doctype = SGML_DOCTYPE_DOCBOOK;
|
||||
|
||||
} else if (!strcasecmp("application/xbel+xml", cached->content_type)
|
||||
|| !strcasecmp("application/x-xbel", cached->content_type)
|
||||
|| !strcasecmp("application/xbel", cached->content_type)) {
|
||||
doctype = SGML_DOCTYPE_XBEL;
|
||||
renderer.doctype = SGML_DOCTYPE_XBEL;
|
||||
|
||||
} else {
|
||||
assertm(!strcasecmp("text/html", cached->content_type)
|
||||
|| !strcasecmp("application/xhtml+xml", cached->content_type),
|
||||
"Couldn't resolve doctype '%s'", cached->content_type);
|
||||
|
||||
doctype = SGML_DOCTYPE_HTML;
|
||||
renderer.doctype = SGML_DOCTYPE_HTML;
|
||||
}
|
||||
|
||||
parser = init_sgml_parser(parser_type, doctype, &uri, 0);
|
||||
parser = init_sgml_parser(parser_type, renderer.doctype, &uri, 0);
|
||||
if (!parser) return;
|
||||
|
||||
if (document->options.plain) {
|
||||
add_dom_stack_context(&parser->stack, &renderer,
|
||||
&dom_source_renderer_context_info);
|
||||
|
||||
} else if (doctype == SGML_DOCTYPE_RSS) {
|
||||
} else if (renderer.doctype == SGML_DOCTYPE_RSS) {
|
||||
add_dom_stack_context(&parser->stack, &renderer,
|
||||
&dom_rss_renderer_context_info);
|
||||
add_dom_config_normalizer(&parser->stack, RSS_CONFIG_FLAGS);
|
||||
}
|
||||
|
||||
/* FIXME: When rendering this way we don't really care about the code.
|
||||
@ -1048,5 +1046,6 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
||||
if (renderer.find_url)
|
||||
regfree(&renderer.url_regex);
|
||||
#endif
|
||||
done_uri(renderer.base_uri);
|
||||
done_sgml_parser(parser);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "bfu/listmenu.h"
|
||||
#include "document/document.h"
|
||||
#include "document/forms.h"
|
||||
#include "document/renderer.h"
|
||||
#include "util/error.h"
|
||||
#include "util/lists.h"
|
||||
#include "util/memory.h"
|
||||
@ -91,6 +92,7 @@ done_form(struct form *form)
|
||||
|
||||
mem_free_if(form->action);
|
||||
mem_free_if(form->name);
|
||||
mem_free_if(form->onsubmit);
|
||||
mem_free_if(form->target);
|
||||
|
||||
foreach (fc, form->items) {
|
||||
@ -130,6 +132,8 @@ get_form_control_link(struct document *document, struct form_control *fc)
|
||||
if (fc->type == FC_HIDDEN)
|
||||
return -1;
|
||||
|
||||
if (!document->links_sorted) sort_links(document);
|
||||
|
||||
for (link = 0; link < document->nlinks; link++)
|
||||
if (fc == get_link_form_control(&document->links[link]))
|
||||
return link;
|
||||
|
@ -32,6 +32,7 @@ struct form {
|
||||
|
||||
unsigned char *action;
|
||||
unsigned char *name;
|
||||
unsigned char *onsubmit;
|
||||
unsigned char *target;
|
||||
enum form_method method;
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -533,8 +533,7 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
|
||||
}
|
||||
|
||||
target = get_target(options, attr);
|
||||
if (!target) target = null_or_stracpy(target_base);
|
||||
if (!target) target = stracpy("");
|
||||
if (!target) target = stracpy(empty_string_or_(target_base));
|
||||
if (!target) {
|
||||
mem_free_if(label);
|
||||
return 1;
|
||||
@ -660,7 +659,7 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
|
||||
|
||||
struct html_element *
|
||||
init_html_parser_state(struct html_context *html_context,
|
||||
enum html_element_type type,
|
||||
enum html_element_mortality_type type,
|
||||
int align, int margin, int width)
|
||||
{
|
||||
html_stack_dup(html_context, type);
|
||||
|
@ -102,7 +102,7 @@ struct par_attrib {
|
||||
};
|
||||
|
||||
/* HTML parser stack mortality info */
|
||||
enum html_element_type {
|
||||
enum html_element_mortality_type {
|
||||
/* Elements of this type can not be removed from the stack. This type
|
||||
* is created by the renderer when formatting a HTML part. */
|
||||
ELEMENT_IMMORTAL,
|
||||
@ -122,7 +122,7 @@ enum html_element_type {
|
||||
struct html_element {
|
||||
LIST_HEAD(struct html_element);
|
||||
|
||||
enum html_element_type type;
|
||||
enum html_element_mortality_type type;
|
||||
|
||||
struct text_attrib attr;
|
||||
struct par_attrib parattr;
|
||||
@ -173,7 +173,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
|
||||
...));
|
||||
|
||||
void done_html_parser(struct html_context *html_context);
|
||||
struct html_element *init_html_parser_state(struct html_context *html_context, enum html_element_type type, int align, int margin, int width);
|
||||
struct html_element *init_html_parser_state(struct html_context *html_context, enum html_element_mortality_type type, int align, int margin, int width);
|
||||
void done_html_parser_state(struct html_context *html_context,
|
||||
struct html_element *element);
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../../.vimrc
|
@ -69,7 +69,7 @@ html_form(struct html_context *html_context, unsigned char *a,
|
||||
}
|
||||
mem_free(al);
|
||||
}
|
||||
|
||||
form->onsubmit = get_attr_val(a, "onsubmit", html_context->options);
|
||||
al = get_attr_val(a, "name", html_context->options);
|
||||
if (al) form->name = al;
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "config/options.h"
|
||||
#include "document/css/apply.h"
|
||||
#include "document/document.h"
|
||||
#include "document/view.h"
|
||||
#include "document/html/frames.h"
|
||||
#include "document/html/parser/general.h"
|
||||
#include "document/html/parser/link.h"
|
||||
@ -26,6 +28,7 @@
|
||||
#include "document/html/renderer.h"
|
||||
#include "document/html/tables.h"
|
||||
#include "document/options.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "intl/charsets.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "terminal/draw.h"
|
||||
@ -37,6 +40,7 @@
|
||||
#include "util/memdebug.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
/* Unsafe macros */
|
||||
#include "document/html/internal.h"
|
||||
@ -343,8 +347,42 @@ imported:
|
||||
}
|
||||
|
||||
if (html_context->part->document && *html != '^') {
|
||||
struct string code, ret;
|
||||
struct part *part = html_context->part;
|
||||
struct document *document = part->document;
|
||||
struct document_view *doc_view = document->doc_view;
|
||||
struct view_state *vs = doc_view->vs;
|
||||
struct ecmascript_interpreter *interpreter;
|
||||
|
||||
if (vs->ecmascript_fragile)
|
||||
ecmascript_reset_state(vs);
|
||||
interpreter = vs->ecmascript;
|
||||
assert(interpreter);
|
||||
|
||||
if (!init_string(&code)) return;
|
||||
if (!init_string(&ret)) {
|
||||
done_string(&code);
|
||||
return;
|
||||
}
|
||||
add_bytes_to_string(&code, html, *end - html);
|
||||
|
||||
ecmascript_eval(interpreter, &code, &ret);
|
||||
done_string(&code);
|
||||
if (!ret.length) {
|
||||
done_string(&ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: it doesn't work */
|
||||
html_top->invisible = 0;
|
||||
parse_html(ret.source, ret.source + ret.length, part, NULL,
|
||||
html_context);
|
||||
|
||||
done_string(&ret);
|
||||
#if 0
|
||||
add_to_string_list(&html_context->part->document->onload_snippets,
|
||||
html, *end - html);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ kill_html_stack_item(struct html_context *html_context, struct html_element *e)
|
||||
|
||||
|
||||
void
|
||||
html_stack_dup(struct html_context *html_context, enum html_element_type type)
|
||||
html_stack_dup(struct html_context *html_context, enum html_element_mortality_type type)
|
||||
{
|
||||
struct html_element *e;
|
||||
struct html_element *ep = html_context->stack.next;
|
||||
|
@ -10,7 +10,7 @@ struct html_element *search_html_stack(struct html_context *html_context,
|
||||
unsigned char *name);
|
||||
|
||||
void html_stack_dup(struct html_context *html_context,
|
||||
enum html_element_type type);
|
||||
enum html_element_mortality_type type);
|
||||
|
||||
void kill_html_stack_item(struct html_context *html_context,
|
||||
struct html_element *e);
|
||||
|
@ -1049,6 +1049,7 @@ new_link(struct html_context *html_context, unsigned char *name, int namelen)
|
||||
|
||||
init_link_event_hooks(html_context, link);
|
||||
|
||||
document->links_sorted = 0;
|
||||
return link;
|
||||
}
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -102,7 +102,7 @@ add_document_link(struct document *document, unsigned char *uri, int length,
|
||||
}
|
||||
|
||||
document->nlinks++;
|
||||
|
||||
document->links_sorted = 0;
|
||||
return link;
|
||||
}
|
||||
|
||||
@ -135,6 +135,10 @@ check_link_word(struct document *document, unsigned char *uri, int length,
|
||||
|
||||
if (!where) return NULL;
|
||||
|
||||
/* We need to reparse the URI and normalize it so that the protocol and
|
||||
* host part are converted to lowercase. */
|
||||
normalize_uri(NULL, where);
|
||||
|
||||
new_link = add_document_link(document, where, length, x, y);
|
||||
|
||||
if (!new_link) mem_free(where);
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include "viewer/text/vs.h"
|
||||
|
||||
|
||||
static void sort_links(struct document *document);
|
||||
|
||||
#ifdef CONFIG_ECMASCRIPT
|
||||
/* XXX: This function is de facto obsolete, since we do not need to copy
|
||||
* snippets around anymore (we process them in one go after the document is
|
||||
@ -129,7 +127,7 @@ process_snippets(struct ecmascript_interpreter *interpreter,
|
||||
|
||||
if (*string->source != '^') {
|
||||
/* Evaluate <script>code</script> snippet */
|
||||
ecmascript_eval(interpreter, string);
|
||||
ecmascript_eval(interpreter, string, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -194,7 +192,7 @@ process_snippets(struct ecmascript_interpreter *interpreter,
|
||||
if (fragment) {
|
||||
struct string code = INIT_STRING(fragment->data, fragment->length);
|
||||
|
||||
ecmascript_eval(interpreter, &code);
|
||||
ecmascript_eval(interpreter, &code, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -284,7 +282,6 @@ render_document(struct view_state *vs, struct document_view *doc_view,
|
||||
options->gradual_rerendering, struri(vs->uri),
|
||||
doc_view, doc_view->name, vs);
|
||||
#endif
|
||||
|
||||
name = doc_view->name;
|
||||
doc_view->name = NULL;
|
||||
|
||||
@ -328,13 +325,18 @@ render_document(struct view_state *vs, struct document_view *doc_view,
|
||||
document = get_cached_document(cached, options);
|
||||
if (document) {
|
||||
doc_view->document = document;
|
||||
#ifdef CONFIG_ECMASCRIPT
|
||||
document->doc_view = doc_view;
|
||||
#endif
|
||||
} else {
|
||||
document = init_document(cached, options);
|
||||
if (!document) return;
|
||||
doc_view->document = document;
|
||||
|
||||
shrink_memory(0);
|
||||
|
||||
#ifdef CONFIG_ECMASCRIPT
|
||||
document->doc_view = doc_view;
|
||||
#endif
|
||||
render_encoded_document(cached, document);
|
||||
sort_links(document);
|
||||
if (!document->title) {
|
||||
@ -492,7 +494,7 @@ comp_links(struct link *l1, struct link *l2)
|
||||
return (l1->number - l2->number);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sort_links(struct document *document)
|
||||
{
|
||||
int i;
|
||||
@ -501,6 +503,7 @@ sort_links(struct document *document)
|
||||
if_assert_failed return;
|
||||
if (!document->nlinks) return;
|
||||
|
||||
if (document->links_sorted) return;
|
||||
assert(document->links);
|
||||
if_assert_failed return;
|
||||
|
||||
@ -509,7 +512,9 @@ sort_links(struct document *document)
|
||||
|
||||
if (!document->height) return;
|
||||
|
||||
mem_free_if(document->lines1);
|
||||
document->lines1 = mem_calloc(document->height, sizeof(*document->lines1));
|
||||
mem_free_if(document->lines2);
|
||||
if (!document->lines1) return;
|
||||
document->lines2 = mem_calloc(document->height, sizeof(*document->lines2));
|
||||
if (!document->lines2) {
|
||||
@ -540,6 +545,7 @@ sort_links(struct document *document)
|
||||
document->lines1[j] = &document->links[i];
|
||||
}
|
||||
}
|
||||
document->links_sorted = 1;
|
||||
}
|
||||
|
||||
struct conv_table *
|
||||
|
@ -12,6 +12,6 @@ struct view_state;
|
||||
void render_document(struct view_state *, struct document_view *, struct document_options *);
|
||||
void render_document_frames(struct session *ses, int no_cache);
|
||||
struct conv_table *get_convert_table(unsigned char *head, int to_cp, int default_cp, int *from_cp, enum cp_status *cp_status, int ignore_server_cp);
|
||||
|
||||
void sort_links(struct document *document);
|
||||
|
||||
#endif
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../.vimrc
|
@ -2,7 +2,7 @@ top_builddir=../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
|
||||
SUBDIRS = css sgml
|
||||
OBJS = node.o select.o stack.o scanner.o
|
||||
OBJS = configuration.o node.o select.o stack.o scanner.o
|
||||
|
||||
SUBDIRS-$(CONFIG_DEBUG) += test
|
||||
|
||||
|
47
src/dom/code.h
Normal file
47
src/dom/code.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef EL_DOM_CODE_H
|
||||
#define EL_DOM_CODE_H
|
||||
|
||||
/* API Doc :: dom-code */
|
||||
|
||||
/** DOM status/error/exception codes
|
||||
*
|
||||
* These enum values are used for return codes throughout the DOM engine.
|
||||
*/
|
||||
enum dom_code {
|
||||
/** ELinks specific codes: */
|
||||
DOM_CODE_OK = 0, /*: The sane default. */
|
||||
DOM_CODE_ERR = -1000, /*: Anything by DOM_CODE_OK. */
|
||||
|
||||
DOM_CODE_INCOMPLETE, /*: The parsing could not be completed */
|
||||
DOM_CODE_FREE_NODE, /*: Discard the node */
|
||||
|
||||
/** Error codes: */
|
||||
DOM_CODE_ALLOC_ERR, /*: Failed to allocate memory */
|
||||
DOM_CODE_MAX_DEPTH_ERR, /*: Stack max depth reached */
|
||||
DOM_CODE_VALUE_ERR, /*: Bad/unexpected value */
|
||||
|
||||
/** DOM Level 1 codes: */
|
||||
DOM_CODE_INDEX_SIZE_ERR = 1,
|
||||
DOM_CODE_STRING_SIZE_ERR = 2,
|
||||
DOM_CODE_HIERARCHY_REQUEST_ERR = 3,
|
||||
DOM_CODE_WRONG_DOCUMENT_ERR = 4,
|
||||
DOM_CODE_INVALID_CHARACTER_ERR = 5,
|
||||
DOM_CODE_NO_DATA_ALLOWED_ERR = 6,
|
||||
DOM_CODE_NO_MODIFICATION_ALLOWED_ERR = 7,
|
||||
DOM_CODE_NOT_FOUND_ERR = 8,
|
||||
DOM_CODE_NOT_SUPPORTED_ERR = 9,
|
||||
DOM_CODE_INUSE_ATTRIBUTE_ERR = 10,
|
||||
|
||||
/** Introduced in DOM Level 2: */
|
||||
DOM_CODE_INVALID_STATE_ERR = 11,
|
||||
DOM_CODE_SYNTAX_ERR = 12,
|
||||
DOM_CODE_INVALID_MODIFICATION_ERR = 13,
|
||||
DOM_CODE_NAMESPACE_ERR = 14,
|
||||
DOM_CODE_INVALID_ACCESS_ERR = 15,
|
||||
|
||||
/** Introduced in DOM Level 3: */
|
||||
DOM_CODE_VALIDATION_ERR = 16,
|
||||
DOM_CODE_TYPE_MISMATCH_ERR = 17,
|
||||
};
|
||||
|
||||
#endif
|
351
src/dom/configuration.c
Normal file
351
src/dom/configuration.c
Normal file
@ -0,0 +1,351 @@
|
||||
/* DOM Configuration */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "dom/configuration.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/stack.h"
|
||||
#include "dom/string.h"
|
||||
|
||||
|
||||
static enum dom_code
|
||||
normalize_text_node_whitespace(struct dom_node *node)
|
||||
{
|
||||
unsigned char buf[256];
|
||||
struct dom_string string = INIT_DOM_STRING(NULL, 0);
|
||||
int count = 0, i = 0;
|
||||
unsigned char *text = node->string.string;
|
||||
|
||||
assert(node->type == DOM_NODE_TEXT);
|
||||
|
||||
while (i < node->string.length) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < sizeof(buf) && i < node->string.length; i++) {
|
||||
unsigned char data = text[i];
|
||||
|
||||
if (isspace(data)) {
|
||||
if (count == 1)
|
||||
continue;
|
||||
|
||||
data = ' ';
|
||||
count = 1;
|
||||
|
||||
} else {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
buf[j++] = data;
|
||||
}
|
||||
|
||||
if (!add_to_dom_string(&string, buf, j)) {
|
||||
done_dom_string(&string);
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->allocated)
|
||||
done_dom_string(&node->string);
|
||||
|
||||
set_dom_string(&node->string, string.string, string.length);
|
||||
node->allocated = 1;
|
||||
|
||||
return DOM_CODE_OK;
|
||||
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
append_node_text(struct dom_config *config, struct dom_node *node)
|
||||
{
|
||||
struct dom_node *prev = get_dom_node_prev(node);
|
||||
size_t length;
|
||||
struct dom_string dest;
|
||||
struct dom_string src;
|
||||
int error = 0;
|
||||
|
||||
copy_struct(&src, &node->string);
|
||||
|
||||
if (!prev || prev->type != DOM_NODE_TEXT) {
|
||||
/* Preserve text nodes with no one to append to. */
|
||||
if (node->type == DOM_NODE_TEXT)
|
||||
return DOM_CODE_OK;
|
||||
|
||||
prev = NULL;
|
||||
set_dom_string(&dest, NULL, 0);
|
||||
|
||||
} else {
|
||||
if (prev->allocated) {
|
||||
copy_struct(&dest, &prev->string);
|
||||
} else {
|
||||
set_dom_string(&dest, NULL, 0);
|
||||
if (!add_to_dom_string(&dest, prev->string.string, prev->string.length))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
set_dom_string(&prev->string, dest.string, dest.length);
|
||||
prev->allocated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
length = dest.length;
|
||||
|
||||
switch (node->type) {
|
||||
case DOM_NODE_CDATA_SECTION:
|
||||
case DOM_NODE_TEXT:
|
||||
if (!add_to_dom_string(&dest, src.string, src.length))
|
||||
error = 1;
|
||||
break;
|
||||
|
||||
case DOM_NODE_ENTITY_REFERENCE:
|
||||
/* FIXME: Until we will have uniform encoding at this point
|
||||
* (UTF-8) we just add the entity reference unexpanded assuming
|
||||
* that convert_string() will eventually do the work of
|
||||
* expanding it. */
|
||||
if (!add_to_dom_string(&dest, "&", 1)
|
||||
|| !add_to_dom_string(&dest, src.string, src.length)
|
||||
|| !add_to_dom_string(&dest, ";", 1)) {
|
||||
error = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERNAL("Cannot append from node %d", node->type);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (prev)
|
||||
prev->string.length = length;
|
||||
else
|
||||
done_dom_string(&dest);
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
copy_struct(&prev->string, &dest);
|
||||
|
||||
if ((config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE)
|
||||
&& node->type != DOM_NODE_ENTITY_REFERENCE) {
|
||||
/* XXX: Ignore errors since we want to always
|
||||
* free the appended node at this point. */
|
||||
normalize_text_node_whitespace(prev);
|
||||
}
|
||||
|
||||
return DOM_CODE_FREE_NODE;
|
||||
|
||||
} else {
|
||||
int was_cdata_section = node->type == DOM_NODE_CDATA_SECTION;
|
||||
|
||||
node->type = DOM_NODE_TEXT;
|
||||
memset(&node->data, 0, sizeof(node->data));
|
||||
node->allocated = 1;
|
||||
copy_struct(&node->string, &dest);
|
||||
|
||||
if ((config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE)
|
||||
&& was_cdata_section) {
|
||||
/* XXX: Ignore errors since we want to always ok the
|
||||
* append. */
|
||||
normalize_text_node_whitespace(node);
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
dom_normalize_node_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_config *config = stack->current->data;
|
||||
enum dom_code code = DOM_CODE_OK;
|
||||
|
||||
switch (node->type) {
|
||||
case DOM_NODE_ELEMENT:
|
||||
if ((config->flags & DOM_CONFIG_UNKNOWN)
|
||||
&& !node->data.element.type) {
|
||||
/* Drop elements that are not known from the built-in
|
||||
* node info. */
|
||||
code = DOM_CODE_FREE_NODE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_ATTRIBUTE:
|
||||
if ((config->flags & DOM_CONFIG_UNKNOWN)
|
||||
&& !node->data.attribute.type) {
|
||||
/* Drop elements that are not known from the built-in
|
||||
* node info. */
|
||||
code = DOM_CODE_FREE_NODE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_PROCESSING_INSTRUCTION:
|
||||
if ((config->flags & DOM_CONFIG_UNKNOWN)
|
||||
&& !node->data.proc_instruction.type) {
|
||||
/* Drop elements that are not known from the built-in
|
||||
* node info. */
|
||||
code = DOM_CODE_FREE_NODE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_TEXT:
|
||||
if (!(config->flags & DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE)
|
||||
&& node->data.text.only_space) {
|
||||
/* Discard all Text nodes that contain
|
||||
* whitespaces in element content]. */
|
||||
code = DOM_CODE_FREE_NODE;
|
||||
} else {
|
||||
code = append_node_text(config, node);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_COMMENT:
|
||||
if (!(config->flags & DOM_CONFIG_COMMENTS)) {
|
||||
/* Discard all comments. */
|
||||
code = DOM_CODE_FREE_NODE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_CDATA_SECTION:
|
||||
if (!(config->flags & DOM_CONFIG_CDATA_SECTIONS)) {
|
||||
/* Transform CDATASection nodes into Text nodes. The new Text
|
||||
* node is then combined with any adjacent Text node. */
|
||||
code = append_node_text(config, node);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_ENTITY_REFERENCE:
|
||||
if (!(config->flags & DOM_CONFIG_ENTITIES)) {
|
||||
/* Remove all EntityReference nodes from the document,
|
||||
* putting the entity expansions directly in their place. Text
|
||||
* nodes are normalized. Only unexpanded entity references are
|
||||
* kept in the document. */
|
||||
code = append_node_text(config, node);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_DOCUMENT:
|
||||
mem_free(config);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
enum dom_code
|
||||
dom_normalize_text(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_config *config = stack->current->data;
|
||||
|
||||
if (config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE) {
|
||||
/* Normalize whitespace in the text. */
|
||||
return normalize_text_node_whitespace(node);
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
|
||||
static struct dom_stack_context_info dom_config_normalizer_context = {
|
||||
/* Object size: */ 0,
|
||||
/* Push: */
|
||||
{
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ NULL,
|
||||
/* DOM_NODE_ATTRIBUTE */ NULL,
|
||||
/* DOM_NODE_TEXT */ dom_normalize_text,
|
||||
/* DOM_NODE_CDATA_SECTION */ NULL,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
|
||||
/* DOM_NODE_ENTITY */ NULL,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||
/* DOM_NODE_COMMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||
/* DOM_NODE_NOTATION */ NULL,
|
||||
},
|
||||
/* Pop: */
|
||||
{
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ dom_normalize_node_end,
|
||||
/* DOM_NODE_ATTRIBUTE */ dom_normalize_node_end,
|
||||
/* DOM_NODE_TEXT */ dom_normalize_node_end,
|
||||
/* DOM_NODE_CDATA_SECTION */ dom_normalize_node_end,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ dom_normalize_node_end,
|
||||
/* DOM_NODE_ENTITY */ dom_normalize_node_end,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ dom_normalize_node_end,
|
||||
/* DOM_NODE_COMMENT */ dom_normalize_node_end,
|
||||
/* DOM_NODE_DOCUMENT */ dom_normalize_node_end,
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ dom_normalize_node_end,
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ dom_normalize_node_end,
|
||||
/* DOM_NODE_NOTATION */ dom_normalize_node_end,
|
||||
}
|
||||
};
|
||||
|
||||
struct dom_config *
|
||||
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags)
|
||||
{
|
||||
struct dom_config *config;
|
||||
|
||||
config = mem_calloc(1, sizeof(*config));
|
||||
if (!config) return NULL;
|
||||
|
||||
config->flags = flags;
|
||||
|
||||
if (add_dom_stack_context(stack, config, &dom_config_normalizer_context))
|
||||
return config;
|
||||
|
||||
mem_free(config);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dom_config_info {
|
||||
struct dom_string name;
|
||||
enum dom_config_flag flag;
|
||||
};
|
||||
|
||||
#define DOM_CONFIG(name, flag) \
|
||||
{ STATIC_DOM_STRING(name), (flag) }
|
||||
|
||||
static struct dom_config_info dom_config_info[] = {
|
||||
DOM_CONFIG("cdata-sections", DOM_CONFIG_CDATA_SECTIONS),
|
||||
DOM_CONFIG("comments", DOM_CONFIG_COMMENTS),
|
||||
DOM_CONFIG("element-content-whitespace",DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE),
|
||||
DOM_CONFIG("entities", DOM_CONFIG_ENTITIES),
|
||||
DOM_CONFIG("normalize-characters", DOM_CONFIG_NORMALIZE_CHARACTERS),
|
||||
DOM_CONFIG("unknown", DOM_CONFIG_UNKNOWN),
|
||||
DOM_CONFIG("normalize-whitespace", DOM_CONFIG_NORMALIZE_WHITESPACE),
|
||||
};
|
||||
|
||||
static enum dom_config_flag
|
||||
get_dom_config_flag(struct dom_string *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof_array(dom_config_info); i++)
|
||||
if (!dom_string_casecmp(&dom_config_info[i].name, name))
|
||||
return dom_config_info[i].flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum dom_config_flag
|
||||
parse_dom_config(unsigned char *flaglist, unsigned char separator)
|
||||
{
|
||||
enum dom_config_flag flags = 0;
|
||||
|
||||
while (flaglist) {
|
||||
unsigned char *end = separator ? strchr(flaglist, separator) : NULL;
|
||||
int length = end ? end - flaglist : strlen(flaglist);
|
||||
struct dom_string name = INIT_DOM_STRING(flaglist, length);
|
||||
|
||||
flags |= get_dom_config_flag(&name);
|
||||
if (end) end++;
|
||||
flaglist = end;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
94
src/dom/configuration.h
Normal file
94
src/dom/configuration.h
Normal file
@ -0,0 +1,94 @@
|
||||
#ifndef EL__DOM_CONFIGURATION_H
|
||||
#define EL__DOM_CONFIGURATION_H
|
||||
|
||||
struct dom_node;
|
||||
struct dom_stack;
|
||||
|
||||
/* API Doc :: dom-config */
|
||||
|
||||
/** DOM Configuration
|
||||
*
|
||||
* The DOMConfiguration interface represents the configuration of a document.
|
||||
* Using the configuration, it is possible to change the behaviour of how
|
||||
* document normalization is done, such as replacing the CDATASection nodes
|
||||
* with Text nodes.
|
||||
*
|
||||
* Note: Parameters are similar to features and properties used in SAX2 [SAX].
|
||||
*
|
||||
* The following list of parameters defined in the DOM: */
|
||||
|
||||
enum dom_config_flag {
|
||||
/** "cdata-sections"
|
||||
*
|
||||
* The default is true and will keep CDATASection nodes in the
|
||||
* document. When false, CDATASection nodes in the document are
|
||||
* transformed into Text nodes. The new Text node is then combined with
|
||||
* any adjacent Text node. */
|
||||
DOM_CONFIG_CDATA_SECTIONS = 1,
|
||||
|
||||
/** "comments"
|
||||
*
|
||||
* If true (the default) keep Comment nodes in the document, else
|
||||
* discard them. */
|
||||
DOM_CONFIG_COMMENTS = 2,
|
||||
|
||||
/** "element-content-whitespace"
|
||||
*
|
||||
* The default is true and will keep all whitespaces in the document.
|
||||
* When false, discard all Text nodes that contain only whitespaces. */
|
||||
DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE = 4,
|
||||
|
||||
/** "entities"
|
||||
*
|
||||
* When true (the default) keep EntityReference nodes in the document.
|
||||
* When false, remove all EntityReference nodes from the document,
|
||||
* putting the entity expansions directly in their place. Text nodes
|
||||
* are normalized. Only unexpanded entity references are kept in the
|
||||
* document. Note: This parameter does not affect Entity nodes. */
|
||||
DOM_CONFIG_ENTITIES = 8,
|
||||
|
||||
/** "normalize-characters"
|
||||
*
|
||||
* The default is false, not to perform character normalization, else
|
||||
* fully normalized the characters in the document as defined in
|
||||
* appendix B of [XML 1.1]. */
|
||||
DOM_CONFIG_NORMALIZE_CHARACTERS = 16,
|
||||
|
||||
/** "unknown"
|
||||
*
|
||||
* If false (default) nothing is done, else elements and attributes
|
||||
* that are not known according to the built-in node info are
|
||||
* discarded. */
|
||||
DOM_CONFIG_UNKNOWN = 32,
|
||||
|
||||
/** "normalize-whitespace"
|
||||
*
|
||||
* If false (default) nothing is done, else all text nodes are
|
||||
* normalized so that sequences of space characters are changed to
|
||||
* being only a single space. */
|
||||
DOM_CONFIG_NORMALIZE_WHITESPACE = 64,
|
||||
};
|
||||
|
||||
struct dom_error;
|
||||
|
||||
struct dom_config {
|
||||
enum dom_config_flag flags; /*: DOM configuration flags. */
|
||||
|
||||
/** FIXME: "error-handler"
|
||||
*
|
||||
* Contains an error handler. If an error is encountered in the
|
||||
* document, this handler is called. When called, DOMError.relatedData
|
||||
* will contain the closest node to where the error occurred. If the
|
||||
* implementation is unable to determine the node where the error
|
||||
* occurs, DOMError.relatedData will contain the Document node.
|
||||
*/
|
||||
void (*error_handler)(struct dom_config *, struct dom_error *);
|
||||
};
|
||||
|
||||
struct dom_config *
|
||||
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags);
|
||||
|
||||
enum dom_config_flag
|
||||
parse_dom_config(unsigned char *flaglist, unsigned char separator);
|
||||
|
||||
#endif
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -55,7 +55,7 @@ static const struct dom_scan_table_info css_scan_table_info[] = {
|
||||
};
|
||||
|
||||
#define CSS_STRING_MAP(str, type, family) \
|
||||
{ INIT_DOM_STRING(str, -1), CSS_TOKEN_##type, CSS_TOKEN_##family }
|
||||
{ STATIC_DOM_STRING(str), CSS_TOKEN_##type, CSS_TOKEN_##family }
|
||||
|
||||
static const struct dom_scanner_string_mapping css_string_mappings[] = {
|
||||
CSS_STRING_MAP("Hz", FREQUENCY, DIMENSION),
|
||||
|
@ -1,25 +0,0 @@
|
||||
#ifndef EL_DOM_DOM_H
|
||||
#define EL_DOM_DOM_H
|
||||
|
||||
enum dom_exception_code {
|
||||
DOM_ERR_NONE = 0,
|
||||
DOM_ERR_INDEX_SIZE = 1,
|
||||
DOM_ERR_STRING_SIZE = 2,
|
||||
DOM_ERR_HIERARCHY_REQUEST = 3,
|
||||
DOM_ERR_WRONG_DOCUMENT = 4,
|
||||
DOM_ERR_INVALID_CHARACTER = 5,
|
||||
DOM_ERR_NO_DATA_ALLOWED = 6,
|
||||
DOM_ERR_NO_MODIFICATION_ALLOWED = 7,
|
||||
DOM_ERR_NOT_FOUND = 8,
|
||||
DOM_ERR_NOT_SUPPORTED = 9,
|
||||
DOM_ERR_INUSE_ATTRIBUTE = 10,
|
||||
|
||||
/* Introduced in DOM Level 2: */
|
||||
DOM_ERR_INVALID_STATE = 11,
|
||||
DOM_ERR_SYNTAX = 12,
|
||||
DOM_ERR_INVALID_MODIFICATION = 13,
|
||||
DOM_ERR_NAMESPACE = 14,
|
||||
DOM_ERR_INVALID_ACCESS = 15,
|
||||
};
|
||||
|
||||
#endif
|
172
src/dom/node.c
172
src/dom/node.c
@ -190,7 +190,8 @@ dom_node_list_bsearch(struct dom_node_search *search, struct dom_node_list *list
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node)
|
||||
int
|
||||
get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node)
|
||||
{
|
||||
struct dom_node_search search = INIT_DOM_NODE_SEARCH(node, list);
|
||||
struct dom_node *match = dom_node_list_bsearch(&search, list);
|
||||
@ -202,7 +203,7 @@ struct dom_node *
|
||||
get_dom_node_map_entry(struct dom_node_list *list, enum dom_node_type type,
|
||||
uint16_t subtype, struct dom_string *name)
|
||||
{
|
||||
struct dom_node node = { type, INIT_DOM_STRING(name->string, name->length) };
|
||||
struct dom_node node = { type, 0, INIT_DOM_STRING(name->string, name->length) };
|
||||
struct dom_node_search search = INIT_DOM_NODE_SEARCH(&node, list);
|
||||
|
||||
if (subtype) {
|
||||
@ -225,16 +226,15 @@ get_dom_node_map_entry(struct dom_node_list *list, enum dom_node_type type,
|
||||
return dom_node_list_bsearch(&search, list);
|
||||
}
|
||||
|
||||
int
|
||||
get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
|
||||
static int
|
||||
get_dom_node_list_pos(struct dom_node_list *list, struct dom_node *node)
|
||||
{
|
||||
struct dom_node_list **list = get_dom_node_list(parent, node);
|
||||
struct dom_node *entry;
|
||||
int i;
|
||||
|
||||
if (!list) return -1;
|
||||
assert(list);
|
||||
|
||||
foreach_dom_node (*list, entry, i) {
|
||||
foreach_dom_node (list, entry, i) {
|
||||
if (entry == node)
|
||||
return i;
|
||||
}
|
||||
@ -242,12 +242,98 @@ get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
|
||||
{
|
||||
struct dom_node_list **list = get_dom_node_list(parent, node);
|
||||
|
||||
return list ? get_dom_node_list_pos(*list, node) : -1;
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
get_dom_node_prev(struct dom_node *node)
|
||||
{
|
||||
struct dom_node_list **list;
|
||||
int index;
|
||||
|
||||
assert(node->parent);
|
||||
|
||||
list = get_dom_node_list(node->parent, node);
|
||||
if (!list) return NULL;
|
||||
|
||||
index = get_dom_node_list_pos(*list, node);
|
||||
if (index > 0)
|
||||
return (*list)->entries[index - 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
get_dom_node_next(struct dom_node *node)
|
||||
{
|
||||
struct dom_node_list **list;
|
||||
int index;
|
||||
|
||||
assert(node->parent);
|
||||
|
||||
list = get_dom_node_list(node->parent, node);
|
||||
if (!list) return NULL;
|
||||
|
||||
index = get_dom_node_list_pos(*list, node);
|
||||
if (index + 1 < (*list)->size)
|
||||
return (*list)->entries[index + 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
get_dom_node_child(struct dom_node *parent, enum dom_node_type type,
|
||||
int16_t subtype)
|
||||
{
|
||||
struct dom_node_list **list;
|
||||
struct dom_node *node;
|
||||
int index;
|
||||
|
||||
list = get_dom_node_list_by_type(parent, type);
|
||||
if (!list) return NULL;
|
||||
|
||||
foreach_dom_node (*list, node, index) {
|
||||
if (node->type != type)
|
||||
continue;
|
||||
|
||||
if (!subtype) return node;
|
||||
|
||||
switch (type) {
|
||||
case DOM_NODE_ELEMENT:
|
||||
if (node->data.element.type == subtype)
|
||||
return node;
|
||||
break;
|
||||
|
||||
case DOM_NODE_ATTRIBUTE:
|
||||
if (node->data.attribute.type == subtype)
|
||||
return node;
|
||||
break;
|
||||
|
||||
case DOM_NODE_PROCESSING_INSTRUCTION:
|
||||
if (node->data.attribute.type == subtype)
|
||||
return node;
|
||||
break;
|
||||
|
||||
default:
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Nodes */
|
||||
|
||||
struct dom_node *
|
||||
init_dom_node_(unsigned char *file, int line,
|
||||
struct dom_node *parent, enum dom_node_type type,
|
||||
struct dom_string *string)
|
||||
struct dom_string *string, int allocated)
|
||||
{
|
||||
#ifdef DEBUG_MEMLEAK
|
||||
struct dom_node *node = debug_mem_calloc(file, line, 1, sizeof(*node));
|
||||
@ -259,7 +345,23 @@ init_dom_node_(unsigned char *file, int line,
|
||||
|
||||
node->type = type;
|
||||
node->parent = parent;
|
||||
|
||||
/* Make it possible to add a node to a parent without allocating the
|
||||
* strings. */
|
||||
if (allocated >= 0) {
|
||||
node->allocated = !!allocated;
|
||||
} else if (parent) {
|
||||
node->allocated = parent->allocated;
|
||||
}
|
||||
|
||||
if (node->allocated) {
|
||||
if (!init_dom_string(&node->string, string->string, string->length)) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
copy_dom_string(&node->string, string);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
struct dom_node_list **list = get_dom_node_list(parent, node);
|
||||
@ -292,17 +394,11 @@ done_dom_node_data(struct dom_node *node)
|
||||
|
||||
switch (node->type) {
|
||||
case DOM_NODE_ATTRIBUTE:
|
||||
if (data->attribute.allocated)
|
||||
done_dom_string(&node->string);
|
||||
if (node->allocated)
|
||||
done_dom_string(&data->attribute.value);
|
||||
break;
|
||||
|
||||
case DOM_NODE_DOCUMENT:
|
||||
if (data->document.element_ids)
|
||||
free_hash(data->document.element_ids);
|
||||
|
||||
if (data->document.meta_nodes)
|
||||
done_dom_node_list(data->document.meta_nodes);
|
||||
|
||||
if (data->document.children)
|
||||
done_dom_node_list(data->document.children);
|
||||
break;
|
||||
@ -315,20 +411,19 @@ done_dom_node_data(struct dom_node *node)
|
||||
done_dom_node_list(data->element.map);
|
||||
break;
|
||||
|
||||
case DOM_NODE_TEXT:
|
||||
if (data->text.allocated)
|
||||
done_dom_string(&node->string);
|
||||
break;
|
||||
|
||||
case DOM_NODE_PROCESSING_INSTRUCTION:
|
||||
if (data->proc_instruction.map)
|
||||
done_dom_node_list(data->proc_instruction.map);
|
||||
if (node->allocated)
|
||||
done_dom_string(&data->proc_instruction.instruction);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (node->allocated)
|
||||
done_dom_string(&node->string);
|
||||
mem_free(node);
|
||||
}
|
||||
|
||||
@ -343,7 +438,6 @@ done_dom_node(struct dom_node *node)
|
||||
|
||||
switch (parent->type) {
|
||||
case DOM_NODE_DOCUMENT:
|
||||
del_from_dom_node_list(data->document.meta_nodes, node);
|
||||
del_from_dom_node_list(data->document.children, node);
|
||||
break;
|
||||
|
||||
@ -370,11 +464,11 @@ done_dom_node(struct dom_node *node)
|
||||
struct dom_string *
|
||||
get_dom_node_name(struct dom_node *node)
|
||||
{
|
||||
static struct dom_string cdata_section_str = INIT_DOM_STRING("#cdata-section", -1);
|
||||
static struct dom_string comment_str = INIT_DOM_STRING("#comment", -1);
|
||||
static struct dom_string document_str = INIT_DOM_STRING("#document", -1);
|
||||
static struct dom_string document_fragment_str = INIT_DOM_STRING("#document-fragment", -1);
|
||||
static struct dom_string text_str = INIT_DOM_STRING("#text", -1);
|
||||
static struct dom_string cdata_section_str = STATIC_DOM_STRING("#cdata-section");
|
||||
static struct dom_string comment_str = STATIC_DOM_STRING("#comment");
|
||||
static struct dom_string document_str = STATIC_DOM_STRING("#document");
|
||||
static struct dom_string document_fragment_str = STATIC_DOM_STRING("#document-fragment");
|
||||
static struct dom_string text_str = STATIC_DOM_STRING("#text");
|
||||
|
||||
assert(node);
|
||||
|
||||
@ -440,18 +534,18 @@ get_dom_node_type_name(enum dom_node_type type)
|
||||
{
|
||||
static struct dom_string dom_node_type_names[DOM_NODES] = {
|
||||
INIT_DOM_STRING(NULL, 0),
|
||||
/* DOM_NODE_ELEMENT */ INIT_DOM_STRING("element", -1),
|
||||
/* DOM_NODE_ATTRIBUTE */ INIT_DOM_STRING("attribute", -1),
|
||||
/* DOM_NODE_TEXT */ INIT_DOM_STRING("text", -1),
|
||||
/* DOM_NODE_CDATA_SECTION */ INIT_DOM_STRING("cdata-section", -1),
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ INIT_DOM_STRING("entity-reference", -1),
|
||||
/* DOM_NODE_ENTITY */ INIT_DOM_STRING("entity", -1),
|
||||
/* DOM_NODE_PROCESSING_INSTRUCTION */ INIT_DOM_STRING("proc-instruction", -1),
|
||||
/* DOM_NODE_COMMENT */ INIT_DOM_STRING("comment", -1),
|
||||
/* DOM_NODE_DOCUMENT */ INIT_DOM_STRING("document", -1),
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ INIT_DOM_STRING("document-type", -1),
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ INIT_DOM_STRING("document-fragment", -1),
|
||||
/* DOM_NODE_NOTATION */ INIT_DOM_STRING("notation", -1),
|
||||
/* DOM_NODE_ELEMENT */ STATIC_DOM_STRING("element"),
|
||||
/* DOM_NODE_ATTRIBUTE */ STATIC_DOM_STRING("attribute"),
|
||||
/* DOM_NODE_TEXT */ STATIC_DOM_STRING("text"),
|
||||
/* DOM_NODE_CDATA_SECTION */ STATIC_DOM_STRING("cdata-section"),
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ STATIC_DOM_STRING("entity-reference"),
|
||||
/* DOM_NODE_ENTITY */ STATIC_DOM_STRING("entity"),
|
||||
/* DOM_NODE_PROCESSING_INSTRUCTION */ STATIC_DOM_STRING("proc-instruction"),
|
||||
/* DOM_NODE_COMMENT */ STATIC_DOM_STRING("comment"),
|
||||
/* DOM_NODE_DOCUMENT */ STATIC_DOM_STRING("document"),
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ STATIC_DOM_STRING("document-type"),
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ STATIC_DOM_STRING("document-fragment"),
|
||||
/* DOM_NODE_NOTATION */ STATIC_DOM_STRING("notation"),
|
||||
};
|
||||
|
||||
assert(type < DOM_NODES);
|
||||
|
119
src/dom/node.h
119
src/dom/node.h
@ -3,9 +3,9 @@
|
||||
#define EL_DOM_NODE_H
|
||||
|
||||
#include "dom/string.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
struct dom_node_list;
|
||||
struct dom_document;
|
||||
|
||||
enum dom_node_type {
|
||||
DOM_NODE_UNKNOWN = 0, /* for internal purpose only */
|
||||
@ -27,27 +27,15 @@ enum dom_node_type {
|
||||
};
|
||||
|
||||
/* Following is the node specific datastructures. They may contain no more
|
||||
* than 3 pointers or something equivalent. */
|
||||
|
||||
struct dom_node_id_item {
|
||||
/* The attibute node containing the id value */
|
||||
struct dom_node *id_attribute;
|
||||
|
||||
/* The node with the @id attribute */
|
||||
struct dom_node *node;
|
||||
};
|
||||
* than 4 pointers or something equivalent. */
|
||||
|
||||
/* The document URI is stored in the string / length members. */
|
||||
struct dom_document_node {
|
||||
/* The document URI is stored in the string / length members. */
|
||||
/* An id to node hash for fast lookup. */
|
||||
struct hash *element_ids; /* -> {struct dom_node_id_item} */
|
||||
|
||||
/* Any meta data the root node carries such as document type nodes,
|
||||
* entity and notation map nodes and maybe some internal CSS stylesheet
|
||||
* node. */
|
||||
struct dom_node_list *meta_nodes;
|
||||
/* The document. */
|
||||
struct dom_document *document;
|
||||
|
||||
/* The child nodes. May be NULL. Ordered like they where inserted. */
|
||||
/* FIXME: Should be just one element (root) node reference. */
|
||||
struct dom_node_list *children;
|
||||
};
|
||||
|
||||
@ -111,13 +99,13 @@ struct dom_attribute_node {
|
||||
* to reduce string comparing and only do one fast find mapping. */
|
||||
uint16_t type;
|
||||
|
||||
/* The attribute value is delimited by quotes. Can be NUL, ' or ". */
|
||||
unsigned char quoted;
|
||||
|
||||
/* Was the attribute specified in the DTD as a default attribute or was
|
||||
* it added from the document source. */
|
||||
unsigned int specified:1;
|
||||
|
||||
/* Was the node->string allocated */
|
||||
unsigned int allocated:1;
|
||||
|
||||
/* Has the node->string been converted to internal charset. */
|
||||
unsigned int converted:1;
|
||||
|
||||
@ -127,9 +115,6 @@ struct dom_attribute_node {
|
||||
|
||||
/* The attribute value references some other resource */
|
||||
unsigned int reference:1;
|
||||
|
||||
/* The attribute value is delimited by quotes */
|
||||
unsigned int quoted:1;
|
||||
};
|
||||
|
||||
struct dom_text_node {
|
||||
@ -140,9 +125,6 @@ struct dom_text_node {
|
||||
* In order to quickly identify such nodes this member is used. */
|
||||
unsigned int only_space:1;
|
||||
|
||||
/* Was the node->string allocated */
|
||||
unsigned int allocated:1;
|
||||
|
||||
/* Has the node->string been converted to internal charset. */
|
||||
unsigned int converted:1;
|
||||
};
|
||||
@ -151,9 +133,8 @@ enum dom_proc_instruction_type {
|
||||
DOM_PROC_INSTRUCTION,
|
||||
|
||||
/* Keep this group sorted */
|
||||
DOM_PROC_INSTRUCTION_DBHTML, /* DocBook toolchain instruction */
|
||||
DOM_PROC_INSTRUCTION_ELINKS, /* Internal instruction hook */
|
||||
DOM_PROC_INSTRUCTION_XML, /* XML instructions */
|
||||
DOM_PROC_INSTRUCTION_XML, /* XML header */
|
||||
DOM_PROC_INSTRUCTION_XML_STYLESHEET, /* XML stylesheet link */
|
||||
|
||||
DOM_PROC_INSTRUCTION_TYPES
|
||||
};
|
||||
@ -183,12 +164,13 @@ union dom_node_data {
|
||||
struct dom_id entity;
|
||||
struct dom_proc_instruction_node proc_instruction;
|
||||
|
||||
/* Node types without a union member yet
|
||||
/* Node types without a union member yet (mostly because it hasn't
|
||||
* been necessary):
|
||||
*
|
||||
* DOM_NODE_CDATA_SECTION,
|
||||
* DOM_NODE_COMMENT,
|
||||
* DOM_NODE_DOCUMENT_FRAGMENT,
|
||||
* DOM_NODE_ENTITY_REFERENCE,
|
||||
* DOM_NODE_CDATA_SECTION: Use dom_text_node?
|
||||
* DOM_NODE_DOCUMENT_FRAGMENT: struct dom_node_list children;
|
||||
* DOM_NODE_ENTITY_REFERENCE: unicode_val_T
|
||||
* DOM_NODE_COMMENT
|
||||
*/
|
||||
};
|
||||
|
||||
@ -198,6 +180,9 @@ struct dom_node {
|
||||
/* The type of the node */
|
||||
uint16_t type; /* -> enum dom_node_type */
|
||||
|
||||
/* Was the node string allocated? */
|
||||
unsigned int allocated:1;
|
||||
|
||||
/* Can contain either stuff like element name or for attributes the
|
||||
* attribute name. */
|
||||
struct dom_string string;
|
||||
@ -243,6 +228,17 @@ int get_dom_node_list_index(struct dom_node *parent, struct dom_node *node);
|
||||
* @list is already sorted properly. */
|
||||
int get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node);
|
||||
|
||||
/* Returns the previous sibling to the node. */
|
||||
struct dom_node *get_dom_node_prev(struct dom_node *node);
|
||||
|
||||
/* Returns the next sibling to the node. */
|
||||
struct dom_node *get_dom_node_next(struct dom_node *node);
|
||||
|
||||
/* Returns first text node of the element or NULL. */
|
||||
struct dom_node *
|
||||
get_dom_node_child(struct dom_node *node, enum dom_node_type child_type,
|
||||
int16_t child_subtype);
|
||||
|
||||
/* Looks up the @node_map for a node matching the requested type and name.
|
||||
* The @subtype maybe be 0 indication unknown subtype and only name should be
|
||||
* tested else it will indicate either the element or attribute private
|
||||
@ -252,12 +248,21 @@ get_dom_node_map_entry(struct dom_node_list *node_map,
|
||||
enum dom_node_type type, uint16_t subtype,
|
||||
struct dom_string *name);
|
||||
|
||||
/* Removes the node and all its children and free()s itself */
|
||||
void done_dom_node(struct dom_node *node);
|
||||
|
||||
/* The allocated argument is used as the value of node->allocated if >= 0.
|
||||
* Use -1 to default node->allocated to the value of parent->allocated. */
|
||||
struct dom_node *
|
||||
init_dom_node_(unsigned char *file, int line,
|
||||
struct dom_node *parent, enum dom_node_type type,
|
||||
struct dom_string *string);
|
||||
#define init_dom_node(type, string) init_dom_node_(__FILE__, __LINE__, NULL, type, string)
|
||||
#define add_dom_node(parent, type, string) init_dom_node_(__FILE__, __LINE__, parent, type, string)
|
||||
struct dom_string *string, int allocated);
|
||||
|
||||
#define init_dom_node(type, string, allocated) \
|
||||
init_dom_node_(__FILE__, __LINE__, NULL, type, string, allocated)
|
||||
|
||||
#define add_dom_node(parent, type, string) \
|
||||
init_dom_node_(__FILE__, __LINE__, parent, type, string, -1)
|
||||
|
||||
#define add_dom_element(parent, string) \
|
||||
add_dom_node(parent, DOM_NODE_ELEMENT, string)
|
||||
@ -269,7 +274,16 @@ add_dom_attribute(struct dom_node *parent, struct dom_string *name,
|
||||
struct dom_node *node = add_dom_node(parent, DOM_NODE_ATTRIBUTE, name);
|
||||
|
||||
if (node && value) {
|
||||
copy_dom_string(&node->data.attribute.value, value);
|
||||
struct dom_string *str = &node->data.attribute.value;
|
||||
|
||||
if (node->allocated) {
|
||||
if (!init_dom_string(str, value->string, value->length)) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
copy_dom_string(str, value);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -282,15 +296,21 @@ add_dom_proc_instruction(struct dom_node *parent, struct dom_string *string,
|
||||
struct dom_node *node = add_dom_node(parent, DOM_NODE_PROCESSING_INSTRUCTION, string);
|
||||
|
||||
if (node && instruction) {
|
||||
copy_dom_string(&node->data.proc_instruction.instruction, instruction);
|
||||
struct dom_string *str = &node->data.proc_instruction.instruction;
|
||||
|
||||
if (node->allocated) {
|
||||
if (!init_dom_string(str, instruction->string, instruction->length)) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
copy_dom_string(str, instruction);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Removes the node and all its children and free()s itself */
|
||||
void done_dom_node(struct dom_node *node);
|
||||
|
||||
/* Compare two nodes returning non-zero if they differ. */
|
||||
int dom_node_casecmp(struct dom_node *node1, struct dom_node *node2);
|
||||
|
||||
@ -304,17 +324,17 @@ struct dom_string *get_dom_node_value(struct dom_node *node);
|
||||
/* Returns the name used for identifying the node type. */
|
||||
struct dom_string *get_dom_node_type_name(enum dom_node_type type);
|
||||
|
||||
/* Based on the type of the parent and the node return a proper list
|
||||
/* Based on the type of the parent and the node type return a proper list
|
||||
* or NULL. This is useful when adding a node to a parent node. */
|
||||
static inline struct dom_node_list **
|
||||
get_dom_node_list(struct dom_node *parent, struct dom_node *node)
|
||||
get_dom_node_list_by_type(struct dom_node *parent, enum dom_node_type type)
|
||||
{
|
||||
switch (parent->type) {
|
||||
case DOM_NODE_DOCUMENT:
|
||||
return &parent->data.document.children;
|
||||
|
||||
case DOM_NODE_ELEMENT:
|
||||
switch (node->type) {
|
||||
switch (type) {
|
||||
case DOM_NODE_ATTRIBUTE:
|
||||
return &parent->data.element.map;
|
||||
|
||||
@ -323,7 +343,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
|
||||
}
|
||||
|
||||
case DOM_NODE_DOCUMENT_TYPE:
|
||||
switch (node->type) {
|
||||
switch (type) {
|
||||
case DOM_NODE_ENTITY:
|
||||
return &parent->data.document_type.entities;
|
||||
|
||||
@ -335,7 +355,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
|
||||
}
|
||||
|
||||
case DOM_NODE_PROCESSING_INSTRUCTION:
|
||||
switch (node->type) {
|
||||
switch (type) {
|
||||
case DOM_NODE_ATTRIBUTE:
|
||||
return &parent->data.proc_instruction.map;
|
||||
|
||||
@ -348,4 +368,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
|
||||
}
|
||||
}
|
||||
|
||||
#define get_dom_node_list(parent, node) \
|
||||
get_dom_node_list_by_type(parent, (node)->type)
|
||||
|
||||
#endif
|
||||
|
@ -67,7 +67,7 @@ struct dom_scanner_string_mapping {
|
||||
};
|
||||
|
||||
#define DOM_STRING_MAP(str, type, family) \
|
||||
{ INIT_DOM_STRING(str, -1), (type), (family) }
|
||||
{ STATIC_DOM_STRING(str), (type), (family) }
|
||||
|
||||
#define DOM_STRING_MAP_END \
|
||||
{ INIT_DOM_STRING(NULL, 0), 0, 0 }
|
||||
|
119
src/dom/select.c
119
src/dom/select.c
@ -7,7 +7,7 @@
|
||||
#include "elinks.h"
|
||||
|
||||
#include "dom/css/scanner.h"
|
||||
#include "dom/dom.h"
|
||||
#include "dom/code.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/scanner.h"
|
||||
#include "dom/select.h"
|
||||
@ -28,7 +28,7 @@ get_dom_select_pseudo(struct dom_scanner_token *token)
|
||||
} pseudo_info[] = {
|
||||
|
||||
#define INIT_DOM_SELECT_PSEUDO_STRING(str, type) \
|
||||
{ INIT_DOM_STRING(str, -1), DOM_SELECT_PSEUDO_##type }
|
||||
{ STATIC_DOM_STRING(str), DOM_SELECT_PSEUDO_##type }
|
||||
|
||||
INIT_DOM_SELECT_PSEUDO_STRING("first-line", FIRST_LINE),
|
||||
INIT_DOM_SELECT_PSEUDO_STRING("first-letter", FIRST_LETTER),
|
||||
@ -80,7 +80,7 @@ get_dom_select_pseudo(struct dom_scanner_token *token)
|
||||
}
|
||||
|
||||
/* Parses attribute selector. For example '[foo="bar"]' or '[foo|="boo"]'. */
|
||||
static enum dom_exception_code
|
||||
static enum dom_code
|
||||
parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
|
||||
@ -88,25 +88,25 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
|
||||
/* Get '['. */
|
||||
|
||||
if (token->type != '[')
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
/* Get the attribute name. */
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token || token->type != CSS_TOKEN_IDENT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
copy_dom_string(&sel->node.string, &token->string);
|
||||
|
||||
/* Get the optional '=' combo or ending ']'. */
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
switch (token->type) {
|
||||
case ']':
|
||||
sel->match.attribute |= DOM_SELECT_ATTRIBUTE_ANY;
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
case CSS_TOKEN_SELECT_SPACE_LIST:
|
||||
sel->match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
|
||||
@ -129,13 +129,13 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
|
||||
break;
|
||||
|
||||
default:
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
/* Get the required value. */
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
switch (token->type) {
|
||||
case CSS_TOKEN_IDENT:
|
||||
@ -144,16 +144,16 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
|
||||
break;
|
||||
|
||||
default:
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
/* Get the ending ']'. */
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (token && token->type == ']')
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
/* Parse:
|
||||
@ -190,7 +190,7 @@ get_scanner_token_number(struct dom_scanner_token *token)
|
||||
}
|
||||
|
||||
/* Parses the '(...)' part of ':nth-of-type(...)' and ':nth-child(...)'. */
|
||||
static enum dom_exception_code
|
||||
static enum dom_code
|
||||
parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token *token = get_next_dom_scanner_token(scanner);
|
||||
@ -198,11 +198,11 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
|
||||
int number = -1;
|
||||
|
||||
if (!token || token->type != '(')
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
switch (token->type) {
|
||||
case CSS_TOKEN_IDENT:
|
||||
@ -220,59 +220,59 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
|
||||
}
|
||||
|
||||
if (skip_css_tokens(scanner, ')'))
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
case '-':
|
||||
sign = -1;
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
if (token->type != CSS_TOKEN_IDENT)
|
||||
break;
|
||||
|
||||
if (token->type != CSS_TOKEN_NUMBER)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
/* Fall-through */
|
||||
|
||||
case CSS_TOKEN_NUMBER:
|
||||
number = get_scanner_token_number(token);
|
||||
if (number < 0)
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
return DOM_CODE_VALUE_ERR;
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
break;
|
||||
|
||||
default:
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
/* The rest can contain n+ part */
|
||||
switch (token->type) {
|
||||
case CSS_TOKEN_IDENT:
|
||||
if (!dom_scanner_token_contains(token, "n"))
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
nth->step = sign * number;
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
if (token->type != '+')
|
||||
break;
|
||||
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token) return DOM_ERR_SYNTAX;
|
||||
if (!token) return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
if (token->type != CSS_TOKEN_NUMBER)
|
||||
break;
|
||||
|
||||
number = get_scanner_token_number(token);
|
||||
if (number < 0)
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
return DOM_CODE_VALUE_ERR;
|
||||
|
||||
nth->index = sign * number;
|
||||
break;
|
||||
@ -283,19 +283,19 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
|
||||
}
|
||||
|
||||
if (skip_css_tokens(scanner, ')'))
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
/* Parse a pseudo-class or -element with the syntax: ':<ident>'. */
|
||||
static enum dom_exception_code
|
||||
static enum dom_code
|
||||
parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
|
||||
enum dom_select_pseudo pseudo;
|
||||
enum dom_exception_code code;
|
||||
enum dom_code code;
|
||||
|
||||
/* Skip double :'s in front of some pseudo's (::first-line, etc.) */
|
||||
do {
|
||||
@ -303,12 +303,12 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
} while (token && token->type == ':');
|
||||
|
||||
if (!token || token->type != CSS_TOKEN_IDENT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
pseudo = get_dom_select_pseudo(token);
|
||||
switch (pseudo) {
|
||||
case DOM_SELECT_PSEUDO_UNKNOWN:
|
||||
return DOM_ERR_NOT_FOUND;
|
||||
return DOM_CODE_ERR;
|
||||
|
||||
case DOM_SELECT_PSEUDO_CONTAINS:
|
||||
/* FIXME: E:contains("text") */
|
||||
@ -317,7 +317,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
case DOM_SELECT_PSEUDO_NTH_CHILD:
|
||||
case DOM_SELECT_PSEUDO_NTH_LAST_CHILD:
|
||||
code = parse_dom_select_nth_arg(&sel->nth_child, scanner);
|
||||
if (code != DOM_ERR_NONE)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
sel->match.element |= DOM_SELECT_ELEMENT_NTH_CHILD;
|
||||
@ -341,7 +341,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
case DOM_SELECT_PSEUDO_NTH_TYPE:
|
||||
case DOM_SELECT_PSEUDO_NTH_LAST_TYPE:
|
||||
code = parse_dom_select_nth_arg(&sel->nth_type, scanner);
|
||||
if (code != DOM_ERR_NONE)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
sel->match.element |= DOM_SELECT_ELEMENT_NTH_TYPE;
|
||||
@ -375,7 +375,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
select->pseudo |= pseudo;
|
||||
}
|
||||
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
/* The element relation flags are mutual exclusive. This macro can be used
|
||||
@ -384,7 +384,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
|
||||
((sel)->match.element & DOM_SELECT_RELATION_FLAGS)
|
||||
|
||||
/* Parse a CSS3 selector and add selector nodes to the @select struct. */
|
||||
static enum dom_exception_code
|
||||
static enum dom_code
|
||||
parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
struct dom_string *string)
|
||||
{
|
||||
@ -397,7 +397,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
|
||||
while (dom_scanner_has_tokens(&scanner)) {
|
||||
struct dom_scanner_token *token = get_dom_scanner_token(&scanner);
|
||||
enum dom_exception_code code;
|
||||
enum dom_code code;
|
||||
struct dom_select_node *select_node;
|
||||
|
||||
assert(token);
|
||||
@ -430,14 +430,14 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
case '[':
|
||||
sel.node.type = DOM_NODE_ATTRIBUTE;
|
||||
code = parse_dom_select_attribute(&sel, &scanner);
|
||||
if (code != DOM_ERR_NONE)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
token = get_next_dom_scanner_token(&scanner);
|
||||
if (!token || token->type != CSS_TOKEN_IDENT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
|
||||
sel.node.type = DOM_NODE_ATTRIBUTE;
|
||||
sel.match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
|
||||
@ -447,30 +447,30 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
|
||||
case ':':
|
||||
code = parse_dom_select_pseudo(select, &sel, &scanner);
|
||||
if (code != DOM_ERR_NONE)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
sel.match.element |= DOM_SELECT_RELATION_DIRECT_CHILD;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
sel.match.element |= DOM_SELECT_RELATION_DIRECT_ADJACENT;
|
||||
break;
|
||||
|
||||
case '~':
|
||||
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
sel.match.element |= DOM_SELECT_RELATION_INDIRECT_ADJACENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return DOM_ERR_SYNTAX;
|
||||
return DOM_CODE_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
skip_dom_scanner_token(&scanner);
|
||||
@ -496,7 +496,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
|
||||
if (!add_to_dom_node_list(list, node, index)) {
|
||||
done_dom_node(node);
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
}
|
||||
|
||||
node->parent = parent;
|
||||
@ -506,8 +506,9 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
select->selector = select_node;
|
||||
}
|
||||
|
||||
if (!push_dom_node(stack, &select_node->node))
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
code = push_dom_node(stack, &select_node->node);
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
if (select_node->node.type != DOM_NODE_ELEMENT)
|
||||
pop_dom_node(stack);
|
||||
@ -516,9 +517,9 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
||||
}
|
||||
|
||||
if (select->selector)
|
||||
return DOM_ERR_NONE;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
return DOM_ERR_INVALID_STATE;
|
||||
return DOM_CODE_ERR;
|
||||
}
|
||||
|
||||
/* Basically this is just a wrapper for parse_dom_select() to ease error
|
||||
@ -528,7 +529,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
|
||||
{
|
||||
struct dom_select *select = mem_calloc(1, sizeof(select));
|
||||
struct dom_stack stack;
|
||||
enum dom_exception_code code;
|
||||
enum dom_code code;
|
||||
|
||||
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||
add_dom_stack_tracer(&stack, "init-select: ");
|
||||
@ -536,7 +537,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
|
||||
code = parse_dom_select(select, &stack, string);
|
||||
done_dom_stack(&stack);
|
||||
|
||||
if (code == DOM_ERR_NONE)
|
||||
if (code == DOM_CODE_OK)
|
||||
return select;
|
||||
|
||||
done_dom_select(select);
|
||||
@ -897,7 +898,7 @@ match_element_selector(struct dom_select_node *selector, struct dom_node *node,
|
||||
#define get_dom_select_data(stack) ((stack)->current->data)
|
||||
|
||||
/* Matches an element node being visited against the current selector stack. */
|
||||
static void
|
||||
enum dom_code
|
||||
dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_select_data *select_data = get_dom_select_data(stack);
|
||||
@ -921,11 +922,13 @@ dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
if (selector)
|
||||
push_dom_node(&select_data->stack, &selector->node);
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
/* Ensures that nodes, no longer 'reachable' on the stack do not have any
|
||||
* states associated with them on the select data stack. */
|
||||
static void
|
||||
enum dom_code
|
||||
dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_select_data *select_data = get_dom_select_data(stack);
|
||||
@ -944,12 +947,14 @@ dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *dat
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
/* For now this is only for matching the ':contains(<string>)' pseudo-class.
|
||||
* Any node which can contain text and thus characters from the given <string>
|
||||
* are handled in this common callback. */
|
||||
static void
|
||||
enum dom_code
|
||||
dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_select_data *select_data = get_dom_select_data(stack);
|
||||
@ -961,7 +966,7 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
WDBG("Text node: %d chars", node->string.length);
|
||||
|
||||
if (!text_sel)
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
text = &text_sel->node.string;
|
||||
|
||||
@ -973,6 +978,8 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
default:
|
||||
ERROR("Unhandled type");
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
/* Context info for interacting with the DOM tree or stream stack. */
|
||||
@ -1070,7 +1077,7 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
|
||||
&dom_select_data_context_info);
|
||||
add_dom_stack_tracer(&select_data.stack, "select-match: ");
|
||||
|
||||
if (push_dom_node(&select_data.stack, &select->selector->node)) {
|
||||
if (push_dom_node(&select_data.stack, &select->selector->node) == DOM_CODE_OK) {
|
||||
get_dom_stack_top(&select_data.stack)->immutable = 1;
|
||||
walk_dom_nodes(&stack, root);
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
|
||||
SUBDIRS = docbook html rss xbel
|
||||
OBJS = sgml.o parser.o scanner.o
|
||||
OBJS = dump.o parser.o scanner.o sgml.o
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
170
src/dom/sgml/dump.c
Normal file
170
src/dom/sgml/dump.c
Normal file
@ -0,0 +1,170 @@
|
||||
/* SGML generics */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "dom/node.h"
|
||||
#include "dom/sgml/dump.h"
|
||||
#include "dom/stack.h"
|
||||
#include "dom/string.h"
|
||||
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_element_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "<%.*s", string->length, string->string);
|
||||
if (!node->data.element.map
|
||||
|| node->data.element.map->size == 0)
|
||||
fprintf(file, ">");
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_element_pop(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "</%.*s>", string->length, string->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_attribute_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *name = &node->string;
|
||||
struct dom_string *value = &node->data.attribute.value;
|
||||
|
||||
if (node->parent->type == DOM_NODE_PROCESSING_INSTRUCTION)
|
||||
return DOM_CODE_OK;
|
||||
|
||||
fprintf(file, " %.*s", name->length, name->string);
|
||||
|
||||
if (value->string) {
|
||||
if (node->data.attribute.quoted)
|
||||
fprintf(file, "=%c%.*s%c",
|
||||
node->data.attribute.quoted,
|
||||
value->length, value->string,
|
||||
node->data.attribute.quoted);
|
||||
else
|
||||
/* FIXME: 'encode' if the value contains '"'s? */
|
||||
fprintf(file, "=\"%.*s\"", value->length, value->string);
|
||||
}
|
||||
|
||||
if (!get_dom_node_next(node))
|
||||
fprintf(file, ">");
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_proc_instruction_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *target = &node->string;
|
||||
struct dom_string *instruction = &node->data.proc_instruction.instruction;
|
||||
|
||||
fprintf(file, "<?%.*s %.*s?>",
|
||||
target->length, target->string,
|
||||
instruction->length, instruction->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_text_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "%.*s", string->length, string->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_cdata_section_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "<![CDATA[%.*s]]>", string->length, string->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_comment_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "<!--%.*s-->", string->length, string->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum dom_code
|
||||
sgml_file_dumper_entity_ref_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
FILE *file = stack->current->data;
|
||||
struct dom_string *string = &node->string;
|
||||
|
||||
fprintf(file, "&%.*s;", string->length, string->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
struct dom_stack_context_info sgml_file_dumper = {
|
||||
/* Object size: */ 0,
|
||||
/* Push: */
|
||||
{
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ sgml_file_dumper_element_push,
|
||||
/* DOM_NODE_ATTRIBUTE */ sgml_file_dumper_attribute_push,
|
||||
/* DOM_NODE_TEXT */ sgml_file_dumper_text_push,
|
||||
/* DOM_NODE_CDATA_SECTION */ sgml_file_dumper_cdata_section_push,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ sgml_file_dumper_entity_ref_push,
|
||||
/* DOM_NODE_ENTITY */ NULL,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ sgml_file_dumper_proc_instruction_push,
|
||||
/* DOM_NODE_COMMENT */ sgml_file_dumper_comment_push,
|
||||
/* DOM_NODE_DOCUMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||
/* DOM_NODE_NOTATION */ NULL,
|
||||
},
|
||||
/* Pop: */
|
||||
{
|
||||
/* */ NULL,
|
||||
/* DOM_NODE_ELEMENT */ sgml_file_dumper_element_pop,
|
||||
/* DOM_NODE_ATTRIBUTE */ NULL,
|
||||
/* DOM_NODE_TEXT */ NULL,
|
||||
/* DOM_NODE_CDATA_SECTION */ NULL,
|
||||
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
|
||||
/* DOM_NODE_ENTITY */ NULL,
|
||||
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||
/* DOM_NODE_COMMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||
/* DOM_NODE_NOTATION */ NULL,
|
||||
}
|
||||
};
|
||||
|
||||
struct dom_stack_context *
|
||||
add_sgml_file_dumper(struct dom_stack *stack, FILE *file)
|
||||
{
|
||||
return add_dom_stack_context(stack, file, &sgml_file_dumper);
|
||||
}
|
12
src/dom/sgml/dump.h
Normal file
12
src/dom/sgml/dump.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef EL_DOM_SGML_DUMP_H
|
||||
#define EL_DOM_SGML_DUMP_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct dom_stack;
|
||||
struct dom_stack_context;
|
||||
|
||||
struct dom_stack_context *
|
||||
add_sgml_file_dumper(struct dom_stack *stack, FILE *file);
|
||||
|
||||
#endif
|
@ -35,11 +35,16 @@
|
||||
* information like node subtypes and SGML parser state information. */
|
||||
|
||||
static inline struct dom_node *
|
||||
add_sgml_document(struct dom_stack *stack, struct dom_string *string)
|
||||
add_sgml_document(struct sgml_parser *parser)
|
||||
{
|
||||
struct dom_node *node = init_dom_node(DOM_NODE_DOCUMENT, string);
|
||||
int allocated = parser->flags & SGML_PARSER_INCREMENTAL;
|
||||
struct dom_node *node;
|
||||
|
||||
return node ? push_dom_node(stack, node) : NULL;
|
||||
node = init_dom_node(DOM_NODE_DOCUMENT, &parser->uri, allocated);
|
||||
if (node && push_dom_node(&parser->stack, node) == DOM_CODE_OK)
|
||||
return node;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct dom_node *
|
||||
@ -58,7 +63,7 @@ add_sgml_element(struct dom_stack *stack, struct dom_scanner_token *token)
|
||||
node_info = get_sgml_node_info(parser->info->elements, node);
|
||||
node->data.element.type = node_info->type;
|
||||
|
||||
if (!push_dom_node(stack, node))
|
||||
if (push_dom_node(stack, node) != DOM_CODE_OK)
|
||||
return NULL;
|
||||
|
||||
state = get_dom_stack_top(stack);
|
||||
@ -71,7 +76,7 @@ add_sgml_element(struct dom_stack *stack, struct dom_scanner_token *token)
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
static inline struct dom_node *
|
||||
add_sgml_attribute(struct dom_stack *stack,
|
||||
struct dom_scanner_token *token, struct dom_scanner_token *valtoken)
|
||||
{
|
||||
@ -90,12 +95,14 @@ add_sgml_attribute(struct dom_stack *stack,
|
||||
node->data.attribute.reference = !!(info->flags & SGML_ATTRIBUTE_REFERENCE);
|
||||
|
||||
if (valtoken && valtoken->type == SGML_TOKEN_STRING)
|
||||
node->data.attribute.quoted = 1;
|
||||
node->data.attribute.quoted = valtoken->string.string[-1];
|
||||
|
||||
if (!node || !push_dom_node(stack, node))
|
||||
return;
|
||||
if (!node || push_dom_node(stack, node) != DOM_CODE_OK)
|
||||
return NULL;
|
||||
|
||||
pop_dom_node(stack);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline struct dom_node *
|
||||
@ -114,33 +121,42 @@ add_sgml_proc_instruction(struct dom_stack *stack, struct dom_scanner_token *tar
|
||||
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION_XML;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS_XML_STYLESHEET:
|
||||
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION_XML_STYLESHEET;
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_PROCESS:
|
||||
default:
|
||||
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION;
|
||||
}
|
||||
|
||||
return push_dom_node(stack, node);
|
||||
if (push_dom_node(stack, node) == DOM_CODE_OK)
|
||||
return node;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline struct dom_node *
|
||||
add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct dom_scanner_token *token)
|
||||
{
|
||||
struct dom_node *parent = get_dom_stack_top(stack)->node;
|
||||
struct dom_node *node = add_dom_node(parent, type, &token->string);
|
||||
|
||||
if (!node) return;
|
||||
if (!node) return NULL;
|
||||
|
||||
if (token->type == SGML_TOKEN_SPACE)
|
||||
node->data.text.only_space = 1;
|
||||
|
||||
if (push_dom_node(stack, node))
|
||||
if (push_dom_node(stack, node) == DOM_CODE_OK)
|
||||
pop_dom_node(stack);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/* SGML parser main handling: */
|
||||
|
||||
static enum sgml_parser_code
|
||||
static enum dom_code
|
||||
call_sgml_error_function(struct dom_stack *stack, struct dom_scanner_token *token)
|
||||
{
|
||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||
@ -151,18 +167,42 @@ call_sgml_error_function(struct dom_stack *stack, struct dom_scanner_token *toke
|
||||
return parser->error_func(parser, &token->string, line);
|
||||
}
|
||||
|
||||
static inline enum sgml_parser_code
|
||||
/* Appends to or 'creates' an incomplete token. This can be used to
|
||||
* force tokens back into the 'stream' if they require that later tokens
|
||||
* are available.
|
||||
*
|
||||
* NOTE: You can only do this for tokens that are not stripped of markup such
|
||||
* as identifiers. */
|
||||
static enum dom_code
|
||||
check_sgml_incomplete(struct dom_scanner *scanner,
|
||||
struct dom_scanner_token *start,
|
||||
struct dom_scanner_token *token)
|
||||
{
|
||||
if (token && token->type == SGML_TOKEN_INCOMPLETE) {
|
||||
token->string.length += token->string.string - start->string.string;
|
||||
token->string.string = start->string.string;
|
||||
return 1;
|
||||
|
||||
} else if (!token && scanner->check_complete && scanner->incomplete) {
|
||||
size_t left = scanner->end - start->string.string;
|
||||
|
||||
assert(left > 0);
|
||||
|
||||
token = scanner->current = scanner->table;
|
||||
scanner->tokens = 1;
|
||||
token->type = SGML_TOKEN_INCOMPLETE;
|
||||
set_dom_string(&token->string, start->string.string, left);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline enum dom_code
|
||||
parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token name;
|
||||
|
||||
assert(dom_scanner_has_tokens(scanner)
|
||||
&& (get_dom_scanner_token(scanner)->type == SGML_TOKEN_ELEMENT_BEGIN
|
||||
|| (get_dom_stack_top(stack)->node->type == DOM_NODE_PROCESSING_INSTRUCTION)));
|
||||
|
||||
if (get_dom_scanner_token(scanner)->type == SGML_TOKEN_ELEMENT_BEGIN)
|
||||
skip_dom_scanner_token(scanner);
|
||||
|
||||
while (dom_scanner_has_tokens(scanner)) {
|
||||
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
|
||||
|
||||
@ -176,7 +216,7 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
case SGML_TOKEN_ELEMENT_BEGIN:
|
||||
case SGML_TOKEN_ELEMENT_END:
|
||||
case SGML_TOKEN_ELEMENT_EMPTY_END:
|
||||
return SGML_PARSER_CODE_OK;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
case SGML_TOKEN_IDENT:
|
||||
copy_struct(&name, token);
|
||||
@ -188,8 +228,8 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
/* If the token is not a valid value token
|
||||
* ignore it. */
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (token && token->type == SGML_TOKEN_INCOMPLETE)
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
if (check_sgml_incomplete(scanner, &name, token))
|
||||
return DOM_CODE_INCOMPLETE;
|
||||
|
||||
if (token
|
||||
&& token->type != SGML_TOKEN_IDENT
|
||||
@ -197,14 +237,15 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
&& token->type != SGML_TOKEN_STRING)
|
||||
token = NULL;
|
||||
|
||||
} else if (token && token->type == SGML_TOKEN_INCOMPLETE) {
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
} else if (check_sgml_incomplete(scanner, &name, token)) {
|
||||
return DOM_CODE_INCOMPLETE;
|
||||
|
||||
} else {
|
||||
token = NULL;
|
||||
}
|
||||
|
||||
add_sgml_attribute(stack, &name, token);
|
||||
if (!add_sgml_attribute(stack, &name, token))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
|
||||
/* Skip the value token */
|
||||
if (token)
|
||||
@ -212,14 +253,14 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_INCOMPLETE:
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
return DOM_CODE_INCOMPLETE;
|
||||
|
||||
case SGML_TOKEN_ERROR:
|
||||
{
|
||||
enum sgml_parser_code code;
|
||||
enum dom_code code;
|
||||
|
||||
code = call_sgml_error_function(stack, token);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
skip_dom_scanner_token(scanner);
|
||||
@ -230,10 +271,10 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
}
|
||||
}
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static enum sgml_parser_code
|
||||
static enum dom_code
|
||||
parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
{
|
||||
struct dom_scanner_token target;
|
||||
@ -244,21 +285,16 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
switch (token->type) {
|
||||
case SGML_TOKEN_ELEMENT:
|
||||
case SGML_TOKEN_ELEMENT_BEGIN:
|
||||
if (!add_sgml_element(stack, token)) {
|
||||
if (token->type == SGML_TOKEN_ELEMENT) {
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
}
|
||||
|
||||
skip_sgml_tokens(scanner, SGML_TOKEN_TAG_END);
|
||||
break;
|
||||
}
|
||||
if (!add_sgml_element(stack, token))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
|
||||
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
|
||||
enum sgml_parser_code code;
|
||||
enum dom_code code;
|
||||
|
||||
skip_dom_scanner_token(scanner);
|
||||
|
||||
code = parse_sgml_attributes(stack, scanner);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
} else {
|
||||
@ -295,7 +331,8 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_NOTATION_COMMENT:
|
||||
add_sgml_node(stack, DOM_NODE_COMMENT, token);
|
||||
if (!add_sgml_node(stack, DOM_NODE_COMMENT, token))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
@ -308,7 +345,8 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_CDATA_SECTION:
|
||||
add_sgml_node(stack, DOM_NODE_CDATA_SECTION, token);
|
||||
if (!add_sgml_node(stack, DOM_NODE_CDATA_SECTION, token))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
skip_dom_scanner_token(scanner);
|
||||
break;
|
||||
|
||||
@ -320,7 +358,7 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
/* Skip the target token */
|
||||
token = get_next_dom_scanner_token(scanner);
|
||||
if (!token || token->type == SGML_TOKEN_INCOMPLETE)
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
return DOM_CODE_INCOMPLETE;
|
||||
|
||||
if (token->type == SGML_TOKEN_ERROR)
|
||||
break;
|
||||
@ -328,9 +366,9 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
assert(token->type == SGML_TOKEN_PROCESS_DATA);
|
||||
/* Fall-through */
|
||||
|
||||
case SGML_TOKEN_PROCESS_DATA:
|
||||
if (add_sgml_proc_instruction(stack, &target, token)
|
||||
&& (target.type == SGML_TOKEN_PROCESS_XML
|
||||
if (!add_sgml_proc_instruction(stack, &target, token))
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
if ((target.type == SGML_TOKEN_PROCESS_XML
|
||||
|| target.type == SGML_TOKEN_PROCESS_XML_STYLESHEET)
|
||||
&& token->string.length > 0) {
|
||||
/* Parse the <?xml data="attributes"?>. */
|
||||
@ -361,14 +399,14 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
break;
|
||||
|
||||
case SGML_TOKEN_INCOMPLETE:
|
||||
return SGML_PARSER_CODE_INCOMPLETE;
|
||||
return DOM_CODE_INCOMPLETE;
|
||||
|
||||
case SGML_TOKEN_ERROR:
|
||||
{
|
||||
enum sgml_parser_code code;
|
||||
enum dom_code code;
|
||||
|
||||
code = call_sgml_error_function(stack, token);
|
||||
if (code != SGML_PARSER_CODE_OK)
|
||||
if (code != DOM_CODE_OK)
|
||||
return code;
|
||||
|
||||
skip_dom_scanner_token(scanner);
|
||||
@ -382,10 +420,10 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||
}
|
||||
}
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
enum sgml_parser_code
|
||||
enum dom_code
|
||||
parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
|
||||
int complete)
|
||||
{
|
||||
@ -396,17 +434,15 @@ parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
|
||||
parser->flags |= SGML_PARSER_COMPLETE;
|
||||
|
||||
if (!parser->root) {
|
||||
parser->root = add_sgml_document(&parser->stack, &parser->uri);
|
||||
parser->root = add_sgml_document(parser);
|
||||
if (!parser->root)
|
||||
return SGML_PARSER_CODE_MEM_ALLOC;
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||
}
|
||||
|
||||
node = init_dom_node(DOM_NODE_TEXT, &source);
|
||||
if (!node || !push_dom_node(&parser->parsing, node))
|
||||
return SGML_PARSER_CODE_MEM_ALLOC;
|
||||
|
||||
pop_dom_node(&parser->parsing);
|
||||
node = init_dom_node(DOM_NODE_TEXT, &source, 0);
|
||||
if (!node || push_dom_node(&parser->parsing, node) != DOM_CODE_OK)
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
|
||||
return parser->code;
|
||||
}
|
||||
@ -423,10 +459,12 @@ parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
|
||||
struct sgml_parsing_state {
|
||||
struct dom_scanner scanner;
|
||||
struct dom_node *node;
|
||||
struct dom_string incomplete;
|
||||
size_t depth;
|
||||
unsigned int resume:1;
|
||||
};
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||
@ -435,29 +473,109 @@ sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
int complete = !!(parser->flags & SGML_PARSER_COMPLETE);
|
||||
int incremental = !!(parser->flags & SGML_PARSER_INCREMENTAL);
|
||||
int detect_errors = !!(parser->flags & SGML_PARSER_DETECT_ERRORS);
|
||||
struct dom_string *string = &node->string;
|
||||
struct dom_scanner_token *token;
|
||||
struct dom_string incomplete;
|
||||
enum sgml_scanner_state scanner_state = SGML_STATE_TEXT;
|
||||
|
||||
parsing->depth = parser->stack.depth;
|
||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, &node->string,
|
||||
SGML_STATE_TEXT, count_lines, complete, incremental,
|
||||
|
||||
if (stack->depth > 1) {
|
||||
struct sgml_parsing_state *parent = &parsing[-1];
|
||||
|
||||
if (parent->resume) {
|
||||
if (is_dom_string_set(&parent->incomplete)) {
|
||||
|
||||
if (!add_to_dom_string(&parent->incomplete,
|
||||
string->string,
|
||||
string->length)) {
|
||||
|
||||
parser->code = DOM_CODE_ALLOC_ERR;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
string = &parent->incomplete;
|
||||
}
|
||||
|
||||
scanner_state = parent->scanner.state;
|
||||
|
||||
/* Pop down to the parent. */
|
||||
parsing = parent;
|
||||
parsing->resume = 0;
|
||||
pop_dom_node(stack);
|
||||
}
|
||||
}
|
||||
|
||||
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, string,
|
||||
scanner_state, count_lines, complete, incremental,
|
||||
detect_errors);
|
||||
|
||||
if (scanner_state == SGML_STATE_ELEMENT) {
|
||||
parser->code = parse_sgml_attributes(&parser->stack, &parsing->scanner);
|
||||
if (parser->code == DOM_CODE_OK)
|
||||
parser->code = parse_sgml_plain(&parser->stack, &parsing->scanner);
|
||||
} else {
|
||||
parser->code = parse_sgml_plain(&parser->stack, &parsing->scanner);
|
||||
}
|
||||
|
||||
if (complete) {
|
||||
pop_dom_node(&parser->parsing);
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
if (parser->code != DOM_CODE_INCOMPLETE) {
|
||||
/* No need to preserve the default scanner state. */
|
||||
if (parsing->scanner.state == SGML_STATE_TEXT) {
|
||||
pop_dom_node(&parser->parsing);
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
done_dom_string(&parsing->incomplete);
|
||||
parsing->resume = 1;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
token = get_dom_scanner_token(&parsing->scanner);
|
||||
assert(token && token->type == SGML_TOKEN_INCOMPLETE);
|
||||
|
||||
string = &token->string;
|
||||
|
||||
set_dom_string(&incomplete, NULL, 0);
|
||||
|
||||
if (!init_dom_string(&incomplete, string->string, string->length)) {
|
||||
parser->code = DOM_CODE_ALLOC_ERR;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
done_dom_string(&parsing->incomplete);
|
||||
set_dom_string(&parsing->incomplete, incomplete.string, incomplete.length);
|
||||
parsing->resume = 1;
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
sgml_parsing_pop(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||
struct sgml_parsing_state *parsing = data;
|
||||
|
||||
/* Only clean up the stack if complete so that we get proper nesting. */
|
||||
if (parser->flags & SGML_PARSER_COMPLETE) {
|
||||
/* Pop the stack back to the state it was in. This includes cleaning
|
||||
* away even immutable states left on the stack. */
|
||||
while (parsing->depth < parser->stack.depth) {
|
||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
||||
pop_dom_node(&parser->stack);
|
||||
}
|
||||
/* It's bigger than when calling done_sgml_parser() in the middle of an
|
||||
* incomplete parsing. */
|
||||
assert(parsing->depth >= parser->stack.depth);
|
||||
}
|
||||
|
||||
assert(parsing->depth == parser->stack.depth);
|
||||
done_dom_string(&parsing->incomplete);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static struct dom_stack_context_info sgml_parsing_context_info = {
|
||||
@ -601,8 +719,10 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||
void
|
||||
done_sgml_parser(struct sgml_parser *parser)
|
||||
{
|
||||
done_dom_stack(&parser->stack);
|
||||
while (!dom_stack_is_empty(&parser->parsing))
|
||||
pop_dom_node(&parser->parsing);
|
||||
done_dom_stack(&parser->parsing);
|
||||
done_dom_stack(&parser->stack);
|
||||
done_dom_string(&parser->uri);
|
||||
mem_free(parser);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef EL_DOM_SGML_PARSER_H
|
||||
#define EL_DOM_SGML_PARSER_H
|
||||
|
||||
#include "dom/code.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/stack.h"
|
||||
#include "dom/sgml/sgml.h"
|
||||
@ -62,27 +63,13 @@ struct sgml_parser_state {
|
||||
struct dom_scanner_token end_token;
|
||||
};
|
||||
|
||||
/** (Error) codes for the SGML parser
|
||||
*
|
||||
* These enum values are used for return codes.
|
||||
*/
|
||||
enum sgml_parser_code {
|
||||
SGML_PARSER_CODE_OK, /*: The parsing was successful */
|
||||
SGML_PARSER_CODE_INCOMPLETE, /*: The parsing could not be completed */
|
||||
SGML_PARSER_CODE_MEM_ALLOC, /*: Failed to allocate memory */
|
||||
/**
|
||||
* FIXME: For when we will add support for requiring stricter parsing
|
||||
* or even a validator. */
|
||||
SGML_PARSER_CODE_ERROR,
|
||||
};
|
||||
|
||||
/** SGML error callback
|
||||
*
|
||||
* Called by the SGML parser when a parsing error has occurred.
|
||||
*
|
||||
* If the return code is not ref:[SGML_PARSER_CODE_OK] the parsing will be
|
||||
* If the return code is not ref:[DOM_CODE_OK] the parsing will be
|
||||
* ended and that code will be returned. */
|
||||
typedef enum sgml_parser_code
|
||||
typedef enum dom_code
|
||||
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);
|
||||
|
||||
|
||||
@ -101,7 +88,7 @@ struct sgml_parser {
|
||||
struct dom_string uri; /*: The URI of the DOM document */
|
||||
struct dom_node *root; /*: The document root node */
|
||||
|
||||
enum sgml_parser_code code; /*: The latest (error) code */
|
||||
enum dom_code code; /*: The latest (error) code */
|
||||
sgml_error_T error_func; /*: Called for detected errors */
|
||||
|
||||
struct dom_stack stack; /*: A stack for tracking parsed nodes */
|
||||
@ -142,10 +129,10 @@ void done_sgml_parser(struct sgml_parser *parser);
|
||||
* bufsize:: The size of the buffer given in the buf parameter.
|
||||
* complete:: Whether this is the last chunk to parse.
|
||||
*
|
||||
* The returned code is ref:[SGML_PARSER_CODE_OK] if the buffer was
|
||||
* The returned code is ref:[DOM_CODE_OK] if the buffer was
|
||||
* successfully parserd, else a code hinting at the error.
|
||||
*/
|
||||
enum sgml_parser_code
|
||||
enum dom_code
|
||||
parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize, int complete);
|
||||
|
||||
/** Get the line position in the source
|
||||
|
@ -44,7 +44,7 @@ static struct dom_scan_table_info sgml_scan_table_info[] = {
|
||||
};
|
||||
|
||||
#define SGML_STRING_MAP(str, type, family) \
|
||||
{ INIT_DOM_STRING(str, -1), SGML_TOKEN_##type, SGML_TOKEN_##family }
|
||||
{ STATIC_DOM_STRING(str), SGML_TOKEN_##type, SGML_TOKEN_##family }
|
||||
|
||||
static struct dom_scanner_string_mapping sgml_string_mappings[] = {
|
||||
SGML_STRING_MAP("--", NOTATION_COMMENT, NOTATION),
|
||||
@ -368,12 +368,20 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string,
|
||||
/* It is always safe to access index -2 and -1 here since we
|
||||
* are supposed to have '<!--' before this is called. We do
|
||||
* however need to check that the '-->' are not overlapping any
|
||||
* preceeding '-'. */
|
||||
if (pos[-2] == '-' && pos[-1] == '-' && &pos[-2] >= *string) {
|
||||
* preceeding '-'. Additionally also handle the quirky '--!>'
|
||||
* end sometimes found. */
|
||||
if (pos[-2] == '-') {
|
||||
if (pos[-1] == '-' && &pos[-2] >= *string) {
|
||||
length = pos - *string - 2;
|
||||
*possibly_incomplete = 0;
|
||||
pos++;
|
||||
break;
|
||||
} else if (pos[-1] == '!' && pos[-3] == '-' && &pos[-3] >= *string) {
|
||||
length = pos - *string - 3;
|
||||
*possibly_incomplete = 0;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,6 +439,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
enum sgml_token_type type = SGML_TOKEN_GARBAGE;
|
||||
int real_length = -1;
|
||||
int possibly_incomplete = 1;
|
||||
enum sgml_scanner_state scanner_state = scanner->state;
|
||||
|
||||
token->string.string = string++;
|
||||
|
||||
@ -440,13 +449,17 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
if (scanner->state == SGML_STATE_ELEMENT) {
|
||||
/* Already inside an element so insert a tag end token
|
||||
* and continue scanning in next iteration. */
|
||||
string--;
|
||||
real_length = 0;
|
||||
type = SGML_TOKEN_TAG_END;
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
scanner_state = SGML_STATE_TEXT;
|
||||
|
||||
/* We are creating a 'virtual' that has no source. */
|
||||
possibly_incomplete = 0;
|
||||
string = token->string.string;
|
||||
real_length = 0;
|
||||
|
||||
} else if (string == scanner->end) {
|
||||
/* It is incomplete so prevent out of bound acess to
|
||||
* the scanned string. */
|
||||
|
||||
} else if (is_sgml_ident(*string)) {
|
||||
token->string.string = string;
|
||||
@ -455,7 +468,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
real_length = string - token->string.string;
|
||||
|
||||
skip_sgml_space(scanner, &string);
|
||||
if (*string == '>') {
|
||||
if (string < scanner->end && *string == '>') {
|
||||
type = SGML_TOKEN_ELEMENT;
|
||||
string++;
|
||||
|
||||
@ -468,8 +481,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
scanner->state = SGML_STATE_ELEMENT;
|
||||
type = SGML_TOKEN_ELEMENT_BEGIN;
|
||||
scanner_state = SGML_STATE_ELEMENT;
|
||||
}
|
||||
|
||||
} else if (*string == '!') {
|
||||
@ -519,7 +532,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
|
||||
type = map_dom_scanner_string(scanner, pos, string, base);
|
||||
|
||||
scanner->state = SGML_STATE_PROC_INST;
|
||||
scanner_state = SGML_STATE_PROC_INST;
|
||||
|
||||
real_length = string - token->string.string;
|
||||
skip_sgml_space(scanner, &string);
|
||||
@ -531,11 +544,37 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
if (scanner->check_complete && scanner->incomplete) {
|
||||
/* We need to fit both the process target token
|
||||
* and the process data token into the scanner
|
||||
* table. */
|
||||
if (token + 1 >= scanner->table + DOM_SCANNER_TOKENS) {
|
||||
possibly_incomplete = 1;
|
||||
|
||||
} else if (!possibly_incomplete) {
|
||||
/* FIXME: We do this twice. */
|
||||
for (pos = string + 1;
|
||||
(pos = skip_sgml_chars(scanner, pos, '>'));
|
||||
pos++) {
|
||||
if (pos[-1] == '?')
|
||||
break;
|
||||
}
|
||||
if (!pos)
|
||||
possibly_incomplete = 1;
|
||||
}
|
||||
|
||||
if (possibly_incomplete)
|
||||
string = scanner->end;
|
||||
}
|
||||
|
||||
} else if (*string == '/') {
|
||||
string++;
|
||||
skip_sgml_space(scanner, &string);
|
||||
|
||||
if (is_sgml_ident(*string)) {
|
||||
if (string == scanner->end) {
|
||||
/* Prevent out of bound access. */
|
||||
|
||||
} else if (is_sgml_ident(*string)) {
|
||||
token->string.string = string;
|
||||
scan_sgml(scanner, string, SGML_CHAR_IDENT);
|
||||
real_length = string - token->string.string;
|
||||
@ -555,8 +594,9 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
possibly_incomplete = 0;
|
||||
}
|
||||
|
||||
if (type != SGML_TOKEN_GARBAGE)
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
if (type != SGML_TOKEN_GARBAGE) {
|
||||
scanner_state = SGML_STATE_TEXT;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Alien < > stuff so ignore it */
|
||||
@ -586,7 +626,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
|
||||
type = SGML_TOKEN_TAG_END;
|
||||
assert(scanner->state == SGML_STATE_ELEMENT);
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
scanner_state = SGML_STATE_TEXT;
|
||||
|
||||
} else if (first_char == '/') {
|
||||
/* We allow '/' inside elements and only consider it as an end
|
||||
@ -598,12 +638,15 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
* For stricter parsing we should always require attribute
|
||||
* values to be quoted.
|
||||
*/
|
||||
if (*string == '>') {
|
||||
if (string == scanner->end) {
|
||||
/* Prevent out of bound access. */
|
||||
|
||||
} else if (*string == '>') {
|
||||
string++;
|
||||
real_length = 0;
|
||||
type = SGML_TOKEN_ELEMENT_EMPTY_END;
|
||||
assert(scanner->state == SGML_STATE_ELEMENT);
|
||||
scanner->state = SGML_STATE_TEXT;
|
||||
scanner_state = SGML_STATE_TEXT;
|
||||
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
@ -631,7 +674,12 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
/* We found the end. */
|
||||
possibly_incomplete = 0;
|
||||
|
||||
} else if (is_sgml_attribute(*string)) {
|
||||
} else if (scanner->check_complete && scanner->incomplete) {
|
||||
/* Force an incomplete token. */
|
||||
string = scanner->end;
|
||||
|
||||
} else if (string < scanner->end
|
||||
&& is_sgml_attribute(*string)) {
|
||||
token->string.string++;
|
||||
scan_sgml_attribute(scanner, string);
|
||||
type = SGML_TOKEN_ATTRIBUTE;
|
||||
@ -643,7 +691,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
type = SGML_TOKEN_IDENT;
|
||||
}
|
||||
|
||||
if (is_sgml_attribute(*string)) {
|
||||
if (string < scanner->end
|
||||
&& is_sgml_attribute(*string)) {
|
||||
scan_sgml_attribute(scanner, string);
|
||||
type = SGML_TOKEN_ATTRIBUTE;
|
||||
if (string[-1] == '/' && string[0] == '>') {
|
||||
@ -670,6 +719,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
||||
}
|
||||
}
|
||||
|
||||
/* Only apply the state change if the token was not abandoned because
|
||||
* it was incomplete. */
|
||||
scanner->state = scanner_state;
|
||||
|
||||
token->type = type;
|
||||
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
|
||||
token->precedence = get_sgml_precedence(type);
|
||||
@ -684,9 +737,9 @@ scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token
|
||||
{
|
||||
unsigned char *string = scanner->position;
|
||||
/* The length can be empty for '<??>'. */
|
||||
size_t length = -1;
|
||||
ssize_t length = -1;
|
||||
|
||||
token->string.string = string;
|
||||
token->string.string = string++;
|
||||
|
||||
/* Figure out where the processing instruction ends. This doesn't use
|
||||
* skip_sgml() since we MUST ignore precedence here to allow '<' inside
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dom/stack.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/string.h"
|
||||
|
||||
/* The flags stored in the attribute sgml node info data */
|
||||
@ -55,10 +55,10 @@ struct sgml_node_info {
|
||||
{ INIT_DOM_STRING(NULL, doctype##_##nodetype##S - 1), doctype##_##nodetype##_UNKNOWN }
|
||||
|
||||
#define SGML_NODE_INFO(doctype, nodetype, name, data) \
|
||||
{ INIT_DOM_STRING(#name, sizeof(#name) - 1), doctype##_##nodetype##_##name, data }
|
||||
{ STATIC_DOM_STRING(#name), doctype##_##nodetype##_##name, data }
|
||||
|
||||
#define SGML_NODE_INF2(doctype, nodetype, name, ident, data) \
|
||||
{ INIT_DOM_STRING(ident, sizeof(ident) - 1), doctype##_##nodetype##_##name, data }
|
||||
{ STATIC_DOM_STRING(ident), doctype##_##nodetype##_##name, data }
|
||||
|
||||
#define SGML_NODE_INFO_TYPE(doctype, nodetype, name) doctype##_##nodetype##_##name
|
||||
|
||||
|
@ -129,10 +129,12 @@ enum dom_stack_action {
|
||||
DOM_STACK_POP,
|
||||
};
|
||||
|
||||
static void
|
||||
/* Returns whether the node should be freed with done_dom_node(). */
|
||||
static int
|
||||
call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
|
||||
enum dom_stack_action action)
|
||||
{
|
||||
int free_node = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < stack->contexts_size; i++) {
|
||||
@ -148,13 +150,21 @@ call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
|
||||
void *data = get_dom_stack_state_data(context, state);
|
||||
|
||||
stack->current = context;
|
||||
callback(stack, state->node, data);
|
||||
switch (callback(stack, state->node, data)) {
|
||||
case DOM_CODE_FREE_NODE:
|
||||
free_node = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack->current = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return free_node;
|
||||
}
|
||||
|
||||
struct dom_node *
|
||||
enum dom_code
|
||||
push_dom_node(struct dom_stack *stack, struct dom_node *node)
|
||||
{
|
||||
struct dom_stack_state *state;
|
||||
@ -164,13 +174,13 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
|
||||
assert(0 < node->type && node->type < DOM_NODES);
|
||||
|
||||
if (stack->depth > DOM_STACK_MAX_DEPTH) {
|
||||
return NULL;
|
||||
return DOM_CODE_MAX_DEPTH_ERR;
|
||||
}
|
||||
|
||||
state = realloc_dom_stack_states(&stack->states, stack->depth);
|
||||
if (!state) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
}
|
||||
|
||||
state += stack->depth;
|
||||
@ -181,7 +191,7 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
|
||||
if (context->info->object_size
|
||||
&& !realloc_dom_stack_state_objects(context, stack->depth)) {
|
||||
done_dom_node(node);
|
||||
return NULL;
|
||||
return DOM_CODE_ALLOC_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +203,7 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
|
||||
stack->depth++;
|
||||
call_dom_stack_callbacks(stack, state, DOM_STACK_PUSH);
|
||||
|
||||
return node;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -211,9 +221,8 @@ pop_dom_node(struct dom_stack *stack)
|
||||
if (state->immutable)
|
||||
return;
|
||||
|
||||
call_dom_stack_callbacks(stack, state, DOM_STACK_POP);
|
||||
|
||||
if (stack->flags & DOM_STACK_FLAG_FREE_NODES)
|
||||
if (call_dom_stack_callbacks(stack, state, DOM_STACK_POP)
|
||||
|| (stack->flags & DOM_STACK_FLAG_FREE_NODES))
|
||||
done_dom_node(state->node);
|
||||
|
||||
stack->depth--;
|
||||
@ -349,7 +358,8 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
push_dom_node(stack, root);
|
||||
if (push_dom_node(stack, root) != DOM_CODE_OK)
|
||||
return;
|
||||
|
||||
while (!dom_stack_is_empty(stack)) {
|
||||
struct dom_stack_state *state = get_dom_stack_top(stack);
|
||||
@ -410,7 +420,7 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
|
||||
if (is_dom_node_list_member(list, wstate->index)) {
|
||||
struct dom_node *child = list->entries[wstate->index++];
|
||||
|
||||
if (push_dom_node(stack, child))
|
||||
if (push_dom_node(stack, child) == DOM_CODE_OK)
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -488,7 +498,7 @@ static unsigned char indent_string[] =
|
||||
#define get_indent_offset(stack) \
|
||||
((stack)->depth < sizeof(indent_string)/2 ? (stack)->depth * 2 : sizeof(indent_string))
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_stack_trace_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *value = &node->string;
|
||||
@ -499,9 +509,11 @@ dom_stack_trace_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
get_indent_offset(stack), indent_string,
|
||||
name->length, name->string,
|
||||
value->length, value->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_stack_trace_id_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string value;
|
||||
@ -520,11 +532,12 @@ dom_stack_trace_id_leaf(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
id->length, id->string, name->length, name->string,
|
||||
value.length, value.string);
|
||||
|
||||
if (is_dom_string_set(&value))
|
||||
done_dom_string(&value);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_stack_trace_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *name;
|
||||
@ -541,11 +554,12 @@ dom_stack_trace_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
name->length, name->string,
|
||||
value.length, value.string);
|
||||
|
||||
if (is_dom_string_set(&value))
|
||||
done_dom_string(&value);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
enum dom_code
|
||||
dom_stack_trace_branch(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *name;
|
||||
@ -560,6 +574,8 @@ dom_stack_trace_branch(struct dom_stack *stack, struct dom_node *node, void *dat
|
||||
empty_string_or_(stack->current->data),
|
||||
get_indent_offset(stack), indent_string,
|
||||
id->length, id->string, name->length, name->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
struct dom_stack_context_info dom_stack_trace_context_info = {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef EL_DOM_STACK_H
|
||||
#define EL_DOM_STACK_H
|
||||
|
||||
#include "dom/code.h"
|
||||
#include "dom/node.h"
|
||||
#include "util/error.h"
|
||||
#include "util/hash.h"
|
||||
@ -12,7 +13,8 @@ struct dom_stack;
|
||||
/** DOM stack callback
|
||||
*
|
||||
* Used by contexts, for 'hooking' into the node traversing. */
|
||||
typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
|
||||
typedef enum dom_code
|
||||
(*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
|
||||
|
||||
#define DOM_STACK_MAX_DEPTH 4096
|
||||
|
||||
@ -230,7 +232,7 @@ void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *c
|
||||
*
|
||||
* If an error occurs the node is released with ref:[done_dom_node] and NULL is
|
||||
* returned. Else the pushed node is returned. */
|
||||
struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
|
||||
enum dom_code push_dom_node(struct dom_stack *stack, struct dom_node *node);
|
||||
|
||||
/** Pop the top stack state
|
||||
*
|
||||
|
@ -3,13 +3,22 @@
|
||||
|
||||
#include "util/memory.h"
|
||||
|
||||
/* For now DOM has it's own little string library. Mostly because there are
|
||||
* some memory overhead associated with util/string's block-based allocation
|
||||
* scheme which is optimized for building strings and quickly dispose of it.
|
||||
* Also, at some point we need to switch to use mainly UTF-8 strings for DOM
|
||||
* and it needs to be possible to adapt the string library to that. --jonas */
|
||||
|
||||
struct dom_string {
|
||||
size_t length;
|
||||
unsigned char *string;
|
||||
};
|
||||
|
||||
#define INIT_DOM_STRING(strvalue, strlength) \
|
||||
{ (strlength) == -1 ? sizeof(strvalue) - 1 : (strlength), (strvalue) }
|
||||
{ (strlength), (strvalue) }
|
||||
|
||||
#define STATIC_DOM_STRING(strvalue) \
|
||||
{ sizeof(strvalue) - 1, (strvalue) }
|
||||
|
||||
static inline void
|
||||
set_dom_string(struct dom_string *string, unsigned char *value, size_t length)
|
||||
|
3
src/dom/test/.gitignore
vendored
Normal file
3
src/dom/test/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
html-mangle
|
||||
sgml-parser
|
||||
trash
|
@ -1,2 +0,0 @@
|
||||
:set runtimepath+=.
|
||||
:runtime ../../../.vimrc
|
@ -4,6 +4,7 @@ include $(top_builddir)/Makefile.config
|
||||
# Disabled since it requires DOM_STACK_TRACE to be defined
|
||||
# dom-select
|
||||
TEST_PROGS = \
|
||||
html-mangle \
|
||||
sgml-parser
|
||||
|
||||
TESTDEPS = \
|
||||
|
@ -38,9 +38,9 @@ main(int argc, char *argv[])
|
||||
struct sgml_parser *parser;
|
||||
struct dom_select *select;
|
||||
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
|
||||
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
|
||||
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
|
||||
struct dom_string selector = INIT_DOM_STRING("(no select)", -1);
|
||||
struct dom_string uri = STATIC_DOM_STRING("dom://test");
|
||||
struct dom_string source = STATIC_DOM_STRING("(no source)");
|
||||
struct dom_string selector = STATIC_DOM_STRING("(no select)");
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
221
src/dom/test/html-mangle.c
Normal file
221
src/dom/test/html-mangle.c
Normal file
@ -0,0 +1,221 @@
|
||||
/* HTML manglizer
|
||||
* --------------
|
||||
* Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx>
|
||||
*
|
||||
* Based on mangleme-1.2, downloaded on the date below.
|
||||
*
|
||||
* Date: Tue, 31 Jan 2006 10:14:38 +0100 (CET)
|
||||
* From: Michal Zalewski <lcamtuf@dione.ids.pl>
|
||||
* To: Jonas Fonseca <fonseca@diku.dk>
|
||||
* Subject: Re: [mangleme] Question about license and reusability
|
||||
* In-Reply-To: <20060131022616.GB30744@diku.dk>
|
||||
* Message-ID: <Pine.LNX.4.58.0601311013400.24339@dione>
|
||||
*
|
||||
* On Tue, 31 Jan 2006, Jonas Fonseca wrote:
|
||||
* > I would like to reuse your HTML manglizer for stress testing a program I
|
||||
* > am working on (licensed under GPL) but mangleme.tgz (version 1.2)
|
||||
* > doesn't carry any license info as far as I can see. The freshmeat
|
||||
* > project page mentions LGPL, is that authoritative?
|
||||
*
|
||||
* The program is so trivial I have no issues with other people using it
|
||||
* under any licence they choose, to be honest. Consider it to be freeware,
|
||||
* or LGPL if you insist on having some restrictions ;-)
|
||||
*
|
||||
* In other words, go ahead.
|
||||
*
|
||||
* Cheers,
|
||||
* /mz
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define R(x) (rand() % (x))
|
||||
|
||||
#define MAXTCOUNT 100
|
||||
#define MAXPCOUNT 20
|
||||
#define MAXSTR2 80
|
||||
#define MAXTAGS 80
|
||||
#define MAXPARS 20
|
||||
|
||||
/* Tag and parameter list: guesstimating / reference compilation. */
|
||||
static char* tags[MAXTAGS][MAXPARS] = {
|
||||
{ "A", "NAME", "HREF", "REF", "REV", "TITLE", "TARGET", "SHAPE", "onLoad", "STYLE", 0 },
|
||||
{ "APPLET", "CODEBASE", "CODE", "NAME", "ALIGN", "ALT", "HEIGHT", "WIDTH", "HSPACE", "VSPACE", "DOWNLOAD", "HEIGHT", "NAME", "TITLE", "onLoad", "STYLE", 0 },
|
||||
{ "AREA", "SHAPE", "ALT", "CO-ORDS", "HREF", "onLoad", "STYLE", 0 },
|
||||
{ "B", "onLoad", "STYLE", 0 },
|
||||
{ "BANNER", "onLoad", "STYLE", 0 },
|
||||
{ "BASE", "HREF", "TARGET", "onLoad", "STYLE", 0 },
|
||||
{ "BASEFONT", "SIZE", "onLoad", "STYLE", 0 },
|
||||
{ "BGSOUND", "SRC", "LOOP", "onLoad", "STYLE", 0 },
|
||||
{ "BQ", "CLEAR", "NOWRAP", "onLoad", "STYLE", 0 },
|
||||
{ "BODY", "BACKGROUND", "BGCOLOR", "TEXT", "LINK", "ALINK", "VLINK", "LEFTMARGIN", "TOPMARGIN", "BGPROPERTIES", "onLoad", "STYLE", 0 },
|
||||
{ "CAPTION", "ALIGN", "VALIGN", "onLoad", "STYLE", 0 },
|
||||
{ "CENTER", "onLoad", "STYLE", 0 },
|
||||
{ "COL", "ALIGN", "SPAN", "onLoad", "STYLE", 0 },
|
||||
{ "COLGROUP", "ALIGN", "VALIGN", "HALIGN", "WIDTH", "SPAN", "onLoad", "STYLE", 0 },
|
||||
{ "DIV", "ALIGN", "CLASS", "LANG", "onLoad", "STYLE", 0 },
|
||||
{ "EMBED", "SRC", "HEIGHT", "WIDTH", "UNITS", "NAME", "PALETTE", "onLoad", "STYLE", 0 },
|
||||
{ "FIG", "SRC", "ALIGN", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 },
|
||||
{ "FN", "ID", "onLoad", "STYLE", 0 },
|
||||
{ "FONT", "SIZE", "COLOR", "FACE", "onLoad", "STYLE", 0 },
|
||||
{ "FORM", "ACTION", "METHOD", "ENCTYPE", "TARGET", "SCRIPT", "onLoad", "STYLE", 0 },
|
||||
{ "FRAME", "SRC", "NAME", "MARGINWIDTH", "MARGINHEIGHT", "SCROLLING", "FRAMESPACING", "onLoad", "STYLE", 0 },
|
||||
{ "FRAMESET", "ROWS", "COLS", "onLoad", "STYLE", 0 },
|
||||
{ "H1", "SRC", "DINGBAT", "onLoad", "STYLE", 0 },
|
||||
{ "HEAD", "onLoad", "STYLE", 0 },
|
||||
{ "HR", "SRC", "SIZE", "WIDTH", "ALIGN", "COLOR", "onLoad", "STYLE", 0 },
|
||||
{ "HTML", "onLoad", "STYLE", 0 },
|
||||
{ "IFRAME", "ALIGN", "FRAMEBORDER", "HEIGHT", "MARGINHEIGHT", "MARGINWIDTH", "NAME", "SCROLLING", "SRC", "ADDRESS", "WIDTH", "onLoad", "STYLE", 0 },
|
||||
{ "IMG", "ALIGN", "ALT", "SRC", "BORDER", "DYNSRC", "HEIGHT", "HSPACE", "ISMAP", "LOOP", "LOWSRC", "START", "UNITS", "USEMAP", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 },
|
||||
{ "INPUT", "TYPE", "NAME", "VALUE", "onLoad", "STYLE", 0 },
|
||||
{ "ISINDEX", "HREF", "PROMPT", "onLoad", "STYLE", 0 },
|
||||
{ "LI", "SRC", "DINGBAT", "SKIP", "TYPE", "VALUE", "onLoad", "STYLE", 0 },
|
||||
{ "LINK", "REL", "REV", "HREF", "TITLE", "onLoad", "STYLE", 0 },
|
||||
{ "MAP", "NAME", "onLoad", "STYLE", 0 },
|
||||
{ "MARQUEE", "ALIGN", "BEHAVIOR", "BGCOLOR", "DIRECTION", "HEIGHT", "HSPACE", "LOOP", "SCROLLAMOUNT", "SCROLLDELAY", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 },
|
||||
{ "MENU", "onLoad", "STYLE", 0 },
|
||||
{ "META", "HTTP-EQUIV", "CONTENT", "NAME", "onLoad", "STYLE", 0 },
|
||||
{ "MULTICOL", "COLS", "GUTTER", "WIDTH", "onLoad", "STYLE", 0 },
|
||||
{ "NOFRAMES", "onLoad", "STYLE", 0 },
|
||||
{ "NOTE", "CLASS", "SRC", "onLoad", "STYLE", 0 },
|
||||
{ "OVERLAY", "SRC", "X", "Y", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 },
|
||||
{ "PARAM", "NAME", "VALUE", "onLoad", "STYLE", 0 },
|
||||
{ "RANGE", "FROM", "UNTIL", "onLoad", "STYLE", 0 },
|
||||
{ "SCRIPT", "LANGUAGE", "onLoad", "STYLE", 0 },
|
||||
{ "SELECT", "NAME", "SIZE", "MULTIPLE", "WIDTH", "HEIGHT", "UNITS", "onLoad", "STYLE", 0 },
|
||||
{ "OPTION", "VALUE", "SHAPE", "onLoad", "STYLE", 0 },
|
||||
{ "SPACER", "TYPE", "SIZE", "WIDTH", "HEIGHT", "ALIGN", "onLoad", "STYLE", 0 },
|
||||
{ "SPOT", "ID", "onLoad", "STYLE", 0 },
|
||||
{ "TAB", "INDENT", "TO", "ALIGN", "DP", "onLoad", "STYLE", 0 },
|
||||
{ "TABLE", "ALIGN", "WIDTH", "BORDER", "CELLPADDING", "CELLSPACING", "BGCOLOR", "VALIGN", "COLSPEC", "UNITS", "DP", "onLoad", "STYLE", 0 },
|
||||
{ "TBODY", "CLASS", "ID", "onLoad", "STYLE", 0 },
|
||||
{ "TD", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 },
|
||||
{ "TEXTAREA", "NAME", "COLS", "ROWS", "onLoad", "STYLE", 0 },
|
||||
{ "TEXTFLOW", "CLASS", "ID", "onLoad", "STYLE", 0 },
|
||||
{ "TFOOT", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 },
|
||||
{ "TH", "ALIGN", "CLASS", "ID", "onLoad", "STYLE", 0 },
|
||||
{ "TITLE", "onLoad", "STYLE", 0 },
|
||||
{ "TR", "ALIGN", "VALIGN", "BGCOLOR", "CLASS", "onLoad", "STYLE", 0 },
|
||||
{ "UL", "SRC", "DINGBAT", "WRAP", "TYPE", "PLAIN", "onLoad", "STYLE", 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void make_up_value(void)
|
||||
{
|
||||
char c=R(2);
|
||||
|
||||
if (c) putchar('"');
|
||||
|
||||
switch (R(31)) {
|
||||
case 0: printf("javascript:"); make_up_value(); break;
|
||||
#if 0
|
||||
case 1: printf("jar:"); make_up_value(); break;
|
||||
#endif
|
||||
case 2: printf("mk:"); make_up_value(); break;
|
||||
case 3: printf("file:"); make_up_value(); break;
|
||||
case 4: printf("http:"); make_up_value(); break;
|
||||
case 5: printf("about:"); make_up_value(); break;
|
||||
case 6: printf("_blank"); break;
|
||||
case 7: printf("_self"); break;
|
||||
case 8: printf("top"); break;
|
||||
case 9: printf("left"); break;
|
||||
case 10: putchar('&'); make_up_value(); putchar(';'); break;
|
||||
case 11: make_up_value(); make_up_value(); break;
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
{
|
||||
int c = R(10) ? R(10) : (1 + R(MAXSTR2) * R(MAXSTR2));
|
||||
char *x = malloc(c);
|
||||
|
||||
memset(x,R(256),c);
|
||||
fwrite(x,c,1,stdout);
|
||||
free(x);
|
||||
break;
|
||||
}
|
||||
case 21: printf("%s","%n%n%n%n%n%n"); break;
|
||||
case 22: putchar('#'); break;
|
||||
case 23: putchar('*'); break;
|
||||
default:
|
||||
if (R(2)) putchar('-'); printf("%d",rand());
|
||||
break;
|
||||
}
|
||||
|
||||
if (c) putchar('"');
|
||||
}
|
||||
|
||||
void random_tag(void)
|
||||
{
|
||||
int tn, tc;
|
||||
|
||||
do
|
||||
tn = R(MAXTAGS);
|
||||
while (!tags[tn][0]);
|
||||
|
||||
tc = R(MAXPCOUNT) + 1;
|
||||
|
||||
putchar('<');
|
||||
|
||||
switch (R(10)) {
|
||||
case 0: putchar(R(256)); break;
|
||||
case 1: putchar('/');
|
||||
}
|
||||
|
||||
printf("%s", tags[tn][0]);
|
||||
|
||||
while (tc--) {
|
||||
int pn;
|
||||
|
||||
switch (R(32)) {
|
||||
case 0: putchar(R(256));
|
||||
case 1: break;
|
||||
default: putchar(' ');
|
||||
}
|
||||
|
||||
do
|
||||
pn = R(MAXPARS-1) + 1;
|
||||
while (!tags[tn][pn]);
|
||||
|
||||
printf("%s", tags[tn][pn]);
|
||||
|
||||
switch (R(32)) {
|
||||
case 0: putchar(R(256));
|
||||
case 1: break;
|
||||
default: putchar('=');
|
||||
}
|
||||
|
||||
make_up_value();
|
||||
}
|
||||
|
||||
putchar('>');
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int tc, seed;
|
||||
|
||||
printf("<HTML>\n");
|
||||
printf("<HEAD>\n");
|
||||
|
||||
seed = (time(0) ^ (getpid() << 16));
|
||||
#if 0
|
||||
fprintf(stderr,"[%u] Mangle attempt 0x%08x (%s) -- %s\n", (int)time(0), seed, getenv("HTTP_USER_AGENT"), getenv("REMOTE_ADDR"));
|
||||
#endif
|
||||
srand(seed);
|
||||
|
||||
tc = R(MAXTCOUNT) + 1;
|
||||
while (tc--) random_tag();
|
||||
fflush(0);
|
||||
return 0;
|
||||
}
|
@ -11,7 +11,9 @@
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "dom/configuration.h"
|
||||
#include "dom/node.h"
|
||||
#include "dom/sgml/dump.h"
|
||||
#include "dom/sgml/parser.h"
|
||||
#include "dom/stack.h"
|
||||
|
||||
@ -97,7 +99,7 @@ print_indent(struct dom_stack *stack)
|
||||
printf("%.*s", get_indent_offset(stack), indent_string);
|
||||
}
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *value = &node->string;
|
||||
@ -105,15 +107,17 @@ sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data
|
||||
|
||||
/* Always print the URI for identification. */
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
print_indent(stack);
|
||||
printf("%.*s: %.*s\n",
|
||||
name->length, name->string,
|
||||
value->length, value->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *name;
|
||||
@ -122,7 +126,7 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
@ -133,9 +137,11 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
|
||||
name->length, name->string);
|
||||
print_dom_node_value(node);
|
||||
printf("\n");
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *name;
|
||||
@ -143,7 +149,7 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
|
||||
@ -152,9 +158,11 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
|
||||
name->length, name->string);
|
||||
print_dom_node_value(node);
|
||||
printf("\n");
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct dom_string *name;
|
||||
@ -163,7 +171,7 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
assert(node);
|
||||
|
||||
if (update_number_of_lines(stack))
|
||||
return;
|
||||
return DOM_CODE_OK;
|
||||
|
||||
name = get_dom_node_name(node);
|
||||
id = get_dom_node_type_name(node->type);
|
||||
@ -171,9 +179,11 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
|
||||
print_indent(stack);
|
||||
printf("%.*s: %.*s\n",
|
||||
id->length, id->string, name->length, name->string);
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
static enum dom_code
|
||||
sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
{
|
||||
struct sgml_parser *parser = stack->contexts[0]->data;
|
||||
@ -182,6 +192,8 @@ sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||
&& !(parser->flags & SGML_PARSER_DETECT_ERRORS)) {
|
||||
printf("%d\n", number_of_lines);
|
||||
}
|
||||
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
struct dom_stack_context_info sgml_parser_test_context_info = {
|
||||
@ -220,14 +232,14 @@ struct dom_stack_context_info sgml_parser_test_context_info = {
|
||||
}
|
||||
};
|
||||
|
||||
static enum sgml_parser_code
|
||||
static enum dom_code
|
||||
sgml_error_function(struct sgml_parser *parser, struct dom_string *string,
|
||||
unsigned int line_number)
|
||||
{
|
||||
printf("error on line %d: %.*s\n",
|
||||
line_number, string->length, string->string);
|
||||
|
||||
return SGML_PARSER_CODE_OK;
|
||||
return DOM_CODE_OK;
|
||||
}
|
||||
|
||||
void die(const char *msg, ...)
|
||||
@ -250,10 +262,15 @@ main(int argc, char *argv[])
|
||||
struct sgml_parser *parser;
|
||||
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
|
||||
enum sgml_parser_flag flags = 0;
|
||||
enum sgml_parser_code code = 0;
|
||||
enum sgml_parser_type type = SGML_PARSER_STREAM;
|
||||
enum dom_code code = 0;
|
||||
enum dom_config_flag normalize_flags = 0;
|
||||
int normalize = 0;
|
||||
int dump = 0;
|
||||
int complete = 1;
|
||||
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
|
||||
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
|
||||
size_t read_stdin = 0;
|
||||
struct dom_string uri = STATIC_DOM_STRING("dom://test");
|
||||
struct dom_string source = STATIC_DOM_STRING("(no source)");
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
@ -288,6 +305,34 @@ main(int argc, char *argv[])
|
||||
set_dom_string(&source, argv[i], strlen(argv[i]));
|
||||
}
|
||||
|
||||
} else if (!strncmp(arg, "stdin", 5)) {
|
||||
arg += 5;
|
||||
if (*arg == '=') {
|
||||
arg++;
|
||||
read_stdin = atoi(arg);
|
||||
set_dom_string(&source, arg, strlen(arg));
|
||||
} else {
|
||||
i++;
|
||||
if (i >= argc)
|
||||
die("--stdin expects a number");
|
||||
read_stdin = atoi(argv[i]);
|
||||
}
|
||||
flags |= SGML_PARSER_INCREMENTAL;
|
||||
|
||||
} else if (!strncmp(arg, "normalize", 9)) {
|
||||
arg += 9;
|
||||
if (*arg == '=') {
|
||||
arg++;
|
||||
} else {
|
||||
i++;
|
||||
if (i >= argc)
|
||||
die("--normalize expects a string");
|
||||
arg = argv[i];
|
||||
}
|
||||
normalize = 1;
|
||||
normalize_flags = parse_dom_config(arg, ',');
|
||||
type = SGML_PARSER_TREE;
|
||||
|
||||
} else if (!strcmp(arg, "print-lines")) {
|
||||
flags |= SGML_PARSER_COUNT_LINES;
|
||||
|
||||
@ -295,6 +340,10 @@ main(int argc, char *argv[])
|
||||
flags |= SGML_PARSER_INCREMENTAL;
|
||||
complete = 0;
|
||||
|
||||
} else if (!strcmp(arg, "dump")) {
|
||||
type = SGML_PARSER_TREE;
|
||||
dump = 1;
|
||||
|
||||
} else if (!strcmp(arg, "error")) {
|
||||
flags |= SGML_PARSER_DETECT_ERRORS;
|
||||
|
||||
@ -306,27 +355,83 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri, flags);
|
||||
parser = init_sgml_parser(type, doctype, &uri, flags);
|
||||
if (!parser) return 1;
|
||||
|
||||
parser->error_func = sgml_error_function;
|
||||
if (normalize)
|
||||
add_dom_config_normalizer(&parser->stack, normalize_flags);
|
||||
else if (!dump)
|
||||
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
||||
|
||||
if (read_stdin > 0) {
|
||||
unsigned char *buffer;
|
||||
|
||||
buffer = mem_alloc(read_stdin);
|
||||
if (!buffer)
|
||||
die("Cannot allocate buffer");
|
||||
|
||||
complete = 0;
|
||||
|
||||
while (!complete) {
|
||||
size_t size = fread(buffer, 1, read_stdin, stdin);
|
||||
|
||||
if (ferror(stdin))
|
||||
die("error reading from stdin");
|
||||
|
||||
complete = feof(stdin);
|
||||
|
||||
code = parse_sgml(parser, buffer, size, complete);
|
||||
switch (code) {
|
||||
case DOM_CODE_OK:
|
||||
break;
|
||||
|
||||
case DOM_CODE_INCOMPLETE:
|
||||
if (!complete) break;
|
||||
/* Error */
|
||||
default:
|
||||
complete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mem_free(buffer);
|
||||
|
||||
} else {
|
||||
code = parse_sgml(parser, source.string, source.length, complete);
|
||||
}
|
||||
|
||||
if (parser->root) {
|
||||
size_t root_offset = parser->stack.depth - 1;
|
||||
assert(!complete || parser->stack.depth > 0);
|
||||
|
||||
assert(!complete || root_offset == 0);
|
||||
|
||||
get_dom_stack_state(&parser->stack, root_offset)->immutable = 0;
|
||||
|
||||
/* For SGML_PARSER_STREAM this will free the DOM
|
||||
* root node. */
|
||||
while (!dom_stack_is_empty(&parser->stack))
|
||||
while (!dom_stack_is_empty(&parser->stack)) {
|
||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
||||
pop_dom_node(&parser->stack);
|
||||
}
|
||||
|
||||
done_sgml_parser(parser);
|
||||
if (normalize || dump) {
|
||||
struct dom_stack stack;
|
||||
|
||||
return code;
|
||||
/* Note, that we cannot free nodes when walking the DOM
|
||||
* tree since walk_dom_node() uses an index to traverse
|
||||
* the tree. */
|
||||
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||
/* XXX: This context needs to be added first because it
|
||||
* assumes the parser can be accessed via
|
||||
* stack->contexts[0].data. */
|
||||
if (normalize)
|
||||
add_dom_stack_context(&stack, parser, &sgml_parser_test_context_info);
|
||||
else if (dump)
|
||||
add_sgml_file_dumper(&stack, stdout);
|
||||
walk_dom_nodes(&stack, parser->root);
|
||||
done_dom_stack(&stack);
|
||||
done_dom_node(parser->root);
|
||||
}
|
||||
}
|
||||
|
||||
done_sgml_parser(parser);
|
||||
#ifdef DEBUG_MEMLEAK
|
||||
check_memory_leaks();
|
||||
#endif
|
||||
|
||||
return code != DOM_CODE_OK ? 1 : 0;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user