[BACK]Return to gphelp.in CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / doc

Annotation of OpenXM_contrib/pari-2.2/doc/gphelp.in, Revision 1.2

1.1       noro        1: #!@perl@
                      2: #
1.2     ! noro        3: # $Id: gphelp.in,v 1.28 2002/09/07 21:48:29 cvsadmin Exp $
1.1       noro        4: #
                      5: # Copyright (C) 2000  The PARI group.
                      6: #
                      7: # This file is part of the PARI/GP package.
                      8: #
                      9: # PARI/GP is free software; you can redistribute it and/or modify it under the
                     10: # terms of the GNU General Public License as published by the Free Software
                     11: # Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     12: # ANY WARRANTY WHATSOEVER.
                     13: #
                     14: # Check the License for details. You should have received a copy of it, along
                     15: # with the package; see the file 'COPYING'. If not, write to the Free Software
                     16: # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
                     17:
                     18: # Output extended help corresponding to a given GP command. By default,
                     19: # extract relevant information from  from the PARI manual, run TeX, then open
                     20: # an xdvi display.
                     21: #
                     22: # The manual can be compressed.
                     23: #
                     24: # Usage: gphelp keyword
                     25: #
                     26: # Command line options:
                     27: #  -k: apropos (list of relevant GP functions)
                     28: #  -detex      (-d): don't use TeX + xdvi (implicit when DISPLAY is not set).
                     29: #  -color_help (-ch) <number>: use color "number" (same scheme as in GP)
                     30: #  -color_bold (-cb) <number>: display bold in color "number"
                     31: #  -color_underline (-cu) <number>: display underlined text in color "number"
                     32: #
                     33: #  -raw   use internal format for output with @x markers, -detex is implicit
                     34: #         (for the TeX-to-pod converter)
                     35: #
                     36: #  -to_pod file                convert file to POD (should be the only args)
                     37: #
                     38: #  -to_dumbpod file    same, but without nested formating
                     39: #
                     40: # Granted environment variables (override):
                     41: #  GPTMPDIR: where temporary files will go (/tmp by default).
                     42: #  GPDOCDIR: where is manual (by default, where make install will put it).
                     43: #  GPXDVI: which 'xdvi' program to call (xdvi by default)
                     44: #
                     45: $version= "@version@";
                     46: $miscdir= "@miscdir@";
                     47: # no expanded material (@key@) below
                     48: $wwwsite= "http://www.parigp-home.de/";
1.2     ! noro       49: $docdir = $ENV{GPDOCDIR} || $ENV{GPHELP_DOCDIR};
        !            50:
        !            51: if (!defined $docdir) {
        !            52:   # work from TOPDIR/Oarch or TOPDIR too: may be uninstalled yet;
        !            53:   for ("$miscdir/doc", './doc', '../doc') {
        !            54:     if (-r "$_/translations") {
        !            55:       $docdir = $_;
        !            56:       last;
        !            57:     }
        !            58:   }
        !            59:   $docdir ||= "$miscdir/doc";  # Last resort
        !            60: }
        !            61:
        !            62: if ($docdir =~ /^\./) {
        !            63:   require Cwd;
        !            64:   $docdir = Cwd::cwd() . "/$docdir";
        !            65: }
