groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[groff] 01/01: grog: rewrite program with many new sub functions, which


From: Bernd Warken
Subject: [groff] 01/01: grog: rewrite program with many new sub functions, which are moved into the new file subs.pl
Date: Tue, 10 Jun 2014 22:07:54 +0000

bwarken pushed a commit to branch master
in repository groff.

commit 04547372acb53ff5778c172a399fd0d1a1d4124d
Author: Bernd Warken <address@hidden>
Date:   Wed Jun 11 00:07:38 2014 +0200

    grog: rewrite program with many new sub functions, which are moved into the 
new file subs.pl
---
 ChangeLog                  |   13 +
 src/roff/grog/Makefile.sub |    8 +-
 src/roff/grog/grog.man     |   77 ++++--
 src/roff/grog/grog.pl      |  401 +++++-----------------------
 src/roff/grog/perl_test.pl |    6 +-
 src/roff/grog/subs.pl      |  626 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 775 insertions(+), 356 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index eb2eb9f..9f6a57c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2014-06-02  Bernd Warken  <address@hidden>
 
+       * src/roff/grog/grog.pl: Totally rewrite the `grog' version,
+       starting at the last stable version.  Write many parts as `sub'
+       functions.
+
+       * src/roff/grog/subs.pl: New file by splitting the src file
+       `grog.pl', such that all functions get into the new file
+       `subs.pl'.
+
+       * src/roff/grog/Makefile.sub: Add file `subs.pl', which goes into
+       the `grog' libdir.
+
+2014-06-02  Bernd Warken  <address@hidden>
+
        * src/roff/grog/grog.pl: The `grog' version of yesterday has many
        bugs.  So reinstall an old version of `grog'.
 
diff --git a/src/roff/grog/Makefile.sub b/src/roff/grog/Makefile.sub
index fcc0020..d5957bd 100644
--- a/src/roff/grog/Makefile.sub
+++ b/src/roff/grog/Makefile.sub
@@ -5,7 +5,7 @@
 # Copyright (C) 1993, 2006, 2009, 2013-2014
 #   Free Software Foundation, Inc.
 
-# Last update: 30 Mar 2014
+# Last update: 04 Jun 2014
 
 # This file is part of `grog' which is part of `groff'.
 
@@ -30,8 +30,7 @@ MOSTLYCLEANADD=grog $(MAN1)
 all: grog $(MAN1)
 
 # lib .pl-files
-#GROG=$(srcdir)/subs.pl
-GROG=
+GROG=$(srcdir)/subs.pl
 GROG_=`echo $(GROG) | sed 's|$(srcdir)/||g'`
 
 
@@ -40,9 +39,10 @@ GROG_=`echo $(GROG) | sed 's|$(srcdir)/||g'`
 grog: grog.pl $(GROG) $(SH_DEPS_SED_SCRIPT)
        rm -f $@
        sed -f "$(SH_DEPS_SED_SCRIPT)" \
+           -e "1s|^\(#! \).*perl|\\1$(PERL)|" \
            -e "s|@g@|$(g)|g" \
            -e "s|@BINDIR@|$(DESTDIR)$(bindir)|g" \
-           -e "s|@libdir@|$(DESTDIR)$(libdir)|g" \
+           -e "s|@grog_dir@|$(DESTDIR)$(grog_dir)|g" \
            -e "s|@EGREP@|$(EGREP)|g" \
            -e "s|@VERSION@|$(version)$(revision)|" \
            -e "$(SH_SCRIPT_SED_CMD)" \
diff --git a/src/roff/grog/grog.man b/src/roff/grog/grog.man
index 539ad69..234bbe2 100644
--- a/src/roff/grog/grog.man
+++ b/src/roff/grog/grog.man
@@ -76,7 +76,7 @@ GPL2
 .\" --------------------------------------------------------------------
 .SH NAME
 .
-grog \- guess options for groff command
+grog \- guess options for a groff command
 .
 .
 .\" --------------------------------------------------------------------
@@ -84,6 +84,8 @@ grog \- guess options for groff command
 .
 .SY grog
 .OP \-C
+.OP \-\-run
+.OP \-\-with_ligatures
 .RI [ \%groff\-option\~ .\|.\|.\&]
 .OP \-\-
 .RI [ \%filespec\~ .\|.\|.]
@@ -106,41 +108,75 @@ grog \- guess options for groff command
 .B grog
 reads the input (file names or standard input) and guesses which of
 the
-.BR groff  (@MAN1EXT@)
+.BR groff (@MAN1EXT@)
 options are needed to perform the input with the
 .B groff
 program.
 .
+.
+.RS
+.P
 The corresponding
 .B groff
-command is output.
+command is usually displayed in standard output.
+.
+With the option
+.BR \-\-run ,
+the generated line is output into standard error and the generated
+.B groff
+command is run on the
+.IR "standard output" .
+.RE
 .
 .
 .\" --------------------------------------------------------------------
 .SH OPTIONS
 .
-The only
-.B grog
-options recognized are
-.B \-C
-(which is also passed on) to enable compatibility mode;
+The option
 .B \-v
-and
+or
 .B \-\-version
-print information on the version number; and
+prints information on the version number.
+.
+Also
 .B \-h
-and
+or
 .B \-\-help
-print usage information.
+prints usage information.
 .
