PennMUSH Community

root/1.8.3/trunk/utils/update.pl

Revision 349, 9.9 kB (checked in by pennmush, 2 years ago)

PennMUSH 1.7.5p7 Archival

  • Property svn:executable set to *
Line 
1 #!/usr/local/bin/perl
2 #
3 # You make have to change the path to perl above, unless you call this
4 # script with 'make update'
5 #
6 # update.pl - integrate previous options.h settings with new options.h.dist
7 #             results appear in options.h
8 #
9 # Usage: update.pl old-file new-file
10 #  e.g.: update.pl options.h options.h.dist
11 #
12 # 'make update' calls this.
13 #
14 # Here's how it works.
15 # 1. We make a backup of your old-file to old-file.bak
16 # 2. We read all the #def's in the old-file, and their
17 #  associated comments. Associated comments means comments
18 #  on the same line, after the define, or comments on lines
19 #  preceding the define. We store the names of all the defines,
20 #  their comments, and whether they're defined or not.
21 # 3. We check to see if there's are enviroment variables named DEFINE
22 #  or UNDEFINE. If so we parse them. DEFINE may contain NAMEs or
23 #  NAME=value pairs. UNDEFINE should contain only NAMEs.
24 #  We consider these as if they were present in old-file.
25 #  These override old-file.
26 # 4. We read in the new-file. If we find a define
27 #  that wasn't in the old-file, we show the user the comment
28 #  and ask them how they want it set. Every time we write out
29 #  a define, we delete it from the list of defines from old-file
30 # 5. Finally, if there's anything left from old-file that's not in
31 #  new-file, we ask if the user would like to retain each one.
32 #  Presumably users want to retain their custom defines, but don't
33 #  want to retain obsoleted defines. Retained defines appear at
34 #  the end of the file.
35
36 die "Usage: update.pl old-file new-file\n" unless $#ARGV == 1;
37
38 $old = $ARGV[0];
39 $bak = $old . ".bak";
40 $new = $ARGV[1];
41
42
43 # Part 1 - back up the old file (inefficient but reliable method)
44 if (-r $old) {
45     print "*** Backing up $old to $bak...\n";
46     die "update.pl: Unable to open $old\n" unless open(OLD,"$old");
47     die "update.pl: Unable to open $bak\n" unless open(BAK,">$bak");
48     print BAK <OLD>;
49     close(BAK);
50     close(OLD);
51 }
52
53 # Part 2 - read the settings from the old file and store them
54 if (-r $old) {
55    print "*** Reading your settings from $old...\n";
56     die "update.pl: Unable to open $old\n" unless open(OLD,"$old");
57     while (<OLD>) {
58         # There are a few possibilities for what we could have:
59         # an #ifdef, #ifndef, #else, #endif, #define, #undef,
60         # commented #define, comment text, etc. We only care
61         # about the settings of define/undefs
62         s#/\*\s*\*/##;
63         s#[ \t]+([\r\n]*)$#$1#;
64         if ( /^#define\s+([A-Z0-9_-]+).*\\$/ ) {
65         # A define with a continuation, we need the next line
66         chop($next = <OLD>);
67         $defs{$1} = $next;
68         $comment{$1} = $comment;
69         } elsif ( m!^#define\s+([A-Z0-9_-]+)\s+(.+)\s+(/\*.*\*/)!
70              ) {
71         # A define with a value and a comment
72         $name = $1;
73         $comment{$name} = $3;
74         $defs{$name} = $2;
75         undef $comment;
76         } elsif ( m!^#define\s+([A-Z0-9_-]+)\s+(.+)!
77              ) {
78         # A define with a value
79         $defs{$1} = $2;
80         $comment{$1} = $comment;
81         } elsif ( /^#undef\s+([A-Z0-9_-]+)/
82              ) {
83         # an undef
84         $defs{$1} = 'undef';
85         $comment{$1} = $comment;
86         } elsif ( m!^/\*\s*#define\s+([A-Z0-9_-]+)\s+(.+)\s+(/\*.*\*/)!
87              ) {
88         # A commented define with a value and a comment
89         $name = $1;
90         $comment{$name} = $3;
91         $cvaldef{$name}++;
92         $defs{$name} = $2;
93         undef $comment;
94         } elsif ( /^(\/\*)*\s*#define\s+([A-Z0-9-][A-Z0-9_-]+)/
95              ) {
96         # a define or commented define
97         $defs{$2} = ($1 eq "/*") ? 'undef' : 'define';
98         $comment{$2} = $comment;
99         } else {
100         if (m#^\s*/\*#) {
101             # Start of a comment
102             $incomment = 1;
103             undef $comment;
104         }
105         if ($incomment) {
106             $comment = $comment . $_;
107             if (m#\*/\s+$#) {
108             # End of a comment
109             $incomment = 0;
110             }
111         }
112         }
113     }
114     close(OLD);
115 }
116 undef $comment; $incomment = 0;
117
118
119 # Part 3 - Check to see if we have environment variable SETTINGS and
120 #          use those settings as if they were in the old file.
121 if ($settings = $ENV{'DEFINE'}) {
122   print "\n*** Found a DEFINE environment variable - applying settings...\n";
123   @pairs = split ' ', $settings;
124   foreach (@pairs) {
125     if (($d,$v) = /(.+)=(.+)/) {
126       $defs{$d} = $v;
127     } else {
128       $defs{$_} = 'define';
129     }
130   }
131 }
132 if ($settings = $ENV{'UNDEFINE'}) {
133   print "\n*** Found an UNDEFINE environment variable - applying settings...\n";
134   @pairs = split ' ', $settings;
135   foreach (@pairs) {
136       $defs{$_} = 'undef';
137   }
138 }
139
140 # Part 4 - read in the new file, modifying its definition lines to
141 #          match the old file. If we come across a definition that
142 #          isn't in the old file, ask the user about it.
143 print "*** Updating $old from $new...\n";
144 die "update.pl: Unable to open $old\n" unless open(OLD,">$old");
145 die "update.pl: Unable to open $new\n" unless open(NEW,"$new");
146 $_ = <NEW>;
147 while ($next = <NEW>) {
148     # Just like before, but we need to keep track of
149     # comments in the file so that we can describe options
150     s#[ \t]+([\r\n]*)$#$1#;
151     if ( /^#define\s+([A-Z0-9_-]+).*\\$/
152     ) {
153     # A define with a continuation, we need the next line
154     print OLD "#define $1 \\\n";
155     &ask_value($1,$next) if (!defined($defs{$1}));
156     print OLD $defs{$1};
157     delete $defs{$1};
158     $next = <NEW>;
159     } elsif ( /^#define\s+([A-Z0-9-][A-Z0-9_-]+)\s+\/\*\s*\*\//) {
160     # a define followed by /* */
161     print OLD defined($defs{$1}) ? &def($1)
162                                  : &def(&ask_simple($1,'define'));
163     } elsif ( m!^(/\*\s*)?#define\s+([A-Z0-9_-]+)\s+(.+)\s+(/\*.*\*/)!) {
164     # A define with a value and a comment
165         $maybeundef = $1;
166     $maybecomment = $4; $name = $2;
167     $olddef = $def = $3;
168     $comment = $maybecomment if ($maybecomment =~ /\w/);
169     $def = "undef" if $maybeundef =~ /./;
170     print OLD defined($defs{$name})
171         ? &def($name,$comment) : &def(&ask_value($name,$def),$maybecomment,$def eq "undef" ? $olddef : $def);
172     } elsif ( m!^#define\s+([A-Z0-9_-]+)\s+(.+)!) {
173     # A define with a value
174     print OLD defined($defs{$1}) ? &def($1) : &def(&ask_value($1,$2));
175     } elsif ( /^#undef\s+([A-Z0-9_-]+)/
176          ) {
177     print OLD defined($defs{$1}) ? &def($1)
178                                  : &def(&ask_simple($1,'undef'));
179     } elsif ( /^(\/\*)*\s*#define\s+([A-Z0-9-][A-Z0-9_-]+)/
180          ) {
181     # a define or commented define
182     print OLD defined($defs{$2}) ?
183         &def($2)
184         : &def(&ask_simple($2,($1 eq "/*" ? 'undef': 'define')));
185     } else {
186     if (m#^\s*/\*#) {
187         # Start of a comment
188         $incomment = 1;
189         undef $comment;
190     }
191     if ($incomment) {
192         $comment = $comment . $_;
193         if (m#\*/\s+$#) {
194         # End of a comment
195         $incomment = 0;
196         }
197     }
198     print OLD;
199     }
200     $_ = $next;
201 }
202 # At the end of that loop, $_ contains the last line of the
203 # file, which should be the #endif.
204 $final = $_;
205 close(NEW);
206
207 # Part 5 - if there are any definitions left from the old file,
208 #          offer to delete them (or not)
209 print "\n*** Checking for leftover defines from $old...\n";
210 foreach $d (keys %defs) {
211     print "\nI found: $d\n";
212     if ($defs{$d} eq 'undef') {
213     print "Currently undefined\n";
214     } elsif ($defs{$d} eq 'define') {
215     print "Currently defined\n";
216     } else {
217     print "Definition: $defs{$d}\n";
218     }
219     print $comment{$d};
220     print "\n";
221     print "If this is a define that you hacked in, you probably should retain it.\n";
222     print "If not, it's probably an obsolete define from an earlier patchlevel,\n";
223     print "and you need not retain it.\n";
224     print "Do you want to retain this in your $old file? [y] ";
225     $yn = <STDIN>;
226     if ($yn !~ /^[Nn]/) {
227     print "Retaining definition. It will appear at the end of $old.\n";
228         @retained = (@retained, $d);
229     print OLD $comment{$d};
230     print OLD &def($d);
231     print OLD "\n";
232     } else {
233     print "Deleting definition.\n";
234     @deleted = (@deleted, $d);
235     }
236 }
237
238 print OLD $final;
239
240 close(OLD);
241
242 print "\nSummary of changes:\n";
243 print "New options from $new: ",join(" ",@newoptions),"\n";
244 print "Old options retained: ",join(" ",@retained),"\n";
245 print "Old options deleted: ",join(" ",@deleted),"\n";
246 print "If this is wrong, you can recover $old from $bak.\n";
247 print "Done!\n";
248 exit 0;
249
250
251 #
252 # &def - Given a define name, return the appopriate C code
253 # to define/undefine it. And delete it.
254 # May also be given a comment as a second arg.
255 #
256 sub def {
257     # We should use my instead of local, but some folks have perl 4
258     local($d,$c,$oldval) = @_;
259     local($df) = $defs{$d};
260     delete $defs{$d};
261     $d =~ s/^\s+//;
262     $d =~ s/\s+$//;
263     $c =~ s/^\s+//;
264     $c =~ s/\s+$//;
265     $df =~ s/^\s+//;
266     $df =~ s/\s+$//;
267     if ($df eq 'undef') {
268       if (defined($oldval) and $oldval) {
269         $oldval =~ s/^\s+//;
270         $oldval =~ s/\s+$//;
271         return "/* #define $d\t$oldval /* */\n";
272       } else {
273         return "/* #define $d /* */\n";
274       }
275     }
276     return "#define $d /* */\n" if ($df eq 'define');
277     return "/* #define $d\t$df\t$c\n" if ($cvaldef{$d} and $c);
278     return "#define $d\t$df\t$c\n" if ($c);
279     return "#define $d\t$df\n";
280 }
281
282 #
283 # &ask_simple - Given a define name and default setting,
284 # show the comment in $comment,
285 # and ask the user if they want to define it or not
286 # Set $defs{$d} and return the name given
287 #
288 sub ask_simple {
289     local($d,$s) = @_;
290     local($yn);
291     print "\nNew option: $d\n";
292     print $comment;
293     $s = ($s eq 'define') ? 'y' : 'n';
294     while (1) {
295     print "Define this option? [$s] ";
296     $yn = <STDIN>;
297     $yn = $s if $yn =~ /^$/;
298     last if $yn =~ /^[YyNn]/;
299     }
300     $defs{$d} = ($yn =~ /^[Yy]/) ? 'define' : 'undef';
301     @newoptions = (@newoptions,$d);
302     return $d;
303 }
304    
305
306 #
307 # &ask_value - Just like ask_simple, but instead of a yes/no,
308 # we're going to get a value
309 #
310 sub ask_value {
311     local($d,$s) = @_;
312     local($val);
313     print "\nNew option: $d\n";
314     print "$comment\n" unless ($comment =~ /^\s*\/\*\s*\*\/\s*$/);
315     print "Default value: $s\n";
316     print "Value for this option? (undef to undefine) [$s] ";
317     $val = <STDIN>;
318     $val = $s if $val =~ /^$/;
319     $defs{$d} = $val;
320     @newoptions = (@newoptions,$d);
321     return $d;
322 }
323
Note: See TracBrowser for help on using the browser.