| #!/bin/sh |
| #! -*-perl-*- |
| |
| # Rewrite a gnulib.mk, adding prefixes to work with automake's subdir-objects. |
| |
| # Copyright (C) 2012-2019 Free Software Foundation, Inc. |
| # |
| # This program is free software: you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation, either version 3 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program. If not, see <https://www.gnu.org/licenses/>. |
| # |
| # Written by Jim Meyering |
| |
| # This is a prologue that allows to run a perl script as an executable |
| # on systems that are compliant to a POSIX version before POSIX:2017. |
| # On such systems, the usual invocation of an executable through execlp() |
| # or execvp() fails with ENOEXEC if it is a script that does not start |
| # with a #! line. The script interpreter mentioned in the #! line has |
| # to be /bin/sh, because on GuixSD systems that is the only program that |
| # has a fixed file name. The second line is essential for perl and is |
| # also useful for editing this file in Emacs. The next two lines below |
| # are valid code in both sh and perl. When executed by sh, they re-execute |
| # the script through the perl program found in $PATH. The '-x' option |
| # is essential as well; without it, perl would re-execute the script |
| # through /bin/sh. When executed by perl, the next two lines are a no-op. |
| eval 'exec perl -wSx "$0" "$@"' |
| if 0; |
| |
| my $VERSION = '2012-01-21 17:13'; # UTC |
| # The definition above must lie within the first 8 lines in order |
| # for the Emacs time-stamp write hook (at end) to update it. |
| # If you change this file with Emacs, please let the write hook |
| # do its job. Otherwise, update this string manually. |
| |
| use strict; |
| use IO::File; |
| use Getopt::Long; |
| use File::Basename; # for dirname |
| |
| (my $ME = $0) =~ s|.*/||; |
| |
| my $prefix; |
| my $lib_name; |
| |
| sub usage ($) |
| { |
| my ($exit_code) = @_; |
| my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR); |
| if ($exit_code != 0) |
| { |
| print $STREAM "Try '$ME --help' for more information.\n"; |
| } |
| else |
| { |
| print $STREAM <<EOF; |
| Usage: $ME --lib-name=NAME FILE |
| or: $ME [--help|--version] |
| Rewrite a gnulib-tool-generated FILE like lib/gnulib.mk to work with |
| automake's subdir-objects. |
| |
| OPTIONS: |
| |
| This option must be specified: |
| |
| --lib-name=NAME library name, often "lib\$project" |
| |
| The following are optional: |
| |
| --help display this help and exit |
| --version output version information and exit |
| |
| EOF |
| } |
| exit $exit_code; |
| } |
| |
| # contents ($FILE_NAME) |
| # --------------------- |
| sub contents ($) |
| { |
| my ($file) = @_; |
| local $/; # Turn on slurp-mode. |
| my $f = new IO::File "< $file" or die "$file"; |
| my $contents = $f->getline or die "$file"; |
| $f->close; |
| return $contents; |
| } |
| |
| # prefix_word ($WORD) |
| # ------------------- |
| # Do not prefix special words such as variable dereferences. Also, |
| # "Makefile" is really "Makefile", since precisely there is no |
| # lib/Makefile. |
| sub prefix_word ($) |
| { |
| local ($_) = @_; |
| $_ = $prefix . $_ |
| unless (/^-/ || m{^\$\(\w+\)} || $_ eq "Makefile" || $_ eq '\\' |
| || $_ eq '@ALLOCA@'); |
| return $_; |
| } |
| |
| |
| # prefix_words ($TEXT) |
| # -------------------- |
| sub prefix_words ($) |
| { |
| local ($_) = @_; |
| s{(\S+)}{prefix_word($1)}gem; |
| return $_; |
| } |
| |
| |
| # prefix_assignment ($LHS-AND-ASSIGN-OP, $RHS) |
| # -------------------------------------------- |
| sub prefix_assignment ($$) |
| { |
| my ($lhs_and_assign_op, $rhs) = @_; |
| |
| # Some variables are initialized by gnulib.mk, and we don't want |
| # that. Change '=' to '+='. |
| if ($lhs_and_assign_op =~ /^(GPERF|V_GPERF.*) =$/) |
| { |
| # Do not change the RHS, which specifies the GPERF program. |
| } |
| # Don't change variables such as HAVE_INCLUDE_NEXT. |
| elsif ($lhs_and_assign_op =~ /^HAVE_/) |
| { |
| } |
| elsif ($lhs_and_assign_op =~ |
| /^(SUBDIRS|EXTRA_DIST|BUILT_SOURCES|SUFFIXES|MOSTLYCLEANFILES |
| |CLEANFILES|DISTCLEANFILES|MAINTAINERCLEANFILES |
| |AM_GNU_GETTEXT)\ =/x) |
| { |
| $lhs_and_assign_op =~ s/=/+=/; |
| } |
| # We don't want things such as AM_CPPFLAGS += |
| # -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\" to apply to the whole |
| # Makefile.in: scope it to the library: libbison_a_CPPFLAGS = |
| # $(AM_CPPFLAGS) -DDEFAULT_TEXT_DOMAIN=\"bison-gnulib\". |
| elsif ($lhs_and_assign_op =~ |
| /^(AM_CFLAGS|AM_CPPFLAGS)\ \+?=/x) |
| { |
| $lhs_and_assign_op =~ s/^AM_(\w+)\ \+?=/${lib_name}_a_$1 =/; |
| $rhs = " \$(AM_$1)$rhs"; |
| } |
| # We don't want to inherit gnulib's AUTOMAKE_OPTIONS, comment them. |
| elsif ($lhs_and_assign_op =~ /^AUTOMAKE_OPTIONS =/) |
| { |
| $lhs_and_assign_op =~ s/^/# /; |
| } |
| # Elide any SUFFIXES assignment or concatenation. |
| elsif ($lhs_and_assign_op =~ /^SUFFIXES /) |
| { |
| $lhs_and_assign_op =~ s/^/# /; |
| } |
| # The words are (probably) paths to files in lib/: prefix them. |
| else |
| { |
| $rhs = prefix_words($rhs) |
| } |
| |
| # Variables whose name depend on the location: libbison_a_SOURCES => |
| # lib_libbison_a_SOURCES. |
| $lhs_and_assign_op =~ s/($lib_name)/lib_$1/g; |
| |
| $lhs_and_assign_op . $rhs; |
| } |
| |
| # prefix $CONTENTS |
| # ---------------- |
| # $CONTENTS is a Makefile content. Post-process it so that each file-name |
| # is prefixed with $prefix (e.g., "lib/"). |
| # |
| # Relies heavily on the regularity of the file generated by gnulib-tool. |
| sub prefix ($) |
| { |
| # Work on $_. |
| local ($_) = @_; |
| |
| # Prefix all the occurrence of files in rules. If there is nothing |
| # after in the :, it's probably a phony target, or a suffix rule. |
| # Don't touch it. |
| s{^([-\w+/]+\.[-\w.]+ *: *\S.*)$} |
| {prefix_words($1)}gem; |
| |
| # Prefix files in variables. |
| s{^([\w.]+\s*\+?=)(.*)$} |
| {prefix_assignment($1, $2)}gem; |
| |
| # $(srcdir)/ is actually $(top_srcdir)/$prefix/. |
| # The trailing slash is required to avoid matching this rule: |
| # test '$(srcdir)' = . || rm -f $(top_builddir)/GNUmakefile |
| s{\$\(srcdir\)/}{\$(top_srcdir)/$prefix}g; |
| |
| # Sometimes, t-$@ is used instead of $@-t, which, of course, does |
| # not work when we have a $@ with a directory in it. |
| s{t-\$\@}{\$\@-t}g; |
| |
| # Some AC_SUBST patterns remain and would better be Make macros. |
| s{\@(MKDIR_P)\@}{\$($1)}g; |
| |
| # Adjust paths in mkdir. |
| s{(\$\(MKDIR_P\))\s*(\w+)}{$1 $prefix$2}g; |
| |
| return $_; |
| } |
| |
| # process ($IN) |
| # ------------- |
| sub process ($) |
| { |
| my ($file) = @_; |
| my ($bak) = "$file.bak"; |
| rename ($file, $bak) or die "$ME: rename $file $bak failed: $!\n"; |
| my $contents = contents ($bak); |
| $contents = prefix ($contents); |
| my $out = new IO::File(">$file") |
| or die "$ME: $file: failed to open for writing: $!\n"; |
| print $out $contents; |
| } |
| |
| { |
| GetOptions |
| ( |
| 'lib-name=s' => \$lib_name, |
| help => sub { usage 0 }, |
| version => sub { print "$ME version $VERSION\n"; exit }, |
| ) or usage 1; |
| |
| my $fail = 0; |
| defined $lib_name |
| or (warn "$ME: no library name; use --lib-name=NAME\n"), $fail = 1; |
| |
| # There must be exactly one argument. |
| @ARGV == 0 |
| and (warn "$ME: missing FILE argument\n"), $fail = 1; |
| 1 < @ARGV |
| and (warn "$ME: too many arguments:\n", join ("\n", @ARGV), "\n"), |
| $fail = 1; |
| $fail |
| and usage 1; |
| |
| my $file = $ARGV[0]; |
| $prefix = (dirname $file) . '/'; |
| warn "prefix=$prefix\n"; |
| |
| process $file; |
| } |
| |
| ### Setup "GNU" style for perl-mode and cperl-mode. |
| ## Local Variables: |
| ## perl-indent-level: 2 |
| ## perl-continued-statement-offset: 2 |
| ## perl-continued-brace-offset: 0 |
| ## perl-brace-offset: 0 |
| ## perl-brace-imaginary-offset: 0 |
| ## perl-label-offset: -2 |
| ## cperl-indent-level: 2 |
| ## cperl-brace-offset: 0 |
| ## cperl-continued-brace-offset: 0 |
| ## cperl-label-offset: -2 |
| ## cperl-extra-newline-before-brace: t |
| ## cperl-merge-trailing-else: nil |
| ## cperl-continued-statement-offset: 2 |
| ## eval: (add-hook 'before-save-hook 'time-stamp) |
| ## time-stamp-line-limit: 50 |
| ## time-stamp-start: "my $VERSION = '" |
| ## time-stamp-format: "%:y-%02m-%02d %02H:%02M" |
| ## time-stamp-time-zone: "UTC0" |
| ## time-stamp-end: "'; # UTC" |
| ## End: |