diff options
Diffstat (limited to 'contrib/gperl')
-rw-r--r-- | contrib/gperl/ChangeLog | 142 | ||||
-rw-r--r-- | contrib/gperl/gperl.1.man | 491 | ||||
-rw-r--r-- | contrib/gperl/gperl.am | 48 | ||||
-rwxr-xr-x | contrib/gperl/gperl.pl | 257 |
4 files changed, 938 insertions, 0 deletions
diff --git a/contrib/gperl/ChangeLog b/contrib/gperl/ChangeLog new file mode 100644 index 0000000..813c320 --- /dev/null +++ b/contrib/gperl/ChangeLog @@ -0,0 +1,142 @@ +2022-10-09 G. Branden Robinson <g.branden.robinson@gmail.com> + + * gperl.pl: Include groff version information when reporting our + own (as recommended by GNU coding standards). Also drop + gratuitous quotation of program's own name. + +2022-05-03 G. Branden Robinson <g.branden.robinson@gmail.com> + + * gperl.am (gperl): Spell dependency on `$(SH_DEPS_SED_SCRIPT)` + using that macro expansion instead of a literal file name. See + groff's doc/automake.mom. + +2021-01-06 Colin Watson <cjwatson@debian.org> + + * gperl.pl: Avoid Perl's unsafe "<>" operator. + + The "<>" operator is implemented using the two-argument form of + "open", which interprets magic such as pipe characters, allowing + execution of arbitrary commands which is unlikely to be + expected. Perl >= 5.22 has a "<<>>" operator which avoids this, + but also forbids the use of "-" to mean the standard input, + which is a facility that the affected groff programs document. + + ARGV::readonly would probably also fix this, but I fundamentally + dislike the approach of escaping data in preparation for a + language facility to unescape it, especially when the required + escaping is as non-obvious as it is here. (For the same reason, + I prefer to use subprocess invocation facilities that allow + passing the argument list as a list rather than as a string to + be interpreted by the shell.) So I've abandoned this dubious + convenience and changed the affected programs to iterate over + command-line arguments manually using the three-argument form of + open. + + Fixes <https://savannah.gnu.org/bugs/?55557>. + +2020-04-22 G. Branden Robinson <g.branden.robinson@gmail.com> + + * gperl.1.man: Delete references to groffer. + +2018-02-28 Werner LEMBERG <wl@gnu.org> + + * gperl.am (gperl): Use $(AM_V_GEN) to silence file generation. + +2015-08-22 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.1.man: Rename `gperl.man'. + + * gperl.am: Include renaming. + +2015-08-05 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.am: Add `Last update'. Setup Emacs mode. + +2015-04-03 Werner LEMBERG <wl@gnu.org> + + * gperl.man: Make it work in compatibility mode. + (EL): Fix typo. + +2014-10-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.6 + Replace `capturex' with backtics, so `use IPC::System::Simple' + can be removed. + +2014-09-03 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.5 + + * all files in `gperl': Copying and Emacs setting. + +2014-07-06 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.4 + Improve handling of `.Perl' lines. + +2014-07-06 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.3 + + * gperl.man: Compatioble to `doclifter'. + +2014-07-04 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.2 + + * gperl.man: Transform to classical man-page style. + +2014-07-03 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Improve definitions. + +2014-06-15 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2.1. + + * gperl.man: Correct the Legalese and documentation of options. + +2014-06-15 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.2. Getting several storage variables from + printing in `Perl' with several lines. Accept string and number + register variable names for `.ds' and `.nr'. + + * gperl.man: Rewrite with the actual additions. + +2014-06-14 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Version 1.1. New structure without subs. Restrict + storage to only strings by creating only `.ds'. + + * gperl.man: Major rewrite. Omit `.nr'. + +2014-02-27 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl: Admit file name arguments. Handle correct temporary + file. + +2014-02-25 Bernd Warken <groff-bernd.warken-72@web.de> + + * gperl.pl, gperl.man, ChangeLog, Makefile.sub: + first version 1.0 + +2014-02-25 Bernd Warken <groff-bernd.warken-72@web.de> +________________________________________________________________________ +License + +Copyright (C) 2014-2020 Free Software Foundation, Inc. +Written by Bernd Warken <groff-bernd.warken-72@web.de>. + +Copying and distribution of this file, with or without +modification, are permitted provided the copyright notice and this +notice are preserved. + +This file is part of `gperl', which is part of the `groff' +project. + +##### Editor settings + +Local Variables: +mode: change-log +End: diff --git a/contrib/gperl/gperl.1.man b/contrib/gperl/gperl.1.man new file mode 100644 index 0000000..14afdcf --- /dev/null +++ b/contrib/gperl/gperl.1.man @@ -0,0 +1,491 @@ +.TH gperl @MAN1EXT@ "@MDATE@" "groff @VERSION@" +.SH Name +gperl \- execute Perl commands in +.I groff +documents +. +. +.\" ==================================================================== +.\" Legal Terms +.\" ==================================================================== +.\" +.\" Copyright (C) 2014-2020 Free Software Foundation, Inc. +.\" +.\" This file is part of gperl, which is part of groff, a free software +.\" project. +.\" +.\" You can redistribute it and/or modify it under the terms of the GNU +.\" General Public License as published by the Free Software Foundation, +.\" version 2. +.\" +.\" The license text is available in the internet at +.\" <http://www.gnu.org/licenses/gpl-2.0.html>. +. +. +.\" Save and disable compatibility mode (for, e.g., Solaris 10/11). +.do nr *groff_gperl_1_man_C \n[.cp] +.cp 0 +. +.\" Define fallback for groff 1.23's MR macro if the system lacks it. +.nr do-fallback 0 +.if !\n(.f .nr do-fallback 1 \" mandoc +.if \n(.g .if !d MR .nr do-fallback 1 \" older groff +.if !\n(.g .nr do-fallback 1 \" non-groff *roff +.if \n[do-fallback] \{\ +. de MR +. ie \\n(.$=1 \ +. I \%\\$1 +. el \ +. IR \%\\$1 (\\$2)\\$3 +. . +.\} +.rr do-fallback +. +. +.\" ==================================================================== +.SH Synopsis +.\" ==================================================================== +. +.SY gperl +.RI [ file\~ .\|.\|.] +.YS +. +. +.SY gperl +.B \-h +. +.SY gperl +.B \-\-help +.YS +. +.SY gperl +.B \-v +. +.SY gperl +.B \-\-version +.YS +. +. +.\" ==================================================================== +.SH Description +.\" ==================================================================== +. +This is a preprocessor for +.MR groff @MAN1EXT@ . +. +It allows the use of +.MR perl 7 +code in +.MR groff @MAN7EXT@ +files. +. +The result of a +.I Perl part +can be stored in groff +.I strings +or +.I numerical registers +based on the arguments at a final line of a +.IR "Perl part" . +. +. +.P +If no operands are given, +or if +.I file +is +.RB \[lq] \- \[rq], +.I gperl +reads the standard input stream. +. +A double-dash argument +.RB (\[lq] \-\- \[rq]) +causes all subsequent arguments to be interpreted as +.I file +operands, +even if their names start with a dash. +. +.B \-h +and +.B \-\-help +display a usage message, +whereas +.B \-v +and +.B \-\-version +display version information; +all exit afterward. +. +. +.\" ==================================================================== +.SH "Perl regions" +.\" ==================================================================== +. +.I Perl +parts in +.I groff files +are enclosed by two +.B .Perl +requests with different arguments, a +.I starting +and an +.I ending +command. +. +. +.\" ==================================================================== +.SS "Starting Perl mode" +.\" ==================================================================== +. +The starting +.I Perl request +can either be without arguments, or by a request that has the term +.B start +as its only argument. +.RS +.IP \(bu +.B .Perl +.IP \(bu +.B .Perl start +.RE +. +. +.\" ==================================================================== +.SS "Ending Perl mode without storage" +.\" ==================================================================== +. +A +.B .Perl +command line with an argument different from +.B start +finishes a running +.IR "Perl part" . +. +Of course, it would be reasonable to add the argument +.BR stop ; +that's possible, but not necessary. +. +.RS +.IP \(bu +.B .Perl stop +.IP \(bu +.BI .Perl " other_than_start" +.RE +. +The argument +.I other_than_start +can additionally be used as a +.I groff +string variable name for storage \(em see next section. +. +. +.\" ==================================================================== +.SS "Ending Perl mode with storage" +.\" ==================================================================== +. +A useful feature of +.I gperl +is to store one or more results from the +.IR "Perl mode" . +. +. +.P +The output of a +.I Perl part +can be got with backticks +.BR \[ga]...\[ga] . +. +. +.P +This program collects all printing to STDOUT (normal standard output) +by the Perl +.B print +program. +. +This pseudo-printing output can have several lines, due to printed +line breaks with +.BR \(rsn . +. +By that, the output of a Perl run should be stored into a Perl array, +with a single line for each array member. +. +. +.P +This Perl array output can be stored by +.I gperl +in either +.TP +.I groff strings +by creating a groff command +.B .ds +. +.TP +.I groff register +by creating a groff command +.B .rn +. +. +.P +The storage modes can be determined by arguments of a final stopping +.B .Perl +command. +. +Each argument +.B .ds +changes the mode into +.I groff string +and +.B .nr +changes the mode into +.I groff register +for all following output parts. +. +. +.br +.ne 2v +.P +By default, all output is saved as strings, so +.B .ds +is not really needed before the first +.B .nr +command. +. +That suits to +.MR groff @MAN7EXT@ , +because every output can be saved as +.I groff +string, but the registers can be very restrictive. +. +. +.P +In +.IR "string mode" , +.I gperl +generates a +.I groff string +storage line +.RS +.EX +.BI .ds " var_name content" +.EE +.RE +. +In +.I register mode +the following groff command is generated +.RS +.EX +.BI .nr " var_name content" +.EE +.RE +. +. +.P +We present argument collections in the following. +. +You can add as first argument for all +.BR stop . +. +We omit this additional element. +. +. +.P +.TP +.BI ".Perl .ds " var_name +This will store 1 output line into the groff string named +.I var_name +by the automatically created command +.RS +.RS +.EX +.BI .ds " var_name output" +.EE +.RE +.RE +. +. +.TP +.BI .Perl " var_name" +If +.I var_name +is different from +.B start +this is equivalent to the former command, because the string mode is +string with +.B .ds +command. +default. +. +. +.TP +.BI .Perl " var_name1 var_name2" +This will store 2 output lines into groff string names +.I var_name1 +and +.IR var_name2 , +because the default mode +.B .ds +is active, such that no +.B .ds +argument is needed. +. +Of course, this is equivalent to +.RS +.RS +.EX +.BI ".Perl .ds " "var_name1 var_name2" +.EE +.RE +and +.RS +.EX +.BI ".Perl .ds " "var_name1 " ".ds" " var_name2" +.EE +.RE +.RE +. +. +.TP +.BI ".Perl .nr" " var_name1 varname2" +stores both variables as register variables. +. +.I gperl +generates +.RS +.EX +.BI .nr " var_name1 output_line1" +.BI .nr " var_name2 output_line2" +.EE +.RE +. +. +.TP +.BI ".Perl .nr " var_name1 " .ds " var_name2 +stores the 1st argument as +.I register +and the second as +.I string +by +.RS +.EX +.BI .nr " var_name1 output_line1" +.BI .ds " var_name2 output_line2" +.EE +.RE +. +. +.\" ==================================================================== +.SH Example +.\" ==================================================================== +. +A possible +.I Perl part +in a +.I roff file +could look like that: +.RS +.EX +before +\&.Perl start +my $result = \[aq]some data\[aq]; +print $result; +\&.Perl stop .ds string_var +after +.EE +.RE +. +. +.P +This stores the result +.B \(rqsome data\(rq +into the +.I roff string +called +.BR string_var , +such that the following line is printed: +.RS +.EX +\&.ds string_var some data +.EE +.RE +by +.I gperl +as food for the coming +.I groff +run. +. +. +.P +A +.I Perl part +with several outputs is: +.RS +.EX +\&.Perl start +print \(rqfirst\(rsn\(rq; +print \(rqsecond line\(rsn\(rq; +print \(rq3\(rsn\(rq; +\&.Perl var1 var2 .nr var3 +.EE +.RE +. +This stores 3 printed lines into 3 +.I groff +strings. +.BR var1 , var2 , var3 . +. +So the following +.I groff +command lines are created: +.RS +.EX +\&.ds var1 first +\&.ds var2 second line +\&.nr var3 3 +.EE +.RE +. +. +.\" ==================================================================== +.SH Authors +.\" ==================================================================== +. +.I gperl +was written by +.MT groff\-bernd\:.warken\-72@\:web\:.de +Bernd Warken +.ME . +. +. +.\" ==================================================================== +.SH "See also" +.\" ==================================================================== +. +.P +Man pages related to +.I groff +are +.MR groff @MAN1EXT@ , +.MR groff @MAN7EXT@ , +and +.MR grog @MAN1EXT@ . +. +. +.P +Documents related to +.I Perl +are +.MR perl 1 , +.MR perl 7 . +. +. +.\" Restore compatibility mode (for, e.g., Solaris 10/11). +.cp \n[*groff_gperl_1_man_C] +.do rr *groff_gperl_1_man_C +. +. +.\" Local Variables: +.\" fill-column: 72 +.\" mode: nroff +.\" End: +.\" vim: set filetype=groff textwidth=72: diff --git a/contrib/gperl/gperl.am b/contrib/gperl/gperl.am new file mode 100644 index 0000000..4d275c2 --- /dev/null +++ b/contrib/gperl/gperl.am @@ -0,0 +1,48 @@ +# Automake rules for 'gperl' (preprocessor for added Perl parts) + +# Copyright (C) 2014-2020 Free Software Foundation, Inc. +# Written by Bernd Warken <groff-bernd.warken-72@web.de>. +# Automake migration by Bertrand Garrigues + +# This file is part of 'gperl' 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>. + +######################################################################## + +bin_SCRIPTS += gperl +man1_MANS += contrib/gperl/gperl.1 +EXTRA_DIST += \ + contrib/gperl/ChangeLog \ + contrib/gperl/gperl.1.man \ + contrib/gperl/gperl.pl + +gperl: $(top_srcdir)/contrib/gperl/gperl.pl $(SH_DEPS_SED_SCRIPT) + $(AM_V_GEN)$(RM) $@ \ + && sed -f "$(SH_DEPS_SED_SCRIPT)" \ + -e "s|[@]g[@]|$(g)|g" \ + -e "s|[@]BINDIR[@]|$(DESTDIR)$(bindir)|g" \ + -e "s|[@]VERSION[@]|$(VERSION)|g" \ + -e "$(SH_SCRIPT_SED_CMD)" \ + $(top_srcdir)/contrib/gperl/gperl.pl \ + >$@ \ + && chmod +x $@ + + +# Local Variables: +# mode: makefile-automake +# fill-column: 72 +# End: +# vim: set autoindent filetype=automake textwidth=72: diff --git a/contrib/gperl/gperl.pl b/contrib/gperl/gperl.pl new file mode 100755 index 0000000..2f9f7d1 --- /dev/null +++ b/contrib/gperl/gperl.pl @@ -0,0 +1,257 @@ +#! /usr/bin/env perl + +# gperl - add Perl part to groff files, this is the preprocessor for that + +# Copyright (C) 2014-2020 Free Software Foundation, Inc. + +# Written by Bernd Warken <groff-bernd.warken-72@web.de>. + +my $version = '1.2.6'; + +# This file is part of 'gperl', 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 can find a copy of the GNU General Public License in the internet +# at <http://www.gnu.org/licenses/gpl-2.0.html>. + +######################################################################## + +use strict; +use warnings; +#use diagnostics; + +# temporary dir and files +use File::Temp qw/ tempfile tempdir /; + +# needed for temporary dir +use File::Spec; + +# for 'copy' and 'move' +use File::Copy; + +# for fileparse, dirname and basename +use File::Basename; + +# current working directory +use Cwd; + +# $Bin is the directory where this script is located +use FindBin; + + +######################################################################## +# system variables and exported variables +######################################################################## + +$\ = "\n"; # final part for print command + +######################################################################## +# read-only variables with double-@ construct +######################################################################## + +our $File_split_env_sh; +our $File_version_sh; +our $Groff_Version; + +my $before_make; # script before run of 'make' +{ + my $at = '@'; + $before_make = 1 if '@VERSION@' eq "${at}VERSION${at}"; +} + +my %at_at; +my $file_perl_test_pl; +my $groffer_libdir; + +if ($before_make) { + my $gperl_source_dir = $FindBin::Bin; + $at_at{'BINDIR'} = $gperl_source_dir; + $at_at{'G'} = ''; +} else { + $at_at{'BINDIR'} = '@BINDIR@'; + $at_at{'G'} = '@g@'; +} + + +######################################################################## +# options +######################################################################## + +foreach (@ARGV) { + if ( /^(-h|--h|--he|--hel|--help)$/ ) { + print q(Usage for the 'gperl' program:); + print 'gperl [-] [--] [filespec...] normal file name arguments'; + print 'gperl [-h|--help] gives usage information'; + print 'gperl [-v|--version] displays the version number'; + print q(This program is a 'groff' preprocessor that handles Perl ) . + q(parts in 'roff' files.); + exit; + } elsif ( /^(-v|--v|--ve|--ver|--vers|--versi|--versio|--version)$/ ) { + print "gperl (groff @VERSION@) version $version"; + exit; + } +} + + +####################################################################### +# temporary file +####################################################################### + +my $out_file; +{ + my $template = 'gperl_' . "$$" . '_XXXX'; + my $tmpdir; + foreach ($ENV{'GROFF_TMPDIR'}, $ENV{'TMPDIR'}, $ENV{'TMP'}, $ENV{'TEMP'}, + $ENV{'TEMPDIR'}, 'tmp', $ENV{'HOME'}, + File::Spec->catfile($ENV{'HOME'}, 'tmp')) { + if ($_ && -d $_ && -w $_) { + eval { $tmpdir = tempdir( $template, + CLEANUP => 1, DIR => "$_" ); }; + last if $tmpdir; + } + } + $out_file = File::Spec->catfile($tmpdir, $template); +} + + +######################################################################## +# input +######################################################################## + +my $perl_mode = 0; + +unshift @ARGV, '-' unless @ARGV; +foreach my $filename (@ARGV) { + my $input; + if ($filename eq '-') { + $input = \*STDIN; + } elsif (not open $input, '<', $filename) { + warn $!; + next; + } + while (<$input>) { + chomp; + s/\s+$//; + my $line = $_; + my $is_dot_Perl = $line =~ /^[.']\s*Perl(|\s+.*)$/; + + unless ( $is_dot_Perl ) { # not a '.Perl' line + if ( $perl_mode ) { # is running in Perl mode + print OUT $line; + } else { # normal line, not Perl-related + print $line; + } + next; + } + + + ########## + # now the line is a '.Perl' line + + my $args = $line; + $args =~ s/\s+$//; # remove final spaces + $args =~ s/^[.']\s*Perl\s*//; # omit .Perl part, leave the arguments + + my @args = split /\s+/, $args; + + ########## + # start Perl mode + if ( @args == 0 || @args == 1 && $args[0] eq 'start' ) { + # For '.Perl' no args or first arg 'start' means opening 'Perl' mode. + # Everything else means an ending command. + if ( $perl_mode ) { + # '.Perl' was started twice, ignore + print STDERR q('.Perl' starter was run several times); + next; + } else { # new Perl start + $perl_mode = 1; + open OUT, '>', $out_file; + next; + } + } + + ########## + # now the line must be a Perl ending line (stop) + + unless ( $perl_mode ) { + print STDERR 'gperl: there was a Perl ending without being in ' . + 'Perl mode:'; + print STDERR ' ' . $line; + next; + } + + $perl_mode = 0; # 'Perl' stop calling is correct + close OUT; # close the storing of 'Perl' commands + + ########## + # run this 'Perl' part, later on about storage of the result + # array stores prints with \n + my @print_res = `perl $out_file`; + + # remove 'stop' arg if exists + shift @args if ( $args[0] eq 'stop' ); + + if ( @args == 0 ) { + # no args for saving, so @print_res doesn't matter + next; + } + + my @var_names = (); + my @mode_names = (); + + my $mode = '.ds'; + for ( @args ) { + if ( /^\.?ds$/ ) { + $mode = '.ds'; + next; + } + if ( /^\.?nr$/ ) { + $mode = '.nr'; + next; + } + push @mode_names, $mode; + push @var_names, $_; + } + + my $n_res = @print_res; + my $n_vars = @var_names; + + if ( $n_vars < $n_res ) { + print STDERR 'gperl: not enough variables for Perl part: ' . + $n_vars . ' variables for ' . $n_res . ' output lines.'; + } elsif ( $n_vars > $n_res ) { + print STDERR 'gperl: too many variablenames for Perl part: ' . + $n_vars . ' variables for ' . $n_res . ' output lines.'; + } + if ( $n_vars < $n_res ) { + print STDERR 'gperl: not enough variables for Perl part: ' . + $n_vars . ' variables for ' . $n_res . ' output lines.'; + } + + my $n_min = $n_res; + $n_min = $n_vars if ( $n_vars < $n_res ); + exit unless ( $n_min ); + $n_min -= 1; # for starting with 0 + + for my $i ( 0..$n_min ) { + my $value = $print_res[$i]; + chomp $value; + print $mode_names[$i] . ' ' . $var_names[$i] . ' ' . $value; + } + } +} + + +1; +# Local Variables: +# mode: CPerl +# End: |