1*04ac863bSchristos#! /usr/bin/perl 2*04ac863bSchristos# grog -- guess options for groff command 3*04ac863bSchristos# Inspired by doctype script in Kernighan & Pike, Unix Programming 4*04ac863bSchristos# Environment, pp 306-8. 5*04ac863bSchristos 6*04ac863bSchristos$prog = $0; 7*04ac863bSchristos$prog =~ s@.*/@@; 8*04ac863bSchristos 9*04ac863bSchristos$sp = "[\\s\\n]"; 10*04ac863bSchristos 11*04ac863bSchristospush(@command, "groff"); 12*04ac863bSchristos 13*04ac863bSchristoswhile ($ARGV[0] =~ /^-./) { 14*04ac863bSchristos $arg = shift(@ARGV); 15*04ac863bSchristos $sp = "" if $arg eq "-C"; 16*04ac863bSchristos &usage(0) if $arg eq "-v" || $arg eq "--version"; 17*04ac863bSchristos &help() if $arg eq "--help"; 18*04ac863bSchristos last if $arg eq "--"; 19*04ac863bSchristos push(@command, $arg); 20*04ac863bSchristos} 21*04ac863bSchristos 22*04ac863bSchristos@ARGV = ('-') unless @ARGV; 23*04ac863bSchristosforeach $arg (@ARGV) { 24*04ac863bSchristos &process($arg, 0); 25*04ac863bSchristos} 26*04ac863bSchristos 27*04ac863bSchristossub process { 28*04ac863bSchristos local($filename, $level) = @_; 29*04ac863bSchristos local(*FILE); 30*04ac863bSchristos 31*04ac863bSchristos if (!open(FILE, $filename eq "-" ? $filename : "< $filename")) { 32*04ac863bSchristos print STDERR "$prog: can't open \`$filename': $!\n"; 33*04ac863bSchristos exit 1 unless $level; 34*04ac863bSchristos return; 35*04ac863bSchristos } 36*04ac863bSchristos while (<FILE>) { 37*04ac863bSchristos if (/^\.TS$sp/) { 38*04ac863bSchristos $_ = <FILE>; 39*04ac863bSchristos if (!/^\./) { 40*04ac863bSchristos $tbl++; 41*04ac863bSchristos $soelim++ if $level; 42*04ac863bSchristos } 43*04ac863bSchristos } 44*04ac863bSchristos elsif (/^\.EQ$sp/) { 45*04ac863bSchristos $_ = <FILE>; 46*04ac863bSchristos if (!/^\./ || /^\.[0-9]/) { 47*04ac863bSchristos $eqn++; 48*04ac863bSchristos $soelim++ if $level; 49*04ac863bSchristos } 50*04ac863bSchristos } 51*04ac863bSchristos elsif (/^\.GS$sp/) { 52*04ac863bSchristos $_ = <FILE>; 53*04ac863bSchristos if (!/^\./) { 54*04ac863bSchristos $grn++; 55*04ac863bSchristos $soelim++ if $level; 56*04ac863bSchristos } 57*04ac863bSchristos } 58*04ac863bSchristos elsif (/^\.G1$sp/) { 59*04ac863bSchristos $_ = <FILE>; 60*04ac863bSchristos if (!/^\./) { 61*04ac863bSchristos $grap++; 62*04ac863bSchristos $pic++; 63*04ac863bSchristos $soelim++ if $level; 64*04ac863bSchristos } 65*04ac863bSchristos } 66*04ac863bSchristos elsif (/^\.PS$sp([ 0-9.<].*)?$/) { 67*04ac863bSchristos if (/^\.PS\s*<\s*(\S+)/) { 68*04ac863bSchristos $pic++; 69*04ac863bSchristos $soelim++ if $level; 70*04ac863bSchristos &process($1, $level); 71*04ac863bSchristos } 72*04ac863bSchristos else { 73*04ac863bSchristos $_ = <FILE>; 74*04ac863bSchristos if (!/^\./ || /^\.ps/) { 75*04ac863bSchristos $pic++; 76*04ac863bSchristos $soelim++ if $level; 77*04ac863bSchristos } 78*04ac863bSchristos } 79*04ac863bSchristos } 80*04ac863bSchristos elsif (/^\.R1$sp/) { 81*04ac863bSchristos $refer++; 82*04ac863bSchristos $soelim++ if $level; 83*04ac863bSchristos } 84*04ac863bSchristos elsif (/^\.\[/) { 85*04ac863bSchristos $refer_open++; 86*04ac863bSchristos $soelim++ if $level; 87*04ac863bSchristos } 88*04ac863bSchristos elsif (/^\.\]/) { 89*04ac863bSchristos $refer_close++; 90*04ac863bSchristos $soelim++ if $level; 91*04ac863bSchristos } 92*04ac863bSchristos elsif (/^\.[PLI]P$sp/) { 93*04ac863bSchristos $PP++; 94*04ac863bSchristos } 95*04ac863bSchristos elsif (/^\.P$/) { 96*04ac863bSchristos $P++; 97*04ac863bSchristos } 98*04ac863bSchristos elsif (/^\.(PH|SA)$sp/) { 99*04ac863bSchristos $mm++; 100*04ac863bSchristos } 101*04ac863bSchristos elsif (/^\.TH$sp/) { 102*04ac863bSchristos $TH++; 103*04ac863bSchristos } 104*04ac863bSchristos elsif (/^\.SH$sp/) { 105*04ac863bSchristos $SH++; 106*04ac863bSchristos } 107*04ac863bSchristos elsif (/^\.([pnil]p|sh)$sp/) { 108*04ac863bSchristos $me++; 109*04ac863bSchristos } 110*04ac863bSchristos elsif (/^\.Dd$sp/) { 111*04ac863bSchristos $mdoc++; 112*04ac863bSchristos } 113*04ac863bSchristos elsif (/^\.(Tp|Dp|De|Cx|Cl)$sp/) { 114*04ac863bSchristos $mdoc_old = 1; 115*04ac863bSchristos } 116*04ac863bSchristos # In the old version of -mdoc `Oo' is a toggle, in the new it's 117*04ac863bSchristos # closed by `Oc'. 118*04ac863bSchristos elsif (/^\.Oo$sp/) { 119*04ac863bSchristos $Oo++; 120*04ac863bSchristos s/^\.Oo/\. /; 121*04ac863bSchristos redo; 122*04ac863bSchristos } 123*04ac863bSchristos # The test for `Oo' and `Oc' not starting a line (as allowed by the 124*04ac863bSchristos # new implementation of -mdoc) is not complete; it assumes that 125*04ac863bSchristos # macro arguments are well behaved, i.e., "" is used within "..." to 126*04ac863bSchristos # indicate a doublequote as a string element, and weird features 127*04ac863bSchristos # like `.foo a"b' are not used. 128*04ac863bSchristos elsif (/^\..* Oo( |$)/) { 129*04ac863bSchristos s/\\\".*//; 130*04ac863bSchristos s/\"[^\"]*\"//g; 131*04ac863bSchristos s/\".*//; 132*04ac863bSchristos if (s/ Oo( |$)/ /) { 133*04ac863bSchristos $Oo++; 134*04ac863bSchristos } 135*04ac863bSchristos redo; 136*04ac863bSchristos } 137*04ac863bSchristos elsif (/^\.Oc$sp/) { 138*04ac863bSchristos $Oo--; 139*04ac863bSchristos s/^\.Oc/\. /; 140*04ac863bSchristos redo; 141*04ac863bSchristos } 142*04ac863bSchristos elsif (/^\..* Oc( |$)/) { 143*04ac863bSchristos s/\\\".*//; 144*04ac863bSchristos s/\"[^\"]*\"//g; 145*04ac863bSchristos s/\".*//; 146*04ac863bSchristos if (s/ Oc( |$)/ /) { 147*04ac863bSchristos $Oo--; 148*04ac863bSchristos } 149*04ac863bSchristos redo; 150*04ac863bSchristos } 151*04ac863bSchristos elsif (/^\.(PRINTSTYLE|START)$sp/) { 152*04ac863bSchristos $mom++; 153*04ac863bSchristos } 154*04ac863bSchristos if (/^\.so$sp/) { 155*04ac863bSchristos chop; 156*04ac863bSchristos s/^.so *//; 157*04ac863bSchristos s/\\\".*//; 158*04ac863bSchristos s/ .*$//; 159*04ac863bSchristos &process($_, $level + 1) unless /\\/ || $_ eq ""; 160*04ac863bSchristos } 161*04ac863bSchristos } 162*04ac863bSchristos close(FILE); 163*04ac863bSchristos} 164*04ac863bSchristos 165*04ac863bSchristossub usage { 166*04ac863bSchristos local($exit_status) = $_; 167*04ac863bSchristos print "GNU grog (groff) version @VERSION@\n"; 168*04ac863bSchristos exit $exit_status; 169*04ac863bSchristos} 170*04ac863bSchristos 171*04ac863bSchristossub help { 172*04ac863bSchristos print "usage: grog [ option ...] [files...]\n"; 173*04ac863bSchristos exit 0; 174*04ac863bSchristos} 175*04ac863bSchristos 176*04ac863bSchristos$refer ||= $refer_open && $refer_close; 177*04ac863bSchristos 178*04ac863bSchristosif ($pic || $tbl || $eqn || $grn || $grap || $refer) { 179*04ac863bSchristos $s = "-"; 180*04ac863bSchristos $s .= "s" if $soelim; 181*04ac863bSchristos $s .= "R" if $refer; 182*04ac863bSchristos # grap must be run before pic 183*04ac863bSchristos $s .= "G" if $grap; 184*04ac863bSchristos $s .= "p" if $pic; 185*04ac863bSchristos $s .= "g" if $grn; 186*04ac863bSchristos $s .= "t" if $tbl; 187*04ac863bSchristos $s .= "e" if $eqn; 188*04ac863bSchristos push(@command, $s); 189*04ac863bSchristos} 190*04ac863bSchristos 191*04ac863bSchristosif ($me > 0) { 192*04ac863bSchristos push(@command, "-me"); 193*04ac863bSchristos} 194*04ac863bSchristoselsif ($SH > 0 && $TH > 0) { 195*04ac863bSchristos push(@command, "-man"); 196*04ac863bSchristos} 197*04ac863bSchristoselse ($mom > 0) { 198*04ac863bSchristos push(@command, "-mom"); 199*04ac863bSchristos} 200*04ac863bSchristoselsif ($PP > 0) { 201*04ac863bSchristos push(@command, "-ms"); 202*04ac863bSchristos} 203*04ac863bSchristoselsif ($P > 0 || $mm > 0) { 204*04ac863bSchristos push(@command, "-mm"); 205*04ac863bSchristos} 206*04ac863bSchristoselsif ($mdoc > 0) { 207*04ac863bSchristos push(@command, ($mdoc_old || $Oo > 0) ? "-mdoc-old" : "-mdoc"); 208*04ac863bSchristos} 209*04ac863bSchristos 210*04ac863bSchristospush(@command, "--") if @ARGV && $ARGV[0] =~ /^-./; 211*04ac863bSchristos 212*04ac863bSchristospush(@command, @ARGV); 213*04ac863bSchristos 214*04ac863bSchristos# We could implement an option to execute the command here. 215*04ac863bSchristos 216*04ac863bSchristosforeach (@command) { 217*04ac863bSchristos next unless /[\$\\\"\';&()|<> \t\n]/; 218*04ac863bSchristos s/\'/\'\\\'\'/; 219*04ac863bSchristos $_ = "'" . $_ . "'"; 220*04ac863bSchristos} 221*04ac863bSchristos 222*04ac863bSchristosprint join(' ', @command), "\n"; 223