ylwrap 6.27 KB
Newer Older
Jason Merrill committed
1 2
#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
3

4
scriptversion=2013-01-12.17; # UTC
5

6
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
7
#
Jason Merrill committed
8 9 10 11 12 13 14 15 16 17 18 19 20
# Written by Tom Tromey <tromey@cygnus.com>.
#
# 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 2, 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
21
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Jason Merrill committed
22

23 24 25 26
# 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.
Jason Merrill committed
27

28 29 30 31
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
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'
}

64 65
case "$1" in
  '')
66
    echo "$0: No files given.  Try '$0 --help' for more information." 1>&2
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    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.

Report bugs to <bug-automake@gnu.org>.
EOF
    exit $?
    ;;
  -v|--v*)
    echo "ylwrap $scriptversion"
    exit $?
    ;;
Jason Merrill committed
95 96
esac

97

Jason Merrill committed
98
# The input.
99
input=$1
Jason Merrill committed
100
shift
101 102 103
# We'll later need for a correct munging of "#line" directives.
input_sub_rx=`get_dirname "$input" | quote_for_sed`
case $input in
104
  [\\/]* | ?:[\\/]*)
Jason Merrill committed
105 106
    # Absolute path; do nothing.
    ;;
107 108
  *)
    # Relative path.  Make it absolute.
109
    input=`pwd`/$input
Jason Merrill committed
110 111
    ;;
esac
112 113 114 115 116 117 118 119 120 121 122 123 124 125
input_rx=`get_dirname "$input" | quote_for_sed`

# 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=
Jason Merrill committed
126

127 128
while test $# -ne 0; do
  if test x"$1" = x"--"; then
129 130 131
    shift
    break
  fi
132
  from=$1
133
  shift
134 135 136 137
  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;"
Jason Merrill committed
138 139
done

140
# The program to run.
141
prog=$1
142 143
shift
# Make any relative path in $prog absolute.
144
case $prog in
145
  [\\/]* | ?:[\\/]*) ;;
146
  *[\\/]*) prog=`pwd`/$prog ;;
147 148
esac

Jason Merrill committed
149
dirname=ylwrap$$
150 151 152 153 154
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
Jason Merrill committed
155 156 157
mkdir $dirname || exit 1

cd $dirname
158 159

case $# in
160 161
  0) "$prog" "$input" ;;
  *) "$prog" "$@" "$input" ;;
162
esac
163 164 165
ret=$?

if test $ret -eq 0; then
166 167 168
  for from in *
  do
    to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
169 170
    if test -f "$from"; then
      # If $2 is an absolute path name, then just use that,
171 172 173 174
      # otherwise prepend '../'.
      case $to in
        [\\/]* | ?:[\\/]*) target=$to;;
        *) target=../$to;;
175 176
      esac

177 178 179 180 181 182 183 184
      # 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'`
Jason Merrill committed
185
      fi
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203

      # 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"
204 205 206 207
          mv -f "$target" "$realtarget"
        fi
      fi
    else
208 209 210 211
      # 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
212 213 214 215
        ret=1
      fi
    fi
  done
Jason Merrill committed
216 217 218 219 220 221
fi

# Remove the directory.
cd ..
rm -rf $dirname

222 223 224 225 226 227 228 229
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"
230 231
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
232
# End: