3 ## $Id: buildconfig.in 6806 2004-05-18 01:18:57Z rra $
5 ## Generate linkage code and makefiles for storage and overview methods.
7 ## Goes through all subdirectories of the current directory and finds
8 ## directories that are either storage methods or overview methods. Builds
9 ## methods.[ch] and ovmethods.[ch] as well as makefile stubs.
14 use vars qw(@OVERVIEW @STORAGE);
16 # Storage API functions.
17 @STORAGE = qw(init store retrieve next freearticle cancel ctl flushcacheddata
20 # Overview API functions.
21 @OVERVIEW = qw(open groupstats groupadd groupdel add cancel opensearch search
22 closesearch getartinfo expiregroup ctl close);
24 # Used to make heredocs more readable.
25 sub unquote { my ($string) = @_; $string =~ s/^:( {0,7}|\t)//gm; $string }
27 # Parse a method.config file for a storage method, putting information about
28 # that storage method into the given hash ref.
30 my ($dir, $file, $config) = @_;
32 $$config{sources} ||= [];
33 $$config{extra} ||= [];
34 $$config{programs} ||= [];
35 $$config{makefiles} ||= [];
36 open (CONFIG, "$dir/$file") or die "Can't open $dir/$file: $!\n";
40 if (/^name\s*=\s*(\S+)$/) {
42 die "$dir/$file: $method has already been defined\n"
43 if (defined $$config{method}{$method});
44 $$config{method}{$method} = $dir;
45 } elsif (/^number\s*=\s*(\d+)$/) {
47 if (defined $$config{number}{$number}) {
48 die "$dir/$file: method number $number was already "
49 . "allocated in $$config{number}{$number}\n";
51 $$config{number}{$dir} = $number;
52 } elsif (/^sources\s*=\s*(.*)/) {
54 my @sources = split (' ', $sources);
55 push (@{ $$config{sources} }, map { "$dir/$_" } @sources);
56 } elsif (/^extra-sources\s*=\s*(.*)/) {
58 my @extra = split (' ', $extra);
59 push (@{ $$config{extra} }, map { "$dir/$_" } @extra);
60 } elsif (/^programs\s*=\s*(.*)/) {
62 my @programs = split (' ', $programs);
63 push (@{ $$config{programs} }, map { "$dir/$_" } @programs);
65 warn "$dir/$file: ignoring unknown line: $_\n";
69 # If there is a makefile fragment in the directory, note it.
70 if (-f "$dir/method.mk") {
71 push (@{ $$config{makefiles} }, "$dir/method.mk");
72 } elsif (-f "$dir/ovmethod.mk") {
73 push (@{ $$config{makefiles} }, "$dir/ovmethod.mk");
77 # Write out include directives for a list of files.
79 my ($fh, $config) = @_;
81 for $method (sort keys %{ $$config{method} }) {
82 my $path = $$config{method}{$method};
83 print $fh qq(\#include "$path/$method.h"\n);
87 # Write out the method struct.
89 my ($fh, $config, $prefix, @funcs) = @_;
90 my ($notfirst, $method);
91 for $method (sort keys %{ $$config{method} }) {
92 print $fh "\n},\n" if $notfirst;
93 print $fh qq(\{\n "$method");
94 print $fh ', ', $prefix, '_', uc ($method) if $prefix;
96 print $fh ",\n ${method}_$_";
100 print $fh "\n}\n};\n\n";
103 # Write out the constant defines for methods.
104 sub write_constants {
105 my ($fh, $config, $prefix) = @_;
107 for $method (sort keys %{ $$config{method} }) {
108 printf $fh "#define ${prefix}_%-30s%d\n", uc ($method),
109 $$config{number}{$$config{method}{$method}};
113 # Write out methods.c and methods.h for the interface to the storage
117 open (DEF, '> methods.c.new') or die "Can't create methods.c.new: $!\n";
118 print DEF unquote (<<'EOE');
119 : /* This file is automatically generated by buildconfig. */
121 : #include "interface.h"
122 : #include "methods.h"
125 write_includes (\*DEF, $storage);
126 print DEF "\nSTORAGE_METHOD storage_methods[",
127 scalar (keys %{ $$storage{method} }), "] = {\n";
128 write_methods (\*DEF, $storage, 'TOKEN', @STORAGE);
130 rename ('methods.c.new', 'methods.c');
132 open (H, '> methods.h.new') or die "Can't open methods.h.new: $!\n";
133 print H unquote (<<'EOE');
134 : /* This file is automatically generated by buildconfig */
137 : #define METHODS_H 1
139 : #include "interface.h"
142 print H '#define NUM_STORAGE_METHODS ',
143 scalar (keys %{ $$storage{method} }), "\n\n";
144 write_constants (\*H, $storage, 'TOKEN');
145 print H unquote (<<'EOE');
147 : extern STORAGE_METHOD storage_methods[NUM_STORAGE_METHODS];
149 : #endif /* METHODS_H */
152 rename ('methods.h.new', 'methods.h');
155 # Write out ovmethods.c and ovmethods.h for the interface to the overview
158 my $overview = shift;
159 open (DEF, '> ovmethods.c.new')
160 or die "Can't create ovmethods.c.new: $!\n";
161 print DEF unquote (<<'EOE');
162 : /* This file is automatically generated by buildconfig. */
164 : #include "ovinterface.h"
166 write_includes (\*DEF, $overview);
167 print DEF "\nOV_METHOD ov_methods[",
168 scalar (keys %{ $$overview{method} }), "] = {\n";
169 write_methods (\*DEF, $overview, undef, @OVERVIEW);
171 rename ('ovmethods.c.new', 'ovmethods.c');
173 open (H, '> ovmethods.h.new') or die "Can't open ovmethods.h.new: $!\n";
174 print H unquote (<<'EOE');
175 : /* This file is automatically generated by buildconfig */
177 : #ifndef OVMETHODS_H
178 : #define OVMETHODS_H 1
180 : #include "ovinterface.h"
183 print H '#define NUM_OV_METHODS ',
184 scalar (keys %{ $$overview{method} }), "\n";
185 print H unquote (<<'EOE');
187 : extern OV_METHOD ov_methods[NUM_OV_METHODS];
189 : #endif /* OVMETHODS_H */
192 rename ('ovmethods.h.new', 'ovmethods.h');
195 # Return a string setting a makefile variable. Tab over the = properly and
196 # wrap to fit our coding standards.
198 my ($variable, @values) = @_;
200 $output = sprintf ("%-15s =", $variable);
203 if ($column > 17 && 77 - $column < length ($_)) {
204 $output .= " \\\n" . ' ' x 17;
208 $column += 1 + length ($_);
214 # Write out the makefile fragment for overview and storage methods.
216 my ($dirs, $sources, $extra, $programs, $makefiles) = @_;
217 open (MAKE, '> Make.methods.new')
218 or die "Can't create Make.methods.new: $!\n";
219 print MAKE "# This file is automatically generated by buildconfig\n\n";
220 print MAKE makefile_var ('METHOD_SOURCES', @$sources);
221 print MAKE makefile_var ('EXTRA_SOURCES', @$extra);
222 print MAKE makefile_var ('PROGRAMS', @$programs);
224 print MAKE "\n\n## Included from $_\n\n";
225 open (FRAG, $_) or die "Can't open $_: $!\n";
229 rename ('Make.methods.new', 'Make.methods');
232 my ($dir, %storage, %overview);
234 if (-d 'storage/cnfs') {
235 chdir 'storage' or die "Can't chdir to storage: $!\n";
237 die "Can't find storage directory (looking for storage/cnfs)\n";
240 opendir (D, ".") or die "Can't open current directory: $!\n";
241 my @dirs = sort readdir D;
243 if (-e "$dir/method.config") {
244 parse_config ($dir, 'method.config', \%storage);
246 if (-e "$dir/ovmethod.config") {
247 parse_config ($dir, 'ovmethod.config', \%overview);
250 write_storage (\%storage);
251 write_overview (\%overview);
252 @dirs = (sort values %{ $storage{method} },
253 sort values %{ $overview{method} });
254 my @sources = (sort @{ $storage{sources} }, sort @{ $overview{sources} });
255 my @extra = (sort @{ $storage{extra} }, sort @{ $overview{extra} });
256 my @programs = sort (@{ $storage{programs} }, @{ $overview{programs} });
257 my @makefiles = sort (@{ $storage{makefiles} }, @{ $overview{makefiles} });
258 write_makefile (\@dirs, \@sources, \@extra, \@programs, \@makefiles);