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

File: [local] / OpenXM_contrib / pari / doc / Attic / gphelp.in (download)

Revision 1.1.1.1 (vendor branch), Sun Jan 9 17:35:29 2000 UTC (24 years, 5 months ago) by maekawa
Branch: PARI_GP
CVS Tags: maekawa-ipv6, VERSION_2_0_17_BETA, RELEASE_20000124, RELEASE_1_2_3, RELEASE_1_2_2_KNOPPIX_b, RELEASE_1_2_2_KNOPPIX, RELEASE_1_2_2, RELEASE_1_2_1, RELEASE_1_1_3, RELEASE_1_1_2
Changes since 1.1: +0 -0 lines

Import PARI/GP 2.0.17 beta.

#!@perl@
#
# Output extended help corresponding to a given GP command. By default,
# extract relevant information from  from the PARI manual, run TeX, then open
# an xdvi display.
#
# The manual can be compressed.
#
# Usage: gphelp keyword
#
# Command line options:
#  -k: apropos (list of relevant GP functions)
#  -detex      (-d): don't use TeX + xdvi (implicit when DISPLAY is not set).
#  -color_help (-ch) <number>: use color "number" (same scheme as in GP)
#  -color_bold (-cb) <number>: display bold in color "number"
#  -color_underline (-cu) <number>: display underlined text in color "number"
#
#  -raw   use internal format for output with @x markers, -detex is implicit
#         (for the TeX-to-pod converter)
#
#  -to_pod file		convert file to POD (should be the only args)
#
# Granted environment variables (override):
#  GPTMPDIR: where temporary files will go (/tmp by default).
#  GPDOCDIR: where is manual (by default, where make install will put it).
#  GPXDVI: which 'xdvi' program to call (xdvi by default)
#
$version= "@version@";
$docdir = $ENV{GPDOCDIR} || $ENV{GPHELP_DOCDIR} || "@miscdir@";
# no expanded material (@key@) below

$xdvi = $ENV{GPXDVI} || "xdvi";
$gzip = "gzip";
$zcat = "$gzip -dc";

&to_pod() if @ARGV == 2 && $ARGV[0] eq '-to_pod'; 