1.1       noro       66:
                     67: $xdvi = $ENV{GPXDVI} || "xdvi";
                     68: $xdviref = $ENV{GPXDVIREF} || "$xdvi -paper 29.7x21cm";
                     69: $gzip = "gzip";
                     70: $zcat = "$gzip -dc";
                     71:
                     72: $refcard = (@ARGV and $ARGV[-1] =~ /refcard/i);
                     73:
                     74: $dumb_pod=1, $ARGV[0] = '-to_pod' if @ARGV && $ARGV[0] eq '-to_dumb_pod';
                     75: &to_pod() if @ARGV == 2 && $ARGV[0] eq '-to_pod';
                     76:
                     77: &options(); &init();
                     78: if ($#ARGV < 0) { &treat($_); cleanexit(); }
                     79:
                     80: &pretex() if (!$detex);
                     81: for (@ARGV) { &treat($_); }
                     82:
                     83:
                     84: if ($apropos) { &apropos_final_print(); cleanexit(); }
                     85: if (!$found) { &clean if (!$detex); cleanexit(); }
                     86:
                     87: &posttex() if (!$detex);
                     88:
                     89: print $gpmsg if (!$detex && $fromgp);
                     90: cleanexit();
                     91:
                     92: #
                     93: # Procedures
                     94: #
                     95: sub cleanexit {
                     96:   print "\e[0m" unless $to_pod;
                     97:   exit 0;
                     98: }
                     99:
                    100: sub help {
                    101:   print "Usage: $0 [-k] [-detex] [-ch c1] [-cb c2] [-cu c3] keyword\n";
                    102:   print "where c1,c2,c3 denote background, bold and underline color\n";
                    103:   exit(1);
                    104: }
                    105:
                    106: sub options
                    107: {
                    108:   $raw = $detex = $fromgp = $apropos = 0;
                    109:   $ch = $cb = $cu = '';
                    110:   while ($_ = $ARGV[0])
                    111:   {
                    112:     last if (! /^-[a-z]/);
                    113:     shift(@ARGV);
                    114:     if ($_ eq "-fromgp")
                    115:       { $fromgp = 1; }
                    116:     elsif ($_ eq "-k")
                    117:       { $apropos = 1; }
                    118:     elsif ($_ eq "-detex" || $_ eq "-d")
                    119:       { $detex = 1; }
                    120:     elsif ($_ eq "-raw")
                    121:       { $raw = $detex = 1; }
                    122:     elsif ($_ eq "-color_help" || $_ eq "-ch")
                    123:       { $ch = &color(shift(@ARGV)); }
                    124:     elsif ($_ eq "-color_bold" || $_ eq "-cb")
                    125:       { $cb = &color(shift(@ARGV)); }
                    126:     elsif ($_ eq "-color_underline" || $_ eq "-cu")
                    127:       { $cu = &color(shift(@ARGV)); }
                    128:     else
                    129:       { &help(); }
                    130:   }
                    131:   $detex = 1 if (!$detex && !$ENV{DISPLAY});
                    132: }
                    133:
                    134: sub init
                    135: {
                    136:   $gpmsg = "ugly_kludge_done\n";
                    137:   &inittr();
                    138:
                    139:   $indent = "   ";
                    140:
                    141:   chdir($docdir);
                    142:   $docfile = "usersch3.tex";
                    143:   $tmpdir = $ENV{GPTMPDIR} || $ENV{TMPDIR} || $ENV{GPHELP_TMPDIR} || "/tmp";
                    144:   $texfile = "$tmpdir/gp.help$$";
                    145:
                    146:   open(IN,"translations") || die("Could not find translation file, docdir='$docdir'");
                    147:   while(<IN>)
                    148:   {
                    149:     chomp; @_ = split(/ *\@ */);
                    150:     $key = shift(@_);
                    151:     $transl{$key} = join('@',@_);
                    152:   }
                    153:   close(IN);
                    154: }
                    155:
                    156: sub not_found
                    157: {
                    158:   local($help) = shift;
                    159:   $help =~ s/\\\\/_B#K#S_/g;
                    160:   $help =~ s/\\(.)/$1/g;
                    161:   $help =~ s/_B#K#S_/\\/g;
                    162:   print "'$help' not found !\n";
                    163: }
                    164:
                    165: sub choose_chap
                    166: {
                    167:   while (s/\@([0-9])$//)
                    168:     { $docfile = "usersch$1.tex"; }
                    169:   if (-r $docfile) { $pipe = ""; }
                    170:   else
                    171:   {
                    172:     die "Cannot find $docfile"
                    173:       if (! -r "$docfile.z" &&
                    174:           ! -r "$docfile.gz" &&
                    175:           ! -r "$docfile.Z");
                    176:     $pipe = $zcat;
                    177:   }
                    178: }
                    179:
                    180: use POSIX 'setsid';
                    181:
                    182: sub open_dvi_then_quit
                    183: {
                    184:   local($dvifile, $viewer)= @_;
1.2     ! noro      185:   local($f) = "$dvifile";
        !           186:   $f = "$dvifile.gz" if (! -f "$f");
        !           187:   $f = "$docdir/$dvifile" if (! -f "$f");
        !           188:   $f = "$docdir/$dvifile.gz" if (! -f "$f");
        !           189:   die "could not find $f" if (! -f "$f");
1.1       noro      190:   (!$ENV{DISPLAY} && !$ENV{GPXDVI}) && die "xdvi needs X-Windows";
1.2     ! noro      191:   if ($f =~ /\//) { $dvifile = "$f"; } else { $dvifile = "$docdir/$f"; }
        !           192:   print "displaying \'$dvifile\'.";
1.1       noro      193:   setsid; # detach from terminal (^C will not kill xdvi)
1.2     ! noro      194:   system("$viewer $f 2>/dev/null >/dev/null&");
1.1       noro      195:   cleanexit();
                    196: }
                    197:
                    198: sub treat
                    199: {
                    200:   local($help);
                    201:   $_ = $_[0];
                    202:   s/_QUOTE/'/g;
                    203:   s/_BACKQUOTE/`/g;
                    204:   s/_DOUBQUOTE/"/g;
                    205:   s/^ *"(.*)"([^"]*) *$/$1$2/;
                    206:   if (s/\@$//)
                    207:   {
                    208:     $found = 0;
                    209:     $searchall = 1;
                    210:     $help = $_;
                    211:     while (<usersch*.tex*>)
                    212:     {
                    213:       if (/usersch(.*)\.tex/)
                    214:       {
                    215:         &treat("$help\@$1");
                    216:         if ($apropos && $#list > 0 || $#sentence_list > 0)
                    217:         {
                    218:           print "\nChapter $1:\n";
                    219:           print "==========\n";
                    220:           &apropos_final_print();
                    221:         }
                    222:       }
                    223:     }
                    224:     return not_found($help) if (!$found && !$apropos);
                    225:     $searchall = 0;
                    226:     $apropos = 0; return;
                    227:   }
                    228:   &choose_chap;
                    229:
                    230:   if (!$apropos)
                    231:   {
                    232:     open_dvi_then_quit("users.dvi",$xdvi) if (/^$/);
                    233:     open_dvi_then_quit("tutorial.dvi",$xdvi) if (/^tutorial$/);
                    234:     open_dvi_then_quit("refcard.dvi",$xdviref) if (/^refcard$/);
                    235:   }
                    236:
                    237:   if (!$apropos && $transl{$_}) { $_ = $transl{$_}; &choose_chap; }
                    238:   s/(\W)/\\$1/g;
                    239:       ($pipe && open(DOC,"$pipe $docfile |"))
                    240:   || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!";
                    241:   return &apropos($_) if ($apropos);
                    242:   if (/^\\[<>=!]=?|[|&]{1,2}$/)
                    243:     { $_ = 'Comparison and boolean operators'; }
                    244:   $help = $_;
                    245:   while (<DOC>)
                    246:   {
                    247:     if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){$help}/)
                    248:       { $first = $_; last; }
                    249:   }
                    250:   if (eof(DOC))
                    251:   {
                    252:     &not_found($help) if (!$searchall);
                    253:     return;
                    254:   }
                    255:   $found = 1;
                    256:
                    257:   if (!$detex) { &tex(); return; }
                    258:
                    259:   &detex(); print "\n" if (!$fromgp);
                    260:   do {local $/; <DOC>} if $^O eq 'os2' and $pipe; # Avoid broken pipe from zcat
                    261:   close(DOC);
                    262: }
                    263:
                    264: #
                    265: #  A propos
                    266: #
                    267:
                    268: sub apropos_print_list
                    269: {
                    270:   $current = "";
                    271:   @_ = sort(@_);
                    272:   for (@_)
                    273:   {
                    274:     next if ($_ eq $current);
                    275:     $current = $_; print "$indent$_\n";
                    276:   }
                    277: }
                    278:
                    279: sub apropos_raw_print
                    280: {
                    281:   $indent = "";
                    282:   &apropos_print_list(@sentence_list);
                    283:   &apropos_print_list(@list);
                    284: }
                    285:
                    286: sub apropos_final_print
                    287: {
                    288:   local($maxlen) = 0;
                    289:   local($i,$nbcol,$current);
                    290:   local($cols) = ($ENV{'COLUMNS'} || 80) - 1;
                    291:
                    292:   if ($raw) { &apropos_raw_print(); return; }
                    293:   @list = sort(@list);
                    294:   for (@list)
                    295:   {
                    296:     $i= length($_);
                    297:     $maxlen = $i if ($i > $maxlen);
                    298:   }
                    299:   $maxlen++; $nbcol = $cols / $maxlen;
                    300:   $nbcol =~ s/\..*//;
                    301:   $nbcol-- if  ($nbcol * $maxlen == $cols);
                    302:   $nbcol = 1 if (!$nbcol);
                    303:
                    304:   $current = ""; $i = 0;
                    305:   for (@list)
                    306:   {
                    307:     next if ($_ eq $current);
                    308:     $current = $_; print($_); $i++;
                    309:     if ($i >= $nbcol)
                    310:     {
                    311:       $i=0; print "\n"; next;
                    312:     }
                    313:     print " " x ($maxlen - length($_));
                    314:   }
                    315:   print "\n" if ($i);
                    316:   if ($#sentence_list > 0)
                    317:   {
                    318:     print "\nSee also:\n" if ($#list > 0);
                    319:     $indent = "  ";
                    320:     apropos_print_list(@sentence_list);
                    321:   }
                    322: }
                    323:
                    324: sub apropos_check
                    325: {
                    326:   local($_) = $line;
                    327:   s/\n/ /g;
                    328:   return if (! /$help/);
                    329:
                    330:   $_ = $current;
                    331:   s/\\b{(.)}/\\$1/; s/\{\}//g;
                    332:   s/\\pow/^/; s/\\%/%/; s/\\bs/\\/; s/\\\#/\#/g;
                    333:   s,\+\$/\$-,+/-,;
                    334:   if (/ /) { push(@sentence_list,$_); } else { push(@list,$_); }
                    335: }
                    336:
                    337: sub apropos
                    338: {
                    339:   local($line,$current,$new);
                    340:   $help = $_[0];
                    341:   $help='\\\\pow' if ($help eq '\^');
                    342:   $help='\\\\til' if ($help eq '\~');
                    343:   @sentence_list = @list = "";
                    344:   while (<DOC>)
                    345:   {
                    346:     if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){/)
                    347:     {
                    348:       $new = &get_match($_,'{','}');
                    349:       &apropos_check();
                    350:       $current = $new; $line = "";
                    351:     }
                    352:     $line .= $_;
                    353:   }
                    354:   &apropos_check();
                    355: }
                    356:
                    357: #
                    358: #  Tex Part
                    359: #
                    360: sub pretex
                    361: {
                    362:   open(TEX,">$texfile.tex") || die "Couldn't open $texfile.tex";
                    363:   print TEX << "EOT";
                    364: \\def\\fromgphelp\{\}
                    365: \\input $docdir/parimacro.tex
                    366: EOT
                    367: }
                    368:
                    369: sub tex
                    370: {
                    371:   print TEX "$first";
                    372:   while (<DOC>)
                    373:   {
                    374:     last if /^\\(section|sub[sub]*sec)/i;
                    375:     print TEX;
                    376:   }
                    377:   close(DOC);
                    378: }
                    379:
                    380: sub posttex
                    381: {
1.2     ! noro      382:   print TEX "\\vfill\\eject\\bye";
        !           383:   close(TEX) || die "Error closing '$texfile.tex': $!";
1.1       noro      384:
                    385:   chdir($tmpdir);
1.2     ! noro      386:   $out = `tex $texfile.tex 2>&1 < /dev/null`;
        !           387:   $? == 0 && -f "$texfile.dvi"
        !           388:     || die "could not create '$texfile.dvi': status=$?, $out";
1.1       noro      389:   setsid; # detach from terminal (^C will not kill xdvi)
                    390:   system("($xdvi $texfile.dvi 2>/dev/null >/dev/null; rm -f $texfile.tex $texfile.dvi $texfile.log)&");
                    391: }
                    392:
                    393: sub clean
                    394: {
                    395:   unlink("$texfile.tex","$texfile.dvi","$texfile.log");
                    396: }
                    397:
                    398: #
                    399: #  Detex Part
                    400: #
                    401: sub fit_loop
                    402: {
                    403:   local($i);
                    404:   return if ($miss > 9);
                    405:   while ($miss > 0)
                    406:   {
                    407: #  print "1:$miss ";print @_;print "\n";
                    408:     for (@_) { $miss-- if (s/([?!\.;])$/$1 /);
                    409:        return if ($miss == 0);
                    410:     }
                    411: #  print "2:$miss ";print @_;print "\n";
                    412:     for (@_) { $miss-- if (s/([?!\.;]) $/$1  /);
                    413:        return if ($miss == 0);
                    414:     }
                    415: #  print "3:$miss ";print @_;print "\n";
                    416:     for (@_) { $miss-- if (s/([\),])$/$1 /);
                    417:        return if ($miss == 0);
                    418:     }
                    419: #  print "4:$miss ";print @_;print "\n";
                    420:     $i = 0;
                    421:     for (@_)
                    422:     {
                    423:       if (!$i) { $i = 1; next; }
                    424:       $miss-- if (s/^\(/ (/);
                    425:        return if ($miss == 0);
                    426:     }
                    427: #  print "5:$miss "; print @_;print "\n";
                    428:     for (@_) { $miss--; s/$/ /;
                    429:        return if ($miss == 0);
                    430:     }
                    431:   }
                    432: }
                    433:
                    434: sub fit_line
                    435: {
                    436:   local($wi, @a);
                    437:   local($l) = -1;
                    438:   local($rem) = $_[0];
                    439:   for (@l)
                    440:   {
                    441:      $l2 = $l; $l += ($_ + 1);
                    442:      last if ($l > $rem);
                    443:      $wi++;
                    444:   }
                    445:   $miss = $rem - $l2;
                    446:   splice(@l, 0, $wi);
                    447:   @a = splice(@w, 0, $wi-1); &fit_loop(@a);
                    448:   push(@a, shift(@w)); return join(' ', @a);
                    449: }
                    450:
                    451: # empty output line
                    452: sub is_void {
                    453:   local($in) = shift;
                    454:   $in =~ s/\@\[\w+\]//g;
                    455:   $in =~ s/\@[012]//g;
                    456:   ($in =~ /^\s*$/)? 1: 0;
                    457: }
                    458:
                    459: sub nl {
                    460:   push(@f_text, shift);
                    461: }
                    462:
                    463: sub format_text
                    464: {
                    465:   local($last_void) = 0;
                    466:   local($add_stuff) = 0;
                    467:   local($cols) = ($ENV{'COLUMNS'} || 80) - 1;
                    468:   local($first) = $cols - length($indent);
                    469:
                    470:   for (@text)
                    471:   {
                    472:     if (s/^\@1//)       # start verbatim
                    473:     {
                    474:       nl(&fit_line($first)) if (@w);
                    475:       nl("") if (!$last_void && !is_void($_)); # add empty line
                    476:       nl("$indent$_");
                    477:     }
                    478:     elsif (s/^\@0//)    # verbatim lines
                    479:     {
                    480:       nl("$indent$_");
                    481:     }
                    482:     elsif (s/^\@2//)       # end verbatim
                    483:     {
                    484:       nl("$indent$_");
                    485:       $last_void = is_void($_);
                    486:     }
                    487:     elsif (is_void($_))    # line is empty
                    488:     {
                    489:       next if (!$add_stuff);
                    490:       nl("") if (!$last_void);
                    491:       $last_void = $add_stuff = 0;
                    492:       nl("\@[endbold]$indent" . &fit_line($first));
                    493:       while (@w) { nl(&fit_line($cols)); }
                    494:     }
                    495:     else
                    496:     {
                    497:       $add_stuff = 1; s/^ +//;
                    498:       @_ = split(/ /, $_);
                    499:       for (@_)
                    500:       {
                    501:        s/\Q$tr{nbrk}/ /g; push(@w, $_);
                    502:         # these codes will be replaced by 1 character
                    503:         s/\@\[(obr|cbr|ouml|uuml|agrav|eacute|ldollar|pm|lt|gt|\{|\})]/\@/g;
                    504:         # the rest will be replaced by zero-width characters
                    505:        s/\@\[\w+\]//g;    push(@l, length($_));
                    506:       }
                    507:     }
                    508:   }
                    509: }
                    510:
                    511: # argument has the form s1${open}s2${close}s3
                    512: # Return 's2'. Set $remainder to 's3'.
                    513: sub get_match
                    514: {
                    515:   local ($_, $open, $close) = (shift,shift,shift);
                    516:   local (@tmp, $arg,$parity,$ok);
                    517:   local ($obr) = 1;
                    518:   $parity = ($open eq $close);
                    519:   /$open/; $_ = $'; # remove everything before (and including) first $open
                    520:
                    521:   while ($_) {
                    522:     @tmp = split(/($open|$close)/);
                    523:     while ($#tmp >= 0) {
                    524:       $_ = shift(@tmp);
                    525:       $obr++ if (/^$open$/);
                    526:       if ($parity && $obr == 2) { $ok = 1; last }
                    527:       $obr-- if (/^$close$/);
                    528:       if (!$obr) { $ok = 1; last }
                    529:       $arg .= $_;
                    530:     }
                    531:     last if ($ok);
                    532:     $_ = <DOC>;
                    533:   }
                    534:   $remainder = join('',@tmp);
                    535:   return $arg;
                    536: }
                    537:
                    538: sub detex
                    539: {
                    540:   local ($fun,$args);
                    541:   chomp;
                    542: # 1: get the function "prototype"
                    543:   $fun = &get_match($_,'{','}');
                    544:   # name
                    545:   $fun = &basic_subst($fun);
                    546:   $_ = $remainder;
                    547:   # args as $(x)$ in \subsecidx{sin}$(x)$:
                    548:   if (/^ *\$/)
                    549:   {
                    550:     $args = &basic_subst(&get_match($_,'\$','\$'));
                    551:     $_ = $remainder;
                    552:   }
                    553:   $_ = <DOC> if (!&basic_subst($_));
                    554:   # dft value as (...) in \subsecidx{echo} (default \kbd{0})
                    555:   if (/^ *\(/)
                    556:   {
                    557:     $args .= ' (' . &basic_subst(&get_match($_,'\(','\)')) . ')';
                    558:     $_ = $remainder;
                    559:   }
                    560:   $args .= ":" if ($args !~ /: *$/ && ($args || $fun !~ /: */));
                    561:
                    562:   $fun = "\@[startbold]$fun\@[endbold]$args";
                    563:   if ($raw) { print("$fun "); } else { &TeXprint($fun); }
                    564: # 2: start parsing the function description
                    565:   if ($_) { s/^ *://; &presubst(); }
                    566:   while (<DOC>)
                    567:   {
                    568:     last if /^\\(section|sub[sub]*sec)/i;
                    569:     &presubst();
                    570:   }
                    571:   if ($raw) { print join("\n", @text); return; }
                    572:
                    573:   &format_text();
                    574:   for (@f_text) { &TeXprint("$_"); }
                    575: }
                    576:
                    577: # We use the special char @ to transmit special sequences
                    578: sub inittr {
                    579:   @ou = qw( dollar nbrk startbold endbold startcode endcode
                    580:            obr cbr uuml ouml agrave eacute
                    581:            startpodcode endpodcode startlink endlink
                    582:            startbcode endbcode startbi endbi startit endit
                    583:            startword endword startlword endlword pm empty gt lt podleader );
                    584:
                    585:   @tr{@ou} = map "\@[$_]", @ou;
                    586:   $tr{dollar} = '$' if $to_pod;
                    587:
                    588:   %pr = ( dollar => '',
                    589:          ldollar => '$',       # literal dollar
                    590:          nbrk => 'S< >',
                    591:          startbold => 'B<',
                    592:          endbold => '>',
                    593:          startcode => 'C<',
                    594:          startlink => 'L<',
                    595:          endlink => '>',
                    596:          endcode => '>',
                    597:          obr => '{',
                    598:          cbr => '}',
                    599:          startpodcode => 'C<',
                    600:          endpodcode => '>',
                    601:          ( $dumb_pod
                    602:            ? (startbcode => 'B<',
                    603:               endbcode => '>',
                    604:               startbi => 'B<',
                    605:               endbi => '>',)
                    606:            : (startbcode => 'B<C<',
                    607:               endbcode => '>>',
                    608:               startbi => 'B<I<',
                    609:               endbi => '>>')),
                    610:          startit => 'I<',
                    611:          endit => '>',
                    612:          startword => 'F<',
                    613:          endword => '>',
                    614:          startlword => ' F<',
                    615:          endlword => '> ',
                    616:          pm => 'F<+->',
                    617:          "gt" => 'E<gt>',
                    618:          "lt" => 'E<lt>',
                    619:          ouml => 'E<ouml>',
                    620:          uuml => 'E<uuml>',
                    621:          eacute => 'E<eacute>',
                    622:          agrave => 'E<agrave>',
                    623:          empty => 'Z<>',
                    624:          podleader => '=',
                    625:        );
                    626: }
                    627:
                    628: sub indent_equally { my $in = shift; $in =~ s/^[ \t]*/    /mg; $in}
                    629:
                    630: sub basic_subst
                    631: {
                    632:   local($_) = shift;
                    633:
                    634:   s/(\S)[ \t]*\n[ \t]+/$1\n/gm;
                    635:   s/([^\\])\\\{/$1$tr{obr}/g;
                    636:   s/([^\\])\\\}/$1$tr{cbr}/g;
                    637:   s/([^\\])\\-/$1/g;
                    638:   s/\A\\q?quad(?![a-zA-Z])\s*/$tr{nbrk}$tr{nbrk}/;
                    639:   s|\\wwwsite|$wwwsite|g;
                    640:   s|\\miscdir|$miscdir|g;
                    641:   s/^\\def\\.*\{\n.*\n\}//gm;
                    642:   s/\\def\\.*//g;
                    643:   s(\\footnote\s*\{?\*+\}?\s*\{\s*((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\})
                    644:     {$tr{startbold}FOOTNOTE$tr{endbold}$tr{lt}$tr{lt}$tr{lt} $1 $tr{gt}$tr{gt}$tr{gt}}g;
                    645:   s/(\{[\w\s]+)\{\}([\s\w]+\})/$1$2/g; # {nf{}init}
                    646:   s(\\op(?![a-zA-Z])\s*)({\\it op\\/})g;       # {nf{}init}
                    647:   s/\\(leavevmode|strut)(?![a-zA-Z])\s*//g;
                    648:   s/ \\funno \s*
                    649:      { \s* ((?:[^{}]|\{[^{}]*\})*) } \s*
                    650:      { \s* ((?:[^{}]|\{[^{}]*\})*) } \s*
                    651:      { \s* ((?:[^{}]|\{[^{}]*\})*) }
                    652:    /\\noindent{\\tt $1 \$\\key{$2}\$($3)}/gx;
                    653:   s/\\funs\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*\{((?:[^{}]|\{[^{}]*\})*)\}/\\fun{}{$1}{$2}/g;
                    654:   s/\\fun\s*\{([^{}]*)\}\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*\{((?:[^{}]|\{[^{}]*\})*)\}/\\kbd{$1 \\key{$2}($3)}\\sidx{$2}/g;
                    655:
                    656:   s/\\\\(?=[a-zA-Z])/\\bs /g;
                    657:   s/\\b{}\\b{}/\\bs\\bs /g;
                    658:   s/\\\\/\\bs/g;
                    659:   s/(\'\'|\`\`)/"/g unless $to_pod;     # (english) double quotes
                    660:   # asymptotic or isomorphic (~) [beware of ties]
                    661:   s/(^|[^\\]) +~/$1~/;
                    662:   s/~ */~/;
                    663:   s/(^|[^\\])~/$1$tr{nbrk}/g;           # ties
                    664:   s/\\(simeq|sim|approx)(?![a-zA-Z])/ ~ /g;
                    665:   s/\\til(?![a-zA-Z])/~/g;             # ~ (transpose)
                    666:   s/\\(~|tilde)/~/g;
                    667:
                    668:   s/\\(equiv)(?![a-zA-Z])/ = /g;
                    669:   s/\\`a/$tr{agrave}/; s/\\`{a}/$tr{agrave}/;
                    670:   s/\\"o/$tr{ouml}/;   s/\\"{o}/$tr{ouml}/;
                    671:   s/\\"u/$tr{uuml}/;   s/\\"{u}/$tr{uuml}/;
                    672:   s/\\'e/$tr{eacute}/; s/\\'{e}/$tr{eacute}/;
                    673:
                    674:   s/(^|[^\\])%.*/$1/g;                 # comments
                    675:   s/\\vadjust\s*\{\s*\\penalty\s*\d+\s*\}//g;
                    676:
                    677:   # We do not strip %\n, thus:
                    678:   s/\\kbd{\n\s*/\\kbd{/g;
                    679:   s/\$\\bf(\b|(?=[\d_]))\s*([^\$]+)\$/\$$tr{startbcode}$1$tr{endbcode}\$/g;
                    680:   s/\$/$tr{dollar}/g;                  # math mode
                    681:   s/\t/ /g; s/\\,//g; s/\\[ ;]/ /g;     # various spaces
                    682:   s/\\\///g;                   # italic correction
                    683:   s/^&+//g;                    # tab marks
                    684:   s/([^\\])&+/$1 /g;           # tab marks
                    685:   s/\\TeX\{\}/TeX/g;
                    686:   s/\\TeX(\W)/TeX$1/g;
                    687:   s/ *\\circ\b */ o /g;
                    688:   s/\\d?frac{\s*((?:[^{}]|\{[^{}]*\})*)}{\s*((?:[^{}]|\{[^{}]*\})*)}/($1)\/($2)/g;
                    689:   s(\\d?frac\s*(\d)\s*(\d))(($1/$2))g;
                    690:   s[{\s*(\w)\s*\\over(?![a-zA-Z])\s*(\w)\s*}]{($1/$2)}g;
                    691:   s[{\s*((?:[^{}]|\{[^{}]*\})*)\\over(?![a-zA-Z])\s*((?:[^{}]|\{[^{}]*\})*)}][($1)/($2)]g;
                    692:
                    693:   # \def\synt#1#2{\syn{#1}{\tt #2}}
                    694:   # \def\syn#1#2{\synx{#1}{#2}{#1}}
                    695:   s/\\synt?\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\synx{$1}{$2}{$1}/g;
                    696:   # \def\synx#1#2#3{\sidx{#3}The library syntax is $\key{#1}({#2})$}
                    697:   # Often used with embedded {}.
                    698:   s/\\synx\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{((?:[^{}]|\{[^{}]*\})*)\}/\\sidx{$3}The library syntax is $tr{startbold}$1$tr{endbold}$tr{startpodcode}($2)$tr{endpodcode}/;
                    699:
                    700:   # May be used with an empty arg
                    701:   s/\\typ\{([^\}]*)\}/$tr{startcode}t_$1$tr{endcode}/g;
                    702:
                    703:   s/(\\string)?\\_/_/g;
                    704:   s/\\([#\$&%|])/$1/g;
                    705:   s/\\(hat(?![a-zA-Z])|\^)({\\?\s*})?/^/g;
1.2     ! noro      706:   s/^(\@\[podleader\]head\d *)\\pow(?![a-zA-z])( *)/$1^$2/gm;
1.1       noro      707:   s/ *\\pow(?![a-zA-z]) */^/g;
                    708:
                    709:   s/\\neq?(?![a-zA-Z])/ != /g;
                    710:   s/\\enspace(?![a-zA-Z])/ /g;
                    711:   s/\\times(?![a-zA-Z]) */ x /g;
                    712:   s/\\infty(?![a-zA-Z]) */ oo /g;
                    713:   s/ *\\(bmod|mod) */ mod /g;
                    714:   s/ *\\pmod(?![a-zA-Z]) *\{\s*((?:[^{}]|\{[^{}]*\})*)\}/ (mod $1)/g;
                    715:   s/ *\\cdot(?![a-zA-Z]) */./g;                # Maybe " . "?
                    716:   s/ *(\\|\@)[lc]?dots(?![a-zA-Z]) */.../g;
                    717:   s/\\(log|sin|cos|lim(proj)?|tan|mod|sqrt|exp|ln|det|Re|Im|deg|wp|cap|oplus)(?![a-zA-Z])/$tr{startlword}$1$tr{endlword}/g;
                    718:   s/\\pi(?![a-zA-Z])/$tr{startword}Pi$tr{endword}/g;
                    719:   s/\\(Alpha | Beta | Chi | Delta | Epsilon | Phi | Gamma
                    720:        | Eta | Iota | vartheta | Kappa | Lambda | Mu | Nu | Omicron
                    721:        | Pi | Theta | Rho | Sigma | Tau | Ypsilon | varsigma | Omega
                    722:        | Xi | Psi | Zeta | alpha | beta | chi | delta | varepsilon | phi | gamma
                    723:        | eta | iota | varphi | kappa | lambda | mu | nu | omicron
                    724:        | pi | theta | rho | sigma | tau | ypsilon | varpi | omega
                    725:        | xi | psi | zeta | int
                    726:        | expr | seq | args | gcd | sum | prod | Re | infty )
                    727:       (?![a-zA-Z])/$tr{startword}$1$tr{endword}/xg;
                    728:   s/ *\\in(?![a-zA-Z]) */ belongs to /g;
                    729:   s/\\pm(?![a-zA-Z])/$tr{pm}/g;
                    730:   s/ *\\mid(?![a-zA-Z]) */ | /g;
                    731:
                    732:   s/\\idxtyp\{([^{}]*)\}/\\sidx{t_$1}/g;
                    733:   s/\\ref\{[^\}]*\}/$tr{startbold}??$tr{endbold}/g unless $to_pod;
                    734:   s/\\secref\{[^\}]*\}/Section ($tr{startbold}??$tr{endbold})/g unless $to_pod;
                    735:   s/\\label\{[^\}]*\}//g unless $to_pod;
                    736:
                    737:   s/\\(noindent|medskip|bigskip|smallskip|left|right)(?![a-zA-Z])[ \t]*//g;
                    738:   s/\\vfill *(\\eject)?//g;
                    739:   s/\\(q|quad)(?![a-zA-Z])\s*/  /g;
                    740:   s/\\qquad(?![a-zA-Z])\s*/    /g;
                    741:
                    742:   s/\\centerline\s*\{\s*(?:\\tt\b\s*)?(.*(\n[ \t].*)*)\}(?=\s*$)/indent_equally($1)/ge;
                    743:   s/\\centerline\s*\{\s*(?:\\tt\b\s*)?((?:[^{}]|\{[^{}]*\})*)\}/ indent_equally($1)/ge;
                    744:
                    745:   s/\\big\b//g;
                    746:
                    747:   s/\\settabs.*//;
                    748:   s/^\\\+/$tr{nbrk}/gm;
                    749:   s/\\\+//g;
                    750:   s/\\cr(?![a-zA-Z])//g;
                    751:   s/\\B(?![a-zA-Z])/\\kbd{BIL}/g;
                    752:
                    753:   s/ *([=><]) */ $1 /g;
                    754:   s/ *<  *([=<]) */ <$1 /g;
                    755:   s/ *>  *([=>]) */ >$1 /g;
                    756:   s/ *([*+-\/^&=|:]) += */ $1= /g;
                    757:   s/ *\\Rightarrow */ ==$tr{gt} /g;
                    758:   s/\\rangle(?![a-zA-Z])\s*/$tr{startcode}$tr{gt}$tr{endcode}/g;
                    759:   s/\\langle(?![a-zA-Z])\s*/$tr{startcode}$tr{lt}$tr{endcode}/g;
                    760:   s/\\rightarrow(?![a-zA-Z])\s*/$tr{startcode}--$tr{gt}$tr{endcode}/g;
                    761:   s/\\longleftrightarrow(?![a-zA-Z])\s*/$tr{startcode}$tr{lt}-----$tr{gt}$tr{endcode}/g;
                    762:   s/\\mapsto(?![a-zA-Z])\s*/$tr{startcode}|---$tr{gt}$tr{endcode}/g;
                    763:   s/ *\\geq?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{gt}=$tr{endcode} $1/g;
                    764:   s/ *\\leq?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{lt}=$tr{endcode} $1/g;
                    765:
                    766:   s/\\(vers|PARIversion)(?![a-zA-Z])/$tr{startbold}$version$tr{endbold}/;
                    767:   s/\\([QRCFZNapdf])(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g;
                    768:   s/\\([QRCFZN])\1(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g;
                    769:   s/\\Bbb\b\s*(\w)/$tr{startbi}$1$tr{endbi}/g;
                    770:
                    771:   s/\\([oc]br)/$tr{$1}/g;
                    772:   s/\\quo(?![a-zA-Z])/\"/g;
                    773:   s/(^|\s)\{(\w+)\}/$1$2/g;
                    774:
                    775:   s/\\p(?![a-zA-Z])/$tr{startbold}p$tr{endbold}$1/g;
                    776:   s/\\point\{([^\}]*)\}/$tr{startbold}* $1$tr{endbold}/g;
                    777:   s/\\bullet/$tr{startbold}*$tr{endbold}/g;
                    778:   s/\\misctitle\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g;
                    779:   s/\\subsec\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g unless $to_pod;
                    780:   s/\\teb\{([^\}]*)\}/\\sidx{$1}$tr{startbold}$1$tr{endbold}/g;
                    781:   s/\\tet\{([^\}]*)\}/\\sidx{$1}$tr{startcode}$1$tr{endcode}/g;
                    782:   s/\\tev\{([^\}]*)\}/\\sidx{$1}$tr{startit}$1$tr{endit}/g;
                    783:   s/\\\$/$tr{ldollar}/g;
                    784:   s/\\kbd\s*\{\s*</\\kbd{$tr{lt}/g if $to_pod;
                    785:   s/\\kbd\s*\{\s*>/\\kbd{$tr{gt}/g if $to_pod;
                    786:   s/\\kbd\s*\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startcode}$1$tr{endcode}/g;
                    787:
                    788:   s/\\key\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g unless $refcard;
1.2     ! noro      789:   s/\\goth\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g;
1.1       noro      790:
                    791:   if ($refcard) {
                    792:     s/\\(?:key|li)\{((?:[^{}]+(?=[{}])|\{[^{}]*\})*)\}\s*\{\}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/g;
                    793:     s/\\(?:key|li)\{((?:[^{}]+(?=[{}])|\{[^{}]*\})*)\}\s*\{(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/\n=item $tr{startcode}$2$tr{endcode}\n\n$1\n/g;
                    794:   }
                    795:
                    796:   s/\\var\{([^\}]*)\}/$tr{startit}$1$tr{endit}/g;
                    797:   s/\\fl(?![a-zA-Z])/$tr{startit}flag$tr{endit}/g;
                    798:   s/\\b{([^}]*)}/$tr{startcode}\\$1$tr{endcode}/g;
                    799:   s/\\kbdsidx/\\sidx/g;
                    800:   s/\\sidx\{[^\}]*\}//g unless $to_pod;
                    801:   s/\\[a-zA-Z]*idx\{([^\}]*)\}/$1/g unless $to_pod;
                    802:   s/\\(?:text|hbox)\s*\{ *(?:\\it\b\s*)?(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$1/g;
                    803:   s/\\(text|hbox)//g;
                    804:   s/^([ \t]+)\{ *\\(it|sl|bf|tt)\b/S<$1>{\\$2/gm;
                    805:   s/\{ *\\(it|sl) *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startit}$2$tr{endit}/g;
                    806:   s/\{ *\\bf *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g;
                    807:   s/\{ *\\tt *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startpodcode}$1$tr{endpodcode}/g;
                    808:   $seek=1 if (s/\{ *\\it */$tr{startit}/g);
                    809:   if ($seek) { $seek=0 if (s/\}/$tr{endit}/) }
                    810:   s/\\(backslash|bs)\{(\w)\}/\\$2/g;
                    811:   s/\\(backslash|bs)(?![a-zA-Z]) */\\/g;
                    812:
                    813:   s/\@com(.*)$/$tr{startcode}$1$tr{endcode}/g;
                    814:
                    815:   # Last resort:
                    816:   s/\\kbd\s*\{(.*?)\}/$tr{startcode}$1$tr{endcode}/g;
                    817:   s/^([ \t]{3,})\Q$tr{startcode}\E(.*)\Q$tr{endcode}\E/$1$2/gmo if $to_pod;
                    818:   # Last resort:
                    819:   s/^([ \t]{3,})\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1$2/gmso if $to_pod;
                    820:   # Remove leading spaces unless have embedded wrapped code:
                    821:   s/^[ \t]+//gm if $to_pod and /^\S/ and not /^[ \t]*\n[ \t]/m;
                    822:   s/\{ *\}//g;                 # empty args
                    823:
                    824:   s{\Q$tr{startcode}\E((ftp|http)://.*?)\Q$tr{endcode}\E}{$tr{startlink}$1$tr{endlink}}go if $to_pod;
                    825:   $_;
                    826: }
                    827:
                    828: sub presubst {
                    829:   chomp;
                    830:   if ($in_prog && /(\\|\@)eprog/)
                    831:   {
                    832:     $in_prog = 0;
                    833:     $_ = "\@2" . &code_subst($`) . $tr{endcode};
                    834:     push(@text, $_);
                    835:     $_ = &basic_subst($');
                    836:   }
                    837:   elsif ($in_prog || s/\\bprog(tabs.*)?//g)
                    838:   {
                    839:     $in_prog++;  # = 1 on the \bprog line
                    840:                  # code should start on the next line
                    841:     $_ = &code_subst($_);
                    842:     s/^/\@1$tr{startcode}/ if ($in_prog == 2);
                    843:     s/^/\@0/ if ($in_prog > 2);
                    844:   }
                    845:   else { $_ = &basic_subst($_); }
                    846:   push(@text, $_);
                    847: }
                    848:
                    849: sub code_subst {
                    850:   my $in = shift;
                    851:   $in =~ s/\@dots\b/.../g;
                    852:   $in =~ s/\@miscdir\b/$miscdir/g;
                    853:   if ($in =~ /\@com(.*)/)
                    854:   {
                    855:     if ($to_pod) {
                    856:       $in = $` . &basic_subst($1) . code_subst($');
                    857:     } else {
                    858:       $in = $` . $tr{endcode} . &basic_subst($1) . $tr{startcode} . code_subst($');
                    859:     }
                    860:   }
                    861:   if ($in =~ /\@Ccom(.*)\*\//)
                    862:   {
                    863:     if ($to_pod) {
                    864:       $in = $` .               &basic_subst($1) . "*/" . &code_subst($');
                    865:     } else {
                    866:       $in = $` . $tr{endcode} . &basic_subst($1) . $tr{startcode}
                    867:                                                  . "*/" . &code_subst($');
                    868:     }
                    869:   }
                    870:   $in;
                    871: }
                    872:
                    873: sub wrap_code {
                    874:   my $in = shift;
                    875:   $in =~ s/^[ \t]+$//mg;
                    876:   $in = &code_subst($in);
                    877:   $in =~ s/^(.)/  $1/mg;
                    878:   $in =~ s/\s*\Z//;
                    879: #  $in =~ s/\\kbd\{((?:[^{}]|\{[^{}]*\})*)\}/$1/g if $to_pod;
                    880:   $in =~ s/\$([^\$\n]*)\$/$1/g if $to_pod;
                    881:   "\n\n$in\n\n";
                    882: }
                    883:
                    884: sub indexify {
                    885:   my $in = shift;
                    886:   $in =~ s/(^|and\s+)(\w+)(\$?\()/$1\\idx{$2}$3/g;
                    887:   $in =~ s/^(\\b\{\w+\})(?!\S)/\\idx{$1}/g;
                    888:   $in;
                    889: }
                    890:
                    891: sub for_index {
                    892:   my $in = shift;
                    893:   1 while $in =~ s/\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1/go;
                    894:   $in;
                    895: }
                    896:
                    897: sub strip_trail { my $in = shift; $in =~ s/\s+\Z//; $in }
                    898:
                    899: # This subroutine works in paragraph mode
                    900: sub TeXprint_topod {
                    901:   s/\A\s+//;
                    902:   s/^\\def\\.*\{\n.*\n\}//gm;
                    903:   s/\\def\\.*//g;              # Repeated in basic_subst, as the next one
                    904:   s/(\{[\w\s]+)\{\}([\s\w]+\})/$1$2/g; # {rnf{}llgram}
                    905:
                    906:   s/\\vbox\s*\{\s*\\bprog/\\bprog/g;
                    907:   s/([\\\@])eprog\s*\}/$1eprog/g;
                    908:
                    909:   #  \n is below to prevent splitting on ' '
                    910:   #  We also remove ':'
                    911:   s/\\sectype\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$2}/g;
                    912:   s/\\sectypeindex\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$3}/g;
                    913:   s/\\sectypes\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} and \\typ{$1} (${3}s)}\n\\sidx{$3}/g;
                    914:
                    915:   # Try to guard \label/\sidx (removing possible '.')
                    916: #  This somehow breaks index...
                    917: #  s/(\\(?:section|subsec(?:ref|idx|op)?(unix)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/;
                    918:   s/(\\(?:section|subsec(?:ref|idx|op)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/;
                    919:
                    920:   # last if /\\subsec[\\{}ref]*[\\\${]$help[}\\\$]/o;
                    921:   s/\\chapter\s*{((?:[^{}]|\{[^{}]*\})*)}\s*/\n\n$tr{podleader}head1 NAME\n\nlibPARI - $1\n\n$tr{podleader}head1 DESCRIPTION\n\n/;
                    922:   s/\\appendix\s*{((?:[^{}]|\{[^{}]*\})*)}\s*/\n\n$tr{podleader}head1 NAME\n\nAppendix - $1\n\n$tr{podleader}head1 DESCRIPTION\n\n/;
                    923:   s/\\section\s*{((?:[^{}]|\{[^{}]*\})*)}\s*/"\n\n$tr{podleader}head1 " . indexify($1) . "\n\n"/e;
                    924:
                    925:   # Try to delimit by :
                    926:   s/\\subsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}((\W*default:)?[^\n:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
                    927:   s/\\subsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^\n:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
                    928:   s/\\subsubsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}item " . indexify("$1$3") . "\n\n"/e;
                    929: #  s/\\subsubsec\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}\s*$/"\n\n$tr{podleader}item " . indexify("$1") . "\n\n"/e;
                    930:   s/\\subsubsec\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(.*)$/"\n\n$tr{podleader}item " . indexify("$1") . "$3\n\n"/me;
                    931: #  s/\\subseckbd\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}:\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e;
                    932:   s/\\subseckbd\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
                    933:   # Try to delimit by ' '
                    934:   s/\\subsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
                    935:   s/\\subsec(?:ref|title|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]*})+)}:?\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e;
                    936:
                    937:   # This is to skip preface in refcard:
                    938:   /\Q$tr{podleader}\Ehead1|\\title(?![a-zA-Z])\s*\{/o and $seen_start = 1
                    939:     or $seen_start or return;  # Skip now!
                    940:
                    941:   s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/$tr{podleader}head1 NAME\n\n$1 - $3.  $5\n\n/ and $seen_title++
                    942:     unless $seen_title;
                    943:   s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/\n\n/;
                    944:   s/\\parskip.*/\n/g;          # Up to end of the line
                    945:   #s/([A-Z])\</$1 < /g;                # Disambiguate with POD...
                    946:
                    947:   # Duplicate removal of settabs, since they may contain \hskip
                    948:   s/\\settabs.*//;
                    949:   s/^[ \t]*\\hskip\s*\w+/$tr{nbrk}/g;
                    950:   s/[ \t]*\\hskip\s*\w+/\n$tr{nbrk}/g;
                    951:   1 while s/ \\
                    952:             ( (small|big)skip | newcolumn | noindent
                    953:             | (short)?copyrightnotice | hfill | break | par
                    954:             | leavevmode | strut | endgroup | bye
                    955:              )
                    956:             (?![a-zA-Z])[ \t]*(\n\s*)
                    957:             /\n\n/gx;
                    958:
                    959:   s/'(\W)'/{\\tt '$1'}/g;
                    960:   s/(\\\w+)(\\hbox)/$1 $2/g;
                    961:   s/\\hbox\s*\{(?:\\it\b\s*)?((?:\\[\{\}]|[^{}]|\{[^{}]*\})*)\}/$1/g;
                    962:
                    963:   # substitute non-verbatim code
                    964:   $acc = '';
                    965:   pos = 0;
                    966:   while ( s/\A(.*?)\\bprog//s ) {
                    967:     $acc .= basic_subst(strip_trail($1));
                    968:     $_ .= <DOC> until /(\\|@)eprog\b/ or eof(DOC);
                    969:     $acc .= wrap_code($1) if s/\A(?:tabs[^\n]*)?(?![a-zA-Z])[ \t]*\n?(.*?)(\\|@)eprog\s*//s;
                    970:   }
                    971:   $_ = $acc . basic_subst($_);
                    972:
                    973: #  s/\\kbd\{/\{\\tt /g;                # startcode
                    974: #  s/\\typ\{/\{\\tt t_/g;      # startcode
                    975:
                    976:   s/\$\s*(\@\[startbi\][A-Z]\@\[endbi\])\s*\$/$1/g;
                    977: #  s/\\p(\b|(?=[\d_]))/B<p>/g;
                    978:   #s/\$\\bf\b\s*([^\$]+)\$/C<B<$1>>/g;
                    979:
                    980:   @lines = split /^$/m, $_;
                    981:   for (@lines) {
                    982:     s/>/\@[gt]/g unless /^\n*[ \t]/;
                    983:     s/</\@[lt]/g unless /^\n*[ \t]/;
                    984:   }
                    985:   $_ = join '', @lines;
                    986:
                    987:   s/\$\$(.*?)\$\$\s*/\n\nS<  >$tr{startcode}$1$tr{endcode}\n\n/gs;
                    988:   s/\$([^\$]+)\$/$tr{startcode}$1$tr{endcode}/g;
                    989:
                    990:   s/\\s(?:ref|idx){\s*([^{}]*)}/"X<" . for_index($1) . ">"/ge; #
                    991:   s/\\(?:ref|idx){\s*([^{}]*)}/"X<" . for_index($1) . ">$1"/ge;
                    992:
                    993: # Conflict between different versions of PARI and refcard:
                    994: # s/\\(?:key|li)\s*{(.*)}\s*{(.+)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/msg;
                    995: # s/\\(?:key|li)\s*{(.*)}\s*{}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/mgs;
                    996: # s/\\(key|var)(?![a-zA-Z])\s*{(\w+)}/C<$2>/mg;
                    997:   s/\\var\s*{X<(\w+)>(\w+)}/X<$1>$tr{startcode}$2$tr{endcode}/mg;
                    998:   s/\\var\s*{f{}lag}/$tr{startcode}flag$tr{endcode}/mg;
                    999:
                   1000:   s/\\metax(?![a-zA-Z])\s*{(.*)}\s*{\s*(\w+)(?=C\<)(.*)}[ \t]*\n/\n\n=item C<L<$2>$3>\n\n$1\n\n/mg;
                   1001:   s/\\metax(?![a-zA-Z])\s*{(.*)}\s*{(.*)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg;
                   1002:   s/C\<\{\}=/C\<=/g;
                   1003:   s/\\fl(?![a-zA-Z])/I<flag>/g;
                   1004:   s/\\file(?![a-zA-Z])/F<file>/g;
                   1005:   s/\\(unix|emacs)\b\s*(\{?)(\s*\\(no)?indent)?\s*/X<\U$1>$2/g;
                   1006:   s/\A\\label\s*\{([\w:.-]*)\}([ \t]*\n\s*(?=[^\s=]))?/X<Label $1>/g;
                   1007:   s/\\label\s*\{([\w:.-]*)\}/X<Label $1>/g;
                   1008:   s/\\secref\s*\{([\w:.-]*)\}/L<Label $1>/g;
                   1009:   s/\\begin(double)?indentedkeys\s*/\n\n=over\n\n/g;
                   1010:   s/\\end(double)?indentedkeys\s*/\n\n=back\n\n/g;
                   1011:   # begin/end group appear in very special context only
                   1012:   s/\\begingroup\W.*//s;               # Eat to the end
                   1013:   s/\n{3,}/\n\n/g;
                   1014:   s/\\subsec\{((?:[^{}]|\{[^{}]*\})+)\}\s*/\n\n=back\n\nB<$1>\n\n=over\n\n/g; # In refcard
                   1015:   # for refcard:
                   1016:   s/{\\rm(?![a-zA-Z])\s*([^{}]*)}/$1/g;
                   1017:   s/\\Z<>/\\/g;                        # Optimize for readability
                   1018:
                   1019:   # Now replace the POD stuff
                   1020:   # Start with cosmetic stuff:
                   1021:   $in_code = 0;
                   1022:   s/(\@\[((start)|end)code\])/ ($3 ? $in_code++ : --$in_code) ? "" : $1 /ge;
                   1023:
                   1024:   if ($dumb_pod) {
                   1025:     my @stack;
                   1026:     s /(\@\[((start)|end)(\w+)\])/
                   1027:       if ($3) {                        # Start
                   1028:        push @stack, $4;
                   1029:        (@stack > 1 ? "\@[end$stack[-2]]" : '') . $1
                   1030:       } else {                 # end
                   1031:        pop @stack;
                   1032:        $1 . (@stack ? "\@[start$stack[-1]]" : '')
                   1033:       }
                   1034:       /ge
                   1035:   }
                   1036:   1 while s/\@\[start(\w+)\](\s*)\@\[end\1\]/$2/g;
                   1037:
                   1038:   s/\@\[(\w+)\]/\@!$pr{$1}/g;
                   1039:   s/(\\\w+)\@!(\w)/$1 $2/g;
                   1040:   s/\@!//g;
                   1041:   s/\\([\{\}])/$1/g;
                   1042:
                   1043:   # Normalize the spacing
                   1044:   s/\n{3,}/\n\n/;
                   1045:   s/\A([ \t]*\n)+//;
                   1046:   # Single label is not healthy...
                   1047:   print "\n" if $last_glued and /\A=/; # POD markup needs a new paragraph
                   1048:   $last_glued = s/((\A|\n\n)(X<[^<>]+>)+)[ \t]*\n\n/$1\n/;
                   1049:
                   1050:   print;
                   1051: }
                   1052:
                   1053: sub color
                   1054: {
                   1055:   local($a);
                   1056:   $_ = $_[0];
                   1057:   if (/[^0-9]/ || $_ < 0 || $_ > 17)
                   1058:     { print "bad color in gphelp: $_\n"; return ""; }
                   1059:   if ($_ < 8) { $a = $_ + 30; } else { $a = $_ + 82; }
                   1060:   return "\e[0;${a}m";
                   1061: }
                   1062:
                   1063: sub TeXprint
                   1064: {
                   1065:   local($_) = $_[0];
                   1066:   s/\@\[obr\]/{/g;
                   1067:   s/\@\[cbr\]/}/g;
                   1068:   # This should better be put in Latin1...  Or Win1251?  ;-)
                   1069:   s/\@\[ouml\]/"o/g;
                   1070:   s/\@\[uuml\]/"u/g;
                   1071:   s/\@\[agrave\]/`a/g;
                   1072:   s/\@\[eacute\]/'e/g;
                   1073:   s/\@\[ldollar\]/\$/g;
                   1074:   s/\@\[end(bold|code|bcode|bi|it)\]/\e[m$ch/g;
                   1075:   s/\@\[start(bold|code|bcode|bi)\]/$cb\e[1m/g;
                   1076:   s/\@\[startit\]/$cu\e[4m/g;
                   1077:   s/\@\[(dollar|empty|endl?word|endpodcode|startl?word|startpodcode)\]//g;
                   1078:   s/\@\[pm\]/±/g;
                   1079:   s/\@\[lt\]/</g;
                   1080:   s/\@\[gt\]/>/g;
                   1081:   s/\\([\{\}])/$1/g;
                   1082:   s/\@\[nbrk\]/ /g; print "$_\n";
                   1083: }
                   1084:
                   1085: sub to_pod {
                   1086:   $to_pod = $ARGV[1];
                   1087:   inittr();
                   1088:   $parifile = $to_pod;
                   1089:   %compress = ('.gz', 'gzip -cd',
                   1090:               '.z', 'gzip -cd',
                   1091:               '.Z', 'zcat',
                   1092:              );
                   1093:   foreach $suffix (keys %compress) {
                   1094:     ($patt = $suffix) =~ s/(\W)/\\$1/;
                   1095:     if ($to_pod =~ /$patt$/) {
                   1096:       $pipe = $compress{$suffix};
                   1097:       last;
                   1098:     }
                   1099:   }
                   1100:   if ($pipe) {
                   1101:     open(DOC,"$pipe $parifile |") ||
                   1102:       die "Cannot open pipe $pipe from $parifile: $!, stopped";
                   1103:   } else {
                   1104:     open(DOC,$parifile) || die "Cannot find file $parifile: $!, stopped";
                   1105:   }
                   1106:   $/='';                       # Paragraph mode
                   1107:   while (<DOC>) {
                   1108:     &TeXprint_topod();
                   1109:   }
                   1110:   if ($pipe) {
                   1111:     close(DOC) || die "Cannot close pipe `$pipe $parifile': $!, stopped";
                   1112:   } else {
                   1113:     close(DOC) || die "Cannot close file $parifile: $!, stopped";
                   1114:   }
                   1115:   cleanexit();
                   1116: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>