http://www.jwz.org/xscreensaver/xscreensaver-5.07.tar.gz
[xscreensaver] / hacks / munge-ad.pl
1 #!/usr/bin/perl -w
2 # Copyright © 2008 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 # This updates driver/XScreenSaver.ad.in with the current list of savers.
13 #
14 # Created:  3-Aug-2008.
15
16 require 5;
17 use diagnostics;
18 use strict;
19
20 my $progname = $0; $progname =~ s@.*/@@g;
21 my $version = q{ $Revision: 1.2 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/;
22
23 my $verbose = 0;
24
25 # These are marked as disabled by default in the .ad file.
26 #
27 my %disable = ( 
28    'abstractile' => 1,
29    'antinspect' => 1,
30    'antmaze' => 1,
31    'ant' => 1,
32    'carousel' => 1,
33    'critical' => 1,
34    'demon' => 1,
35    'dnalogo' => 1,
36    'glblur' => 1,
37    'glforestfire' => 1,
38    'glslideshow' => 1,
39    'hyperball' => 1,
40    'juggle' => 1,
41    'laser' => 1,
42    'lcdscrub' => 1,
43    'lightning' => 1,
44    'lisa' => 1,
45    'lissie' => 1,
46    'lmorph' => 1,
47    'loop' => 1,
48    'rotor' => 1,
49    'sballs' => 1,
50    'sierpinski' => 1,
51    'sphere' => 1,
52    'spiral' => 1,
53    'thornbird' => 1,
54    'vidwhacker' => 1,
55    'vines' => 1,
56    'webcollage' => 1,
57    'worm' => 1,
58   );
59
60
61 sub munge_ad($) {
62   my ($file) = @_;
63   my $body = '';
64   local *IN;
65   open (IN, "<$file") || error ("$file: $!");
66   while (<IN>) { $body .= $_; }
67   close IN;
68   my $obody = $body;
69
70   my ($top, $mid, $bot) = ($body =~ m/^(.*?\n)(\*hacks\..*?\n)(\n.*)$/s);
71
72   my $mid2 = '';
73
74   my %hacks;
75
76   # Update the "*hacks.foo.name" section of the file based on the contents
77   # of config/*.xml.
78   #
79   my $dir = $file;
80   $dir =~ s@/[^/]*$@@s;
81   my @counts = (0,0,0,0,0,0);
82   foreach my $xml (sort (glob ("$dir/../hacks/config/*.xml"))) {
83     my $b = '';
84     open (IN, "<$xml") || error ("$xml: $!");
85     while (<IN>) { $b .= $_; }
86     close IN;
87     my ($name) = ($b =~ m@<screensaver[^<>]*\b_label=\"([^<>\"]+)\">@s);
88     error ("$xml: no name") unless $name;
89
90     my $name2 = lc($name);
91     $name2 =~ s/^((x|gl)?[a-z])/\U$1/s;  # what prefs.c (make_hack_name) does
92
93     $xml =~ s@^.*/([^/]+)\.xml$@$1@s;
94     if ($name ne $name2) {
95       my $s = sprintf("*hacks.%s.name:", $xml);
96       $mid2 .= sprintf ("%-28s%s\n", $s, $name);
97       $counts[1]++;
98     }
99
100     # Grab the year.
101     my ($year) =
102       ($b =~ m/<_description>.*Written by.*?;\s+(19[6-9]\d|20\d\d)\b/si);
103     error ("no year in $xml.xml") unless $year;
104     $hacks{$xml} = $year;
105     $counts[0]++;
106   }
107
108   # Splice in new names.
109   $body = $top . $mid2 . $bot;
110
111
112   # Replace the "programs" section.
113   # Sort hacks by creation date, but put the OpenGL ones at the end.
114   #
115   my $segregate_p = 0;  # whether to put the GL hacks at the end.
116   my $xhacks = '';
117   my $ghacks = '';
118   foreach my $hack (sort { $hacks{$a} == $hacks{$b}
119                            ? $a cmp $b 
120                            : $hacks{$a} <=> $hacks{$b}}
121                     (keys(%hacks))) {
122     my $cmd = "$hack -root";
123     my $ts = (length($cmd) / 8) * 8;
124     while ($ts < 40) { $cmd .= "\t"; $ts += 8; }
125     next if ($hack eq 'ant' || $hack eq 'rdbomb');
126
127     my $glp;
128     my $glep = ($hack eq 'extrusion');
129     if (-f "$hack.c" || -f "$hack") { $glp = 0; }
130     elsif (-f "glx/$hack.c") { $glp = 1; }
131     else { error ("is $hack X or GL?"); }
132
133     my $dis = ($disable{$hack} ? '-' : '');
134     my $vis = ($glp
135                ? (($dis ? '' : $glep ? '@GLE_KLUDGE@' : '@GL_KLUDGE@') .
136                   ' GL: ')
137                : '');
138     $cmd = "$dis$vis\t\t\t\t$cmd    \\n\\\n";
139
140     if ($glp) {
141       ($segregate_p ? $ghacks : $xhacks) .= $cmd;
142       $counts[4+defined($disable{$hack})]++;
143     } else {
144       $xhacks .= $cmd;
145       $counts[2+defined($disable{$hack})]++;
146     }
147   }
148
149   # Splice in new programs list.
150   #
151   $mid2 = ($xhacks .
152            ($segregate_p ? "\t\t\t\t\t\t\t\t\t      \\\n" : "") .
153            $ghacks);
154   $mid2 =~ s@\\$@@s;
155   ($top, $mid, $bot) = 
156     ($body =~ m/^(.*?\n\*programs:\s+\\\n)(.*?\n)(\n.*)$/s);
157   error ("unparsable") unless $mid;
158   $body = $top . $mid2 . $bot;
159
160   print STDERR "$progname: Total: $counts[0]; " .
161     "X11: $counts[2]+$counts[3]; GL: $counts[4]+$counts[5]; " .
162       "Names: $counts[1]\n"
163         if ($verbose);
164
165   # Write file if changed.
166   #
167   if ($body ne $obody) {
168     local *OUT;
169     open (OUT, ">$file") || error ("$file: $!");
170     print OUT $body;
171     close OUT;
172     print STDERR "$progname: wrote $file\n";
173   } elsif ($verbose) {
174     print STDERR "$progname: $file unchanged\n";
175   }
176 }
177
178
179 sub error($) {
180   my ($err) = @_;
181   print STDERR "$progname: $err\n";
182   exit 1;
183 }
184
185 sub usage() {
186   print STDERR "usage: $progname [--verbose] ad-file\n";
187   exit 1;
188 }
189
190 sub main() {
191   my $file;
192   while ($#ARGV >= 0) {
193     $_ = shift @ARGV;
194     if (m/^--?verbose$/) { $verbose++; }
195     elsif (m/^-v+$/) { $verbose += length($_)-1; }
196     elsif (m/^-./) { usage; }
197     elsif (!$file) { $file = $_; }
198     else { usage; }
199   }
200
201   usage unless ($file);
202   munge_ad ($file);
203 }
204
205 main();
206 exit 0;