#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
-# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+scriptversion=2013-01-12.17; # UTC
+
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+#
#
# This program is free software; you can redistribute it and/or modify
# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-# Usage:
-# ylwrap PROGRAM INPUT [OUTPUT DESIRED]... -- [ARGS]...
-# * PROGRAM is program to run.
-# * INPUT is the input file
-# * OUTPUT is file PROG generates
-# * DESIRED is file we actually want
-# * ARGS are passed to PROG
-# Any number of OUTPUT,DESIRED pairs may be used.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
-# The program to run.
-prog="$1"
-shift
-# Make any relative path in $prog absolute.
-case "$prog" in
- /* | [A-Za-z]:\\*) ;;
- */*) prog="`pwd`/$prog" ;;
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+
+get_dirname ()
+{
+ case $1 in
+ */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
+ # Otherwise, we want the empty string (not ".").
+ esac
+}
+
+# guard FILE
+# ----------
+# The CPP macro used to guard inclusion of FILE.
+guard ()
+{
+ printf '%s\n' "$1" \
+ | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
+ -e 's/__*/_/g'
+}
+
+# quote_for_sed [STRING]
+# ----------------------
+# Return STRING (or stdin) quoted to be used as a sed pattern.
+quote_for_sed ()
+{
+ case $# in
+ 0) cat;;
+ 1) printf '%s\n' "$1";;
+ esac \
+ | sed -e 's|[][\\.*]|\\&|g'
+}
+
+case "$1" in
+ '')
+ echo "$0: No files given. Try '$0 --help' for more information." 1>&2
+ exit 1
+ ;;
+ --basedir)
+ basedir=$2
+ shift 2
+ ;;
+ -h|--h*)
+ cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+ INPUT is the input file
+ OUTPUT is one file PROG generates
+ DESIRED is the file we actually want instead of OUTPUT
+ PROGRAM is program to run
+ ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+EOF
+ exit $?
+ ;;
+ -v|--v*)
+ echo "ylwrap $scriptversion"
+ exit $?
+ ;;
esac
+
# The input.
-input="$1"
+input=$1
shift
-case "$input" in
- /* | [A-Za-z]:\\*)
+# We'll later need for a correct munging of "#line" directives.
+input_sub_rx=`get_dirname "$input" | quote_for_sed`
+case $input in
+ [\\/]* | ?:[\\/]*)
# Absolute path; do nothing.
;;
- *)
- # Relative path. Make it absolute. Why? Because otherwise any
- # debugging info in the generated file will point to the wrong
- # place. This is really gross.
- input="`pwd`/$input"
+ *)
+ # Relative path. Make it absolute.
+ input=`pwd`/$input
;;
esac
+input_rx=`get_dirname "$input" | quote_for_sed`
-# We don't want to use the absolute path if the input in the current
-# directory like when making a tar ball.
-input_base=`echo $input | sed -e 's|.*/||'`
-if test -f $input_base && cmp $input_base $input >/dev/null 2>&1; then
- input=$input_base
-fi
+# The parser itself, the first file, is the destination of the .y.c
+# rule in the Makefile.
+parser=$1
+
+# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
+# instance, we rename #include "y.tab.h" into #include "parse.h"
+# during the conversion from y.tab.c to parse.c.
+sed_fix_filenames=
+
+# Also rename header guards, as Bison 2.7 for instance uses its header
+# guard in its implementation file.
+sed_fix_header_guards=
-pairlist=
-while test "$#" -ne 0; do
- if test "$1" = "--"; then
- shift
- break
- fi
- pairlist="$pairlist $1"
- shift
+while test $# -ne 0; do
+ if test x"$1" = x"--"; then
+ shift
+ break
+ fi
+ from=$1
+ shift
+ to=$1
+ shift
+ sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
+ sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
done
-# FIXME: add hostname here for parallel makes that run commands on
-# other machines. But that might take us over the 14-char limit.
+# The program to run.
+prog=$1
+shift
+# Make any relative path in $prog absolute.
+case $prog in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog=`pwd`/$prog ;;
+esac
+
dirname=ylwrap$$
-trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
+trap "ret=129; $do_exit" 1
+trap "ret=130; $do_exit" 2
+trap "ret=141; $do_exit" 13
+trap "ret=143; $do_exit" 15
mkdir $dirname || exit 1
cd $dirname
-case "$input" in
- /* | [A-Za-z]:\\*)
- # Absolute path; do nothing.
- ;;
- *)
- # Make a symbolic link, hard link or hardcopy.
- ln -s ../"$input" . > /dev/null 2>&1 || ln ../"$input" . > /dev/null 2>&1 || cp ../"$input" .
- ;;
+
+case $# in
+ 0) "$prog" "$input" ;;
+ *) "$prog" "$@" "$input" ;;
esac
-$prog ${1+"$@"} "$input"
-status=$?
-
-if test $status -eq 0; then
- set X $pairlist
- shift
- first=yes
- while test "$#" -ne 0; do
- if test -f "$1"; then
- # If $2 is an absolute path name, then just use that,
- # otherwise prepend `../'.
- case "$2" in
- /* | [A-Za-z]:\\*) target="$2";;
- *) target="../$2";;
- esac
- mv "$1" "$target" || status=$?
- else
- # A missing file is only an error for the first file. This
- # is a blatant hack to let us support using "yacc -d". If -d
- # is not specified, we don't want an error when the header
- # file is "missing".
- if test $first = yes; then
- status=1
- fi
+ret=$?
+
+if test $ret -eq 0; then
+ for from in *
+ do
+ to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
+ if test -f "$from"; then
+ # If $2 is an absolute path name, then just use that,
+ # otherwise prepend '../'.
+ case $to in
+ [\\/]* | ?:[\\/]*) target=$to;;
+ *) target=../$to;;
+ esac
+
+ # Do not overwrite unchanged header files to avoid useless
+ # recompilations. Always update the parser itself: it is the
+ # destination of the .y.c rule in the Makefile. Divert the
+ # output of all other files to a temporary file so we can
+ # compare them to existing versions.
+ if test $from != $parser; then
+ realtarget=$target
+ target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
fi
- shift
- shift
- first=no
- done
-else
- status=$?
+
+ # Munge "#line" or "#" directives. Don't let the resulting
+ # debug information point at an absolute srcdir. Use the real
+ # output file name, not yy.lex.c for instance. Adjust the
+ # include guards too.
+ sed -e "/^#/!b" \
+ -e "s|$input_rx|$input_sub_rx|" \
+ -e "$sed_fix_filenames" \
+ -e "$sed_fix_header_guards" \
+ "$from" >"$target" || ret=$?
+
+ # Check whether files must be updated.
+ if test "$from" != "$parser"; then
+ if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+ echo "$to is unchanged"
+ rm -f "$target"
+ else
+ echo "updating $to"
+ mv -f "$target" "$realtarget"
+ fi
+ fi
+ else
+ # A missing file is only an error for the parser. This is a
+ # blatant hack to let us support using "yacc -d". If -d is not
+ # specified, don't fail when the header file is "missing".
+ if test "$from" = "$parser"; then
+ ret=1
+ fi
+ fi
+ done
fi
# Remove the directory.
cd ..
rm -rf $dirname
-exit $status
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End: