#!/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 . # # 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 <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: