1#! /usr/bin/perl 2 3## $Id: buildconfig.in 6803 2004-05-18 00:48:58Z rra $ 4## 5## Generate linkage code and makefiles for storage and overview methods. 6## 7## Goes through all subdirectories of the current directory and finds 8## directories that history methods or overview methods. Builds 9## hismethods.[ch] as well as makefile stubs. 10 11require 5.003; 12 13use strict; 14use vars qw(@HISTORY); 15 16# History API functions. 17@HISTORY = qw(open close sync lookup check write replace expire walk remember 18 ctl); 19 20# Used to make heredocs more readable. 21sub unquote { my ($string) = @_; $string =~ s/^:( {0,7}|\t)//gm; $string } 22 23# Parse a hismethod.config file for a history method, putting information 24# about that history method into the given hash ref. 25sub parse_config { 26 my ($dir, $file, $config) = @_; 27 local $_; 28 $$config{sources} ||= []; 29 $$config{extra} ||= []; 30 $$config{programs} ||= []; 31 $$config{makefiles} ||= []; 32 open (CONFIG, "$dir/$file") or die "Can't open $dir/$file: $!\n"; 33 while (<CONFIG>) { 34 s/^\s+//; 35 s/\s+$//; 36 if (/^name\s*=\s*(\S+)$/) { 37 my $method = $1; 38 die "$dir/$file: $method has already been defined\n" 39 if (defined $$config{method}{$method}); 40 $$config{method}{$method} = $dir; 41 } elsif (/^number\s*=\s*(\d+)$/) { 42 my $number = $1; 43 if (defined $$config{number}{$number}) { 44 die "$dir/$file: method number $number was already " 45 . "allocated in $$config{number}{$number}\n"; 46 } 47 $$config{number}{$dir} = $number; 48 } elsif (/^sources\s*=\s*(.*)/) { 49 my $sources = $1; 50 my @sources = split (' ', $sources); 51 push (@{ $$config{sources} }, map { "$dir/$_" } @sources); 52 } elsif (/^extra-sources\s*=\s*(.*)/) { 53 my $extra = $1; 54 my @extra = split (' ', $extra); 55 push (@{ $$config{extra} }, map { "$dir/$_" } @extra); 56 } elsif (/^programs\s*=\s*(.*)/) { 57 my $programs = $1; 58 my @programs = split (' ', $programs); 59 push (@{ $$config{programs} }, map { "$dir/$_" } @programs); 60 } else { 61 warn "$dir/$file: ignoring unknown line: $_\n"; 62 } 63 } 64 65 # If there is a makefile fragment in the directory, note it. 66 if (-f "$dir/hismethod.mk") { 67 push (@{ $$config{makefiles} }, "$dir/hismethod.mk"); 68 } 69} 70 71# Write out include directives for a list of files. 72sub write_includes { 73 my ($fh, $config) = @_; 74 my $method; 75 for $method (sort keys %{ $$config{method} }) { 76 my $path = $$config{method}{$method}; 77 print $fh qq(\#include "$path/$method.h"\n); 78 } 79} 80 81# Write out the method struct. 82sub write_methods { 83 my ($fh, $config, $prefix, @funcs) = @_; 84 my ($notfirst, $method); 85 for $method (sort keys %{ $$config{method} }) { 86 print $fh "\n},\n" if $notfirst; 87 print $fh qq(\{\n "$method"); 88 print $fh ', ', $prefix, '_', uc ($method) if $prefix; 89 for (@funcs) { 90 print $fh ",\n ${method}_$_"; 91 } 92 $notfirst++; 93 } 94 print $fh "\n}\n};\n\n"; 95} 96 97# Write out hismethods.c and hismethods.h for the interface to the history 98# methods. 99sub write_history { 100 my $history = shift; 101 open (DEF, '> hismethods.c.new') 102 or die "Can't create hismethods.c.new: $!\n"; 103 print DEF unquote (<<'EOE'); 104: /* This file is automatically generated by buildconfig. */ 105: 106: #include "hisinterface.h" 107: #include "hismethods.h" 108EOE 109 my $method; 110 write_includes (\*DEF, $history); 111 print DEF "\nHIS_METHOD his_methods[", 112 scalar (keys %{ $$history{method} }), "] = {\n"; 113 write_methods (\*DEF, $history, undef, @HISTORY); 114 close DEF; 115 rename ('hismethods.c.new', 'hismethods.c'); 116 117 open (H, '> hismethods.h.new') or die "Can't open hismethods.h.new: $!\n"; 118 print H unquote (<<'EOE'); 119: /* This file is automatically generated by buildconfig */ 120: 121: #ifndef HISMETHODS_H 122: #define HISMETHODS_H 1 123: 124: #include "hisinterface.h" 125: 126EOE 127 print H '#define NUM_HIS_METHODS ', 128 scalar (keys %{ $$history{method} }), "\n"; 129 print H unquote (<<'EOE'); 130: 131: extern HIS_METHOD his_methods[NUM_HIS_METHODS]; 132: 133: #endif /* HISMETHODS_H */ 134EOE 135 close H; 136 rename ('hismethods.h.new', 'hismethods.h'); 137} 138 139# Return a string setting a makefile variable. Tab over the = properly and 140# wrap to fit our coding standards. 141sub makefile_var { 142 my ($variable, @values) = @_; 143 my $output; 144 $output = sprintf ("%-15s =", $variable); 145 my $column = 17; 146 for (@values) { 147 if ($column > 17 && 77 - $column < length ($_)) { 148 $output .= " \\\n" . ' ' x 17; 149 $column = 17; 150 } 151 $output .= " $_"; 152 $column += 1 + length ($_); 153 } 154 $output .= "\n"; 155 return $output; 156} 157 158# Write out the makefile fragment for history methods. 159sub write_makefile { 160 my ($dirs, $sources, $extra, $programs, $makefiles) = @_; 161 open (MAKE, '> Make.methods.new') 162 or die "Can't create Make.methods.new: $!\n"; 163 print MAKE "# This file is automatically generated by buildconfig\n\n"; 164 print MAKE makefile_var ('METHOD_SOURCES', @$sources); 165 print MAKE makefile_var ('EXTRA_SOURCES', @$extra); 166 print MAKE makefile_var ('PROGRAMS', @$programs); 167 for (@$makefiles) { 168 print MAKE "\n\n## Included from $_\n\n"; 169 open (FRAG, $_) or die "Can't open $_: $!\n"; 170 print MAKE <FRAG>; 171 close FRAG; 172 } 173 rename ('Make.methods.new', 'Make.methods'); 174} 175 176my ($dir, %history); 177if (!-d 'hisv6') { 178 if (-d 'history/cnfs') { 179 chdir 'history' or die "Can't chdir to history: $!\n"; 180 } else { 181 die "Can't find history directory (looking for history/hisv6)\n"; 182 } 183} 184opendir (D, ".") or die "Can't open current directory: $!\n"; 185my @dirs = sort readdir D; 186for $dir (@dirs) { 187 if (-e "$dir/hismethod.config") { 188 parse_config ($dir, 'hismethod.config', \%history); 189 } 190} 191write_history (\%history); 192@dirs = sort values %{ $history{method} }; 193my @sources = sort @{ $history{sources} }; 194my @extra = sort @{ $history{extra} }; 195my @programs = sort @{ $history{programs} }; 196my @makefiles = sort @{ $history{makefiles} }; 197write_makefile (\@dirs, \@sources, \@extra, \@programs, \@makefiles); 198