1eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
2  & eval 'exec perl -wS "$0" $argv:q'
3    if 0;
4
5use strict;
6use IO::File;
7use Getopt::Long;
8use File::Basename; # for dirname
9
10my $VERSION = '2012-01-21 17:13'; # UTC
11(my $ME = $0) =~ s|.*/||;
12
13my $prefix;
14my $lib_name;
15
16sub usage ($)
17{
18  my ($exit_code) = @_;
19  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
20  if ($exit_code != 0)
21    {
22      print $STREAM "Try '$ME --help' for more information.\n";
23    }
24  else
25    {
26      print $STREAM <<EOF;
27Usage: $ME --lib-name=NAME FILE
28   or: $ME [--help|--version]
29Rewrite a gnulib-tool-generated FILE like lib/gnulib.mk to work with
30automake's subdir-objects.
31
32OPTIONS:
33
34This option must be specified:
35
36   --lib-name=NAME    library name, often "lib\$project"
37
38The following are optional:
39
40   --help             display this help and exit
41   --version          output version information and exit
42
43EOF
44    }
45  exit $exit_code;
46}
47
48# contents ($FILE_NAME)
49# ---------------------
50sub contents ($)
51{
52  my ($file) = @_;
53  local $/;                     # Turn on slurp-mode.
54  my $f = new IO::File "< $file" or die "$file";
55  my $contents = $f->getline or die "$file";
56  $f->close;
57  return $contents;
58}
59
60# prefix_word ($WORD)
61# -------------------
62# Do not prefix special words such as variable dereferences.  Also,
63# "Makefile" is really "Makefile", since precisely there is no
64# lib/Makefile.
65sub prefix_word ($)
66{
67  local ($_) = @_;
68  $_ = $prefix . $_
69    unless (/^-/ || m{^\$\(\w+\)} || $_ eq "Makefile" || $_ eq '\\'
70            || $_ eq '@ALLOCA@');
71  return $_;
72}
73
74
75# prefix_words ($TEXT)
76# --------------------
77sub prefix_words ($)
78{
79  local ($_) = @_;
80  s{(\S+)}{prefix_word($1)}gem;
81  return $_;
82}
83
84
85# prefix_assignment ($LHS-AND-ASSIGN-OP, $RHS)
86# --------------------------------------------
87sub prefix_assignment ($$)
88{
89  my ($lhs_and_assign_op, $rhs) = @_;
90  my $res;
91
92  # Some variables are initialized by gnulib.mk, and we don't want
93  # that.  Change '=' to '+='.
94  if ($lhs_and_assign_op =~ /^GPERF =$/)
95    {
96      # Do not change the RHS, which specifies the GPERF program.
97    }
98  elsif ($lhs_and_assign_op =~
99      /^(SUBDIRS|EXTRA_DIST|BUILT_SOURCES|SUFFIXES|MOSTLYCLEANFILES
100         |CLEANFILES|DISTCLEANFILES|MAINTAINERCLEANFILES|AM_CFLAGS
101         |AM_CPPFLAGS|AM_GNU_GETTEXT)\ =/x)
102    {
103      $lhs_and_assign_op =~ s/=/+=/;
104    }
105  # We don't want to inherit gnulib's AUTOMAKE_OPTIONS, comment them.
106  elsif ($lhs_and_assign_op =~ /^AUTOMAKE_OPTIONS =/)
107    {
108      $lhs_and_assign_op =~ s/^/# /;
109    }
110  elsif ($lhs_and_assign_op =~ /^SUFFIXES /)
111    {
112      # Elide any SUFFIXES assignment or concatenation.
113      $lhs_and_assign_op =~ s/^/# /;
114    }
115  # The words are (probably) paths to files in lib/: prefix them.
116  else
117    {
118      $rhs = prefix_words($rhs)
119    }
120
121  # Variables which name depend on the location: libbison_a_SOURCES =>
122  # lib_libbison_a_SOURCES.
123  $lhs_and_assign_op =~ s/($lib_name)/lib_$1/g;
124
125  return $lhs_and_assign_op . $rhs;
126}
127
128# prefix $CONTENTS
129# ----------------
130# $CONTENTS is a Makefile content.  Post-process it so that each file-name
131# is prefixed with $prefix (e.g., "lib/").
132#
133# Relies heavily on the regularity of the file generated by gnulib-tool.
134sub prefix ($)
135{
136  # Work on $_.
137  local ($_) = @_;
138
139  # Prefix all the occurrence of files in rules.  If there is nothing
140  # after in the :, it's probably a phony target, or a suffix rule.
141  # Don't touch it.
142  s{^([-\w+/]+\.[-\w.]+ *: *\S.*)$}
143   {prefix_words($1)}gem;
144
145  # Prefix files in variables.
146  s{^([\w.]+\s*\+?=)(.*)$}
147   {prefix_assignment($1, $2)}gem;
148
149  # These three guys escape all the other regular rules.
150  # Require the leading white space to avoid inserting the prefix
151  # on a line like this:
152  # charset_alias = $(DESTDIR)$(libdir)/charset.alias
153  # With $(libdir), it would be erroneous.
154  s{(\s)(charset\.alias|ref-add\.sed|ref-del\.sed)}{$1$prefix$2}g;
155  # Unfortunately, as a result we sometimes have lib/lib.
156  s{($prefix){2}}{$1}g;
157
158  # lib_libcoreutils_a_SOURCES += \
159  #   imaxtostr.c \
160  #   inttostr.c \
161  #   offtostr.c \
162  #   uinttostr.c \
163  #   umaxtostr.c
164  # The above are not handled since they're on continued lines, so
165  # deal with them manually:
166  s{^(\s*)((?:[ui]max|u?int|off)tostr\.c(:? \\)?)$}{$1$prefix$2}gm;
167
168  # $(srcdir)/ is actually $(top_srcdir)/$prefix/.
169  # The trailing slash is required to avoid matching this rule:
170  #   test '$(srcdir)' = . || rm -f $(top_builddir)/GNUmakefile
171  s{\$\(srcdir\)/}{\$(top_srcdir)/$prefix}g;
172
173  # Sometimes, t-$@ is used instead of $@-t, which, of course, does
174  # not work when we have a $@ with a directory in it.
175  s{t-\$\@}{\$\@-t}g;
176
177  # Some AC_SUBST patterns remain and would better be Make macros.
178  s{\@(MKDIR_P)\@}{\$($1)}g;
179
180  # Adjust paths in mkdir.
181  s{(\$\(MKDIR_P\))\s*(\w+)}{$1 $prefix$2}g;
182
183  return $_;
184}
185
186# process ($IN)
187# -------------
188sub process ($)
189{
190  my ($file) = @_;
191  my ($bak) = "$file.bak";
192  rename ($file, $bak) or die "$ME: rename $file $bak failed: $!\n";
193  my $contents = contents ($bak);
194  $contents = prefix ($contents);
195  my $out = new IO::File(">$file")
196    or die "$ME: $file: failed to open for writing: $!\n";
197  print $out $contents;
198}
199
200{
201  GetOptions
202    (
203     'lib-name=s' => \$lib_name,
204     help => sub { usage 0 },
205     version => sub { print "$ME version $VERSION\n"; exit },
206    ) or usage 1;
207
208  my $fail = 0;
209  defined $lib_name
210    or (warn "$ME: no library name; use --lib-name=NAME\n"), $fail = 1;
211
212  # There must be exactly one argument.
213  @ARGV == 0
214    and (warn "$ME: missing FILE argument\n"), $fail = 1;
215  1 < @ARGV
216    and (warn "$ME: too many arguments:\n", join ("\n", @ARGV), "\n"),
217      $fail = 1;
218  $fail
219    and usage 1;
220
221  my $file = $ARGV[0];
222  $prefix = (dirname $file) . '/';
223  warn "prefix=$prefix\n";
224
225  process $file;
226}
227
228### Setup "GNU" style for perl-mode and cperl-mode.
229## Local Variables:
230## perl-indent-level: 2
231## perl-continued-statement-offset: 2
232## perl-continued-brace-offset: 0
233## perl-brace-offset: 0
234## perl-brace-imaginary-offset: 0
235## perl-label-offset: -2
236## cperl-indent-level: 2
237## cperl-brace-offset: 0
238## cperl-continued-brace-offset: 0
239## cperl-label-offset: -2
240## cperl-extra-newline-before-brace: t
241## cperl-merge-trailing-else: nil
242## cperl-continued-statement-offset: 2
243## eval: (add-hook 'write-file-hooks 'time-stamp)
244## time-stamp-start: "my $VERSION = '"
245## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
246## time-stamp-time-zone: "UTC"
247## time-stamp-end: "'; # UTC"
248## End:
249