summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:21:21 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:21:21 +0000
commit510ed32cfbffa6148018869f5ade416505a450b3 (patch)
tree0aafabcf3dfaab7685fa0fcbaa683dafe287807e /scripts
parentInitial commit. (diff)
downloadlynx-510ed32cfbffa6148018869f5ade416505a450b3.tar.xz
lynx-510ed32cfbffa6148018869f5ade416505a450b3.zip
Adding upstream version 2.9.0rel.0.upstream/2.9.0rel.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/cfg2html.pl620
-rwxr-xr-xscripts/cfg_defs.sh51
-rwxr-xr-xscripts/cfg_edit.sh17
-rwxr-xr-xscripts/cfg_path.sh5
-rwxr-xr-xscripts/collapse-br162
-rwxr-xr-xscripts/conf.mingw.sh38
-rwxr-xr-xscripts/config.djgpp.sh24
-rwxr-xr-xscripts/fixtext.sh11
-rwxr-xr-xscripts/indent.sh153
-rwxr-xr-xscripts/install-cfg.sh89
-rwxr-xr-xscripts/install-lss.sh38
-rwxr-xr-xscripts/man2hlp.sh22
-rwxr-xr-xscripts/relpath.sh43
-rwxr-xr-xscripts/tbl2html.pl364
14 files changed, 1637 insertions, 0 deletions
diff --git a/scripts/cfg2html.pl b/scripts/cfg2html.pl
new file mode 100755
index 0000000..44ad36e
--- /dev/null
+++ b/scripts/cfg2html.pl
@@ -0,0 +1,620 @@
+#!/usr/bin/perl -w
+# $LynxId: cfg2html.pl,v 1.21 2014/01/08 22:49:46 tom Exp $
+#
+# This script uses embedded formatting directives in the lynx.cfg file to
+# guide it in extracting comments and related information to construct a
+# set of HTML files. Comments begin with '#', and directives with '.'.
+# Directives implemented:
+#
+# h1 {Text}
+# major heading. You may specify the same major heading in
+# more than one place.
+# h2 {Text}
+# minor heading, i.e. a keyword.
+# ex [number]
+# the following line(s) are an example. The [number] defaults
+# to 1.
+# nf [number]
+# turn justification off for the given number of lines, defaulting
+# to the remainder of the file.
+# fi
+# turn justification back on
+# url text
+# embed an HREF to external site.
+#
+use strict;
+
+use Getopt::Std;
+
+use vars qw($opt_a $opt_m $opt_s);
+
+use vars qw(@cats);
+use vars qw(%cats);
+
+use vars qw(@settings_avail);
+use vars qw(%settings_avail);
+
+# Options:
+# -a show all options, not only those that are available.
+# -m mark unavailable options with an '*'. Data for this is read
+# from standard input.
+# -s sort entries in body.html
+&getopts('ams');
+
+if ( defined $opt_m ) {
+ my $l;
+ my @settings_ = <STDIN>;
+ %settings_avail = ();
+ foreach $l (@settings_) {
+ chop $l;
+ if ( $l =~ /^[[:alpha:]_][[:alnum:]_]*$/ ) {
+ $settings_avail{ uc $l } = 1;
+ }
+ }
+}
+else {
+ $opt_a = 1;
+}
+
+# This sub tells whether the support for the given setting was enabled at
+# compile time.
+sub ok {
+ my ($name) = @_;
+ my $ret = defined( $settings_avail{ uc $name } ) + 0;
+ $ret;
+}
+
+if ( $#ARGV < 0 ) {
+ &doit("lynx.cfg");
+}
+else {
+ while ( $#ARGV >= 0 ) {
+ &doit( shift @ARGV );
+ }
+}
+exit(0);
+
+# process a Lynx configuration-file
+sub doit {
+ my ($name) = @_;
+ my $n;
+
+ # Ignore our own backup files
+ if ( $name =~ ".*~" ) {
+ return;
+ }
+
+ # Read the file into an array in memory.
+ open( FP, $name ) || do {
+ print STDERR "Can't open $name: $!\n";
+ return;
+ };
+ my (@input) = <FP>;
+ close(FP);
+
+ for $n ( 0 .. $#input ) {
+ chop $input[$n]; # trim newlines
+ $input[$n] =~ s/\s*$//; # trim trailing blanks
+ $input[$n] =~ s/^\s*//; # trim leading blanks
+ }
+
+ &gen_alphatoc(@input);
+ @cats = &gen_cattoc(@input);
+ &gen_body(@input);
+}
+
+sub gen_alphatoc {
+ my (@input) = @_;
+ my @minor;
+ my ( $n, $m, $c, $d, $need_p );
+ my $output = "alphatoc.html";
+ open( FP, ">$output" ) || do {
+ print STDERR "Can't open $output: $!\n";
+ return;
+ };
+ print FP <<'EOF';
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rev="made" href="mailto:lynx-dev@nongnu.org">
+<title>lynx.cfg settings by name</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content=
+"This is a table of Lynx's settings in lynx.cfg, listed alphabetically. Some settings are disabled at compile-time.">
+</head>
+<body>
+EOF
+ $m = 0;
+ for $n ( 0 .. $#input ) {
+ if ( $input[$n] =~ /^\.h2\s*[[:upper:]][[:upper:][:digit:]_]*$/ ) {
+ $minor[$m] = $input[$n];
+ $minor[$m] =~ s/^.h2\s*//;
+ $m++ if ( ok( $minor[$m] ) || defined $opt_a );
+ }
+ }
+ @minor = sort @minor;
+
+ # index by the first character of each keyword
+ $c = ' ';
+ $need_p = 1;
+ for $n ( 0 .. $#minor ) {
+ $d = substr( $minor[$n], 0, 1 );
+ if ( $d ne $c ) {
+ if ($need_p) {
+ printf FP "<p>";
+ $need_p = 0;
+ }
+ printf FP "<a href=\"#%s\">%s</a> \n", $d, $d;
+ $c = $d;
+ }
+ }
+
+ # index by the first character of each keyword
+ $c = ' ';
+ for $n ( 0 .. $#minor ) {
+ $d = substr( $minor[$n], 0, 1 );
+ if ( $d ne $c ) {
+ printf FP "<h2><a name=%s>%s</a></h2>\n", $d, $d;
+ $need_p = 1;
+ $c = $d;
+ }
+ my $avail = ok( $minor[$n] );
+ my $mark = ( !$avail && defined $opt_m ) ? "*" : "";
+ if ( defined $opt_a || $avail ) {
+ if ($need_p) {
+ printf FP "<p>";
+ $need_p = 0;
+ }
+ printf FP "<a href=\"body.html#%s\">%s</a>&nbsp;&nbsp;\n",
+ $minor[$n], $minor[$n] . $mark;
+ }
+ }
+ my $str = <<'EOF'
+<p>
+<a href=cattoc.html>To list of settings by category</a>
+EOF
+ . (
+ defined $opt_a && defined $opt_m
+ ? "<p>Support for all settings suffixed with '*' was disabled at compile time.\n"
+ : ""
+ )
+ . <<'EOF'
+</body>
+</html>
+EOF
+ ;
+ print FP $str;
+ close(FP);
+}
+
+# This uses the associative array $cats{} to store HREF values pointing into
+# the cattoc file.
+#
+# We could generate this file in alphabetic order as well, but choose to use
+# the order of entries in lynx.cfg, since some people expect that arrangement.
+sub gen_body {
+ my @input = @_;
+ my ( $n, $c );
+ my @h2;
+ my $output = "body.html";
+ open( FP, ">$output" ) || do {
+ print STDERR "Can't open $output: $!\n";
+ return;
+ };
+ print FP <<'EOF';
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rev="made" href="mailto:lynx-dev@nongnu.org">
+<title>Description of settings in lynx configuration file</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content=
+"This is a list of each of Lynx's settings in lynx.cfg, with full description and their default values indicated.">
+</head>
+<body>
+EOF
+ my $l;
+ my $t;
+ my $d = -1;
+ my $p = 0;
+ my $m = 0;
+ my $h1 = "";
+ my $sp = ' ';
+ my $ex = 0;
+ my $nf = 0;
+ my $any = 0;
+ my $first = 0;
+ my $next = 0;
+ my $left = 0;
+ my $needp = 0;
+ my %keys;
+ undef %keys;
+
+ my @optnames;
+ my %optname_to_fname; #this maps optname to fname - will be used
+ #for alphabetical output of the content
+ my $curfilename = "tmp000"; #will be incremented each time
+ my $tmpdir = "./"; #temp files will be created there
+ close(FP);
+
+ for $n ( 0 .. $#input ) {
+ if ($next) {
+ $next--;
+ next;
+ }
+ $c = $input[$n];
+ my $count = $#input;
+ my $once = 1;
+ if ( $c =~ /^\.h1\s/ ) {
+ $h1 = 1;
+ $h1 = $c;
+ $h1 =~ s/^.h1\s*//;
+ $m = 0;
+ $first = 1;
+ undef %keys;
+ next;
+ }
+ elsif ( $c =~ /^\.h2\s/ ) {
+ $c =~ s/^.h2\s*//;
+ $h2[$m] = $c;
+ $keys{$c} = 1;
+ $m++;
+ next;
+ }
+ elsif ( $c =~ /^\./ ) {
+ my $s = $c;
+ $s =~ s/^\.[[:lower:]]+\s//;
+ if ( $s =~ /^[[:digit:]]+$/ ) {
+ $count = $s;
+ $once = $s;
+ }
+ }
+ if ( $c =~ /^\.ex/ ) {
+ $ex = $once;
+ printf FP "<h3><em>Example%s:</em></h3>\n", $ex > 1 ? "s" : "";
+ $needp = 1;
+ }
+ elsif ( $c =~ /^\.url/ ) {
+ my $url = $c;
+ $url =~ s/^\.url\s+//;
+ printf FP "<blockquote><p><a href=\"%s\">%s</a></p></blockquote>\n",
+ $url, $url;
+ $needp = 1;
+ }
+ elsif ( $c =~ /^\.nf/ ) {
+ $needp = 0;
+ printf FP "<pre>\n";
+ $nf = $count;
+ }
+ elsif ( $c =~ /^\.fi/ ) {
+ printf FP "</pre>\n";
+ $nf = 0;
+ $needp = 1;
+ }
+ elsif ( $c =~ /^$/ ) {
+ if ( $m > 1 ) {
+ my $j;
+ for $j ( 1 .. $#h2 ) {
+ close(FP);
+ ++$curfilename;
+ push @optnames, $h2[$j];
+ open( FP, ">$tmpdir/$curfilename" ) || do {
+ print STDERR "Can't open tmpfile: $!\n";
+ return;
+ };
+ $optname_to_fname{ $h2[$j] } = $curfilename;
+
+ printf FP "<hr>\n";
+ printf FP "<h2><kbd><a name=\"%s\">%s</a></kbd>\n", $h2[$j],
+ $h2[$j];
+ if ( $h1 ne "" ) {
+ printf FP " &ndash; <a href=\"cattoc.html#%s\">%s</a>",
+ $cats{$h1}, $h1;
+ }
+ printf FP "</h2>\n";
+ printf FP "<h3><em>Description</em></h3>\n";
+ printf FP "<p>Please see the description of "
+ . "<a href=\"#%s\">%s</a>\n",
+ $h2[0], $h2[0];
+ $needp = 0;
+ }
+ @h2 = "";
+ }
+ $m = 0;
+ $first = 1;
+ }
+ elsif ( $c =~ /^[#[:alpha:]]/ && $m != 0 ) {
+ if ($first) {
+ close(FP);
+ ++$curfilename;
+ push @optnames, $h2[0];
+ open( FP, ">$tmpdir/$curfilename" ) || do {
+ print STDERR "Can't open tmpfile: $!\n";
+ return;
+ };
+ $optname_to_fname{ $h2[0] } = $curfilename;
+
+ if ($any) {
+ printf FP "<hr>\n";
+ }
+ printf FP "<h2><kbd><a name=\"%s\">%s</a></kbd>\n", $h2[0],
+ $h2[0];
+ if ( $h1 ne "" ) {
+ printf FP " &ndash; <a href=\"cattoc.html#%s\">%s</a>",
+ $cats{$h1}, $h1;
+ }
+ printf FP "</h2>\n";
+ printf FP "<h3><em>Description</em></h3>\n";
+ $needp = 1;
+ $any++;
+ $first = 0;
+ }
+
+ # Convert tabs first, to retain relative alignment
+ $c =~ s#^\t#' 'x8#e;
+ while ( $c =~ /\t/ ) {
+ $c =~ s#(^[^\t]+)\t#$1 . $sp x (9 - (length($1) % 8 ))#e;
+ }
+
+ # Strip off the comment marker
+ $c =~ s/^#//;
+
+ # and convert simple expressions:
+ $c =~ s/&/&amp;/g;
+ $c =~ s/>/&gt;/g;
+ $c =~ s/</&lt;/g;
+
+ #hvv - something wrong was with next statement
+ $c =~ s/'([^ ])'/"<strong>$1<\/strong>"/g;
+
+ my $k = 0;
+ if ( $c =~ /^[[:alpha:]_][[:alnum:]_]+:/ ) {
+ $t = $c;
+ $t =~ s/:.*//;
+ $k = $keys{$t};
+ }
+
+ if ( $c =~ /^$/ ) {
+ if ($nf) {
+ printf FP "\n";
+ }
+ else {
+ $p = 1;
+ }
+ }
+ elsif ( $ex != 0 ) {
+ printf FP "%s", $needp ? "<p>" : "<br>";
+ $needp = 0;
+ printf FP "<code>%s</code><br>\n", $c;
+ $ex--;
+ }
+ elsif ($k) {
+ if ( $d != $n && !$nf ) {
+ printf FP "<h3><em>Default value</em></h3>\n";
+ printf FP "<p>";
+ $needp = 0;
+ }
+ $c =~ s/:$/:<em>none<\/em>/;
+ $c =~ s/:/<\/code>:<code>/;
+ $c = "<code>" . $c . "</code>";
+ if ( !$nf ) {
+ $c .= "<br>";
+ }
+ printf FP "%s\n", $c;
+ $d = $n + 1;
+ }
+ else {
+ if ( $p && !$nf ) {
+ printf FP "<p>\n";
+ $needp = 0;
+ }
+ $p = 0;
+ if ( $input[ $n + 1 ] =~ /^#\s*==/ ) {
+ $c = "<br><em>$c</em>";
+ if ( !$nf ) {
+ $c .= "<br>";
+ }
+ $next++;
+ }
+ printf FP "<p>" if $needp;
+ $needp = 0;
+ printf FP "%s\n", $c;
+ }
+ if ( $nf != 0 && $nf-- == 0 ) {
+ printf FP "</pre>\n";
+ }
+ }
+ }
+ close(FP);
+
+ # Here we collect files with description of needed lynx.cfg
+ # options in the proper (natural or sorted) order.
+ open( FP, ">>$output" ) || do {
+ print STDERR "Can't open $output: $!\n";
+ return;
+ };
+ {
+ my @ordered =
+ ( defined $opt_s ? ( sort keys(%optname_to_fname) ) : @optnames );
+ printf FP "<p>";
+ if ( defined $opt_s ) {
+ print FP "Options are sorted by name.\n";
+ }
+ else {
+ print FP "Options are in the same order as lynx.cfg.\n";
+ }
+ foreach $l (@ordered) {
+ my $fnm = $tmpdir . $optname_to_fname{$l};
+ open( FP1, "<$fnm" ) || do {
+ print STDERR "Can't open $fnm: $!\n";
+ return;
+ };
+ my $avail = ok($l);
+ if ( defined $opt_a || $avail ) {
+ my @lines = <FP1>;
+ print FP @lines;
+ if ( !$avail && defined $opt_m ) {
+ print FP <<'EOF';
+<p>Support for this setting was disabled at compile-time.
+EOF
+ }
+ }
+ close(FP1);
+ }
+ foreach $l ( values(%optname_to_fname) ) {
+ unlink $l;
+ }
+ }
+
+ print FP <<'EOF';
+</body>
+</html>
+EOF
+ close(FP);
+}
+
+sub gen_cattoc {
+ my @input = @_;
+ my @major;
+ my %descs;
+ my %index;
+ my ( $n, $m, $c, $d, $found, $h1, $nf, $ex, $count, $once );
+ my $output = "cattoc.html";
+
+ open( FP, ">$output" ) || do {
+ print STDERR "Can't open $output: $!\n";
+ return;
+ };
+ print FP <<'EOF';
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rev="made" href="mailto:lynx-dev@nongnu.org">
+<title>lynx.cfg settings by category</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content=
+"These are the categories for Lynx's settings in lynx.cfg, with summary descriptions and links to each setting.">
+</head>
+<body>
+<p>These are the major categories of configuration settings in Lynx:
+<ul>
+EOF
+ $m = -1;
+ $h1 = 0;
+ $nf = 0;
+ for $n ( 0 .. $#input ) {
+ my $count = $#input;
+ my $once = 1;
+ $c = $input[$n];
+ if ( $input[$n] =~ /^\.h1\s/ ) {
+ $h1 = 1;
+ $c =~ s/^.h1\s*//;
+ $m = $#major + 1;
+ $d = 0;
+ $found = 0;
+ while ( $d <= $#major && !$found ) {
+ if ( $major[$d] eq $c ) {
+ $m = $d;
+ $found = 1;
+ }
+ $d++;
+ }
+ if ( !$found ) {
+ $major[$m] = $c;
+ $descs{ $major[$m] } = "";
+ $index{ $major[$m] } = "";
+ }
+ next;
+ }
+ elsif ( $h1 != 0 ) {
+ if ( $c =~ /^\.(nf|ex)/ ) {
+ my $s = $c;
+ $s =~ s/^\.[[:lower:]]+\s//;
+ if ( $s =~ /^[[:digit:]]+$/ ) {
+ $count = $s;
+ $once = $s;
+ }
+ }
+ if ( $input[$n] =~ /^$/ ) {
+ $h1 = 0;
+ }
+ elsif ( $input[$n] =~ /^\.nf/ ) {
+ $descs{ $major[$m] } .= "<pre>" . "\n";
+ $nf = $count;
+ }
+ elsif ( $input[$n] =~ /^\.fi/ ) {
+ $descs{ $major[$m] } .= "</pre>" . "\n";
+ $nf = 0;
+ }
+ elsif ( $input[$n] =~ /^\.ex/ ) {
+ $ex = $once;
+ $descs{ $major[$m] } .=
+ "<h3><em>Example"
+ . ( $ex > 1 ? "s" : "" )
+ . ":</em></h3>\n" . "\n";
+ }
+ elsif ( $input[$n] =~ /^\s*#/ ) {
+ $c = $input[$n];
+ $c =~ s/^\s*#\s*//;
+ $descs{ $major[$m] } .= $c . "\n";
+ }
+ }
+ if ( $m >= 0 && $input[$n] =~ /^\.h2\s/ ) {
+ $c = $input[$n];
+ $c =~ s/^.h2\s*//;
+ $index{ $major[$m] } .= $c . "\n"
+ if ( defined $opt_a || ok($c) );
+ $h1 = 0;
+ }
+ if ( $nf != 0 && $nf-- == 0 ) {
+ $descs{ $major[$m] } .= "</pre>\n";
+ }
+ }
+ @major = sort @major;
+ for $n ( 0 .. $#major ) {
+ $cats{ $major[$n] } = sprintf( "header%03d", $n );
+ printf FP "<li><a href=\"#%s\">%s</a>\n", $cats{ $major[$n] },
+ $major[$n];
+ }
+ printf FP "</ul>\n";
+ for $n ( 0 .. $#major ) {
+ printf FP "\n";
+ printf FP "<h2><a name=\"%s\">%s</a></h2>\n", $cats{ $major[$n] },
+ $major[$n];
+ if ( $descs{ $major[$n] } !~ /^$/ ) {
+ printf FP "<h3>Description</h3>\n<p>%s\n", $descs{ $major[$n] };
+ }
+ $c = $index{ $major[$n] };
+ if ( $c ne "" ) {
+ my @c = split( /\n/, $c );
+ @c = sort @c;
+ printf FP
+ "<p>Here is a list of settings that belong to this category\n";
+ printf FP "<ul>\n";
+ for $m ( 0 .. $#c ) {
+ my $avail = ok( $c[$m] );
+ my $mark = ( !$avail && defined $opt_m ) ? "*" : "";
+ printf FP "<li><a href=\"body.html#%s\">%s</a>\n", $c[$m],
+ $c[$m] . $mark;
+ }
+ printf FP "</ul>\n";
+ }
+ }
+ my $str = <<'EOF'
+<p>
+<a href=alphatoc.html>To list of settings by name</a>
+EOF
+ . (
+ defined $opt_a && defined $opt_m
+ ? "<p>Support for all settings suffixed with '*' was disabled at compile time."
+ : ""
+ )
+ . <<'EOF'
+</body>
+</html>
+EOF
+ ;
+ print FP $str;
+ close(FP);
+ return @cats;
+}
diff --git a/scripts/cfg_defs.sh b/scripts/cfg_defs.sh
new file mode 100755
index 0000000..560dfc4
--- /dev/null
+++ b/scripts/cfg_defs.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# $LynxId: cfg_defs.sh,v 1.2 2021/01/07 00:38:05 tom Exp $
+# Translate the lynx_cfg.h and config.cache data into a table, useful for
+# display at runtime.
+
+TOP="${1-.}"
+OUT=cfg_defs.h
+
+# just in case we want to run this outside the makefile
+: "${SHELL:=/bin/sh}"
+
+{
+cat <<EOF
+#ifndef CFG_DEFS_H
+#define CFG_DEFS_H 1
+
+static const struct {
+ const char *name;
+ const char *value;
+} config_cache[] = {
+EOF
+
+sed \
+ -e '/^#/d' \
+ -e 's/^.[^=]*_cv_//' \
+ -e 's/=\${.*=/=/' \
+ -e 's/}$//' \
+ config.cache | $SHELL "$TOP/scripts/cfg_edit.sh"
+
+cat <<EOF
+};
+
+static const struct {
+ const char *name;
+ const char *value;
+} config_defines[] = {
+EOF
+${FGREP-fgrep} '#define' lynx_cfg.h |
+sed -e 's@ @ @g' \
+ -e 's@ @ @g' \
+ -e 's@^[ ]*#define[ ]*@@' \
+ -e 's@[ ]*/\*.*\*/@@' \
+ -e 's@[ ][ ]*@=@' \
+ | $SHELL "$TOP/scripts/cfg_edit.sh"
+
+cat <<EOF
+};
+
+#endif /* CFG_DEFS_H */
+EOF
+} >$OUT
diff --git a/scripts/cfg_edit.sh b/scripts/cfg_edit.sh
new file mode 100755
index 0000000..99f00be
--- /dev/null
+++ b/scripts/cfg_edit.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Invoked from cfg_defs.sh as a filter
+# Strip leading and trailing whitespace
+# Escape any iternal '\'
+# Escape any iternal '"'
+# Entify any iternal '&', '<' or '>'
+# Append a '=' if none present'
+# Break into two strings at '='
+# Prefix ' { "' and suffix '" },'
+LC_ALL=C sort |
+sed -e 's!^[ ]*!!' -e 's![ ]*$!!' \
+ -e 's!\\!\\\\!g' \
+ -e 's!"!\\"!g' \
+ -e 's!&!\&amp;!g' -e 's!<!\&lt;!g' -e 's!>!\&gt;!g' \
+ -e 's!^[^=]*$!&=!' \
+ -e 's!=!", "!' \
+ -e 's!^! { "!' -e 's!$!" },!'
diff --git a/scripts/cfg_path.sh b/scripts/cfg_path.sh
new file mode 100755
index 0000000..321f5b9
--- /dev/null
+++ b/scripts/cfg_path.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Use this script for substituting the configured path into lynx.cfg -
+# not all paths begin with a slash.
+SECOND=`echo "$2" | sed -e 's,^/,,'`
+sed -e "/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]*:file:/s,/PATH_TO/$1,/$SECOND,"
diff --git a/scripts/collapse-br b/scripts/collapse-br
new file mode 100755
index 0000000..a3378b5
--- /dev/null
+++ b/scripts/collapse-br
@@ -0,0 +1,162 @@
+#!/usr/bin/env perl
+# $LynxId: collapse-br,v 1.8 2017/07/04 19:35:45 tom Exp $
+# Generate a series of HTML files containing a mixture of text and <br> tags,
+# comparing dumps of those to w3m and elinks.
+
+use warnings;
+use strict;
+use diagnostics;
+
+$| = 1;
+
+use Getopt::Std;
+use File::Temp qw/ tempdir /;
+
+our ( $opt_C, $opt_T, $opt_e, $opt_l, $opt_p, $opt_t, $opt_w );
+our $tempdir = tempdir( CLEANUP => 1 );
+
+sub dumpit($$) {
+ my $prog = shift;
+ my $html = shift;
+ my $opts = "-dump";
+ $html =
+ "<html>"
+ . "<head><title>T</title></head>"
+ . "<body>$html</body>"
+ . "</html>"
+ if ($opt_t);
+ my @result;
+ if ( $prog =~ /lynx$/ ) {
+ my $name = "$tempdir/lynx.cfg";
+ $opts .= " -cfg=$name";
+ open my $fh, ">$name";
+ printf $fh "collapse_br_tags:%s\n", $opt_C ? "false" : "true";
+ printf $fh "trim_blank_lines:%s\n", $opt_T ? "false" : "true";
+ close $fh;
+ }
+ if ($opt_p) {
+ $opts .= " -stdin" if ( $prog =~ /lynx$/ );
+ $opts .= " -force-html" if ( $prog =~ /elinks$/ );
+ $opts .= " -T text/html" if ( $prog =~ /w3m$/ );
+ if ( open my $fh, "echo '$html' | $prog $opts |" ) {
+ @result = <$fh>;
+ close $fh;
+ }
+ }
+ else {
+ my $name = "$tempdir/foobar.html";
+ open my $fh, ">$name";
+ printf $fh "%s", $html;
+ close $fh;
+
+ $opts .= " $name";
+ if ( open my $fh, "$prog $opts |" ) {
+ @result = <$fh>;
+ close $fh;
+ }
+ }
+ for my $n ( 0 .. $#result ) {
+ chomp $result[$n];
+ }
+
+ if ( open my $fh, "echo '$html' | $prog $opts |" ) {
+ @result = <$fh>;
+ close $fh;
+ for my $n ( 0 .. $#result ) {
+ chomp $result[$n];
+ }
+ }
+ $result[0] = "OOPS" unless ( $#result >= 0 );
+ return @result;
+}
+
+sub header($) {
+ my @cols = @{ $_[0] };
+ my $text = "";
+ for my $c ( 0 .. $#cols ) {
+ $text .= sprintf "%-8s", $cols[$c];
+ }
+ printf "\t %s\n", $text;
+}
+
+sub doit() {
+ my $length = 1;
+ my $state = -1;
+
+ my @tokens;
+ $tokens[0] = " ";
+ $tokens[1] = "X";
+ $tokens[2] = "<br>";
+ my $tokens = $#tokens + 1;
+
+ my @progs;
+ $progs[ $#progs + 1 ] = "lynx";
+
+ $progs[ $#progs + 1 ] = "w3m" if ($opt_w);
+ $progs[ $#progs + 1 ] = "elinks" if ($opt_e);
+ $progs[ $#progs + 1 ] = "./lynx" if ( -f "./lynx" );
+
+ while ( $length <= $opt_l ) {
+ my $bits = "";
+ my $html = "";
+ my $value = ++$state;
+ $length = 0;
+ while ( $value >= 0 ) {
+ my $digit = $value % $tokens;
+ my $update = ( $value - $digit ) / $tokens;
+ last if ( ( $update <= 0 ) and ( $value <= 0 ) and $length > 0 );
+ $bits .= sprintf "%d", $digit;
+ $length++;
+ $html .= $tokens[$digit];
+ $value = $update;
+ }
+
+ # skip the non-interesting cases
+ next if ( $bits =~ /00/ );
+ next if ( $bits =~ /11/ );
+ next unless ( $bits =~ /2/ );
+ printf "%-*s '%s'\n", $opt_l, $bits, $html;
+ my @listing;
+ for my $p ( 0 .. $#progs ) {
+ my @q = &dumpit( $progs[$p], $html );
+ my $l = $p * 8;
+ for my $r ( 0 .. $#q ) {
+
+ $listing[$r] = "" unless ( $listing[$r] );
+ $listing[$r] = sprintf "%-*s", $l, $listing[$r] if ( $l > 0 );
+ $listing[$r] .= sprintf "|%s",
+ substr( $q[$r] . "........", 0, 7 );
+ }
+ }
+ &header( \@progs );
+ for my $r ( 0 .. $#listing ) {
+ printf "\t%2d %s|\n", $r, $listing[$r];
+ }
+ }
+}
+
+sub main::HELP_MESSAGE() {
+ printf STDERR <<EOF
+Usage: $0 [options]
+
+Options:
+ -C do not collapse BR-tags (lynx only)
+ -T do not trim blank lines (lynx only)
+ -e compare with elinks
+ -l NUM generate test-cases up to this length (default: 3)
+ -p pipe HTML to the program rather than reading a file
+ -t add dummy title
+ -w compare with w3m
+
+EOF
+ ;
+ exit;
+}
+
+&getopts('CTel:ptw') || main::HELP_MESSAGE;
+
+$opt_l = 3 unless ($opt_l);
+
+&doit;
+
+1;
diff --git a/scripts/conf.mingw.sh b/scripts/conf.mingw.sh
new file mode 100755
index 0000000..3828a98
--- /dev/null
+++ b/scripts/conf.mingw.sh
@@ -0,0 +1,38 @@
+#!/bin/bash.exe
+# $LynxId: conf.mingw.sh,v 1.2 2014/02/13 13:30:54 tom Exp $
+
+LYNX_DEV=d
+LYNX_TOP=/cygwin/mingw/lynx2.8.7dev.13
+LYNX_ETC=$LYNX_TOP/lynx-conf
+
+LDFLAGS="-mno-cygwin -static -L/mingw/lib" \
+LIBS="-lwsock32 -lgdi32 -lmsvcrt -liconv" \
+CFLAGS="-mno-cygwin -I/mingw/include -I/mingw/include/openssl -W -Wall -O3 -D_WINDOWS -DSH_EX -DWIN_EX -DNOUSERS -DNOSIGHUP -DDOSPATH -DUSE_ALT_BLAT_MAILER -DBOXHORI=0 -DBOXVERT=0" \
+CPPFLAGS="-mno-cygwin -I/mingw/include -I/mingw/include/openssl" \
+./configure --prefix=/$LYNX_DEV$LYNX_ETC \
+--host=mingw32 \
+--disable-dired-override \
+--disable-full-paths \
+--enable-addrlist-page \
+--enable-change-exec \
+--enable-charset-choice \
+--enable-default-colors \
+--enable-exec-links \
+--enable-externs \
+--enable-file-upload \
+--enable-gzip-help \
+--enable-nested-tables \
+--enable-nls \
+--enable-vertrace \
+--includedir=/mingw/include \
+--sysconfdir=/$LYNX_DEV$LYNX_ETC \
+--datadir=/$LYNX_DEV$LYNX_ETC \
+--with-bzlib \
+--with-cfg-file=$LYNX_DEV:$LYNX_ETC/lynx.cfg \
+--with-lss-file=$LYNX_DEV:$LYNX_ETC/lynx.lss \
+--with-mime-libdir=c:/ \
+--with-nls-datadir=d:/cygwin/mingw/share \
+--with-pkg-config=no \
+--with-screen=curses \
+--with-ssl=/mingw/lib \
+--with-zlib
diff --git a/scripts/config.djgpp.sh b/scripts/config.djgpp.sh
new file mode 100755
index 0000000..fa4dcfe
--- /dev/null
+++ b/scripts/config.djgpp.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+CFLAGS="-g -gcoff -O2 -W -Wall -I/dev/env/DJDIR/pdcur_cvs/PDCurses -I/dev/env/DJDIR/watt32/inc" \
+CPPFLAGS="-DBOXHORI=0 -DBOXVERT=0 -I/dev/env/DJDIR/pdcur_cvs/PDCurses -I/dev/env/DJDIR/watt32/inc" \
+LIBS="-L/dev/env/DJDIR/pdcur_cvs/PDCurses/lib -L/dev/env/DJDIR/watt32/lib -lwmemu" \
+/dev/env/DJDIR/bin/bash.exe ./configure \
+--datadir=/dev/env/DJDIR/lib \
+--sysconfdir=/dev/env/DJDIR/lib \
+--disable-dired-override \
+--disable-full-paths \
+--enable-addrlist-page \
+--enable-change-exec \
+--enable-cgi-links \
+--enable-charset-choice \
+--enable-exec-links \
+--enable-externs \
+--enable-nested-tables \
+--enable-nls \
+--enable-scrollbar \
+--enable-vertrace \
+--with-bzlib \
+--with-mime-libdir=/dev/env/DJDIR/lib \
+--with-screen=curses \
+--with-ssl \
+--with-zlib
diff --git a/scripts/fixtext.sh b/scripts/fixtext.sh
new file mode 100755
index 0000000..a6f53b6
--- /dev/null
+++ b/scripts/fixtext.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# $LynxId: fixtext.sh,v 1.2 2021/01/07 00:21:03 tom Exp $
+
+# xgettext only processes literal strings. Someone with a poor sense of humor
+# decided to ignore strings in preprocessor lines. So we construct a fake
+# ".c" file with the definitions turned into literals.
+
+sed -e 's/")/");/' \
+ -e 's/^#define[ ]*\([^ ]*\)[ ]*gettext/char *\1 = gettext/' \
+ -e 's,^#define[ ]*\([^ ]*\)[ ]*\\,/* #define \1 */char *\1 = \\,' \
+ "$@"
diff --git a/scripts/indent.sh b/scripts/indent.sh
new file mode 100755
index 0000000..8933084
--- /dev/null
+++ b/scripts/indent.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+# $LynxId: indent.sh,v 1.6 2021/01/07 00:23:01 tom Exp $
+# Indent LYNX files (for reference). See "lnx-indent" from
+# https://invisible-island.net/cindent/
+NOOP=no
+OPTS='
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--braces-on-if-line
+--continue-at-parentheses
+--cuddle-else
+--dont-break-procedure-type
+--indent-level4
+--leave-preprocessor-space
+--line-length80
+--no-space-after-function-call-names
+--parameter-indentation4
+--space-after-cast
+--space-special-semicolon
+--swallow-optional-blank-lines
+-T AddressDefList
+-T BOOL
+-T BOOLEAN
+-T CSOfield_info
+-T DIR
+-T DocAddress
+-T DocInfo
+-T DocObj
+-T EntryInfo
+-T EditFieldData
+-T FILE
+-T GCC_NORETURN
+-T GCC_UNUSED
+-T GLOBALREF
+-T GroupDef
+-T GroupDefList
+-T HTAAFailReasonType
+-T HTAAProt
+-T HTAARealm
+-T HTAAServer
+-T HTAssoc
+-T HTAssocList
+-T HTAtom
+-T HTBTElement
+-T HTBTree
+-T HTChildAnchor
+-T HTChunk
+-T HTConverter
+-T HTFormat
+-T HTLine
+-T HTLinkType
+-T HTList
+-T HTParentAnchor
+-T HTParentAnchor0
+-T HTPresentation
+-T HTStream
+-T HTStyle
+-T HTStyleChange
+-T HTStyleSheet
+-T HText
+-T HyperDoc
+-T InitResponseAPDU
+-T Item
+-T ItemList
+-T LYNX_ADDRINFO
+-T LYNX_HOSTENT
+-T LYUCcharset
+-T LexItem
+-T ProgramPaths
+-T STable_cellinfo
+-T STable_info
+-T STable_rowinfo
+-T STable_states
+-T SearchAPDU
+-T SearchResponseAPDU
+-T TextAnchor
+-T UCode_t
+-T UserDefList
+-T WAISDocumentCodes
+-T WAISDocumentHeader
+-T WAISDocumentHeadlines
+-T WAISDocumentLongHeader
+-T WAISDocumentShortHeader
+-T WAISDocumentText
+-T WAISInitResponse
+-T WAISSearch
+-T _cdecl
+-T any
+-T bit_map
+-T boolean
+-T bstring
+-T data_tag
+-T eServerType
+-T lynx_list_item_type
+-T pdu_type
+-T query_term
+-nbacc
+'
+for name in "$@"
+do
+ case $name in
+ -n) NOOP=yes
+ OPTS="$OPTS -v"
+ ;;
+ -*)
+ OPTS="$OPTS $name"
+ ;;
+ *.[ch])
+ save="${name}".a$$
+ test="${name}".b$$
+ rm -f "$save" "$test"
+ mv "$name" "$save"
+ sed \
+ -e '/MODULE_ID(/s/)$/);/' \
+ -e 's,)[ ]*\<GCC_PRINTFLIKE,);//GCC_PRINTFLIKE,' \
+ -e 's,[ ]*\<GCC_NORETURN;,;//GCC_NORETURN;,' \
+ -e 's,[ ]*\<GCC_UNUSED;,;//GCC_UNUSED;,' \
+ "$save" >"$test"
+ cp "$test" "$name"
+ chmod u+w "$name"
+ ${INDENT_PROG-indent} -npro $OPTS "$name"
+ sed \
+ -e '/MODULE_ID(/s/);$/)/' \
+ -e 's,;[ ]*//GCC_UNUSED;, GCC_UNUSED;,' \
+ -e 's,;[ ]*//GCC_NORETURN;, GCC_NORETURN;,' \
+ -e 's,);[ ]*//GCC_PRINTFLIKE,) GCC_PRINTFLIKE,' \
+ "$name" >"$test"
+ mv "$test" "$name"
+ rm -f "${name}~"
+ if test $NOOP = yes ; then
+ if ! ( cmp -s "$name" "$save" )
+ then
+ diff -u "$save" "$name"
+ fi
+ mv "$save" "$name"
+ rm -f "${name}~"
+ else
+ if ( cmp -s "$name" "$save" )
+ then
+ echo "** unchanged $name"
+ rm -f "${name}" "${name}~"
+ mv "$save" "$name"
+ else
+ echo "** updated $name"
+ rm -f "$save"
+ fi
+ fi
+ ;;
+ *)
+ echo "** ignored: $name"
+ ;;
+ esac
+done
diff --git a/scripts/install-cfg.sh b/scripts/install-cfg.sh
new file mode 100755
index 0000000..6faa21a
--- /dev/null
+++ b/scripts/install-cfg.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+# $LynxId: install-cfg.sh,v 1.5 2021/01/07 00:31:20 tom Exp $
+# install lynx.cfg, ensuring the old config-file is saved to a unique file,
+# and prepending customizations to the newly-installed file.
+#
+# $1 = install program
+# $2 = file to install
+# $3 = where to install it
+PRG="$1"
+SRC=$2
+DST=$3
+
+LANG=C; export LANG
+LC_ALL=C; export LC_ALL
+LC_CTYPE=C; export LC_CTYPE
+LANGUAGE=C; export LANGUAGE
+
+if test -f "$DST" ; then
+ echo "** checking if you have customized $DST"
+ OLD=lynx-cfg.old
+ NEW=lynx-cfg.new
+ TST=lynx-cfg.tst
+ TMP=lynx-cfg.tmp
+ trap 'rm -f $OLD $NEW $TST $TMP; exit 9' INT QUIT TERM HUP
+ rm -f $OLD $NEW $TST $TMP
+
+ # avoid propagating obsolete URLs into new installs
+ {
+ echo lynx.isc.org;
+ echo lynx.browser.org;
+ echo www.trill-home.com;
+ echo www.cc.ukans.edu;
+ echo www.ukans.edu;
+ echo www.slcc.edu;
+ echo sol.slcc.edu;
+ }>$TMP
+
+ # Make a list of the settings which are in the original lynx.cfg
+ # Do not keep the user's HELPFILE setting since we modify that in
+ # a different makefile rule.
+ ${EGREP-egrep} '^[ ]*[A-Za-z]' "$SRC" |sed -e 's/^[ ]*HELPFILE:.*/HELPFILE:/' >>$TMP
+ ${EGREP-egrep} '^[ ]*[A-Za-z]' "$SRC" |${FGREP-fgrep} -v -f $TMP >$OLD
+ ${EGREP-egrep} '^[ ]*[A-Za-z]' "$DST" |${FGREP-fgrep} -v -f $TMP >$TST
+
+ if test -s $TST ; then
+ cat >$TMP <<EOF
+## The following lines were saved from your previous configuration.
+
+EOF
+ cat "$TST" >>$TMP
+ cat "$SRC" >$NEW
+ cat "$TMP" >>$NEW
+
+ # See if we have saved this information before (ignoring the
+ # HELPFILE line).
+ if cmp -s $NEW $OLD
+ then
+ echo "... installed $DST would not be changed"
+ else
+ NUM=1
+ while test -f "${DST}-${NUM}"
+ do
+ if cmp -s "$NEW" "${DST}-${NUM}"
+ then
+ break
+ fi
+ NUM=`expr "$NUM" + 1`
+ done
+ if test ! -f "${DST}-${NUM}"
+ then
+ echo "... saving old config as ${DST}-${NUM}"
+ mv "$DST" "${DST}-${NUM}" || exit 1
+ fi
+ echo "** installing $NEW as $DST"
+ eval "$PRG" "$NEW" "$DST" || exit 1
+ fi
+ else
+ echo "... no customizations found"
+ echo "** installing $SRC as $DST"
+ eval "$PRG" "$SRC" "$DST" || exit 1
+ fi
+ rm -f "$SKIP" "$OLD" "$NEW" "$TST" "$TMP"
+elif cmp -s "$SRC" "$DST"
+then
+ echo "... installed $DST would not be changed"
+else
+ echo "** installing $SRC as $DST"
+ eval "$PRG" "$SRC" "$DST" || exit 1
+fi
diff --git a/scripts/install-lss.sh b/scripts/install-lss.sh
new file mode 100755
index 0000000..eb9694a
--- /dev/null
+++ b/scripts/install-lss.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# $LynxId: install-lss.sh,v 1.2 2021/01/07 00:32:39 tom Exp $
+# install lynx.lss, ensuring the old config-file is saved to a backup file.
+#
+# $1 = install program
+# $2 = file to install
+# $3 = where to install it
+PRG="$1"
+SRC=$2
+DST=$3
+
+if test -f "$DST" ; then
+ # See if we have saved this information before
+ if cmp -s "$SRC" "$DST"
+ then
+ echo "... installed $DST would not be changed"
+ else
+ NUM=1
+ while test -f "${DST}-${NUM}"
+ do
+ if cmp -s "$SRC" "${DST}-${NUM}"
+ then
+ break
+ fi
+ NUM=`expr "$NUM" + 1`
+ done
+ if test ! -f "${DST}-${NUM}"
+ then
+ echo "... saving old config as ${DST}-${NUM}"
+ mv "$DST" "${DST}-${NUM}" || exit 1
+ fi
+ echo "** installing $SRC as $DST"
+ eval "$PRG" "$SRC" "$DST" || exit 1
+ fi
+else
+ echo "** installing $SRC as $DST"
+ eval "$PRG" "$SRC" "$DST" || exit 1
+fi
diff --git a/scripts/man2hlp.sh b/scripts/man2hlp.sh
new file mode 100755
index 0000000..cc1653c
--- /dev/null
+++ b/scripts/man2hlp.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# $LynxId: man2hlp.sh,v 1.4 2021/01/07 00:34:48 tom Exp $
+# This script uses rman (Rosetta Man), which complements TkMan, to strip
+# nroff headers from a manpage file, and format the result into a VMS help
+# file.
+
+LANG=C; export LANG
+LC_ALL=C; export LC_ALL
+LC_CTYPE=C; export LC_CTYPE
+LANGUAGE=C; export LANGUAGE
+
+for name in "$@"
+do
+ NAME=`echo "$name" |sed -e 's/\.man$/.1/'`
+ (echo 1 "`echo \"$NAME\" | sed -e 's/^.*\///' -e 's/\..*$//' | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`" ; \
+ (echo '.hy 0'; cat "$name") |\
+ nroff -Tascii -man |\
+ rman -n"$NAME" |\
+ sed -e 's/^[1-9].*$//' \
+ -e 's/^\([A-Z]\)/2 \1/' |\
+ uniq)
+done
diff --git a/scripts/relpath.sh b/scripts/relpath.sh
new file mode 100755
index 0000000..cee5a21
--- /dev/null
+++ b/scripts/relpath.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# Given two pathnames, print the first relative to the second.
+#
+# Adapted from
+# https://unix.stackexchange.com/questions/573047/how-to-get-the-relative-path-between-two-directories
+
+usage() {
+ echo "usage: $0 source target" >&2
+ exit 1
+}
+
+check_abs() {
+ case "$1" in
+ /*)
+ ;;
+ *)
+ echo "? not an absolute pathname: $1"
+ usage
+ ;;
+ esac
+}
+
+[ $# = 2 ] || usage
+check_abs "$1"
+check_abs "$2"
+
+source="$1"
+target="$2"
+prefix=""
+
+source="`echo "$source" | sed -e 's%/$%%'`/"
+target="`echo "$target" | sed -e 's%/$%%'`/"
+remain=`echo "$source" | sed -e 's%^'$target'%%'`
+while [ -n "$target" ] && [ "$source" = "$remain" ]
+do
+ prefix="../$prefix"
+ target=`echo "$target" | sed -e 's%/[^/]*/$%/%'`
+ remain=`echo "$source" | sed -e 's%^'$target'%%'`
+done
+result="${prefix}${remain}"
+[ -n "$result" ] || result="."
+
+echo "$result"
diff --git a/scripts/tbl2html.pl b/scripts/tbl2html.pl
new file mode 100755
index 0000000..ba8ae09
--- /dev/null
+++ b/scripts/tbl2html.pl
@@ -0,0 +1,364 @@
+#!/usr/bin/perl -w
+# $LynxId: tbl2html.pl,v 1.5 2011/05/21 15:18:16 tom Exp $
+#
+# Translate one or more ".tbl" files into ".html" files which can be used to
+# test the charset support in lynx. Each of the ".html" files will use the
+# charset that corresponds to the input ".tbl" file.
+
+use strict;
+
+use Getopt::Std;
+use File::Basename;
+use POSIX qw(strtod);
+
+sub field($$) {
+ my $value = $_[0];
+ my $count = $_[1];
+
+ while ( $count > 0 ) {
+ $count -= 1;
+ $value =~ s/^\S*\s*//;
+ }
+ $value =~ s/\s.*//;
+ return $value;
+}
+
+sub notes($) {
+ my $value = $_[0];
+
+ $value =~ s/^[^#]*//;
+ $value =~ s/^#//;
+ $value =~ s/^\s+//;
+
+ return $value;
+}
+
+sub make_header($$$) {
+ my $source = $_[0];
+ my $charset = $_[1];
+ my $official = $_[2];
+
+ printf FP "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
+ printf FP "<HTML>\n";
+ printf FP "<HEAD>\n";
+ printf FP "<!-- $source -->\n";
+ printf FP "<TITLE>%s table</TITLE>\n", &escaped($official);
+ printf FP "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=%s\">\n", &escaped($charset);
+ printf FP "</HEAD>\n";
+ printf FP "\n";
+ printf FP "<BODY> \n";
+ printf FP "\n";
+ printf FP "<H1 ALIGN=center>%s table</H1> \n", &escaped($charset);
+ printf FP "\n";
+ printf FP "<PRE>\n";
+ printf FP "Code Char Entity Render Description\n";
+}
+
+sub make_mark() {
+ printf FP "---- ---- ------ ------ -----------------------------------\n";
+}
+
+sub escaped($) {
+ my $result = $_[0];
+ $result =~ s/&/&amp;/g;
+ $result =~ s/</&lt;/g;
+ $result =~ s/>/&gt;/g;
+ return $result;
+}
+
+sub make_row($$$) {
+ my $old_code = $_[0];
+ my $new_code = $_[1];
+ my $comments = $_[2];
+
+ # printf "# make_row %d %d %s\n", $old_code, $new_code, $comments;
+ my $visible = sprintf("&amp;#%d; ", $new_code);
+ if ($old_code < 256) {
+ printf FP "%4x %c %.13s &#%d; %s\n",
+ $old_code, $old_code,
+ $visible, $new_code,
+ &escaped($comments);
+ } else {
+ printf FP "%4x . %.13s &#%d; %s\n",
+ $old_code,
+ $visible, $new_code,
+ &escaped($comments);
+ }
+}
+
+sub null_row($$) {
+ my $old_code = $_[0];
+ my $comments = $_[1];
+
+ if ($old_code < 256) {
+ printf FP "%4x %c %s\n",
+ $old_code, $old_code,
+ &escaped($comments);
+ } else {
+ printf FP "%4x . %s\n",
+ $old_code,
+ &escaped($comments);
+ }
+}
+
+sub make_footer() {
+ printf FP "</PRE>\n";
+ printf FP "</BODY>\n";
+ printf FP "</HTML>\n";
+}
+
+# return true if the string describes a range
+sub is_range($) {
+ return ($_[0] =~ /.*-.*/);
+}
+
+# convert the U+'s to 0x's so strtod() can convert them.
+sub zeroxes($) {
+ my $result = $_[0];
+ $result =~ s/^U\+/0x/;
+ $result =~ s/-U\+/-0x/;
+ return $result;
+}
+
+# convert a string to a number (-1's are outside the range of Unicode).
+sub value_of($) {
+ my ($result, $oops) = strtod($_[0]);
+ $result = -1 if ($oops ne 0);
+ return $result;
+}
+
+# return the first number in a range
+sub first_of($) {
+ my $range = &zeroxes($_[0]);
+ $range =~ s/-.*//;
+ return &value_of($range);
+}
+
+# return the last number in a range
+sub last_of($) {
+ my $range = &zeroxes($_[0]);
+ $range =~ s/^.*-//;
+ return &value_of($range);
+}
+
+sub one_many($$$) {
+ my $oldcode = $_[0];
+ my $newcode = &zeroxes($_[1]);
+ my $comment = $_[2];
+
+ my $old_code = &value_of($oldcode);
+ if ( $old_code lt 0 ) {
+ printf "? Problem with number \"%s\"\n", $oldcode;
+ } else {
+ &make_mark if (( $old_code % 8 ) == 0 );
+
+ if ( $newcode =~ /^#.*/ ) {
+ &null_row($old_code, $comment);
+ } elsif ( &is_range($newcode) ) {
+ my $first_item = &first_of($newcode);
+ my $last_item = &last_of($newcode);
+ my $item;
+
+ if ( $first_item lt 0 or $last_item lt 0 ) {
+ printf "? Problem with one:many numbers \"%s\"\n", $newcode;
+ } else {
+ if ( $comment =~ /^$/ ) {
+ $comment = sprintf("mapped: %#x to %#x..%#x", $old_code, $first_item, $last_item);
+ } else {
+ $comment = $comment . " (range)";
+ }
+ for $item ( $first_item..$last_item) {
+ &make_row($old_code, $item, $comment);
+ }
+ }
+ } else {
+ my $new_code = &value_of($newcode);
+ if ( $new_code lt 0 ) {
+ printf "? Problem with number \"%s\"\n", $newcode;
+ } else {
+ if ( $comment =~ /^$/ ) {
+ $comment = sprintf("mapped: %#x to %#x", $old_code, $new_code);
+ }
+ &make_row($old_code, $new_code, $comment);
+ }
+ }
+ }
+}
+
+sub many_many($$$) {
+ my $oldcode = $_[0];
+ my $newcode = $_[1];
+ my $comment = $_[2];
+
+ my $first_old = &first_of($oldcode);
+ my $last_old = &last_of($oldcode);
+ my $item;
+
+ if (&is_range($newcode)) {
+ my $first_new = &first_of($newcode);
+ my $last_new = &last_of($newcode);
+ for $item ( $first_old..$last_old) {
+ &one_many($item, $first_new, $comment);
+ $first_new += 1;
+ }
+ } else {
+ for $item ( $first_old..$last_old) {
+ &one_many($item, $newcode, $comment);
+ }
+ }
+}
+
+sub approximate($$$) {
+ my $values = $_[0];
+ my $expect = sprintf("%-8s", $_[1]);
+ my $comment = $_[2];
+ my $escaped = &escaped($expect);
+ my $left;
+ my $this;
+ my $next;
+
+ $escaped =~ s/\\134/\\/g;
+ $escaped =~ s/\\015/\&#13\;/g;
+ $escaped =~ s/\\012/\&#10\;/g;
+
+ while ( $escaped =~ /^.*\\[0-7]{3}.*$/ ) {
+ $left = $escaped;
+ $left =~ s/\\[0-7]{3}.*//;
+ $this = substr $escaped,length($left)+1,3;
+ $next = substr $escaped,length($left)+4;
+ $escaped = sprintf("%s&#%d;%s", $left, oct $this, $next);
+ }
+
+ my $visible = sprintf("&amp;#%d; ", $values);
+ if ($values < 256) {
+ printf FP "%4x %c %.13s &#%d; approx: %s\n",
+ $values, $values,
+ $visible,
+ $values,
+ $escaped;
+ } else {
+ printf FP "%4x . %.13s &#%d; approx: %s\n",
+ $values,
+ $visible,
+ $values,
+ $escaped;
+ }
+}
+
+sub doit($) {
+ my $source = $_[0];
+
+ printf "** %s\n", $source;
+
+ my $target = basename($source, ".tbl");
+
+ # Read the file into an array in memory.
+ open(FP,$source) || do {
+ print STDERR "Can't open input $source: $!\n";
+ return;
+ };
+ my (@input) = <FP>;
+ chomp @input;
+ close(FP);
+
+ my $n;
+ my $charset = "";
+ my $official = "";
+ my $empty = 1;
+
+ for $n (0..$#input) {
+ $input[$n] =~ s/\s*$//; # trim trailing blanks
+ $input[$n] =~ s/^\s*//; # trim leading blanks
+ $input[$n] =~ s/^#0x/0x/; # uncomment redundant stuff
+
+ next if $input[$n] =~ /^$/;
+ next if $input[$n] =~ /^#.*$/;
+
+ if ( $empty
+ and ( $input[$n] =~ /^\d/
+ or $input[$n] =~ /^U\+/ ) ) {
+ $target = $charset . ".html";
+ printf "=> %s\n", $target;
+ open(FP,">$target") || do {
+ print STDERR "Can't open output $target: $!\n";
+ return;
+ };
+ &make_header($source, $charset, $official);
+ $empty = 0;
+ }
+
+ if ( $input[$n] =~ /^M.*/ ) {
+ $charset = $input[$n];
+ $charset =~ s/^.//;
+ } elsif ( $input[$n] =~ /^O.*/ ) {
+ $official = $input[$n];
+ $official =~ s/^.//;
+ } elsif ( $input[$n] =~ /^\d/ ) {
+
+ my $newcode = &field($input[$n], 1);
+
+ next if ( $newcode eq "idem" );
+ next if ( $newcode eq "" );
+
+ my $oldcode = &field($input[$n], 0);
+ if ( &is_range($oldcode) ) {
+ &many_many($oldcode, $newcode, &notes($input[$n]));
+ } else {
+ &one_many($oldcode, $newcode, &notes($input[$n]));
+ }
+ } elsif ( $input[$n] =~ /^U\+/ ) {
+ if ( $input[$n] =~ /^U\+\w+:/ ) {
+ my $values = $input[$n];
+ my $expect = $input[$n];
+
+ $values =~ s/:.*//;
+ $values = &zeroxes($values);
+ $expect =~ s/^[^:]+://;
+
+ if ( &is_range($values) ) {
+ printf "fixme:%s(%s)(%s)\n", $input[$n], $values, $expect;
+ } else {
+ &approximate(&value_of($values), $expect, &notes($input[$n]));
+ }
+ } else {
+ my $value = $input[$n];
+ $value =~ s/\s*".*//;
+ $value = &value_of(&zeroxes($value));
+ if ($value gt 0) {
+ my $quote = $input[$n];
+ my $comment = &notes($input[$n]);
+ $quote =~ s/^[^"]*"//;
+ $quote =~ s/".*//;
+ &approximate($value, $quote, $comment);
+ } else {
+ printf "fixme:%d(%s)\n", $n, $input[$n];
+ }
+ }
+ } else {
+ # printf "skipping line %d:%s\n", $n + 1, $input[$n];
+ }
+ }
+ if ( ! $empty ) {
+ &make_footer();
+ }
+ close FP;
+}
+
+sub usage() {
+ print <<USAGE;
+Usage: $0 [tbl-files]
+
+The script writes a new ".html" file for each input, using
+the same name as the input, stripping the ".tbl" suffix.
+USAGE
+ exit(1);
+}
+
+if ( $#ARGV < 0 ) {
+ usage();
+} else {
+ while ( $#ARGV >= 0 ) {
+ &doit ( shift @ARGV );
+ }
+}
+exit (0);