code:
# Texinfo.pm: format Pod as Texinfo.
#
# Copyright 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas <pertusus@free.fr>
# Parts from L<Pod::Simple::HTML>.

package Pod::Simple::Texinfo;

require 5;
use strict;

use Carp qw(cluck);
#use Pod::Simple::Debug (3);
use Pod::Simple::PullParser ();

use Texinfo::Convert::NodeNameNormalization qw(normalize_node);
use Texinfo::Parser qw(parse_texi_line parse_texi_text);
use Texinfo::Convert::Texinfo;
use Texinfo::Convert::TextContent;
use Texinfo::Common qw(protect_comma_in_tree protect_first_parenthesis
                       protect_hashchar_at_line_beginning);
use Texinfo::Transformations;

use vars qw(
  @ISA $VERSION
);

@ISA = ('Pod::Simple::PullParser');
$VERSION = '0.01';

#use UNIVERSAL ();

# Allows being called from the comand line as
# perl -w -MPod::Simple::Texinfo -e Pod::Simple::Texinfo::go thingy.pod
sub go { Pod::Simple::Texinfo->parse_from_file(@ARGV); exit 0 }

my %head_commands_level;
foreach my $level (1 .. 4) {
  $head_commands_level{'head'.$level} = $level;
}

my @numbered_sectioning_commands = ('part', 'chapter', 'section', 'subsection',
  'subsubsection');
my @appendix_sectioning_commands = ('part', 'appendix', 'appendixsec',
  'appendixsubsec', 'appendixsubsubsec');
my @unnumbered_sectioning_commands = ('part', 'unnumbered', 'unnumberedsec',
  'unnumberedsubsec', 'unnumberedsubsubsec');

my @raw_formats = ('html', 'HTML', 'docbook', 'DocBook', 'texinfo',
                       'Texinfo');

# from other Pod::Simple modules.  Creates accessor subroutine.
__PACKAGE__->_accessorize(
  'texinfo_sectioning_base_level',
  'texinfo_short_title',
  'texinfo_man_url_prefix',
  'texinfo_sectioning_style',
  'texinfo_add_upper_sectioning_command',
  'texinfo_section_nodes',
  'texinfo_internal_pod_manuals',
);

my $sectioning_style = 'numbered';
#my $sectioning_base_level = 2;
my $sectioning_base_level = 0;
my $man_url_prefix = 'http://man.he.net/man';

sub new
{
  my $class = shift;
  my $new = $class->SUPER::new(@_);
  $new->accept_targets(@raw_formats);
  $new->preserve_whitespace(1);
  $new->texinfo_section_nodes(0);
  $new->texinfo_sectioning_base_level ($sectioning_base_level);
  $new->texinfo_man_url_prefix ($man_url_prefix);
  $new->texinfo_sectioning_style ($sectioning_style);
  $new->texinfo_add_upper_sectioning_command(1);
  return $new;
}

sub run
{
  my $self = shift;

  # In case the caller changed the formats
  my @formats = $self->accept_targets();
  foreach my $format (@formats) {
    if (lc($format) eq 'texinfo') {
      $self->{'texinfo_raw_format_commands'}->{$format} = '';
      $self->{'texinfo_if_format_commands'}->{':'.$format} = '';
    } else {
      $self->{'texinfo_raw_format_commands'}->{$format} = lc($format);
      $self->{'texinfo_if_format_commands'}->{':'.$format} = lc($format);
    }
  }
  my $base_level = $self->texinfo_sectioning_base_level;
  $base_level = 1 if ($base_level <= 1);
  if ($self->texinfo_sectioning_style eq 'numbered') {
    $self->{'texinfo_sectioning_commands'} = \@numbered_sectioning_commands;
  } elsif ($self->texinfo_sectioning_style eq 'unnumbered') {
    $self->{'texinfo_sectioning_commands'} = \@unnumbered_sectioning_commands;
  } else {
    $self->{'texinfo_sectioning_commands'} = \@appendix_sectioning_commands;
  }
  foreach my $heading_command (keys(%head_commands_level)) {
    my $level = $head_commands_level{$heading_command} + $base_level -1;
    if (!defined($self->{'texinfo_sectioning_commands'}->[$level])) {
      $self->{'texinfo_head_commands'}->{$heading_command}
        = $self->{'texinfo_sectioning_commands'}->[-1];
    } else {
      $self->{'texinfo_head_commands'}->{$heading_command}
        = $self->{'texinfo_sectioning_commands'}->[$level];
    }
  }
  $self->{'texinfo_internal_pod_manuals_hash'} = {};
  my $manuals = $self->texinfo_internal_pod_manuals();
  if ($manuals) {
    foreach my $manual (@$manuals) {
       $self->{'texinfo_internal_pod_manuals_hash'}->{$manual} = 1;
    }
  }

  if ($self->bare_output()) {
    $self->_convert_pod();
  } else {
    $self->_preamble();
    $self->_convert_pod();
    $self->_postamble();
  }
}

my $STDIN_DOCU_NAME = 'stdin';
sub _preamble($)
{
  my $self = shift;

  my $fh = $self->{'output_fh'};

  if (!defined($self->texinfo_short_title)) {
    my $short_title = $self->get_short_title();
    if (defined($short_title) and $short_title =~ m/\S/) {
      $self->texinfo_short_title($short_title);
    }
  }

  if ($self->texinfo_sectioning_base_level == 0) {
    #print STDERR "$fh\n";
    print $fh '\input texinfo'."\n";
    my $setfilename;
    if (defined($self->texinfo_short_title)) {
      $setfilename = _pod_title_to_file_name($self->texinfo_short_title);
    } else {
      # FIXME maybe output filename would be better than source_filename?
      my $source_filename = $self->source_filename();
      if (defined($source_filename) and $source_filename ne '') {
        if ($source_filename eq '-') {
          $setfilename = $STDIN_DOCU_NAME;
        } else {
          $setfilename = $source_filename;
          $setfilename =~ s/\.(pod|pm)$//i;
        }
      }
    }
    if (defined($setfilename) and $setfilename =~ m/\S/) {
      $setfilename = _protect_text($setfilename, 1);
      $setfilename .= '.info';
      print $fh "\@setfilename $setfilename\n\n"
    }
    # FIXME depend on =encoding
    print $fh '@documentencoding utf-8'."\n\n";

    my $title = $self->get_title();
    if (defined($title) and $title =~ m/\S/) {
      print $fh "\@settitle "._protect_text($title, 1)."\n\n";
    }
    print $fh "\@node Top\n";
    if (defined($self->texinfo_short_title)) {
       print $fh "\@top "._protect_text($self->texinfo_short_title, 1)."\n\n";
    }
  } elsif (defined($self->texinfo_short_title)
           and $self->texinfo_add_upper_sectioning_command) {
      my $level = $self->texinfo_sectioning_base_level() - 1;
      my $name = _protect_text($self->texinfo_short_title, 1);
      my $node_name = _prepare_anchor($self, $name);

      my $anchor = '';
      my $node = '';
      if ($node_name =~ /\S/) {
        if (!$self->texinfo_section_nodes
            or $self->{'texinfo_sectioning_commands'}->[$level] eq 'part') {
          $anchor = "\@anchor{$node_name}\n";
        } else {
          $node = "\@node $node_name\n";
        }
      }
      print $fh "$node\@$self->{'texinfo_sectioning_commands'}->[$level] "
         ._protect_text($self->texinfo_short_title, 1)."\n$anchor\n";
  }
}

# 'out' is out of the context, for now for index entries.
sub _output($$$;$)
{
  my $fh = shift;
  my $accumulated_stack = shift;
  my $text = shift;
  my $out = shift;

  if (scalar(@$accumulated_stack)) {
    if ($out) {
      $accumulated_stack->[-1]->{'out'} .= $text;
    } else {
      $accumulated_stack->[-1]->{'text'} .= $text;
    }
  } else {
    print $fh $text;
  }
}

sub _begin_context($$)
{
  my $accumulated_stack = shift;
  my $tag = shift;
  push @$accumulated_stack, {'text' => '', 'tag' => $tag,
                             'out' => ''};
}

sub _end_context($)
{
  my $accumulated_stack = shift;
  my $previous_context = pop @$accumulated_stack;
  return ($previous_context->{'text'}, $previous_context->{'out'});
}

sub _protect_text($;$)
{
  my $text = shift;
  my $remove_new_lines = shift;
  cluck if (!defined($text));
  $text =~ s/\n/ /g if ($remove_new_lines);
  $text =~ s/([\@\{\}])/\@$1/g;
  return $text;
}

sub _pod_title_to_file_name($)
{
  my $name = shift;
  $name =~ s/\s+/_/g;
  $name =~ s/::/-/g;
  $name =~ s/[^\w\.-]//g;
  $name = '_' if ($name eq '');
  return $name;
}

sub _protect_comma($)
{
  my $texinfo = shift;
  my $tree = parse_texi_line(undef, $texinfo);
  $tree = protect_comma_in_tree($tree);
  return Texinfo::Convert::Texinfo::convert($tree);
}

sub _protect_hashchar($)
{
  my $texinfo = shift;
  # protect # first in line
  if ($texinfo =~ /#/) {
    my $tree = parse_texi_text(undef, $texinfo);
    protect_hashchar_at_line_beginning(undef, $tree);
    return Texinfo::Convert::Texinfo::convert($tree);
  } else {
    return $texinfo;
  }
}

sub _reference_to_text_in_texi($)
{
  my $texinfo = shift;
  my $tree = parse_texi_text(undef, $texinfo);
  Texinfo::Transformations::reference_to_arg_in_tree(undef, $tree);
  return Texinfo::Convert::Texinfo::convert($tree);
}

sub _section_manual_to_node_name($$$)
{
  my $self = shift;
  my $manual = shift;
  my $section = shift;
  my $base_level = shift;

  if (defined($manual) and $base_level > 0) {
    return _protect_text($manual, 1). " $section";
  } else {
    return $section;
  }
}

sub _normalize_texinfo_name($$)
{
  # Pod may be more forgiven than Texinfo, so we go through
  # a normalization, by parsing and converting back to Texinfo
  my $name = shift;
  my $command = shift;
  my $texinfo_text;
  if ($command eq 'anchor') {
    $texinfo_text = "\@anchor{$name}";
  } else {
    # item is not correct since it cannot happen outside of a table
    # context, so we use @center which accepts the same on the line
    if ($command eq 'item') {
      $command = 'center';
    }
    $texinfo_text = "\@$command $name\n";
  }
  my $tree = parse_texi_text(undef, $texinfo_text);
  if ($command eq 'anchor') {
    #print STDERR "GGG $tree->{'contents'}->[0]->{'cmdname'}\n";
    $tree->{'contents'}->[0]->{'args'}->[-0]->{'contents'}
      = protect_first_parenthesis($tree->{'contents'}->[0]->{'args'}->[-0]->{'contents'});
  }
  my $fixed_text = Texinfo::Convert::Texinfo::convert($tree, 1);
  my $result = $fixed_text;
  if ($command eq 'anchor') {
    $result =~ s/^\@anchor\{(.*)\}$/$1/s;
  } else {
    chomp($result);
    $result =~ s/^\@$command (.*)$/$1/s;
  }
  return $result;
}

sub _node_name($$)
{
  my $self = shift;
  my $texinfo_node_name = shift;

  chomp $texinfo_node_name;
  $texinfo_node_name
     = $self->_section_manual_to_node_name($self->texinfo_short_title,
                                          $texinfo_node_name,
                                          $self->texinfo_sectioning_base_level);
  # also change refs to text
  return _reference_to_text_in_texi($texinfo_node_name);
}

