#! /usr/bin/perl # grog -- guess options for groff command # Inspired by doctype script in Kernighan & Pike, Unix Programming # Environment, pp 306-8. $prog = $0; $prog =~ s@.*/@@; $sp = "[\\s\\n]"; push(@command, "groff"); while ($ARGV[0] =~ /^-./) { $arg = shift(@ARGV); $sp = "" if $arg eq "-C"; &usage(0) if $arg eq "-v" || $arg eq "--version"; &help() if $arg eq "--help"; last if $arg eq "--"; push(@command, $arg); } @ARGV = ('-') unless @ARGV; foreach $arg (@ARGV) { &process($arg, 0); } sub process { local($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 () { if (/^\.TS$sp/) { $_ = ; if (!/^\./) { $tbl++; $soelim++ if $level; } } elsif (/^\.EQ$sp/) { $_ = ; if (!/^\./ || /^\.[0-9]/) { $eqn++; $soelim++ if $level; } } elsif (/^\.GS$sp/) { $_ = ; if (!/^\./) { $grn++; $soelim++ if $level; } } elsif (/^\.G1$sp/) { $_ = ; if (!/^\./) { $grap++; $pic++; $soelim++ if $level; } } elsif (/^\.PS$sp([ 0-9.<].*)?$/) { if (/^\.PS\s*<\s*(\S+)/) { $pic++; $soelim++ if $level; &process($1, $level); } else { $_ = ; if (!/^\./ || /^\.ps/) { $pic++; $soelim++ if $level; } } } elsif (/^\.R1$sp/) { $refer++; $soelim++ if $level; } elsif (/^\.\[/) { $refer_open++; $soelim++ if $level; } elsif (/^\.\]/) { $refer_close++; $soelim++ if $level; } elsif (/^\.[PLI]P$sp/) { $PP++; } elsif (/^\.P$/) { $P++; } elsif (/^\.(PH|SA)$sp/) { $mm++; } elsif (/^\.TH$sp/) { $TH++; } elsif (/^\.SH$sp/) { $SH++; } elsif (/^\.([pnil]p|sh)$sp/) { $me++; } elsif (/^\.Dd$sp/) { $mdoc++; } elsif (/^\.(Tp|Dp|De|Cx|Cl)$sp/) { $mdoc_old = 1; } # In the old version of -mdoc `Oo' is a toggle, in the new it's # closed by `Oc'. elsif (/^\.Oo$sp/) { $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( |$)/ /) { $Oo++; } redo; } elsif (/^\.Oc$sp/) { $Oo--; s/^\.Oc/\. /; redo; } elsif (/^\..* Oc( |$)/) { s/\\\".*//; s/\"[^\"]*\"//g; s/\".*//; if (s/ Oc( |$)/ /) { $Oo--; } redo; } elsif (/^\.(PRINTSTYLE|START)$sp/) { $mom++; } if (/^\.so$sp/) { chop; s/^.so *//; s/\\\".*//; s/ .*$//; &process($_, $level + 1) unless /\\/ || $_ eq ""; } } close(FILE); } sub usage { local($exit_status) = $_; print "GNU grog (groff) version @VERSION@\n"; exit $exit_status; } sub help { print "usage: grog [ option ...] [files...]\n"; exit 0; } $refer ||= $refer_open && $refer_close; if ($pic || $tbl || $eqn || $grn || $grap || $refer) { $s = "-"; $s .= "s" if $soelim; $s .= "R" if $refer; # grap must be run before pic $s .= "G" if $grap; $s .= "p" if $pic; $s .= "g" if $grn; $s .= "t" if $tbl; $s .= "e" if $eqn; push(@command, $s); } if ($me > 0) { push(@command, "-me"); } elsif ($SH > 0 && $TH > 0) { push(@command, "-man"); } else ($mom > 0) { push(@command, "-mom"); } elsif ($PP > 0) { push(@command, "-ms"); } elsif ($P > 0 || $mm > 0) { push(@command, "-mm"); } elsif ($mdoc > 0) { push(@command, ($mdoc_old || $Oo > 0) ? "-mdoc-old" : "-mdoc"); } push(@command, "--") if @ARGV && $ARGV[0] =~ /^-./; push(@command, @ARGV); # We could implement an option to execute the command here. foreach (@command) { next unless /[\$\\\"\';&()|<> \t\n]/; s/\'/\'\\\'\'/; $_ = "'" . $_ . "'"; } print join(' ', @command), "\n";