Refactor file writing - Remake Makefile.org into a template
[openssl.git] / util / dofile.pl
1 #! /usr/bin/perl
2 #
3 # Reads one or more template files and runs it through Text::Template
4 #
5 # It is assumed that this scripts is called with -Mconfigdata, a module
6 # that holds configuration data in %config
7
8 use strict;
9 use warnings;
10
11 # Because we know that Text::Template isn't a core Perl module, we use
12 # a fallback in case it's not installed on the system
13 use File::Basename;
14 use File::Spec::Functions;
15 use lib catdir(dirname(__FILE__));
16 use with_fallback qw(Text::Template);
17
18 # We actually expect to get the following hash tables from configdata:
19 #
20 #    %config
21 #    %target
22 #    %withargs
23 #
24 # We just do a minimal test to see that we got what we expected.
25 # $config{target} must exist as an absolute minimum.
26 die "You must run this script with -Mconfigdata\n" if !exists($config{target});
27
28 # Helper functions for the templates #################################
29
30 # It might be practical to quotify some strings and have them protected
31 # from possible harm.  These functions primarly quote things that might
32 # be interpreted wrongly by a perl eval.
33
34 # quotify1 STRING
35 # This adds quotes (") around the given string, and escapes any $, @, \,
36 # " and ' by prepending a \ to them.
37 sub quotify1 {
38     my $s = shift @_;
39     $s =~ s/([\$\@\\"'])/\\$1/g;
40     '"'.$s.'"';
41 }
42
43 # quotify_l LIST
44 # For each defined element in LIST (i.e. elements that aren't undef), have
45 # it quotified with 'quotofy1'
46 sub quotify_l {
47     map {
48         if (!defined($_)) {
49             ();
50         } else {
51             quotify1($_);
52         }
53     } @_;
54 }
55
56 # Error reporter #####################################################
57
58 # The error reporter uses %lines to figure out exactly which file the
59 # error happened and at what line.  Not that the line number may be
60 # the start of a perl snippet rather than the exact line where it
61 # happened.  Nothing we can do about that here.
62
63 my %lines = ();
64 sub broken {
65     my %args = @_;
66     my $filename = "<STDIN>";
67     my $deducelines = 0;
68     foreach (sort keys %lines) {
69         $filename = $lines{$_};
70         last if ($_ > $args{lineno});
71         $deducelines += $_;
72     }
73     print STDERR $args{error}," in $filename, fragment starting at line ",$args{lineno}-$deducelines;
74     undef;
75 }
76
77 # Template reading ###################################################
78
79 # Read in all the templates into $text, while keeping track of each
80 # file and its size in lines, to try to help report errors with the
81 # correct file name and line number.
82
83 my $prev_linecount = 0;
84 my $text =
85     @ARGV
86     ? join("", map { my $x = Text::Template::_load_text($_);
87                      my $linecount = $x =~ tr/\n//;
88                      $prev_linecount = ($linecount += $prev_linecount);
89                      $lines{$linecount} = $_;
90                      $x } @ARGV)
91     : join("", <STDIN>);
92
93 # Engage! ############################################################
94
95 # Load the full template (combination of files) into Text::Template
96 # and fill it up with our data.  Output goes directly to STDOUT
97
98 my $template = Text::Template->new(TYPE => 'STRING', SOURCE => $text );
99 $template->fill_in(OUTPUT => \*STDOUT,
100                    HASH => { config => \%config,
101                              target => \%target,
102                              withargs => \%withargs,
103                              quotify1 => \&quotify1,
104                              quotify_l => \&quotify_l },
105                    DELIMITERS => [ "{-", "-}" ],
106                    BROKEN => \&broken);