sub _prepare_anchor($$)
{
  my $self = shift;
  my $texinfo_node_name = shift;

  my $node = _normalize_texinfo_name($texinfo_node_name, 'anchor');

  if ($node !~ /\S/) {
    return '';
  }
  # Now we know that we have something.
  my $node_tree = parse_texi_line(undef, $node);
  my $normalized_base = normalize_node($node_tree);
  my $normalized = $normalized_base;
  my $number_appended = 0;
  while ($self->{'texinfo_nodes'}->{$normalized}) {
    $number_appended++;
    $normalized = "${normalized_base}-$number_appended";
  }
  my $node_name;
  if ($number_appended) {
    $texinfo_node_name = "$node $number_appended";
    $node_tree = parse_texi_line(undef, $texinfo_node_name);
  }
  $node_tree = protect_comma_in_tree($node_tree);
  $self->{'texinfo_nodes'}->{$normalized} = $node_tree;
  my $final_node_name = Texinfo::Convert::Texinfo::convert($node_tree, 1);
  return $final_node_name;
}

# from Pod::Simple::HTML general_url_escape
sub _url_escape($)
{
  my $string = shift;

  $string =~ s/([^\x00-\xFF])/join '', map sprintf('%%%02X',$_), unpack 'C*', $1/eg;
     # express Unicode things as urlencode(utf(orig)).

  # A pretty conservative escaping, behoovey even for query components
  #  of a URL (see RFC 2396)

  $string =~ s/([^-_\.!~*()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/sprintf('%%%02X',ord($1))/eg;
   # Yes, stipulate the list without a range, so that this can work right on
   #  all charsets that this module happens to run under.
   # Altho, hmm, what about that ord?  Presumably that won't work right
   #  under non-ASCII charsets.  Something should be done
   #  about that, I guess?

  return $string;
}

my %tag_commands = (
  'F' => 'file',
  'S' => 'w',
  'I' => 'emph',
  'B' => 'strong', # or @b?
  'C' => 'code'
);

my %environment_commands = (
  'Verbatim' => 'verbatim',
  'over-text' => 'table @asis',
  'over-bullet' => 'itemize',
  'over-number' => 'enumerate',
  'over-block' => 'quotation',
);

my %line_commands = (
  'item-bullet' => 'item',
  'item-text' => 'item',
  'item-number' => 'item',
  'encoding' => 'documentencoding'
);

foreach my $tag (keys(%head_commands_level)) {
  $line_commands{$tag} = 1;
}

my %tags_index_before;
my %context_tags;
foreach my $context_tag (keys(%line_commands), 'L', 'X', 'Para') {
  $context_tags{$context_tag} = 1;
}

# do not appear as parsed token
# E entity/character
sub _convert_pod($)
{
  my $self = shift;

  my $fh = $self->{'output_fh'};

  my ($token, $type, $tagname, $top_seen);

  my @accumulated_output;
  my @format_stack;
  while($token = $self->get_token()) {
    my $type = $token->type();
    #print STDERR "* type $type\n";
    #print STDERR $token->dump()."\n";
    if ($type eq 'start') {
      my $tagname = $token->tagname();
      if ($context_tags{$tagname}) {
        if ($tagname eq 'L') {
          my $linktype = $token->attr('type');
          my $content_implicit = $token->attr('content-implicit');
          #print STDERR " L: $linktype\n";
          #my @attrs = keys %{$token->attr_hash};
          #print STDERR "  @attrs\n";
          #my $raw_L = $token->attr('raw').'';
          #print STDERR " $token->attr('raw'): $raw_L\n";
          my ($url_arg, $texinfo_node, $texinfo_manual, $texinfo_section);
          if ($linktype eq 'man') {
            # NOTE: the .'' is here to force the $token->attr to ba a real
            # string and not an object.
            # NOTE 2: It is not clear that setting the url should be done
            # here, maybe this should be in the Texinfo HTML converter.
            # However, there is a 'man' category here and not in Texinfo,
            # so the information is more precise in pod.
            my $replacement_arg = $token->attr('to').'';
            # regexp from Pod::Simple::HTML resolve_man_page_link
            # since it is very small, it is likely that copyright cannot be
            # claimed for that part.
            $replacement_arg =~ /^([^(]+)(?:[(](\d+)[)])?$/;
            my $page = $1;
            my $section = $2;
            if (defined($page) and $page ne '') {
              $section = 1 if (!defined($section));
              # it is unlikely that there is a comma because of _url_escape
              # but to be sure there is still a call to _protect_comma.
              $url_arg
                = _protect_comma(_protect_text(
                    $self->texinfo_man_url_prefix
                    ."$section/"._url_escape($page)));
            } else {
              $url_arg = '';
            }
            $replacement_arg = _protect_text($replacement_arg);
            _output($fh, \@accumulated_output, "\@url{$url_arg,, $replacement_arg}");
          } elsif ($linktype eq 'url') {
            # NOTE: the .'' is here to force the $token->attr to be a real
            # string and not an object.
            $url_arg = _protect_comma(_protect_text($token->attr('to').''));
          } elsif ($linktype eq 'pod') {
            my $manual = $token->attr('to');
            my $section = $token->attr('section');
            $manual .= '' if (defined($manual));
            $section .= '' if (defined($section));
            if (0) {
              my $section_text = 'UNDEF';
              if (defined($section)) {
                $section_text = $section;
              }
              my $manual_text = 'UNDEF';
              if (defined($manual)) {
                $manual_text = $manual;
              }
              print STDERR "L: $linktype $manual_text/$section_text\n";
            }
            if (defined($manual)) {
              if (! defined($section) or $section !~ m/\S/) {
                if ($self->{'texinfo_internal_pod_manuals_hash'}->{$manual}) {
                  $section = 'NAME';
                }
              }
              if ($self->{'texinfo_internal_pod_manuals_hash'}->{$manual}) {
                $texinfo_node =
                 $self->_section_manual_to_node_name($manual, $section,
                                     $self->texinfo_sectioning_base_level);
              } else {
                $texinfo_manual = _protect_text(_pod_title_to_file_name($manual));
                if (defined($section)) {
                  $texinfo_node = $section;
                } else {
                  $texinfo_node = '';
                }
              }
            } elsif (defined($section) and $section =~ m/\S/) {
              $texinfo_node =
               $self->_section_manual_to_node_name(
                                     $self->texinfo_short_title, $section,
                                     $self->texinfo_sectioning_base_level);
              $texinfo_section = _normalize_texinfo_name(
                 _protect_comma(_protect_text($section)), 'section');
              #print STDERR "L: internal: $texinfo_node/$texinfo_section\n";
            }
            $texinfo_node = _normalize_texinfo_name(
                    _protect_comma(_protect_text($texinfo_node)), 'anchor');
            #print STDERR "L: normalized node: $texinfo_node\n";

            # for pod, 'to' is the pod manual name.  Then 'section' is the
            # section.
          }
          push @format_stack, [$linktype, $content_implicit, $url_arg,
                               $texinfo_manual, $texinfo_node, $texinfo_section];
          #if (defined($to)) {
          #  print STDERR " | $to\n";
          #} else {
          #  print STDERR "\n";
          #}
          #print STDERR $token->dump."\n";
        }
        _begin_context(\@accumulated_output, $tagname);
      } elsif ($tag_commands{$tagname}) {
        _output($fh, \@accumulated_output, "\@$tag_commands{$tagname}\{");
      } elsif ($environment_commands{$tagname}) {
        _output($fh, \@accumulated_output, "\@$environment_commands{$tagname}\n");
        if ($tagname eq 'Verbatim') {
          push @format_stack, 'verbatim';
        }
      } elsif ($tagname eq 'for') {
        my $target = $token->attr('target');
        push @format_stack, $target;
        if ($self->{'texinfo_raw_format_commands'}->{$target}) {
          _output($fh, \@accumulated_output,
             "\@$self->{'texinfo_raw_format_commands'}->{$target}\n");
        } elsif ($self->{'texinfo_if_format_commands'}->{$target}) {
          _output($fh, \@accumulated_output,
             "\@if$self->{'texinfo_if_format_commands'}->{$target}\n");
        }
      }
    } elsif ($type eq 'text') {
      my $text;
      if (@format_stack and !ref($format_stack[-1])
          and ((defined($self->{'texinfo_raw_format_commands'}->{$format_stack[-1]})
                and !$self->{'texinfo_raw_format_commands'}->{$format_stack[-1]})
               or ($format_stack[-1] eq 'verbatim'))) {
        $text = $token->text();
      } else {
        $text = _protect_text($token->text());
        if (@format_stack and !ref($format_stack[-1])
            and ($self->{'texinfo_raw_format_commands'}->{$format_stack[-1]})) {
          $text =~ s/^(\s*)#(\s*(line)? (\d+)(( "([^"]+)")(\s+\d+)*)?\s*)$/$1\@hashchar{}$2/mg;
        }
      }
      _output($fh, \@accumulated_output, $text);
    } elsif ($type eq 'end') {
      my $tagname = $token->tagname();
      if ($context_tags{$tagname}) {
        my ($result, $out) = _end_context(\@accumulated_output);
        #print STDERR "end: $tagname: $result, $out\n";
        my $texinfo_node = '';
        if ($line_commands{$tagname}) {

          my ($command, $command_argument);
          if ($head_commands_level{$tagname}) {
            $command = $self->{'texinfo_head_commands'}->{$tagname};
          } elsif ($line_commands{$tagname}) {
            $command = $line_commands{$tagname};
          }

          if ($head_commands_level{$tagname} or $tagname eq 'item-text') {
            chomp ($result);
            $result =~ s/\n/ /g;
            $result =~ s/^\s*//;
            $result =~ s/\s*$//;

            $command_argument = _normalize_texinfo_name($result, $command);
            if ($result =~ /\S/ and $command_argument !~ /\S/) {
              # use some raw text if the expansion lead to an empty section
              my $tree = parse_texi_line(undef, $result);
              my $converter = Texinfo::Convert::TextContent->converter();
              $command_argument = _protect_text($converter->convert_tree($tree));
            }

            my $anchor = '';
            my $node_name = _prepare_anchor($self, _node_name($self, $result));
            if ($node_name =~ /\S/) {
              if ($tagname eq 'item-text' or !$self->texinfo_section_nodes) {
                $anchor = "\n\@anchor{$node_name}";
              } else {
                $texinfo_node = "\@node $node_name\n";
              }
            }
            $command_argument .= $anchor;
          } else {
            $command_argument = $result;
          }
          _output($fh, \@accumulated_output,
                  "$texinfo_node\@$command $command_argument\n$out\n");
        } elsif ($tagname eq 'Para') {
          _output($fh, \@accumulated_output, $out.
                                   _protect_hashchar($result)."\n\n");
        } elsif ($tagname eq 'L') {
          my $format = pop @format_stack;
          my ($linktype, $content_implicit, $url_arg,
              $texinfo_manual, $texinfo_node, $texinfo_section) = @$format;
          if ($linktype ne 'man') {
            my $explanation;
            if (defined($result) and $result =~ m/\S/ and !$content_implicit) {
              $explanation = ' '. _protect_comma($result);
            }
            if ($linktype eq 'url') {
              if (defined($explanation)) {
                _output($fh, \@accumulated_output,
                         "\@url{$url_arg,$explanation}");
              } else {
                _output($fh, \@accumulated_output,
                         "\@url{$url_arg}");
              }
            } elsif ($linktype eq 'pod') {
              if (defined($texinfo_manual)) {
                $explanation = '' if (!defined($explanation));
                _output($fh, \@accumulated_output,
                         "\@ref{$texinfo_node,$explanation,, $texinfo_manual}");
              } elsif (defined($explanation)) {
                _output($fh, \@accumulated_output,
                       "\@ref{$texinfo_node,$explanation,$explanation}");
              } else {
                if (defined($texinfo_section)
                    and $texinfo_section ne $texinfo_node) {
                  _output($fh, \@accumulated_output,
                           "\@ref{$texinfo_node,, $texinfo_section}");
                } else {
                  _output($fh, \@accumulated_output,
                           "\@ref{$texinfo_node}");
                }
              }
            }
          }
        } elsif ($tagname eq 'X') {
          my $next_token = $self->get_token();
          if ($next_token) {
            if ($next_token->type() eq 'text') {
              my $next_text = $next_token->text;
              $next_text =~ s/^\s*//;
              $next_token->text($next_text);
              #_output($fh, \@accumulated_output, "\n");
            }
            $self->unget_token($next_token);
          }
          chomp ($result);
          $result =~ s/\n/ /g;
          $result .= "\n";
          _output($fh, \@accumulated_output, "\@cindex $result", 1);
        }
      } elsif ($tag_commands{$tagname}) {
        _output($fh, \@accumulated_output, "}");
      } elsif ($environment_commands{$tagname}) {
        if ($tagname eq 'Verbatim') {
          pop @format_stack;
          _output($fh, \@accumulated_output, "\n");
        }
        my $tag = $environment_commands{$tagname};
        $tag =~ s/ .*//;
        _output($fh, \@accumulated_output, "\@end $tag\n\n");
      } elsif ($tagname eq 'for') {
        my $target = pop @format_stack;
        if ($self->{'texinfo_raw_format_commands'}->{$target}) {
          _output($fh, \@accumulated_output,
                  "\n\@end $self->{'texinfo_raw_format_commands'}->{$target}\n");
        } elsif ($self->{'texinfo_if_format_commands'}->{$target}) {
          _output($fh, \@accumulated_output,
                  "\@end if$self->{'texinfo_if_format_commands'}->{$target}\n");
        }
      }
    }
  }
}

sub _postamble($)
{
  my $self = shift;

  my $fh = $self->{'output_fh'};
  if ($self->texinfo_sectioning_base_level == 0) {
    #print STDERR "$fh\n";
    print $fh "\@bye\n";
  }
}

1;

__END__

=head1 NAME

Pod::Simple::Texinfo - format Pod as Texinfo

=head1 SYNOPSIS

  # From the command like
  perl -MPod::Simple::Texinfo -e Pod::Simple::Texinfo::go thingy.pod

  # From perl
  my $new = Pod::Simple::Texinfo->new;
  $new->texinfo_sectioning_style('unnumbered');
  my $from = shift @ARGV;
  my $to = $from;
  $to =~ s/\.(pod|pm)$/.texi/i;
  $new->parse_from_file($from, $to);

=head1 DESCRIPTION

This class is for making a Texinfo rendering of a Pod document.

This is a subclass of L<Pod::Simple::PullParser> and inherits all its
methods (and options).

It supports producing a standalone manual per Pod (the default) or
render the Pod as a chapter, see L</texinfo_sectioning_base_level>.

=head1 METHODS

=over

=item texinfo_sectioning_base_level

Sets the level of the head1 commands.  1 is for the @chapter/@unnumbered
level.  If set to 0, the head1 commands level is still 1, but the output
manual is considered to be a standalone manual.  If not 0, the pod file is
rendered as a fragment of a Texinfo manual.

=item texinfo_man_url_prefix

String used as a prefix for man page urls.  Default
is C<http://man.he.net/man>.

=item texinfo_sectioning_style

Default is C<numbered>, using the numbered sectioning Texinfo @-commands
(@chapter, @section...).  Giving C<unnumbered> leads to using unnumbered
sectioning command variants (@unnumbered...), and any other value would
lead to using appendix sectioning command variants (@appendix...).

=item texinfo_add_upper_sectioning_command

If set (the default case), a sectioning command is added at the beginning
of the output for the whole document, using the module name, at the level
above the level set by L<texinfo_sectioning_base_level>.  So there will be
a C<@part> if the level is equal to 1, a C<@chapter> if the level is equal
to 2 and so on and so forth.  If the base level is 0, a C<@top> command is
output instead.

=item texinfo_section_nodes

If set, add C<@node> and not C<@anchor> for each sectioning command.

=back

=head1 SEE ALSO

L<Pod::Simple>. L<Pod::Simple::PullParser>. The Texinfo manual.

=head1 COPYRIGHT

Copyright (C) 2011, 2012 Free Software Foundation, Inc.

This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.

C<_url_escape> is C<general_url_escape> from L<Pod::Simple::HTML>.

=head1 AUTHOR

Patrice Dumas E<lt>pertusus@free.frE<gt>.  Parts from L<Pod::Simple::HTML>.

=cut


code:
#! /usr/bin/env perl
# $Id$
# pod2texi -- convert Pod to Texinfo.
# Copyright 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas <pertusus@free.fr>

use strict;
use Getopt::Long qw(GetOptions);
# for dirname.
use File::Basename;
use File::Spec;

Getopt::Long::Configure("gnu_getopt");
#use Pod::Simple::Debug (4);

BEGIN
{
  # emulate -w
  $^W = 1;
  my ($real_command_name, $command_directory, $command_suffix)
     = fileparse($0, '.pl');

  my $datadir = '@datadir@';
  my $package = '@PACKAGE@';
  my $updir = File::Spec->updir();

  my $texinfolibdir;
  my $lib_dir;

  # in-source run
  if (($command_suffix eq '.pl' and !(defined($ENV{'TEXINFO_DEV_SOURCE'})
       and $ENV{'TEXINFO_DEV_SOURCE'} eq 0)) or $ENV{'TEXINFO_DEV_SOURCE'}) {
    my $srcdir = defined $ENV{'srcdir'} ? $ENV{'srcdir'} : $command_directory;
    $texinfolibdir = File::Spec->catdir($srcdir, $updir, 'tp');
    $lib_dir = File::Spec->catdir($texinfolibdir, 'maintain');
    unshift @INC, (File::Spec->catdir($srcdir, 'lib'), $texinfolibdir);
  } elsif ($datadir ne '@' .'datadir@' and $package ne '@' . 'PACKAGE@'
           and $datadir ne '') {
    $texinfolibdir = File::Spec->catdir($datadir, $package);
    # try to make package relocatable, will only work if standard relative paths
    # are used
    if (! -f File::Spec->catfile($texinfolibdir, 'Texinfo', 'Parser.pm')
        and -f File::Spec->catfile($command_directory, $updir, 'share',
                                   'texinfo', 'Texinfo', 'Parser.pm')) {
      $texinfolibdir = File::Spec->catdir($command_directory, $updir,
                                          'share', 'texinfo');
    }
    $lib_dir = $texinfolibdir;
    unshift @INC, (File::Spec->catdir($texinfolibdir, 'Pod-Simple-Texinfo'),
                   $texinfolibdir);
  }

  # '@USE_EXTERNAL_LIBINTL @ and similar are substituted in the
  # makefile using values from configure
  if (defined($texinfolibdir)) {
    if ('@USE_EXTERNAL_LIBINTL@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'libintl-perl', 'lib'));
    }
    if ('@USE_EXTERNAL_EASTASIANWIDTH@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'Unicode-EastAsianWidth', 'lib'));
    }
    if ('@USE_EXTERNAL_UNIDECODE@' ne 'yes') {
      unshift @INC, (File::Spec->catdir($lib_dir, 'lib', 'Text-Unidecode', 'lib'));
    }
  }
}

use Pod::Simple::Texinfo;
use Texinfo::Common;
use Texinfo::Parser;
use Texinfo::Transformations;

{
# A fake package to be able to use Pod::Simple::PullParser without generating
# any output.
package Pod::Simple::PullParserRun;

use vars qw(@ISA);
@ISA = ('Pod::Simple::PullParser');
sub new
{
  return shift->SUPER::new(@_);
}
sub run(){};
}

my ($real_command_name, $directories, $suffix) = fileparse($0);

# placeholder for string translations, not used for now
sub __($)
{
  return $_[0];
}

sub pod2texi_help()
{
  return __("Usage: pod2texi [OPTION]... POD...

Translate Perl pod documentation file(s) to Texinfo.  There are two
basic modes of operation.  First, by default, each pod is translated to
a standalone Texinfo manual.

Second, if C<--base-level> is set higher than 0, each pod is translated
to a file suitable for C<\@include>, and one more file with all the
C<\@include>s is generated, intended to be C<\@include>d in turn within
a hand-written top-level file.

Options:
  --appendix-sections     use appendix-like sections.
  --base-level=NUM|NAME   level of the head1 commands; default 0.
  --debug=NUM             set debugging level.
  --help                  display this help and exit.
  --no-fill-section-gaps  do not fill sectioning gaps.
  --no-section-nodes      use anchors for sections instead of nodes.
  --output=NAME           output to NAME for the first or main manual
                          instead of standard output.
  --preamble=STR          insert STR as beginning boilerplate.
  --subdir=NAME           put files included in the main manual in NAME.
  --top                   top for the main manual.
  --unnumbered-sections   use unumbered sections.
  --version               display version information and exit.

Email bug reports to bug-texinfo\@gnu.org,
general questions and discussion to help-texinfo\@gnu.org.
Texinfo home page: http://www.gnu.org/software/texinfo/\n");
}

my $base_level = 0;
my $unnumbered_sections = 0;
my $appendix_sections = 0;
my $output = '-';
my $top = 'top';
my $preamble = undef;
my $subdir;
my $section_nodes = 1;
my $fill_sectioning_gaps = 1;
my $debug = 0;

my $result_options = Getopt::Long::GetOptions (
  'help|h' => sub { print pod2texi_help(); exit 0; },
  'version|V' => sub {print "$real_command_name $Pod::Simple::Texinfo::VERSION\n\n";
    printf __("Copyright (C) %s Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.\n"), "2016";
      exit 0;},
  'base-level=s' => sub {
     if ($_[1] =~ /^[0-4]$/) {
       $base_level = $_[1];
     } elsif (defined($Texinfo::Common::command_structuring_level{$_[1]})) {
       $base_level = $Texinfo::Common::command_structuring_level{$_[1]};
     } else {
       die sprintf(__("%s: wrong argument for --base-level\n"),
                   $real_command_name);
     }
   },
  'unnumbered-sections!' => \$unnumbered_sections,
  'appendix-sections!' => \$appendix_sections,
  'output|o=s' => \$output,
  'preamble=s' => \$preamble,
  'subdir=s' => \$subdir,
  'top=s' => \$top,
  'section-nodes!' => \$section_nodes,
  'fill-section-gaps!' => \$fill_sectioning_gaps,
  'debug=i' => \$debug,
);

exit 1 if (!$result_options);

if (defined($subdir)) {
  if (! -d $subdir) {
    if (!mkdir($subdir)) {
      die sprintf(__("%s: could not create directory %s: %s"),
                  $real_command_name, $subdir, $!);
    }
  }
}

my $STDOUT_DOCU_NAME = 'stdout';

my @manuals;
my @all_manual_names;

my @input_files = @ARGV;

# use STDIN if not a tty, like makeinfo does
@input_files = ('-') if (!scalar(@input_files) and !-t STDIN);
die sprintf(__("%s: missing file argument;\n"), $real_command_name)
   .sprintf(__("try `%s --help' for more information\n"), $real_command_name)
     unless (scalar(@input_files) >= 1);

my @processed_files;
# First gather all the manual names
if ($base_level > 0) {
  foreach my $file (@input_files) {
    # we don't want to read from STDIN, as the input read would be lost
    # same with named pipe and socket...
    # FIXME are there other file that have the same problem?
    next if ($file eq '-' or -p $file or -S $file);
    # not really used, only the manual name is used.
    my $parser = Pod::Simple::PullParserRun->new();
    $parser->parse_file($file);
    my $short_title = $parser->get_short_title();
    if (defined($short_title) and $short_title =~ m/\S/) {
      push @manuals, $short_title;
      push @all_manual_names, $short_title;
      #print STDERR "NEW MANUAL: $short_title\n";
    } else {
      if (!$parser->content_seen) {
        warn sprintf(__("%s: ignoring %s without content\n"),
                     $real_command_name, $file);
        next;
      }
      push @all_manual_names, undef;
    }
    push @processed_files, $file;
  }
} else {
  @processed_files = @input_files;
}

sub _fix_texinfo_tree($$$$;$)
{
  my $self = shift;
  my $manual_texi = shift;
  my $section_nodes = shift;
  my $fill_gaps_in_sectioning = shift;
  my $do_master_menu = shift;

  my $parser = Texinfo::Parser::parser();
  my $tree = $parser->parse_texi_text($manual_texi);

  if ($fill_gaps_in_sectioning) {
    my ($added_sections, $added_nodes);
    ($tree->{'contents'}, $added_sections)
      = Texinfo::Transformations::fill_gaps_in_sectioning($tree);
    # there should already be nodes associated with other sections.  Therefore
    # new nodes should only be created for the $added_sections.
    if ($section_nodes) {
      ($tree->{'contents'}, $added_nodes)
        = Texinfo::Transformations::insert_nodes_for_sectioning_commands($parser, $tree);
      if ($self and $self->texinfo_sectioning_base_level > 0) {
        # prepend the manual name
        foreach my $node (@$added_nodes) {
          # First remove the old normalized entry
          delete $parser->{'labels'}->{$node->{'extra'}->{'normalized'}};
          # now get the number
          my $node_texi = Texinfo::Convert::Texinfo::convert(
                {'contents' => $node->{'extra'}->{'node_content'}});
          # We could have kept the asis, too, it is kept when !section_nodes
          $node_texi =~ s/^\s*(\@asis\{\})?\s*//;
          # complete with manual name
          my $complete_node_name = $self->_node_name($node_texi);
          # now recreate node arg, similar with Texinfo::Transformations::_new_node
          my $tree = Texinfo::Parser::parse_texi_text(undef, $complete_node_name);
          my $node_arg = $node->{'args'}->[0];
          $node_arg->{'contents'} = $tree->{'contents'};
          push @{$node_arg->{'contents'}},
              {'type' => 'spaces_at_end', 'text' => "\n"};
          unshift @{$node_arg->{'contents'}},
                  {'extra' => {'command' => $node},
                   'text' => ' ',
                   'type' => 'empty_spaces_after_command'};
          foreach my $content (@{$node_arg->{'contents'}}) {
            $content->{'parent'} = $node_arg;
          }
          # Last parse and register node
          my $parsed_node = Texinfo::Parser::_parse_node_manual($node_arg);
          #push @{$node->{'extra'}->{'nodes_manuals'}}, $parsed_node;
          @{$node->{'extra'}->{'nodes_manuals'}} = ($parsed_node);
          if (!Texinfo::Parser::_register_label($parser, $node, $parsed_node, undef)) {
            print STDERR "BUG: node not unique, register failed:  $parsed_node->{'normalized'}\n";
          }
        }
      }
    }
  }
  my $structure = Texinfo::Structuring::sectioning_structure($parser, $tree);
  Texinfo::Transformations::complete_tree_nodes_menus($parser, $tree)
    if ($section_nodes);
  Texinfo::Transformations::regenerate_master_menu($parser) if ($do_master_menu);
  return ($parser, $tree);
}

sub _fix_texinfo_manual($$$$;$)
{
  my $self = shift;
  my $manual_texi = shift;
  my $section_nodes = shift;
  my $fill_gaps_in_sectioning = shift;
  my $do_master_menu = shift;
  my ($parser, $tree) = _fix_texinfo_tree($self, $manual_texi, $section_nodes,
                                    $fill_gaps_in_sectioning, $do_master_menu);
  return Texinfo::Convert::Texinfo::convert($tree);
}

sub _do_top_node_menu($)
{
  my $manual_texi = shift;
  my ($parser, $tree) = _fix_texinfo_tree(undef, $manual_texi, 1, 0, 1);
  my $labels = $parser->labels_information();
  my $top_node_menu = $labels->{'Top'}->{'menus'}->[0];
  if ($top_node_menu) {
    return Texinfo::Convert::Texinfo::convert($top_node_menu);
  } else {
    return '';
  }
}

my $file_nr = 0;
# Full manual is collected to generate the top node menu, if $section_nodes
my $full_manual = '';
my @included;
foreach my $file (@processed_files) {
  my $manual_texi = '';
  my $outfile;
  my $name = shift @all_manual_names;
  if ($base_level == 0 and !$file_nr) {
    $outfile = $output;
  } else {
    if (defined($name)) {
      $outfile = Pod::Simple::Texinfo::_pod_title_to_file_name($name);
      $outfile .= '.texi';
    } else {
      if ($file eq '-') {
        $outfile = $STDOUT_DOCU_NAME;
      } else {
        $outfile = $file;
      }
      if ($outfile =~ /\.(pm|pod)$/) {
        $outfile =~ s/\.(pm|pod)$/.texi/i;
      } else {
        $outfile .= '.texi';
      }
    }
    $outfile = File::Spec->catfile($subdir, $outfile)
      if (defined($subdir));
  }

  my $new = Pod::Simple::Texinfo->new();

  push @included, [$name, $outfile, $file] if ($base_level > 0);
  my $fh;
  if ($outfile eq '-') {
    $fh = *STDOUT;
  } else {
    open (OUT, ">$outfile") or die sprintf(__("%s: could not open %s for writing: %s\n"),
                                          $real_command_name, $outfile, $!);
    $fh = *OUT;
  }
  # FIXME should use =encoding
  binmode($fh, ':encoding(utf8)');

  $new->output_string(\$manual_texi);

  $new->texinfo_sectioning_base_level($base_level);
  if ($section_nodes) {
    $new->texinfo_section_nodes(1);
  }
  if ($unnumbered_sections) {
    $new->texinfo_sectioning_style('unnumbered');
  } elsif ($appendix_sections) {
    $new->texinfo_sectioning_style('appendix');
  }
  if ($base_level > 0 and @manuals) {
    $new->texinfo_internal_pod_manuals(\@manuals);
  }

  print STDERR "processing $file -> $outfile ($name)\n" if ($debug);
  $new->parse_file($file);

  if ($section_nodes or $fill_sectioning_gaps) {
    if ($debug > 4) {
      # print to a file
      open (DBGFILE, ">$outfile-dbg") or die sprintf(__("%s: could not open %s: %s\n"),
                                      $real_command_name, "$outfile-dbg", $!);
      binmode(DBGFILE, ':encoding(utf8)');
      print DBGFILE $manual_texi;

    }
    $manual_texi = _fix_texinfo_manual($new, $manual_texi, $section_nodes,
                                             $fill_sectioning_gaps);
    $full_manual .= $manual_texi if ($section_nodes);
  }
  print $fh $manual_texi;

  if ($outfile ne '-') {
    close($fh) or die sprintf(__("%s: error on closing %s: %s\n"),
                               $real_command_name, $outfile, $!);
  }

  if ($base_level > 0) {
    if (!$new->content_seen) {
      # this should only happen for input coming from pipe or the like
      warn sprintf(__("%s: removing %s as input file %s has no content\n"),
                   $real_command_name, $outfile, $file);
      unlink ($outfile);
      pop @included;
    # if we didn't gather the short title, try now, and rename out file if found
    } elsif (!defined($name)) {
      my $short_title = $new->texinfo_short_title;
      if (defined($short_title) and $short_title =~ /\S/) {
        push @manuals, $short_title;
        pop @included;
        my $new_outfile
         = Pod::Simple::Texinfo::_pod_title_to_file_name($short_title);
        $new_outfile .= '.texi';
        $new_outfile = File::Spec->catfile($subdir, $new_outfile)
           if (defined($subdir));
        if ($new_outfile ne $outfile) {
          unless (rename ($outfile, $new_outfile)) {
            die sprintf(__("%s: rename %s failed: %s\n"),
                        $real_command_name, $outfile, $!);
          }
        }
        push @included, [$short_title, $new_outfile, $file];
      }
    }
  }
  $file_nr++;
}

if ($base_level > 0) {
  my $fh;
  if ($output ne '-') {
    open (OUT, ">$output") or die sprintf(__("%s: could not open %s for writing: %s\n"),
                                          $real_command_name, $output, $!);
    $fh = *OUT;
  } else {
    $fh = *STDOUT;
  }

  # FIXME should use =encoding
  binmode($fh, ':encoding(utf8)');

  my $outfile_name = $output;

  $outfile_name = $STDOUT_DOCU_NAME if ($outfile_name eq '-');
  $outfile_name =~ s/\.te?x(i|info)?$//;
  $outfile_name .= '.info';

  if (! defined ($preamble)) {
    $preamble = '\input texinfo
@setfilename ' . Pod::Simple::Texinfo::_protect_text($outfile_name) . "
\@documentencoding utf-8
\@settitle $top

\@contents

\@ifnottex
\@node Top
\@top $top
\@end ifnottex\n\n";
  }

  print $fh $preamble;
  if ($section_nodes) {
    #print STDERR "\@node Top\n\@top top\n".$full_manual;
    my $menu = _do_top_node_menu("\@node Top\n\@top top\n".$full_manual);
    print $fh $menu."\n";
  }
  foreach my $include (@included) {
    my $file = $include->[1];
    print $fh "\@include ".Pod::Simple::Texinfo::_protect_text($file)."\n";
  }
  print $fh "\n\@bye\n";

  if ($output ne '-') {
    close($fh) or die sprintf(__("%s: error on closing %s: %s\n"),
                               $real_command_name, $output, $!);
  }
}

if (defined($output) and $output eq '-') {
  close(STDOUT) or die sprintf(__("%s: error on closing stdout: %s\n"),
                               $real_command_name, $!);
}

1;

__END__

=head1 NAME

pod2texi - convert Pod to Texinfo

=head1 SYNOPSIS

  pod2texi [OPTION]... POD...

=head1 DESCRIPTION

Translate Pod file(s) to Texinfo.  There are two basic modes of
operation.  First, by default, each pod is translated to a standalone
Texinfo manual.

Second, if C<--base-level> is set higher than 0, each pod is translated
to a file suitable for C<@include>, and one more file with all the
C<@include>s is generated, intended to be C<@include>d in turn within a
hand-written top-level file.

=head1 OPTIONS

=over

=item B<--appendix-sections>

Use appendix sectioning commands (C<@appendix>, ...) instead of the
default numbered sectioning Texinfo @-commands (C<@chapter>,
C<@section>, ...).

=item B<--base-level>=I<NUM|NAME>

Sets the level of the C<head1> commands.  It may be an integer or a
Texinfo sectioning command (without the C<@>): 1 corresponds to the
C<@chapter>/C<@unnumbered> level, 2 to the C<@section> level, and so on.
The default is 0, meaning that C<head1> commands are still output as
chapters, but the output is arranged as a standalone manual.

If the level is not 0, the pod file is rendered as a fragment of a
Texinfo manual suitable for C<@include>.  In this case, each pod file
has an additional sectioning command covering the entire file, one level
above the C<--base-level> value.  Therefore, to make each pod file a
chapter in a large manual, you should use C<section> as the base level.

For an example of making Texinfo out of the Perl documentation itself,
see C<contrib/perldoc-all> in the Texinfo source distribution, with
output available at L<http://www.gnu.org/software/perl/manual>.

=item B<--debug>=I<NUM>

Set debugging level to I<NUM>.

=item B<--help>

Display help and exit.

=item B<--output>=I<NAME>

Name for the first manual, or the main manual if there is a main manual.
Default is to write to standard output.

=item B<--no-section-nodes>

Use anchors for sections instead of nodes.

=item B<--no-fill-section-gaps>

Do not fill sectioning gaps with empty C<@unnumbered> files.
Ordinarily, it's good to keep the sectioning hierarchy intact.

=item B<--preamble>=I<STR>

Insert I<STR> as top boilerplate before includes.  The default is a
minimal beginning for a Texinfo document, and sets C<@documentencoding>
to C<utf-8> (because the output is written that way).

=item B<--subdir>=I<NAME>

If there is a main manual with include files (each corresponding to
an input pod file), then those include files are put in directory I<NAME>.

=item B<--unnumbered-sections>

Use unnumbered sectioning commands (C<@unnumbered>, ...) instead of the
default numbered sectioning Texinfo @-commands (C<@chapter>,
C<@section>, ...).

=item B<--top>=I<TOP>

Name of the C<@top> element for the main manual.  May contain Texinfo code.

=item B<--version>

Display version information and exit.

=back

=head1 SEE ALSO

L<Pod::Simple::Texinfo>.  L<perlpod>.  The Texinfo manual.
Texinfo home page: L<http://www.gnu.org/software/texinfo/>

=head1 COPYRIGHT

Copyright 2016 Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.

There is NO WARRANTY, to the extent permitted by law.

=head1 AUTHOR

Patrice Dumas E<lt>bug-texinfo@gnu.orgE<gt>.

=cut

repo_name: mthl/texinfo

license: mit


code:
#! /bin/sh -x
# $Id$
# Copyright 2010, 2012 Free Software Foundation, Inc.
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.

if test z"$srcdir" = 'z'; then
  srcdir='.'
fi

#prove -I "$tpdir" -I "$srcdir"/lib "$srcdir"/t/*.t

tpdir=$srcdir/../tp
prove -I "$tpdir" -I "$tpdir"/maintain/lib/Unicode-EastAsianWidth/lib/ \
      -I "$tpdir"/maintain/lib/libintl-perl/lib \
      -I "$tpdir"/maintain/lib/Text-Unidecode/lib/ \
      -I "$srcdir"/lib \
      "$srcdir"/t/*.t


code:
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl Pod-Simple-Texinfo.t'

#########################

# change 'tests => 1' to 'tests => last_test_to_print';

use Test::More;
BEGIN { plan tests => 17 };
use Pod::Simple::Texinfo;
ok(1); # If we made it this far, we're ok.

#########################

sub run_test($$$;$$)
{
  my $in = shift;
  my $out = shift;
  my $name = shift;
  my $test_nodes = shift;
  my $sectioning_base_level = shift;

  my $parser = Pod::Simple::Texinfo->new();
  $parser->set_source(\$in);
  $parser->texinfo_section_nodes(1)
    if ($test_nodes);
  if (defined($sectioning_base_level)) {
    $parser->texinfo_sectioning_base_level($sectioning_base_level);
    my $short_title = $parser->get_short_title();
    $parser->texinfo_short_title($short_title);
  }
  my $result;
  $parser->output_string(\$result);
  $parser->bare_output(1);
  $parser->run();
  if (defined($out)) {
    is ($result, $out, $name);
  } else {
    print "$name:\n";
    print STDERR $result;
  }
}

run_test ('=head1 T
X<aaa>
',
'@chapter T
@anchor{T}
@cindex aaa

', 'index in head');

TODO: {

local $TODO = 'Pod::Simple not ignoring correctly X<>';

run_test ('=head1 NAME
X<aaa>
',
'@node NAME aaa NAME
@section NAME
@cindex aaa

', 'index in head node', 1, 2);

}

run_test ('=head1 NAME

T@c

=head1 @{}
',
'@node T@@c NAME
@section NAME

T@@c

@node T@@c @@@{@}
@section @@@{@}

', 'protected characters', 1, 2);

run_test ('=head1 T

Para X<bb>
in para X<cc>
qtil X<ff> ggg
n X<ww> X<ff> C<aa>.
C<JJ> X<tt>.
X<-r>X<+p>
X<fff>
X<WWW>
I<GG>X<DD>C<MM>.
',
'@chapter T
@anchor{T}

@cindex bb
@cindex cc
@cindex ff
@cindex ww
@cindex ff
@cindex tt
@cindex -r
@cindex +p
@cindex fff
@cindex WWW
@cindex DD
Para in para qtil ggg
n @code{aa}.
@code{JJ} .
@emph{GG}@code{MM}.

', 'index in paragaph');

run_test('=over

=item a
X<it> b

=item c
X<C<code>>

Para

=back
',
'@table @asis
@item a b
@anchor{a b}
@cindex it

@item c
@anchor{c}
@cindex @code{code}

Para

@end table

', 'index in item-text');

run_test('=over

=item L</somewhere>

=back
', '@table @asis
@item @ref{somewhere}
@anchor{somewhere}

@end table

', 'ref in item');

run_test('=head1 NAME

=head1 NAME
', '@chapter NAME
@anchor{NAME}

@chapter NAME
@anchor{NAME 1}

', 'double ref');

run_test('=head1 head with
new line
', '@chapter head with new line
@anchor{head with new line}

', 'head with new line');

run_test('=head1 L</somewhere>
', '@chapter @ref{somewhere}
@anchor{somewhere}

', 'ref in section');

run_test('=over

=item a L<pod2text|pod2text>

=item a L<pod2latex|pod2latex>

=back
', '@table @asis
@item a @ref{, pod2text,, pod2text}
@anchor{a pod2text}

@item a @ref{, pod2latex,, pod2latex}
@anchor{a pod2latex}

@end table

', 'duplicate anchors ref');

run_test('=head1 a, b', '@chapter a, b
@anchor{a@comma{} b}

', 'comma in head1');

run_test('=head1 a, b

=over

=item c, d

=back

L</a, b>. L</c, d>.
', '@chapter a, b
@anchor{a@comma{} b}

@table @asis
@item c, d
@anchor{c@comma{} d}

@end table

@ref{a@comma{} b}. @ref{c@comma{} d}.

', 'comma in refs');

run_test('=head1 (man) t

L</(man) t>', '@chapter (man) t
@anchor{@asis{(}man) t}

@ref{@asis{(}man) t,, (man) t}

', 'node beginning with a parenthesis');

run_test('=head1 head

# line 4 "ggggg"
and
 # line 5 "fff"

# line 4 "bbb"
# 7 "aaaa"
', '@chapter head
@anchor{head}

@hashchar{} line 4 "ggggg"
and
 @hashchar{} line 5 "fff"

@hashchar{} line 4 "bbb"
@hashchar{} 7 "aaaa"

', 'cpp lines');

run_test('=head1 head

 # line 4 "ggggg"
 and @
 # line 5 "fff"

Text

  # line 4 "bbb"
  # 7 "aaaa"
','@chapter head
@anchor{head}

@verbatim
 # line 4 "ggggg"
 and @
 # line 5 "fff"
@end verbatim

Text

@verbatim
  # line 4 "bbb"
  # 7 "aaaa"
@end verbatim

', 'cpp lines in verbatim');

run_test('=head1 head

=for html
 # line 4 "ggggg"
  <html> @

=begin html

 # line 8 "kkk"
 and @
 # line 5 "fff"

=end html
', '@chapter head
@anchor{head}

@html

 @hashchar{} line 4 "ggggg"
  <html> @@
@end html
@html
 @hashchar{} line 8 "kkk"
 and @@
 @hashchar{} line 5 "fff"

@end html
','cpp lines in formats');

1;


code:
$Id$
This is the README file for the GNU Texinfo distribution.  Texinfo is
the preferred documentation format for GNU software.

  Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
  2002, 2003, 2004, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016
  Free Software Foundation, Inc.

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

Home page: http://www.gnu.org/software/texinfo/
  Including links to Texinfo-related programs not part of this package.

Primary distribution point: http://ftp.gnu.org/gnu/texinfo/
  automatic mirror redirection: http://ftpmirror.gnu.org/texinfo/
                   mirror list: http://www.gnu.org/prep/ftp.html

Texinfo is a documentation system that uses a single source to produce
many forms of output:
- a PDF or DVI document (via the TeX typesetting system) with the normal
  features of a book, including sectioning, cross references, indices, etc.
- an Info file with analogous features to make documentation browsing easy.
- a plain text (ASCII) file.
- an HTML output file suitable for use with a web browser.
- a Docbook file.
- a XML file transliterating the source with a Texinfo DTD.

See ./INSTALL* for installation instructions.

To get started with Texinfo, best is to read the Texinfo manual;
it is online at http://www.gnu.org/software/texinfo/manual/texinfo.
If you don't have Internet access, you can read the manual locally:
- first, build the distribution.
- then, for HTML, run: make -C doc html
  and you can start reading at doc/texinfo.html/index.html.
- for PDF, if you have a working TeX, run: make -C doc pdf
- for Info, you can read a tutorial on reading Info files:
 ./info/ginfo doc/info
  and/or read the Texinfo manual:
 ./info/ginfo doc/texinfo

Texinfo mailing lists and archives:
- http://lists.gnu.org/mailman/listinfo/bug-texinfo
  for bug reports, enhancement suggestions, technical discussion.
- http://lists.gnu.org/mailman/listinfo/help-texinfo
  for authoring questions and general discussion.
There are no corresponding newsgroups.

Bug reports:
Please include enough information for the maintainers to reproduce the
problem.  Generally speaking, that means:
- the contents of all input files needed to reproduce the bug (crucial!).
- a statement of the problem and any samples of the erroneous output.
- the version number of Texinfo and the program(s) involved (use --version).
- hardware and operating system information (uname -a).
- unusual options you gave to configure, if any (try ./config.status --help).
- anything else that you think could be helpful.

Patches are most welcome; if possible, please make them with diff -c and
include ChangeLog entries.

See README-hacking for information on the Texinfo development
environment -- any interested parties are welcome.  If you're a
programmer and wish to contribute, this should get you started.  If
you're not a programmer, you can still make significant contributions by
writing test cases, checking the documentation against the
implementation, etc.

This distribution includes the following files, among others:
    README                 This file.
    README-hacking         Texinfo developer information.

    INSTALL                Texinfo-specific installation notes.
    NEWS                   Summary of new features by release.

Texinfo documentation files (in ./doc):
    texinfo.texi           Describes the Texinfo language and many
                           of the associated tools.  It tells how to use
                           Texinfo to write documentation, how to use
                           Texinfo mode in GNU Emacs, TeX,
                           texi2any/makeinfo, and much else.

    info.texi              Describes how to read manuals in Info.
                           This document also comes as part of GNU Emacs.

    info-stnd.texi         How to use the standalone GNU Info reader that is
                           included in this distribution (./info).

Printing-related files:
    doc/texinfo.tex        This implements Texinfo in TeX, to typeset a
                           Texinfo file into a DVI or PDF file.

    util/texi2dvi          This is a shell script for producing an
                           indexed DVI file using TeX and texindex.

    util/texi2pdf          Generate PDF (wrapper for texi2dvi).

Source directories:
  djgpp/                   Support for compiling under DJGPP.
  gnulib/                  Support files from Gnulib.
  info/                    Standalone Info reader.
  install-info/            Maintain the Info dir file.
  tp/                      Texinfo Parser in Perl, includes texi2any/makeinfo.
  texindex/                The `texindex' program that generates
                           sorted indices used by TeX when
                           typesetting a file for printing.

Translation support:
  po/                      Strings of the programs.
  po_document/             Strings in generated Texinfo documents.

Installation support:
  Makefile.am              Read by Automake to create a Makefile.in.
  Makefile.in              Read by configure to make a Makefile,
                             created by Automake.
  configure.ac             Read by Autoconf to create `configure'.
  configure                Configuration script for local conditions,
                             created by Autoconf.
  build-aux/               Common files.

The util/ directory contains a few other scripts, e.g., examples of
using makeinfo in various ways.  See util/README.

Finally, the contrib/ directory contains additional files from users
provided for your reading and/or hacking pleasure.  They aren't part of
Texinfo proper or maintained by the Texinfo developers.

path: README


code:
$Id$
This is the README-alpha file for GNU Texinfo.

  Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
  2001, 2002, 2003, 2004, 2005, 2011, 2012, 2014, 2015
  Free Software Foundation, Inc.

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

This is a test release!

The latest test release (if any) is available at
ftp://alpha.gnu.org/gnu/texinfo/

Please email comments and problem reports to bug-texinfo@gnu.org. You
are welcome to join that mailing list; to do so, please visit
http://lists.gnu.org/mailman/listinfo/bug-texinfo.  (There is no
dedicated mailing list for pretests any more.)

If you see a problem in this release that you've already reported, feel
free to re-report it -- it's good to get a reminder.  If you sent a
patch for a previous release, and you haven't received any feedback
about it, please do re-send it, it likely got lost.

For development environment information, see README-hacking.

path: README-alpha


code:
$Id$
This file describes the development environment for Texinfo.

  Copyright 2002, 2003, 2005, 2006, 2007, 2008, 2010, 2011, 2012, 2013,
  2014, 2015, 2016 Free Software Foundation, Inc.

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

The development sources for GNU Texinfo are available through anonymous
Subversion at Savannah:
  http://savannah.gnu.org/svn/?group=texinfo

This distribution uses whatever versions of Automake, Autoconf, and
Gettext are listed in NEWS; usually the latest official releases.  If
you are getting the sources from the development repository (or change
configure.ac), you'll need to have these tools installed to (re)build.
You'll also need help2man.  If you modify texindex/ti.twjr, you'll need
gawk >= 4.0.  All of these programs are available from
http://ftp.gnu.org/gnu.

After getting the development sources, and installing the tools above,
you can run
 ./autogen.sh
and then, for example,
 ./configure -C CFLAGS='-g -Wdeclaration-after-statement'
and then
 make

After the initial autogen && configure, simply running make should suffice.

The -C tells configure to cache test results, which usually speeds
things up a bit.

That particular -W is useful because a) intermixing declarations with
statements is an easy thing to do accidentally, b) gcc doesn't warn
about it by default, and c) other compilers that don't support it are
still widespread.  If you're not using gcc, of course you shouldn't
specify that option.

Other -W options can be useful too, and patches are welcome to resolve
diagnostics; however, removing all possible warning messages, or
warnings with nonfree compilers, is explicitly not a goal.

Running make in one particular subdirectory is possible, for example
make -C info.  However there are interdependencies between the
subdirectories, notably on gnulib, so if you don't want to run "make",
you may have to run "make -C gnulib/lib" first.

Additionally, make dist may not work until make has been run at least
once, because of rules to create man pages under the man/ directory.

"make dist" will fail if the use of Perl XS extension modules is
disabled and there is no Makefile in the XSParagraph subdirectory.

Gnulib
------

This distribution also uses Gnulib (http://www.gnu.org/software/gnulib)
to share common files.  Gnulib files used in Texinfo are checked in to
the repository.  If you get automake/conf/etc. errors from ./autogen.sh,
please try getting a checkout of gnulib (in a separate directory from
the texinfo checkout), and then run, say,
  ../gnulib/gnulib-tool --add-import
in your top-level Texinfo directory.
(gnulib-tool is in the gnulib source tree.)

The currently-used gnulib modules and other gnulib information are
recorded in gnulib/m4/gnulib-cache.m4.  Given a source checkout of
gnulib, you can update the files with gnulib-tool --add-import.

When running gnulib-tool --add-import or otherwise adding modules, it is
necessary to check what files were added (e.g., run "svn status
build-aux gnulib") and add them to the repository with "svn add";
likewise for removals, likewise for adding new generated files
(typically gnulib/lib/foo.h from foo.h.in) to the ignore list (e.g.,
  svn propedit svn:ignore gnulib/lib).

Subdirectories in repository
----------------------------

In addition to the subdirectories listed in README, there are these
directories in the source control repository:

makeinfo/  - Implementation of makeinfo in C, distributed before version 5.0
texi2html/ - Perl program to generate HTML from Texinfo, superseded by texi2any

About running the Texinfo programs from a development source tree:

- Once the distribution is built, you can run the compiled programs
(info, install-info) out of the build tree without special settings;
they don't try to read any installed data files.

- The texi2dvi script and texinfo.tex can be run as-is, since they
are standalone and don't require compilation.  For the same reasons,
they are officially updated between full Texinfo releases, at
http://ftpmirror.gnu.org/texinfo.

- Regarding texi2any (aka makeinfo), you can run tp/texi2any.pl
directly.  This is the original source file for the program, so it's
convenient to be able to make changes and then run it.

To run the output "tp/texi2any" instead, you can set the environment
variable TEXINFO_DEV_SOURCE to 1.  Otherwise, it will try to use
Texinfo's Perl modules in the installed locations.  "tp/texi2any" uses
the Perl interpreter found by configure, so you might want to run that
instead of texi2any.pl if it's different to the default interpreter in
your environment.

References for working on various parts of the system:

If you want to delve into making a new backend for the Perl makeinfo,
the documentation in tp/Texinfo/Convert/Converter.pm is a good starting
point, as it describes the existing backends and other places to look.

If you want to delve into texinfo.tex, a thorough plain TeX reference
is available under the GFDL:
  TeX by Topic - http://www.eijkhout.net/texbytopic/texbytopic.html
Another book on plain TeX, also available under the GFDL, is a GNU package:
  TeX for the Impatient - http://www.gnu.org/software/teximpatient/
Occasionally you may need to know about the details of the PDF format.
A reference for this is the PDF reference, Sixth Edition, version 1.7,
downloadable at http://www.adobe.com/devnet/pdf/pdf_reference_archive.html

The texindex program is implemented using the TexiWebJR literate
programming system, combining Texinfo and Awk
(https://github.com/arnoldrobbins/texiwebjr).  Running "make ti.pdf"
in the texindex/ subdirectory creates the printable form of the
program.  All the usual Texinfo output formats are possible.

Steps for making a release (pretest or official):

- When close to official release:
check at latest automake/autoconf/gettext version, and mention in NEWS
(to upgrade gettext, run
  gettextize -f --po-dir=po --po-dir=po_document
after installing new version of gettext)

special pleading with bug-texinfo / beebe / platform-testers to try.
check OpenCSW build reports at
  https://buildfarm.opencsw.org/buildbot/waterfall?category=texinfo
try groff.texinfo from groff source repo.
process doc/texinfo-tex-test.texi with TeX and check that output is good.

- First checks:
Ensure texinfo.tex, texi2dvi, and htmlxref.cnf are updated on ftp.gnu.org.
Ensure TXI_XLATE in doc/Makefile.am matches actual file list.
Check that LINGUAS under po and po_document match actual file list.
Have a look at the output of "svn status ." to check for files that
  should be tracked in SVN or ignored.
Check that TEXINFO_DTD_VERSION has been updated to the next version in
  configure.ac if the DTD has been modified since the last release.
  See comments in configure.ac, and run (at the top level) make dtd-check.
Check "make ccheck" and "make vcheck" work in "doc/refcard".
Check "dist-xz" is in the option list in configure.ac (often removed
for speed when testing).
Update copyright years in many files for release; best to grep -r for
  the previous year.  See also ChangeLog entries for "copyright years".
  No need (though it's ok) to change every source file at once, just the
  ones relevant to --version calls, etc., such as texindex.awk and info.c.
make po-check             # update po/POTFILES.in as needed

# Under the top level, and also under tp/Texinfo/Convert/XSParagraph, which
# uses a separate gnulib import.
gnulib-tool --add-import

util/srclist-txi          # for pretest, to sync files with other sources

- Official releases only:
version and date in NEWS.
version number in texi2dvi, texi2pdf, txirefcard.tex.
(cd tp && ./maintain/change_perl_modules_version.sh auto)
  -- this updates all the version numbers in the Perl modules
(cd tp && maintain/regenerate_documentlanguages.pl)
  -- regenerates tp/Texinfo/Documentlanguages.pm

make V=1 pdf and fix underfull/overfull boxes.

- Changes to sources:
update version in configure.ac, notice in ChangeLog.
check that texindex version is updated properly
  (rm texindex.awk ; make)
Check that translations have been updated, e.g.:
  rsync  -Lrtzv  translationproject.org::tp/latest/texinfo/ po
  rsync  -Lrtzv  translationproject.org::tp/latest/texinfo_document/ \
                 po_document # note the trailing slashes in these commands
pod2man Pod-Simple-Texinfo/pod2texi.pl >man/pod2texi.1 # until we fix deps

check that the svn checkout is up-to-date (run "svnversion" and "svn update")
make
make update-po            # both po and po_document needed, build a dist first
(export MALLOC_CHECK_=2; make distcheck)  # repeat until clean
svn commit                # when clean, then distcheck to be sure

- To do the actual upload:
pkg=texinfo
ver=6.0

then do one of:
gnupload --to alpha.gnu.org:$pkg $pkg-$ver.tar.xz                #pretest
gnupload --to ftp.gnu.org:$pkg   $pkg-$ver.tar.{gz,xz} *.diff.xz #official
   Use --user option if not using default key
   texinfo.tex and texi2dvi should already be up to date, but check.  Use
gnupload --replace --to ftp.gnu.org:texinfo texi2dvi

#  Official releases only: tag source tree (use your own username before @):
svn copy -r 6363 -m'texinfo_6_0 tag based on r6363' \
  svn+ssh://gavin@svn.savannah.gnu.org/texinfo/trunk \
  svn+ssh://gavin@svn.savannah.gnu.org/texinfo/tags/texinfo_6_0
[for karl: /srv/svn/texinfo]

#  ... set up dtd directory on web pages:
cd $HOME/gnu/www/texinfo/dtd # or wherever webpages checkout is
mkdir $ver && cvs add $ver
cp $tutil/texinfo.dtd $ver
cvs add -kb $ver $ver/texinfo.dtd
cvs commit -m$ver $ver

# If -kb is forgotten, CVS will do its own $Id expansion.
# Recover by editing and committing a new version of texinfo.dtd in svn,
# copying it again to the cvs dir, then:
#   cvs admin -kb texinfo.dtd; cvs update -A
# (See the "How to store binary files" node in the CVS manual.)

#  ... make diffs at official release:
prev=5.2
ver=6.0
cd $misc/archive/$pkg/prod
tar xf $txi/texinfo-$ver.tar.gz
tar xf texinfo-$prev.tar.gz
diff -Nrc2 texinfo-$prev texinfo-$ver | xz >texinfo-$prev-$ver.diff.xz
ls -l !$
gnupload --to ftp.gnu.org:texinfo !$
rm -rf texinfo-$ver texinfo-$prev
ro texinfo-*$ver*

- To save in local archives:
pkg=texinfo
ver=6.0

mv -v $pkg-$ver.tar.xz* $misc/archive/$pkg/alpha/                #pretest
mv -v $pkg-$ver.tar.{gz,xz}* *.diff.xz $misc/archive/$pkg/prod/  #official

- When official release is out there ...
update home page (texinfo.html) and commit as needed.
including:
  pod2html $txi/Pod-Simple-Texinfo/pod2texi.pl \
  | fgrep -v 'rev="made"' >manual/pod2texi.html

Build web documentation with
  make -C doc wwwdoc-build
Copy documentation files to web checkout with, e.g.
  make -C doc \
  wwwdoc-install www_target=../../TEXINFO_WEB_PAGES/texinfo/manual/
Check for removed files with, e.g. ls -ltu $(www_target)/*/html_node,
followed by cvs rm -f.  Likewise, check for added files with
cvs -qn update, followed by cvs add.  When done, run cvs commit.

#  Official releases only: ... update texinfo at tug.org
#  (contact root@tug.org):
prev=6.0
ver=6.1
cd ~ftp/tex
rm -rf texinfo-$prev*
cp ~/texinfo-$ver.tar.{gz,xz} .
tar xzf texinfo-$ver.tar.gz
ln -s texinfo-$ver.tar.gz texinfo.tar.gz
!!:gs/gz/xz
relink texinfo $ver

#  For pretest release, send announcement to bug-texinfo and
bcc coordinator@translationproject.org.

#  For official releases:
send announcement to info-gnu,
  cc bug-texinfo and bcc coordinator@translationproject.org.
news item at savannah.

#  ... post-release, or when development resumes:
configure.ac, util/texi2dvi: add "dev" to versions for clarity,
until it's time to do pretests again.

#  ... [personal for karl] move mail:
mv ~/mail/txi.done $ver.mail
bzip2 $ver.mail

path: README-hacking


code:
$Id$
This is the todo list for GNU Texinfo.
If you are interested in working on any of these, email bug-texinfo@gnu.org.

  Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003,
  2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012,
  2013, 2014, 2015
  Free Software Foundation.

  Copying and distribution of this file, with or without modification,
  are permitted in any medium without royalty provided the copyright
  notice and this notice are preserved.

* Language:
  - Remove the need for @if[not]tex at the beginning of the document.
  - Allow : in node names for info files, for names such as
    `class::method'.  Likewise index entries.  A quoting mechanism such
    as surrounding node names with SPACE BACKSPACE is probably the best
    solution, although this is an incompatible change to Info format.
    This would also allow references without any *note and :: in text,
    (pace goptical, Alexandre Becoulet, 18 Jan 2011 00:31:42).
  - consider doing some @inline version of @set, @ifset, like
    @inlineset{flag, ...}, @inlineifset{flag, if set} or @inlineifset{flag,
    if set, if not set} in analogy with @inlinefmt.
  - @xindexterm [def] primary [,secondary [,tertiary]]  or some such?
  - Allow subitems and `see' and `see also' in indices.
  - generalize @vtable/@htable to any defined index.
  - generalize @deffn/etc. with variants that don't make index entries.
  - @mergeindex to do @syn*index without changing fonts.
  - multicolumn * width to take up `the rest'.
  - Allow @hsep/@vsep at @item, instead of just in template.
  - another table command to take N succeeding items and split them
    into M columns (see eplain).
  - support bibliographies with BibTeX (see web2c/doc for kludge prototype).
  - @flushboth to combine @flushleft and @flushright, for RFC's.
  - @exercise/@answer command for, e.g., gawk.
  - Support automatic line numbering of examples.
  - Better def... command syntax, explicitly marking variables, etc.
  - Glossary/general definition support (dumas msg 28 Nov 2003 17:09:57 +0100).
  - Add support for other Latin 9 (and Latin 2 and Latin 1) characters.

* Makeinfo:
  - Improve the HTML customization API.
  - HTML: support thumbnails.
  - HTML: have a library of different CSS styles.
    http://mail.gnu.org/archive/html/bug-texinfo/2004-01/msg00025.html
  - XML: cannot be loaded directly in a browser; browsers are supposed to
    be able to look up the DTD and do something.
  - add --output-encoding, to set OUTPUT_ENCODING_NAME.
  - Support output formats retaining the tree structure of Texinfo documents
    as parsed by the Parser.  A lisp-like format for GUILE? Maybe JSON?
  - Support LaTeX as a backend.
  - Support the epub output format, http://en.wikipedia.org/wiki/OEBPS.
    Suggested by Sean Young, 30 Nov 2008 20:13:11.
  - Support the MediaWiki output format.

* TeX:
  - Index above @item allows page break.
  - Table of contents is misaligned if there are 10 or more [sub]sections.
  - @float captions should be typeset in a smaller font?
  - Reset the scriptfonts and scriptscriptfonts when font size changes.
  - Reasonable way to change fonts from the default (some work has been
    done), to allow for PostScript fonts, for example.
  - @multitable: handle @hsep and @vsep.
  - @multitable: repeat table headings if multiple pages long.
  - @multitable: support a heading line concept (<thead> in HTML).
  - Introduce new command to change \bindingoffset.
  - Use marks to define a real @thissection.
  - Include synctex support.
  - Include hyperlink \special's in the DVI output for xdvi, etc.
  - PDF: make each letter of the index (A, B, ...) a section in the TOC.
    From Carsten Dominik.
  - PDF: use the PageLabels dictionary to allow jumping to logical
    pages, presumably after xpdf/gv support it.  Section 8.3.1 of the
    PDF reference.  From Werner Lemberg, texinfo-pretest mail of
    27 Feb 2006 22:55:13 +0100.
  - Use @ as the escape character in index files by default,
    after new texindex is deployed (2020?).

* Doc:
  - New section on doing dedication pages. See gawk.texi
    for an example of doing it in both the tex and info versions.
  - Use/distribute pod2texi generated documentation of the perl modules in
    tp generated in doc/tp_api -- when api is stable.
  - Documentation of the HTML customization is missing.

* Info:
  - Perhaps comply with LANGUAGE setting on a per-node basis, to allow
    incremental translation of Texinfo files.
  - Display images when running under X, as Emacs 22+ can.
  - Search all nodes of dir file at startup, then can have
    INFO-DIR-SEPARATE-GROUPS and other such.  I.e., we could have
    programs (what is now "Individual utilities") in one node, library
    functions, in another, etc.  And how about supporting other languages?
  - Better dir file merging.
  - Global dir file (as in /etc/conf/dir) and texinfo config file
    specifying which info directories to search.  From Dale Mellor.
    http://mail.gnu.org/mailman/private/gnu-prog-discuss/2003q4/000439.html
  - More sample .infokey files, so people can choose without writing their own.
  - Incorporate an X-based viewer, perhaps the old GNU xinfo widget
     (http://www.gnu.org/software/xinfo) or saxinfo
     or tkinfo (http://www.math.ucsb.edu/~boldt/tkinfo/).
  - Handle M-n, C-u m, and C-u g like Emacs Info (opening new windows).
  - A running view mode, to display the next node after the end of the
    last one, and be able to toggle display of a node's subnodes.
    (Could be hard to implement though, because of how much code assumes
    that only one node is in a window at once.)

* install-info:
  - install-info --dir-file=dir2 --entry=info foo.info installs garbage
    from the misformatted --entry (and no entries from foo.info).
  - be able to copy the info file to compile-time $infodir, to
    simplify by-hand installation.
  - also support installing HTML files, etc., along with subsidiary
    @image (or other) files.  In subdirs.  Or something.
  - support info dir entries for other than the current info file name;
    see comments in menu_item_equal.
  - Monitor and improve the dir categories in existing manuals,
    following the Free Software Directory categories.  Much mail to
    developers has already been sent, what's needed now is to check new
    releases and make sure they are using the right categories.
    See the util/dir-example in the Texinfo distribution for our current
    recommended categories.
    For background, see the thread (which discusses a lot of other
    issues too) at
    http://lists.gnu.org/archive/html/emacs-devel/2002-10/msg00011.html
    especially
      http://lists.gnu.org/archive/html/emacs-devel/2002-10/msg00090.html
      http://lists.gnu.org/archive/html/emacs-devel/2002-10/msg00137.html

* texindex:
  - read source file (specified by new option) for @documentlanguage
    and/or @documentencoding, and change the sorting appropriately.
  From: Wojciech Polak, 26 Apr 2003 11:30:59 +0200.

* Distribution:
  - generate txi-??.tex from .po's to make translators' jobs easier.
    From Akim and Karl E.

***********************************************************************

* Ideas that will not be implemented:

- Support general reference card creation.
  [Reference cards are too different from normal Texinfo.]

- Support installation of manuals in different languages, along these lines:
  . support a LINGUAS file or variable saying which subdirs LL in the
    source to descend into (under doc/).
  . within each subdir LL, install the info files into $infodir/LL,
    and run install-info on $infodir/LL/dir.
  . info (both emacs and standalone) should read $infodir/$LANG/dir
    as the first dir file, and likewise read info files first from
    $infodir/$LANG, before falling back to $infodir.
  . consider ways to avoid installing images in both places.
    In fact, images probably need to be installed in a subdir
    $infodir/MANUAL/ in the first place, to avoid conflicts of having
    the same image name in different manuals.
  For a test case, see texinfo cvs, with its one translated manual
  (info-fr.texi).
  From Wojciech Polak.
  ... Except, in practice, people just name their manuals with a
  suffix for the language, and that seems to work well enough.  There
  aren't that many manuals even in English, let alone other languages,
  and there are almost no manuals in multiple languages.

- Process Texinfo files directly instead of converting to Info:
  ftp://ftp.cs.berkeley.edu/ucb/people/phelps/tcltk/tkman.tar.Z, which
  uses Tcl/Tk 8.0 from ftp.smli.com in the /pub/tcl directory.
  From: Tom Phelps @ berkeley
  [This has the disadvantage of needing to be updated when the
  Texinfo language changes, so don't.]

- Call Ghostscript to get ASCII/jpg output for the @image command.
  [makeinfo should not try to be make, or assume it knows how the user
   wants to generate images.  Too many different methods are possible.]

- Get Info declared as a MIME Content-Type, and
  an `info:' URI scheme; a library consortium has proposed a
  completely different purpose for the URI scheme, but I don't know
  how to send comments, despite it being a "request for comments".  Sigh.
  There is mail about this in the bug-texinfo archives:
    http://mail.gnu.org/archive/html/bug-texinfo/2003-09/msg00086.html
  [I suppose it is too late, and it doesn't seem to matter in practice.]

- Change bars.  This is difficult or impossible in TeX,
  unfortunately.  To do it right requires device driver support.
  wdiff or ediff may be all we can do.  Merely specifying what should be
  changed is not obvious.  texdiff (http://www.robmar.net/TexDiff) does
  something reasonable for LaTeX, maybe it can be adapted.

- @else for the @if... conditionals.  Using (for example) an @iftex block
  followed by an @ifnottex block is good enough.

path: TODO


code:
#!/bin/sh
# $Id$
# Created 2003-08-29, Karl Berry.  Public domain.

if test "x$1" = x-n; then
  chicken=true
  echo "Ok, playing chicken; not actually running any commands."
else
  chicken=
fi

echo "Preparing Texinfo development infrastructure:"

# Generates an include file for tp/Makefile.am.
cmd="./tp/maintain/regenerate_file_lists.pl"
echo "  $cmd"
$chicken eval $cmd || exit 1

# Generates another include file for tp/Makefile.am.
cmd="(cd tp && ./maintain/regenerate_docstr.sh Makefile.docstr)"
echo "  $cmd"
$chicken eval $cmd || exit 1

# Generates an include file for tp/tests/Makefile.am.
cmd="(cd tp/tests && ../maintain/regenerate_cmd_tests.sh Makefile.onetst . -base 'formatting' -long 'sectioning coverage indices nested_formats contents layout' -tex_html 'tex_html')"
echo "  $cmd"
$chicken eval $cmd || exit 1

# Generates an include file for each of tp/tests/htmlxref*/Makefile.am.
for dir in htmlxref htmlxref-only_mono htmlxref-only_split; do
  cmd="(cd tp/tests/$dir && ../../maintain/regenerate_cmd_tests.sh Makefile.onetst $dir -base .)"
  echo "  $cmd"
  $chicken eval $cmd || exit 1
done

# This overwrites lots of files with older versions.
# I keep the newest versions of files common between distributions up to
# date in CVS (see util/srclist.txt), because it's not trivial for every
# developer to do this.
#cmd="autoreconf --verbose --force --install --include=m4"

# So instead:
: ${ACLOCAL=aclocal}
: ${AUTOHEADER=autoheader}
: ${AUTOMAKE=automake}
: ${AUTOCONF=autoconf}
cmd="$ACLOCAL -I gnulib/m4 && $AUTOCONF && $AUTOHEADER && $AUTOMAKE"
echo "  $cmd $*"
$chicken eval $cmd "$@" || exit 1

: ${LIBTOOLIZE=libtoolize}
cmd="(cd tp/Texinfo/Convert/XSParagraph && ${LIBTOOLIZE} \
 && autoreconf --force --verbose --install)"
echo "  $cmd"
$chicken eval $cmd || exit 1

: ${LIBTOOLIZE=libtoolize}
cmd="(cd tp/Texinfo/MiscXS && ${LIBTOOLIZE} \
 && autoreconf --force --verbose --install)"
echo "  $cmd"
$chicken eval $cmd || exit 1

echo
echo "Now run configure with your desired options, for instance:"
echo "  ./configure CFLAGS='-g'"


code:
#! /bin/sh
# Wrapper for Microsoft lib.exe

me=ar-lib
scriptversion=2012-03-01.08; # UTC

# Copyright (C) 2010-2014 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.

# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.

# func_error message
func_error ()
{
  echo "$me: $1" 1>&2
  exit 1
}

file_conv=

# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
  file=$1
  case $file in
    / | /[!/]*) # absolute file, and not a UNC file
      if test -z "$file_conv"; then
	# lazily determine how to convert abs files
	case `uname -s` in
	  MINGW*)
	    file_conv=mingw
	    ;;
	  CYGWIN*)
	    file_conv=cygwin
	    ;;
	  *)
	    file_conv=wine
	    ;;
	esac
      fi
      case $file_conv in
	mingw)
	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
	  ;;
	cygwin)
	  file=`cygpath -m "$file" || echo "$file"`
	  ;;
	wine)
	  file=`winepath -w "$file" || echo "$file"`
	  ;;
      esac
      ;;
  esac
}

# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
  operation=$2
  archive=$3
  at_file_contents=`cat "$1"`
  eval set x "$at_file_contents"
  shift

  for member
  do
    $AR -NOLOGO $operation:"$member" "$archive" || exit $?
  done
}

case $1 in
  '')
     func_error "no command.  Try '$0 --help' for more information."
     ;;
  -h | --h*)
    cat <<EOF
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]

Members may be specified in a file named with @FILE.
EOF
    exit $?
    ;;
  -v | --v*)
    echo "$me, version $scriptversion"
    exit $?
    ;;
esac

if test $# -lt 3; then
  func_error "you must specify a program, an action and an archive"
fi

AR=$1
shift
while :
do
  if test $# -lt 2; then
    func_error "you must specify a program, an action and an archive"
  fi
  case $1 in
    -lib | -LIB \
    | -ltcg | -LTCG \
    | -machine* | -MACHINE* \
    | -subsystem* | -SUBSYSTEM* \
    | -verbose | -VERBOSE \
    | -wx* | -WX* )
      AR="$AR $1"
      shift
      ;;
    *)
      action=$1
      shift
      break
      ;;
  esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file

# strip leading dash in $action
action=${action#-}

delete=
extract=
list=
quick=
replace=
index=
create=

while test -n "$action"
do
  case $action in
    d*) delete=yes  ;;
    x*) extract=yes ;;
    t*) list=yes    ;;
    q*) quick=yes   ;;
    r*) replace=yes ;;
    s*) index=yes   ;;
    S*)             ;; # the index is always updated implicitly
    c*) create=yes  ;;
    u*)             ;; # TODO: don't ignore the update modifier
    v*)             ;; # TODO: don't ignore the verbose modifier
    *)
      func_error "unknown action specified"
      ;;
  esac
  action=${action#?}
done

case $delete$extract$list$quick$replace,$index in
  yes,* | ,yes)
    ;;
  yesyes*)
    func_error "more than one action specified"
    ;;
  *)
    func_error "no action specified"
    ;;
