xref: /netbsd/external/gpl2/groff/dist/src/roff/grog/grog.pl (revision 04ac863b)
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