#! /bin/sh
# Rename yy.* identifiers to avoid name clashes.  This file is part of Grecs.
# Copyright (C) 2011-2016 Sergey Poznyakoff
#
# Grecs 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, or (at your option)
# any later version.
#
# Grecs 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 Grecs.  If not, see <http://www.gnu.org/licenses/>.

# Usage: yyrename [-f "OUTFILE [OUTFILE...]"] COMMAND INFILE
# Makefile.am:
#  LEXCOMPILE = yyrename -f $(LEX_OUTPUT_ROOT).c \
#                        '$(LEX) $(LFLAGS) $(AM_LFLAGS)'
#  YACCCOMPILE = yyrename '$(YACC) $(YFLAGS) $(AM_YFLAGS)'
#
# This script runs COMMAND with INFILE as its argument and scans
# OUTFILEs for identifiers starting with 'yy'.  It then renames these
# identifiers by replacing 'yy' with the selected prefix.
#
# The prefix is looked up in the file yytrans, located in the INFILE's
# directory.  If this file does not exist, the prefix is constructed
# by concatenating the string 'grecs_' and the ``root name''.  The root
# name is built by removing '-lex.l' or '-gram.y' from the base name.
# If the latter does not end in any of these, the root name
# is constructed by removing the suffix from the base name.
#
# The yytrans file is a line-oriented lookup table.  Empty lines are
# ignored, usual UNIX comment lines are honored.  The remaining lines
# shall consist of two words separated by any amount of whitespace.
# The first word is a look-up key, the second one provides a translation
# (yy replacement) for that key.
#
# Two look-ups are tried: first the base name and then the root name.
# If both result in a non-empty replacement, the former is preferred
# over the latter.
#
# The -f option supplies a list of output file names generated by COMMAND.
# If not supplied, the following defaults are used: y.tab.c and y.tab.h, if
# INFILE ends in '.y', and yy.lex.c, if it ends in '.l'.  If INFILE does not
# end in any of these suffixes, error is reported.
#
# BUGS: Any occurrence of 'yy' is replaced, not only 'yy' prefixes.
#
case $1 in
-f) files=$2
    shift
    shift
esac

if test $# -ne 2; then
  echo >&2 "usage: yyrename [-f "OUTFILE [OUTFILE...]"] COMMAND INFILE"
  exit 1
fi

base=`expr "$2" : '.*/\(.*\)\.[ly]'`
dir=`dirname "$2"`
case $2 in
*.y) test -z "$files" && files="y.tab.c y.tab.h"
     root=`expr "$2" : '.*/\(.*\)-gram\.y'`;;
*.l) test -z "$files" && files=lex.yy.c
     root=`expr "$2" : '.*/\(.*\)-lex\.l'`;;
*)   if test -z "$files"; then
       echo >&2 "$0: suffix unknown, files must be given (use -f)"
       exit 1
     fi
     root=$base
esac

if test -f $dir/yytrans; then
  pfx=`awk '
{ sub(/#.*$/,"") }
NF == 2 && $1=="'$base'" { exact=$2 }
NF == 2 && $1=="'$root'" { root=$2 }
{ next }
END { print exact ? exact : root ? root : "" }' $dir/yytrans`
else
  pfx=
fi
if test -z "$pfx"; then
  pfx=grecs_`echo $root | tr .- __`
fi

eval $* || exit $?

for file in $files
do
  mv $file ${file}.tmp
  sed -e '/^#line/b' -e '/^#  *[0-9]/b' -e "s/yy/$pfx/g" ${file}.tmp > $file
  rm ${file}.tmp
done