&options(); &init();
if ($#ARGV < 0) { &treat($_); exit 0; }

&pretex() if (!$detex);
for (@ARGV) { &treat($_); }

if ($apropos) { &apropos_final_print(); exit 0; }
if (!$found) { &clean if (!$detex); exit 0; }

&posttex() if (!$detex);

print $gpmsg if (!$detex && $fromgp);
exit 0;

#
# Procedures
#
sub help
{
  print "Usage: $0 [-k] [-detex] [-ch c1] [-cb c2] [-cu c3] keyword\n";
  print "where c1,c2,c3 denote background, bold and underline color\n";
  exit(1);
}

sub options
{
  while ($_ = $ARGV[0])
  {
    last if (! /^-[a-z]/);
    shift(@ARGV);
    if ($_ eq "-fromgp")
      { $fromgp = 1; }
    elsif ($_ eq "-k")
      { $apropos = 1; }
    elsif ($_ eq "-detex" || $_ eq "-d")
      { $detex = 1; }
    elsif ($_ eq "-raw")
      { $raw = $detex = 1; }
    elsif ($_ eq "-color_help" || $_ eq "-ch")
      { $ch = &color(shift(@ARGV)); }
    elsif ($_ eq "-color_bold" || $_ eq "-cb")
      { $cb = &color(shift(@ARGV)); }
    elsif ($_ eq "-color_underline" || $_ eq "-cu")
      { $cu = &color(shift(@ARGV)); }
    else
      { &help(); }
  }
  $detex = 1 if (!$detex && !$ENV{DISPLAY});
}

sub init
{
  $gpmsg = "ugly_kludge_done\n";
  $notfound = "not found !\n";
  &inittr();

  $indent = "   ";

  chdir($docdir);
  $docfile = "usersch3.tex";
  $tmpdir = $ENV{GPTMPDIR} || $ENV{TMPDIR} || $ENV{GPHELP_TMPDIR} || "/tmp";
  $texfile = "$tmpdir/gp.help$$";

  open(IN,"translations") || die("Could not find translation file");
  while(<IN>)
  {
    chop; @_ = split(/ *\@ */);
    $key = shift(@_);
    $transl{$key} = join('@',@_);
  }
  close(IN);
}

sub choose_chap
{
  while (s/\@([0-9])$//)
    { $docfile = "usersch$1.tex"; }
  if (-r $docfile) { $pipe = ""; }
  else
  {
    die "Cannot find $docfile"
      if (! -r "$docfile.z" &&
          ! -r "$docfile.gz" &&
          ! -r "$docfile.Z");
    $pipe = $zcat;
  }
}

sub open_dvi_then_quit
{
  local($dvifile) = $_[0];
  $dvifile = "$docdir/$dvifile" if (! -f "$dvifile");
  die "could not find $dvifile" if (! -f "$dvifile");
  (!$ENV{DISPLAY} && !$ENV{GPXDVI}) && die "xdvi needs X-Windows";
  system("$xdvi $dvifile 2>/dev/null >/dev/null&");
  exit 0;
}

sub treat
{
  $_ = $_[0]; s/^ *"(.*)"([^"]*) *$/$1$2/;
  if (s/\@$//)
  {
    $found = 0;
    $searchall = 1;
    $help = $_;
    while (<usersch*.tex*>)
    {
      if (/usersch(.*)\.tex/)
      {
        &treat("$help\@$1");
        if ($apropos && $#list > 0 || $#sentence_list > 0)
        {
          print "\nChapter $1:\n";
          print "==========\n";
          &apropos_final_print();
        }
      }
    }
    if (!$found && !$apropos) { print "$help $notfound"; return }
    $searchall = 0;
    $apropos = 0; return;
  }
  &choose_chap;

  if (!$apropos)
  {
    open_dvi_then_quit("users.dvi") if (/^$/);
    open_dvi_then_quit("tutorial.dvi") if (/^tutorial$/);
    open_dvi_then_quit("refcard.dvi") if (/^refcard$/);
  }

  if (!$apropos && $transl{$_}) { $_ = $transl{$_}; &choose_chap; }
  s/(\W)/\\$1/g;
      ($pipe && open(DOC,"$pipe $docfile |"))
  || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!";
  return &apropos($_) if ($apropos);
  if (/^\\[<>=!]=?|[|&]{1,2}$/)
    { $_ = 'Comparison and boolean operators'; }
  $help = $_;
  while (<DOC>)
  {
    if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){$help}/)
      { $first = $_; last; }
  }
  if (eof(DOC) && !$searchall) { print "$help $notfound"; return }
  $found = 1;

  if (!$detex) { &tex(); return; }

  &detex(); print "\n" if (!$fromgp);
  close(DOC);
}

#
#  A propos
#

sub apropos_print_list
{
  $current = "";
  @_ = sort(@_);
  for (@_)
  { 
    next if ($_ eq $current);
    $current = $_; print "$indent$_\n";
  }
}

sub apropos_raw_print
{
  $indent = "";
  &apropos_print_list(@sentence_list);
  &apropos_print_list(@list);
}

sub apropos_final_print
{
  local($maxlen) = 0;
  local($i,$nbcol,$current);
  local($cols) = ($ENV{'COLUMNS'} || 80) - 1;

  if ($raw) { &apropos_raw_print(); return; }
  @list = sort(@list);
  for (@list)
  {
    $i= length($_);
    $maxlen = $i if ($i > $maxlen);
  }
  $maxlen++; $nbcol = $cols / $maxlen;
  $nbcol =~ s/\..*//; 
  $nbcol-- if  ($nbcol * $maxlen == $cols);
  $nbcol = 1 if (!$nbcol);

  $current = ""; $i = 0;
  for (@list)
  {
    next if ($_ eq $current);
    $current = $_; print($_); $i++;
    if ($i >= $nbcol)
    {
      $i=0; print "\n"; next;
    }
    print " " x ($maxlen - length($_));
  }
  print "\n" if ($i);
  if ($#sentence_list > 0)
  {
    print "\nSee also:\n" if ($#list > 0);
    $indent = "  ";
    apropos_print_list(@sentence_list);
  }
}

sub apropos_check
{
  local($_) = $line;
  s/\n/ /g;
  return if (! /$help/);

  $_ = $current;
  s/\{\}//g; s/\}.*//;
  s/\\pow/^/; s/\\%/%/; s/\\bs/\\/; s/\\\#/\#/g;
  s,\+\$/\$-,+/-,;
  if (/ /) { push(@sentence_list,$_); } else { push(@list,$_); }
}

sub apropos
{
  local($line,$current,$new);
  $help = $_[0];
  $help='\\\\pow' if ($help eq '\^');
  $help='\\\\til' if ($help eq '\~');
  @sentence_list = @list = "";
  while (<DOC>)
  {
    if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){(.*)}/)
    {
      $new = $2;
      &apropos_check();
      $current = $new; $line = "";
    }
    $line .= $_;
  }
  &apropos_check();
}

#
#  Tex Part
#
sub pretex
{
  open(TEX,">$texfile.tex") || die "Couldn't open $texfile.tex";
  print TEX << "EOT";
\\def\\fromgphelp\{\}
\\input $docdir/parimacro.tex
EOT
}

sub tex
{
  print TEX "$first";;
  while (<DOC>)
  {
    last if /^\\(section|sub[sub]*sec)/i;
    print TEX;
  }
  close(DOC);
}

sub posttex
{
  print TEX "\\vfill\\eject\\bye"; close(TEX);

  chdir($tmpdir);
  system("tex $texfile.tex 2>/dev/null > /dev/null < /dev/null") == 0
    || die "could not process $texfile.dvi" if (! -f "$texfile.dvi");
  system("($xdvi $texfile.dvi 2>/dev/null >/dev/null; rm -f $texfile.tex $texfile.dvi $texfile.log)&");
  &handler(1);
}

sub clean
{
  unlink("$texfile.tex","$texfile.dvi","$texfile.log");
}

sub handler
{
  &clean if (!$_[0]);
  $SIG{'INT'} = 'DEFAULT';
  $SIG{'QUIT'} = 'DEFAULT';
}

#
#  Detex Part
#
sub fit_loop
{
  return if ($miss > 9);
  while ($miss > 0)
  {
#  print "1:$miss ";print @_;print "\n";
    for (@_) { $miss-- if (s/([?!\.;])$/$1 /);
       return if ($miss == 0);
    }
#  print "2:$miss ";print @_;print "\n";
    for (@_) { $miss-- if (s/([?!\.;]) $/$1  /);
       return if ($miss == 0);
    }
#  print "3:$miss ";print @_;print "\n";
    for (@_) { $miss-- if (s/([\),])$/$1 /);
       return if ($miss == 0);
    }
#  print "4:$miss ";print @_;print "\n";
    for (@_) { $miss-- if (s/^\(/ (/);
       return if ($miss == 0);
    }
#  print "5:$miss "; print @_;print "\n";
    for (@_) { $miss--; s/$/ /;
       return if ($miss == 0);
    }
  }
}

sub fit_line
{
  local($wi, @a);
  local($l) = -1;
  local($rem) = $_[0];
  for (@l)
  {
     $l2 = $l; $l += ($_ + 1);
     last if ($l > $rem);
     $wi++;
  }
  $miss = $rem - $l2;
  splice(@l, 0, $wi);
  @a = splice(@w, 0, $wi-1); &fit_loop(@a);
  push(@a, shift(@w)); return join(' ', @a);
}

sub format_text
{
  local($last_void) = 0;
  local($cols) = ($ENV{'COLUMNS'} || 80) - 1;
  local($first) = $cols - length($indent);

  for (@text)
  {
    if (s/^\@9//)
    {
      push(@f_text, "\n$indent" . &fit_line($first)) if (!$last_void);
      push(@f_text, "") if (/^\@\[startbold\]/);
      push(@f_text, "$indent$_");
      $last_void=1;
    }
    elsif (/^[\t ]*$/ || /^[\t ]*@\[\w+\][\t ]*$/)
    {
      next if ($last_void);
      $last_void=1;
      push(@f_text, "\n\@[endbold]$indent" . &fit_line($first)) if (@w);
      while (@w) { push(@f_text, &fit_line($cols)); }
    }
    else
    {
      $last_void = 0 ;
      @_ = split(/ /, $_);
      for (@_)
      {
	s/\Q$tr{nbrk}/ /g; push(@w, $_);
	s/\@\[\w+\]//g; push(@l, length($_));
      }
    }
  }
}

sub detex
{
  s/^\\[a-z][^\{]*\{//;
  &presubst();
  if (/([^\}]*)\.*\}\.*([^:\n]*)[ :.]*/)
  {
    if ($raw)
      { print("\@[startbold]$1\@[endbold]$2: "); }
    else
      { &TeXprint("\@[startbold]$1\@[endbold]$2:"); }
    $_ = $';
  }
  push(@text, $_);
  while (<DOC>)
  {
    last if /^\\(section|sub[sub]*sec)/i;
    &presubst(); push(@text, $_);
  }
  if ($raw)
  {
    print join("\n", @text);
    return;
  }
    
  &format_text();
  for (@f_text) { &TeXprint("$_"); }
}

# We use the special char @ to transmit special sequences
sub inittr {
  @ou = qw( dollar nbrk startbold endbold startcode endcode 
	    startpodcode endpodcode
	    startbcode endbcode startbi endbi startit endit
	    startword endword startlword endlword pm empty gt lt podleader
	  );

  @tr{@ou} = map "\@[$_]", @ou;
  $tr{dollar} = '$' if $to_pod;
  
  %pr = ( dollar => '',
	  nbrk => 'S< >', 
	  startbold => 'B<',
	  endbold => '>',
	  startcode => 'C<',
	  endcode => '>',
	  startpodcode => 'C<',
	  endpodcode => '>',
	  startbcode => 'B<C<',
	  endbcode => '>>',
	  startbi => 'B<I<',
	  endbi => '>>',
	  startit => 'I<',
	  endit => '>',
	  startword => 'F<',
	  endword => '>',
	  startlword => ' F<',
	  endlword => '> ',
	  pm => 'F<+->',
	  gt => 'E<gt>',
	  lt => 'E<lt>',
	  empty => 'Z<>',
	  podleader => '=',
	);
}

sub presubst
{
  chop unless $to_pod;
  s/\\\\(?=[a-zA-Z])/\\bs /g;
  s/\\\\/\\bs/g;
  s/(\'\'|\`\`)/"/g unless $to_pod; # "
  # asymptotic or equivalent (~)
  s/(^|[^\\]) +~/$1~/;
  s/~ */~/;
  s/(^|[^\\])~/$1$tr{nbrk}/g;
  s/\\(simeq|sim|approx|equiv)(?![a-zA-Z])/ ~ /g;
  s/(^|[^\\])%.*/$1/g;		# comments
  s/\$\\bf(\b|(?=[\d_]))\s*([^\$]+)\$/\$$tr{startbcode}$1$tr{endbcode}\$/g;
  s/\$/$tr{dollar}/g;		# math mode
  s/\t/ /g; s/\\,//g; s/\\[ ;]/ /g;# various spaces
  s/\\til(?![a-zA-Z])/~/g;		# ~
  s/\\~/~/g;
  s/\\tilde/~/g;
  s/\\\///g;			# italic correction
  s/([^\\])&+/$1/g;		# tab marks
  s/\\TeX\{\}/TeX/g;
  s/\\TeX(\W)/TeX$1/g;
  s/ *\\circ\b */ o /g;

  # \def\synt#1#2{\syn{#1}{\tt #2}}
  # \def\syn#1#2{\synx{#1}{#2}{#1}}
  s/\\synt?\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\synx{$1}{$2}{$1}/g;
  # \def\synx#1#2#3{\sidx{#3}The library syntax is $\key{#1}({#2})$}
  # Often used with embedded {}.
  s/\\synx\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{((?:[^{}]|\{[^{}]*\})*)\}/\\sidx{$3}The library syntax is $tr{startbold}$1$tr{endbold}$tr{startpodcode}($2)$tr{endpodcode}/;

  # May be used with an empty arg
  s/\\typ\{([^\}]*)\}/$tr{startcode}t_$1$tr{endcode}/g;

  s/\{ *\}//g;			# empty args
  s/(\\string)?\\_/_/g;
  s/\\([#\$&%|])/$1/g;
  s/\\(hat(?![a-zA-Z])|\^)({\\?\s*})?/^/g;
  s/ *\\pow(?![a-zA-z]) */^/g;

  s/\\neq?(?![a-zA-Z])/ != /g;
  s/\\enspace(?![a-zA-Z])/ /g;
  s/\\times(?![a-zA-Z]) */ x /g;
  s/\\infty(?![a-zA-Z]) */oo /g;
  s/ *\\(bmod|mod) */ mod /g;
  s/ *\\pmod(?![a-zA-Z]) *\{\s*((?:[^{}]|\{[^{}]*\})*)\}/ (mod $1)/g;
  s/ *\\cdot(?![a-zA-Z]) */./g;		# Maybe " . "?
  s/ *\\[lc]?dots(?![a-zA-Z]) */.../g;
  s/\\(log|sin|cos|lim|tan|mod|sqrt|exp|ln|det|Re|Im|deg|wp)(?![a-zA-Z])/$tr{startlword}$1$tr{endlword}/g;
  s/\\pi(?![a-zA-Z])/$tr{startword}Pi$tr{endword}/g;
  s/\\(Alpha | Beta | Chi | Delta | Epsilon | Phi | Gamma
       | Eta | Iota | vartheta | Kappa | Lambda | Mu | Nu | Omicron
       | Pi | Theta | Rho | Sigma | Tau | Ypsilon | varsigma | Omega
       | Xi | Psi | Zeta | alpha | beta | chi | delta | varepsilon | phi | gamma
       | eta | iota | varphi | kappa | lambda | mu | nu | omicron
       | pi | theta | rho | sigma | tau | ypsilon | varpi | omega
       | xi | psi | zeta | int
       | expr | seq | args | gcd | sum | prod | Re | infty )
      (?![a-zA-Z])/$tr{startword}$1$tr{endword}/xg;
  s/ *\\in(?![a-zA-Z]) */ belongs to /g;
  s/\\pm(?![a-zA-Z])/$tr{pm}/g;
  s/ *\\mid(?![a-zA-Z]) */ | /g;

  s/^\\def\\.*\{\n.*\n\}//gm;
  s/\\def\\.*//;
  s/\\idxtyp\{[^\}]*\}//g;
  s/\\ref\{[^\}]*\}/$tr{startbold}??$tr{endbold}/g unless $to_pod;
  s/\\secref\{[^\}]*\}/Section ($tr{startbold}??$tr{endbold})/g unless $to_pod;
  s/\\label\{[^\}]*\}//g unless $to_pod;
  s/\\(text|hbox)//g;
  s/\\rightarrow(?![a-zA-Z])/C<--E<gt>>/g;
  s/\\longleftrightarrow(?![a-zA-Z])/C<E<lt>-----E<gt>>/g;

  s/\\(noindent|medskip|bigskip|smallskip|left|right)(?![a-zA-Z])[ \t]*//g;
  s/\\vfill *\\eject//g;
  s/\\(q|quad)(?![a-zA-Z])/  /g; 
  s/\\qquad(?![a-zA-Z])/    /g; 
  s/\\centerline\b/    /g;
  s/\\big\b//g;

  s/\\settabs.*//; 
  s/\\\+//g; 
  s/\\cr(?![a-zA-Z])//g;

  s/ *\\leq?(?![a-zA-Z]) *([^ ])/<=$1/g;
  s/ *\\geq?(?![a-zA-Z]) *([^ ])/>=$1/g;
  s/ *([=><]) */ $1 /g;
  s/ *<  *([=<]) */ <$1 /g;
  s/ *>  *([=>]) */ >$1 /g;
  s/ *=  *= */ == /g;

  s/\\(vers|PARIversion)(?![a-zA-Z])/$tr{startbold}$version$tr{endbold}/;
  s/\\([QRCFZNapdf])(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g;
  s/\\([QRCFZN])\1(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g;
  s/\\Bbb\b\s*(\w)/$tr{startbi}$1$tr{endbi}/g;

  s/\\obr/{/g; s/\\cbr/}/g;
  s/\\quo(?![a-zA-Z])/\"/g;
  s/(^|\s)\{(\w+)\}/$1$2/g;

  s/\\p(?![a-zA-Z])/$tr{startbold}p$tr{endbold}$1/g;
  s/\\point\{([^\}]*)\}/$tr{startbold}* $1$tr{endbold}/g;
  s/\\bullet/$tr{startbold}*$tr{endbold}/g;
  s/\\misctitle\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g;
  s/\\subsec\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g unless $to_pod;
  s/\\teb\{([^\}]*)\}/\\sidx{$1}$tr{startbold}$1$tr{endbold}/g;
  s/\\tet\{([^\}]*)\}/\\sidx{$1}$tr{startcode}$1$tr{endcode}/g;
  s/\\tec\{\s*([^{}]*)\}\{\s*([^{}]*)\}/\\sidx{$1}$1$tr{startcode}$2$tr{endcode}/g;
  s/\\kbd\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startcode}$1$tr{endcode}/g;
  s/\\key\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g;
  s/\\var\{([^\}]*)\}/$tr{startit}$1$tr{endit}/g;
  s/\\fl(?![a-zA-Z])/$tr{startit}flag$tr{endit}/g;
  s/\\b{([^}]*)}/$tr{startcode}\\$1$tr{endcode}/g;
  s/\\sidx\{[^\}]*\}//g unless $to_pod;
  s/\\[a-zA-Z]*idx\{([^\}]*)\}/$1/g unless $to_pod;
  s/\{ *\\(it|sl) *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startit}$2$tr{endit}/g;
  s/\{ *\\bf *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startbold}$1$tr{endbold}/g;
  s/\{ *\\tt *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startpodcode}$1$tr{endpodcode}/g;
  $seek=1 if (s/\{ *\\it */$tr{startit}/g);
  if ($seek) { $seek=0 if (s/\}/$tr{endit}/) }
  s/\\(backslash|bs)\{(\w)\}/\\$2/g;
  s/\\(backslash|bs)(?![a-zA-Z]) */\\/g;

  return if $to_pod;

  $in_prog = 0 if (s/\\eprog/$tr{endbold}/g);
  if ($in_prog || s/\\bprog(tabs.*)?//g)
  {
    $in_prog++;
    s/^/\@9$tr{startbold}/ if ($in_prog==2);
    s/^/\@9/ if ($in_prog>2);
  }
}

