fea8707db3
MFC after: 1 month
234 lines
4.6 KiB
Bash
Executable File
234 lines
4.6 KiB
Bash
Executable File
#! /bin/sh
|
|
|
|
#
|
|
# runlex.sh
|
|
# Script to run Lex/Flex.
|
|
# First argument is the (quoted) name of the command; if it's null, that
|
|
# means that neither Flex nor Lex was found, so we report an error and
|
|
# quit.
|
|
#
|
|
|
|
#
|
|
# Get the name of the command to run, and then shift to get the arguments.
|
|
#
|
|
if [ $# -eq 0 ]
|
|
then
|
|
echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
|
|
exit 1
|
|
fi
|
|
LEX="$1"
|
|
shift
|
|
|
|
#
|
|
# Check whether we have Lex or Flex.
|
|
#
|
|
if [ -z "${LEX}" ]
|
|
then
|
|
echo "Neither lex nor flex was found" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
#
|
|
# Process the flags. We don't use getopt because we don't want to
|
|
# embed complete knowledge of what options are supported by Lex/Flex.
|
|
#
|
|
flags=""
|
|
outfile=lex.yy.c
|
|
while [ $# -ne 0 ]
|
|
do
|
|
case "$1" in
|
|
|
|
-o*)
|
|
#
|
|
# Set the output file name.
|
|
#
|
|
outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
|
|
;;
|
|
|
|
-*)
|
|
#
|
|
# Add this to the list of flags.
|
|
#
|
|
flags="$flags $1"
|
|
;;
|
|
|
|
--|*)
|
|
#
|
|
# End of flags.
|
|
#
|
|
break
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
#
|
|
# Is it Lex, or is it Flex?
|
|
#
|
|
if [ "${LEX}" = flex ]
|
|
then
|
|
#
|
|
# It's Flex.
|
|
#
|
|
have_flex=yes
|
|
|
|
#
|
|
# Does it support the --noFUNCTION options? If so, we pass
|
|
# --nounput, as at least some versions that support those
|
|
# options don't support disabling yyunput by defining
|
|
# YY_NO_UNPUT.
|
|
#
|
|
if flex --help | egrep noFUNCTION >/dev/null
|
|
then
|
|
flags="$flags --nounput"
|
|
|
|
#
|
|
# Does it support -R, for generating reentrant scanners?
|
|
# If so, we're not currently using that feature, but
|
|
# it'll generate some unused functions anyway - and there
|
|
# won't be any header file declaring them, so there'll be
|
|
# defined-but-not-declared warnings. Therefore, we use
|
|
# --noFUNCTION options to suppress generating those
|
|
# functions.
|
|
#
|
|
if flex --help | egrep reentrant >/dev/null
|
|
then
|
|
flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
|
|
fi
|
|
fi
|
|
else
|
|
#
|
|
# It's Lex.
|
|
#
|
|
have_flex=no
|
|
fi
|
|
|
|
#
|
|
# OK, run it.
|
|
# If it's lex, it doesn't support -o, so we just write to
|
|
# lex.yy.c and, if it succeeds, rename it to the right name,
|
|
# otherwise we remove lex.yy.c.
|
|
# If it's flex, it supports -o, so we use that - flex with -P doesn't
|
|
# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
|
|
#
|
|
if [ $have_flex = yes ]
|
|
then
|
|
${LEX} $flags -o"$outfile" "$@"
|
|
|
|
#
|
|
# Did it succeed?
|
|
#
|
|
status=$?
|
|
if [ $status -ne 0 ]
|
|
then
|
|
#
|
|
# No. Exit with the failing exit status.
|
|
#
|
|
exit $status
|
|
fi
|
|
|
|
#
|
|
# Flex has the annoying habit of stripping all but the last
|
|
# component of the "-o" flag argument and using that as the
|
|
# place to put the output. This gets in the way of building
|
|
# in a directory different from the source directory. Try
|
|
# to work around this.
|
|
#
|
|
# Is the outfile where we think it is?
|
|
#
|
|
outfile_base=`basename "$outfile"`
|
|
if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
|
|
then
|
|
#
|
|
# No, it's not, but it is in the current directory. Put it
|
|
# where it's supposed to be.
|
|
#
|
|
mv "$outfile_base" "$outfile"
|
|
|
|
#
|
|
# Did that succeed?
|
|
#
|
|
status=$?
|
|
if [ $status -ne 0 ]
|
|
then
|
|
#
|
|
# No. Exit with the failing exit status.
|
|
#
|
|
exit $status
|
|
fi
|
|
fi
|
|
else
|
|
${LEX} $flags "$@"
|
|
|
|
#
|
|
# Did it succeed?
|
|
#
|
|
status=$?
|
|
if [ $status -ne 0 ]
|
|
then
|
|
#
|
|
# No. Get rid of any lex.yy.c file we generated, and
|
|
# exit with the failing exit status.
|
|
#
|
|
rm -f lex.yy.c
|
|
exit $status
|
|
fi
|
|
|
|
#
|
|
# OK, rename lex.yy.c to the right output file.
|
|
#
|
|
mv lex.yy.c "$outfile"
|
|
|
|
#
|
|
# Did that succeed?
|
|
#
|
|
status=$?
|
|
if [ $status -ne 0 ]
|
|
then
|
|
#
|
|
# No. Get rid of any lex.yy.c file we generated, and
|
|
# exit with the failing exit status.
|
|
#
|
|
rm -f lex.yy.c
|
|
exit $status
|
|
fi
|
|
fi
|
|
|
|
#
|
|
# OK, now let's generate a header file declaring the relevant functions
|
|
# defined by the .c file; if the .c file is .../foo.c, the header file
|
|
# will be .../foo.h.
|
|
#
|
|
# This works around some other Flex suckage, wherein it doesn't declare
|
|
# the lex routine before defining it, causing compiler warnings.
|
|
# XXX - newer versions of Flex support --header-file=, to generate the
|
|
# appropriate header file. With those versions, we should use that option.
|
|
#
|
|
|
|
#
|
|
# Get the name of the prefix; scan the source files for a %option prefix
|
|
# line. We use the last one.
|
|
#
|
|
prefix=`sed -n 's/%option[ ][ ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
|
|
if [ ! -z "$prefix" ]
|
|
then
|
|
prefixline="#define yylex ${prefix}lex"
|
|
fi
|
|
|
|
#
|
|
# Construct the name of the header file.
|
|
#
|
|
header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
|
|
|
|
#
|
|
# Spew out the declaration.
|
|
#
|
|
cat <<EOF >$header_file
|
|
/* This is generated by runlex.sh. Do not edit it. */
|
|
$prefixline
|
|
#ifndef YY_DECL
|
|
#define YY_DECL int yylex(void)
|
|
#endif
|
|
YY_DECL;
|
|
EOF
|