esac

if test -n "$delete"; then
  if test ! -f "$orig_archive"; then
    func_error "archive not found"
  fi
  for member
  do
    case $1 in
      @*)
        func_at_file "${1#@}" -REMOVE "$archive"
        ;;
      *)
        func_file_conv "$1"
        $AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
        ;;
    esac
  done

elif test -n "$extract"; then
  if test ! -f "$orig_archive"; then
    func_error "archive not found"
  fi
  if test $# -gt 0; then
    for member
    do
      case $1 in
        @*)
          func_at_file "${1#@}" -EXTRACT "$archive"
          ;;
        *)
          func_file_conv "$1"
          $AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
          ;;
      esac
    done
  else
    $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
    do
      $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
    done
  fi

elif test -n "$quick$replace"; then
  if test ! -f "$orig_archive"; then
    if test -z "$create"; then
      echo "$me: creating $orig_archive"
    fi
    orig_archive=
  else
    orig_archive=$archive
  fi

  for member
  do
    case $1 in
    @*)
      func_file_conv "${1#@}"
      set x "$@" "@$file"
      ;;
    *)
      func_file_conv "$1"
      set x "$@" "$file"
      ;;
    esac
    shift
    shift
  done

  if test -n "$orig_archive"; then
    $AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
  else
    $AR -NOLOGO -OUT:"$archive" "$@" || exit $?
  fi