sub wrap_code {
  my $in = shift;
  $in =~ s/^[ \t]+$//mg;
#  if ($in =~ /[A-Z]</ && 0) {			# No such things so early
#    $in =~ s/^(.)/\nS<  >$1/mg;
#  } else {
    $in =~ s/^(.)/  $1/mg;
#  }
  $in
}

sub rewrap_code {	# This code got some escapes inside...
  my $in = shift;
  $in =~ s/((^|\n\n)[ \t]+(.|\n(?!\n))*[A-Z]<(.|\n(?!\n))*)/rewrap_lines($1)/e;
  $in
}

sub rewrap_lines {	# This code got some escapes inside...
  my $in = shift;
  $in =~ s/^([ \t]+)(.*)/\nS<$1>$2\n/mg;
  $in
}

sub indexify {
  my $in = shift;
  $in =~ s/(^|and\s+)(\w+)(\$?\()/$1\\idx{$2}$3/g;
  $in;
}

sub TeXprint_topod {
  s/\A\s+//;
  s/^\\def\\.*\{\n.*\n\}//gm;
  s/\\def\\.*//;		# Repeated in presubst

  # \def\sectype#1#2{\subsec{Type \typ{#1} (#2s):}\sidx{#2}}
  # \def\sectypeindex#1#2#3{\subsec{Type \typ{#1} (#2):}\sidx{#3}}
  # \def\sectypes#1#2#3{\subsec{Types \typ{#1} and \typ{#2} (#3s):}\sidx{#3}}

  #  \n is below to prevent splitting on ' '
  #  We also remove ':'
  s/\\sectype\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$2}/g;
  s/\\sectypeindex\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$3}/g;
  s/\\sectypes\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} and \\typ{$1} (${3}s)}\n\\sidx{$3}/g;

  # Try to guard \label/\sidx (removing possible '.')
  s/(\\(?:section|subsec(?:ref|idx|op)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/;

  # last if /\\subsec[\\{}ref]*[\\\${]$help[}\\\$]/o;
  s/\\chapter\s*{((?:[^{}]|\{[^{}]*\})*)}/\n\n$tr{podleader}head1 NAME\n\nlibPARI - $1\n\n$tr{podleader}head1 DESCRIPTION\n\n/;
  s/\\section\s*{((?:[^{}]|\{[^{}]*\})*)}/"\n\n$tr{podleader}head1 " . indexify($1) . "\n\n"/e;

  # Try to delimit by :
  s/\\subsec(?:ref|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^\n:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
  s/\\subsubsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}item " . indexify("$1$3") . "\n\n"/e;
  # Try to delimit by ' '
  s/\\subsec(?:ref|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e;
  s/\\subsec(?:ref|title|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]*})+)}:?\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e;

  # This is to skip preface in refcard:
  /\Q$tr{podleader}\Ehead1|\\title(?![a-zA-Z])\s*\{/ and $seen_start = 1
    or $seen_start or return;	# Skip now!

  s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?/$tr{podleader}head1 NAME\n\n$1 - $3.  $5\n\n/ and $seen_title++ 
    unless $seen_title;
  s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?/\n\n/;
  s/\\parskip.*/\n/g;		# Up to end of the line
  #s/([A-Z])\</$1 < /g;		# Disambiguate with POD...
  s/\\((small|big)skip|newcolumn|noindent|(short)?copyrightnotice|hfill|break|par|leavevmode|strut|endgroup|bye)(?![a-zA-Z])[ \t]*/\n\n/g;
  s/^[ \t]*\\hskip\s*\w+//gm;

  s/'(\W)'/{\\tt '$1'}/g;
  s/(\\\w+)(\\hbox)/$1 $2/g;
  s/\\hbox\s*\{((?:\\[\{\}]|[^{}]|\{[^{}]*\})*)\}/$1/g;
  s/\\h\b/ /g;

  # XXXX ????
  s/^{\\tt\s*\\obeylines\s*(([^{}]+(?=[{}])|{[^{}]*})+)}/\bprog $1 \eprog/g;
  s/\\bprog(?:tabs[^\n]*)?(?![a-zA-Z])\s*(.*?)\\eprog/wrap_code($1)/ges;

  presubst();

#  s/\\kbd\{/\{\\tt /g;		# startcode
#  s/\\typ\{/\{\\tt t_/g;	# startcode

  s/\$\s*(\@\[startbi\][A-Z]\@\[endbi\])\s*\$/$1/g;
#  s/\\([RQZCF])(\b|(?=[\d_]))/B<I<$1>>/g;
#  s/\\p(\b|(?=[\d_]))/B<p>/g;
  #s/\$\\bf\b\s*([^\$]+)\$/C<B<$1>>/g;

  @lines = split /^$/m, $_;
  for (@lines) {
    s/>/\@[gt]/g unless /^\s/;
    s/</\@[lt]/g unless /^\s/;
  }
  $_ = join '', @lines;

  s/\$\$(.*?)\$\$[ \t]*/\n\nS<  >C<$1>\n\n/gs;
  s/\$([^\$]+)\$/C<$1>/g;

  s/\\d?frac{\s*((?:[^{}]|\{[^{}]*\})*)}{\s*((?:[^{}]|\{[^{}]*\})*)}/($1)\/($2)/g;

  s/\\s(?:ref|idx){\s*([^{}]*)}/X<$1>/g; # 
  s/\\(?:ref|idx){\s*([^{}]*)}/X<$1>$1/g;


#  s/\\(backslash|bs)\s*(\b|(?=[\d_]|C\<))/\\Z<>/g;
#  s/\\bmod\b/ mod /g;

  #s/\\pm(\b|(?=[\d_]))/F<+->/g;
  #s/\\noindent(\b|(?=[\d_]))/  /g;

  # Conflict between different versions of PARI and refcard:
  s/\\(?:key|li)(?![a-zA-Z])\s*{(.*)}\s*{(.+)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg;
  s/\\(?:key|li)(?![a-zA-Z])\s*{(.*)}\s*{}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/mg;
  s/\\(key|var)(?![a-zA-Z])\s*{(\w+)}/C<$2>/mg;
  s/\\var(?![a-zA-Z])\s*{X<(\w+)>(\w+)}/X<$1>C<$2>/mg;
  s/\\var(?![a-zA-Z])\s*{f{}lag}/C<flag>/mg;

  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;
  s/\\metax(?![a-zA-Z])\s*{(.*)}\s*{(.*)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg;
  s/C\<\{\}=/C\<=/g;
  s/\\fl(?![a-zA-Z])/I<flag>/g;
  s/\\file(?![a-zA-Z])/F<file>/g;
  s/\\label\s*\{([\w:.-]*)\}/X<Label $1>/g;
  s/\\secref\s*\{([\w:.-]*)\}/L<Label $1>/g;
  s/\\begin(double)?indentedkeys/\n\n=over\n\n/g;
  s/\\end(double)?indentedkeys/\n\n=back\n\n/g;
  # begin/end group appear in very special context only
  s/\\begingroup\W.*//s;		# Eat to the end
  s/\n{3,}/\n\n/g;
  s/\\subsec\{((?:[^{}]|\{[^{}]*\})+)\}/\n\n=back\n\nB<$1>\n\n=over\n\n/g; # In refcard
  # for refcard:
  s/{\\rm(?![a-zA-Z])\s*([^{}]*)}/$1/g;
  s/\\Z<>/\\/g;			# Optimize for readability
  s/\@\[(\w+)\]/\@!$pr{$1}/g;
  s/(\\\w+)\@!(\w)/$1 $2/g;
  s/\@!//g;
  s/\\([\{\}])/$1/g;

  #$_ = rewrap_code($_) if /(^|\n\n)[ \t]/;	# flacky yet...

  print;
}

sub color
{
  local($a);
  $_ = $_[0];
  if (/[^0-9]/ || $_ < 0 || $_ > 17)
    { print "bad color in gphelp: $_\n"; return ""; }
  if ($_ < 8) { $a = $_ + 30; } else { $a = $_ + 82; }
  return "\e[0;${a}m";
}

sub TeXprint
{
  $_= $_[0];
  s/ *\@\[end(bold|code|bcode|bi|it)\]/\e[m$ch/g;
  s/\@\[start(bold|code|bcode|bi)\] */$cb\e[1m/g;
  s/\@\[startit\] */$cu\e[4m/g;
  s/\@\[(dollar|empty|endl?word|endpodcode|startl?word|startpodcode)\]//g;
  s/\@\[pm\]/±/g;
  s/\\([\{\}])/$1/g;
  s/\@\[nbrk\]/ /g; print "$_\n";
}


sub to_pod {
  $to_pod = $ARGV[1];
  inittr();
  $parifile = $to_pod;
  %compress = ('.gz', 'gzip -cd',
	       '.z', 'gzip -cd',
	       '.Z', 'zcat',
	      );
  foreach $suffix (keys %compress) {
    ($patt = $suffix) =~ s/(\W)/\\$1/;
    if ($to_pod =~ /$patt$/) {
      $pipe = $compress{$suffix};
      last;
    }
  }
  if ($pipe) {
    open(DOC,"$pipe $parifile |") || 
      die "Cannot open pipe $pipe from $parifile: $!, stopped";
  } else {
    open(DOC,$parifile) || die "Cannot find file $parifile: $!, stopped";
  }
  $/='';			# Paragraph mode
  while (<DOC>) {
    &TeXprint_topod();
  }
  if ($pipe) {
    close(DOC) || die "Cannot close pipe `$pipe $parifile': $!, stopped";
  } else {
    close(DOC) || die "Cannot close file $parifile: $!, stopped";
  }
  exit 0;
}