From http://www.jwz.org/xscreensaver/xscreensaver-5.30.tar.gz
[xscreensaver] / hacks / xml2man.pl
1 #!/usr/bin/perl -w
2 # Copyright © 2002-2014 Jamie Zawinski <jwz@jwz.org>
3 #
4 # Permission to use, copy, modify, distribute, and sell this software and its
5 # documentation for any purpose is hereby granted without fee, provided that
6 # the above copyright notice appear in all copies and that both that
7 # copyright notice and this permission notice appear in supporting
8 # documentation.  No representations are made about the suitability of this
9 # software for any purpose.  It is provided "as is" without express or 
10 # implied warranty.
11 #
12 # Created: 30-May-2002.
13 #
14 # This creates man pages from the XML program descriptions in 
15 # xscreensaver/hacks/config/.
16 #
17 # They aren't necessarily the most accurate or well-written man pages,
18 # but at least they exist.
19
20 require 5;
21 use diagnostics;
22 use strict;
23
24 use Text::Wrap;
25
26 my $progname = $0; $progname =~ s@.*/@@g;
27 my ($version) = ('$Revision: 1.6 $' =~ m/\s(\d[.\d]+)\s/s);
28
29 my $verbose = 0;
30
31 my $default_args = ("[\\-display \\fIhost:display.screen\\fP]\n" .
32                     "[\\-visual \\fIvisual\\fP]\n" .
33                     "[\\-window]\n" .
34                     "[\\-root]\n");
35 my $default_options = (".TP 8\n" .
36                        ".B \\-visual \\fIvisual\\fP\n" .
37                        "Specify which visual to use.  Legal values " .
38                        "are the name of a visual class,\n" .
39                        "or the id number (decimal or hex) of a " .
40                        "specific visual.\n" .
41                        ".TP 8\n" .
42                        ".B \\-window\n" .
43                        "Draw on a newly-created window.  " .
44                        "This is the default.\n" .
45                        ".TP 8\n" .
46                        ".B \\-root\n" .
47                        "Draw on the root window.\n");
48
49 my $man_suffix = (".SH ENVIRONMENT\n" .
50                   ".PP\n" .
51                   ".TP 8\n" .
52                   ".B DISPLAY\n" .
53                   "to get the default host and display number.\n" .
54                   ".TP 8\n" .
55                   ".B XENVIRONMENT\n" .
56                   "to get the name of a resource file that overrides " .
57                   "the global resources\n" .
58                   "stored in the RESOURCE_MANAGER property.\n" .
59                   ".SH SEE ALSO\n" .
60                   ".BR X (1),\n" .
61                   ".BR xscreensaver (1)\n" .
62                   ".SH COPYRIGHT\n" .
63                   "Copyright \\(co %YEAR% by %AUTHOR%.  " .
64                   "Permission to use, copy, modify, \n" .
65                   "distribute, and sell this software and its " .
66                   "documentation for any purpose is \n" .
67                   "hereby granted without fee, provided that " .
68                   "the above copyright notice appear \n" .
69                   "in all copies and that both that copyright " .
70                   "notice and this permission notice\n" .
71                   "appear in supporting documentation.  No " .
72                   "representations are made about the \n" .
73                   "suitability of this software for any purpose.  " .
74                   "It is provided \"as is\" without\n" .
75                   "express or implied warranty.\n" .
76                   ".SH AUTHOR\n" .
77                   "%AUTHOR%.\n");
78
79 sub xml2man($) {
80   my ($exe) = @_;
81   $exe =~ s/\.xml$//s;
82   my $cfgdir = (-d "config" ? "config" : "../config");
83   my $xml = "$cfgdir/$exe.xml";
84   my $man = "$exe.man";
85
86   error ("$exe does not exist") if (! -f $exe);
87   error ("$xml does not exist") if (! -f $xml);
88   error ("$man already exists") if (-f $man);
89
90   local *IN;
91   open (IN, "<$xml") || error ("$xml: $!");
92   my $xmltxt = "";
93   while (<IN>) { $xmltxt .= $_; }
94   close IN;
95
96   my $args = "";
97   my $body = "";
98   my $desc;
99
100   $xmltxt =~ s/\s+/ /gs;
101   $xmltxt =~ s/<!--.*?-->//g;
102   $xmltxt =~ s@(<[^/])@\n$1@gs;
103
104   foreach (split ('\n', $xmltxt)) {
105     next if m/^$/;
106     next if m/^<\?xml\b/;
107     next if m/^<screensaver\b/;
108     next if m/^<command\b/;
109     next if m/^<[hv]group\b/;
110     next if m/^<select\b/;
111
112     my ($x,$arg) = m@\barg(|-unset|-set)=\"([^\"]+)\"@;
113     my ($label)  = m@\b_?label=\"([^\"]+)\"@;
114     my ($low)    = m@\blow=\"([^\"]+)\"@;
115     my ($hi)     = m@\bhigh=\"([^\"]+)\"@;
116     my ($def)    = m@\bdefault=\"([^\"]+)\"@;
117
118     $arg =~ s@\s*\%\s*@ \\fInumber\\fP@g if ($arg);
119                          
120     my $carg = $arg;
121     my $boolp = m/^<boolean/;
122     my $novalsp = 0;
123
124     if ($arg && $arg =~ m/^-no(-.*)/) {
125       $arg = "$1 | \\$arg";
126     } elsif ($boolp && $arg) {
127       $arg = "$arg | \\-no$arg";
128     }
129
130     if ($carg && $carg =~ m/colors/) {
131       $hi = $low = undef;
132     }
133
134     if (!$carg) {
135     } elsif ($carg eq '-move' || $carg eq '-no-move' ||
136              $carg eq '-wander' || $carg eq '-no-wander') {
137       $label = "Whether the object should wander around the screen.";
138     } elsif ($boolp && ($carg eq '-spin' || $carg eq '-no-spin')) {
139       $label = "Whether the object should spin.";
140     } elsif ($carg eq '-spin X') {
141       $carg = '-spin \fI[XYZ]\fP';
142       $arg = $carg;
143       $label = "Around which axes should the object spin?";
144     } elsif ($carg eq '-fps' || $carg eq '-no-fps') {
145       $label = "Whether to show a frames-per-second display " .
146                "at the bottom of the screen.";
147     } elsif ($carg eq '-wireframe' || $carg eq '-wire') {
148       $label = "Render in wireframe instead of solid.";
149     } elsif ($carg =~ m/^-delay/ && $hi && $hi >= 10000) {
150       $label = "Per-frame delay, in microseconds.";
151       $def = sprintf ("%d (%0.2f seconds)", $def, ($def/1000000.0));
152       $low = $hi = undef;
153     } elsif ($carg eq '-speed \fInumber\fP') {
154       $label = "Animation speed.  2.0 means twice as fast, " .
155                "0.5 means half as fast.";
156       $novalsp = 1;
157     } elsif ($boolp) {
158       $label .= ".  Boolean.";
159     } elsif ($label) {
160       $label .= ".";
161     }
162
163     if (m/^<(number|boolean|option)/) {
164
165       next if (!$arg && m/<option/);
166       if (!$label) {
167         print STDERR "$progname: ERROR: no label: $_\n";
168         $label = "???";
169       }
170
171       $args .= "[\\$carg]\n";
172
173       if (! $novalsp) {
174         $label .= "  $low - $hi." if (defined($low) && defined($hi));
175         $label .= "  Default: $def." if (defined ($def));
176       }
177       $label = wrap ("", "", $label);
178
179       $body .= ".TP 8\n.B \\$arg\n$label";
180       $body .= "\n";
181
182     } elsif (m@^<_description>\s*(.*)\s*</_description>@) {
183       $desc = $1;
184     } elsif (m@^<xscreensaver-updater@) {
185     } else {
186       print STDERR "$progname: ERROR: UNKNOWN: $_\n";
187     }
188   }
189
190   $desc = "Something pretty." unless $desc;
191
192   my $author = undef;
193   if ($desc =~ m@^(.*?)\s*(Written by|By) ([^.]+\.?\s*)$@s) {
194     $desc = $1;
195     $author = $3;
196     $author =~ s/\s*[.]\s*$//;
197   }
198
199   if (!$author) {
200     print STDERR "$progname: $exe: WARNING: unknown author\n";
201     $author = "UNKNOWN";
202   }
203
204   $desc =~ s@http://en\.wikipedia\.org/[^\s]+@@gs;
205
206   $desc = wrap ("", "", $desc);
207
208   $body = (".TH XScreenSaver 1 \"\" \"X Version 11\"\n" .
209            ".SH NAME\n" .
210            "$exe - screen saver.\n" .
211            ".SH SYNOPSIS\n" .
212            ".B $exe\n" .
213            $default_args .
214            $args .
215            ".SH DESCRIPTION\n" .
216            $desc . "\n" .
217            ".SH OPTIONS\n" .
218            $default_options .
219            $body .
220            $man_suffix);
221
222   my $year = $1 if ($author =~ s/; (\d{4})$//s);
223   $year = (localtime)[5] + 1900 unless $year;
224
225   $body =~ s/%AUTHOR%/$author/g;
226   $body =~ s/%YEAR%/$year/g;
227
228 #print $body; exit 0;
229
230   local *OUT;
231   open (OUT, ">$man") || error ("$man: $!");
232   print OUT $body || error ("$man: $!");
233   close OUT || error ("$man: $!");
234   print STDERR "$progname: wrote $man\n";
235 }
236
237
238 sub error($) {
239   my ($err) = @_;
240   print STDERR "$progname: $err\n";
241   exit 1;
242 }
243
244 sub usage() {
245   print STDERR "usage: $progname [--verbose] programs...\n";
246   exit 1;
247 }
248
249 sub main() {
250   my @progs = ();
251   while ($_ = $ARGV[0]) {
252     shift @ARGV;
253     if ($_ eq "--verbose") { $verbose++; }
254     elsif (m/^-v+$/) { $verbose += length($_)-1; }
255     elsif (m/^-./) { usage; }
256     else { push @progs, $_; }
257   }
258
259   usage() if ($#progs < 0);
260
261   foreach (@progs) { xml2man($_); }
262 }
263
264 main();
265 exit 0;