Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563641 views
1
#!/usr/bin/perl -w
2
#
3
# Script to convert GAP manual TeX files to HTML
4
# Usage:
5
# convert.pl [-csti] [-f <frontpage>] [-n <sharepkg>] <doc-dir> [<html-dir>]
6
#
7
# Requirements: Perl (might need to edit the first line of this file)
8
# TtH is not strictlty necessary but very desirable to treat
9
# formulas.
10
#
11
# Caveats:
12
#
13
# 1. This script assumes that the .toc, .lab and .bbl files are up-to-date
14
# with the .tex files and will almost certainly fail horribly if they
15
# are not.
16
#
17
# 2. The output files are CxxxSxxx.htm, (not .html) plus chapters.htm,
18
# theindex.htm and biblio.htm, except when called with the -c option
19
# (in which case, there are CHAPxxx.htm files instead of CxxxSxxx.htm).
20
# A (front page) file index.htm is assumed, but not created.
21
# Not all servers will serve .htm files as HTML without adjustments.
22
#
23
# 3. The script assumes that the .tex files comply with GAP conventions,
24
# including unwritten ones. It tries to follow the behaviour of TeX
25
# assuming those conventions. The on-line browser attempts to provide
26
# an ASCII equivalent. See BUGS.
27
#
28
# 4. The hierarchy of the HTML manuals assumed is of the following form:
29
#
30
# <GAPDIR>/
31
# doc/
32
# htm/
33
# <main>
34
# pkg/
35
# <pkg>/
36
# htm
37
#
38
# for each main manual <main> (in: ref, ext, tut, prg, new) and each
39
# share package <pkg>. To make inter-linking between manuals work,
40
# one should generally use the -c option for everything, (or not use
41
# it for everything). Linking to share package manuals from the main
42
# manual can only be expected to work if the share package manuals
43
# are created using this converter.
44
#
45
# 5. Only the manual.lab files for books that are referenced via the
46
# \UseReferences and \UseGapDocReferences commands in the manual.tex
47
# file of the book being converted (and the book's own manual.lab
48
# file, of course) are read. Make sure all the \UseReferences and
49
# \UseGapDocReferences commands needed are present! (The TeX-produced
50
# manuals will be missing lots of cross-references also, if some are
51
# missing.) You will get `Bad link' messages if you have some missing.
52
#
53
# Options:
54
#
55
# -c file-per-chapter mode: Generates one HTML file CHAPxxx.htm
56
# for each chapter; sections are level 2 headings and anchors
57
# CHAPxxx.htm#SECTxxx.
58
# This is intended for local browsing, especially under MS-DOS.
59
# It may be used with the -n (share package) option.
60
#
61
# -f <frontpage>
62
# Adds a "Top" link to link <frontpage> to each manual page,
63
# only available if -n option is also used.
64
#
65
# -s silent running: Conversational messages are suppressed.
66
#
67
# -n <sharepkg>
68
# We are not building the main manual but the one for the share
69
# package <sharepkg>. To get cross references to the main library
70
# right, it assumes that the share package is in the right place.
71
# The -c option may be used with this option.
72
#
73
# -i index: Only one index file is produced.
74
#
75
# -t tex-math: Runs `tth' (which must be installed on the local system)
76
# to produce better HTML code for formulae. (It would be possible to
77
# replace tth by another conversion, for example TeXexplorer, but
78
# (at least) the line calling `tth' would need to be modified.)
79
80
# -u Like -t, but uses `tth -u1' to produce unicode.
81
#
82
# <doc-dir> The directory where all the needed .tex, .toc, .lab and .bbl
83
# files are located.
84
#
85
# <html-dir> The directory (which should already exist) in which to put
86
# the generated .htm files. Defaults to the current directory,
87
# if omitted.
88
#
89
# Example usage:
90
# convert.pl -n mypkg doc htm # in directory .../pkg/mypkg
91
# convert.pl -t -n mypkg doc htm # ditto previous + use tth for maths
92
# convert.pl -t -n mypkg -c doc htm # ditto previous + 1 file per chapter
93
# convert.pl -t -c ../ref ref # (for Ref manual) in dir .../doc/htm
94
#
95
# FEATURES (and intended departures from the TeX behaviour)
96
# . Now interprets 2nd argument of an \atindex command if it is
97
# of form @... and ignores the first argument, or otherwise it
98
# interprets the first argument. Interprets ! as a comma and
99
# indices output have no sub-headers.
100
# . The @... component of \> commands is ignored. The assumption
101
# is that for: \>`...'{...}@{...} the @{...} component is just
102
# the {...} with font changes.
103
# . In a \beginitems ... \enditems environment everything is indented
104
# except for the item headers, rather than just the paragraph
105
# following the item header.
106
# . By default, the \beginlist ... \endlist environment is interpreted
107
# as a compact description list. By adding %unordered or %ordered...
108
# markup it will be interpreted as either an unordered or ordered
109
# list respectively (see the ext manual for details).
110
# . There are spacing differences e.g. \begintt ... \endtt etc.
111
# environments are not indented.
112
# . Supports all accents of TeX, in probably the best way currently
113
# possible with HTML.
114
# . Treats PseudoInput chapters in the `same' way as Input chapters.
115
# . With -t switch announces the version of TtH used.
116
# . Now supports %display{nontex}, %display{nontext} and
117
# %display{nonhtml} variants of %display environment.
118
# . References to subsections are now interpreted as one would expect.
119
#
120
# BUGS (and known departures from the TeX behaviour)
121
# . $a.b$ is only interpreted correctly in -t mode.
122
# . The citation keys that appear are the .bib file keys rather
123
# than the keys BibTeX constructs with the `alpha' bib-style.
124
#
125
# TODO
126
# . Refine macro_replace subroutine so it can also be used to purge
127
# 2nd arg of \atindex macros.
128
# . For -t mode, scan for \def commands in manual.tex and write
129
# to TTHIN (tthmacros.tex). Should we only look for a block
130
# demarcated by %mathsmacros ... %endmathsmacros ?
131
# These \def commands are only intended for such font
132
# changing commands as: \def\B{{\cal B}} (`tth' provides a
133
# script-type font).
134
# . Provide a table environment, if/when a \begintable ...
135
# \endtable environment is added to gapmacro.tex.
136
#
137
#############################################################################
138
139
# Check PERL version
140
#
141
$] > 5 or die "Needs perl 5";
142
143
use Getopt::Std;
144
145
146
#
147
# Global variables
148
#
149
# $dir -- the full pathname of the input directory, including a trailing /
150
# $odir -- the full pathname of the output directory, including a trailing /
151
# $opt_c and $opt_s set by getopts()
152
# @chapters -- the chapters data structure
153
# IN -- the current input file (outputfiles are handled by select)
154
# $footer -- the trailer put on every page
155
# $indexcount -- used within chapters to number the index anchors
156
# $lastnumchap -- number of last numerically numbered chapter
157
#
158
159
160
# These match chapter and section lines in a .toc file
161
#
162
163
$chapexp = '\\\\chapcontents\s+\{((?:\d+|[A-Z]))\}\s*\{(.+)\}\s*\{\d+\}';
164
$secexp = '\\\\seccontents\s+\{((?:\d+|[A-Z]))\.(\d+)\}\s*\{(.+)\}\s*\{\d+\}';
165
#$ignoreexp = '\\\\tocstrut|\\\\appno|\\\\seccontents\s+\{\d+\}';
166
$lastnumchap = 0;
167
168
# Variable that is set to 2 inside a nest of \itemitem s of a
169
# \beginlist ... \endlist environment
170
#
171
172
$listdepth = 0;
173
174
# This is augmented each time a line: \Package{...} is read in a manual.tex
175
# file, so that macro_replace knows to set a {\...} macro in sans-serif.
176
#
177
178
$sharepkg = "";
179
180
# The books converted to HTML with this converter
181
# The values set are: 0 or 1 according to whether or not -c was used.
182
#
183
184
%convertbooks = ();
185
186
# This is added to when scanning for \UseGapDocReferences.
187
#
188
189
%gapdocbooks = ();
190
191
# Types of href label are:
192
# 0 (non -c books) : C<MMM>S<NNN>.htm
193
# 1 (-c books) : CHAP<MMM>.htm#SECT<NNN>
194
# 2 (== $gapdoc) : chap<M>.html#s<N>ss0
195
#
196
# It would be nice to support subsections properly like GapDoc,
197
# but this involves creating a subsection data-structure modelled
198
# on section, which is a mite non-trivial (maybe ... if I find time).
199
# For now in-text references go to the beginning of the chapter.
200
#
201
202
$gapdoc = 2;
203
204
# sansserif:
205
#
206
# Used mainly to set GAP in sans serif font. Inside <title> ... </title>
207
# there should *not* be any tags, since they are not translated there by
208
# web browsers, and hence sansserif should *not* be applied to anything
209
# that ends up in the <title> ... </title> field, but *is* quite appropriate
210
# for the header in the <h1> ... </h1> field at the top of the body of an
211
# HTML file and anywhere else within the body of an HTML file.
212
#
213
sub sansserif {
214
my ($name) = @_;
215
return "<font face=\"Gill Sans,Helvetica,Arial\">$name</font>";
216
}
217
218
# booktitle_body:
219
#
220
# This is for generating the title of a document that goes in the
221
# <h1> ... </h1> field at the top of the body, as opposed to the title
222
# that goes in the <title> ... </title> field which should be unembellished.
223
#
224
sub booktitle_body {
225
my ($bktitle, @prog_or_pkg) = @_;
226
foreach $prog_or_pkg (@prog_or_pkg) {
227
$newstring = sansserif $prog_or_pkg;
228
$bktitle =~ s/$prog_or_pkg/$newstring/;
229
}
230
return $bktitle;
231
}
232
233
#
234
# used to standardize section names for use as hash indices.
235
#
236
237
sub canonize {
238
my ($key) = @_;
239
$key =~ tr/A-Z/a-z/;
240
$key =~ s/\s//g;
241
$key =~ s/\\//g;
242
$key;
243
}
244
sub kanonize {
245
my ($key) = @_;
246
$key =~ s/\\ / /g;
247
$key =~ s/!/ /g;
248
$key;
249
}
250
251
sub def_section_by_name {
252
my ($sec, $chapno, $secno, $ssecno) = @_;
253
my $secname = canonize $1;
254
if (defined $sections_by_name{$secname}) {
255
if (($sections_by_name{$secname}->{chapnum} ne $chapno) ||
256
($sections_by_name{$secname}->{secnum} ne $secno) ||
257
($sections_by_name{$secname}->{ssecnum} ne $ssecno)) {
258
print STDERR "Section: \"$secname\" already defined as: ",
259
"$sections_by_name{$secname}->{chapnum}.",
260
"$sections_by_name{$secname}->{secnum}.",
261
"$sections_by_name{$secname}->{ssecnum}\n";
262
print STDERR "Now being redefined as: $chapno.$secno.$ssecno\n";
263
$redefined_secname{$secname} = 1;
264
} else {
265
return;
266
}
267
}
268
$sections_by_name{$secname}
269
= {chapnum => $chapno,
270
secnum => $secno,
271
ssecnum => $ssecno};
272
# print STDERR "Defined section \"$secname\": $chapno.$secno.$ssecno\n";
273
}
274
275
sub tonum { # Needed since chanu may be A,B,... for appendices
276
my ($chanu) = @_;
277
return $chanu =~ /\d+/ ? $chanu : $lastnumchap + ord($chanu) - ord('A') + 1;
278
}
279
280
# getchaps:
281
#
282
# Scan the .tex and .toc files to get chapter names and numbers,
283
# section names and numbers and associated filenames.
284
# Loads up chapters and sections_by_name.
285
#
286
287
sub getchaps {
288
open( TOC, "<${dir}manual.toc" )
289
|| die "Can't open ${dir}manual.toc.\n You can " .
290
"create the .toc file by doing: tex manual (at least once).\n";
291
my ($chap,$sec,$chapno,$chap_as_sec,$chapnam,$chanu);
292
while (<TOC>) {
293
if ( /$chapexp/o ) {
294
$chapnam = $2;
295
$chanu = $1;
296
$lastnumchap = $chanu if ( $chanu =~ /\d+/ );
297
298
# remove `(preliminary)' part that messes everything up
299
$chapnam =~ s/ \(preliminary\)//g;
300
301
$chap = {name => $chapnam,
302
number => $chanu};
303
$chap_as_sec = {name => $chapnam,
304
chapnum => $chanu,
305
secnum => 0,
306
chapter => $chap};
307
$chap->{sections}[0] = $chap_as_sec;
308
defined ($chapters[tonum $chanu]) && die "chapter number repeated";
309
$chapters[tonum $chanu] = $chap;
310
} elsif ( /$secexp/o ) {
311
defined ($chapters[tonum $1])
312
|| die "section $2:$3 in unknown chapter $1";
313
defined ($chapters[tonum $1]{sections}[$2])
314
&& die "section number repeated";
315
$sec = {name => $3,
316
secnum => $2,
317
chapnum => $1,
318
chapter => $chapters[tonum $1]};
319
$chapters[tonum $1]{sections}[$2] = $sec;
320
# this would produce warnings from empty chapters. Thus ignore.
321
# } elsif ( $_ !~ /$ignoreexp/o ) {
322
# print STDERR "Bad line: $_";
323
}
324
}
325
close TOC;
326
open (TEX, "<${dir}manual.tex") || die "Can't open ${dir}manual.tex";
327
$chapno = 0;
328
while (<TEX>) {
329
if ( /^[^%]*\\(|Pseudo)Input\{([^}]+)\}(\{([^}]+)\}\{([^}]+)\})?/ ) {
330
if (not -f "$dir$2.tex" or not -r "$dir$2.tex") {
331
print STDERR "Chapter file $2.tex does not exist in $dir\n";
332
}
333
if ($1 eq "") {
334
$chapters[++$chapno]{file} = $2;
335
} else {
336
$chapnam = $5;
337
$chanu = ++$chapno;
338
$lastnumchap = $chanu;
339
340
$chap = {name => $chapnam,
341
number => $chanu};
342
$chap_as_sec = {name => $chapnam,
343
chapnum => $chanu,
344
secnum => 0,
345
ssecnum => 0,
346
chapter => $chap};
347
if ($4 ne $5) {
348
def_section_by_name("$book:$chapnam", $chanu, 0, 0);
349
add_to_index(htm_fname($opt_c,$chanu,0),
350
$4, $chap_as_sec, 0);
351
}
352
353
$chap->{sections}[0] = $chap_as_sec;
354
defined($chapters[$chanu]) && die "chapter number repeated";
355
$chapters[$chanu] = $chap;
356
$chapters[$chanu]{file} = $2;
357
}
358
}
359
}
360
close TEX;
361
}
362
363
sub getlabs {
364
my ($bkdir) = @_;
365
open (LAB, "<${bkdir}manual.lab") || print "Can't open ${bkdir}manual.lab";
366
while (<LAB>) {
367
if ( /\\setcitlab/ ) {
368
next; # We don't get the bibliography labels from here
369
} elsif (/\\makelabel\s*\{([^}]+)\}\s*\{(\w+)(\.(\d+))?(\.(\d+))?\}/) {
370
def_section_by_name($1, $2, (defined($3) ? $4 : 0),
371
(defined($5) ? $6 : 0));
372
} else {
373
chomp;
374
print STDERR "Ignored line: $_\n... in ${bkdir}manual.lab\n";
375
}
376
}
377
close LAB;
378
}
379
380
#
381
# Mainly diagnostic, prints the chapters data structure. Also
382
# checks that each section has the correct back reference to its
383
# chapter
384
#
385
386
sub printchaps {
387
my @chapters = @_;
388
CHAP: foreach $chapter (@chapters) {
389
next CHAP unless (defined ($chapter));
390
print "Chapter $chapter->{number} $chapter->{name} $chapter->{file}\n";
391
SECT: foreach $section (@{$chapter->{sections}}) {
392
next SECT unless defined ($section);
393
print " Section $section->{chapnum}.$section->{secnum} $section->{name}\n";
394
if ($section->{chapter} ne $chapter ) {
395
print " loop problem\n";
396
}
397
}
398
399
}
400
}
401
402
# Printed at the bottom of every page.
403
$footer = "<P>\n" . sansserif( "GAP 4 manual<br>" . `date +"%B %Y"` ) .
404
"</body></html>";
405
406
# Section label ... this is the bit that goes after a # in an HREF link
407
# or is assigned to the value of NAME in an anchor.
408
#
409
sub sec_label {
410
my ($c_s_gapdoc,$cnum,$snum,$ssnum) = @_;
411
412
if ($c_s_gapdoc == $gapdoc) {
413
return "s${snum}ss${ssnum}";
414
}
415
416
$snum = "0" x (3 - length $snum) . $snum;
417
if ($c_s_gapdoc) {
418
if ($snum eq "000") {
419
return "";
420
} elsif ($ssnum) {
421
return "SSEC${snum}.$ssnum";
422
} else {
423
return "SECT${snum}";
424
}
425
} else {
426
return ($ssnum) ? "SSEC$ssnum" : "";
427
}
428
}
429
430
# The HREFs of subsections, sections and chapter files are determined by
431
# this routine directly if the chapter, section, subsection numbers are known.
432
sub htm_fname {
433
my ($c_s_gapdoc,$cnum,$snum,$ssnum) = @_;
434
435
my $seclabel = sec_label($c_s_gapdoc,$cnum,$snum,$ssnum);
436
$seclabel = "#$seclabel" if ($seclabel ne "");
437
438
if ($c_s_gapdoc == $gapdoc) {
439
return "chap${cnum}.html$seclabel";
440
}
441
442
$cnum = "0" x (3 - length $cnum) . $cnum;
443
$snum = "0" x (3 - length $snum) . $snum;
444
return ($c_s_gapdoc) ? "CHAP${cnum}.htm$seclabel"
445
: "C${cnum}S$snum.htm$seclabel";
446
}
447
448
# Returns the value that $opt_c must have had when the book $book
449
# was compiled with this converter.
450
sub hreftype {
451
my ($book, $bdir) = @_;
452
if ( !(exists $convertbooks{$book}) ) {
453
my @ls = `ls ${odir}$bdir`;
454
$convertbooks{$book}
455
= (grep { m/^CHAP...[.]htm$/ } @ls) ?
456
1 : # .htm files have shape CHAP<MMM>.htm
457
(grep { m/^CHAP...[.]htm$/ } @ls) ?
458
0 : # .htm files have shape C<MMM>S<NNN>.htm
459
$opt_c; # can't determine the shape ... don't exist
460
# yet ... we assume the shape of the current
461
# manual being compiled.
462
}
463
return $convertbooks{$book};
464
}
465
466
# The names of the section and chapter files are determined by this routine
467
# when one has to determine the chapter and section number indirectly.
468
sub name2fn {
469
my ($name,$ischap) = @_;
470
my $bdir = "";
471
my $c_s_gapdoc = $opt_c;
472
473
# : indicates a cross-volume reference
474
my $canon_name = canonize $name;
475
#print STDERR "canon_name = $canon_name\n";
476
if ( $canon_name =~ /^(ref|tut|ext|prg|new):/ ) {
477
if ($mainman==1) {
478
$bdir = "../$1/";
479
} else {
480
$bdir = "../../../doc/htm/$1/";
481
}
482
$c_s_gapdoc = hreftype($1, $bdir);
483
} elsif ($canon_name =~ /^([a-zA-Z_0-9]*):/ ) {
484
# presumably a package name
485
#print STDERR "package name = $1\n";
486
if ($mainman==1) {
487
if (exists $gapdocbooks{$1}) { # a main manual referring
488
$bdir = "../../../pkg/$1/doc/"; # to a GapDoc-produced manual
489
$c_s_gapdoc = $gapdoc;
490
} else {
491
$bdir = "../../../pkg/$1/htm/";
492
$c_s_gapdoc = hreftype($1, $bdir);
493
}
494
} elsif (exists $gapdocbooks{$1}) { # a package manual referring
495
$bdir = "../../$1/doc/"; # to a GapDoc-produced manual
496
$c_s_gapdoc = $gapdoc;
497
} else {
498
$bdir = "../../$1/htm/";
499
$c_s_gapdoc = hreftype($1, $bdir);
500
}
501
} elsif ($canon_name !~ /^($book):/) {
502
$name = "$book:$name";
503
$canon_name = canonize $name;
504
}
505
$name =~ s/\s+/ /g;
506
507
if (exists $redefined_secname{$canon_name}) {
508
print STDERR "Ref to multiply defined label: ",
509
"\"$name\" at line $. of $chap->{file}.tex\n";
510
}
511
my $sec = $sections_by_name{$canon_name};
512
513
unless (defined ( $sec)) {
514
print STDERR "Bad link: \"$name\" at line $. of $chap->{file}.tex\n";
515
return "badlink:$name";
516
}
517
return $bdir . htm_fname($c_s_gapdoc,
518
$sec->{chapnum},
519
($ischap == 1) ? 0 : $sec->{secnum},
520
($ischap == 1) ? 0 : $sec->{ssecnum});
521
}
522
523
524
# strip out the tag from cross book references for the body of links
525
sub name2linktext {
526
my $name;
527
($name) = @_;
528
$name =~ s/^(ref|tut|ext|prg|new)://;
529
return $name;
530
}
531
532
#
533
# Add an index entry to the index.
534
# ($hname = $fname or $fname#..., where $fname is a filename)
535
sub add_to_index {
536
my ($hname, $key, $sec) = @_;
537
my $secno = "$sec->{chapnum}.$sec->{secnum}";
538
if (defined $sec->{ssecnum} and $sec->{ssecnum}) {
539
$secno .= ".$sec->{ssecnum}";
540
}
541
push @{$index{$key}}, [ $hname, $secno ];
542
# print STDERR "hname = $hname, key = $key, ";
543
# print STDERR "sec = $secno\n";
544
}
545
546
#
547
# Create a label for an index entry, add it to the index if new,
548
# and return the label (which is an empty string if not new).
549
sub inxentry {
550
my ($fname,$key,$sec) = @_;
551
my $curs="$sec->{chapnum}.$sec->{secnum}";
552
# print STDERR "curs = $curs\n";
553
# print STDERR "fname = $fname, key = $key, ";
554
# print STDERR "sec = $sec->{chapnum}.$sec->{secnum}\n";
555
my $label = "<a name = \"I$indexcount\"></a>\n";
556
if (defined $index{$key}) {
557
my $ar;
558
foreach $ar (@{$index{$key}}) {
559
if ( ($ar->[1]) eq $curs ) {
560
$label=""; # index entry is not new
561
last;
562
}
563
}
564
} else {
565
$index{$key} = [];
566
}
567
if ($label ne "") {
568
add_to_index("$fname#I$indexcount", $key, $sec);
569
# print STDERR "$fname#I$indexcount\n";
570
$indexcount++;
571
}
572
return $label;
573
}
574
575
#
576
# Return a NAME anchor for a subsection
577
#
578
sub subsec_name {
579
my ($fname,$key,$sec) = @_;
580
# print STDERR "curs = $curs\n";
581
# print STDERR "sec = $sec->{chapnum}.$sec->{secnum}.$sec->{ssecnum}\n";
582
$key =~ s/!\{(.*)\}$/!$1/;
583
$key =~ s/\s+/ /g;
584
my $canon_name = canonize "$book:$key";
585
my $sec_of_key = $sections_by_name{$canon_name};
586
if (exists $redefined_secname{$key}) {
587
print STDERR "Multiply defined label: ",
588
"\"$key\" at line $. of $chap->{file}.tex\n",
589
"... subsection will be unreachable\n";
590
return "";
591
} elsif ($sec_of_key->{chapnum} ne $sec->{chapnum} ||
592
$sec_of_key->{secnum} ne $sec->{secnum}) {
593
print STDERR "Section of \"$key\" (",
594
"$sec_of_key->{chapnum}.$sec_of_key->{secnum}) ",
595
"doesn't agree with the current section (",
596
"$sec->{chapnum}.$sec->{secnum}) ",
597
"at line $. of $chap->{file}.tex\n",
598
"... subsection will be unreachable\n";
599
return "";
600
} else {
601
my $curs = "$sec_of_key->{chapnum}.$sec_of_key->{secnum}" .
602
".$sec_of_key->{ssecnum}";
603
my $label = sec_label($opt_c, $sec_of_key->{chapnum},
604
$sec_of_key->{secnum},
605
$sec_of_key->{ssecnum});
606
if (defined $index{$key}) {
607
my $ar;
608
foreach $ar (@{$index{$key}}) {
609
if ( ($ar->[1]) eq $curs ) {
610
return ""; # index entry is not new
611
}
612
}
613
} else {
614
$index{$key} = [];
615
}
616
# print STDERR "Subsection key: \"$key\"\n";
617
add_to_index("$fname#$label", $key, $sec_of_key);
618
return "<a name = \"$label\"></a>\n";
619
}
620
}
621
622
623
# Some characters must be represented differently in HTML.
624
sub html_literal {
625
my ($lit) = @_;
626
if ($lit eq "<") { return "&lt;"; }
627
elsif ($lit eq ">") { return "&gt;"; }
628
elsif ($lit eq "&") { return "&amp;"; }
629
else { return $lit; }
630
}
631
632
633
# Gather lines ending in % together.
634
sub gather {
635
my ($line, $nontex) = @_;
636
my $nextline;
637
while ($line =~ s/%+\s*$// and defined($nextline = <IN>)) {
638
$nextline =~ s/^%// if $nontex;
639
unless ($nextline =~ /^%/) {
640
$nextline =~ s/^\s*//;
641
$line .= $nextline;
642
chomp $line;
643
}
644
}
645
return $line;
646
}
647
648
649
# This routine is called to process the text of the section
650
# the output file is assumed to be pre-selected. The input filehandle
651
# is simply IN
652
#
653
# As we process, we can be in "normal" mode (text), "maths" mode
654
# inside $ ... $, or "verbatim" mode inside a multi-line example
655
#
656
# We separately track whether we are in bold or tt,
657
# whether we are in a xxx: .... paragraph and whether we are reading
658
# a cross-reference that is split across multiple lines
659
#
660
# Finally, we track whether we have already
661
# emitted a <P> for this group of blank lines
662
#
663
664
665
$boldcommands = 'CAS|[A-Z]|danger|exercise';
666
$TeXbinops = "in|wedge|vee|cup|cap|otimes|oplus|le|ge|rightarrow";
667
$EndTeXMacro = "(?![A-Za-z])";
668
$TeXaccents = "\'`~=^"; # ^ must come last, this is also used as regexp
669
# From these and the argument following the HTML symbol is built
670
# e.g. `a -> &agrave;
671
%accents = ( "\'" => "acute", "19" => "acute",
672
"`" => "grave", "18" => "grave",
673
"~" => "tilde", "126" => "tilde",
674
"^" => "circ", "94" => "circ",
675
"c" => "cedil", "48" => "cedil",
676
"H" => "uml", "125" => "uml", "127" => "uml" );
677
# These are the replacements for accents that have an empty argument
678
# or for which there is no single HTML symbol (so that the accent must
679
# precede the argument)
680
%acc_0arg = ( "\'" => "\'", "19" => "\'",
681
"`" => "`", "18" => "`",
682
"~" => "~", "126" => "~",
683
"=" => "macr", "22" => "macr",
684
"^" => "^", "94" => "^",
685
"c" => "", "48" => "", # too hard ... just omit
686
"d" => "", # too hard ... just omit
687
"b" => "", # too hard ... just omit
688
"t" => "", # too hard ... just omit
689
"u" => "\\u", "21" => "\\u", # too hard ... put back
690
"v" => "\\v", "20" => "\\v", # too hard ... put back
691
"H" => "uml", "125" => "uml", "127" => "uml" );
692
693
# Calls tth to find out its version number
694
sub tth_version {
695
`tth -H >tthout 2> tthout`;
696
open (TTHOUT, "<tthout") || die "Can't read tthout\n";
697
while (<TTHOUT>) {
698
if (s/.*(Version [^ ]*).*/$1/) {
699
close TTHOUT;
700
system("rm tthout");
701
chomp;
702
return $_;
703
}
704
}
705
}
706
707
708
# We use this routine when using -t option to do any maths translation
709
sub tth_math_replace {
710
my ($tth) = @_;
711
open (TTHIN, ">tthin") || die "Can't create tthin";
712
#print STDERR "in: ${tth}\n";
713
my $tthorig = $tth;
714
# replace <...> by proper TeX
715
while ($tth =~ /(.*[^\\])<(.*[^\\])>(.*)/) {
716
$tth= $1."{\\it ".$2."\\/}".$3;
717
}
718
# replace `...' by proper TeX
719
while ($tth =~ /(.*[^\\])`(.*[^\\])\'(.*)/) {
720
$tth= $1."{\\tt ".$2."}".$3;
721
}
722
# replace \< by proper TeX
723
while ($tth =~ /(.*[^\\])\\<(.*)/) {
724
$tth= $1."<".$2;
725
}
726
#while ($tth =~ /(.*[^\\])\\>(.*)/) {
727
# $tth= $1.">".$2;
728
#}
729
730
$tth =~ s/([^\\]|^)([.])/$1\\cdot /g; # . not preceded by \ becomes \cdot
731
$tth =~ s/\\[.]/./g; # \. becomes .
732
$tth =~ s/(\\right)\\cdot/$1./g; # ... except for \right. (leave as is)
733
$tth =~ s/(\\not)\s*/$1/g;
734
$tth =~ s/\\\*/*/g;
735
if ($opt_t < 2.52) {
736
$tth =~ s/\\not\\in(?![a-zA-Z])/\\notin/g;
737
$tth =~ s/\\not\\subset/ not subset/g;
738
}
739
# Ensure display mode used for \buildrel and \choose constructions
740
$tth =~ s/\$/\$\$/g if ($tth =~ /\\buildrel|\\choose/ and $tth !~ /\$\$/);
741
if ($tth =~ /\\[A-Za-z]/) {
742
# there might be macros: Load our macros
743
#print STDERR "tth: ${tth}\n";
744
print TTHIN "\\input tthmacros.tex\n";
745
}
746
# we put in TTHBEGIN .. TTHEND
747
# so we can strip out the superfluous <p>s
748
# tth 2.78+ puts in, later.
749
print TTHIN "TTHBEGIN${tth}TTHEND\n";
750
close TTHIN;
751
`$tthbin -r -i <tthin >tthout 2>/dev/null`;
752
open (TTHOUT, "<tthout") || die "Can't read tthout";
753
$tth="";
754
while ( $tthin = <TTHOUT> ) {
755
chomp($tthin);
756
$tth .= $tthin;
757
}
758
close TTHOUT;
759
#print STDERR "out: ${tth}\n";
760
# only the stuff between TTHBEGIN and TTHEND
761
# actually belongs to the formula translated
762
$tth =~ s/.*TTHBEGIN(.*)TTHEND.*/$1/
763
|| do {print STDERR "!tth failed with input:\n $tthorig\n",
764
"!Null formula written to HTML file\n";
765
$tth = "";};
766
# tth leaves \mathbin etc. in ... get rid of them if present
767
$tth =~ s/\\math(bin|rel|op)//g;
768
# TtH up to version 2.86 doesn't know the following
769
$tth =~ s/\\wr(?![a-zA-Z])/ wr /g;
770
$tth =~ s/\\vdash(?![a-zA-Z])/ |- /g;
771
$tth =~ s/\\tilde(?![a-zA-Z])/~/g; # needed for in-line maths
772
#print STDERR "stripped: ${tth}\n";
773
774
# replace italic typewriter (happens because we force
775
# italic letters) by roman typewriter style
776
while ($tth =~ /(.*)<tt><i>(.*)<\/i><\/tt>(.*)/) {
777
$tth= $1."<tt>".$2."</tt>".$3;
778
}
779
780
# increasing the font size doesn't affect maths displays
781
# ... and `...' markup doesn't get increased in font size
782
# So let's get rid of it.
783
#$tth = "<font size=\"+1\">$tth</font>";
784
#print STDERR "enlarged: ${tth}\n";
785
return $tth;
786
}
787
788
#
789
# Takes a line of form: "<head><spaces>{<arg>}<rest>"
790
# and returns an array with: <rest>, <arg>, <head>
791
# i.e. it finds the matching } for {.
792
sub get_arg {
793
my ($line) = @_;
794
if ($line =~ /\s*\{([^{}]*)/) {
795
$line = $`;
796
my $arg = $1;
797
my $rest = $';
798
my $nbraces = 1;
799
while ($nbraces) {
800
if ($rest =~ s/^(\{[^{}]*)//) {
801
$arg .= $1;
802
$nbraces++;
803
} elsif ($nbraces == 1 and $rest =~ s/^\}//) {
804
$nbraces--;
805
} elsif ($rest =~ s/^(\}[^{}]*)//) {
806
$arg .= $1;
807
$nbraces--;
808
} else { # abort ... but make sure braces match
809
$rest = "{" x $nbraces . $rest;
810
$arg .= "}" x ($nbraces - 1);
811
$nbraces = 0;
812
}
813
}
814
return ($rest, $arg, $line);
815
} else {
816
print STDERR "line:$line\n";
817
die "Expected argument: at line $. of file";
818
}
819
}
820
821
#
822
# Given an accent macro with the \ or \accent stripped and the rest
823
# of a line with the macro's argument at it beginning return the
824
# HTML version of the accented argument and rest after the macro's
825
# argument has been stripped from it.
826
sub do_accent {
827
my ($rest, $macro) = @_;
828
$rest =~ /^(\w)|\{(\w?)\}/;
829
$rest = $';
830
my $arg = (defined $1) ? $1 : $2;
831
$macro = ($arg eq "") ? $acc_0arg{$macro} : "&$arg$accents{$macro};";
832
return ($rest, $macro);
833
}
834
835
#
836
# Takes rest which has a TeX macro without its \ at its beginning and
837
# returns the HTML version of the TeX macro and rest with the TeX macro
838
# stripped from it.
839
sub macro_replace {
840
my ($rest) = @_;
841
if ($rest =~ /^([$TeXaccents])\s*/) {
842
return do_accent($', $1);
843
}
844
if ($rest =~ /^([a-zA-Z]+)\s*/) {
845
$rest = $';
846
my $macro = $1;
847
if ($macro eq "accent") {
848
$rest =~ /^(\d+)\s*/;
849
$rest = $';
850
$macro = $1;
851
$macro = "" unless (defined $acc_0arg{$macro});
852
}
853
if (defined $accents{$macro}) { return do_accent($rest, $macro); }
854
elsif (defined $acc_0arg{$macro}) { return ($rest, $acc_0arg{$macro}); }
855
elsif ($macro eq "copyright") { return ($rest, "&copy;"); }
856
elsif ($macro eq "aa") { return ($rest, "&aring;"); }
857
elsif ($macro eq "AA") { return ($rest, "&Aring;"); }
858
elsif ($macro eq "lq") { return ($rest, "`"); }
859
elsif ($macro =~ /^(rq|pif)$/) { return ($rest, "'"); }
860
elsif ($macro =~ /^($boldcommands)$/)
861
{ return ($rest,"<font face=\"helvetica,arial\">".uc($&)."</font>"); }
862
elsif ($macro =~ /^(GAP|ATLAS|MOC$sharepkg)$/)
863
{ return ($rest, sansserif $macro); }
864
elsif ($macro eq "package")
865
{ my ($last, $arg, $first) = get_arg("$rest"); # $first = ""
866
return ($last, sansserif $arg);}
867
elsif ($macro eq "sf")
868
{ my ($last, $arg, $first) = get_arg("{$rest"); # $first = ""
869
return ($last, sansserif $arg);}
870
elsif ($macro =~ /^([hv]box|rm|kernttindent|math(bin|rel|op))$/)
871
{ return ($rest, "");}
872
elsif ($macro =~ /^(obeylines|(begin|end)group)$/)
873
{ return ($rest, "");}
874
elsif ($macro =~ /^hfil(|l)$/) { return ($rest, " ");}
875
elsif ($macro =~ /^break$/) { return ($rest, "<br>");}
876
elsif ($macro =~ /^(it|sl)$/)
877
{ my ($last, $arg, $first) = get_arg("{$rest"); # $first = ""
878
return ("$arg}\\emphend $last", "<em>");}
879
# pseudo ``emph'' end token
880
elsif ($macro eq "emphend") { return ($rest, "</em>"); }
881
elsif ($macro eq "hrule") { return ($rest, "<hr>"); }
882
elsif ($macro eq "enspace") { return ($rest, "&nbsp;"); }
883
elsif ($macro eq "quad") { return ($rest, "&nbsp;"); }
884
elsif ($macro eq "qquad") { return ($rest, "&nbsp;&nbsp;"); }
885
elsif ($macro eq "ss") { return ($rest, "&szlig;"); }
886
elsif ($macro eq "o") { return ($rest, "&oslash;"); }
887
elsif ($macro eq "O") { return ($rest, "&Oslash;"); }
888
elsif ($macro =~ /^l?dots$/) { return ($rest, "..."); }
889
elsif ($macro =~ /^bs?f|stars$/) { return ($rest, "<hr>"); }
890
elsif ($macro eq "cr") { return ($rest, "<br>"); }
891
# <li> in the next line would be invalid HTML
892
elsif ($macro eq "fmark") { return ($rest, "&nbsp;"); }
893
elsif ($macro eq "item")
894
{ ($rest, $itemarg, $first) = get_arg("$rest"); # $first = ""
895
if ($listdepth == 2) {
896
$listdepth = 1;
897
if ($listtype eq "d") {
898
return ("$itemarg\\itmnd $rest", "\n</dl>\n<dt>");
899
} else { #ignore bit in braces (ordered and unordered lists)
900
return ($rest, "\n</${listtype}l>\n<li>");
901
}
902
} else {
903
if ($listtype eq "d") {
904
return ("$itemarg\\itmnd $rest", "<dt>");
905
} else { #ignore bit in braces (ordered and unordered lists)
906
return ($rest, "<li>");
907
}
908
}
909
}
910
elsif ($macro eq "itemitem")
911
{ ($rest, $itemarg, $first) = get_arg("$rest"); # $first = ""
912
$rest =~ /^(%(un|)ordered)? #defines $sublisttype
913
(\{([1aAiI])\})? #defines TYPE of ordered sublist
914
(\{(\d+)\})? #defines START of ordered sublist
915
/x;
916
if ($listdepth == 1) {
917
$sublisttype = list_type($1, $2);
918
$sublistentry = begin_list($sublisttype, $3, $4, $5, $6) . "\n";
919
$listdepth = 2;
920
} else {
921
$sublistentry = "";
922
}
923
if ($sublisttype eq "d") {
924
return ("$itemarg\\itmnd $rest", "$sublistentry<dt>");
925
} else { #ignore bit in braces (ordered and unordered lists)
926
return ($rest, "$sublistentry<li>");
927
}
928
}
929
# pseudo ``itemend'' character
930
elsif ($macro eq "itmnd") { return ($rest, "<dd>"); }
931
elsif ($macro eq "cite" and $rest =~ /^\{\s*(\w+)\s*\}/)
932
{ return ($', "<a href=\"biblio.htm#$1\"><cite>$1</cite></a>"); }
933
elsif ($macro eq "URL" and $rest =~ /^\{([^\}]*)\}/)
934
{ return ($', "<a href=\"$1\">$1</a>"); }
935
elsif ($macro eq "Mailto" and $rest =~ /^\{([^\}]*)\}/)
936
{ return ($', "<a href=\"mailto:$1\">$1</a>"); }
937
else { return ($rest, $macro); }
938
} elsif ($rest =~ /^-/) {
939
return ($', ""); # hyphenation help -- ignore
940
} elsif ($rest =~ /^</) {
941
return ($', "&lt;");
942
} elsif ($rest =~ /^\&/) {
943
return ($', "&amp;");
944
} else {
945
$rest =~ /^./;
946
return ($', $&);
947
}
948
}
949
950
# Returns the type of a list
951
952
sub list_type {
953
my ($type, $un) = @_;
954
return ( !(defined $type) ) ? "d" #descriptive
955
: ($un eq "un")
956
? "u" #unordered
957
: "o"; #ordered
958
}
959
960
# Returns a string for starting a list of the appropriate type
961
962
sub begin_list {
963
my ($listtype, $otypedef, $otype, $ostartdef, $ostart) = @_;
964
my $beginlist = "<${listtype}l";
965
if ($listtype eq "d") {
966
$beginlist .= " compact";
967
} elsif ($listtype eq "o") {
968
if ( (defined $otypedef) && (defined $otype) ) {
969
$beginlist .= " type=$otype";
970
if ( (defined $ostartdef) && (defined $ostart) ) {
971
$beginlist .= " start=$ostart";
972
}
973
}
974
}
975
$beginlist .= ">";
976
return $beginlist;
977
}
978
979
#
980
# This could probably be done more cleverly -- this routine is too long
981
#
982
983
sub convert_text {
984
my $fname = $_[0];
985
my $refchars = '[\-\\w\\s`\',./:!()?$]'; # these make up cross references
986
my $ref = "";
987
my $endline = ""; # used for </code> at the end of line
988
my $mode = "normal"; # $mode can be:
989
# "normal" : TeX macros need to be interpreted
990
# "verbatim" : No interpretation done, except that
991
# || is converted to |.
992
# "html" : No interpretation done, except that
993
# initial % is removed.
994
# "maths" : A variant of "normal" where inside
995
# $...$ or $$...$$ (TeX's math mode)
996
my $ttenv = 0; # $ttenv is set to 1 in \begintt .. \endtt "verbatim" mode
997
my $nontex = 0; # $nontex is set to 1 in %display{nontex} and
998
# %display{nontext} env'ts, for which $mode is "normal"
999
# but initial % of each line is removed.
1000
my $skip_lines = 0; # $skip_lines is set non-zero in %display{tex},
1001
# %display{text}, %display{jpeg}, %display{nonhtml}
1002
# and \answer env'ts
1003
my ($bold,$tt,$it,$sub,$sup,$inlist,$inref,$donepar) = (0,0,0,0,0,0,0);
1004
my ($indexarg,$indexarg2,$zwei,$drei,$vier,$macro,$endmath,$endmathstring);
1005
1006
#
1007
# Now we loop over lines. a line with 16 initial % signs marks
1008
# end of section
1009
#
1010
1011
LINE: while (defined($_ = <IN>) and not /^\%{16,}/) {
1012
chomp; # drop the trailing newline
1013
my $rest = $_; # rest of the line to scan
1014
my $outline = ""; # build the output in here
1015
1016
# First we deal with various special whole lines.
1017
# \beginexample, \begintt, %display (this may end a $skip_lines)
1018
if ($mode eq "normal" and /^\\begin(example|tt)/) {
1019
if ($_ =~ /^\\begintt/) { # This is to catch a \begintt .. \endtt
1020
$ttenv = 1; # environment enclosing \beginexample ..
1021
} # \endexample
1022
$mode = "verbatim";
1023
$skip_lines = 0;
1024
print "<pre>\n";
1025
next LINE;
1026
} elsif ($mode eq "normal" and /^%display\{nontex(|t)\}/) {
1027
$nontex = 1;
1028
$skip_lines = 0;
1029
next LINE;
1030
} elsif ($mode eq "normal" and /^%display\{(text?|jpeg|nonhtml)\}/) {
1031
# Paragraphs to be skipped by HTML.
1032
$mode = "normal";
1033
$nontex = 0;
1034
$skip_lines = 2;
1035
next LINE;
1036
} elsif ($mode eq "normal" and /^%display\{html\}/) {
1037
$mode = "html";
1038
$skip_lines = 0;
1039
} elsif ($mode eq "html" and /^%display\{text\}/) {
1040
$mode = "normal";
1041
$nontex = 0;
1042
$skip_lines = 2;
1043
next LINE;
1044
} elsif (/^%enddisplay/ and !$ttenv) {
1045
if ($mode eq "verbatim") {
1046
print "</pre>\n";
1047
}
1048
$mode = "normal";
1049
$nontex = 0;
1050
$skip_lines = 0;
1051
next LINE;
1052
} elsif ($mode eq "verbatim") {
1053
# \endexample, \endtt
1054
if (/^\\endtt/ or (/^\\endexample/ and !$ttenv)) {
1055
$mode = "normal";
1056
$ttenv = 0;
1057
print "</pre>\n";
1058
next LINE;
1059
}
1060
# |_
1061
if (/^\|_/) {
1062
next LINE;
1063
}
1064
} elsif ($mode eq "html") {
1065
if (/^%/) {
1066
print "$'\n";
1067
} else {
1068
print STDERR "Line $. ignored in \%display{html} mode, " .
1069
"because it didn't start with \%\n";
1070
}
1071
next LINE;
1072
} elsif ((!$nontex and /^%/) ||
1073
(!/\\(at|)index/ and /^([{}]|\s*\{?\\[a-zA-Z].*)%$/)) {
1074
# Ignore lines starting with a % except if in html or verbatim
1075
# modes (dealt with above) or if in nontex mode which we deal
1076
# with below.
1077
# Also ignore specific lines ending in a % (we have to be careful
1078
# here -- % also indicates a continuation). The lines we ignore are
1079
# those that match: "{%", "}%", "{\\X..%", "\\X..%" where X denotes
1080
# any letter and .. any sequence of chars. This is meant to exclude
1081
# lines like "{\obeylines ... %", "\begingroup ... %". If this proves
1082
# problematic the .tex files will need to use the %display{tex} env't
1083
# to exclude such lines.
1084
next LINE;
1085
1086
# All that's left are whole lines that occur in "normal" mode
1087
} else {
1088
1089
# Line skipping.
1090
if ($skip_lines) {
1091
if ($skip_lines == 1 and $_ =~ /^\s*$/) {
1092
$skip_lines = 0;
1093
}
1094
next LINE;
1095
}
1096
1097
# Remove initial % if there is one when in %display{nontex} or
1098
# %display{nontext} environment
1099
if ($nontex) {
1100
s/^%//;
1101
$rest = $_;
1102
}
1103
# a '%' at end-of-line indicates a continuation
1104
$_ = gather($_, $nontex);
1105
1106
# Paragraphs are ended by blank lines.
1107
if (/^\s*$/) {
1108
unless ($donepar) {
1109
$outline .= "<p>\n";
1110
$donepar = 1;
1111
}
1112
1113
# If we get to the end of a paragraph we assume that we have
1114
# lost track of what is going on, warn and try to resume.
1115
if ($mode eq "maths" or $inref) {
1116
print STDERR "Paragraph ended in $mode mode at $.\n" .
1117
"reverting to normal\n";
1118
$outline .= "</I>" if ($mode eq "maths");
1119
$mode = "normal";
1120
}
1121
1122
print $outline;
1123
next LINE;
1124
}
1125
# Vertical skips.
1126
if (/^\\(med|big)skip/) {
1127
$outline .= "<p>";
1128
print "$outline\n";
1129
next LINE;
1130
}
1131
# Index entries -- emit an anchor and remember the index
1132
# keys for later there may be several on one line and
1133
# several references to one key
1134
if (/^\\(at|)index/) {
1135
# $_ = gather($_, $nontex); # already done above
1136
while (/\\((at|)index(tt|))\{/g) {
1137
($rest, $indexarg) = (get_arg("{".$'))[0,1];
1138
if ($1 eq "atindex") {
1139
($indexarg2) = (get_arg($rest))[1];
1140
if ($indexarg2 =~ /^@/) {
1141
$indexarg = $';
1142
$indexarg =~ s/\\noexpand\s*`([^']*)'/$1/g;
1143
$indexarg =~ s/\\noexpand\s*<([^>]*)>/$1/g;
1144
$indexarg =~ s/\\noexpand//g;
1145
$indexarg =~ s/\|.*//; # remove "|indexit" if present
1146
# $indexarg might still have macros ...
1147
# we should do something about these too
1148
}
1149
}
1150
# Just the crudest form of macro removal - probably enough
1151
$indexarg =~ s/\\(.)/$1/g;
1152
$indexarg =~ s/\$//g; #assume $s match in pairs!!
1153
$bla = inxentry($fname,$indexarg,$sec);
1154
$outline .= $bla;
1155
print "$outline\n";
1156
}
1157
next LINE;
1158
}
1159
# \> and \) lines (joined with next line if ending in %)
1160
if (/^\\[>)]/) {
1161
# $_ = gather($_, $nontex); # already done above
1162
# if \> with ` or ( without a matching ' or ) gather lines
1163
if ( /^\\> *\`/ ) { # line should have ended in a %
1164
while ( !/\'/ ) { $_ = gather("$_%", $nontex); }
1165
} elsif ( /^\\>.*\(/ ) { # line should have ended in a %
1166
while ( !/\)/ ) { $_ = gather("$_%", $nontex); }
1167
}
1168
# get rid of @{...} or @`...' if present.
1169
if (/@/) {
1170
# print STDERR "before:$_\n";
1171
if (s/@\s*(\{[^{}]*\}|\`[^\']*\')\s*/ /) { # easy
1172
} elsif (/@\s*/) {
1173
# nested braces ... need to find matching brace
1174
$_ = $`;
1175
($rest) = get_arg($');
1176
$_ .= " $rest";
1177
$rest ="";
1178
}
1179
# print STDERR "after:$_\n";
1180
print STDERR "@ still present at $_" if (/@/);
1181
}
1182
}
1183
# if there is a comment in square brackets we extract it now
1184
# ... this way if this feature is undesirable we can easily get
1185
# rid of it
1186
my $comment = "";
1187
# These cases [<something>] is not a comment:
1188
# \><anything>; # [<arg>] here is treated as an optional arg
1189
# \>`<func-with-args>'{<func>![gdfile]} # possibility from
1190
# # buildman.pe \Declaration
1191
if (/^\\>(.*;|`[^\']+\'{[^}!]*!\[[^\]]*\]})/) {
1192
;
1193
} elsif (/^\\>.*\(/) {
1194
if (s/^(\\>[^(]*\([^)]*\)[^\[]*)(\[[^\]]*\])/$1/) {
1195
$comment = " $2";
1196
}
1197
} elsif (s/^(\\>[^\[]*)(\[[^\]]*\])/$1/) {
1198
$comment = " $2";
1199
}
1200
# \>`<variable>' V
1201
if (/^\\> *`([^\']+)\'\s*(\[[^\]]*\])?\s*V?\s*$/) {
1202
$endline = "</code>";
1203
$outline .= subsec_name($fname,$1,$sec); # $1 = <variable>
1204
$outline .= "<dt>" if $inlist;
1205
$outline .= "<li><code>";
1206
$tt = 1;
1207
$rest = $1.$comment." V";
1208
}
1209
# \>`<non-func>'{<label>}[!<sub-entry>][ <capital>]
1210
# <capital> is usually one of A-Z (but any non-space will be matched)
1211
elsif (/^\\> *`([^\']+)\'\s*\{([^}]+)\}(!\{.*\})?\s*([^\s]+)?\s*$/) {
1212
# $1 = <non-func> $2 = <label> [$3 = !<sub-entry>][$4 = <capital>]
1213
$endline = "</code>";
1214
$drei = defined($3) ? $3 : "";
1215
$vier = defined($4) ? " $4" : "";
1216
# $2$drei = <label><sub-entry>
1217
$outline .= subsec_name($fname,"$2$drei",$sec);
1218
#print STDERR "non-func:$1 - $2 - $drei - $vier |$2$drei|\n";
1219
$outline .= "<dt>" if $inlist;
1220
$outline .= "<li><code>";
1221
$tt = 1;
1222
$rest = $1.$comment.$vier;
1223
}
1224
# \><func>[(<args>)][!{<sub-entry>}][ <capital>]
1225
# <capital> is usually one of A-Z (but any non-space will be matched)
1226
elsif (/^\\> *([^(]+)(\([^)]*\))?(!\{.*\})?\s*([^\s]+)?\s*$/) {
1227
# $1 = <func> $2 = (<args>) [$3 = !<sub-entry>][$4 = <capital>]
1228
$endline = "</code>";
1229
$zwei = defined($2) ? $2 : "";
1230
$drei = defined($3) ? $3 : "";
1231
$vier = defined($4) ? " $4" : "";
1232
$outline .= subsec_name($fname,"$1$drei",$sec);
1233
# $1$drei = <func><sub-entry>
1234
#print STDERR "func:$1 - $zwei - $drei - $vier |$1$drei|\n";
1235
$outline .= "<dt>" if $inlist;
1236
$outline .= "<li><code>";
1237
$tt = 1;
1238
$rest = $1.$zwei.$comment.$vier;
1239
1240
}
1241
elsif (/^\\\>/) {
1242
die "Didn't find an appropriate \\> match for $_ ... syntax?";
1243
}
1244
elsif (/^\\\) *(.*)$/) {
1245
$endline = "</code>";
1246
$outline .= "<dt>" if $inlist;
1247
if ($donepar) {
1248
$outline .= "<code>";
1249
} else {
1250
$outline .= "<br><code>";
1251
}
1252
$tt = 1;
1253
$rest = $1;
1254
# Skip all other lines starting or ending in % or containing
1255
# `align'.
1256
} elsif ($mode ne "verbatim" and
1257
$_ =~ /^\s*%|%\s*$|\\[a-z]+align/) {
1258
next LINE;
1259
}
1260
}
1261
1262
# Here we have a "non-special" line to process We scan it for
1263
# special characters and deal with them individually $rest
1264
# contains the text that we have yet to look at We accumulate
1265
# the output in $outline, rather than printing it because a &
1266
# requires us to back up to start of line
1267
$donepar = 0;
1268
1269
# The (rare) situation that we are processing a multi-line cross
1270
# reference is handled specially.
1271
if ($inref) {
1272
# if it finishes on this line emit the link
1273
# otherwise keep accumulating it
1274
if ($rest =~ /^$refchars+\"/o) {
1275
$rest = $';
1276
chop($ref .= $&);
1277
$ref1 = name2fn($ref,0);
1278
$ref2 = name2linktext($ref);
1279
$outline .= "<a href=\"$ref1\">$ref2</a>";
1280
$inref = "0";
1281
} elsif ($rest =~ /^$refchars*$/o) {
1282
$ref .= "$rest ";
1283
next LINE;
1284
} else {
1285
die "Bad reference. So far $ref, now got $rest";
1286
}
1287
}
1288
1289
# || really means | in verbatim mode
1290
$rest =~ s/\|\|/\|/g if ($mode eq "verbatim");
1291
1292
# The main case, scan for special characters.
1293
SPECIAL: while ( $rest =~ /[\\{}\$<>`\'*\"&%~_^]/ ) {
1294
$outline .= $`; # the part that we scanned past
1295
$rest = $'; # the remainder
1296
my $matched = $&; # the character matched
1297
1298
# In verbatim mode, everything is passed to HTML.
1299
if ($mode eq "verbatim") {
1300
# if ($matched ne "%") {
1301
$outline .= html_literal $matched;
1302
# }
1303
next SPECIAL;
1304
}
1305
1306
# backslash
1307
if ($matched eq "\\") {
1308
# commands that begin a new output line
1309
NEWLINE: {
1310
if ($rest =~ /^beginitems/ and not $inlist) {
1311
$outline .= "<p>\n<dl compact>";
1312
$inlist = 1;
1313
} elsif ($rest =~ /^enditems/ and $inlist) {
1314
$outline .= "</dl>";
1315
$inlist = 0;
1316
} elsif ($rest =~ /^beginlist
1317
(%(un|)ordered)? #defines $listtype
1318
(\{([1aAiI])\})? #defines TYPE of ordered list
1319
(\{(\d+)\})? #defines START of ordered list
1320
/x ) {
1321
$listtype = list_type($1, $2);
1322
$outline .= begin_list($listtype, $3, $4, $5, $6);
1323
$listdepth = 1;
1324
} elsif ($rest =~ /^endlist/) {
1325
$outline .= ("</${listtype}l>") x $listdepth;
1326
$listdepth = 0;
1327
} elsif ($rest =~ /^answer/) {
1328
$outline = "";
1329
$skip_lines = 1;
1330
} else {
1331
last NEWLINE;
1332
}
1333
print "$outline\n";
1334
next LINE;
1335
}
1336
# commands that are replaced by HTML text
1337
REPLACE: {
1338
($rest, $macro) = macro_replace($rest);
1339
$outline .= $macro;
1340
next SPECIAL;
1341
}
1342
# Try to get nice spacing around certain maths constructs that
1343
# are used a lot.
1344
if ($mode eq "maths") {
1345
MATHREPLACE: {
1346
if ($rest =~/^($TeXbinops)$EndTeXMacro/o) {
1347
$outline .= " $1 "; }
1348
elsif ($rest =~/^backslash$EndTeXMacro/o) {
1349
$outline .= " \\ "; }
1350
elsif ($rest =~/^split$EndTeXMacro/o) {
1351
$outline .= ":"; }
1352
elsif ($rest =~/^langle$EndTeXMacro/o) {
1353
$outline .= " &lt;"; }
1354
elsif ($rest =~ /^rangle$EndTeXMacro/o) {
1355
$outline .= "&gt; "; }
1356
else { last MATHREPLACE; }
1357
$rest = $';
1358
next SPECIAL;
1359
}
1360
}
1361
# Take the next character literally.
1362
if ($rest ne "") {
1363
$outline .= html_literal substr($rest,0,1);
1364
$rest = substr($rest,1);
1365
}
1366
next SPECIAL;
1367
}
1368
1369
# Subscripts and superscripts in math mode.
1370
if ($mode eq "maths" and !$sub and !$sup) {
1371
SUBSUPER: {
1372
if ($matched eq "_" and $rest =~ /^\{/) {
1373
$outline .= "<sub>";
1374
$sub = 1; if ($tt) { $tt++; } }
1375
elsif ($matched eq "^" and $rest =~ /^\{/) {
1376
$outline .= "<sup>";
1377
$sup = 1; if ($tt) { $tt++; } }
1378
elsif ($matched eq "_" and $rest =~ /^[^\\]/) {
1379
$outline .= "<sub>$&</sub>"; }
1380
elsif ($matched eq "^" and $rest =~ /^[^\\]/) {
1381
$outline .= "<sup>$&</sup>"; }
1382
else { last SUBSUPER; }
1383
$rest = $';
1384
next SPECIAL;
1385
}
1386
}
1387
if ($matched =~ /[_^]/) {
1388
$outline .= $matched;
1389
next SPECIAL;
1390
}
1391
1392
# Braces are ignored, but must must be balanced inside `...'.
1393
if ($matched eq "{") {
1394
if ($tt) { $tt++; }
1395
if ($sub) { $sub++; }
1396
elsif ($sup) { $sup++; }
1397
next SPECIAL;
1398
}
1399
if ($matched eq "}") {
1400
if ($tt == 1) {
1401
# print STDERR "o:$outline,m:$matched,r:$rest\n";
1402
die "Unbalanced braces in `...' ($outline$matched$rest)";
1403
}
1404
if ($tt) { $tt--; }
1405
if ($sub and !--$sub) { $outline .= "</sub>"; }
1406
if ($sup and !--$sup) { $outline .= "</sup>"; }
1407
next SPECIAL;
1408
}
1409
1410
# A tilde is a non-break space.
1411
if ($matched eq "~") {
1412
$outline .= "&nbsp;";
1413
next SPECIAL;
1414
}
1415
1416
# $ toggles maths mode.
1417
if ($matched eq "\$") {
1418
if ($rest =~ /^\$/) {
1419
$rest = $';
1420
$endmath = "[\$][\$]";
1421
$endmathstring = "\$\$";
1422
} else {
1423
$endmath = "[\$]";
1424
$endmathstring = "\$";
1425
}
1426
if ($opt_t) {
1427
if ($mode eq "normal") {
1428
$tth= "";
1429
$mode = "tth";
1430
1431
while ($mode eq "tth") {
1432
if ( $rest =~ /$endmath/ ) {
1433
$tth .= $`; # the part scanned past
1434
$rest = $';
1435
1436
# make a math mode string
1437
$tth = "$endmathstring$tth$endmathstring";
1438
1439
# pass $tth to tth to convert to HTML
1440
# and append the result
1441
$outline .= tth_math_replace($tth);
1442
$mode = "normal";
1443
}
1444
else {
1445
# we are in tth mode but the line has no terminating
1446
# $ or $$: continue into next line
1447
if ($rest =~ s/%$//) { # Mirror TeX behaviour when
1448
$tth .= $rest; # line ends in a % ...
1449
$rest = <IN>; # swallow whitespace at
1450
$rest =~ s/^\s*//; # beginning of next line
1451
} else {
1452
$tth .= $rest." ";
1453
$rest = <IN>;
1454
}
1455
chomp($rest);
1456
}
1457
}
1458
1459
next SPECIAL;
1460
} else {
1461
die "math mode messup";
1462
}
1463
} else {
1464
$outline .= "<p>" if ($endmathstring eq "\$\$");
1465
if ($mode eq "maths") {
1466
if ($sub) { die "Math mode ended during subscript ".
1467
"($outline$matched$rest)"; }
1468
elsif ($sup) { die "Math mode ended during superscript ".
1469
"($outline$matched$rest)"; }
1470
$mode = "normal";
1471
$outline .= "</var>";
1472
if ($tt) { $outline .= "<code>"; }
1473
next SPECIAL;
1474
}
1475
$mode = "maths";
1476
if ($tt) { $outline .= "</code>"; }
1477
$outline .= "<var>";
1478
next SPECIAL;
1479
}
1480
}
1481
1482
# < > open and close italics.
1483
if ($matched eq "<") {
1484
if (not $it) {
1485
if ($tt) { $outline .= "</code>"; }
1486
$outline .= "<var>";
1487
$it = 1;
1488
} else {
1489
$outline .= "&lt;";
1490
}
1491
next SPECIAL;
1492
}
1493
if ($matched eq ">") {
1494
if ($it) {
1495
$outline .= "</var>";
1496
if ($tt) { $outline .= "<code>"; }
1497
$it = 0;
1498
} else {
1499
$outline .= "&gt;";
1500
}
1501
next SPECIAL;
1502
}
1503
1504
# * in normal mode toggles bold-face.
1505
if ($matched eq "*") {
1506
if ($mode eq "normal" and not $tt) {
1507
if ($bold) {
1508
$outline .= "</strong>";
1509
$bold = 0;
1510
} else {
1511
$outline .= "<strong>";
1512
$bold = 1;
1513
}
1514
} else {
1515
$outline .= "*";
1516
}
1517
next SPECIAL;
1518
}
1519
1520
# ` and ' in normal mode control typewriter.
1521
if ($matched eq "`") {
1522
if ($tt) {
1523
$outline .= "`";
1524
} elsif ( $rest =~ /^`/ ) {
1525
$rest = $';
1526
$outline .= "``";
1527
} else {
1528
$tt = 1;
1529
$outline .= "<code>";
1530
}
1531
next SPECIAL;
1532
}
1533
if ($matched eq "\'") {
1534
if ($tt == 1) {
1535
$outline .= "</code>";
1536
$tt = 0;
1537
} else {
1538
$outline .= "\'";
1539
}
1540
next SPECIAL;
1541
}
1542
1543
# & signals a definition. We go back to start of line for the
1544
# tag, and on to end of para for the definition. We do not
1545
# merge adjacent definitions into the same list.
1546
if ($matched eq "&") {
1547
if ($inlist) {
1548
$outline = "<dt>$outline<dd>"; # Sometimes we get an extra
1549
} # <dt> we don't need ...
1550
next SPECIAL; # but it has no effect :)
1551
}
1552
1553
# " starts a cross-reference. If it ends on the same input
1554
# line then we can deal with it at once otherwise we set
1555
# $inref.
1556
if ($matched eq "\"") {
1557
if ($tt) {
1558
$outline .= "\"";
1559
next SPECIAL;
1560
}
1561
if ($rest =~ /^$refchars+\"/o) {
1562
$rest = $';
1563
chop($ref = $&);
1564
$ref1 = name2fn($ref,0);
1565
$ref2 = name2linktext($ref,0);
1566
$outline .= "<a href=\"$ref1\">$ref2</a>";
1567
next SPECIAL;
1568
}
1569
if ($rest =~ /^$refchars*$/o) {
1570
$ref = "$rest ";
1571
$inref = 1;
1572
print $outline;
1573
next LINE;
1574
}
1575
die "Bad reference $rest at $_";
1576
}
1577
1578
# Ignore from % to end of line, on-line browser does not do this.
1579
if ($matched eq "%") {
1580
print $outline."\n";
1581
next LINE;
1582
}
1583
1584
} # SPECIAL
1585
print $outline.$rest.$endline."\n";
1586
if ($endline =~ /<\/code>/) {
1587
$tt = 0;
1588
}
1589
$endline ="";
1590
} # LINE
1591
}
1592
1593
1594
sub metaquote {
1595
my $name = quotemeta $_[0];
1596
$name =~ s/\\ /\\s+/g;
1597
return $name;
1598
}
1599
1600
sub startfile {
1601
my $sec = $_[0];
1602
my ($num, $name, $re, $fname, $name1, $name2);
1603
if ($sec->{secnum} == 0) {
1604
$sec->{chapnum} = $chap->{number};
1605
$num = $chap->{number};
1606
$name = $chap->{name};
1607
$name1 = metaquote $name;
1608
$re = "^\\\\(Chapter|PreliminaryChapter)\\{$name1\\}";
1609
} else {
1610
$num = $sec->{chapnum} . "." .$sec->{secnum};
1611
$name = $sec->{name};
1612
$name1 = metaquote $name;
1613
$re = "^\\\\Section\\{$name1\\}";
1614
}
1615
$name2 = kanonize $name;
1616
$fname = htm_fname($opt_c,
1617
$sec->{chapnum}, $sec->{secnum}, $sec->{ssecnum});
1618
1619
open ( OUT, ">${odir}${fname}" ) || die "Can't write to ${odir}${fname}";
1620
select OUT;
1621
1622
print "<html><head><title>[$book] $num $name2</title></head>\n";
1623
print "<body text=\"\#000000\" bgcolor=\"\#ffffff\">\n";
1624
add_to_index($fname, $name, $sec);
1625
navigation( ($opt_c) ? $chap->{sections}[0] : $sec );
1626
print "<h1>$num $name2</h1><p>\n";
1627
1628
return ($fname, $re);
1629
}
1630
1631
sub startsec {
1632
my $sec = $_[0];
1633
my $snum = $sec->{secnum};
1634
my $name = $sec->{name};
1635
add_to_index(htm_fname($opt_c, $sec->{chapnum}, $snum, 0), $name, $sec);
1636
my $num = $sec->{chapnum} . "." .$snum;
1637
$snum = "0" x (3 - length $snum) . $snum;
1638
my $name1 = metaquote $name;
1639
my $name2 = kanonize $name;
1640
print "<h2><a name=\"SECT$snum\">$num $name2</a></h2>\n<p>";
1641
return "^\\\\Section\\{$name1\\}";
1642
}
1643
1644
sub sectionlist {
1645
my $chap = $_[0];
1646
my $sec;
1647
print "<P>\n<H3>Sections</H3>\n<oL>\n";
1648
SUBSEC: for $sec (@{$chap->{sections}}) {
1649
next SUBSEC if ($sec->{secnum} == 0);
1650
my $link = htm_fname($opt_c, $sec->{chapnum}, $sec->{secnum}, 0);
1651
my $name2 = kanonize $sec->{name};
1652
print "<li> <A HREF=\"$link\">$name2</a>\n";
1653
}
1654
print "</ol><p>\n";
1655
}
1656
1657
#
1658
# Basically the chapter file is read in one pass, using information previously
1659
# read from the .toc file to fill in next and previous pointers and the like
1660
#
1661
1662
sub navigation {
1663
my $sec = $_[0];
1664
my $chap = $sec->{chapter};
1665
my $cfname = htm_fname($opt_c, $sec->{chapnum}, 0, 0);
1666
if ($mainman == 1) {
1667
print "[<a href=\"../index.htm\">Top</a>] "
1668
} else {
1669
if ($opt_f) {
1670
print "[<a href=\"$opt_f\">Top</a>] "
1671
}
1672
};
1673
if ($sec->{secnum} == 0) {
1674
print "[<a href = \"chapters.htm\">Up</a>] ";
1675
if (tonum($chap->{number}) != 1) {
1676
my $prev = htm_fname($opt_c,
1677
$chapters[tonum($chap->{number}) - 1]{number},
1678
0, 0);
1679
print "[<a href =\"$prev\">Previous</a>] ";
1680
}
1681
if (tonum($chap->{number}) != $#chapters) {
1682
my $next = htm_fname($opt_c,
1683
$chapters[tonum($chap->{number}) + 1]{number},
1684
0, 0);
1685
print "[<a href =\"$next\">Next</a>] ";
1686
}
1687
} else {
1688
print "[<a href = \"$cfname\">Up</a>] ";
1689
if ($sec->{secnum} != 1) {
1690
my $prev = htm_fname($opt_c, $chap->{number}, $sec->{secnum} - 1,
1691
0);
1692
print "[<a href =\"$prev\">Previous</a>] ";
1693
}
1694
if ($sec->{secnum} != $#{$chap->{sections}}) {
1695
my $next = htm_fname($opt_c, $chap->{number}, $sec->{secnum} + 1,
1696
0);
1697
print "[<a href =\"$next\">Next</a>] ";
1698
} elsif (tonum($chap->{number}) != $#chapters) {
1699
my $next = htm_fname($opt_c,
1700
$chapters[tonum($chap->{number}) + 1]{number},
1701
0, 0);
1702
print "[<a href =\"$next\">Next</a>] ";
1703
}
1704
}
1705
print "[<a href = \"theindex.htm\">Index</a>]\n";
1706
}
1707
1708
1709
sub convert_chap {
1710
my ($chap) = @_;
1711
my ($re, $startre, $fname, $secline);
1712
$indexcount = 0;
1713
open (IN, "<$dir$chap->{file}.tex")
1714
|| die "Can't read $dir$chap->{file}.tex";
1715
$_ = <IN>;
1716
1717
# loop, controlled by the list of sections that we expect
1718
# will fail, possibly messily if this does not match reality
1719
1720
# The call to startfile produces navigation + a chapter heading
1721
if ($opt_c) { # each chapter in a single file
1722
($fname,$re) = startfile $chap->{sections}[0];
1723
}
1724
1725
# note we *need* $sec to act globally in what follows!
1726
SECT: for $sec (@{$chap->{sections}}) {
1727
1728
# sort out what we are processing (chapter or section)
1729
# produce the header of the Web page
1730
1731
if ($opt_c) {
1732
$re = startsec $sec unless ($sec->{secnum} == 0);
1733
} else {
1734
# The call to startfile produces navigation + a section heading
1735
($fname, $re) = startfile $sec;
1736
# print STDERR "fname: $fname, re: $re\n";
1737
}
1738
($startre = $re) =~ s/(^[^\{]*\{).*/$1/;
1739
1740
#
1741
# Look for the \Chapter or \Section line
1742
#
1743
1744
while ( !/$startre/ ) {
1745
unless (defined($_ = <IN>)) {
1746
die "Missing chapter or section line matching $startre" };
1747
};
1748
1749
chomp;
1750
$secline = $_;
1751
while ( $secline !~ /\}/ ) {
1752
unless (defined($_ = <IN>)) {
1753
die "Missing chapter or section line matching $re" };
1754
chomp;
1755
s/\%.*//;
1756
$secline .= " $_";
1757
};
1758
1759
unless ($secline =~ /$re/) {
1760
die "Missing chapter or section line matching $re"
1761
};
1762
1763
# If this is the beginning of a chapter, we list its sections
1764
if ($sec->{secnum} == 0) {
1765
if (defined($chap->{sections}[1])) {
1766
sectionlist $chap;
1767
} else {
1768
print STDERR "Warning: Chapter has no sections\n";
1769
}
1770
}
1771
1772
# Now we print the section body
1773
convert_text($fname);
1774
print "<p>\n";
1775
1776
# If it's one file per section ... add navigation etc. at end of file
1777
unless ($opt_c) {
1778
navigation $sec;
1779
print $footer;
1780
close OUT;
1781
select STDOUT;
1782
}
1783
}
1784
1785
# If it's one file per chapter ... add navigation etc. at end of file
1786
if ($opt_c) {
1787
navigation $chap->{sections}[0];
1788
print $footer;
1789
close OUT;
1790
select STDOUT;
1791
}
1792
close IN;
1793
}
1794
1795
1796
1797
sub chapters_page {
1798
open (OUT, ">${odir}chapters.htm")
1799
|| die "Can't write to ${odir}chapters.htm";
1800
select OUT;
1801
1802
print <<END
1803
<html><head><title>$booktitle - Chapters</title></head>
1804
<body text=\"\#000000\" bgcolor=\"\#ffffff\">
1805
<h1>$booktitle_body - Chapters</h1>
1806
<ul>
1807
<li><a href=\"theindex.htm\">Index</a>
1808
</ul>
1809
<ol>
1810
END
1811
;
1812
1813
CHAP: foreach $chap (@chapters) {
1814
unless (defined $chap) { next CHAP};
1815
my $link = htm_fname($opt_c, $chap->{number}, 0, 0);
1816
my $name2 = kanonize $chap->{name};
1817
print "</ol><ol type=\"A\">\n" if ( $chap->{number} eq "A" );
1818
print "<li><a href=\"$link\">$name2</a>\n";
1819
}
1820
1821
print <<END
1822
</ol>
1823
<ul>
1824
<li><a href=\"biblio.htm\">References</a>
1825
<li><a href=\"theindex.htm\">Index</a>
1826
</ul><p>
1827
END
1828
;
1829
if ($mainman == 1) {
1830
print "[<a href=\"../index.htm\">Top</a>]<p>"
1831
} else {
1832
if ($opt_f) {
1833
print "[<a href=\"$opt_f\">Top</a>] "
1834
}
1835
};
1836
print $footer;
1837
close OUT;
1838
select STDOUT;
1839
1840
# Touch the chapters file so that `make' recognizes the conversion
1841
# has been done.
1842
system "touch ${odir}chapters.htm";
1843
}
1844
1845
sub caseless { lc($a) cmp lc ($b) or $a cmp $b }
1846
1847
sub index_head {
1848
my ($letter, @letters) = @_;
1849
my ($bstb);
1850
print <<END
1851
<html><head><title>$booktitle - Index ${letter}</title></head>
1852
<body text=\"\#000000\" bgcolor=\"\#ffffff\">
1853
<h1>$booktitle_body - Index ${letter}</h1>
1854
<p>
1855
END
1856
;
1857
# print STDERR $letter, @letters, "\n";
1858
foreach $bstb (@letters) {
1859
if ($opt_i) {
1860
print "<a href=\"\#idx${bstb}\">$bstb</A>\n";
1861
}
1862
elsif ($bstb eq "_") {
1863
print "<a href=\"theindex.htm\">$bstb</A>\n";
1864
}
1865
else {
1866
print "<a href=\"indx${bstb}.htm\">$bstb</A>\n";
1867
}
1868
}
1869
}
1870
1871
sub index_end {
1872
print "</dl><p>\n";
1873
if ($mainman == 1) {
1874
print "[<a href=\"../index.htm\">Top</a>] "
1875
} else {
1876
if ($opt_f) {
1877
print "[<a href=\"$opt_f\">Top</a>] "
1878
}
1879
};
1880
print "[<a href=\"chapters.htm\">Up</a>]";
1881
print "<p>\n$footer";
1882
}
1883
1884
sub index_page {
1885
my ($ent, $ref, $letter, $bstb, $thisletter, @entries, %letters, @letters);
1886
%letters = $opt_i ? ()
1887
: ("_" => ""); # With multiple indices, the "_"
1888
# index is theindex.htm
1889
foreach $ent (keys %index) {
1890
$bstb = uc(substr($ent,0,1));
1891
if ($bstb lt "A" or $bstb gt "Z") {$bstb = "_";}
1892
$letters{$bstb} = "";
1893
}
1894
@letters = sort caseless keys %letters;
1895
1896
$letter = $opt_i ? "" : "_";
1897
open (OUT, ">${odir}theindex.htm")
1898
|| die "Can't write to ${odir}theindex.htm";
1899
select OUT;
1900
index_head($letter, @letters);
1901
1902
ENTRY: foreach $ent (sort caseless keys %index) {
1903
$thisletter = uc(substr($ent,0,1));
1904
if ($thisletter lt "A" or $thisletter gt "Z") {$thisletter = "_";}
1905
if ($letter eq "") { # Only happens first time round for $opt_i
1906
$letter = $thisletter;
1907
print "<H2><A NAME=\"idx${letter}\">$letter</A></H2>\n<dl>\n";
1908
}
1909
elsif ($letter ne $thisletter) {
1910
$letter = $thisletter;
1911
if ($opt_i) {
1912
print "</dl><p>\n";
1913
print "<H2><A NAME=\"idx${letter}\">$letter</A></H2>\n<dl>\n";
1914
}
1915
else {
1916
index_end;
1917
close OUT;
1918
select STDOUT;
1919
open (OUT, ">${odir}indx${letter}.htm")
1920
|| die "Can't write to ${odir}indx${letter}.htm";
1921
select OUT;
1922
index_head($letter, @letters);
1923
}
1924
}
1925
$ent1 = $ent;
1926
$ent1 =~ s/!/, /g;
1927
$ent1 =~ s/[{}]//g;
1928
print "<dt>".kanonize $ent1." ";
1929
for $ref (@{$index{$ent}}) {
1930
print "<a href=\"$ref->[0]\">$ref->[1]</a> ";
1931
}
1932
print "\n";
1933
}
1934
index_end;
1935
close OUT;
1936
select STDOUT;
1937
}
1938
1939
sub biblio_page {
1940
my $infile = "${dir}manual.bbl";
1941
my $outfile = "${odir}biblio.htm";
1942
my $macro;
1943
open (OUT, ">${outfile}") || die "Can't write to ${outfile}";
1944
select OUT;
1945
1946
print <<END
1947
<html><head><title>$booktitle - References</title></head>
1948
<body text=\"\#000000\" bgcolor=\"\#ffffff\">
1949
<h1>$booktitle_body - References</h1><dl>
1950
END
1951
;
1952
1953
if (-f $infile and -r $infile) {
1954
open IN, "<$infile";
1955
my ($brace,$embrace) = (0,-1);
1956
while (<IN>) {
1957
chomp;
1958
my $outline = "";
1959
if (/newcommand/ || /thebibliography/) { }
1960
elsif (/^\\bibitem\[[^\]]+\]\{([^\}]+)\}/) {
1961
print "<dt><a name=\"$1\"><b>[$1]</b></a><dd>\n";
1962
} else {
1963
my $line = $_;
1964
if ($line =~ /^\s*\\newblock/) { $outline .= "<br>";
1965
$line = $'; }
1966
while ($line =~ /[\${}<>~&\\]/) {
1967
$outline .= $`;
1968
$matched = $&;
1969
$line = $';
1970
if ($opt_t and $matched eq "\$" and $line =~ /([^\$]*\$)/) {
1971
# if we are using the -t option and we have
1972
# detected a *simple* maths formula $...$ pass it
1973
# off directly to tth_math_replace. Bibliographies
1974
# should only have very simple maths formulae. If
1975
# it's broken over a line, we won't detect it.
1976
$matched .= $&;
1977
$outline .= tth_math_replace($matched);
1978
$line = $';
1979
} elsif ($matched eq "\{") {
1980
if ($line =~ /^\\(em|it)\s*/) { $embrace = $brace;
1981
$outline .= "<em>";
1982
$line = $'; }
1983
$brace++;
1984
} elsif ($matched eq "\}") {
1985
$brace--;
1986
if ($brace == -1 ) {
1987
die "Unbalanced braces in bbl file ".
1988
"($outline$matched$line";
1989
} elsif ($brace == $embrace) { $outline .= "</em>";
1990
$embrace = -1; }
1991
} elsif ($matched eq "\\") {
1992
if ($line =~ /^cite\{([^\}]*)\}/) {
1993
$outline .= "<a href=\"#$1\"><cite>$1</cite></a>";
1994
$line = $';
1995
} else {
1996
($line, $macro) = macro_replace($line);
1997
$outline .= $macro;
1998
}
1999
} elsif ($matched eq "~" ) {
2000
$outline .= "&nbsp;";
2001
} elsif ($matched ne "\$") {
2002
$outline .= html_literal $matched;
2003
}
2004
}
2005
print "$outline$line\n";
2006
}
2007
}
2008
} else {
2009
print STDERR "Warning: did not find a .bbl file ... ok?\n";
2010
}
2011
print "</dl><p>\n";
2012
if ($mainman == 1) {
2013
print "[<a href=\"../index.htm\">Top</a>] "
2014
} else {
2015
if ($opt_f) {
2016
print "[<a href=\"$opt_f\">Top</a>] "
2017
}
2018
};
2019
print "[<a href=\"chapters.htm\">Up</a>]";
2020
print "<p>\n$footer\n";
2021
close OUT;
2022
select STDOUT;
2023
}
2024
2025
#
2026
# Main program starts here
2027
#
2028
# Process option and sort out input and output directories
2029
#
2030
2031
getopts('csitun:f:');
2032
2033
if (!$opt_c) {$opt_c = 0;} # just to ensure it is not empty
2034
2035
chomp($dir = shift @ARGV);
2036
if (substr($dir,0,1) ne "/") {
2037
$dir = `pwd` . "/" . $dir;
2038
$dir =~ s/\n//;
2039
}
2040
if (substr($dir,-1) ne "/") {
2041
$dir .= "/";
2042
}
2043
unless (-d $dir and -r $dir) {
2044
die "Can't use input directory $dir";
2045
}
2046
2047
if ($opt_t) {
2048
my ($whichtth) = `which tth`;
2049
chomp($whichtth);
2050
if ($whichtth !~ m+/tth$+) {
2051
print STDERR "!! tth: not in path.\n$whichtth\n",
2052
"... Maths formulae will vanish!",
2053
" Install tth or avoid -t option.\n";
2054
}
2055
$tthbin="tth";
2056
}
2057
2058
if ($opt_u) {
2059
my ($whichtth) = `which tth`;
2060
chomp($whichtth);
2061
if ($whichtth !~ m+/tth$+) {
2062
print STDERR "!! tth: not in path.\n$whichtth\n",
2063
"... Maths formulae will vanish!",
2064
" Install tth or avoid -t option.\n";
2065
}
2066
$tthbin="tth -u1";
2067
}
2068
2069
if ($opt_n) {
2070
# get book title
2071
$book=$opt_n;
2072
#$booktitle = "$opt_n : a GAP example";
2073
$booktitle = "$opt_n : a GAP 4 package";
2074
$booktitle_body = booktitle_body($booktitle, ("GAP", $opt_n));
2075
$mainman=0;
2076
$footer = "<P>\n<address>$opt_n manual<br>" .
2077
`date +"%B %Y"` . "</address></body></html>";
2078
#print "c: $opt_c \n";
2079
} else {
2080
if ($opt_f) {
2081
die "option -f can only be used together with -n ";
2082
}
2083
if ($dir =~ /\/([^\/]+)\/$/) {
2084
$book = $1;
2085
} else {
2086
die "Can't find basename of $dir";
2087
}
2088
if ($book eq "tut") {
2089
$booktitle = "The GAP 4 Tutorial";
2090
} elsif ($book eq "ref") {
2091
$booktitle = "The GAP 4 Reference Manual";
2092
} elsif ($book eq "prg") {
2093
$booktitle = "The GAP 4 Programming Tutorial";
2094
} elsif ($book eq "ext") {
2095
$booktitle = "The GAP 4 Programming Reference Manual";
2096
} elsif ($book eq "new") {
2097
$booktitle = "GAP 4: New Features for Developers";
2098
} else {
2099
die "Invalid book, must be tut, ref, prg, new or ext";
2100
}
2101
$booktitle_body = booktitle_body($booktitle, "GAP");
2102
$mainman=1;
2103
}
2104
2105
if ($#ARGV != -1) {
2106
chomp($odir=shift @ARGV);
2107
} else {
2108
$odir = "";
2109
}
2110
if (substr($odir,0,1) ne "/") {
2111
$odir = `pwd` . "/" . $odir;
2112
$odir =~ s/\n//;
2113
}
2114
if (substr($odir,-1) ne "/") {
2115
$odir .= "/";
2116
}
2117
unless (-d $odir and -w $odir) {
2118
die "Can't use output directory $odir";
2119
}
2120
print "Reading input from $dir\n" unless ($opt_s);
2121
print "Creating output in $odir\n" unless ($opt_s);
2122
2123
if ($opt_t || $opt_u) {
2124
# create macro file for our expressions and macros not known to tth in TeX
2125
# mode.
2126
$opt_t = tth_version;
2127
print STDERR "Using TtH $opt_t to translate maths formulae.\n";
2128
$opt_t =~ s/Version //;
2129
open (TTHIN, ">tthmacros.tex") || die "Can't create tthmacros.tex";
2130
print TTHIN "\\def\\Q{{\\bf Q}}\\def\\Z{{\\bf Z}}\\def\\N{{\\bf N}}\n",
2131
"\\def\\R{{\\bf R}}\\def\\F{{\\bf F}}\n";
2132
# \R and \I are used in the last chapter of ext
2133
print TTHIN "\\def\\calR{{\\cal R}}\\def\\I{{\\cal I}}\n",
2134
"\\def\\frac#1#2{{{#1}\\over{#2}}}\\def\\colon{:}\n",
2135
"\\def\\longmapsto{\\mapsto}\\def\\lneqq{<}\n",
2136
"\\def\\hookrightarrow{\\rightarrow}\n";
2137
if ($opt_t < 2.52) {
2138
# We work-around most of the deficiencies of versions of TtH
2139
# prior to Version 2.52 ... but can't easily fix the lack of
2140
# proper treatment of \not.
2141
print STDERR
2142
"Your version of TtH does not know many TeX commands.\n",
2143
"It is recommended that you upgrade to the latest version from\n",
2144
" http://hutchinson.belmont.ma.us/tth/tth-noncom/download.html\n";
2145
print TTHIN "\\def\\mid{ | }\\def\\lbrack{[}\\def\\rbrack{]}\n",
2146
"\\def\\gets{\\leftarrow}\\def\\land{\\wedge}\n";
2147
}
2148
close TTHIN;
2149
}
2150
2151
getchaps;
2152
print "Processed TOC files\n" unless ($opt_s);
2153
2154
open (TEX, "<${dir}manual.tex") || die "Can't open ${dir}manual.tex";
2155
getlabs $dir;
2156
while (<TEX>) {
2157
if (/\\UseReferences{([^}]*)}/) {
2158
getlabs "$dir$1/";
2159
} elsif (/\\UseGapDocReferences{([^}]*)}/) {
2160
getlabs "$dir$1/";
2161
($gapdocbook = $1) =~ s?.*/([^/]*)/doc?$1?;
2162
$gapdocbooks{$gapdocbook} = 1;
2163
print STDERR "GapDoc books: ", keys(%gapdocbooks), "\n";
2164
} elsif (/\\Package{([^}]*)}/) {
2165
$sharepkg .= "|$1";
2166
}
2167
}
2168
print "Processed LAB files\n" unless ($opt_s);
2169
2170
#
2171
# OK go to work
2172
#
2173
2174
CHAP: foreach $chap (@chapters) {
2175
unless (defined $chap) {
2176
next CHAP;
2177
}
2178
print "$chap->{number}. $chap->{name} ... $chap->{file}.tex\n"
2179
unless ($opt_s);
2180
convert_chap $chap;
2181
}
2182
2183
print "and the chapters page\n" unless ($opt_s);
2184
chapters_page;
2185
print "and the index pages\n" unless ($opt_s);
2186
index_page;
2187
print "and the references\n" unless ($opt_s);
2188
biblio_page;
2189
2190
if ($opt_t || $opt_u ) {
2191
# remove the tth stuff
2192
unlink 'tthin','tthout','tthmacros.tex';
2193
}
2194
2195
print "done\n" unless ($opt_s);
2196
#############################################################################
2197
2198