1#!/usr/bin/perl -w
2##
3# gphelp originally written by Niels Skoruppa for pariGUIde; forked and
4# maintained by Karim Belabas (since v 1.7, 2002)
5#
6# This script generates html documentation of the gp/pari functions
7# on using the tex documentation as given in chapter 3 of the users manual.
8# Currently this is a workaround since there seems to exist no reasonable
9# plain TeX to html converter. Here we just take the outputs of
10# gphelp -raw and translate them into html form. It will be easy to replace,
11# in the following code, the use of this function by a more powerful tex2html
12# translator.
13#
14# Usage: gphtml [--dist|--4gui|--base=BASE|--out=OUT|--subsections]
15#
16# Without any option this will create, in the directory where you
17# called, a subdirectory named html, and therein the html documentation.
18# --base=BASE: where to find PARI's toplevel (mandatory)
19# --out=OUT: where to output our pages
20# --dist : add this file and a tar archive of html to html.
21# --4gui : creates the reference docs for pariguide.
22# The other options are for debugging purposes or consistency checks only.
23#
24# Adjust the three pathes below (look for AdJuSt).
25#########################################################################
26
27#use strict 'vars';
28
29my ($USERSCH3_TEX,
30#    $HTML, $DATE, $version,
31    $distFlag, $guiFlag, $subsectionsFlag,
32    %pics, %basicFrames, %subsections, %sections, %subsectionsByAl, %fill,
33    %sublabel, %tr, %html,
34    @ou, @shortcuts,
35    );
36
37$DATE = localtime();
38
39##############
40# AdJuSt these
41##############
42$base = "/usr/local/src/pari"; # the toplevel PARI/GP sources
43
44#########################
45# Parse the argument line
46#########################
47$distFlag = $guiFlag = $subsectionsFlag = 0;
48for (@ARGV) {
49  /--dist/        and do { $distFlag = 1; next;};
50  /--4gui/        and do { $guiFlag = 1; next;};
51  /--subsections/ and do { $subsectionsFlag = 1; next;};
52  /--base=(.*)/   and do { $base = $1; next;};
53  /--out=(.*)/    and do { $HTML = $1; next;};
54  &usage;
55}
56my ($HTMLdft) = $guiFlag? "./ref": "./html";
57if (!$HTML) { $HTML = $HTMLdft; }
58$ENV{'GPHELP_DOCDIR'} = "$base/doc";
59$USERSCH3_TEX = "$base/doc/usersch3.tex";
60$gphelp       = "$base/doc/gphelp";
61
62sub usage {
63  print STDERR "Usage: $0 [--base=BASE|--out=OUT|--dist|--4gui|--subsections]\n";
64  exit( 0);
65}
66
67# We see first what information the system has about pari/gp and collect it
68initVersionAndShortcuts();
69initSubsections();
70
71# If we only want to list the subsections of usersch3.tex, then this
72sub dbgSections {
73  for my $k (sort keys %sections) { print "$k $sections{$k}\n"; }
74  for my $k (sort keys %subsections) {
75    print "\n\n $k\n\n";
76    for my $i (@{ $subsections{$k} }) { print "\t$i\n"; }
77  }
78}
79if ($subsectionsFlag) { dbgSections(); exit(0); }
80
81initFixedData();
82
83system( "mkdir -p $HTML");
84#######################################################################
85# Here we write all *.html files of the pariguide doc
86#######################################################################
87if ($guiFlag) {
88  my ($HEAD) = <<"__UP_TO_HERE__";
89<table class="reftop">
90<tr>
91<td id="top"><b>Pari/GP Reference Documentation</b></td>
92<td class="right"><a href="index.html"
93  ><img alt="HOME" src="./home.gif" />&nbsp;Contents</a>
94 - <a href="function_index.html">Global index</a>
95 - <a href="keyboard_shortcuts.html">GP keyboard shortcuts</a></td>
96</tr>
97</table><br/>
98
99__UP_TO_HERE__
100
101  writeData(*DATA, 1); # icons
102  writeToC4Ref($HEAD); #toc
103  writeIndex(6, $HEAD); # function index using 6 columns,
104  # subsection pages,
105  for my $k (sort keys %subsections) { &writeEntries4Ref($k, $HEAD); }
106  # and meta commands.
107  writeShortcuts($HEAD);
108  exit(0);
109};
110
111#######################################################################
112# Here we write all *.html files, according to the
113# frame layout sketched in the data section below (after __DATA__ ).
114# Change look and feel by altering the descriptions in the data section.
115#######################################################################
116# Write basic frames
117writeData(*DATA, 0);
118writeToC();
119# ... and the pages for the frames "item" and "entry"
120for my $k (keys %subsections) {
121  writeFunctionsByCategory($k);
122  &writeEntries($k);
123}
124writeModRewrite();
125writeShortcuts("");
126writeOperators();
127writeReadline();
128for my $l (sort keys %subsectionsByAl) { writeFunctionsByAlphabet($l) }
129if ($distFlag)
130{ system("cp gphtml $HTML; H=`basename $HTML`; cd $HTML/..; tar cfz \$H.tgz \$H") }
131
132########### The subroutines ##################
133sub warning { print STDERR "\t\e[0;31m\e[1mWarning:\e[m ".$_[0]."\n"; }
134sub fatal { die "\t\e[0;31m\e[1mError:\e[m ".$_[0]."\n"; }
135sub happy { print STDERR "\t".$_[0]." ...... \e[0;32m\e[1m OK\e[m\n"; }
136sub unhappy { print STDERR "\t".$_[0]." ...... \e[0;31m\e[1m FAILED\e[m\n"; }
137
138###############################################################################
139# Sets ups $version and the list @shortcuts of GP keyboard shortcuts. Calls gp!
140# Checks if gphelp is available
141###############################################################################
142sub initVersionAndShortcuts {
143  my ($gp) = "$base/gp";
144  my ($v) = `$gp --version-short 2>&1`;
145  if ($v eq "") { fatal( "gp --version-short doesn't work"); }
146  chomp($v);
147  $version = "PARI/GP calculator, version $v";
148  happy("gp found ($gp, version $v)");
149  @shortcuts = split "\n", `echo '?\\' | $gp -q --test`;
150  #
151  my ($e) = `$gphelp -raw addprimes`;
152  if ($e eq "") { fatal( "gphelp not found"); }
153  happy("gphelp found ($gphelp)");
154}
155
156###########################################################################
157# Sets up hash of lists %subsections. Keys are the sections of usersch3.tex
158# Values are the list of corresponding subsections.
159###########################################################################
160sub initSubsections {
161  my($j, $key);
162
163  open IN, "<$USERSCH3_TEX"
164    or fatal("Cannot open $USERSCH3_TEX: fix the --base argument");
165
166  $j = 1; $key = "Dummy";
167  while (<IN>) {
168    next if (/^%/);
169    if (s/\\section\{(.*?)\}//) {
170      $key = $1;
171      $subsections{$key} = [];
172      $sections{$j} = $key; $j++;
173      $fill{$key} = cleanid($key);
174    }
175    if (/\\label\{([^}]*)}/) {
176      die "duplicate label: $1" if ($sublabel{$1});
177      $sublabel{$1} = $fill{$key};
178    }
179    if( s/\\subseckbd\{(.*?)\}//) {
180      $id = $1;
181    }
182    elsif( s/\\subsecidx\{(.*?)\}//) {
183      $id = $1;
184    }
185    elsif( s/\\subsec\{(.*?)\}//) {
186      $id = $1;
187      $id =~ s/\$\(.*//; # remove arguments
188      $id =~ s/\\//g;
189    }
190    else { next; }
191    push @{ $subsections{$key} }, $id;
192    next if ($id =~ / /); # keep only keywords for index, not all subsections
193    next if ($id !~ /^([a-zA-Z])/); # remove operators
194    my ($letter) = uc($1);
195    push @{ $subsectionsByAl{$letter} }, "[$id]__($key)__\n";
196  }
197  close IN;
198}
199
200sub GPatEnd {
201  my ($A) = cleankey($a); $A = "ZZZ$A" if ($A =~ /GP/);
202  my ($B) = cleankey($b); $B = "ZZZ$B" if ($B =~ /GP/);
203  $A cmp $B;
204}
205
206# Writes index.html, the entry page for the reference documentation.
207# Relies on the hash %subsection.
208sub writeToC4Ref {
209  my ($HEAD) = $_[0];
210  my ($toc1, $toc2);
211
212  $toc1 = $toc2 =''; $z = 0;
213  for my $key (sort GPatEnd keys %subsections) {
214    0 == $z and $toc1 .= "<tr>\n";
215    $toc1 .= "<td><a href=\"./$fill{$key}.html\">". cleankey($key) . '</a></td>' . "\n";
216    1 == $z and $toc1 .= "</tr>\n";
217    $z = 1 - $z;
218  }
219  1 == $z and $toc1 .= "<td>&nbsp;</td>\n</tr>";
220
221  for my $l (sort keys %subsectionsByAl) {
222    $toc2 .= "<a href = \"./function_index.html#$l\">$l</a>\n";
223  }
224
225  my ($txt) = <<"__UP_TO_HERE__";
226$HEAD
227<h3>Functions by Category</h3>
228<table class="toc">
229$toc1
230</table>
231
232<h4><a href="./keyboard_shortcuts.html">GP Keyboard Shortcuts</a></h4><br/>
233
234<h3>Functions in Alphabetical Order</h3>
235$toc2
236<br><hr><br>
237<small>
238Catalogue of Functions for the $version.
239<br>
240(generated by gphtml on $DATE.)</small>
241__UP_TO_HERE__
242
243  printHTML("index.html", "Table of Contents", '', $txt);
244}
245
246# Writes toc.html. Relies on the hash %subsection.
247sub writeToC {
248  my($txt, $toc1, $toc2);
249
250  $toc1 = $toc2 ='';
251  for my $key (sort GPatEnd keys %subsections) {
252    die "Unknown subsection: $key" if (!defined($fill{$key}) );
253    $toc1 .= "<A href=\"./cont_$fill{$key}.html\" target=\"itemFrame\" "
254      . "onClick=\"parent.entryFrame.location='$fill{$key}'\">"
255      . cleankey($key) . "</A>\n<HR>\n";
256  }
257  for my $l (sort keys %subsectionsByAl) {
258    $toc2 .= "&nbsp;<A href=\"./cont_$l.html\" target=\"itemFrame\">$l</A>\n";
259  }
260
261  $txt = <<"__UP_TO_HERE__";
262<div class="center">
263<A href="https://pari.math.u-bordeaux.fr/" target="_top">
264<img alt="Pari/GP Home Page" src="https://pari.math.u-bordeaux.fr/site_icons/Logo_PARI-GP_Couleurs_L150px.png"></A>
265</div>
266
267<div class="left">
268<H4>Functions by Category</H4>
269<small>
270$toc1
271<A href="./operators.html" target="entryFrame">GP operators</A>
272<hr>
273<A href="./readline.html" target="entryFrame">GP line editor: readline</A>
274<hr>
275<A href="./keyboard_shortcuts.html" target="entryFrame">GP keyboard shortcuts</A>
276</small>
277<hr>
278
279<H4>Functions in Alphabetical Order</H4>
280<div style="font-size: 80%; text-align: justify;">
281$toc2
282</div>
283</div>
284__UP_TO_HERE__
285
286  printHTML("toc.html", "Table of Contents", 'style="background-image:url(toc.jpg)"', $txt);
287}
288
289sub cleankey { my ($k) = $_[0];
290  $k =~ s/\$//g;
291  $k =~ s/\\bs/\\/g;
292  $k =~ s/\\%/%/g;
293  $k =~ s/\\pow/\^/g;
294  $k;
295}
296sub cleanid  { my ($k) = $_[0];
297  $k =~s/\+/plus/g;
298  $k =~s/\-/minus/g;
299  $k =~s/\\/backslash/g;
300  $k =~s/\//slash/g;
301  $k =~s/\%/percent/g;
302  $k =~s/\*/star/g;
303  $k =~ s/[^a-zA-Z0-9]/_/g;
304  $k;
305}
306
307#############################################################################
308# Writes, for each list of subsection titles pointed to by $key, an html file
309# cont_$key.html. This is a collection of links to the respective entries in
310# $key.html. Uses the hash %subsection.
311# Call in the form writeFunctionsByCategory($key)
312#############################################################################
313sub writeFunctionsByCategory {
314  my($key, $txt, @A);
315  $key = $_[0];
316
317  for my $item (@{$subsections{$key}}) {
318    my ($a, $b) = (cleanid($item), cleankey($item));
319    push(@A, "<A href=\"$fill{$key}.html#$a\" target=\"entryFrame\">$b</A>");
320  }
321  my ($cleankey) = cleankey($key);
322  $txt = "\n<h3 class=\"center\">Index: $cleankey</h3>\n"
323       . '<div style="font-size: 80%; text-align: justify;">'
324       . join(",\n", @A)
325       . "\n</div>";
326  printHTML("cont_$fill{$key}.html", "$cleankey", '', $txt);
327}
328
329############################################################################
330# Writes function_index.html. This is a collection of links to the respective
331# entries in the entry pages. Uses the hash %subsectionsByAl.
332# Call in the form writeIndex(number_of_columns)
333############################################################################
334sub writeIndex {
335  my ($nCols, $HEAD) = @_;
336  my ($txt);
337  $txt = $HEAD . "<h3 class=\"left\">Index</h3>\n"
338               .'<table class="index">'."\n";
339  for my $letter (sort keys %subsectionsByAl) {
340    $txt .= "<tr>\n<td id=\"$letter\"><b>$letter</b></td>\n";
341    my ($z) = 1;
342    for my $item (sort @{$subsectionsByAl{$letter}}) {
343      $item =~ /^\[(.*?)\]__\((.*?)\)__$/;
344      if ($z == $nCols) { $z = 1; $txt .= "</tr>\n<tr>\n<td>&nbsp;</td>\n"; }
345      $txt .= "<td><A href=\"./$fill{$2}.html#$1\">$1</A></td>\n";
346      $z++;
347    }
348    for(; $z < $nCols; $z++) { $txt .= "<td>&nbsp;</td>\n"; }
349    $txt .= '</tr>'."\n";
350  }
351  $txt .= "</table>";
352  printHTML('function_index.html', 'Index', '', $txt);
353}
354
355sub writeModRewrite {
356  my ($f) = "ModRewrite-table";
357  my ($txt);
358  for my $letter (sort keys %subsectionsByAl) {
359    for my $item (sort @{$subsectionsByAl{$letter}}) {
360      $item =~ /^\[(.*?)\]__\((.*?)\)__$/;
361      $txt .= "$1 $fill{$2}.html#$1\n";
362    }
363  }
364  open OUT, ">$HTML/$f" or fatal("Cannot create the file $HTML/$f\n");
365  print OUT $txt;
366  close(OUT);
367}
368
369############################################################################
370# Writes, for each letter the file cont_$letter.html. This is a collection of
371# links to the respective entries in the entry pages.
372# Uses the hash %subsectionsByAl.
373# Call in the form  writeFunctionsByAlphabet( $letter)
374############################################################################
375sub writeFunctionsByAlphabet {
376  my ($letter) = $_[0];
377  my ($txt) = "\n<h3 class=\"center\">Index: $letter</h3></div>\n";;
378  for my $item (sort @{ $subsectionsByAl{$letter} }) {
379    $item =~ /^\[(.*?)\]__\((.*?)\)__$/;
380    $txt .=
381      "&nbsp;&nbsp;<A href=\"./$fill{$2}.html#$1\" target=\"entryFrame\">$1</A>\n";
382  }
383  printHTML("cont_$letter.html", "$letter", '', $txt);
384}
385
386sub refexpand { my ($c) = $_[0];
387  my ($p) = $sublabel{$c};
388  if (!$p)
389  {
390#    warning("missing label $c");
391    return $c;
392  }
393  "<a href=\"$p.html\#$c\"
394    onClick=\"parent.itemFrame.location='cont_$p.html'\">$c<\/a>";
395}
396sub keyrefexpand { my ($c) = $_[0];
397  my ($p) = $sublabel{'se:' . $c};
398  if (!$p) { return $c; }
399  "<a href=\"$p.html\#se:$c\"
400    onClick=\"parent.itemFrame.location='cont_$p.html'\">$c<\/a>";
401}
402
403sub get_entry {
404  my ($item) = @_;
405  my ($l, $r, $d, @names);
406  my (%trans0) = (
407#    '&' => '&amp;',
408    '<' => '&lt;',
409    '>' => '&gt;',
410    '~{O}' => '&Otilde;',
411    '\oplus' =>  '&bigoplus; ',
412    '\bigoplus' => ' &bigoplus; ',
413    '\bigsqcup' => ' &bigsqcup; ',
414    '\subset' => ' &subset; ',
415    '\otimes' => ' &bigotimes; ',
416    '\in' => ' &in; ',
417    '\bigotimes' => ' &bigotimes; ',
418    '\to' => ' &rightarrow; ',
419    '\triangleleft' => ' &triangleleft; ',
420    '\geq' => ' &geq; ',
421    '\leq' => ' &leq; ',
422    ':---@[gt]' => ' &longmapsto; ',
423    '---' => ' &mdash; ',
424  );
425  my (%trans) = (
426    '\{'         => '{',
427    '\}'         => '}',
428    '\langle'    => '&langle;',
429    '\rangle'    => '&rangle;',
430    '@0'         => '  ',
431    '@1'         => '',
432    '@2'         => '',
433    '@3'         => '',
434  );
435
436  my ($e, $title);
437  $e = `$gphelp -raw -noskip '$item'`;
438  ($e =~ /^'.*' not\ found !$/) and unhappy("\t$item");
439  # first kill TeX leftovers
440  $e =~ s/\\not *\\in\b/ \&notin; /gs;
441  for my $key (keys %trans0) {
442    $l = quotemeta($key); $r = $trans0{$key};
443    $e =~ s/$l/$r/gs;
444  }
445  $e =~ s/\_\{([^}]*)}/<sub>$1<\/sub>/g;
446  $e =~ s/\^\{([^}]*)}/<sup>$1<\/sup>/g;
447  # one letter subscripts, otherwise 't_MAT' & co gets mangled
448  $e =~ s/\_([a-zA-Z0-9])\b/<sub>$1<\/sub>/g;
449#  Too many mistakes: polynomials in verbatim code :-(
450#  $e =~ s/\^([a-zA-Z0-9])\b/<sup>$1<\/sup>/g;
451  $e =~ s/\^\*/<sup>*<\/sup>/g;  # this one is OK
452  my ($a, $b);
453  # symbols
454  $a = quotemeta('@[startword]');
455  $b = quotemeta('@[endword]');
456  $e =~ s/$a([a-zA-Z]*)$b/\&$1;/xg;
457  # calligraphic letters
458  $a = quotemeta('@[startbc]');
459  $b = quotemeta('@[endbc]');
460  $e =~ s/$a([A-Z])$b/\&$1scr;/g;
461  # blackboard bold letters
462  $a = quotemeta('@[startbi]');
463  $b = quotemeta('@[endbi]');
464  $e =~ s/$a([A-Z])$b/\&$1opf;/g;
465  # Fraktur
466  $a = quotemeta('@[startbg]');
467  $b = quotemeta('@[endbg]');
468  $e =~ s/$a([A-Za-z])$b/\&$1fr;/g;
469  #overline
470  $e =~ s/\\(overline|bar)\{([^}]*)\}/<span style="text-decoration:overline">$2<\/span>/g;
471  # <=, >=
472  $a = quotemeta('@[startcode]');
473  $b = quotemeta('@[endcode]');
474  $e =~ s/$a\@\[lt\]=$b/&leq;/g;
475  $e =~ s/$a\@\[gt\]=$b/&geq;/g;
476  $e =~ s/$a(\w+)$b/'@[startcode]' . keyrefexpand($1) . '@[endcode]'/gse;
477
478  $e =~ s/\@\[startref\]([^\@]*)\@\[endref\]/refexpand($1)/gse;
479  while ($e =~ s/\@\[label ([^\]]*)\]//) { push(@names,$1); }
480# TODO: Fix the dirty hack from here
481  # handle \bprog @com
482  $e =~ s/(\@1 *\@\[startcode\][^\@]*)\@\[endcode\]([^\n]*)\@\[startcode\]/$1 $2/gs;
483  # handle @com
484  $e =~ s/(\@0[^\@]*)\@\[endcode\]([^\n]*)\@\[startcode\]/$1 $2/gs;
485  $l = '\@1 *\@\[startcode\]'; $r = '</p><pre class="code">  ';
486  $e =~ s/$l/$r/gs;
487  $l = '\@[23] *\@\[endcode\]'; $r = '</pre><p>';
488  $e =~ s/$l/$r/gs;
489# to here.
490
491  for my $key (keys %trans) {
492    $l = quotemeta($key); $r = $trans{$key};
493    $e =~ s/$l/$r/gs;
494  }
495
496  # warn about leftovers
497  if ($e =~ /(\\[a-zA-Z]{3,})/)
498  { my ($w) = "$item: $1";
499    # silence false positive
500    if ($w ne 'se:def,TeXstyle: \right' &&
501        $w ne 'se:def,TeXstyle: \def' &&
502        $w ne 'ecppexport: \nFormat' &&
503        $w ne 'strtex: \pmatrix' &&
504        $w ne 'mspolygon: \usepackage' &&
505        $w ne 'msfarey: \documentclass'
506    ) { warning $w; }
507  }
508
509  # then make a nice header
510  $e =~ s/^\@\[startbold](.*?)\:\@\[endbold]\n\n/<p>/;
511  warning("no title: $item") if (!$1);
512  $title = "<h4>$1<\/h4>";
513  $title =~ s/, */, /g;
514
515  # now care for the @[] markers
516  for my $key (@ou) {
517    $l = quotemeta($tr{$key}); $r = $html{$key};
518    $e =~ s/$l/$r/gs;
519    $title =~ s/$l/$r/gs;
520  }
521
522  # finally break into paragraphs
523  $e =~ s/\n\n/\<\/p\>\n\<p\>/gs;
524
525  my ($names) = "";
526  for (@names) { $names .= "<div id=\"$_\"><\/div>\n"; }
527  return ($e, $names, $title);
528}
529
530sub writeEntries4Ref() {
531  my ($key, $HEAD) = @_;
532  my ($cleankey) = cleankey($key);
533  print STDERR "\twriting: $cleankey\n";
534  # desambiguate between keywords belonging to 2 sections, e.g. 'log'
535  my ($pre) = ($cleankey eq "GP defaults")? "se:def,": "";
536  my ($toc) = '';
537  for my $item (sort @{ $subsections{$key} }) {
538    my ($a, $b) = (cleanid($item), cleankey($item));
539    $toc .= "<a href=\"./$fill{$key}.html#$a\">$b</a>&nbsp;&nbsp;\n";
540  }
541
542  my ($txt) = <<"__UP_TO_HERE__";
543$HEAD
544<h2 class="left">$cleankey</h2><br/>
545
546<table class="ref">
547<tr><td colspan=2>
548$toc
549</td></tr>
550<tr><td colspan=2>&nbsp;</td></tr>
551__UP_TO_HERE__
552  my ($e, $names) = get_entry($key);
553  $txt .= "<tr><td colspan=2>$e</td></tr>";
554
555  for my $item (@{ $subsections{$key} }) {
556    my ($a, $b) = (cleanid($item), cleankey($item));
557    my ($e, $names) = get_entry("$pre$item");
558
559    $txt .= <<"__UP_TO_HERE__";
560<tr>
561<td class="refh" id="$a"><b>$b</b></td>
562<td class="refh right">
563<a href="./index.html"><img alt="HOME" src="./home.gif" /></a>&nbsp;&nbsp;
564<a href="#top"><img alt="TOP" src="./top.gif" /></a></td></tr>
565<tr><td class="ref" colspan=2>$e</td></tr>
566<tr class="spacer"><td class="ref" colspan=2></td></tr>
567__UP_TO_HERE__
568  }
569  $txt .= '</table>';
570
571  printHTML("$fill{$key}.html", "$key", '', $txt);
572}
573
574# write GP keyboard shortcuts
575sub writeShortcuts { my ($header) = @_;
576  my ($t,$t2) = ('','');
577  for (@shortcuts)
578  {
579    if (/^ *([^:].*) *: *(.*) *$/)
580    { $t .= "<tr><td class=\"shortcuts\">$1</td>" .
581                "<td class=\"shortcuts\">$2</td></tr>\n"; }
582    else
583    { $t2 .= $_; }
584  }
585  $t =<<"__UP_TO_HERE__";
586$header
587<h3>GP Keyboard Shortcuts</h3>
588$t2
589<table class="shortcuts">
590$t
591</table>
592__UP_TO_HERE__
593  printHTML('keyboard_shortcuts.html', 'GP Keyboard Shortcuts', '', $t);
594}
595# write GP readline introduction
596sub writeReadline {
597  my ($t) = "<h3>GP Line Editor: Readline</h3>\n";
598  my ($e) = get_entry("readline");
599  $t .= $e;
600  printHTML('readline.html', 'GP Keyboard Shortcuts', '', $t);
601}
602# write GP operators section
603sub writeOperators {
604  my ($t) = "<h3>GP Operators and their Priorities</h3>\n";
605  my ($e) = get_entry("operator");
606  $t .= $e;
607  printHTML('operators.html', 'GP Operators', '', $t);
608}
609
610###########################################################################
611# Writes, for each list pointed to by $key, a file $key.html containing the
612# subsections of the corresponding section in usersch3.tex. Needs %subsections
613# and uses "gphelp -raw to convert subsections of usersch3.tex into html.
614# Use in the form writeEntries($key)
615###########################################################################
616sub writeEntries() {
617  my ($key) = $_[0];
618
619  my ($cleankey) = cleankey($key);
620  print STDERR "\twriting: $cleankey\n";
621  # desambiguate between keywords belonging to 2 sections, e.g. 'log'
622  my ($pre) = ($cleankey eq "GP defaults")? "se:def,": "";
623  my ($e, $names) = get_entry("$key");
624  my ($txt) = "\n$names<h2 class=\"center\">$cleankey</h2>\n\n";
625  $txt .= $e; # initial text
626  if ($e) { $txt .= "<hr>\n" }
627  for my $item (@{ $subsections{$key} }) {
628    my ($a) = cleanid($item);
629    my ($e,$names,$title) = get_entry("$pre$item");
630    $txt .= "$names<div id=\"$a\"></div>\n$title\n$e\n<hr>\n";
631  }
632  printHTML( "$fill{$key}.html", "$cleankey", '', $txt);
633}
634
635# auxilliary for writeData
636sub printFile { my($skin, $Mode, $data, $parm) = @_;
637  # all skins
638  return if (!$Mode);
639  if ($Mode eq 'TXT') { printTXT(@{$parm}, $data); return; }
640  # no html in ref mode
641  if ($Mode eq 'HTML') { printHTML(@{$parm}, $data) if (!$skin); return; }
642  # PIC: filter out unneeded icons according to skin
643  my ($f) = @{$parm}; # filename
644  return if ($skin && ($f eq 'empty.jpg' || $f eq 'toc.jpg'));
645  return if (!$skin && ($f eq 'home.gif' || $f eq 'top.gif'));
646  $data =~ s/\s//g; printPIC(@{$parm}, $data);
647}
648
649################################################################
650# Writes html pages and images described in file FILE. See below
651# __DATA__ for the description syntax.
652# Call in the form writeData (*FILEHANDLE, $skin) 1 for ref/0 else
653################################################################
654sub writeData {
655  my ($IN, $skin) = @_;
656  my($Mode, @parm, $data);
657
658  $Mode = '';
659  while (<$IN>) {
660    if (/^\s*\@PIC\{\s*(.*?)\s*\}/) {
661      @parm = ($1);
662      $data = ''; $Mode = 'PIC'; next;
663    }
664    if (/^\s*\@HTML\{\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\}/) {
665      @parm = ($1, $2, $3);
666      $data = ''; $Mode = 'HTML'; next;
667    }
668    if (/^\s*\@TXT\{\s*(.*?)\}/)
669    {
670      @parm = ($1);
671      $data = ''; $Mode = 'TXT'; next;
672    }
673    if (/\@DONE/) {
674#      print "writing $parm[0]\n";
675      printFile($skin, $Mode, $data, \@parm);
676      $Mode = ''; next;
677    }
678    next if (!$Mode);
679
680    # eval. variables in DATA section
681    if ($Mode eq 'HTML') { s/\$(\w+)/${$1}/g; };
682    $data .= $_; next;
683  }
684}
685
686##################################################################
687# Writes an html page to file $HTML/$f. Call in the form
688# printHTML($name_of_file, $title_of_page, $background, $contents)
689# with properly initialized scalar arguments.
690# If $content starts by <FRAMESET> then no <BODY> tag is printed
691##################################################################
692sub printHTML { my ($f, $title, $bgd, $con) = @_;
693  my ($DTD);
694  if ($con =~ /^<FRAMESET/i)
695  { $DTD = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">'; }
696  else
697  {
698    $DTD = '<!DOCTYPE html>';
699    $con = "<body $bgd>$con</body>";
700  }
701  my ($meta) = '';
702  $meta = '<meta name="robots" content="noindex">' if ($f =~ /^cont_/);
703
704  open OUT, ">$HTML/$f" or fatal("Cannot create the file $HTML/$f\n");
705  print OUT <<"__UP_TO_HERE__";
706$DTD
707<html lang="en">
708<head>
709  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
710  <title>Catalogue of GP/PARI Functions: $title</title>
711
712  <meta name="author"       content="Karim Belabas">
713  <meta name="created"      content="$DATE">
714  <meta name="author-email" content="pari\@math.u-bordeaux.fr">
715  <meta name="keywords"     content="PARI, GP, DOC">
716  $meta
717  <link rel="stylesheet" href="/pari.css">
718  <link rel="stylesheet" href="./gphtml.css">
719</head>
720$con
721__UP_TO_HERE__
722  close OUT;
723}
724
725########################################################
726# Writes a stream of 2 digit hex values as chars to file
727# Call in the form printPIC( $file, $stream)
728########################################################
729sub printPIC { my ($f, $data) = @_;
730  open OUT, ">${HTML}/$f" or fatal( "Cannot create the file ${HTML}/$f\n");
731  $data =~ s/(..)/chr(hex($1))/ge;
732  print OUT $data;
733  close OUT;
734}
735sub printTXT { my ($f, $data) = @_;
736  open OUT, ">${HTML}/$f" or fatal( "Cannot create the file ${HTML}/$f\n");
737  print OUT $data;
738  close OUT;
739}
740
741################DO NOT ALTER BELOW THIS LINE #############################
742sub initFixedData
743{
744  @ou = qw(
745    nbrk
746    dollar
747    startbold endbold
748    startcode endcode
749    startpodcode endpodcode
750    startbi endbi
751    startit endit
752    startword endword
753    startlword endlword
754    pm
755    obr cbr
756    lt gt
757    agrave eacute uuml ouml
758  );
759#         dollar                                             => ignore
760#         nbrk                                               => ignore
761#         startbold endbold        -gp/pari functions        => boldface
762#         startcode endcode        -???                      => color
763#         startpodcode endpodcode  -???                      => go
764#startlink endlink                 -nix da in raw
765#startbcode endbcode               -nix da in raw
766#         startbi endbi            -blackboard boldface      => boldface
767#         startit endit            -optional argments        => underline
768#         startword endword        -greek letters            => color
769#         startlword endlword      -math.abbrev. like $\log$ => ignore
770#         pm                       -+-                       =>
771#empty gt lt podleader             -nix da in raw            => ignore
772#
773# Neu in parigp.2.1.1:
774#         obr cbr                                            => { }
775#         lt gt                                              => < >
776#	  agrave eacute uuml ouml                            => &agrave; ...
777
778  @tr{@ou} = map "\@[$_]", @ou;
779
780  %html = (
781    nbrk         => '&nbsp;',
782    startbold    => '<b>',
783    endbold      => '</b>',
784    startcode    => '<code>',
785    endcode      => '</code>',
786    startpodcode => '',
787    endpodcode   => '',
788    startbi      => '<b>',
789    endbi        => '</b>',
790    startit      => '<em>',
791    endit        => '</em>',
792    startword    => '<font color=#FF0000>',
793    endword      => '</font>',
794    dollar       => '',
795    startlword   => '',
796    endlword     => '',
797    pm           => '&#177;',
798    obr          => '{',
799    cbr          => '}',
800    lt           => '&lt;',
801    gt           => '&gt;',
802    agrave       => '&agrave;',
803    eacute       => '&eacute;',
804    uuml         => '&uuml;',
805    ouml         => '&uml;',
806  );
807}
808
809__DATA__
810
811Layout of frames:
812=================
813
814         / empty empty empty empty
815        /              item
816 index <   empty toc   ----- empty
817        \              entry
818         \ empty empty title empty
819
820@HTML{index.html, Main Page,}
821<FRAMESET COLS="1%,280,*,1%" ROWS="1%,91%,8%" BORDER=0 FRAMEBORDER="no" FRAMESPACING=0>
822<FRAME src="empty.html" scrolling="no" style="border:none">
823<FRAME src="empty.html" scrolling="no" style="border:none">
824<FRAME src="empty.html" scrolling="no" style="border:none">
825<FRAME src="empty.html" scrolling="no" style="border:none">
826
827<FRAME src="empty.html" scrolling="no" style="border:none">
828<FRAME src="toc.html" style="border:none">
829<FRAMESET rows="140,*" border=0 frameborder="yes" framespacing=0>
830<FRAME name="itemFrame"   src="item.html">
831<FRAME name="entryFrame"  src="entry.html">
832</FRAMESET>
833<FRAME src="empty.html" scrolling="no">
834
835<FRAME src="empty.html" scrolling="no">
836<FRAME src="empty.html" scrolling="no">
837<FRAME src="title.html" scrolling="no">
838<FRAME src="empty.html" scrolling="no">
839</FRAMESET>
840@DONE
841
842@HTML{empty.html, Empty Page :-), style="background-image:url(empty.jpg)"}
843@DONE
844
845@HTML{title.html, Title Page, style="background-image:url(empty.jpg)"}
846Catalogue of Functions for the $version.
847<br>
848<small>(generated by gphtml on $DATE.)</small>
849@DONE
850
851@HTML{item.html, Items Page, style="background-color:#FFFFFF;"}
852@DONE
853
854@HTML{entry.html, Welcome Page, style="background-color:#FFFFFF;"}
855<br><br>
856<center>
857<h2>This is an html documentation of<br>
858functions available under the $version.</h2>
859</center>
860<br>
861Comments and proposals for improvement
862<a href="mailto:pari@math.u-bordeaux.fr">
863are welcome</a>.
864<br>
865<br>
866You can <a href="../$HTML.tgz">download these html files</a> (as gzipped tar
867file) or generate them by yourself using the perl script
868<a href="../gphtml">gphtml</a> (provided perl, gp, gphelp and the gp/pari tex
869documentation file usersch3.tex are installed on your system).
870@DONE
871
872@PIC{empty.jpg}
873ffd8ffe000104a46494600010101004800480000fffe0017437265617465642077697468205468652047494d50ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27393d38323c2e333432ffdb0043010909090c0b0c180d0d1832211c213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232ffc0001108000a000a03012200021101031101ffc4001500010100000000000000000000000000000006ffc40014100100000000000000000000000000000000ffc4001501010100000000000000000000000000000506ffc40014110100000000000000000000000000000000ffda000c03010002110311003f00b800c261ffd9
874@DONE
875
876@PIC{toc.jpg}
877ffd8ffe000104a46494600010101004800480000fffe0017437265617465642077697468205468652047494d50ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27393d38323c2e333432ffdb0043010909090c0b0c180d0d1832211c213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232ffc00011080014011803012200021101031101ffc40017000101010100000000000000000000000002000106ffc4001510010100000000000000000000000000000001ffc40017010101010100000000000000000000000002010506ffc4001511010100000000000000000000000000000001ffda000c03010002110311003f00ee0a0946c399850861094694128850a10c242850a0c28250a3632362142282510a142830a2146c3810e2146c2184250a1418510a146c646c42850a0c282508a09442850a0c28851b0a0c28850a10c24285128909c01449aae76142484a34a24850a124850a14484a146c490a114490a142892146c3892146c2484a1428921428d8921428512128451242850a24851b0a24850a124850a24909ffd9
878@DONE
879
880@PIC{home.gif}
88147494638396110000d00b30000000000664433995522444444bb6644bb8866aa8888ccbb88bbccddddddddddbb99ffddbbffffddddeeffc0c0c0ffffff21f9040100000c002c0000000010000d0040042c90c949ab7429eb9d9cbf5cd84d5e699614b6391673bedee88a2b4b9a2d18be3a9db12a5acc1614a17a464604003b
882@DONE
883
884@PIC{top.gif}
8854749463839610f000b00f10300000000c0c0c0ddddddffffff21f90401000003002c000000000f000b0000025edcb871e3c28d1b376edcb871a1c28d1b376edcb850a2c28d1b376e5c2851a2c28d1b372e942851a2c28d1b17268c283161c28d1b372e94a870e3c68d1b3746949871e3c68d1b174a54b871e3c68d1b234accb871e3c68d0b1326dcb87105003b
886@DONE
887
888@TXT{gphtml.css}
889table { width: 100%; }
890img { border: 0px; }
891
892table.ref { padding: 0px; border-spacing: 0px; background-color: #FFFFEE;
893            border: 0px;}
894td.refh { padding: 4px; background-color: #EEEEAA; }
895tr.spacer { background-color:#FFFFFF; height: 6px; }
896table.reftop { padding: 2px; border-spacing: 0px; background-color: #83a2ef;
897            border: 0px; }
898table.toc { padding: 0px; border-spacing: 0px; border: 0px }
899table.index { padding: 4px; border-spacing: 0px; border: 0px }
900
901.shortcuts { padding: 5px; border-spacing: 0; background-color: #83a2ef;
902             border: 1px solid black;}
903table.shortcuts { border-collapse: collapse; width: 80%; }
904
905.right { text-align:right; }
906.center { text-align:center; }
907.left { text-align:left; }
908@DONE
909