1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-29 03:17:53 -04:00
This commit is contained in:
Kalle Olavi Niemitalo 2006-01-10 21:02:21 +02:00 committed by Kalle Olavi Niemitalo
commit 9deceafa0b
24 changed files with 513 additions and 277 deletions

View File

@ -294,7 +294,7 @@ b.Xi ISOgrk4 0x039E # GREEK CAPITAL LETTER XI
b.alpha ISOgrk4 0x03B1 # GREEK SMALL LETTER ALPHA b.alpha ISOgrk4 0x03B1 # GREEK SMALL LETTER ALPHA
b.beta ISOgrk4 0x03B2 # GREEK SMALL LETTER BETA b.beta ISOgrk4 0x03B2 # GREEK SMALL LETTER BETA
b.chi ISOgrk4 0x03C7 # GREEK SMALL LETTER CHI b.chi ISOgrk4 0x03C7 # GREEK SMALL LETTER CHI
b.delta ? 0x03B3 # GREEK SMALL LETTER GAMMA b.delta ISOgrk4 0x03B4 # GREEK SMALL LETTER DELTA
b.epsi ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON b.epsi ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON
b.epsis ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON b.epsis ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON
b.epsiv ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON b.epsiv ISOgrk4 0x03B5 # GREEK SMALL LETTER EPSILON

View File

