2 # grog - guess options for groff command
3 # Inspired by doctype script in Kernighan & Pike, Unix Programming
4 # Environment, pp 306-8.
6 # Source file position: <groff-source>/src/roff/grog/subs.pl
7 # Installed position: <prefix>/lib/grog/subs.pl
9 # Copyright (C) 1993-2014 Free Software Foundation, Inc.
10 # This file was split from grog.pl and put under GPL2 by
11 # Bernd Warken <groff-bernd.warken-72@web.de>.
12 # The macros for identifying the devices were taken from Ralph
13 # Corderoy's `grog.sh' of 2006.
15 # This file is part of `grog', which is part of `groff'.
17 # `groff' is free software; you can redistribute it and/or modify it
18 # under the terms of the GNU General Public License as published by
19 # the Free Software Foundation, either version 2 of the License, or
20 # (at your option) any later version.
22 # `groff' is distributed in the hope that it will be useful, but
23 # WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 # General Public License for more details.
27 # You can get the license text for the GNU General Public License
28 # version 2 in the internet at
29 # <http://www.gnu.org/licenses/gpl-2.0.html>.
31 ########################################################################
40 # printing of hashes: my %hash = ...; print Dumper(\%hash);
45 # my $Sp = "[\\s\\n]";
46 # my $Sp = qr([\s\n]);
47 # my $Sp = '' if $arg eq '-C';
50 # from `src/roff/groff/groff.cpp' near `getopt_long'
52 'abcCd:D:eEf:F:gGhiI:jJkK:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ';
54 my @Command = (); # stores the final output
55 my @Mparams = (); # stores the options `-m*'
57 my $do_run = 0; # run generated `groff' command
58 my $pdf_with_ligatures = 0; # `-P-y -PU' for `pdf' device
59 my $with_warnings = 0;
63 my ($v, $d, $f) = File::Spec->splitpath($Prog);
82 'PS' => 0, # opening for pic
83 'PF' => 0, # alternative opening for pic
84 'PE' => 0, # closing for pic
112 'IP' => 0, # man and ms
113 'LP' => 0, # man and ms
114 'P' => 0, # man and ms
115 'PP' => 0, # man and ms
116 'SH' => 0, # man and ms
126 # for mdoc and mdoc-old
127 # .Oo and .Oc for modern mdoc, only .Oo for mdoc-old
128 'Oo' => 0, # mdoc and mdoc-old
134 # for first line check
167 ########################################################################
169 ########################################################################
172 my $double_minus = 0;
176 # globals: @filespec, @Command, @devices, @Mparams
178 foreach my $arg (@ARGV) {
186 if ( $double_minus ) {
187 if (-f $arg && -r $arg) {
188 push @filespec, $arg;
190 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
191 "grog: $arg is not a readable file.";
201 ####### handle_args()
203 unless ( $arg =~ /^-/ ) { # file name, no opt, no optarg
204 unless (-f $arg && -r $arg) {
205 print 'unknown file name: ' . $arg;
207 push @filespec, $arg;
211 # now $arg starts with `-'
214 unless ($was_minus) {
215 push @filespec, $arg;
223 push(@filespec, $arg);
227 &version() if $arg =~ /^--?v/; # --version, with exit
228 &help() if $arg =~ /--?h/; # --help, with exit
230 if ( $arg =~ /^--r/ ) { # --run, no exit
235 if ( $arg =~ /^--wa/ ) { # --warnings, no exit
239 ####### handle_args()
241 if ( $arg =~ /^--(wi|l)/ ) { # --ligatures, no exit
242 # the old --with_ligatures is only kept for compatibility
243 $pdf_with_ligatures = 1;
252 if ($arg =~ /^-T$/) {
257 if ($arg =~ s/^-T(\w+)$/$1/) {
262 if ($arg =~ /^-(\w)(\w*)$/) { # maybe a groff option
264 my $opt_char_with_arg = $opt_char . ':';
266 if ( $groff_opts =~ /$opt_char_with_arg/ ) { # groff optarg
267 if ( $others ) { # optarg is here
268 push @Command, '-' . $opt_char;
269 push @Command, '-' . $others;
275 ####### handle_args()
276 } elsif ( $groff_opts =~ /$opt_char/ ) { # groff no optarg
277 push @Command, '-' . $opt_char;
278 if ( $others ) { # $others is now an opt collection
279 $arg = '-' . $others;
284 } else { # not a groff opt
285 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
286 'unknown argument ' . $arg;
287 push(@Command, $arg);
292 @filespec = ('-') unless (@filespec);
297 ########################################################################
299 ########################################################################
301 sub handle_file_ext {
302 # get tmac from file name extension
303 # output number of found single tmac
305 # globals: @filespec, $tmac_ext;
307 foreach my $file ( @filespec ) {
308 # test for each file name in the arguments
309 unless ( open(FILE, $file eq "-" ? $file : "< $file") ) {
310 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
311 "$Prog: can't open \`$file\': $!";
315 next unless ( $file =~ /\./ ); # file name has no dot `.'
317 ##### handle_file_ext()
326 next unless ( $ext );
328 ##### handle_file_ext()
329 # these extensions are correct, but not based on a tmac
330 next if ( $ext =~ /^(
349 ##### handle_file_ext()
350 # extensions for man tmac
357 # `man|n' from `groff' source
358 # `1b' from `heirloom'
359 # `[1-9lno]' from man-pages
360 if ( $tmac_ext && $tmac_ext ne 'man' ) {
361 # found tmac is not 'man'
362 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
363 '2 different file name extensions found ' .
364 $tmac_ext . ' and ' . $ext;
369 ##### handle_file_ext()
383 if ( $tmac_ext && $tmac_ext ne $ext ) {
384 # found tmac is not identical to former found tmac
385 ##### handle_file_ext()
386 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
387 '2 different file name extensions found ' .
388 $tmac_ext . ' and ' . $ext;
397 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
398 'Unknown file name extension '. $file . '.';
403 } # handle_file_ext()
406 ########################################################################
407 # handle_whole_files()
408 ########################################################################
410 sub handle_whole_files {
413 foreach my $file ( @filespec ) {
414 unless ( open(FILE, $file eq "-" ? $file : "< $file") ) {
415 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
416 "$Prog: can't open \`$file\': $!";
419 my $line = <FILE>; # get single line
421 unless ( defined($line) ) {
422 # empty file, go to next filearg
429 unless ( &do_first_line( $line, $file ) ) {
431 &do_line( $line, $file );
433 } else { # emptry line
437 while (<FILE>) { # get lines by and by
439 &do_line( $_, $file );
443 } # handle_whole_files()
446 ########################################################################
448 ########################################################################
450 # As documented for the `man' program, the first line can be
451 # used as a groff option line. This is done by:
452 # - start the line with '\" (apostrophe, backslash, double quote)
453 # - add a space character
454 # - a word using the following characters can be appended: `egGjJpRst'.
455 # Each of these characters means an option for the generated
456 # `groff' command line, e.g. `-t'.
459 my ( $line, $file ) = @_;
461 # globals: %preprocs_tmacs
463 # For a leading groff options line use only [egGjJpRst]
464 if ( $line =~ /^[.']\\"[\segGjJpRst]+&/ ) {
465 # this is a groff options leading line
466 if ( $line =~ /^\./ ) {
467 # line is a groff options line with . instead of '
468 print "First line in $file must start with an apostrophe \ " .
469 "instead of a period . for groff options line!";
472 if ( $line =~ /j/ ) {
475 if ( $line =~ /e/ ) {
478 if ( $line =~ /g/ ) {
481 if ( $line =~ /G/ ) {
484 if ( $line =~ /i/ ) {
487 if ( $line =~ /p/ ) {
490 if ( $line =~ /R/ ) {
493 if ( $line =~ /s/ ) {
496 ####### do_first_line()
497 if ( $line =~ /t/ ) {
500 return 1; # a leading groff options line, 1 means yes, 0 means no
503 # not a leading short groff options line
505 return 0 if ( $line !~ /^[.']\\"\s*(.*)$/ ); # ignore non-comments
507 return 0 unless ( $1 ); # for empty comment
509 # all following array members are either preprocs or 1 tmac
510 my @words = split '\s+', $1;
514 for $word ( @words ) {
515 if ( $word eq 'ideal' ) {
517 } elsif ( $word eq 'gpic' ) {
519 } elsif ( $word =~ /^(gn|)eqn$/ ) {
522 if ( exists $preprocs_tmacs{$word} ) {
525 # not word for preproc or tmac
536 ########################################################################
538 ########################################################################
541 my ( $line, $file ) = @_;
543 return if ( $line =~ /^[.']\s*\\"/ ); # comment
545 return unless ( $line =~ /^[.']/ ); # ignore text lines
547 $line =~ s/^['.]\s*/./; # let only a dot as leading character,
548 # remove spaces after the leading dot
549 $line =~ s/\s+$//; # remove final spaces
551 return if ( $line =~ /^\.$/ ); # ignore .
552 return if ( $line =~ /^\.\.$/ ); # ignore ..
555 $line =~ /^(\.\w+)\s*(.*)$/;
557 $command = '' unless ( defined $command );
559 $args = '' unless ( defined $args );
562 ######################################################################
564 if ( $line =~ /^\.(do)?\s*(so|mso|PS\s*<|SO_START).*$/ ) {
565 # `.so', `.mso', `.PS<...', `.SO_START'
569 if ( $line =~ /^\.(do)?\s*(so|mso|PS\s*<|SO_START).*$/ ) {
570 # `.do so', `.do mso', `.do PS<...', `.do SO_START'
576 ######################################################################
579 if ( $line =~ /^\.de1?\W?/ ) {
580 # this line is a macro definition, add it to %macros
582 $macro =~ s/^\.de1?\s+(\w+)\W*/.$1/;
583 return if ( exists $macros{$macro} );
589 # if line command is a defined macro, just ignore this line
590 return if ( exists $macros{$command} );
593 ######################################################################
596 if ( $command =~ /^(\.cstart)|(begin\s+chem)$/ ) {
597 $Groff{'chem'}++; # for chem
600 if ( $command =~ /^\.EQ$/ ) {
601 $Groff{'eqn'}++; # for eqn
604 if ( $command =~ /^\.G1$/ ) {
605 $Groff{'grap'}++; # for grap
608 if ( $command =~ /^\.Perl/ ) {
609 $Groff{'gperl'}++; # for gperl
612 if ( $command =~ /^\.pinyin/ ) {
613 $Groff{'gpinyin'}++; # for gperl
616 if ( $command =~ /^\.GS$/ ) {
617 $Groff{'grn'}++; # for grn
620 if ( $command =~ /^\.IS$/ ) {
621 $Groff{'gideal'}++; # preproc gideal for ideal
624 if ( $command =~ /^\.lilypond$/ ) {
625 $Groff{'lilypond'}++; # for glilypond
631 # pic can be opened by .PS or .PF and closed by .PE
632 if ( $command =~ /^\.PS$/ ) {
633 $Groff{'pic'}++; # normal opening for pic
636 if ( $command =~ /^\.PF$/ ) {
637 $Groff{'PF'}++; # alternate opening for pic
640 if ( $command =~ /^\.PE$/ ) {
641 $Groff{'PE'}++; # closing for pic
645 if ( $command =~ /^\.R1$/ ) {
646 $Groff{'refer'}++; # for refer
649 if ( $command =~ /^\.\[$/ ) {
650 $Groff{'refer_open'}++; # for refer open
653 if ( $command =~ /^\.\]$/ ) {
654 $Groff{'refer_close'}++; # for refer close
657 if ( $command =~ /^\.TS$/ ) {
658 $Groff{'tbl'}++; # for tbl
663 ######################################################################
664 # macro package (tmac)
665 ######################################################################
670 if ( $command =~ /^\.(Dd)$/ ) {
671 $Groff{'Dd'}++; # for modern mdoc
676 # In the old version of -mdoc `Oo' is a toggle, in the new it's
678 if ( $command =~ /^\.Oc$/ ) {
679 $Groff{'Oc'}++; # only for modern mdoc
685 # old and modern mdoc
687 if ( $command =~ /^\.Oo$/ ) {
688 $Groff{'Oo'}++; # for mdoc and mdoc-old
695 if ( $command =~ /^\.(Tp|Dp|De|Cx|Cl)$/ ) {
696 $Groff{'mdoc_old'}++; # true for old mdoc
705 if ( $command =~ /^\.AB$/ ) {
706 $Groff{'AB'}++; # for ms
709 if ( $command =~ /^\.AE$/ ) {
710 $Groff{'AE'}++; # for ms
713 if ( $command =~ /^\.AI$/ ) {
714 $Groff{'AI'}++; # for ms
717 if ( $command =~ /^\.AU$/ ) {
718 $Groff{'AU'}++; # for ms
721 if ( $command =~ /^\.NH$/ ) {
722 $Groff{'NH'}++; # for ms
725 if ( $command =~ /^\.TL$/ ) {
726 $Groff{'TL'}++; # for ms
729 if ( $command =~ /^\.XP$/ ) {
730 $Groff{'XP'}++; # for ms
738 if ( $command =~ /^\.IP$/ ) {
739 $Groff{'IP'}++; # for man and ms
742 if ( $command =~ /^\.LP$/ ) {
743 $Groff{'LP'}++; # for man and ms
747 if ( $command =~ /^\.P$/ ) {
748 $Groff{'P'}++; # for man and ms
751 if ( $command =~ /^\.PP$/ ) {
752 $Groff{'PP'}++; # for man and ms
755 if ( $command =~ /^\.SH$/ ) {
756 $Groff{'SH'}++; # for man and ms
759 if ( $command =~ /^\.UL$/ ) {
760 $Groff{'UL'}++; # for man and ms
768 if ( $command =~ /^\.OP$/ ) { # for man
772 if ( $command =~ /^\.SS$/ ) { # for man
776 if ( $command =~ /^\.SY$/ ) { # for man
780 if ( $command =~ /^\.TH$/ ) {
781 $Groff{'TH'}++; # for man
784 if ( $command =~ /^\.TP$/ ) { # for man
788 if ( $command =~ /^\.UR$/ ) {
789 $Groff{'UR'}++; # for man
792 if ( $command =~ /^\.YS$/ ) { # for man
802 if ( $command =~ /^\.(
806 $Groff{'me'}++; # for me
814 if ( $command =~ /^\.(
824 $Groff{'mm'}++; # for mm and mmse
825 if ( $command =~ /^\.LO$/ ) {
826 if ( $args =~ /^(DNAMN|MDAT|BIL|KOMP|DBET|BET|SIDOR)/ ) {
827 $Groff{'mmse'}++; # for mmse
829 } elsif ( $command =~ /^\.LT$/ ) {
830 if ( $args =~ /^(SVV|SVH)/ ) {
831 $Groff{'mmse'}++; # for mmse
856 $Groff{'mom'}++; # for mom
863 ########################################################################
864 # sub make_groff_device
865 ########################################################################
868 my @preprograms = ();
869 my $correct_tmac = '';
871 sub make_groff_device {
874 # default device is empty, i.e. it is `ps' when without `-T'
875 return '' unless ( @devices );
878 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
879 $_ . ': not a suitable device'
896 ###### make_groff_device()
897 my $device = pop( @devices );
900 next if ( $_ eq $device );
901 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
902 'additional device: ' . $_;
904 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
905 'device ' . $device . ' taken instead';
908 return '' unless ( $device );
910 push @Command, $device;
912 ###### make_groff_device()
913 if ( $device eq 'pdf' ) {
914 if ( $pdf_with_ligatures ) { # with --ligature argument
915 push( @Command, '-P-y' );
916 push( @Command, '-PU' );
917 } else { # no --ligature argument
918 if ( $with_warnings ) {
920 If you have trouble with ligatures like `fi' in the `groff' output, you
921 can proceed as one of
922 - add `grog' option `--with_ligatures' or
923 - use the `grog' option combination `-P-y -PU' or
924 - try to remove the font named similar to `fonts-texgyre' from your system.
928 } # end of pdf device
929 } # make_groff_device()
932 ########################################################################
933 # make_groff_preproc()
934 ########################################################################
936 sub make_groff_preproc {
937 # globals: %Groff, @preprograms, @Command
939 # preprocessors without `groff' option
940 if ( $Groff{'lilypond'} ) {
941 push @preprograms, 'glilypond';
943 if ( $Groff{'gperl'} ) {
944 push @preprograms, 'gperl';
946 if ( $Groff{'gpinyin'} ) {
947 push @preprograms, 'gpinyin';
950 # preprocessors with `groff' option
951 if ( ( $Groff{'PS'} || $Groff{'PF'} ) && $Groff{'PE'} ) {
954 if ( $Groff{'gideal'} ) {
958 ###### make_groff_preproc()
959 $Groff{'refer'} ||= $Groff{'refer_open'} && $Groff{'refer_close'};
961 if ( $Groff{'chem'} || $Groff{'eqn'} || $Groff{'gideal'} ||
962 $Groff{'grap'} || $Groff{'grn'} || $Groff{'pic'} ||
963 $Groff{'refer'} || $Groff{'tbl'} ) {
964 push(@Command, '-s') if $Groff{'soelim'};
966 push(@Command, '-R') if $Groff{'refer'};
968 push(@Command, '-t') if $Groff{'tbl'}; # tbl before eqn
969 push(@Command, '-e') if $Groff{'eqn'};
971 push(@Command, '-j') if $Groff{'chem'}; # chem produces pic code
972 push(@Command, '-J') if $Groff{'gideal'}; # gideal produces pic
973 push(@Command, '-G') if $Groff{'grap'};
974 push(@Command, '-g') if $Groff{'grn'}; # gremlin files for -me
975 push(@Command, '-p') if $Groff{'pic'};
978 } # make_groff_preproc()
981 ########################################################################
982 # make_groff_tmac_man_ms()
983 ########################################################################
985 sub make_groff_tmac_man_ms {
986 # globals: @filespec, $tmac_ext, %Groff
988 # `man' requests, not from `ms'
989 if ( $Groff{'SS'} || $Groff{'SY'} || $Groff{'OP'} ||
990 $Groff{'TH'} || $Groff{'TP'} || $Groff{'UR'} ) {
994 $tmac_ext = 'man' unless ( $tmac_ext );
995 &err('man requests found, but file name extension ' .
996 'was: ' . $tmac_ext) unless ( $tmac_ext eq 'man' );
1001 ###### make_groff_tmac_man_ms()
1002 # `ms' requests, not from `man'
1004 $Groff{'1C'} || $Groff{'2C'} ||
1005 $Groff{'AB'} || $Groff{'AE'} || $Groff{'AI'} || $Groff{'AU'} ||
1006 $Groff{'BX'} || $Groff{'CD'} || $Groff{'DA'} || $Groff{'DE'} ||
1007 $Groff{'DS'} || $Groff{'LD'} || $Groff{'ID'} || $Groff{'NH'} ||
1008 $Groff{'TL'} || $Groff{'UL'} || $Groff{'XP'}
1013 $tmac_ext = 'ms' unless ( $tmac_ext );
1014 &err('ms requests found, but file name extension ' .
1015 'was: ' . $tmac_ext) unless ( $tmac_ext eq 'ms' );
1020 ###### make_groff_tmac_man_ms()
1022 # both `man' and `ms' requests
1023 if ( $Groff{'P'} || $Groff{'IP'} ||
1024 $Groff{'LP'} || $Groff{'PP'} || $Groff{'SH'} ) {
1025 if ( $tmac_ext eq 'man' ) {
1029 } elsif ( $tmac_ext eq 'ms' ) {
1036 } # make_groff_tmac_man_ms()
1040 ########################################################################
1041 # make_groff_tmac_others()
1042 ########################################################################
1044 sub make_groff_tmac_others {
1045 # globals: @filespec, $tmac_ext, %Groff
1048 if ( ( $Groff{'Oo'} && $Groff{'Oc'} ) || $Groff{'Dd'} ) {
1054 if ( $Groff{'mdoc_old'} || $Groff{'Oo'} ) {
1055 push(@m, '-mdoc_old');
1060 if ( $Groff{'me'} ) {
1065 ##### make_groff_tmac_others()
1067 if ( $Groff{'mm'} ) {
1071 if ( $Groff{'mmse'} ) { # Swedish mm
1077 if ( $Groff{'mom'} ) {
1081 } # make_groff_tmac_others()
1084 ########################################################################
1085 # make_groff_line_rest()
1086 ########################################################################
1088 sub make_groff_line_rest {
1089 my $file_args_included; # file args now only at 1st preproc
1090 unshift @Command, 'groff';
1091 if ( @preprograms ) {
1093 $progs[0] = shift @preprograms;
1094 push(@progs, @filespec);
1095 for ( @preprograms ) {
1100 unshift @Command, @progs;
1101 $file_args_included = 1;
1103 $file_args_included = 0;
1106 foreach (@Command) {
1108 # when one argument has several words, use accents
1109 $_ = "'" . $_ . "'";
1115 my $nr_m_guessed = scalar @m;
1116 if ( $nr_m_guessed > 1 ) {
1117 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1118 'argument for -m found: ' . @m;
1121 ###### make_groff_line()
1123 my $nr_m_args = scalar @Mparams; # m-arguments for grog
1124 my $last_m_arg = ''; # last provided -m option
1125 if ( $nr_m_args > 1 ) {
1126 # take the last given -m argument of grog call,
1127 # ignore other -m arguments and the found ones
1128 $last_m_arg = $Mparams[-1]; # take the last -m argument
1129 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1130 $Prog . ": more than 1 `-m' argument: @Mparams";
1131 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1132 'We take the last one: ' . $last_m_arg;
1133 } elsif ( $nr_m_args == 1 ) {
1134 $last_m_arg = $Mparams[0];
1138 if ( $last_m_arg ) {
1141 if ( $_ eq $last_m_arg ) {
1148 $final_m = $last_m_arg;
1150 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1151 'Provided -m argument ' . $last_m_arg .
1152 ' differs from guessed -m args: ' . @m;
1153 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1154 'The argument is taken.';
1155 $final_m = $last_m_arg;
1157 ###### make_groff_line()
1158 } else { # no -m arg provided
1159 if ( $nr_m_guessed > 1 ) {
1160 print STDERR __FILE__ . ' ' . __LINE__ . ': ' .
1161 'More than 1 -m arguments were guessed: ' . @m;
1162 print STDERR __FILE__ . ' ' . __LINE__ . ': ' . 'Guessing stopped.';
1164 } elsif ( $nr_m_guessed == 1 ) {
1167 # no -m provided or guessed
1170 push @Command, $final_m if ( $final_m );
1172 push(@Command, @filespec) unless ( $file_args_included );
1175 # execute the `groff' command here with option `--run'
1176 if ( $do_run ) { # with --run
1177 print STDERR __FILE__ . ' ' . __LINE__ . ': ' . "@Command";
1178 my $cmd = join ' ', @Command;
1185 } # make_groff_line()
1188 ########################################################################
1190 ########################################################################
1194 usage: grog [option]... [--] [filespec]...
1196 "filespec" is either the name of an existing, readable file or "-" for
1197 standard input. If no `filespec' is specified, standard input is
1198 assumed automatically. All arguments after a `--' are regarded as file
1199 names, even if they start with a `-' character.
1201 `option' is either a `groff' option or one of these:
1203 -h|--help print this uasge message and exit
1204 -v|--version print version information and exit
1206 -C compatibility mode
1207 --ligatures include options `-P-y -PU' for internal font, which
1208 preserverses the ligatures like `fi'
1209 --run run the checked-out groff command
1210 --warnings display more warnings to standard error
1212 All other options should be `groff' 1-character options. These are then
1213 appended to the generated `groff' command line. The `-m' options will
1214 be checked by `grog'.
1221 ########################################################################
1223 ########################################################################
1227 print "Perl version of GNU $Prog " .
1228 "in groff version " . $at_at{'GROFF_VERSION'};
1234 ########################################################################