root/1.8.3/tags/p5rc1/utils/mkcmds.pl

Revision 1070, 6.8 KB (checked in by shawnw, 17 months ago)

#7430: mkcmds and switches.h

Line 
1#!/usr/bin/perl -w
2# perl version of the old mkcmds.sh script. Runs faster by simply not running
3# a bazillion child processes. Also uses SelfLoader to avoid compiling functions
4# that are never used, since it's usually invoked with at most 1 argument.
5#
6
7use SelfLoader;
8use File::Compare;
9use File::Copy;
10use strict; # Please ma'am may I have another?
11
12# SelfLoaded functions
13use subs qw/make_patches make_switches make_cmds make_funs/;
14# Always present functions
15use subs qw/maybemove temp_header temp_source scan_files_for_pattern/;
16
17# Main loop, dispatch for each command line argument.
18foreach my $command (@ARGV) {
19    if ($command eq "patches") {
20        make_patches;
21    } elsif ($command eq "switches") {
22        make_switches;
23    } elsif ($command eq "commands") {
24        make_cmds;
25    } elsif ($command eq "functions") {
26        make_funs;
27    } elsif ($command eq "all") {
28        make_patches;
29        make_switches;
30        make_cmds;
31        make_funs;
32    } else {
33        warn "Unknown option '${command}'\n";
34    }
35}
36
37# Return name of a temp file in hdrs/
38sub temp_header {
39    return "hdrs/temp.$$.h";
40}
41
42# Return name of a temp file in src/
43sub temp_source {
44    return "src/temp.$$.c";
45}
46
47# maybemove(file1, file2) copies file1 to file 2 if they are different,
48# otherwise just deletes file1 and leaves file2 unchanged.
49sub maybemove {
50    my $from = shift;
51    my $to = shift;
52
53    if (compare $from, $to) {
54        if (move $from, $to) {
55            print "File ${to} updated.\n";
56        } else {
57            warn "Couldn't rename ${from} to ${to}: $!\n";
58        }
59    } else {
60        print "File ${to} unchanged.\n";
61        unlink $from;
62    }
63}
64
65# scan_files_for_pattern(glob-pattern, re) searches all files matching
66# glob-pattern for lines matching re, and returns a sorted list of
67# $1's for each matching line.
68sub scan_files_for_pattern {
69    my $filepattern = shift;
70    my $re = shift;
71    my @idents;
72
73    foreach my $file (glob $filepattern) {
74        open FILE, "<", $file 
75            or die "Cannot open ${file} for reading: $!\n";
76        while (<FILE>) {
77            chomp;
78            push @idents, $1 if m/$re/;
79        }
80        close FILE;
81    }
82    return sort @idents;
83}
84
85
86END {
87    # Make sure temp files get deleted.
88    my @files = (temp_header(), temp_source());
89    foreach my $file (@files) {
90        unlink $file if -f $file;
91    }
92}
93
94__DATA__
95
96sub make_patches {
97    print "Rebuilding list of installed patches\n";
98    my $tempfile = temp_header;
99    my $patchfile = "hdrs/patches.h";
100    my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
101    open PATCHES, ">", $tempfile
102        or die "Couldn't open $tempfile for writing: $!\n";
103    print PATCHES $auto_msg;
104    print PATCHES "#ifndef PATCHES_H\n";
105    print PATCHES "#define PATCHES_H\n";
106    my %patches;
107    if (-d "patches") {
108        foreach $file (<patches/*>) {
109            next if $file =~ /(?:\.bak|\.orig|\.rej|~)$/o;
110            open FILE, "<", $file
111                or die "Couldn't open file '$file' for reading: $!\n";
112            my $name = undef;
113            my $version = undef;
114            LINE: while (<FILE>) {
115                chomp;
116                $name = $1 if m/^# Patch name: (.*)/o;
117                $version = $1 if m/^# Patch version: (.*)/o;
118                if (defined $name && defined $version) {
119                    $patches{$name} = $version;
120                    last LINE;
121                }
122            }
123            close FILE;
124        }
125        if (scalar keys %patches > 0) {
126            print PATCHES '#define PATCHES "';
127            while (my ($name, $version) = each %patches) {
128                print PATCHES "$name($version) ";               
129            }
130            print PATCHES '"', "\n";
131        } else {
132            print PATCHES "#undef PATCHES\n";
133        }
134    } else {
135        print PATCHES "#undef PATCHES\n";
136    }
137    print PATCHES "#endif /* PATCHES_H */\n";
138    close PATCHES;
139   
140    maybemove $tempfile, $patchfile;
141}
142
143sub make_switches {
144    print "Rebuilding command switch file and header.\n";
145    my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
146   
147    my $temphdr = temp_header;
148    my $tempsrc = temp_source;
149
150    open CMDHDR, "<", "hdrs/command.h" or
151        die "Unable to open hdrs/command.h for reading: $!\n";
152    my $numbytes = 20;
153    while (<CMDHDR>) {
154        if (m/^#define\s+NUM_BYTES\s+(\d+)/o) {
155            $numbytes = $1;
156            last;
157        }
158    }
159    close CMDHDR;
160
161    my $MAXSWITCHES = $numbytes * 8;
162   
163    my @switches = scan_files_for_pattern "src/SWITCHES", qr/^(.+)/;
164   
165    warn "Too many switches defined!\n" if length @switches > $MAXSWITCHES;
166
167    open HDR, ">", $temphdr or
168        die "Unable to open $temphdr for writing: $!\n";
169    open SRC, ">", $tempsrc or
170        die "Unable to open $tempsrc for writing: $1\n";
171
172    print HDR $auto_msg;
173    print HDR "#ifndef SWITCHES_H\n";
174    print HDR "#define SWITCHES_H\n";
175
176    print SRC $auto_msg;
177    print SRC "SWITCH_VALUE switch_list[] = {\n";
178   
179    my $n = 1;
180    foreach my $switch (@switches) {
181        print HDR "#define SWITCH_${switch} ${n}\n";
182        print SRC "  {\"${switch}\", SWITCH_${switch}},\n";
183        $n++;
184    }
185   
186    print SRC "  {NULL, 0}\n";
187    print SRC "};\n";
188    close SRC;
189
190    print HDR "#endif                          /* SWITCHES_H */\n";
191    close HDR;
192
193    maybemove $temphdr, "hdrs/switches.h";
194    maybemove $tempsrc, "src/switchinc.c";
195}
196
197# I really should combine this and make_funs into one function that does
198# the work with specific files/regexps/defines passed as arguments
199
200sub make_cmds {
201    my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
202
203    print "Rebuilding command prototype header.\n";
204   
205    my $tempfile = temp_header;
206   
207    my @commands =
208        scan_files_for_pattern "src/*.c", qr/^\s*COMMAND\(([^\)]+)\)/;
209
210    open HDR, ">", $tempfile
211        or die "Can't open ${tempfile} for writing: $!\n";
212   
213    print HDR $auto_msg;
214    print HDR "#ifndef CMDS_H\n";
215    print HDR "#define CMDS_H\n";
216
217    foreach my $command (@commands) {
218        print HDR "COMMAND_PROTO(${command});\n";
219    }
220
221    print HDR "#endif /* CMDS_H */\n";
222    close HDR;
223
224    maybemove $tempfile, "hdrs/cmds.h";
225
226}
227
228sub make_funs {
229    my $auto_msg = "/* AUTOGENERATED FILE. DO NOT EDIT! */\n";
230
231    print "Rebuilding function prototype header.\n";
232   
233    my $tempfile = temp_header;
234   
235    my @functions =
236        scan_files_for_pattern "src/*.c", qr/^\s*FUNCTION\(([^\)]+)\)/;
237
238    open HDR, ">", $tempfile
239        or die "Can't open ${tempfile} for writing: $!\n";
240   
241    print HDR $auto_msg;
242    print HDR "#ifndef FUNS_H\n";
243    print HDR "#define FUNS_H\n";
244
245    foreach my $function (@functions) {
246        print HDR "FUNCTION_PROTO(${function});\n";
247    }
248
249    print HDR "#endif /* FUNS_H */\n";
250    close HDR;
251
252    maybemove $tempfile, "hdrs/funs.h";
253}
Note: See TracBrowser for help on using the browser.