#!/usr/bin/perl -w
##
# gphelp originally written by Niels Skoruppa for pariGUIde; forked and
# maintained by Karim Belabas (since v 1.7, 2002)
#
# This script generates html documentation of the gp/pari functions
# on using the tex documentation as given in chapter 3 of the users manual.
# Currently this is a workaround since there seems to exist no reasonable
# plain TeX to html converter. Here we just take the outputs of
# gphelp -raw and translate them into html form. It will be easy to replace,
# in the following code, the use of this function by a more powerful tex2html
# translator.
#
# Usage: gphtml [--dist|--4gui|--base=BASE|--out=OUT|--subsections]
#
# Without any option this will create, in the directory where you
# called, a subdirectory named html, and therein the html documentation.
# --base=BASE: where to find PARI's toplevel (mandatory)
# --out=OUT: where to output our pages
# --dist : add this file and a tar archive of html to html.
# --4gui : creates the reference docs for pariguide.
# The other options are for debugging purposes or consistency checks only.
#
# Adjust the three pathes below (look for AdJuSt).
#########################################################################
#use strict 'vars';
my ($USERSCH3_TEX,
# $HTML, $DATE, $version,
$distFlag, $guiFlag, $subsectionsFlag,
%pics, %basicFrames, %subsections, %sections, %subsectionsByAl, %fill,
%sublabel, %tr, %html,
@ou, @shortcuts,
);
$DATE = localtime();
##############
# AdJuSt these
##############
$base = "/usr/local/src/pari"; # the toplevel PARI/GP sources
#########################
# Parse the argument line
#########################
$distFlag = $guiFlag = $subsectionsFlag = 0;
for (@ARGV) {
/--dist/ and do { $distFlag = 1; next;};
/--4gui/ and do { $guiFlag = 1; next;};
/--subsections/ and do { $subsectionsFlag = 1; next;};
/--base=(.*)/ and do { $base = $1; next;};
/--out=(.*)/ and do { $HTML = $1; next;};
&usage;
}
my ($HTMLdft) = $guiFlag? "./ref": "./html";
if (!$HTML) { $HTML = $HTMLdft; }
$ENV{'GPHELP_DOCDIR'} = "$base/doc";
$USERSCH3_TEX = "$base/doc/usersch3.tex";
$gphelp = "$base/doc/gphelp";
$gphelp_translations = "$base/doc/translations";
sub usage {
print STDERR "Usage: $0 [--base=BASE|--out=OUT|--dist|--4gui|--subsections]\n";
exit( 0);
}
# We see first what information the system has about pari/gp and collect it
initVersionAndShortcuts();
initSubsections();
# If we only want to list the subsections of usersch3.tex, then this
sub dbgSections {
for my $k (sort keys %sections) { print "$k $sections{$k}\n"; }
for my $k (sort keys %subsections) {
print "\n\n $k\n\n";
for my $i (@{ $subsections{$k} }) { print "\t$i\n"; }
}
}
if ($subsectionsFlag) { dbgSections(); exit(0); }
initFixedData();
system( "mkdir -p $HTML");
#######################################################################
# Here we write all *.html files of the pariguide doc
#######################################################################
if ($guiFlag) {
my ($HEAD) = <<"__UP_TO_HERE__";
__UP_TO_HERE__
writeData(*DATA, 1); # icons
writeToC4Ref($HEAD); #toc
writeIndex(6, $HEAD); # function index using 6 columns,
# subsection pages,
for my $k (sort keys %subsections) { &writeEntries4Ref($k, $HEAD); }
# and meta commands.
writeShortcuts($HEAD);
exit(0);
};
#######################################################################
# Here we write all *.html files, according to the
# frame layout sketched in the data section below (after __DATA__ ).
# Change look and feel by altering the descriptions in the data section.
#######################################################################
# Write basic frames
writeData(*DATA, 0);
writeToC();
# ... and the pages for the frames "item" and "entry"
for my $k (keys %subsections) {
writeFunctionsByCategory($k);
&writeEntries($k);
}
writeModRewrite();
writeShortcuts("");
writeOperators();
writeReadline();
for my $l (sort keys %subsectionsByAl) { writeFunctionsByAlphabet($l) }
if ($distFlag)
{ system("cp gphtml $HTML; H=`basename $HTML`; cd $HTML/..; tar cfz \$H.tgz \$H") }
########### The subroutines ##################
sub warning { print STDERR "\t\e[0;31m\e[1mWarning:\e[m ".$_[0]."\n"; }
sub fatal { die "\t\e[0;31m\e[1mError:\e[m ".$_[0]."\n"; }
sub happy { print STDERR " ".$_[0]." ....\e[0;32m\e[1m OK\e[m\n"; }
sub unhappy { print STDERR " ".$_[0]." ....\e[0;31m\e[1m FAILED\e[m\n"; }
###############################################################################
# Sets ups $version and the list @shortcuts of GP keyboard shortcuts. Calls gp!
# Checks if gphelp is available
###############################################################################
sub initVersionAndShortcuts {
my ($gp) = "$base/gp";
my ($v) = `$gp --version 2>&1 | grep CALCULATOR`;
if ($v eq "") { fatal( "gp --version doesn't work"); }
chomp($v);
$v =~ s/ *development *//;
$version = $v;
$v =~ s/.*CALCULATOR *//;
happy("gp found: $gp, $v");
@shortcuts = split "\n", `echo '?\\' | $gp -q --test`;
#
my ($e) = `$gphelp -raw addprimes`;
if ($e eq "") { fatal( "gphelp not found"); }
happy("gphelp found: $gphelp");
if (-f "$gphelp_translations")
{ happy("gphelp translations found $gphelp_translations"); }
else
{ $gphelp_translations = ""; }
}
###########################################################################
# Sets up hash of lists %subsections. Keys are the sections of usersch3.tex
# Values are the list of corresponding subsections.
###########################################################################
sub initSubsections {
my($j, $key);
open IN, "<$USERSCH3_TEX"
or fatal("Cannot open $USERSCH3_TEX: fix the --base argument");
$j = 1; $key = "Dummy";
while () {
next if (/^%/);
if (s/\\section\{(.*?)\}//) {
$key = $1;
$subsections{$key} = [];
$sections{$j} = $key; $j++;
$fill{$key} = cleanid($key);
}
if (/\\label\{([^}]*)}/) {
die "duplicate label: $1" if ($sublabel{$1});
$sublabel{$1} = $fill{$key};
}
if( s/\\subseckbd\{(.*?)\}//) {
$id = $1;
}
elsif( s/\\subsecidx\{(.*?)\}//) {
$id = $1;
}
elsif( s/\\subsec\{(.*?)\}//) {
$id = $1;
$id =~ s/\$\(.*//; # remove arguments
$id =~ s/\\//g;
}
else { next; }
push @{ $subsections{$key} }, $id;
next if ($id =~ / /); # keep only keywords for index, not all subsections
next if ($id !~ /^([a-zA-Z])/); # remove operators
my ($letter) = uc($1);
push @{ $subsectionsByAl{$letter} }, "[$id]__($key)__\n";
}
close IN;
}
sub GPatEnd {
my ($A) = cleankey($a); $A = "ZZZ$A" if ($A =~ /GP/);
my ($B) = cleankey($b); $B = "ZZZ$B" if ($B =~ /GP/);
$A cmp $B;
}
# Writes index.html, the entry page for the reference documentation.
# Relies on the hash %subsection.
sub writeToC4Ref {
my ($HEAD) = $_[0];
my ($toc1, $toc2);
$toc1 = $toc2 =''; $z = 0;
for my $key (sort GPatEnd keys %subsections) {
0 == $z and $toc1 .= "
__UP_TO_HERE__
printHTML("toc.html", "Table of Contents", 'style="background-image:url(toc.jpg)"', $txt);
}
sub cleankey { my ($k) = $_[0];
$k =~ s/\$//g;
$k =~ s/\\bs/\\/g;
$k =~ s/\\%/%/g;
$k =~ s/\\pow/\^/g;
$k;
}
sub cleanid { my ($k) = $_[0];
$k =~s/\+/plus/g;
$k =~s/\-/minus/g;
$k =~s/\\/backslash/g;
$k =~s/\//slash/g;
$k =~s/\%/percent/g;
$k =~s/\*/star/g;
$k =~ s/[^a-zA-Z0-9]/_/g;
$k;
}
#############################################################################
# Writes, for each list of subsection titles pointed to by $key, an html file
# cont_$key.html. This is a collection of links to the respective entries in
# $key.html. Uses the hash %subsection.
# Call in the form writeFunctionsByCategory($key)
#############################################################################
sub writeFunctionsByCategory {
my($key, $txt, @A);
$key = $_[0];
for my $item (@{$subsections{$key}}) {
my ($a, $b) = (cleanid($item), cleankey($item));
push(@A, "$b");
}
my ($cleankey) = cleankey($key);
$txt = "\n
Index: $cleankey
\n"
. '
'
. join(",\n", @A)
. "\n
";
printHTML("cont_$fill{$key}.html", "$cleankey", '', $txt);
}
############################################################################
# Writes function_index.html. This is a collection of links to the respective
# entries in the entry pages. Uses the hash %subsectionsByAl.
# Call in the form writeIndex(number_of_columns)
############################################################################
sub writeIndex {
my ($nCols, $HEAD) = @_;
my ($txt);
$txt = $HEAD . "
Index
\n"
.'
'."\n";
for my $letter (sort keys %subsectionsByAl) {
$txt .= "
\n
$letter
\n";
my ($z) = 1;
for my $item (sort @{$subsectionsByAl{$letter}}) {
$item =~ /^\[(.*?)\]__\((.*?)\)__$/;
if ($z == $nCols) { $z = 1; $txt .= "
";
printHTML('function_index.html', 'Index', '', $txt);
}
sub writeModRewrite {
my ($txt, %H);
for my $key (sort keys %subsections) {
my ($F) = "$fill{$key}.html";
$H{$key} = "$F";
for my $item (sort @{ $subsections{$key} }) {
my ($a) = cleanid($item);
$H{$item} = "$F#$a";
$txt .= "$a $F#$a\n";
}
}
if ($gphelp_translations)
{
open IN, "<$gphelp_translations";
while ()
{
next if (/@[0-9]$/);
m/^([^ ]*) *@(.*)$/;
my ($v) = $H{$2}; next if (!$v);
$txt .= "$1 $v\n";
}
}
my ($f) = "ModRewrite-table";
open OUT, ">$HTML/$f" or fatal("Cannot create the file $HTML/$f\n");
print OUT $txt;
close(OUT);
}
############################################################################
# Writes, for each letter the file cont_$letter.html. This is a collection of
# links to the respective entries in the entry pages.
# Uses the hash %subsectionsByAl.
# Call in the form writeFunctionsByAlphabet( $letter)
############################################################################
sub writeFunctionsByAlphabet {
my ($letter) = $_[0];
my ($txt) = "\n
__UP_TO_HERE__
printHTML('keyboard_shortcuts.html', 'GP Keyboard Shortcuts', '', $t);
}
# write GP readline introduction
sub writeReadline {
my ($t) = "
GP Line Editor: Readline
\n";
my ($e) = get_entry("readline");
$t .= $e;
printHTML('readline.html', 'GP Keyboard Shortcuts', '', $t);
}
# write GP operators section
sub writeOperators {
my ($t) = "
GP Operators and their Priorities
\n";
my ($e) = get_entry("operator");
$t .= $e;
printHTML('operators.html', 'GP Operators', '', $t);
}
###########################################################################
# Writes, for each list pointed to by $key, a file $key.html containing the
# subsections of the corresponding section in usersch3.tex. Needs %subsections
# and uses "gphelp -raw to convert subsections of usersch3.tex into html.
# Use in the form writeEntries($key)
###########################################################################
sub writeEntries() {
my ($key) = $_[0];
my ($cleankey) = cleankey($key);
print STDERR " writing: $cleankey\n";
# desambiguate between keywords belonging to 2 sections, e.g. 'log'
my ($pre) = ($cleankey eq "GP defaults")? "se:def,": "";
my ($e, $names) = get_entry("$key");
my ($txt) = "\n$names
$cleankey
\n\n";
$txt .= $e; # initial text
if ($e) { $txt .= "\n" }
for my $item (@{ $subsections{$key} }) {
my ($a) = cleanid($item);
my ($e,$names,$title) = get_entry("$pre$item");
$txt .= "$names\n$title\n$e\n\n";
}
printHTML( "$fill{$key}.html", "$cleankey", '', $txt);
}
# auxilliary for writeData
sub printFile { my($skin, $Mode, $data, $parm) = @_;
# all skins
return if (!$Mode);
if ($Mode eq 'TXT') { printTXT(@{$parm}, $data); return; }
# no html in ref mode
if ($Mode eq 'HTML') { printHTML(@{$parm}, $data) if (!$skin); return; }
# PIC: filter out unneeded icons according to skin
my ($f) = @{$parm}; # filename
return if ($skin && ($f eq 'empty.jpg' || $f eq 'toc.jpg'));
return if (!$skin && ($f eq 'home.gif' || $f eq 'top.gif'));
$data =~ s/\s//g; printPIC(@{$parm}, $data);
}
################################################################
# Writes html pages and images described in file FILE. See below
# __DATA__ for the description syntax.
# Call in the form writeData (*FILEHANDLE, $skin) 1 for ref/0 else
################################################################
sub writeData {
my ($IN, $skin) = @_;
my($Mode, @parm, $data);
$Mode = '';
while (<$IN>) {
if (/^\s*\@PIC\{\s*(.*?)\s*\}/) {
@parm = ($1);
$data = ''; $Mode = 'PIC'; next;
}
if (/^\s*\@HTML\{\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\}/) {
@parm = ($1, $2, $3);
$data = ''; $Mode = 'HTML'; next;
}
if (/^\s*\@TXT\{\s*(.*?)\}/)
{
@parm = ($1);
$data = ''; $Mode = 'TXT'; next;
}
if (/\@DONE/) {
# print "writing $parm[0]\n";
printFile($skin, $Mode, $data, \@parm);
$Mode = ''; next;
}
next if (!$Mode);
# eval. variables in DATA section
if ($Mode eq 'HTML') { s/\$(\w+)/${$1}/g; };
$data .= $_; next;
}
}
##################################################################
# Writes an html page to file $HTML/$f. Call in the form
# printHTML($name_of_file, $title_of_page, $background, $contents)
# with properly initialized scalar arguments.
# If $content starts by