@ -49,6 +49,11 @@ ELINKS = $(top_builddir)/src/elinks
KBDBIND = $(top_srcdir)/src/config/kbdbind.c KBDBIND = $(top_srcdir)/src/config/kbdbind.c
FEATURES = $(top_srcdir)/features.conf FEATURES = $(top_srcdir)/features.conf
### Locale env vars to override system one to ensure commands
# using elinks binary will generate texts in english
#
LOCALES = LC_ALL=C LANGUAGE=en
### Scripts ### Scripts
# #
@ -59,7 +64,7 @@ MAKE_ELINKS_MANPAGE = $(top_srcdir)/doc/tools/make-elinks-manpage
MAKE_ELINKSKEYS_MANPAGE = $(top_srcdir)/doc/tools/make-elinkskeys-manpage MAKE_ELINKSKEYS_MANPAGE = $(top_srcdir)/doc/tools/make-elinkskeys-manpage
HTML_DOCS-$(CONFIG_ASCIIDOC) += \ HTML_DOCS-$(CONFIG_ASCIIDOC) += \
api/dom-sgml-parser.html \ api/dom.html \
elinks.1.html \ elinks.1.html \
elinkskeys.5.html \ elinkskeys.5.html \
hacking.html \ hacking.html \
@ -109,10 +114,10 @@ $(TXT_DIR)/import-features.conf.txt: $(FEATURES) $(IMPORT_FEATURES_CONF)
$(IMPORT_FEATURES_CONF) > $@ $(IMPORT_FEATURES_CONF) > $@
$(TXT_DIR)/elinks.1.%.txt: $(MAKE_ELINKS_MANPAGE) $(ELINKS) $(TXT_DIR)/elinks.1.%.txt: $(MAKE_ELINKS_MANPAGE) $(ELINKS)
$(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@ $(LOCALES) $(MAKE_ELINKS_MANPAGE) $@ $(ELINKS) $(HELP2DOC) > $@
$(TXT_DIR)/elinkskeys.5.%.txt: $(MAKE_ELINKSKEYS_MANPAGE) $(KBDBIND) $(TXT_DIR)/elinkskeys.5.%.txt: $(MAKE_ELINKSKEYS_MANPAGE) $(KBDBIND)
$(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@ $(LOCALES) $(MAKE_ELINKSKEYS_MANPAGE) $@ $(KBDBIND) > $@
# Man Pages # Man Pages
@ -122,15 +127,19 @@ $(XML_DIR)/%.man.xml: $(TXT_DIR)/%.man.txt
$(MAN_DIR)/man1/elinks.1.in: $(XML_DIR)/elinks.1.man.xml $(MAN_DIR)/man1/elinks.1.in: $(XML_DIR)/elinks.1.man.xml
$(XMLTO) -o $(MAN_DIR)/man1 man $< $(XMLTO) -o $(MAN_DIR)/man1 man $<
mv $(MAN_DIR)/man1/elinks.1 $@ sed 's/^\.TH "ELINKS" 1 .*/.TH "ELINKS" 1 "The ELinks text-browser" "$(shell date -I)" "The ELinks text-browser"/' \
< $(MAN_DIR)/man1/elinks.1 > $@
rm $(MAN_DIR)/man1/elinks.1
$(MAN_DIR)/man5/elinkskeys.5: $(XML_DIR)/elinkskeys.5.man.xml $(MAN_DIR)/man5/elinkskeys.5: $(XML_DIR)/elinkskeys.5.man.xml
$(XMLTO) -o $(MAN_DIR)/man5 man $< $(XMLTO) -o $(MAN_DIR)/man5 man $<
sed -e 's/\\fI\\fR'\''/\\fI\\'\''\\fR/' < $@ > $@.tmp sed -e 's/\\fI\\fR'\''/\\fI\\'\''\\fR/' < $@ > $@.tmp
mv $@.tmp $@ sed 's/^\.TH "ELINKSKEYS" 5 .*/.TH "ELINKSKEYS" 5 "ELinks keybindings" "$(shell date -I)" "ELinks keybindings"/' \
< $@.tmp > $@
rm $@.tmp
$(MAN_DIR)/man5/elinks.conf.5: $(ELINKS) $(MAN_DIR)/man5/elinks.conf.5: $(ELINKS)
$(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@ $(LOCALES) $(HELP2DOC) --elinks=$(ELINKS) --elinksconf > $@
# XHTML/CSS Man Pages # XHTML/CSS Man Pages
@ -171,7 +180,12 @@ $(HTML_DIR)/perl-hooks.html: $(top_srcdir)/contrib/perl/hooks.pl
## API Docs ## API Docs
# #
$(HTML_DIR)/api/dom-sgml-parser.html: $(top_srcdir)/src/dom/sgml/parser.h DOM_API = \
$(CODE2DOC) $< | $(ASCIIDOC) -f code2doc.conf -b xhtml11 -d book -o $@ -n - $(top_srcdir)/src/dom/scanner.h \
$(top_srcdir)/src/dom/stack.h \
$(top_srcdir)/src/dom/sgml/parser.h
$(HTML_DIR)/api/dom.html: $(DOM_API)
$(CODE2DOC) $(DOM_API) | $(ASCIIDOC) -f code2doc.conf -b xhtml11 -d book -o $@ -n -
include $(top_srcdir)/Makefile.lib include $(top_srcdir)/Makefile.lib

View File

@ -6,16 +6,19 @@ monospacedwords=\basciidoc\(1\)
<a id="{0}" href="#{0}">{0}</a> <a id="{0}" href="#{0}">{0}</a>
[enum-inlinemacro] [enum-inlinemacro]
<a id="{0}" href="#{0}">enum {0}</a> <a id="{target}">enum {target}: {0}</a>
[func-inlinemacro] [func-inlinemacro]
<a id="{0}" href="#{0}">{0}()</a> <a id="{target}">{target}(): {0}</a>
[struct-inlinemacro] [struct-inlinemacro]
<a id="{0}" href="#{0}">struct {0}</a> <a id="{target}">struct {target}: {0}</a>
[callback-inlinemacro] [macro-inlinemacro]
<a id="{0}" href="#{0}">callback {0}</a> <a id="{target}">struct {target}: {0}</a>
[typedef-inlinemacro]
<a id="{target}">typedef {target}: {0}</a>
[ref-inlinemacro] [ref-inlinemacro]
<a href="{target}#{0}">{0}</a> <a href="{target}#{0}">{0}</a>

View File

@ -17,7 +17,7 @@
.el .ne 3 .el .ne 3
.IP "\\$1" \\$2 .IP "\\$1" \\$2
.. ..
.TH "ELINKS" 1 "" "" "" .TH "ELINKS" 1 "The ELinks text-browser" "2006-01-10" "The ELinks text-browser"
.SH NAME .SH NAME
elinks \- lynx-like alternative character mode WWW browser elinks \- lynx-like alternative character mode WWW browser
.SH "SYNOPSIS" .SH "SYNOPSIS"

View File

@ -1,6 +1,6 @@
.\" elinks.conf.5 .\" elinks.conf.5
.\" .\"
.\" Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT. .\" Generated by help2doc (Revision: 1.19) on 2006-01-10 using output from ELinks version 0.12.GIT.
.\" .\"
.\" Copyleft (c) 2002-2004 The ELinks project .\" Copyleft (c) 2002-2004 The ELinks project
.\" .\"
@ -8,7 +8,7 @@
.\" General Public License. <www.gnu.org/licenses/gpl.html> .\" General Public License. <www.gnu.org/licenses/gpl.html>
.\" .\"
.\" Process this file with groff -man -Tascii elinks.conf.5 .\" Process this file with groff -man -Tascii elinks.conf.5
.TH ELINKS.CONF 5 \"03 January 06\" .TH ELINKS.CONF 5 "ELinks configuration file" "2006-01-10" "ELinks configuration file"
.SH NAME .SH NAME
elinks.conf \- ELinks configuration file elinks.conf \- ELinks configuration file
@ -50,7 +50,7 @@ set document.browse.margin_width = 3
# Default document codepage. # Default document codepage.
set document.codepage.assume = "ISO-8859-1" set document.codepage.assume = "ISO-8859-1"
# User defined protocol handlers # User defined protocol handlers
set protocol.user.mailto.unix = "mutt %h -s \"%s\"" set protocol.user.mailto.unix = "mutt %h -s \e\*(lq%s\e\*(rq"
.SH OPTIONS .SH OPTIONS
.SS Bookmarks (bookmarks) .SS Bookmarks (bookmarks)
@ -784,8 +784,6 @@ in dump output.
.TP .TP
\f3document.dump.separator\f2 <str>\f1 (document.dump.separator <str> (default: ") \f3document.dump.separator\f2 <str>\f1 (document.dump.separator <str> (default: ")
.TP .TP
\f3String\f2 Swhich\f1 (String which separates two dumps.)
.TP
\f3document.dump.width\f2 <num>\f1 (default: 80) \f3document.dump.width\f2 <num>\f1 (default: 80)
Width of screen in characters when dumping documents. Width of screen in characters when dumping documents.
.PD .PD
@ -2162,8 +2160,6 @@ Keep the session active even if the last terminal exits.
Automatically save a snapshot of all tabs periodically. Automatically save a snapshot of all tabs periodically.
This will periodically bookmark the tabs of each terminal in a separate folder This will periodically bookmark the tabs of each terminal in a separate folder
for recovery after a crash. for recovery after a crash.
.TP
\f3This\f2 Tfeature\f1 (This feature requires bookmark support.)
.SS Window tabs (ui.tabs) .SS Window tabs (ui.tabs)
Window tabs settings. Window tabs settings.
.TP .TP
@ -2246,7 +2242,7 @@ in an xterm-like terminal. This way the document's title is
shown on the window titlebar. shown on the window titlebar.
.SH "DOCUMENT INFO" .SH "DOCUMENT INFO"
.PP .PP
Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT. Generated by help2doc (Revision: 1.19) on 2006-01-10 using output from ELinks version 0.12.GIT.
help2doc is distributed with ELinks under the terms of the GPL. help2doc is distributed with ELinks under the terms of the GPL.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR elinks (1), .BR elinks (1),

View File

@ -17,7 +17,7 @@
.el .ne 3 .el .ne 3
.IP "\\$1" \\$2 .IP "\\$1" \\$2
.. ..
.TH "ELINKSKEYS" 5 "" "" "" .TH "ELINKSKEYS" 5 "ELinks keybindings" "2006-01-10" "ELinks keybindings"
.SH NAME .SH NAME
elinkskeys \- keybindings for ELinks elinkskeys \- keybindings for ELinks
.SH "SYNOPSIS" .SH "SYNOPSIS"

View File

@ -2,45 +2,111 @@
use strict; use strict;
use warnings; use warnings;
use diagnostics; use diagnostics;
use Getopt::Std;
print "Usage: $0 [FILE]\n\tParses [FILE], outputing the result to stdout.\n" my $HELP = "Usage: $0 [FILE]...
and exit if not @ARGV; Parses [FILE], outputing the result to stdout.";
my ($input) = @ARGV; sub usage {
my ($found, $start, $first, $gotone, $idpath); print "@_\n";
print "Copyleft© 2006, Russ Rowan (See `COPYING')\n" and exit if $input eq '-v'; exit;
open FILEIN, "<$input" or print "File `$input' was not found.\n" and exit; }
$idpath = '';
while (<FILEIN>) our($opt_h, $opt_v, $title, $body, $indent, $idpath, $inblock);
{
if ($found) getopts("hv") or usage($HELP);
{ $opt_v and usage("Copyleft (c) 2006, Russ Rowan (See `COPYING')");
if ($_ =~ /^\s+\*\s$/) { next if $first; $_ =~ s/\s\*// if not $first; } usage($HELP) if $opt_h or @ARGV < 1;
if ($_ =~ /^\s\*+\/$/ or $_ !~ /^\s/) { $found = undef; next; }
$_ =~ s/^(\s*)\s\*\s/$1/; sub put_section {
$found = 'sorta' if $_ =~ s/\s*\*\/$/\n/; $first = undef; if ($title) {
} print "\n$title\n";
elsif ($_ =~ /^\s*\/\*\*\s(.*)/) $_ = $title;
{ s/[^-]/-/g;
$_ = $1; $first = 1; print "$_\n" if not $indent;
print STDOUT "\n\n" if $start; }
if ($_ =~ s/\s*\*\/$//) { $found = 'sorta'; } else { $found = $.; } if ($body) {
if ($_ =~ /struct:[[]([^\]]+)[\]]/) { $idpath = "$1."; } else { $idpath = ''; } $_ = $body;
if ($_ =~ /::/) { $_ = "$_\n\n"; } s/#newline#/$indent/g;
else print "$_\n";
{ }
my $dash; for (my $x = 0; $x < length($_); $x++) { $dash .= '-'; } $title = $body = undef;
$_ = "$_\n$dash\n\n"; }
}
} $idpath = $title = $body = "";
elsif ($_ =~ /^(\s|[^\s=]+)*[\s*]([A-Za-z0-9_]+)(\s+=\s+[^,;]+)?[,;]\s*\/\*::\s*(.*)\s+\*\/$/) while (<>)
{ {
print STDOUT "\n" if $gotone; my $end = s/\s*\*+\//\n/ ? 'yes' : undef;
$_ = "\nid:[$idpath$2]::\n\t$4\n";
$found = 'sorta'; $gotone = $.; if ($end and /[^=]*[\s*](\w+)[\s:,;].*\/\*:\s*(.*)/) {
} # Implicit id for enum values and struct members.
print STDOUT "\n" and $gotone = undef if $gotone and $gotone < $.; print "\nid:[$idpath$1]::\n\t$2\n";
next if not $found; $found = undef if $found eq 'sorta';
print STDOUT $_ and $start = 1; } elsif ($inblock) {
# Redo the indentation, preserve empty lines.
s/^(\s|\*)*//;
s/^$/\n/;
$body .= "#newline#" . $_;
} elsif (s/\s*\/\*\*+\s*(.*)/$1/) {
# Found magic header; flush, record title and set indentation.
put_section;
$title = "$1";
$indent = /::/ ? "\t" : "";
} else {
next if not ($title or $body) or /^\s$/;
my $orig_title = $title;
if (not /^#define\s/) {
while (not /(struct|enum|typedef|[^=])*[\s*](\w+).*[\[:,;{]/) {
$_ .= <>;
}
}
if (/struct\s+(\w+)\s*{/) {
$title = "struct:$1" . "[$title]";
$idpath = "$1.";
} elsif (/enum\s+(\w+)\s*{/) {
$title = "enum:$1" . "[$title]";
$idpath = "";
} elsif (/#define\s+(\w+)[(]/) {
$title = "func:$1" . "[$title]";
$idpath = "";
} elsif (/#define\s+(\w+)/) {
$title = "macro:$1" . "[$title]";
$idpath = "";
} else {
if (/typedef/) {
if (/.*\(\*(\w+)\)\(/) {
$title = "typedef:$1" . "[$title]";
} elsif (/typedef.*\s(\w+);/) {
$title = "typedef:$1" . "[$title]";
}
$idpath = "";
} else {
if (/.*[\s*](\w+)\(/) {
$title = "func:$1" . "[$title]";
$idpath = "";
} elsif (/.*\(\*(\w+)\)\(/) {
$body = "#newline#" . $title if not $body;
$title = "id:[$idpath$1]::";
$indent = "\t";
} elsif (/[^=]*[\s*](\w+)[\[\s,:;]/) {
$body = "#newline#" . $title if not $body;
$title = "id:[$idpath$1]::";
$indent = "\t";
}
}
}
put_section if $orig_title ne $title;
next;
}
$inblock = $end ? undef : 'yes';
} }
close FILEIN;

View File

@ -67,7 +67,7 @@ then
usage "No backend defined" usage "No backend defined"
fi fi
date_string=`date +"%d %B %y"` date_string=`date -I`
script_version=`echo "\\$Revision: 1.19 $" | sed -e 's/\\$\(.*\) \\$/\1/'` script_version=`echo "\\$Revision: 1.19 $" | sed -e 's/\\$\(.*\) \\$/\1/'`
elinks_version="`$elinks -version | head -n 1 | sed -e 's/ELinks \([0-9][^ ]*\).*/\1/'`" elinks_version="`$elinks -version | head -n 1 | sed -e 's/ELinks \([0-9][^ ]*\).*/\1/'`"
script_info="Generated by `basename $0` ($script_version) on $date_string" script_info="Generated by `basename $0` ($script_version) on $date_string"
@ -171,7 +171,7 @@ print_elinksconf_header()
.\" General Public License. <www.gnu.org/licenses/gpl.html> .\" General Public License. <www.gnu.org/licenses/gpl.html>
.\" .\"
.\" Process this file with groff -man -Tascii elinks.conf.5 .\" Process this file with groff -man -Tascii elinks.conf.5
.TH ELINKS.CONF 5 \"$date_string\" .TH ELINKS.CONF 5 "ELinks configuration file" "$date_string" "ELinks configuration file"
.SH NAME .SH NAME
elinks.conf \- ELinks configuration file elinks.conf \- ELinks configuration file
@ -213,7 +213,7 @@ set document.browse.margin_width = 3
# Default document codepage. # Default document codepage.
set document.codepage.assume = "ISO-8859-1" set document.codepage.assume = "ISO-8859-1"
# User defined protocol handlers # User defined protocol handlers
set protocol.user.mailto.unix = "mutt %h -s \"%s\"" set protocol.user.mailto.unix = "mutt %h -s \e\*(lq%s\e\*(rq"
.SH OPTIONS .SH OPTIONS
__END__ __END__

View File

@ -855,6 +855,16 @@ render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
struct dom_string *date = get_rss_text(item, RSS_ELEMENT_PUBDATE); struct dom_string *date = get_rss_text(item, RSS_ELEMENT_PUBDATE);
if (title && is_dom_string_set(title)) { if (title && is_dom_string_set(title)) {
if (item == renderer->channel) {
unsigned char *str;
str = convert_string(renderer->convert_table,
title->string, title->length,
renderer->document->options.cp,
CSM_DEFAULT, NULL, NULL, NULL);
if (str)
renderer->document->title = str;
}
render_dom_text(renderer, &renderer->styles[DOM_NODE_ELEMENT], render_dom_text(renderer, &renderer->styles[DOM_NODE_ELEMENT],
title->string, title->length); title->string, title->length);
} }

View File

@ -114,9 +114,10 @@ struct html_context {
void *(*special_f)(struct html_context *, enum html_special_type, ...); void *(*special_f)(struct html_context *, enum html_special_type, ...);
}; };
#define format (((struct html_element *) html_context->stack.next)->attr) #define html_top ((struct html_element *) html_context->stack.next)
#define par_format (((struct html_element *) html_context->stack.next)->parattr) #define html_bottom ((struct html_element *) html_context->stack.prev)
#define html_top (*(struct html_element *) html_context->stack.next) #define format (html_top->attr)
#define par_format (html_top->parattr)
#define html_is_preformatted() (format.style.attr & AT_PREFORMATTED) #define html_is_preformatted() (format.style.attr & AT_PREFORMATTED)

View File

@ -93,7 +93,7 @@ get_target(struct document_options *options, unsigned char *a)
void void
ln_break(struct html_context *html_context, int n) ln_break(struct html_context *html_context, int n)
{ {
if (!n || html_top.invisible) return; if (!n || html_top->invisible) return;
while (n > html_context->line_breax) { while (n > html_context->line_breax) {
html_context->line_breax++; html_context->line_breax++;
html_context->line_break_f(html_context); html_context->line_break_f(html_context);
@ -108,7 +108,7 @@ put_chrs(struct html_context *html_context, unsigned char *start, int len)
if (html_is_preformatted()) if (html_is_preformatted())
html_context->putsp = HTML_SPACE_NORMAL; html_context->putsp = HTML_SPACE_NORMAL;
if (!len || html_top.invisible) if (!len || html_top->invisible)
return; return;
switch (html_context->putsp) { switch (html_context->putsp) {
@ -258,8 +258,8 @@ html_focusable(struct html_context *html_context, unsigned char *a)
void void
html_skip(struct html_context *html_context, unsigned char *a) html_skip(struct html_context *html_context, unsigned char *a)
{ {
html_top.invisible = 1; html_top->invisible = 1;
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
} }
void void
@ -663,10 +663,7 @@ init_html_parser_state(struct html_context *html_context,
enum html_element_type type, enum html_element_type type,
int align, int margin, int width) int align, int margin, int width)
{ {
struct html_element *element;
html_stack_dup(html_context, type); html_stack_dup(html_context, type);
element = &html_top;
par_format.align = align; par_format.align = align;
@ -677,10 +674,10 @@ init_html_parser_state(struct html_context *html_context,
par_format.list_level = 0; par_format.list_level = 0;
par_format.list_number = 0; par_format.list_number = 0;
par_format.dd_margin = 0; par_format.dd_margin = 0;
html_top.namelen = 0; html_top->namelen = 0;
} }
return element; return html_top;
} }
@ -691,20 +688,20 @@ done_html_parser_state(struct html_context *html_context,
{ {
html_context->line_breax = 1; html_context->line_breax = 1;
while (&html_top != element) { while (html_top != element) {
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
#if 0 #if 0
/* I've preserved this bit to show an example of the Old Code /* I've preserved this bit to show an example of the Old Code
* of the Mikulas days (I _HOPE_ it's by Mikulas, at least ;-). * of the Mikulas days (I _HOPE_ it's by Mikulas, at least ;-).
* I think this assert() can never fail, for one. --pasky */ * I think this assert() can never fail, for one. --pasky */
assertm(&html_top && (void *) &html_top != (void *) &html_stack, assertm(html_top && (void *) html_top != (void *) &html_stack,
"html stack trashed"); "html stack trashed");
if_assert_failed break; if_assert_failed break;
#endif #endif
} }
html_top.type = ELEMENT_KILLABLE; html_top->type = ELEMENT_KILLABLE;
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
} }
@ -777,12 +774,12 @@ init_html_parser(struct uri *uri, struct document_options *options,
par_format.bgcolor = options->default_bg; par_format.bgcolor = options->default_bg;
html_top.invisible = 0; html_top->invisible = 0;
html_top.name = NULL; html_top->name = NULL;
html_top.namelen = 0; html_top->namelen = 0;
html_top.options = NULL; html_top->options = NULL;
html_top.linebreak = 1; html_top->linebreak = 1;
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
html_context->has_link_lines = 0; html_context->has_link_lines = 0;
html_context->table_level = 0; html_context->table_level = 0;

View File

@ -254,7 +254,7 @@ html_input_format(struct html_context *html_context, unsigned char *a,
case FC_HIDDEN: case FC_HIDDEN:
INTERNAL("bad control type"); INTERNAL("bad control type");
} }
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
put_chrs(html_context, " ", 1); put_chrs(html_context, " ", 1);
} }
@ -498,7 +498,7 @@ end_parse:
for (i = 0; i < max_width; i++) for (i = 0; i < max_width; i++)
put_chrs(html_context, "_", 1); put_chrs(html_context, "_", 1);
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
put_chrs(html_context, "]", 1); put_chrs(html_context, "]", 1);
html_context->special_f(html_context, SP_CONTROL, fc); html_context->special_f(html_context, SP_CONTROL, fc);
} }
@ -513,7 +513,7 @@ do_html_select_multiple(struct html_context *html_context, unsigned char *a,
if (!al) return; if (!al) return;
html_focusable(html_context, a); html_focusable(html_context, a);
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
mem_free_set(&format.select, al); mem_free_set(&format.select, al);
format.select_disabled = has_attr(a, "disabled", html_context->options) format.select_disabled = has_attr(a, "disabled", html_context->options)
? FORM_MODE_DISABLED ? FORM_MODE_DISABLED
@ -603,7 +603,7 @@ end_parse:
format.form = fc; format.form = fc;
format.style.attr |= AT_BOLD; format.style.attr |= AT_BOLD;
put_chrs(html_context, "[ ]", 3); put_chrs(html_context, "[ ]", 3);
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
put_chrs(html_context, " ", 1); put_chrs(html_context, " ", 1);
html_context->special_f(html_context, SP_CONTROL, fc); html_context->special_f(html_context, SP_CONTROL, fc);
} }
@ -709,7 +709,7 @@ pp:
ln_break(html_context, 1); ln_break(html_context, 1);
} }
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
if (rows > 1) if (rows > 1)
ln_break(html_context, 1); ln_break(html_context, 1);
else else

View File

@ -141,14 +141,14 @@ html_apply_canvas_bgcolor(struct html_context *html_context)
/* If there are any CSS twaks regarding bgcolor, make sure we will get /* If there are any CSS twaks regarding bgcolor, make sure we will get
* it _and_ prefer it over bgcolor attribute. */ * it _and_ prefer it over bgcolor attribute. */
if (html_context->options->css_enable) if (html_context->options->css_enable)
css_apply(html_context, &html_top, &html_context->css_styles, css_apply(html_context, html_top, &html_context->css_styles,
&html_context->stack); &html_context->stack);
#endif #endif
if (par_format.bgcolor != format.style.bg) { if (par_format.bgcolor != format.style.bg) {
/* Modify the root HTML element - format_html_part() will take /* Modify the root HTML element - format_html_part() will take
* this from there. */ * this from there. */
struct html_element *e = html_context->stack.prev; struct html_element *e = html_bottom;
html_context->was_body_background = 1; html_context->was_body_background = 1;
e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg; e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg;
@ -195,7 +195,7 @@ html_script(struct html_context *html_context, unsigned char *a,
mem_free(type); mem_free(type);
not_processed: not_processed:
/* Permit nested scripts and retreat. */ /* Permit nested scripts and retreat. */
html_top.invisible++; html_top->invisible++;
return; return;
} }
@ -364,7 +364,7 @@ html_html(struct html_context *html_context, unsigned char *a,
/* Modify the root HTML element - format_html_part() will take /* Modify the root HTML element - format_html_part() will take
* this from there. */ * this from there. */
struct html_element *e = html_context->stack.prev; struct html_element *e = html_bottom;
if (par_format.bgcolor != format.style.bg) if (par_format.bgcolor != format.style.bg)
e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg; e->parattr.bgcolor = e->attr.style.bg = par_format.bgcolor = format.style.bg;
@ -403,8 +403,8 @@ void
html_title(struct html_context *html_context, unsigned char *a, html_title(struct html_context *html_context, unsigned char *a,
unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{ {
html_top.invisible = 1; html_top->invisible = 1;
html_top.type = ELEMENT_WEAK; html_top->type = ELEMENT_WEAK;
} }
void void
@ -586,7 +586,7 @@ html_hr(struct html_context *html_context, unsigned char *a,
} }
html_context->special_f(html_context, SP_NOWRAP, 0); html_context->special_f(html_context, SP_NOWRAP, 0);
ln_break(html_context, 2); ln_break(html_context, 2);
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
} }
void void
@ -690,7 +690,7 @@ html_ul(struct html_context *html_context, unsigned char *a,
int_upper_bound(&par_format.leftmargin, par_format.width / 2); int_upper_bound(&par_format.leftmargin, par_format.width / 2);
par_format.align = ALIGN_LEFT; par_format.align = ALIGN_LEFT;
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
} }
void void
@ -725,7 +725,7 @@ html_ol(struct html_context *html_context, unsigned char *a,
int_upper_bound(&par_format.leftmargin, par_format.width / 2); int_upper_bound(&par_format.leftmargin, par_format.width / 2);
par_format.align = ALIGN_LEFT; par_format.align = ALIGN_LEFT;
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
} }
static struct { static struct {
@ -873,10 +873,10 @@ html_dl(struct html_context *html_context, unsigned char *a,
par_format.list_number = 0; par_format.list_number = 0;
par_format.align = ALIGN_LEFT; par_format.align = ALIGN_LEFT;
par_format.dd_margin = par_format.leftmargin; par_format.dd_margin = par_format.leftmargin;
html_top.type = ELEMENT_DONT_KILL; html_top->type = ELEMENT_DONT_KILL;
if (!(par_format.flags & P_COMPACT)) { if (!(par_format.flags & P_COMPACT)) {
ln_break(html_context, 2); ln_break(html_context, 2);
html_top.linebreak = 2; html_top->linebreak = 2;
} }
} }
@ -948,14 +948,14 @@ html_frame(struct html_context *html_context, unsigned char *a,
} }
if (!name) return; if (!name) return;
if (!html_context->options->frames || !html_top.frameset) { if (!html_context->options->frames || !html_top->frameset) {
html_focusable(html_context, a); html_focusable(html_context, a);
put_link_line("Frame: ", name, url, "", html_context); put_link_line("Frame: ", name, url, "", html_context);
} else { } else {
if (html_context->special_f(html_context, SP_USED, NULL)) { if (html_context->special_f(html_context, SP_USED, NULL)) {
html_context->special_f(html_context, SP_FRAME, html_context->special_f(html_context, SP_FRAME,
html_top.frameset, name, url); html_top->frameset, name, url);
} }
} }
@ -997,12 +997,12 @@ html_frameset(struct html_context *html_context, unsigned char *a,
} }
} }
if (!html_top.frameset) { if (!html_top->frameset) {
width = html_context->options->box.width; width = html_context->options->box.width;
height = html_context->options->box.height; height = html_context->options->box.height;
html_context->options->needs_height = 1; html_context->options->needs_height = 1;
} else { } else {
struct frameset_desc *frameset_desc = html_top.frameset; struct frameset_desc *frameset_desc = html_top->frameset;
int offset; int offset;
if (frameset_desc->box.y >= frameset_desc->box.height) if (frameset_desc->box.y >= frameset_desc->box.height)
@ -1020,9 +1020,9 @@ html_frameset(struct html_context *html_context, unsigned char *a,
parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT, parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT,
&fp.height, &fp.y); &fp.height, &fp.y);
fp.parent = html_top.frameset; fp.parent = html_top->frameset;
if (fp.x && fp.y) { if (fp.x && fp.y) {
html_top.frameset = html_context->special_f(html_context, SP_FRAMESET, &fp); html_top->frameset = html_context->special_f(html_context, SP_FRAMESET, &fp);
} }
mem_free_if(fp.width); mem_free_if(fp.width);
mem_free_if(fp.height); mem_free_if(fp.height);

View File

@ -67,20 +67,20 @@ html_a(struct html_context *html_context, unsigned char *a,
#ifdef CONFIG_GLOBHIST #ifdef CONFIG_GLOBHIST
} else if (get_global_history_item(format.link)) { } else if (get_global_history_item(format.link)) {
format.style.fg = format.vlink; format.style.fg = format.vlink;
html_top.pseudo_class &= ~ELEMENT_LINK; html_top->pseudo_class &= ~ELEMENT_LINK;
html_top.pseudo_class |= ELEMENT_VISITED; html_top->pseudo_class |= ELEMENT_VISITED;
#endif #endif
#ifdef CONFIG_BOOKMARKS #ifdef CONFIG_BOOKMARKS
} else if (get_bookmark(format.link)) { } else if (get_bookmark(format.link)) {
format.style.fg = format.bookmark_link; format.style.fg = format.bookmark_link;
html_top.pseudo_class &= ~ELEMENT_VISITED; html_top->pseudo_class &= ~ELEMENT_VISITED;
/* XXX: Really set ELEMENT_LINK? --pasky */ /* XXX: Really set ELEMENT_LINK? --pasky */
html_top.pseudo_class |= ELEMENT_LINK; html_top->pseudo_class |= ELEMENT_LINK;
#endif #endif
} else { } else {
format.style.fg = format.clink; format.style.fg = format.clink;
html_top.pseudo_class &= ~ELEMENT_VISITED; html_top->pseudo_class &= ~ELEMENT_VISITED;
html_top.pseudo_class |= ELEMENT_LINK; html_top->pseudo_class |= ELEMENT_LINK;
} }
mem_free_set(&format.title, mem_free_set(&format.title,
@ -89,7 +89,7 @@ html_a(struct html_context *html_context, unsigned char *a,
html_focusable(html_context, a); html_focusable(html_context, a);
} else { } else {
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
} }
set_fragment_identifier(html_context, a, "name"); set_fragment_identifier(html_context, a, "name");
@ -269,7 +269,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
* If not, just exit now. */ * If not, just exit now. */
if (!options->images && !format.link) { if (!options->images && !format.link) {
mem_free_if(src); mem_free_if(src);
if (usemap) kill_html_stack_item(html_context, &html_top); if (usemap) pop_html_element(html_context);
return; return;
} }
@ -332,7 +332,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
put_image_label(a, label, html_context); put_image_label(a, label, html_context);
if (ismap) kill_html_stack_item(html_context, &html_top); if (ismap) pop_html_element(html_context);
mem_free_set(&format.image, NULL); mem_free_set(&format.image, NULL);
mem_free_set(&format.title, NULL); mem_free_set(&format.title, NULL);
} }
@ -341,7 +341,7 @@ html_img_do(unsigned char *a, unsigned char *object_src,
} }
mem_free_if(src); mem_free_if(src);
if (usemap) kill_html_stack_item(html_context, &html_top); if (usemap) pop_html_element(html_context);
} }
void void
@ -369,7 +369,7 @@ put_link_line(unsigned char *prefix, unsigned char *linkname,
format.style.fg = format.clink; format.style.fg = format.clink;
put_chrs(html_context, linkname, strlen(linkname)); put_chrs(html_context, linkname, strlen(linkname));
ln_break(html_context, 1); ln_break(html_context, 1);
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
} }