-.BR \-v ,
-.BR \-\-version ,
-.BR \-h ,
-and
-.B \-\-help
-stop the program directly without printing a
+Both of these options automatically end the
+.B grog
+program.
+.
+Other options are thenignored, and no
 .B groff
-command to standard output.
+command line is generated.
+.
+.
+The following 3 options are the only
+.B grog
+options,
+.
+.TP
+.B \-C
+this option means enabling the
+.I groff
+compatibility mode, which is also transfered to the generated
+.B groff
+command line.
+.
+.TP
+.B \-\-run
+with this option, the command line is output at standard error and
+then run on the computer.
+.
+.TP
+.B \-\-with_ligatures
+this option forces to include the arguments
+.B -P-y -PU
+within the generated
+.B groff
+command line.
 .
 .
 .P
@@ -318,8 +354,9 @@ grog.sh
 is used instead.
 .
 .
-.\" --------------------------------------------------------------------
+.\" ####################################################################
 .SH EXAMPLES
+.\" ####################################################################
 .
 .IP \(bu
 Calling
diff --git a/src/roff/grog/grog.pl b/src/roff/grog/grog.pl
index 1aca1f2..514f39d 100644
--- a/src/roff/grog/grog.pl
+++ b/src/roff/grog/grog.pl
@@ -6,15 +6,16 @@
 # Source file position: <groff-source>/src/roff/grog/grog.pl
 # Installed position: <prefix>/bin/grog
 
-# Copyright (C) 1993, 2006, 2009, 2011-2012 Free Software Foundation, Inc.
+# Copyright (C) 1993, 2006, 2009, 2011-2012, 2014
+#               Free Software Foundation, Inc.
 # Written by James Clark, maintained by Werner Lemberg.
 # Rewritten and put under GPL by Bernd Warken <address@hidden>.
 
 # This file is part of `grog', which is part of `groff'.
 
 # `groff' is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License (GPL) as published
-# by the Free Software Foundation, either version 3 of the License, or
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
 # (at your option) any later version.
 
 # `groff' is distributed in the hope that it will be useful, but
@@ -23,366 +24,108 @@
 # 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/>.
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/gpl-2.0.html>.
 
 ########################################################################
-my $Last_Update = '24 May 2012';
+our $Last_Update = '10 Jun 2014';
 ########################################################################
 
 require v5.6;
 
 use warnings;
 use strict;
-use File::Spec;
 
-my $Prog = $0;
-{
-  my ($v, $d, $f) = File::Spec->splitpath($Prog);
-  $Prog = $f;
-}
-
-#my $Sp = "[\\s\\n]";
-my $Sp = qr([\s\n]);
-
-my @Command;                   # stores the final output
-my @Mparams;                   # stores the options -m*
-my %Groff;
+# $Bin is the directory where this script is located
+use FindBin;
 
+my $before_make;       # script before run of `make'
 {
-  my @filespec = ();
-  my $double_minus = 0;
-  my $was_minus = 0;
-  my $had_filespec = 0;
-
-  foreach my $arg (@ARGV) {
-    next unless $arg;
-    if ($double_minus) {
-      $had_filespec = 1;
-      if (-f $arg && -r $arg) {
-       push @filespec, $arg;
-      } else {
-       print STDERR "grog: $arg is not a readable file.\n";
-      }
-      next;
-    }
-
-    if ($arg eq '--') {
-      $double_minus = 1;
-      push(@Command, $arg);
-      next;
-    }
-    if ($arg eq '-') {
-      unless ($was_minus) {
-       push @filespec, $arg;
-       $was_minus = 1;
-      }
-      next;
-    }
-
-    &version(0) if $arg eq '-v' || '--version' =~ /^$arg/;
-    &help() if $arg eq '-h' || '--help' =~ /^$arg/;
-    print STDERR "grog: wrong option $arg.\n" if $arg =~ /^--/;
-
-    if ($arg =~ /^-m/) {
-      push @Mparams, $arg;
-      next;
-    }
-    $Sp = '' if $arg eq '-C';
-
-    if ($arg =~ /^-/) {
-      push(@Command, $arg);
-      next;
-    } else {
-      $had_filespec = 1;
-      if (-f $arg && -r $arg) {
-       push @filespec, $arg;
-      } else {
-       print STDERR "grog: $arg is not a readable file.\n";
-      }
-      next;
-    }
-  }
-  @filespec = ('-') if ! @filespec && ! $had_filespec;
-  exit 1 unless @filespec;
-  @ARGV = @filespec;
+  my $at = '@';
+  $before_make = 1 if '@VERSION@' eq "${at}VERSION${at}";
 }
 
-foreach my $arg (@ARGV) {
-  &process($arg, 0);
-}
-
-sub process {
-  my ($filename, $level) = @_;
-  local(*FILE);
-
-  if (!open(FILE, $filename eq "-" ? $filename : "< $filename")) {
-    print STDERR "$Prog: can't open \`$filename': $!\n";
-    exit 1 unless $level;
-    return;
-  }
-  while (<FILE>) {
-    chomp;
-    s/^[.']\s*/./;
-    s/^\s+|\s+$//g;
-    s/$/\n/;
 
-    if (/^(.cstart)|(begin\s+chem)$/) {
-      $Groff{'chem'}++;
-      $Groff{'soelim'}++ if $level;
-    } elsif (/^\.TS$Sp/) {
-      $_ = <FILE>;
-      if (!/^\./ || /^\.so/) {
-       $Groff{'tbl'}++;
-       $Groff{'soelim'}++ if $level;
-      }
-    } elsif (/^\.EQ$Sp/) {
-      $_ = <FILE>;
-      if (!/^\./ || /^\.[0-9]/ || /^\.so/) {
-       $Groff{'eqn'}++;
-       $Groff{'soelim'}++ if $level;
-      }
-    } elsif (/^\.GS$Sp/) {
-      $_ = <FILE>;
-      if (!/^\./ || /^\.so/) {
-       $Groff{'grn'}++;
-       $Groff{'soelim'}++ if $level;
-      }
-    } elsif (/^\.G1$Sp/) {
-      $_ = <FILE>;
-      if (!/^\./ || /^\.so/) {
-       $Groff{'grap'}++;
-       $Groff{'soelim'}++ if $level;
-      }
-#    } elsif (/^\.PS\Sp([ 0-9.<].*)?$/) {
-#      if (/^\.PS\s*<\s*(\S+)/) {
-#      $Groff{'pic'}++;
-#      $Groff{'soelim'}++ if $level;
-#      &process($1, $level);
-#      } else {
-#      $_ = <FILE>;
-#      if (!/^\./ || /^\.ps/ || /^\.so/) {
-#        $Groff{'pic'}++;
-#        $Groff{'soelim'}++ if $level;
-#      }
-#      }
-    } elsif (/^\.PS[\s\n<]/) {
-      $Groff{'pic'}++;
-      $Groff{'soelim'}++ if $level;
-      if (/^\.PS\s*<\s*(\S+)/) {
-       &process($1, $level);
-      }
-    } elsif (/^\.R1$Sp/) {
-      $Groff{'refer'}++;
-      $Groff{'soelim'}++ if $level;
-    } elsif (/^\.\[/) {
-      $Groff{'refer_open'}++;
-      $Groff{'soelim'}++ if $level;
-    } elsif (/^\.\]/) {
-      $Groff{'refer_close'}++;
-      $Groff{'soelim'}++ if $level;
-    } elsif (/^\.NH$Sp/) {
-      $Groff{'NH'}++;          # for ms
-    } elsif (/^\.TL$Sp/) {
-      $Groff{'TL'}++;          # for mm and ms
-    } elsif (/^\.PP$Sp/) {
-      $Groff{'PP'}++;          # for mom and ms
-    } elsif (/^\.[IL]P$Sp/) {
-      $Groff{'ILP'}++;         # for man and ms
-    } elsif (/^\.P$/) {
-      $Groff{'P'}++;
-    } elsif (/^\.(PH|SA)$Sp/) {
-      $Groff{'mm'}++;
-    } elsif (/^\.TH$Sp/) {
-      $Groff{'TH'}++;
-    } elsif (/^\.SH$Sp/) {
-      $Groff{'SH'}++;
-    } elsif (/^\.([pnil]p|sh)$Sp/) {
-      $Groff{'me'}++;
-    } elsif (/^\.Dd$Sp/) {
-      $Groff{'mdoc'}++;
-    } elsif (/^\.(Tp|Dp|De|Cx|Cl)$Sp/) {
-      $Groff{'mdoc_old'} = 1;
-    }
-    # In the old version of -mdoc `Oo' is a toggle, in the new it's
-    # closed by `Oc'.
-    elsif (/^\.Oo$Sp/) {
-      $Groff{'Oo'}++;
-      s/^\.Oo/\. /;
-      redo;
-    }
-    # The test for `Oo' and `Oc' not starting a line (as allowed by the
-    # new implementation of -mdoc) is not complete; it assumes that
-    # macro arguments are well behaved, i.e., "" is used within "..." to
-    # indicate a doublequote as a string element, and weird features
-    # like `.foo a"b' are not used.
-    elsif (/^\..* Oo( |$)/) {
-      s/\\\".*//;
-      s/\"[^\"]*\"//g;
-      s/\".*//;
-      if (s/ Oo( |$)/ /) {
-       $Groff{'Oo'}++;
-      }
-      redo;
-    } elsif (/^\.Oc$Sp/) {
-      $Groff{'Oo'}--;
-      s/^\.Oc/\. /;
-      redo;
-    } elsif (/^\..* Oc( |$)/) {
-      s/\\\".*//;
-      s/\"[^\"]*\"//g;
-      s/\".*//;
-      if (s/ Oc( |$)/ /) {
-       $Groff{'Oo'}--;
-      }
-      redo;
-    } elsif (/^\.(PRINTSTYLE|START)$Sp/) {
-      $Groff{'mom'}++;
-    }
-    if (/^\.so$Sp/) {
-      chop;
-      s/^.so *//;
-      s/\\\".*//;
-      s/ .*$//;
-      # The next if-clause catches e.g.
-      #
-      #   .EQ
-      #   .so foo
-      #   .EN
-      #
-      # However, the code is not fully correct since it is too generous.
-      # Theoretically, we should check for .so only within preprocessor
-      # blocks like .EQ/.EN or .TS/.TE; but it doesn't harm if we call
-      # soelim even if we don't need to.
-      if ( $Groff{'pic'} || $Groff{'tbl'} || $Groff{'eqn'} ||
-          $Groff{'grn'} || $Groff{'grap'} || $Groff{'refer'} ||
-          $Groff{'refer_open'} || $Groff{'refer_close'} ||
-          $Groff{'chem'} ) {
-       $Groff{'soelim'}++;
-      }
-      &process($_, $level + 1) unless /\\/ || $_ eq "";
-    }
-  }
-  close(FILE);
+our %at_at;
+my $file_perl_test_pl;
+my $grog_dir;
+
+if ($before_make) { # before installation
+  my $grog_source_dir = $FindBin::Bin;
+  $at_at{'BINDIR'} = $grog_source_dir;
+  $grog_dir = $grog_source_dir;
+  $file_perl_test_pl = File::Spec->catfile($grog_source_dir,
+                                          'perl_test.pl');
+  my $top = $grog_source_dir . '/../../../';
+  open FILE, '<', $top . 'VERSION' ||
+    die 'Could not open top file VERSION.';
+  my $version = <FILE>;
+  chomp $version;
+  close FILE;
+  open FILE, '<', $top . 'REVISION' ||
+    die 'Could not open top file REVISION.';
+  my $revision = <FILE>;
+  chomp $revision;
+  $at_at{'GROFF_VERSION'} = $version . '.' . $revision;
+} else { # after installation}
+  $at_at{'GROFF_VERSION'} = '@VERSION@';
+  $at_at{'BINDIR'} = '@BINDIR@';
+  $grog_dir = '@grog_dir@';
+  $file_perl_test_pl = File::Spec->catfile($grog_dir,
+                                          'perl_test.pl');
 }
 
-sub help {
-  print <<EOF;
-usage: grog [option]... [--] [filespec]...
-
-"filespec" is either the name of an existing, readable file or "-" for
-standard input.  If no "filespec" is specified, standard input is
-assumed automatically.
+die "$grog_dir is not an existing directory;" unless -d $grog_dir;
 
-"option" is either a "groff" option or one of these:
+unshift(@INC, $grog_dir);
 
--C            compatibility mode
--h --help     print this uasge message
--v --version  print version information
+require 'subs.pl';
 
-"groff" options are appended to the output, "-m" options are checked.
-
-EOF
-  exit 0;
+our $Prog = $0;
+{
+  my ($v, $d, $f) = File::Spec->splitpath($Prog);
+  $Prog = $f;
 }
 
-sub version {
-  my ($exit_status) = @_;
-  print "Perl version of GNU $Prog of $Last_Update " .
-    'in groff version @VERSION@' . "\n";
-  exit $exit_status;
-}
 
-{
-  my @m = ();
-  my $is_man = 0;
-  my $is_mm = 0;
-  my $is_mom = 0;
+&minus_args();
 
-  $Groff{'refer'} ||= $Groff{'refer_open'} && $Groff{'refer_close'};
 
-  if ( $Groff{'pic'} || $Groff{'tbl'} || $Groff{'eqn'} ||
-       $Groff{'grn'} || $Groff{'grap'} || $Groff{'refer'} ||
-       $Groff{'chem'} ) {
-    my $s = "-";
-    $s .= "s" if $Groff{'soelim'};
-    $s .= "R" if $Groff{'refer'};
-    $s .= "G" if $Groff{'grap'};
-    $s .= "j" if $Groff{'chem'};
-    $s .= "p" if $Groff{'pic'};
-    $s .= "g" if $Groff{'grn'};
-    $s .= "t" if $Groff{'tbl'};
-    $s .= "e" if $Groff{'eqn'};
-    push(@Command, $s);
-  }
 
-  if ( $Groff{'me'} ) {
-    push(@m, '-me');
-    push(@Command, '-me');
-  }
-  if ( $Groff{'SH'} && $Groff{'TH'} ) {
-    push(@m, '-man');
-    push(@Command, '-man');
-    $is_man = 1;
+foreach my $file ( @ARGV ) { # test for each file name in the arguments
+  unless ( open(FILE, $file eq "-" ? $file : "< $file") ) {
+    print STDERR "$Prog: can't open \`$file\': $!";
+    next;
   }
-  if ( $Groff{'mom'} ) {
-    push(@m, '-mom');
-    push(@Command, '-mom');
-    $is_mom = 1;
-  }
-  if ( $Groff{'mm'} || ($Groff{'P'} && ! $is_man) ) {
-    push(@m, '-mm');
-    push(@Command, '-mm');
-    $is_mm = 1;
-  }
-  if ( $Groff{'NH'} || ($Groff{'TL'} && ! $is_mm) ||
-       ($Groff{'ILP'} && ! $is_man) ||
-       ($Groff{'PP'} && ! $is_mom && ! $is_man) ) {
-    # .PP occurs in -mom, -man and -ms, .IP and .LP occur in -man and -ms
-    push(@m, '-ms');
-    push(@Command, '-ms');
-  }
-  if ( $Groff{'mdoc'} ) {
-    my $s = ( $Groff{'mdoc_old'} || $Groff{'Oo'} ) ? '-mdoc-old' : '-mdoc';
-    push(@m, $s);
-    push(@Command, $s);
-  }
-
-  unshift @Command, 'groff';
-  push(@Command, @ARGV);
-
-  foreach (@Command) {
-    next unless /\s/;
-    $_ = "'" . $_ . "'";
-  }
-
-  # We could implement an option to execute the command here.
 
-#  foreach (@Command) {
-#    next unless /[\$\\\"\';&()|<> \t\n]/;
-#    s/\'/\'\\\'\'/;
-#    $_ = "'" . $_ . "'";
-#  }
+  my $line = <FILE>;
 
-  my $n = scalar @m;
-  my $np = scalar @Mparams;
-  print STDERR "$Prog: more than 1 `-m' argument: @Mparams" if $np > 1;
-  if ($n == 0) {
-    unshift @Command, $Mparams[0] if $np == 1;
-  } elsif ($n == 1) {
-    if ($np == 1) {
-      print STDERR "$Prog: wrong `-m' argument: $Mparams[0]\n"
-       if $m[0] ne $Mparams[0];
+  if ( defined $line ) {
+    if ( $line ) {
+      chomp $line;
+      unless ( &do_first_line( $line, $file ) ) {      # not an option line
+       &do_line( $line, $file );
+      }
+    } else {
+      # empty first line
     }
-  } else {
-    print STDERR "$Prog: error: there are several macro packages: @m\n";
+  } else {     # empty file, go to next filearg
+    close (FILE);
+    next;
   }
 
-  print "@Command\n";
+  while (<FILE>) {
+    chomp;
+    &do_line( $_, $file );
+  }
+  close(FILE);
 
-  exit $n if $n > 1;
-  exit 0;
 }
 
+&make_groff_line();
+
+
+1;
 ########################################################################
 ### Emacs settings
 # Local Variables:
diff --git a/src/roff/grog/perl_test.pl b/src/roff/grog/perl_test.pl
index 19c68ed..5cc18cc 100644
--- a/src/roff/grog/perl_test.pl
+++ b/src/roff/grog/perl_test.pl
@@ -5,11 +5,11 @@
 # Source file position: <groff-source>/roff/grog/perl_test.sh
 # Installed position: <prefix>/lib/groff/grog/perl_test.sh
 
-# Copyright (C) 2013
+# Copyright (C) 2013-14
 #   Free Software Foundation, Inc.
 # Written by Bernd Warken <address@hidden>.
 
-# Last update: 12 Apr 2013
+# Last update: 04 Jun 2014
 
 # This file is part of `grog', which is part of `groff'.
 
@@ -29,7 +29,7 @@
 ########################################################################
 
 # This file tests whether perl has a suitable version.  It is used by
-# glilypond.pl and Makefile.sub.
+# grog.pl and Makefile.sub.
 
 require v5.6;
 
diff --git a/src/roff/grog/subs.pl b/src/roff/grog/subs.pl
new file mode 100644
index 0000000..9025bf5
--- /dev/null
+++ b/src/roff/grog/subs.pl
@@ -0,0 +1,626 @@
+#! /usr/bin/env perl
+# grog - guess options for groff command
+# Inspired by doctype script in Kernighan & Pike, Unix Programming
+# Environment, pp 306-8.
+
+# Source file position: <groff-source>/src/roff/grog/subs.pl
+# Installed position: <prefix>/lib/grog/subs.pl
+
+# Copyright (C) 1993, 2006, 2009, 2011-2012, 2014
+#               Free Software Foundation, Inc.
+# Split from grog.pl and put under GPL2 by
+#               Bernd Warken <address@hidden>.
+
+# This file is part of `grog', which is part of `groff'.
+
+# `groff' 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 of the License, or
+# (at your option) any later version.
+
+# `groff' 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/gpl-2.0.html>.
+
+########################################################################
+# Last_Update = '10 Jun 2014';
+########################################################################
+
+require v5.6;
+
+use warnings;
+use strict;
+use File::Spec;
+
+$\ = "\n";
+
+# my $Sp = "[\\s\\n]";
+# my $Sp = qr([\s\n]);
+# my $Sp = '' if $arg eq '-C';
+my $Sp = '';
+
+my @Command;                   # stores the final output
+my @Mparams;                   # stores the options `-m*'
+my $do_run = 0;                        # run generated `groff' command
+my $pdf_with_ligatures = 0;    # `-P-y -PU' for `pdf' device
+my $device = '';
+
+our $Prog;
+
+my %macros;
+my %Groff = (
+            # preprocessors
+            'chem' => 0,
+            'eqn' => 0,
+            'gperl' => 0,
+            'grap' => 0,
+            'grn' => 0,
+            'lilypond' => 0,
+            'pic' => 0,
+            'refer' => 0,
+            'refer_open' => 0,
+            'refer_close' => 0,
+            'soelim' => 0,
+            'tbl' => 0,
+
+            # tmacs
+            'man' => 0,
+            'mdoc' => 0,
+            'mdoc_old' => 0,
+            'me' => 0,
+            'mm' => 0,
+            'mom' => 0,
+            'ms' => 0,
+
+            # requests
+            'NH' => 0,         # ms
+            'TH' => 0,         # man and ms
+            'SH' => 0,         # man and ms
+            'SS' => 0,         # man
+            'P' => 0,          # man
+
+            # for mdoc and mdoc-old
+            # .Oo and .Oc for modern mdoc, only .Oo for mdoc-old
+            'Oo' => 0,         # mdoc and mdoc-old
+            'Oc' => 0,         # mdoc
+            'Dd' => 0,         # mdoc
+);
+
+
+############################ subs ######################################
+
+########################################################################
+# sub minus_args: command line arguments except file names
+########################################################################
+
+sub minus_args {
+  my @filespec = ();
+  my $double_minus = 0;
+  my $was_minus = 0;
+  my $was_T = 0;
+  my $had_filespec = 0;
+
+  foreach my $arg (@ARGV) {
+    next unless $arg;
+    if ($double_minus) {
+      $had_filespec = 1;
+      if (-f $arg && -r $arg) {
+       push @filespec, $arg;
+      } else {
+       print STDERR "grog: $arg is not a readable file.";
+      }
+      next;
+    }
+
+    if ( $was_T ) {
+      $was_T = 0;
+      $device = $arg;
+      next;
+    }
+
+    if ( $arg =~ /^--/ ) {
+
+      if ($arg eq '--') {
+       $double_minus = 1;
+       push(@Command, $arg);
+       next;
+      }
+
+      &version() if $arg =~ /^--?v/;   # --version, with exit
+      &help() if $arg  =~ /--?h/;      # --help, with exit
+
+      if ( $arg =~ /^--?r/ ) {         #  --run, no exit
+       $do_run = 1;
+       next;
+      }
+
+      if ( $arg =~ /^--?w/ ) {         #  --with_ligatures, no exit
+       $pdf_with_ligatures = 1;
+       next;
+      }
+    }
+
+    print STDERR "grog: wrong option $arg." if $arg =~ /^--/;
+
+    if ($arg eq '-') {
+      unless ($was_minus) {
+       push @filespec, $arg;
+       $was_minus = 1;
+      }
+      next;
+    }
+
+    if ($arg =~ /^-m/) {
+      push @Mparams, $arg;
+      next;
+    }
+
+    if ($arg =~ /^-T\s*$/) {
+      $was_T = 1;
+      next;
+    }
+
+    if ($arg =~ s/^-T(.+)$/$1/) {
+      $device = $arg;
+      next;
+    }
+
+    if ($arg =~ /^-/) {
+      push(@Command, $arg);
+      next;
+    } else {
+      $had_filespec = 1;
+      if (-f $arg && -r $arg) {
+       push @filespec, $arg;
+      } else {
+       print STDERR "grog: $arg is not a readable file.";
+      }
+      next;
+    }
+  }
+  @filespec = ('-') if ! @filespec && ! $had_filespec;
+  exit 1 unless @filespec;
+  @ARGV = @filespec;
+}
+
+
+########################################################################
+# sub do_first_line
+########################################################################
+
+# As documented for the `man' program, the first line can be
+# used as an groff option line.  This is done by:
+# - start the line with '\" (apostrophe, backslash, double quote)
+# - add a space character
+# - a word using the following characters can be appended: `egGjpRst'.
+#     Each of these characters means an option for the generated
+#     `groff' command line, e.g. `-t'.
+
+sub do_first_line {
+  my ( $line, $file ) = @_;
+
+  # For a leading groff options line use only [egGjpRst]
+  if  ( $line =~ /^[.']\\"[\segGjpRst]+&/ ) {
+    # this is a groff options leading line
+    if ( $line =~ /^\./ ) {
+      # line is a groff options line with . instead of '
+      print "First line in $file must start with an apostrophe \ " .
+       "instead of a period . for groff options line!";
+    }
+
+    if ( $line =~ /e/ ) {
+      $Groff{'eqn'}++;
+    }
+    if ( $line =~ /g/ ) {
+      $Groff{'grn'}++;
+    }
+    if ( $line =~ /G/ ) {
+      $Groff{'grap'}++;
+    }
+    if ( $line =~ /j/ ) {
+      $Groff{'chem'}++;
+    }
+    if ( $line =~ /p/ ) {
+      $Groff{'pic'}++;
+    }
+    if ( $line =~ /R/ ) {
+      $Groff{'refer'}++;
+    }
+    if ( $line =~ /s/ ) {
+      $Groff{'soelim'}++;
+    }
+    if ( $line =~ /t/ ) {
+      $Groff{'tbl'}++;
+    }
+    return 1;  # a leading groff options line
+  } else {
+    return 0;  # not a leading groff options line
+  }
+}      # sub do_first_line
+
+
+########################################################################
+# sub do_line
+########################################################################
+
+sub do_line {
+  my ( $line, $file ) = @_;
+
+  return if ( $line =~ /^[.']\s*\\"/ );        # comment
+
+  return unless ( $line =~ /^[.']/ );  # ignore text lines
+
+  $line =~ s/^['.]\s*/./;      # let only a dot as leading character,
+                               # remove spaces after the leading dot
+  $line =~ s/\s+$//;           # remove final spaces
+
+  return if ( $line =~ /^\.$/ );       # ignore .
+  return if ( $line =~ /^\.\.$/ );     # ignore ..
+
+  # soelim
+  if ( $line =~ /^\.(so|mso|PS\s*<).*$/ ) {    # `.so', `.mso', `.PS<...'
+    $Groff{'soelim'}++;
+    return;
+  }
+  if ( $line =~ /^\.\s*do\s*(so|mso|PS\s*<).*$/ ) {    # `.do so', etc
+    $Groff{'soelim'}++;
+    return;
+  }
+
+  if ( $line =~ /^\.de1?\W?/ ) {
+    # this line is a macro definition, add it to %macros
+    my $macro = $line;
+    $macro =~ s/^\.de1?\s+(\w+)\W*/.$1/;
+    return if ( exists $macros{$macro} );
+    $macros{ $macro } = 1;
+    return;
+  }
+
+  $line =~ s/(\.\w+).*$/$1/;           # let only request left
+
+  {
+    # if line command is a defined macro, just ignore this line
+    my $macro = $line;
+    $macro =~ s/^(\.\w+)/$1/;
+    return if ( exists $macros{ $macro } );
+  }
+
+  # preprocessors
+  if ( $line =~ /^(\.cstart)|(begin\s+chem)$/ ) {
+    $Groff{'chem'}++;          # for chem
+    return;
+  }
+  if ( $line =~ /^\.EQ$/ ) {
+    $Groff{'eqn'}++;           # for eqn
+    return;
+  }
+  if ( $line =~ /^\.G1$/ ) {
+    $Groff{'grap'}++;          # for grap
+    return;
+  }
+  if ( $line =~ /^\.Perl$/ ) {
+    $Groff{'gperl'}++;         # for gperl
+    return;
+  }
+  if ( $line =~ /^\.GS$/ ) {
+    $Groff{'grn'}++;           # for grn
+    return;
+  }
+  if ( $line =~ /^\.lilypond$/ ) {
+    $Groff{'lilypond'}++;      # for glilypond
+    return;
+  }
+  if ( $line =~ /^\.PS$/ ) {
+    $Groff{'pic'}++;           # for gpic
+    return;
+  }
+  if ( $line =~ /^\.R1$/ ) {
+    $Groff{'refer'}++;         # for refer
+    return;
+  }
+  if ( $line =~ /^\.\[$/ ) {
+    $Groff{'refer_open'}++;    # for refer open
+    return;
+  }
+  if ( $line =~ /^\.\]$/ ) {
+    $Groff{'refer_close'}++;   # for refer close
+    return;
+  }
+  if ( $line =~ /^\.TS$/ ) {
+    $Groff{'tbl'}++;           # for tbl
+    return;
+  }
+
+
+  # devices
+
+  # for man
+  if ( $line =~ /^\.TH$/ ) {
+    $Groff{'TH'}++;
+    return;
+  }
+  if ( $line =~ /^\.SH$/ ) {
+    $Groff{'SH'}++;
+    return;
+  }
+  if ( $line =~ /^\.SS$/ ) {
+    $Groff{'SS'}++;
+    return;
+  }
+#  if ( $line =~ /^\.P$/ ) {
+#   $Groff{'P'}++;
+#    return;
+#  }
+
+  # In the old version of -mdoc `Oo' is a toggle, in the new it's
+  # closed by `Oc'.
+  if ( $line =~ /^\.Oc$/ ) {
+    $Groff{'Oc'}++;            # only for modern mdoc
+    return;
+  }
+  if ( $line =~ /^\.Oo$/ ) {
+    $Groff{'Oo'}++;            # for mdoc and mdoc-old
+    return;
+  }
+
+  if ( $line =~ /^\.(Dd)$/ ) {
+    $Groff{'Dd'}++;            # for modern mdoc
+    return;
+  }
+  if ( $line =~ /^\.(Tp|Dp|De|Cx|Cl)$/ ) {
+    $Groff{'mdoc_old'}++;      # true for old mdoc
+    return;
+  }
+
+  if ( $line =~ /^\.([ilnp]p|sh)$/ ) {
+    $Groff{'me'}++;            # for me
+    return;
+  }
+  if ( $line =~ /^\.(PH|SA)$/ ) {
+    $Groff{'mm'}++;            # for mm
+    return;
+  }
+  if ( $line =~ /^\.(PRINTSTYLE|START)$/ ) {
+    $Groff{'mom'}++;           # for mom
+    return;
+  }
+  if ( $line =~ /^\.NH$/ ) {
+    $Groff{'NH'}++;            # for ms
+    return;
+  }
+} # sub do_line
+
+
+########################################################################
+# sub make_groff_line
+########################################################################
+
+sub make_groff_line {
+  my @m = ();
+  my @preprograms = ();
+
+  # device from -T
+  $device = '' unless ( defined $device );
+
+  # default device when without `-T' is `ps' ($device empty)
+
+  if ( $device =~
+       /^(
+         dvi
+       |
+         html
+       |
+         xhtml
+       |
+         lbp
+       |
+         lj4
+       |
+         ps
+       |
+         pdf
+       |
+         ascii
+       |
+         cp1047
+       |
+         latin1
+       |
+         utf8
+       )$/x ) {        # suitable device
+
+    push(@Command, '-T' . $device);    # for all suitable devices
+
+    if ( $device eq 'pdf' ) {
+      if ( $pdf_with_ligatures ) {     # with ligature argument
+       push( @Command, '-P-y -PU' );
+      } else { # no ligature argument
+       print STDERR <<EOF;
+If you have trouble with ligatures like `fi' in the `groff' output, you
+can proceed as one of
+- add `grog' option `--with_ligatures' or
+- use the `grog' option combination `-P-y -PU' or
+- try to remove the font named similar to `fonts-texgyre' from your system.
+EOF
+      }        # end of ligature
+    }  # end of pdf device
+  } else {     # wrong device
+    if ( $device ) {
+      print STDERR 'The device ' . $device . ' for -T is wrong.';
+      $device = '';
+    }
+  }
+
+  # preprocessors
+  if ( $Groff{'lilypond'} ) {
+    push @preprograms, 'glilypond';
+  }
+  if ( $Groff{'gperl'} ) {
+    push @preprograms, 'gperl';
+  }
+  $Groff{'refer'} ||= $Groff{'refer_open'} && $Groff{'refer_close'};
+  if ( $Groff{'pic'} || $Groff{'tbl'} || $Groff{'eqn'} ||
+       $Groff{'grn'} || $Groff{'grap'} || $Groff{'refer'} ||
+       $Groff{'chem'} ) {
+    my $s = "-";
+    $s .= "e" if $Groff{'eqn'};
+    $s .= "g" if $Groff{'grn'};
+    $s .= "G" if $Groff{'grap'};
+    $s .= "j" if $Groff{'chem'};
+    $s .= "p" if $Groff{'pic'};
+    $s .= "R" if $Groff{'refer'};
+    $s .= "s" if $Groff{'soelim'};
+    $s .= "t" if $Groff{'tbl'};
+    push(@Command, $s);
+  }
+
+
+  # tmacs
+
+  if ( $Groff{'TH'} && ( $Groff{'SH'} ||  $Groff{'SS'} ) ) {
+    $Groff{'TH'} = 0;
+    $Groff{'SH'} = 0;
+    $Groff{'SS'} = 0;
+    $Groff{'man'} = 1;
+    push(@m, '-man');
+    push(@Command, '-man');
+  }
+
+  if ( $Groff{'NH'} ) {
+    $Groff{'ms'}++;
+    push(@m, '-ms');
+    push(@Command, '-ms');
+  }
+
+  if ( ( $Groff{'Oo'} && $Groff{'Oc'} ) || $Groff{'Dd'} ) {
+    $Groff{'Oc'} = 0;
+    $Groff{'Oo'} = 0;
+    push(@m, '-mdoc');
+    push(@Command, '-mdoc');
+  }
+
+  if ( $Groff{'mdoc_old'} || $Groff{'Oo'} ) {
+    push(@m, '-mdoc_old');
+    push(@Command, '-mdoc_old');
+  }
+
+
+  if ( $Groff{'me'} ) {
+    push(@m, '-me');
+    push(@Command, '-me');
+  }
+  if ( $Groff{'mm'} ) {
+    push(@m, '-mm');
+    push(@Command, '-mm');
+  }
+  if ( $Groff{'mom'} ) {
+    push(@m, '-mom');
+    push(@Command, '-mom');
+  }
+
+
+  unshift @Command, 'groff';
+  if ( @preprograms ) {
+    my @progs;
+    $progs[0] = shift @preprograms;
+    push(@progs, @ARGV);
+    for ( @preprograms ) {
+      push @progs, '|';
+      push @progs, $_;
+    }
+    push @progs, '|';
+    unshift @Command, @progs;
+  } else {
+    push(@Command, @ARGV);
+  }
+
+  foreach (@Command) {
+    next unless /\s/;
+    $_ = "'" . $_ . "'";
+  }
+
+
+  my $n = scalar @m;
+  my $np = scalar @Mparams;
+  print STDERR "$Prog: more than 1 `-m' argument: @Mparams" if $np > 1;
+  if ($n == 0) {
+    unshift @Command, $Mparams[0] if $np == 1;
+  } elsif ($n == 1) {
+    if ($np == 1) {
+      print STDERR "$Prog: wrong `-m' argument: $Mparams[0]"
+       if $m[0] ne $Mparams[0];
+    }
+  } else {
+    print STDERR "$Prog: error: there are several macro packages: @m";
+    exit 1;
+  }
+
+  # execute the `groff' command here with option `--run'
+  if ( $do_run ) {
+    print STDERR "@Command";
+    system(join ' ', @Command);
+  } else {
+    print "@Command";
+  }
+
+  exit $n if $n > 1;
+  exit 0;
+}      # sub make_groff_line
+
+
+########################################################################
+# sub help
+########################################################################
+
+sub help {
+  print <<EOF;
+usage: grog [option]... [--] [filespec]...
+
+"filespec" is either the name of an existing, readable file or "-" for
+standard input.  If no `filespec' is specified, standard input is
+assumed automatically.  All arguments after a `--' are regarded as file
+names, even if they start with a `-' character.
+
+`option' is either a `groff' option or one of these:
+
+-h --help              print this uasge message and exit
+-v --version           print version information and exit
+
+-C                     compatibility mode
+--run                  run the checked-out groff command
+--with_ligatures       include options `-P-y -PU' for internal font,
+                       which preserverses the ligatures like `fi'
+
+All other options should be `groff' 1-character options.  These are then
+appended to the generated `groff' command line.  The `-m' options will
+be checked by `grog'.
+
+EOF
+  exit 0;
+} # sub help
+
+
+########################################################################
+# sub version
+########################################################################
+
+sub version {
+  our %at_at;
+  our $Last_Update;
+  print "Perl version of GNU $Prog of $Last_Update " .
+    "in groff version " . $at_at{'GROFF_VERSION'};
+  exit 0;
+} # sub version
+
+
+1;
+########################################################################
+### Emacs settings
+# Local Variables:
+# mode: CPerl
+# End:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]