elif test -n "$list"; then
  if test ! -f "$orig_archive"; then
    func_error "archive not found"
  fi
  $AR -NOLOGO -LIST "$archive" || exit $?
fi

path: build-aux/ar-lib


code:
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.

scriptversion=2012-10-14.11; # UTC

# Copyright (C) 1999-2015 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.

# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.

nl='
'

# We need space, tab and new line, in precisely that order.  Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" ""	$nl"

file_conv=

# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
  file=$1
  case $file in
    / | /[!/]*) # absolute file, and not a UNC file
      if test -z "$file_conv"; then
	# lazily determine how to convert abs files
	case `uname -s` in
	  MINGW*)
	    file_conv=mingw
	    ;;
	  CYGWIN*)
	    file_conv=cygwin
	    ;;
	  *)
	    file_conv=wine
	    ;;
	esac
      fi
      case $file_conv/,$2, in
	*,$file_conv,*)
	  ;;
	mingw/*)
	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
	  ;;
	cygwin/*)
	  file=`cygpath -m "$file" || echo "$file"`
	  ;;
	wine/*)
	  file=`winepath -w "$file" || echo "$file"`
	  ;;
      esac
      ;;
  esac
}

# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
  func_file_conv "$1"
  if test -z "$lib_path"; then
    lib_path=$file
  else
    lib_path="$lib_path;$file"
  fi
  linker_opts="$linker_opts -LIBPATH:$file"
}

# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
  lib=$1
  found=no
  save_IFS=$IFS
  IFS=';'
  for dir in $lib_path $LIB
  do
    IFS=$save_IFS
    if $shared && test -f "$dir/$lib.dll.lib"; then
      found=yes
      lib=$dir/$lib.dll.lib
      break
    fi
    if test -f "$dir/$lib.lib"; then
      found=yes
      lib=$dir/$lib.lib
      break
    fi
    if test -f "$dir/lib$lib.a"; then
      found=yes
      lib=$dir/lib$lib.a
      break
    fi
  done
  IFS=$save_IFS

  if test "$found" != yes; then
    lib=$lib.lib
  fi
}

# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
  # Assume a capable shell
  lib_path=
  shared=:
  linker_opts=
  for arg
  do
    if test -n "$eat"; then
      eat=
    else
      case $1 in
	-o)
	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
	  eat=1
	  case $2 in
	    *.o | *.[oO][bB][jJ])
	      func_file_conv "$2"
	      set x "$@" -Fo"$file"
	      shift
	      ;;
	    *)
	      func_file_conv "$2"
	      set x "$@" -Fe"$file"
	      shift
	      ;;
	  esac
	  ;;
	-I)
	  eat=1
	  func_file_conv "$2" mingw
	  set x "$@" -I"$file"
	  shift
	  ;;
	-I*)
	  func_file_conv "${1#-I}" mingw
	  set x "$@" -I"$file"
	  shift
	  ;;
	-l)
	  eat=1
	  func_cl_dashl "$2"
	  set x "$@" "$lib"
	  shift
	  ;;
	-l*)
	  func_cl_dashl "${1#-l}"
	  set x "$@" "$lib"
	  shift
	  ;;
	-L)
	  eat=1
	  func_cl_dashL "$2"
	  ;;
	-L*)
	  func_cl_dashL "${1#-L}"
	  ;;
	-static)
	  shared=false
	  ;;
	-Wl,*)
	  arg=${1#-Wl,}
	  save_ifs="$IFS"; IFS=','
	  for flag in $arg; do
	    IFS="$save_ifs"
	    linker_opts="$linker_opts $flag"
	  done
	  IFS="$save_ifs"
	  ;;
	-Xlinker)
	  eat=1
	  linker_opts="$linker_opts $2"
	  ;;
	-*)
	  set x "$@" "$1"
	  shift
	  ;;
	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
	  func_file_conv "$1"
	  set x "$@" -Tp"$file"
	  shift
	  ;;
	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
	  func_file_conv "$1" mingw
	  set x "$@" "$file"
	  shift
	  ;;
	*)
	  set x "$@" "$1"
	  shift
	  ;;
      esac
    fi
    shift
  done
  if test -n "$linker_opts"; then
    linker_opts="-link$linker_opts"
  fi
  exec "$@" $linker_opts
  exit 1
}

eat=

case $1 in
  '')
     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
     exit 1;
     ;;
  -h | --h*)
    cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]

Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.

If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.

Report bugs to <bug-automake@gnu.org>.
EOF
    exit $?
    ;;
  -v | --v*)
    echo "compile $scriptversion"
    exit $?
    ;;
  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
    func_cl_wrapper "$@"      # Doesn't return...
    ;;
esac

ofile=
cfile=

for arg
do
  if test -n "$eat"; then
    eat=
  else
    case $1 in
      -o)
	# configure might choose to run compile as 'compile cc -o foo foo.c'.
	# So we strip '-o arg' only if arg is an object.
	eat=1
	case $2 in
	  *.o | *.obj)
	    ofile=$2
	    ;;
	  *)
	    set x "$@" -o "$2"
	    shift
	    ;;
	esac
	;;
      *.c)
	cfile=$1
	set x "$@" "$1"
	shift
	;;
      *)
	set x "$@" "$1"
	shift
	;;
    esac
  fi
  shift
done

if test -z "$ofile" || test -z "$cfile"; then
  # If no '-o' option was seen then we might have been invoked from a
  # pattern rule where we don't need one.  That is ok -- this is a
  # normal compilation that the losing compiler can handle.  If no
  # '.c' file was seen then we are probably linking.  That is also
  # ok.
  exec "$@"
fi

# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`

# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file.  Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
  if mkdir "$lockdir" >/dev/null 2>&1; then
    break
  fi
  sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15

# Run the compile.
"$@"
ret=$?

if test -f "$cofile"; then
  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi

rmdir "$lockdir"
exit $ret

# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

path: build-aux/compile