View File

@ -714,7 +714,7 @@ next_break:
element: element:
endingtag = *name == '/'; name += endingtag; namelen -= endingtag; endingtag = *name == '/'; name += endingtag; namelen -= endingtag;
if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top.invisible) if (!endingtag && html_context->putsp == HTML_SPACE_ADD && !html_top->invisible)
put_chrs(html_context, " ", 1); put_chrs(html_context, " ", 1);
put_chrs(html_context, base_pos, html - base_pos); put_chrs(html_context, base_pos, html - base_pos);
if (!html_is_preformatted() && !endingtag && html_context->putsp == HTML_SPACE_NORMAL) { if (!html_is_preformatted() && !endingtag && html_context->putsp == HTML_SPACE_NORMAL) {
@ -766,14 +766,14 @@ start_element(struct element_info *ei,
struct css_selector *selector = NULL; struct css_selector *selector = NULL;
#endif #endif
if (html_top.type == ELEMENT_WEAK) { if (html_top->type == ELEMENT_WEAK) {
kill_html_stack_item(html_context, &html_top); pop_html_element(html_context);
} }
/* We try to process nested <script> if we didn't process the parent /* We try to process nested <script> if we didn't process the parent
* one. */ * one. */
if (html_top.invisible if (html_top->invisible
&& (ei->func != html_script || html_top.invisible < 2)) { && (ei->func != html_script || html_top->invisible < 2)) {
ELEMENT_RENDER_PROLOGUE ELEMENT_RENDER_PROLOGUE
return html; return html;
} }
@ -803,11 +803,14 @@ start_element(struct element_info *ei,
if (e->type < ELEMENT_KILLABLE) break; if (e->type < ELEMENT_KILLABLE) break;
if (is_block_element(e) || is_inline_element(ei)) break; if (is_block_element(e) || is_inline_element(ei)) break;
} }
} else foreach (e, html_context->stack) { } else {
if (is_block_element(e) && is_inline_element(ei)) break; foreach (e, html_context->stack) {
if (e->type < ELEMENT_KILLABLE) break; if (is_block_element(e) && is_inline_element(ei)) break;
if (!strlcasecmp(e->name, e->namelen, name, namelen)) break; if (e->type < ELEMENT_KILLABLE) break;
if (!strlcasecmp(e->name, e->namelen, name, namelen)) break;
}
} }
if (!strlcasecmp(e->name, e->namelen, name, namelen)) { if (!strlcasecmp(e->name, e->namelen, name, namelen)) {
while (e->prev != (void *) &html_context->stack) while (e->prev != (void *) &html_context->stack)
kill_html_stack_item(html_context, e->prev); kill_html_stack_item(html_context, e->prev);
@ -819,10 +822,10 @@ start_element(struct element_info *ei,
if (ei->type != ELEMENT_TYPE_NON_PAIRABLE) { if (ei->type != ELEMENT_TYPE_NON_PAIRABLE) {
html_stack_dup(html_context, ELEMENT_KILLABLE); html_stack_dup(html_context, ELEMENT_KILLABLE);
html_top.name = name; html_top->name = name;
html_top.namelen = namelen; html_top->namelen = namelen;
html_top.options = attr; html_top->options = attr;
html_top.linebreak = ei->linebreak; html_top->linebreak = ei->linebreak;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT
if (has_attr(attr, "onClick", html_context->options)) { if (has_attr(attr, "onClick", html_context->options)) {
@ -830,7 +833,7 @@ start_element(struct element_info *ei,
mem_free_set(&format.link, stracpy("javascript:void(0);")); mem_free_set(&format.link, stracpy("javascript:void(0);"));
mem_free_set(&format.target, stracpy(html_context->base_target)); mem_free_set(&format.target, stracpy(html_context->base_target));
format.style.fg = format.clink; format.style.fg = format.clink;
html_top.pseudo_class = ELEMENT_LINK; html_top->pseudo_class = ELEMENT_LINK;
mem_free_set(&format.title, stracpy("onClick placeholder")); mem_free_set(&format.title, stracpy("onClick placeholder"));
/* Er. I know. Well, double html_focusable()s shouldn't /* Er. I know. Well, double html_focusable()s shouldn't
* really hurt. */ * really hurt. */
@ -840,7 +843,7 @@ start_element(struct element_info *ei,
} }
#ifdef CONFIG_CSS #ifdef CONFIG_CSS
if (html_top.options && html_context->options->css_enable) { if (html_top->options && html_context->options->css_enable) {
/* XXX: We should apply CSS otherwise as well, but that'll need /* XXX: We should apply CSS otherwise as well, but that'll need
* some deeper changes in order to have options filled etc. * some deeper changes in order to have options filled etc.
* Probably just applying CSS from more places, since we * Probably just applying CSS from more places, since we
@ -852,12 +855,12 @@ start_element(struct element_info *ei,
/* FIXME: The caching of the CSS selector is broken, since t can /* FIXME: The caching of the CSS selector is broken, since t can
* lead to wrong styles being applied to following elements, so * lead to wrong styles being applied to following elements, so
* disabled for now. */ * disabled for now. */
selector = get_css_selector_for_element(html_context, &html_top, selector = get_css_selector_for_element(html_context, html_top,
&html_context->css_styles, &html_context->css_styles,
&html_context->stack); &html_context->stack);
if (selector) { if (selector) {
apply_css_selector_style(html_context, &html_top, selector); apply_css_selector_style(html_context, html_top, selector);
done_css_selector(selector); done_css_selector(selector);
} }
} }
@ -868,14 +871,14 @@ start_element(struct element_info *ei,
ELEMENT_RENDER_PROLOGUE ELEMENT_RENDER_PROLOGUE
if (ei->func) ei->func(html_context, attr, html, eof, &html); if (ei->func) ei->func(html_context, attr, html, eof, &html);
#ifdef CONFIG_CSS #ifdef CONFIG_CSS
if (selector && html_top.options) { if (selector && html_top->options) {
/* Call it now to override default colors of the elements. */ /* Call it now to override default colors of the elements. */
selector = get_css_selector_for_element(html_context, &html_top, selector = get_css_selector_for_element(html_context, html_top,
&html_context->css_styles, &html_context->css_styles,
&html_context->stack); &html_context->stack);
if (selector) { if (selector) {
apply_css_selector_style(html_context, &html_top, selector); apply_css_selector_style(html_context, html_top, selector);
done_css_selector(selector); done_css_selector(selector);
} }
} }
@ -909,7 +912,7 @@ end_element(struct element_info *ei,
/* Apply background color from the <HTML> element. (bug 696) */ /* Apply background color from the <HTML> element. (bug 696) */
if (ei->func == html_html if (ei->func == html_html
&& html_top.type >= ELEMENT_KILLABLE && html_top->type >= ELEMENT_KILLABLE
&& !html_context->was_body_background) && !html_context->was_body_background)
html_apply_canvas_bgcolor(html_context); html_apply_canvas_bgcolor(html_context);

View File

@ -60,7 +60,7 @@ search_html_stack(struct html_context *html_context, unsigned char *name)
#endif #endif
foreach (element, html_context->stack) { foreach (element, html_context->stack) {
if (element == &html_top) if (element == html_top)
continue; /* skip the top element */ continue; /* skip the top element */
if (strlcasecmp(element->name, element->namelen, name, namelen)) if (strlcasecmp(element->name, element->namelen, name, namelen))
continue; continue;
@ -189,7 +189,7 @@ kill_element(struct html_context *html_context, int ls, struct html_element *e)
void void
kill_html_stack_until(struct html_context *html_context, int ls, ...) kill_html_stack_until(struct html_context *html_context, int ls, ...)
{ {
struct html_element *e = &html_top; struct html_element *e = html_top;
if (ls) e = e->next; if (ls) e = e->next;

View File

@ -14,6 +14,8 @@ void html_stack_dup(struct html_context *html_context,
void kill_html_stack_item(struct html_context *html_context, void kill_html_stack_item(struct html_context *html_context,
struct html_element *e); struct html_element *e);
#define pop_html_element(html_context) \
kill_html_stack_item(html_context, html_top)
void kill_html_stack_until(struct html_context *html_context, int ls, ...); void kill_html_stack_until(struct html_context *html_context, int ls, ...);
/* void dump_html_stack(struct html_context *html_context); */ /* void dump_html_stack(struct html_context *html_context); */

View File

@ -7,30 +7,32 @@
/* Define if you want a talking scanner */ /* Define if you want a talking scanner */
/* #define DEBUG_DOM_SCANNER */ /* #define DEBUG_DOM_SCANNER */
/* The {struct dom_scanner_token} describes one scanner state. There are two /** DOM scanner token
* kinds of tokens: char and non-char tokens. Char tokens contains only one *
* char and simply have their char value as type. They are tokens having * This struct describes one scanner state. There are two kinds of tokens: char
* special control meaning in the code, like ':', ';', '{', '}' and '*'. Non * and non-char tokens. Char tokens contains only one char and simply have
* char tokens has one or more chars and contain stuff like number or * their char value as type. They are tokens having special control meaning in
* indentifier strings. */ * the code, like ':', ';', '{', '}' and '*'. Non-char tokens have one or more
* chars and contain stuff like number or indentifier strings. */
struct dom_scanner_token { struct dom_scanner_token {
/* The type the token */ /** The type the token. */
int type; int type;
/* Some precedence value */ /** Some precedence value. */
int precedence; int precedence;
/* The line number; used for error tokens */ /** The line number; used for error tokens. */
unsigned int lineno; unsigned int lineno;
/* The start of the token string and the token length */ /** The start of the token string and the token length. */
struct dom_string string; struct dom_string string;
}; };
/** Skip the first charector of a token */
#define skip_dom_scanner_token_char(token) \ #define skip_dom_scanner_token_char(token) \
do { (token)->string.string++; (token)->string.length--; } while (0) do { (token)->string.string++; (token)->string.length--; } while (0)
/* Compare the string of @token with the "static" string in @str. */ /** Compare the token string to a "static" string */
#define dom_scanner_token_contains(token, str) \ #define dom_scanner_token_contains(token, str) \
((token)->string.length == (sizeof(str) - 1) \ ((token)->string.length == (sizeof(str) - 1) \
&& !strncasecmp((token)->string.string, str, sizeof(str) - 1)) && !strncasecmp((token)->string.string, str, sizeof(str) - 1))
@ -70,55 +72,72 @@ struct dom_scanner_string_mapping {
struct dom_scanner; struct dom_scanner;
/** DOM scanner info
*
* Backend-specific information used during the actual scanning and
* by the front end to fill the token table on-demand, etc.
*/
struct dom_scanner_info { struct dom_scanner_info {
/* Table containing how to map strings to token types */ /** Table containing how to map strings to token types */
const struct dom_scanner_string_mapping *mappings; const struct dom_scanner_string_mapping *mappings;
/* Information for how to initialize the scanner table */ /** Information for how to initialize the scanner table */
const struct dom_scan_table_info *scan_table_info; const struct dom_scan_table_info *scan_table_info;
/* Fills the scanner with tokens. Already scanned tokens which have not /**
* Fills the scanner with tokens. Already scanned tokens which have not
* been requested remain and are moved to the start of the scanners * been requested remain and are moved to the start of the scanners
* token table. */ * token table. Returns the current token or NULL if there are none. */
/* Returns the current token or NULL if there are none. */
struct dom_scanner_token *(*scan)(struct dom_scanner *scanner); struct dom_scanner_token *(*scan)(struct dom_scanner *scanner);
/* The scanner table */ /**
/* Contains bitmaps for the various characters groups. * The scanner table. Contains bitmaps for the various characters
* Idea sync'ed from mozilla browser. */ * groups. Idea sync'ed from mozilla browser. */
int scan_table[DOM_SCAN_TABLE_SIZE]; int scan_table[DOM_SCAN_TABLE_SIZE];
/* Has the scanner info been initialized? */ /** Has the scanner info been initialized? */
unsigned int initialized:1; unsigned int initialized:1;
}; };
/* Initializes the scanner. */ /** Initializes a DOM scanner
*
* See struct ref:[dom_scanner] for a description of the `int` flags. */
void init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info, void init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
struct dom_string *string, int state, int count_lines, int complete, struct dom_string *string, int state, int count_lines, int complete,
int check_complete, int detect_error); int check_complete, int detect_error);
/* The number of tokens in the scanners token table: /** The number of tokens in the scanners token table
*
* At best it should be big enough to contain properties with space separated * At best it should be big enough to contain properties with space separated
* values and function calls with up to 3 variables like rgb(). At worst it * values and function calls with up to 3 variables like rgb(). At worst it
* should be no less than 2 in order to be able to peek at the next token in * should be no less than 2 in order to be able to peek at the next token in
* the scanner. */ * the scanner. */
#define DOM_SCANNER_TOKENS 10 #define DOM_SCANNER_TOKENS 10
/* The {struct dom_scanner} describes the current state of the scanner. */ /** DOM scanner
*
* Holds the current state of the scanner. */
struct dom_scanner { struct dom_scanner {
/* The very start of the scanned string, the position in the string /** The start of the scanned string. */
* where to scan next and the end of the string. If position is NULL it unsigned char *string;
* means that no more tokens can be retrieved from the string. */ /** The end of the scanned string. */
unsigned char *string, *position, *end; unsigned char *end;
/**
* The position in the string where to scan next and the end of the
* string. If position is NULL it means that no more tokens can be
* retrieved from the string. */
unsigned char *position;
/* The current token and number of scanned tokens in the table. /**
* If the number of scanned tokens is less than DOM_SCANNER_TOKENS it * The current token. If the number of scanned tokens is less than
* is because there are no more tokens in the string. */ * ref:[DOM_SCANNER_TOKENS] it is because there are no more tokens in
* the string. */
struct dom_scanner_token *current; struct dom_scanner_token *current;
/** The number of scanned tokens left in the table. */
int tokens; int tokens;
/* The 'meta' scanner information */ /** The 'meta' scanner information */
struct dom_scanner_info *info; struct dom_scanner_info *info;
#ifdef DEBUG_SCANNER #ifdef DEBUG_SCANNER
@ -130,25 +149,27 @@ struct dom_scanner {
/* The following two flags are used when parsing is incremental and /* The following two flags are used when parsing is incremental and
* the scanner must ensure that only tokens that are complete are * the scanner must ensure that only tokens that are complete are
* generated. */ * generated. */
unsigned int check_complete:1; /* Only generate complete tokens */ unsigned int check_complete:1; /*: Only generate complete tokens */
unsigned int incomplete:1; /* The scanned string is incomplete */ unsigned int incomplete:1; /*: The scanned string is incomplete */
unsigned int detect_errors:1; /* Check for markup errors */ unsigned int detect_errors:1; /*: Check for markup errors */
unsigned int found_error; /* Did we already report this error? */ unsigned int found_error; /*: Did we already report this error? */
unsigned int count_lines:1; /* Is line counting enbaled? */ unsigned int count_lines:1; /*: Is line counting enbaled? */
unsigned int lineno; /* Line # of the last scanned token */ unsigned int lineno; /*: Line # of the last scanned token */
/* Some state indicator only meaningful to the scanner internals */ /** Some state indicator only meaningful to the scanner internals */
int state; int state;
/* The table contain already scanned tokens. It is maintained in /**
* The table contain already scanned tokens. It is maintained in
* order to optimize the scanning a bit and make it possible to look * order to optimize the scanning a bit and make it possible to look
* ahead at the next token. You should always use the accessors * ahead at the next token. You should always use the accessors
* (defined below) for getting tokens from the scanner. */ * (defined below) for getting tokens from the scanner. */
struct dom_scanner_token table[DOM_SCANNER_TOKENS]; struct dom_scanner_token table[DOM_SCANNER_TOKENS];
}; };
/** Check if there are more tokens */
#define dom_scanner_has_tokens(scanner) \ #define dom_scanner_has_tokens(scanner) \
((scanner)->tokens > 0 && (scanner)->current < (scanner)->table + (scanner)->tokens) ((scanner)->tokens > 0 && (scanner)->current < (scanner)->table + (scanner)->tokens)
@ -162,22 +183,24 @@ struct dom_scanner {
/* Scanner table accessors and mutators */ /* Scanner table accessors and mutators */
/* Checks the type of the next token */ /** Check the type of the next token */
#define check_next_dom_scanner_token(scanner, token_type) \ #define check_next_dom_scanner_token(scanner, token_type) \
(scanner_has_tokens(scanner) \ (scanner_has_tokens(scanner) \
&& ((scanner)->current + 1 < (scanner)->table + (scanner)->tokens) \ && ((scanner)->current + 1 < (scanner)->table + (scanner)->tokens) \
&& (scanner)->current[1].type == (token_type)) && (scanner)->current[1].type == (token_type))
/* Access current and next token. Getting the next token might cause /** Get the current token */
* a rescan so any token pointers that has been stored in a local variable
* might not be valid after the call. */
static inline struct dom_scanner_token * static inline struct dom_scanner_token *
get_dom_scanner_token(struct dom_scanner *scanner) get_dom_scanner_token(struct dom_scanner *scanner)
{ {
return dom_scanner_has_tokens(scanner) ? scanner->current : NULL; return dom_scanner_has_tokens(scanner) ? scanner->current : NULL;
} }
/* Do a scanning if we do not have also have access to next token. */ /** Get the next token
*
* Getting the next token might cause a rescan so any token pointers that has
* been stored in a local variable might not be valid after the call. */
/* Do a scanning if we do not also have access to next token. */
static inline struct dom_scanner_token * static inline struct dom_scanner_token *
get_next_dom_scanner_token(struct dom_scanner *scanner) get_next_dom_scanner_token(struct dom_scanner *scanner)
{ {
@ -186,16 +209,20 @@ get_next_dom_scanner_token(struct dom_scanner *scanner)
? scanner->info->scan(scanner) : get_dom_scanner_token(scanner)); ? scanner->info->scan(scanner) : get_dom_scanner_token(scanner));
} }
/* This should just make the code more understandable .. hopefully */ /** Skip the current token */
#define skip_dom_scanner_token(scanner) get_next_dom_scanner_token(scanner) #define skip_dom_scanner_token(scanner) get_next_dom_scanner_token(scanner)
/* Removes tokens from the scanner until it meets a token of the given type. /** Conditionally skip tokens
*
* Removes tokens from the scanner until it meets a token of the given type.
* This token will then also be skipped. */ * This token will then also be skipped. */
struct dom_scanner_token * struct dom_scanner_token *
skip_dom_scanner_tokens(struct dom_scanner *scanner, int skipto, int precedence); skip_dom_scanner_tokens(struct dom_scanner *scanner, int skipto, int precedence);
/* Looks up the string from @ident to @end to in the scanners string mapping /** Map a string to internal ID
* table */ *
* Looks up the string from @ident to @end to in the scanners string mapping
* table. */
int int
map_dom_scanner_string(struct dom_scanner *scanner, map_dom_scanner_string(struct dom_scanner *scanner,
unsigned char *ident, unsigned char *end, int base_type); unsigned char *ident, unsigned char *end, int base_type);

View File

@ -11,12 +11,12 @@ struct sgml_parser;
struct string; struct string;
struct uri; struct uri;
/** enum:[sgml_parser_type]: SGML parser type /** SGML parser type
* *
* There are two kinds of parser types: One that optimises one-time access to * There are two kinds of parser types: One that optimises one-time access to
* the DOM tree and one that creates a persistent DOM tree. */ * the DOM tree and one that creates a persistent DOM tree. */
enum sgml_parser_type { enum sgml_parser_type {
/** id:[SGML_PARSER_STREAM]:: /**
* The first one will simply push nodes on the stack, not building a * The first one will simply push nodes on the stack, not building a
* DOM tree. This interface is similar to that of SAX (Simple API for * DOM tree. This interface is similar to that of SAX (Simple API for
* XML) where events are fired when nodes are entered and exited. It is * XML) where events are fired when nodes are entered and exited. It is
@ -24,7 +24,7 @@ enum sgml_parser_type {
* do all processing in a stream-like manner, such as when highlighting * do all processing in a stream-like manner, such as when highlighting
* HTML code. */ * HTML code. */
SGML_PARSER_STREAM, SGML_PARSER_STREAM,
/** id:[SGML_PARSER_TREE]:: /**
* The second one is a DOM tree builder, that builds a persistent DOM * The second one is a DOM tree builder, that builds a persistent DOM
* tree. When using this type, it is possible to do even more * tree. When using this type, it is possible to do even more
* (pre)processing than for parser streams. For example you can sort * (pre)processing than for parser streams. For example you can sort
@ -33,49 +33,48 @@ enum sgml_parser_type {
SGML_PARSER_TREE, SGML_PARSER_TREE,
}; };
/** enum:[sgml_parser_flag]: SGML parser flags /** SGML parser flags
* *
* These flags control how the parser behaves. * These flags control how the parser behaves.
*/ */
enum sgml_parser_flag { enum sgml_parser_flag {
SGML_PARSER_COUNT_LINES = 1, /*:: Make line numbers available. */ SGML_PARSER_COUNT_LINES = 1, /*: Make line numbers available. */
SGML_PARSER_COMPLETE = 2, /*:: Used internally when incremental. */ SGML_PARSER_COMPLETE = 2, /*: Used internally when incremental. */
SGML_PARSER_INCREMENTAL = 4, /*:: Parse chunks of input. */ SGML_PARSER_INCREMENTAL = 4, /*: Parse chunks of input. */
SGML_PARSER_DETECT_ERRORS = 8, /*:: Report errors. */ SGML_PARSER_DETECT_ERRORS = 8, /*: Report errors. */
}; };
/** struct:[sgml_parser_state]: SGML parser state /** SGML parser state
* *
* The SGML parser has only little state. * The SGML parser has only little state.
*/ */
struct sgml_parser_state { struct sgml_parser_state {
/** id:[sgml_parser_state.info]:: /**
* Info about the properties of the node contained by state. * Info about the properties of the node contained by state.
* This is only meaningful to element and attribute nodes. For * This is only meaningful to element and attribute nodes. For
* unknown nodes it points to the common 'unknown node' info. */ * unknown nodes it points to the common 'unknown node' info. */
struct sgml_node_info *info; struct sgml_node_info *info;
/** id:[sgml_parser_state.end_token]:: /**
* This is used by the DOM source renderer for highlighting the * This is used by the DOM source renderer for highlighting the
* end-tag of an element. */ * end-tag of an element. */
struct dom_scanner_token end_token; struct dom_scanner_token end_token;
}; };
/** enum:[sgml_parser_code]: (Error) codes for the SGML parser /** (Error) codes for the SGML parser
* *
* These enum values are used for return codes. * These enum values are used for return codes.
*/ */
enum sgml_parser_code { enum sgml_parser_code {
SGML_PARSER_CODE_OK, /*:: The parsing was successful */ SGML_PARSER_CODE_OK, /*: The parsing was successful */
SGML_PARSER_CODE_INCOMPLETE, /*:: The parsing could not be completed */ SGML_PARSER_CODE_INCOMPLETE, /*: The parsing could not be completed */
SGML_PARSER_CODE_MEM_ALLOC, /*:: Failed to allocate memory */ SGML_PARSER_CODE_MEM_ALLOC, /*: Failed to allocate memory */
/**
/** id:[SGML_PARSER_CODE_ERROR]::
* FIXME: For when we will add support for requiring stricter parsing * FIXME: For when we will add support for requiring stricter parsing
* or even a validator. */ * or even a validator. */
SGML_PARSER_CODE_ERROR, SGML_PARSER_CODE_ERROR,
}; };
/** callback:[sgml_error_T]: SGML error callback /** SGML error callback
* *
* Called by the SGML parser when a parsing error has occurred. * Called by the SGML parser when a parsing error has occurred.
* *
@ -85,28 +84,29 @@ typedef enum sgml_parser_code
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int); (*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);
/** struct:[sgml_parser]: The SGML parser /** The SGML parser
* *
* This struct hold info used while parsing SGML data. * This struct hold info used while parsing SGML data.
* *
* NOTE: The only variable the user should set is ref:[error_func]. */ * NOTE: The only variable the user should set is ref:[sgml_parser.error_func].
*/
struct sgml_parser { struct sgml_parser {
enum sgml_parser_type type; /*:: Stream or tree */ enum sgml_parser_type type; /*: Stream or tree */
enum sgml_parser_flag flags; /*:: Flags that control the behaviour */ enum sgml_parser_flag flags; /*: Flags that control the behaviour */
struct sgml_info *info; /*:: Backend dependent info */ struct sgml_info *info; /*: Backend dependent info */
struct dom_string uri; /*:: The URI of the DOM document */ struct dom_string uri; /*: The URI of the DOM document */
struct dom_node *root; /*:: The document root node */ struct dom_node *root; /*: The document root node */
sgml_error_T error_func; /*:: Called for detected errors */ sgml_error_T error_func; /*: Called for detected errors */
struct dom_stack stack; /*:: A stack for tracking parsed nodes */ struct dom_stack stack; /*: A stack for tracking parsed nodes */
struct dom_stack parsing; /*:: Used for tracking parsing states */ struct dom_stack parsing; /*: Used for tracking parsing states */
}; };
/** func:[init_sgml_parser]: Initialise an SGML parser /** Initialise an SGML parser
* *
* Initialise an SGML parser with the given properties. * Initialise an SGML parser with the given properties.
* *
@ -121,7 +121,7 @@ struct sgml_parser *
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype, init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
struct dom_string *uri, enum sgml_parser_flag flags); struct dom_string *uri, enum sgml_parser_flag flags);
/** func:[done_sgml_parser]: Release an SGML parser /** Release an SGML parser
* *
* Deallocates all resources, _expect_ the root node. * Deallocates all resources, _expect_ the root node.
* *
@ -129,7 +129,7 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
*/ */
void done_sgml_parser(struct sgml_parser *parser); void done_sgml_parser(struct sgml_parser *parser);
/** func:[parse_sgml]: Parse a chunk of SGML source /** Parse a chunk of SGML source
* *
* Parses the given `buffer`. For incremental rendering the last buffer can be * Parses the given `buffer`. For incremental rendering the last buffer can be
* signals through the `complete` parameter. * signals through the `complete` parameter.
@ -144,12 +144,12 @@ void done_sgml_parser(struct sgml_parser *parser);
enum sgml_parser_code enum sgml_parser_code
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete); parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete);
/** func:[get_sgml_parser_line_number]: Get the line position in the source /** Get the line position in the source
* *
* Returns what line number the parser is currently at or zero if there has * Returns what line number the parser is currently at or zero if there has
* been no parsing yet. * been no parsing yet.
* *
* NOTE: Line numbers are recoderded in the scanner tokens. * NOTE: Line numbers are recorded in the scanner tokens.
*/ */
unsigned int get_sgml_parser_line_number(struct sgml_parser *parser); unsigned int get_sgml_parser_line_number(struct sgml_parser *parser);

View File

@ -7,75 +7,110 @@
struct dom_stack; 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 void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
#define DOM_STACK_MAX_DEPTH 4096 #define DOM_STACK_MAX_DEPTH 4096
/** DOM stack state
*
* This state records what node and where it is placed. */
struct dom_stack_state { struct dom_stack_state {
/** The node assiciated with the state */
struct dom_node *node; struct dom_node *node;
/**
/* The depth of the state in the stack. This is amongst other things * The depth of the state in the stack. This is amongst other things
* used to get the state object data. */ * used to get the state object data. */
unsigned int depth; unsigned int depth;
/** Whether this stack state can be popped with pop_dom_*() family. */
/* Wether this stack state can be popped with pop_dom_*() family. */
unsigned int immutable:1; unsigned int immutable:1;
}; };
/** DOM stack context info
*
* To add a DOM stack context define this struct either statically or on the
* stack. */
struct dom_stack_context_info { struct dom_stack_context_info {
/* The @object_size member tells whether the stack should allocate /**
* objects for each state to be assigned to the state's @data member. * This member tells whether the stack should allocate objects for each
* Zero means no state data should be allocated. */ * state to be assigned to the state's @data member. Zero means no
* state data should be allocated. */
size_t object_size; size_t object_size;
/* Callbacks to be called when pushing and popping nodes. */ /** Callbacks to be called when pushing nodes. */
dom_stack_callback_T push[DOM_NODES]; dom_stack_callback_T push[DOM_NODES];
/** Callbacks to be called when popping nodes. */
dom_stack_callback_T pop[DOM_NODES]; dom_stack_callback_T pop[DOM_NODES];
}; };
/** DOM stack context
*
* This holds 'runtime' data for the stack context. */
struct dom_stack_context { struct dom_stack_context {
/* Data specific to the context. */ /** Data specific to the context. */
void *data; void *data;
/* This is one big array of context specific objects. */ /**
/* For the SGML parser this holds DTD-oriented info about the node * This is one big array of context specific objects. For the SGML
* (recorded in struct sgml_node_info). E.g. whether an element node * parser this holds DTD-oriented info about the node (recorded in
* is optional. */ * struct sgml_node_info). E.g. whether an element node is optional.
*/
unsigned char *state_objects; unsigned char *state_objects;
/* Info about node callbacks and such. */ /** Info about node callbacks and such. */
struct dom_stack_context_info *info; struct dom_stack_context_info *info;
}; };
/** Flags for controlling the DOM stack */
enum dom_stack_flag { enum dom_stack_flag {
/** No flag needed. */
DOM_STACK_FLAG_NONE = 0, DOM_STACK_FLAG_NONE = 0,
/* Free nodes when popping them by calling done_dom_node(). */ /** Free nodes when popping by calling ref:[done_dom_node]. */
DOM_STACK_FLAG_FREE_NODES = 1, DOM_STACK_FLAG_FREE_NODES = 1,
}; };
/* The DOM stack is a convenient way to traverse DOM trees. Also it /** The DOM stack
*
* The DOM stack is a convenient way to traverse DOM trees. Also it
* maintains needed state info and is therefore also a holder of the current * maintains needed state info and is therefore also a holder of the current
* context since the stack is used to when the DOM tree is manipulated. */ * context since the stack is used to when the DOM tree is manipulated. */
struct dom_stack { struct dom_stack {
/* The stack of nodes */ /** The states currently on the stack. */
struct dom_stack_state *states; struct dom_stack_state *states;
/** The depth of the stack. */
size_t depth; size_t depth;
/** Flags given to ref:[init_dom_stack]. */
enum dom_stack_flag flags; enum dom_stack_flag flags;
/* Contexts for the pushed and popped nodes. */ /** Contexts for the pushed and popped nodes. */
struct dom_stack_context **contexts; struct dom_stack_context **contexts;
/** The number of active contexts. */
size_t contexts_size; size_t contexts_size;
/* The current context. */ /**
/* XXX: Only meaningful within dom_stack_callback_T functions. */ * The current context. Only meaningful within
* ref:[dom_stack_callback_T] functions. */
struct dom_stack_context *current; struct dom_stack_context *current;
}; };
/** Check whether stack is empty or not
*
* stack:: The stack to check.
*
* Returns non-zero if stack is empty. */
#define dom_stack_is_empty(stack) \ #define dom_stack_is_empty(stack) \
(!(stack)->states || (stack)->depth == 0) (!(stack)->states || (stack)->depth == 0)
/** Access state by offset from top
*
* stack:: The stack to fetch the state from.
* top_offset:: The offset from the stack top, zero is the top.
*
* Returns the requested state. */
static inline struct dom_stack_state * static inline struct dom_stack_state *
get_dom_stack_state(struct dom_stack *stack, int top_offset) get_dom_stack_state(struct dom_stack *stack, int top_offset)
{ {
@ -84,8 +119,24 @@ get_dom_stack_state(struct dom_stack *stack, int top_offset)
return &stack->states[stack->depth - 1 - top_offset]; return &stack->states[stack->depth - 1 - top_offset];
} }
#define get_dom_stack_top(stack) get_dom_stack_state(stack, 0) /** Access the stack top
*
* stack:: The stack to get the top state from.
*
* Returns the top state. */
#define get_dom_stack_top(stack) \
get_dom_stack_state(stack, 0)
/** Access context specific state data
*
* Similar to ref:[get_dom_stack_state], this will fetch the data
* associated with the state for the given context.
*
* context:: The context to get data from.
* state:: The stack state to get data from.
*
* Returns the state data or NULL if ref:[dom_stack_context_info.object_size]
* was zero. */
static inline void * static inline void *
get_dom_stack_state_data(struct dom_stack_context *context, get_dom_stack_state_data(struct dom_stack_context *context,
struct dom_stack_state *state) struct dom_stack_state *state)
@ -99,25 +150,36 @@ get_dom_stack_state_data(struct dom_stack_context *context,
return (void *) &context->state_objects[state->depth * object_size]; return (void *) &context->state_objects[state->depth * object_size];
} }
/* Define to have debug info about the nodes added printed to the log.
* Run as: ELINKS_LOG=/tmp/dom-dump.txt ./elinks -no-connect <url>
* to have the debug dumped into a file. */
/*#define DOM_STACK_TRACE*/ /*#define DOM_STACK_TRACE*/
#ifdef DOM_STACK_TRACE #ifdef DOM_STACK_TRACE
extern struct dom_stack_context_info dom_stack_trace_context_info; extern struct dom_stack_context_info dom_stack_trace_context_info;
/** Get debug info from the DOM stack
*
* Define `DOM_STACK_TRACE` to have debug info about the nodes added printed to
* the log. It will define add_dom_stack_tracer() to not be a no-op.
*
* Run as:
*
* ELINKS_LOG=/tmp/dom-dump.txt ./elinks -no-connect <url>
*
* to have the debug dumped into a file. */
#define add_dom_stack_tracer(stack, name) \ #define add_dom_stack_tracer(stack, name) \
add_dom_stack_context(stack, name, &dom_stack_trace_context_info) add_dom_stack_context(stack, name, &dom_stack_trace_context_info)
#else #else
#define add_dom_stack_tracer(stack, name) /* Nada */ #define add_dom_stack_tracer(stack, name) /* Nada */
#endif #endif
/* The state iterators do not include the bottom state */ /** The state iterators
*
* To safely iterate through the stack state iterators. */
/** Iterate the stack from bottom to top. */
#define foreach_dom_stack_state(stack, state, pos) \ #define foreach_dom_stack_state(stack, state, pos) \
for ((pos) = 0; (pos) < (stack)->depth; (pos)++) \ for ((pos) = 0; (pos) < (stack)->depth; (pos)++) \
if (((state) = &(stack)->states[(pos)])) if (((state) = &(stack)->states[(pos)]))
/** Iterate the stack from top to bottom. */
#define foreachback_dom_stack_state(stack, state, pos) \ #define foreachback_dom_stack_state(stack, state, pos) \
for ((pos) = (stack)->depth - 1; (pos) >= 0; (pos)--) \ for ((pos) = (stack)->depth - 1; (pos) >= 0; (pos)--) \
if (((state) = &(stack)->states[(pos)])) if (((state) = &(stack)->states[(pos)]))
@ -125,41 +187,96 @@ extern struct dom_stack_context_info dom_stack_trace_context_info;
/* Life cycle functions. */ /* Life cycle functions. */
/** Initialise a DOM stack
* stack:: Pointer to a (preallocated) stack.
* flags:: Any flags needed for controlling the behaviour of the stack.
*/
void init_dom_stack(struct dom_stack *stack, enum dom_stack_flag flags); void init_dom_stack(struct dom_stack *stack, enum dom_stack_flag flags);
/** Release a DOM stack
*
* Free all resources collected by the stack.
*
* stack:: The stack to release. */
void done_dom_stack(struct dom_stack *stack); void done_dom_stack(struct dom_stack *stack);
/* Add a context to the stack. This is needed if either you want to have the /** Add a context to the stack
* stack allocated objects for created states and/or if you want to install *
* callbacks for pushing or popping. . */ * This is needed if either you want to have the stack allocated objects for
* created states and/or if you want to install callbacks for pushing or
* popping.
*
* stack:: The stack where the context should be created.
* data:: Private data to be stored in ref:[dom_stack_context.data].
* context_info:: Information about state objects and node callbacks.
*
* Returns a pointer to the newly created context or NULL. */
struct dom_stack_context * struct dom_stack_context *
add_dom_stack_context(struct dom_stack *stack, void *data, add_dom_stack_context(struct dom_stack *stack, void *data,
struct dom_stack_context_info *context_info); struct dom_stack_context_info *context_info);
/* Unregister a stack @context. This should be done especially for temporary /** Unregister a stack context
* stack contexts (without any callbacks) so that they do not increasing the * This should be done especially for temporary stack contexts (without any
* memory usage. */ * callbacks) so that they do not increasing the memory usage. */
void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *context); void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *context);
/* Decends down to the given node making it the current parent */ /** Push a node onto the stack
/* If an error occurs the node is free()d and NULL is returned */ *
* Makes the pushed node the new top of the stack.
*
* stack:: The stack to push onto.
* node:: The node to push onto the stack.
*
* 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); struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
/* Ascends the stack to the current parent */ /** Pop the top stack state
*
* stack:: The stack to pop from. */
void pop_dom_node(struct dom_stack *stack); void pop_dom_node(struct dom_stack *stack);
/* Ascends the stack looking for specific parent */ /** Conditionally pop the stack states
*
* Searches the stack (using ref:[search_dom_stack]) for a specific node and
* pops all states until that particular state is met.
*
* NOTE: The popping is stopped if an immutable state is encountered. */
void pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type, void pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type,
struct dom_string *string); struct dom_string *string);
/* Pop all stack states until a specific state is reached. */ /** Pop all states until target state
*
* Pop all stack states until a specific state is reached. The target state
* is also popped.
*
* stack:: The stack to pop from.
* target:: The state to pop until and including. */
void pop_dom_state(struct dom_stack *stack, struct dom_stack_state *target); void pop_dom_state(struct dom_stack *stack, struct dom_stack_state *target);
/* Dive through the stack states in search for the specified match. */ /** Search the stack states
*
* The string comparison is done against the ref:[dom_node.string] member of
* the of the state nodes.
*
* stack:: The stack to search in.
* type:: The type of node to match against.
* string:: The string to match against.
*
* Returns a state that matched the type and string or NULL. */
struct dom_stack_state * struct dom_stack_state *
search_dom_stack(struct dom_stack *stack, enum dom_node_type type, search_dom_stack(struct dom_stack *stack, enum dom_node_type type,
struct dom_string *string); struct dom_string *string);
/* Visit each node in the tree rooted at @root pre-order */ /** Walk all nodes reachable from a given node
*
* Visits each node in the DOM tree rooted at a given node, pre-order style.
*
* stack:: The stack to use for walking the nodes.
* root:: The root node to start from.
*
* It is assummed that the given stack has been initialised with
* ref:[init_dom_stack] and that the caller already added one or more
* context to the stack. */
void walk_dom_nodes(struct dom_stack *stack, struct dom_node *root); void walk_dom_nodes(struct dom_stack *stack, struct dom_node *root);
#endif #endif

View File

@ -259,7 +259,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
{ "b.alpha", 0x03B1 }, /* GREEK SMALL LETTER ALPHA */ { "b.alpha", 0x03B1 }, /* GREEK SMALL LETTER ALPHA */
{ "b.beta", 0x03B2 }, /* GREEK SMALL LETTER BETA */ { "b.beta", 0x03B2 }, /* GREEK SMALL LETTER BETA */
{ "b.chi", 0x03C7 }, /* GREEK SMALL LETTER CHI */ { "b.chi", 0x03C7 }, /* GREEK SMALL LETTER CHI */
{ "b.delta", 0x03B3 }, /* GREEK SMALL LETTER GAMMA */ { "b.delta", 0x03B4 }, /* GREEK SMALL LETTER DELTA */
{ "b.epsi", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */ { "b.epsi", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
{ "b.epsis", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */ { "b.epsis", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
{ "b.epsiv", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */ { "b.epsiv", 0x03B5 }, /* GREEK SMALL LETTER EPSILON */
@ -1005,4 +1005,4 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
{ NULL, 0 } { NULL, 0 }
}; };
#define N_ENTITIES 1001 #define N_ENTITIES 1001

View File

@ -110,7 +110,8 @@ init_response_digest(md5_digest_hex_T response, struct auth_entry *entry,
MD5_Init(&MD5Ctx); MD5_Init(&MD5Ctx);
MD5_Update(&MD5Ctx, ha1, sizeof(ha1)); MD5_Update(&MD5Ctx, ha1, sizeof(ha1));
MD5_Update(&MD5Ctx, ":", 1); MD5_Update(&MD5Ctx, ":", 1);
MD5_Update(&MD5Ctx, entry->nonce, strlen(entry->nonce)); if (entry->nonce)
MD5_Update(&MD5Ctx, entry->nonce, strlen(entry->nonce));
MD5_Update(&MD5Ctx, ":", 1); MD5_Update(&MD5Ctx, ":", 1);
MD5_Update(&MD5Ctx, "00000001", 8); MD5_Update(&MD5Ctx, "00000001", 8);
MD5_Update(&MD5Ctx, ":", 1); MD5_Update(&MD5Ctx, ":", 1);
@ -142,10 +143,12 @@ get_http_auth_digest_response(struct auth_entry *entry, struct uri *uri)
add_to_string(&string, entry->user); add_to_string(&string, entry->user);
add_to_string(&string, "\", "); add_to_string(&string, "\", ");
add_to_string(&string, "realm=\""); add_to_string(&string, "realm=\"");
add_to_string(&string, entry->realm); if (entry->realm)
add_to_string(&string, entry->realm);
add_to_string(&string, "\", "); add_to_string(&string, "\", ");
add_to_string(&string, "nonce=\""); add_to_string(&string, "nonce=\"");
add_to_string(&string, entry->nonce); if (entry->nonce)
add_to_string(&string, entry->nonce);
add_to_string(&string, "\", "); add_to_string(&string, "\", ");
add_to_string(&string, "uri=\"/"); add_to_string(&string, "uri=\"/");
add_bytes_to_string(&string, uri->data, uri->datalen); add_bytes_to_string(&string, uri->data, uri->datalen);

View File

@ -140,7 +140,7 @@ get_gopher_entity_info(enum gopher_entity type)
{ {
int entry; int entry;
for (entry = 0; entry < sizeof(gopher_entity_info) - 1; entry++) for (entry = 0; entry < sizeof_array(gopher_entity_info) - 1; entry++)
if (gopher_entity_info[entry].type == type) if (gopher_entity_info[entry].type == type)
return &gopher_entity_info[entry]; return &gopher_entity_info[entry];
@ -282,7 +282,7 @@ init_gopher_connection_info(struct connection *conn)
/* Get entity type, and selector string. */ /* Get entity type, and selector string. */
/* Pick up gopher_entity */ /* Pick up gopher_entity */
if (selectorlen > 0) { if (selectorlen > 1 && selector[1] == '/') {
entity = *selector++; entity = *selector++;
selectorlen--; selectorlen--;
} }
@ -296,7 +296,7 @@ init_gopher_connection_info(struct connection *conn)
* _after_ the Gopher entity. If the <entity-char> '/' combo is not * _after_ the Gopher entity. If the <entity-char> '/' combo is not
* found assume that the whole URI data part is the selector. */ * found assume that the whole URI data part is the selector. */
entity_info = get_gopher_entity_info(entity); entity_info = get_gopher_entity_info(entity);
if (entity_info->type == GOPHER_UNKNOWN) { if (entity_info->type == GOPHER_UNKNOWN && entity != GOPHER_UNKNOWN) {
selector--; selector--;
selectorlen++; selectorlen++;
} }
@ -518,7 +518,8 @@ add_gopher_menu_line(struct string *buffer, unsigned char *line)
default: default:
{ {
struct string address; struct string address;
unsigned char *format = *selector ? "%s://%s@%s/" : "%s://%s%s/"; unsigned char *format = selector && *selector
? "%s://%s@%s/" : "%s://%s%s/";
/* If port is defined it means that both @selector and @host /* If port is defined it means that both @selector and @host
* was correctly parsed. */ * was correctly parsed. */

View File

@ -10,10 +10,6 @@
* Ie. MIN(a+b, c+d) will do 3 additions... * Ie. MIN(a+b, c+d) will do 3 additions...
* Please prefer to use int_min() and int_max() if possible. */ * Please prefer to use int_min() and int_max() if possible. */
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h> /* MIN/MAX may be defined in this header. */
#endif
/* FreeBSD needs this. */ /* FreeBSD needs this. */
#ifdef MIN #ifdef MIN
#undef MIN #undef MIN