COMP: support m4 include directories for wrap-lemon

Set the m4 -I include accordingly to have the folllowing:
  - the directory of the parser.
  - include/ in the top-level source tree of the current target
    (eg, src/finiteVolume/include-m4/ when compiling libfiniteVolume)
  - include/ from OpenFOAM

Additional -dry-run option for makeParser, wrap-lemon for expanding m4
only.

Extend m4 wrapping support to include bison as well.
This commit is contained in:
Mark Olesen
2019-12-03 12:34:24 +01:00
parent 4030ed4543
commit 3a816006dc
5 changed files with 434 additions and 122 deletions

View File

@ -1,4 +1,4 @@
SUFFIXES += .Y .y .yy SUFFIXES += .Y .y .yy .yy-m4
ytoo = $E $(call QUIET_MESSAGE,bison,$(<F)) \ ytoo = $E $(call QUIET_MESSAGE,bison,$(<F)) \
$(WM_SCHEDULER) bison -v -d -y $< $(AND) \ $(WM_SCHEDULER) bison -v -d -y $< $(AND) \
@ -14,5 +14,13 @@ Ytoo = $E $(call QUIET_MESSAGE,bison,$(<F)) \
yytoo = $E $(call QUIET_MESSAGE,bison,$(<F)) \ yytoo = $E $(call QUIET_MESSAGE,bison,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-bison \ $(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-bison \
-input=$< -output=$(@D)/$(*F).tab.cc -v -d $(AND) \ -output=$(@D)/$(*F).tab.cc -v -d $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).tab.cc -o $@ $(CC) $(c++FLAGS) -c $(@D)/$(*F).tab.cc -o $@
# Retains intermediate m4-filtered files (-no-tmp to suppress)
yy-m4too = $E $(call QUIET_MESSAGE,bison-m4,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-bison \
-output=$(@D)/$(*F).tab.cc -v -d $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).tab.cc -o $@
#------------------------------------------------------------------------------

View File

@ -8,10 +8,9 @@ lyytoo = $E $(call QUIET_MESSAGE,lemon,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -d$(@D) -ecc $< $(AND) \ $(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -d$(@D) -ecc $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@ $(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@
# Retain intermediate files (-with-debug) to help when something goes wrong, # Retains intermediate m4-filtered files (-no-tmp to suppress)
# and to verify that the generated grammar looks correct.
lyy-m4too = $E $(call QUIET_MESSAGE,lemon-m4,$(<F)) \ lyy-m4too = $E $(call QUIET_MESSAGE,lemon-m4,$(<F)) \
$(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -with-debug -d$(@D) -ecc $< $(AND) \ $(WM_SCHEDULER) $(WM_SCRIPTS)/wrap-lemon -d$(@D) -ecc $< $(AND) \
$(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@ $(CC) $(c++FLAGS) -c $(@D)/$(*F).cc -o $@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -28,11 +28,10 @@ options:
-prefix=NAME Common prefix for parser and scanner -prefix=NAME Common prefix for parser and scanner
-parser=FILE Generate lemon parser header -parser=FILE Generate lemon parser header
-scanner=FILE Generate ragel scanner code -scanner=FILE Generate ragel scanner code
-parser Use 'LemonParser.lyy' for non-prefixed parser name -code Generate parser code, not header
-parser-m4 Use 'LemonParser.lyy-m4' for non-prefixed parser name -header Generate parser header, not code (default)
-scanner Use 'Scanner.rl' for non-prefixed scanner name -dry-run Process m4 only (output on stdout)
-code Generate lemon parser code -no-tmp Do not retain temporary m4 processed files
-with-debug Retain intermediate files (eg, m4 output)
-remove Remove generated code -remove Remove generated code
-h, -help Print the usage -h, -help Print the usage
@ -46,7 +45,7 @@ USAGE
# Parse arguments and options # Parse arguments and options
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
unset prefix parser scanner optCode optDebug optRemove unset prefix parser scanner optHeader optDryRun optRemoveFile optRemoveTmp
while [ "$#" -gt 0 ] while [ "$#" -gt 0 ]
do do
case "$1" in case "$1" in
@ -56,12 +55,11 @@ do
(-parser=*) parser="${1#*=}" ;; (-parser=*) parser="${1#*=}" ;;
(-scanner=*) scanner="${1#*=}" ;; (-scanner=*) scanner="${1#*=}" ;;
(-parser) parser=LemonParser.lyy ;; (-code) optHeader=false ;;
(-parser-m4) parser=LemonParser.lyy-m4 ;; (-head*) optHeader=true ;;
(-scanner) scanner=Scanner.rl ;; (-dry-run) optDryRun="-dry-run" ;; # Pass verbatim to wrapper
(-code) optCode=true ;; (-no-tmp) optRemoveTmp="-no-tmp" ;; # Pass verbatim to wrapper
(-with-debug) optDebug=true ;; (-remove) optRemoveFile=true ;;
(-remove) optRemove=true ;;
(*) break ;; (*) break ;;
esac esac
@ -72,11 +70,11 @@ done
# Remove file, with feedback. $1 = file, $2 = message # Remove file, with feedback. $1 = file, $2 = message
removeFile() { removeFile() {
if test -f "$1" && rm -f "$1" 2>/dev/null if test -f "$1" && rm -f "$1"
then then
echo "Removed generated $2 file" echo "Removed generated $2 file" 1>&2
else else
echo "No generated $2 file to remove" echo "No generated $2 file to remove" 1>&2
fi fi
} }
@ -86,44 +84,100 @@ case "$scanner" in
input="${prefix}${scanner}" input="${prefix}${scanner}"
output="${prefix}${scanner%.*}.cc" output="${prefix}${scanner%.*}.cc"
if [ "$optRemove" = true ] if [ "$optRemoveFile" = true ]
then then
removeFile "$output" "ragel scanner" removeFile "$output" "ragel scanner"
elif command -v ragel >/dev/null elif command -v ragel >/dev/null
then then
echo "Generating ragel scanner" echo "Generating ragel scanner" 1>&2
ragel -G2 -o "$output" "$input" ragel -G2 -o "$output" "$input"
else else
echo "No ragel, leaving scanner intact" echo "No ragel, leaving scanner intact" 1>&2
fi fi
echo echo
;; ;;
esac esac
# The output code extension is .c (default) or .cc, but also possibly .C
# - mapping here consistent with wmake/rules/General/{bison,lemon}
extCode=c
case "$parser" in case "$parser" in
(*.ly | *.lyy | *.ly*m4) (*.Y) extCode=C ;;
extCode=cc (*.yy | *.yy-m4 | *.lyy | *.lyy-m4) extCode=cc ;;
esac
# Detect m4, any additional messages (eg, using m4 etc)
unset usingM4 message
case "$parser" in
(*m4)
usingM4=true
message=", using m4 filtering"
;;
esac
case "$parser" in
(*.ly | *.lyy | *.ly-m4 | *.lyy-m4) # Lemon
input="${prefix}${parser}" input="${prefix}${parser}"
output="${parser%.*}.h" output="${parser%.*}.h"
# Pass -with-debug to wrap-lemon if [ "$optRemoveFile" = true ]
[ -n "$optDebug" ] && optDebug="-with-debug"
# Additional message (eg, using m4 etc)
unset message
case "$parser" in (*m4) message=", using m4 filtering" ;; esac
if [ "$optRemove" = true ]
then then
removeFile "$output" "lemon header" removeFile "$output" "lemon header"
elif [ "$optCode" = true ]
then
echo "Generating lemon parser code ($extCode)$message"
"${WM_PROJECT_DIR:?}/wmake/scripts/wrap-lemon" $optDebug -e"$extCode" -s "$input"
else else
echo "Generating lemon parser header$message"
"${WM_PROJECT_DIR:?}/wmake/scripts/wrap-lemon" $optDebug -header -s "$input" # Touch parser file time when using m4.
# This ensures that we have a better correspondence between
# generated and compiled versions since changes to the m4 macros
# may otherwise not be noticed.
if [ "$usingM4" = true ] && [ -f "$input" ]
then
message="$message (touching input file time)"
touch "$input"
fi
if [ "$optHeader" = false ]
then
echo "Generating lemon parser code ($extCode)$message" 1>&2
"${WM_PROJECT_DIR:?}/wmake/scripts/wrap-lemon" \
$optDryRun $optRemoveTmp -e"$extCode" -p -s "$input"
else
echo "Generating lemon parser header$message" 1>&2
"${WM_PROJECT_DIR:?}/wmake/scripts/wrap-lemon" \
$optDryRun $optRemoveTmp -header -p -s "$input"
fi
fi
echo
;;
(*.[Yy] | *.yy | *.y-m4 | *.yy-m4) # Bison
input="${prefix}${parser}"
if [ "$optRemoveFile" = true ]
then
echo "File removal not yet supported for bison" 1>&2
else
# Touch parser file time when using m4.
# This ensures that we have a better correspondence between
# generated and compiled versions since changes to the m4 macros
# may otherwise not be noticed.
if [ "$usingM4" = true ] && [ -f "$input" ]
then
message="$message (touching input file time)"
touch "$input"
fi
if [ -n "$optDryRun" ]
then
echo "Generating bison parser code ($extCode)$message" 1>&2
"${WM_PROJECT_DIR:?}/wmake/scripts/wrap-bison" \
$optDryRun $optRemoveTmp "$input"
else
echo "Currently only -dry-run is supported for bison" 1>&2
fi
fi fi
echo echo
;; ;;

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# ========= | # ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
@ -14,7 +14,7 @@
# wrap-bison # wrap-bison
# #
# Usage # Usage
# wrap-bison -input=*.yy -output=*.cc [bison-options] # wrap-bison -output=*.cc [bison options/args]
# #
# Description # Description
# A wrapper to handle renaming/relocation of bison-generated files. # A wrapper to handle renaming/relocation of bison-generated files.
@ -41,6 +41,13 @@
# - place generated *.hh files directly into lnInclude/ # - place generated *.hh files directly into lnInclude/
# - place generated *.cc file into the build/ directory # - place generated *.cc file into the build/ directory
# #
# When called with m4 wrapping, it sets the m4 -I include to have
# the following:
# - the directory of the parser.
# - include/ in the top-level source tree of the current target
# (eg, src/finiteVolume/include/ when compiling libfiniteVolume)
# - include/ from OpenFOAM
#
# Note # Note
# General idea lifted from swak # General idea lifted from swak
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@ -52,8 +59,9 @@ usage() {
Usage: ${0##*/} [options] [bison args/options] Usage: ${0##*/} [options] [bison args/options]
options: options:
-input=NAME Perform the renaming actions -dry-run Process m4 only (output on stdout)
-output=NAME Perform the renaming actions -no-tmp Do not retain temporary m4 processed files
-output=NAME Request renaming actions
-h, -help Print the usage -h, -help Print the usage
A bison wrapper with renaming of skeleton files A bison wrapper with renaming of skeleton files
@ -62,7 +70,7 @@ USAGE
exit 1 exit 1
} }
# File extensions used # File extensions used (may need adjustment)
extCode="cc" extCode="cc"
extHead="hh" extHead="hh"
@ -70,71 +78,151 @@ extHead="hh"
# Parse arguments and options # Parse arguments and options
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# wrap-bison -input=... -output=... # wrap-bison -output=...
unset inputFile outputFile unset outputFile optDryRun optRemoveTmp m4Flags
while [ "$#" -gt 0 ] while [ "$#" -gt 0 ]
do do
case "$1" in case "$1" in
(-h | -help*) usage ;; (-h | -help*) usage ;;
(-input=*) inputFile="${1#*=}" ;; (-dry-run) optDryRun=true ;;
(-output=*) outputFile="${1#*=}" ;; (-no-tmp) optRemoveTmp=true ;;
(-output=*) outputFile="${1#*=}" ;;
(*) break ;; (*) break ;;
esac esac
shift shift
done done
# No rename action supplied? Juet execute bison directly. #------------------------------------------------------------------------------
if [ -z "$inputFile" ] # Additional m4Flags (for includes etc)
#
# $1 : path-qualified name of the parser
#
# Set includes accordingly to
# - the directory containing the parser
# - include/ in the top-level source tree of the current target
# - include/ from OpenFOAM
defineM4Flags()
{
# Always include the directory containing the parser file
m4Flags="$m4Flags${m4Flags:+ }-I$(dirname ${1:-.})"
local proj="$WM_PROJECT_DIR/src/${WM_PROJECT:-OpenFOAM}"
local curr="$PWD"
# Called from the Makefile (PWD contains the parser source)
# or from elsewhere (eg, createCode)?
if [ ! -f "$curr/Make/options" ]
then
# No Make/options (eg createCode) - discover with "wmake -pwd"
curr="$(wmake -pwd 2>/dev/null)"
fi
# Avoid examining twice
[ "$curr" != "$proj" ] || unset curr
if [ -n "$curr" ] && [ -d "$curr/include" ]
then
m4Flags="$m4Flags -I$curr/include"
fi
if [ -n "$proj" ] && [ -d "$proj/include" ]
then
m4Flags="$m4Flags -I$proj/include"
fi
}
#------------------------------------------------------------------------------
# Get some information based on the bison options
# The last argument is the input file
unset parser
findBisonOptions()
{
parser="${@: -1}"
}
findBisonOptions "$@"
unset parserFlags extParser usingM4
# Detect m4 use (defines parser macro too) and get extension without m4
case "$parser" in
(*.*m4)
usingM4=true
parserFlags="-Dm4"
defineM4Flags "$parser"
extParser=".${parser##*.}" # The extension (with dot)
extParser="${extParser%m4}" # Without trailing m4
extParser="${extParser/%[-_]/}" # Without - or _ separators
;;
esac
# No rename action requested? Just execute bison directly.
if [ -z "$outputFile" ] && [ "$usingM4" != true ]
then then
bison $* bison $*
exit $? exit $?
fi fi
#------------------------------------------------------------------------------
# Renaming requested
# Need lnInclude/ directory exitCode=0 # No failures
[ -d lnInclude ] || mkdir lnInclude 2>/dev/null || {
#------------------------------------------------------------------------------
# Dry-run
if [ "$optDryRun" = true ]
then
if [ "$usingM4" = true ]
then
echo "m4 flags: $m4Flags" 1>&2
m4 $m4Flags "$parser"; exitCode=$?
else
echo "Nothing to do - not using m4" 2>/dev/null
fi
[ "$exitCode" -eq 0 ] || echo "m4 failed" 2>/dev/null
exit "$exitCode" # Done
fi
#------------------------------------------------------------------------------
# Called from the Makefile (PWD contains the parser source)
# or from elsewhere (eg, createCode)?
curr="$PWD"
if [ ! -f "$curr/Make/options" ]
then
# No Make/options (eg createCode) - discover with "wmake -pwd"
curr="$(wmake -pwd 2>/dev/null)"
fi
# Will most likely need a lnInclude/ directory
[ -d "$curr/lnInclude" ] || mkdir "$curr/lnInclude" 2>/dev/null || {
echo "Cannot continue without an lnInclude directory" 1>&2 echo "Cannot continue without an lnInclude directory" 1>&2
pwd -L (cd "$curr" && pwd -L)
exit 1 exit 1
} }
# Get a baseName (stem) for the output # Get a baseName (stem) for the output
baseName="${inputFile##*/}" baseName="${parser##*/}"
baseName="${baseName%.*}" baseName="${baseName%.*}"
# Fallback for output # Fallback for output
if [ -z "$outputFile" ] if [ -z "$outputFile" ]
then then
outputFile="$(dirname ${inputFile})/${baseName}.$extCode" outputFile="$(dirname ${parser})/${baseName}.$extCode"
fi fi
# Execute in a temporary directory (keeps files together) outputDir="$(dirname $outputFile)"
cwd="$(pwd -L)"
tmpDir="Make/bisonWrapper-$baseName"
rm -rf "$tmpDir" 2>/dev/null
mkdir "$tmpDir" 2>/dev/null
cd "$tmpDir" || exit #------------------------------------------------------------------------------
rc=1
# DO WE WANT THIS?
# trap 'cd $cwd; rm -f $tmpDir 2>/dev/null; exit $rc' EXIT TERM INT
bison "$@" "../../$inputFile"
rc=$?
cd "../.." || exit
if [ "$rc" -ne 0 ]
then
rm -rf "$tmpDir" 2>/dev/null
exit "$rc" # Exit with bison return code
fi
# Renaming, filter code
# Check for/remove .tab. tag? # Check for/remove .tab. tag?
unset untabFilter unset untabFilter
@ -146,7 +234,7 @@ hasTab="${hasTab%.*}"
if [ "$hasTab" = "${hasTab%.tab}" ] if [ "$hasTab" = "${hasTab%.tab}" ]
then then
untab='/^#.*".*\.tab\./s/\.tab\././' untabFilter='/^#.*".*\.tab\./s/\.tab\././'
fi fi
# Filter include names to generate new files # Filter include names to generate new files
@ -160,12 +248,80 @@ filterRename()
-e '/include *"location/s/"/"'"${baseName}."'/;' \ -e '/include *"location/s/"/"'"${baseName}."'/;' \
-e '/include *"position/s/"/"'"${baseName}."'/;' \ -e '/include *"position/s/"/"'"${baseName}."'/;' \
-e '/include *"stack/s/"/"'"${baseName}."'/;' \ -e '/include *"stack/s/"/"'"${baseName}."'/;' \
-e "$untab;" \ -e "$untabFilter;" \
"$1" >| "$2" "$1" >| "$2"
fi fi
} }
#------------------------------------------------------------------------------
# This gets slightly complicated with temporary files/dirs.
#
# - a tmp FILE for the m4-filtered parser (optional).
# - a tmp DIR for storing the bison generated files so that we can
# properly edit and rename them.
unset tmpFile tmpDir parserInput
if [ "$usingM4" = true ]
then
# Drop last argument (the parser input file)
set -- "${@:1:${#}-1}"
# Filter via m4
# The outputDir is always defined. Make absolute
tmpFile="$(cd ${outputDir:?} && pwd -L)/${parser##*/}"
tmpFile="${tmpFile%.*}$extParser" # Eg, from .lyy-m4 -> .lyy
# We may want this:
# trap 'rm -f $tmpFile 2>/dev/null; exit $exitCode' EXIT TERM INT
if m4 $m4Flags "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
then
parserInput="$tmpFile"
exitCode=0
else
echo "m4 stage failed on $parser" 2>/dev/null
rm -f "$tmpFile" 2>/dev/null
exit 1
fi
else
# No special (m4) handling
# Make parser input name absolute
parserInput="$(cd $(dirname $parser) && pwd -L)/${parser##*/}"
fi
#------------
# Execute bison in a temporary directory to keeps all files together
cwd="$(pwd -L)"
tmpDir="Make/wrap-bison-$baseName"
rm -rf "$tmpDir" 2>/dev/null
mkdir "$tmpDir" 2>/dev/null
# We may want this:
# trap 'cd $cwd; rm -f $tmpDir 2>/dev/null; exit $exitCode' EXIT TERM INT
cd "$tmpDir" || exit
# Execute bison
bison "$@" "$parserInput"
exitCode=$?
cd "../.." || exit
if [ "$exitCode" -ne 0 ]
then
rm -rf "$tmpDir" 2>/dev/null
exit "$exitCode" # Exit with bison return code
fi
#------------
# Boilerplate -> lnInclude/ directory with new name # Boilerplate -> lnInclude/ directory with new name
for file in position location stack for file in position location stack
do do
@ -185,7 +341,17 @@ filterRename \
"${outputFile}" "${outputFile}"
if [ -n "$tmpFile" ]
then
if [ -n "$optRemoveTmp" ]
then
rm -f "$tmpFile" 2>/dev/null
else
echo "Retaining intermediate: $tmpFile" 2>/dev/null
fi
fi
rm -rf "$tmpDir" 2>/dev/null rm -rf "$tmpDir" 2>/dev/null
exit "$rc" # Exit with bison return code exit "$exitCode" # Exit with bison return code
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -14,12 +14,19 @@
# wrap-lemon # wrap-lemon
# #
# Usage # Usage
# wrap-lemon [options] [lemon args/options] # wrap-lemon [options] [lemon options/args]
# #
# Description # Description
# A wrapper to use lemon compiled with OpenFOAM with the appropriate # A wrapper to use lemon compiled with OpenFOAM with the appropriate
# parser template. # parser template.
# #
# When called with m4 wrapping, it sets the m4 -I include to have
# the following:
# - the directory of the parser.
# - include/ in the top-level source tree of the current target
# (eg, src/finiteVolume/include/ when compiling libfiniteVolume)
# - include/ from OpenFOAM
#
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
binDir="${WMAKE_BIN:-$WM_PROJECT_DIR/wmake/platforms/$WM_ARCH$WM_COMPILER}" binDir="${WMAKE_BIN:-$WM_PROJECT_DIR/wmake/platforms/$WM_ARCH$WM_COMPILER}"
@ -38,7 +45,8 @@ Usage: ${0##*/} [options] [lemon args/options]
options: options:
-header Generate header only, suppressing other output -header Generate header only, suppressing other output
-with-debug Retain intermediate files (eg, m4 output) -dry-run Process m4 only (output on stdout)
-no-tmp Do not retain temporary m4 processed files
-h, -help Print the usage -h, -help Print the usage
A lemon wrapper using predefined executable and skeleton locations. A lemon wrapper using predefined executable and skeleton locations.
@ -54,21 +62,65 @@ USAGE
# Parse arguments and options # Parse arguments and options
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# wrap-lemon -header # Eg, wrap-lemon -header
unset optHeader optDebug unset optHeader optDryRun optRemoveTmp m4Flags
while [ "$#" -gt 0 ] while [ "$#" -gt 0 ]
do do
case "$1" in case "$1" in
(-h | -help*) usage ;; (-h | -help*) usage ;;
(-head*) optHeader=true ;; (-head*) optHeader=true ;;
(-with-debug) optDebug=true ;; (-dry-run) optDryRun=true ;;
(-no-tmp) optRemoveTmp=true ;;
(*) break ;; (*) break ;;
esac esac
shift shift
done done
#------------------------------------------------------------------------------
# Additional m4Flags (for includes etc)
#
# $1 : path-qualified name of the parser
#
# Set includes accordingly to
# - the directory containing the parser
# - include/ in the top-level source tree of the current target
# - include/ from OpenFOAM
defineM4Flags()
{
# Always include the directory containing the parser file
m4Flags="$m4Flags${m4Flags:+ }-I$(dirname ${1:-.})"
local proj="$WM_PROJECT_DIR/src/${WM_PROJECT:-OpenFOAM}"
local curr="$PWD"
# Called from the Makefile (PWD contains the parser source)
# or from elsewhere (eg, createCode)?
if [ ! -f "$curr/Make/options" ]
then
# No Make/options (eg createCode) - discover with "wmake -pwd"
curr="$(wmake -pwd 2>/dev/null)"
fi
# Avoid examining twice
[ "$curr" != "$proj" ] || unset curr
if [ -n "$curr" ] && [ -d "$curr/include" ]
then
m4Flags="$m4Flags -I$curr/include"
fi
if [ -n "$proj" ] && [ -d "$proj/include" ]
then
m4Flags="$m4Flags -I$proj/include"
fi
}
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Get some information based on the lemon options # Get some information based on the lemon options
# * '-dXX' for the output directory # * '-dXX' for the output directory
@ -95,19 +147,43 @@ findLemonOptions()
findLemonOptions "$@" findLemonOptions "$@"
# Detect m4 use (defines lemon macro too) and get extension without m4 unset parserFlags extParser usingM4
unset extLemon usingMacros
# Detect m4 use (defines parser macro too) and get extension without m4
case "$parser" in case "$parser" in
(*.*m4) (*.*m4)
extLemon=".${parser##*.}" # The extension (with dot) usingM4=true
extLemon="${extLemon%m4}" # Without trailing m4 parserFlags="-Dm4"
extLemon="${extLemon/%[-_]/}" # Without - or _ separators defineM4Flags "$parser"
usingMacros="-Dm4"
extParser=".${parser##*.}" # The extension (with dot)
extParser="${extParser%m4}" # Without trailing m4
extParser="${extParser/%[-_]/}" # Without - or _ separators
;; ;;
esac esac
rc=1 # Assume some failure exitCode=0 # No failures
#------------------------------------------------------------------------------
# Dry-run
if [ "$optDryRun" = true ]
then
if [ "$usingM4" = true ]
then
echo "m4 flags: $m4Flags" 1>&2
m4 $m4Flags "$parser"; exitCode=$?
else
echo "Nothing to do - not using m4" 2>/dev/null
fi
[ "$exitCode" -eq 0 ] || echo "m4 failed" 2>/dev/null
exit "$exitCode" # Done
fi
#------------------------------------------------------------------------------
unset tmpFile tmpDir
if [ -n "$optHeader" ] if [ -n "$optHeader" ]
then then
@ -119,41 +195,49 @@ then
rm -rf "$tmpDir" 2>/dev/null rm -rf "$tmpDir" 2>/dev/null
mkdir "$tmpDir" 2>/dev/null mkdir "$tmpDir" 2>/dev/null
if [ -n "$usingMacros" ] # We may want this:
# trap 'rm -f $tmpDir 2>/dev/null; exit $exitCode' EXIT TERM INT
if [ "$usingM4" = true ]
then then
# Using m4 - redirect to a temporary file # Using m4 - redirect to a temporary file
tmpFile="$tmpDir/${parser##*/}" tmpFile="$tmpDir/${parser##*/}"
tmpFile="${tmpFile%.*}$extLemon" # Eg, from .lyy-m4 -> .lyy tmpFile="${tmpFile%.*}$extParser" # Eg, from .lyy-m4 -> .lyy
if m4 "$parser" > "$tmpFile" && [ -f "$tmpFile" ] if m4 $m4Flags "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
then then
parser="$tmpFile" parser="$tmpFile"
else else
echo "m4 stage failed on $parser" 2>/dev/null echo "m4 stage failed on $parser" 2>/dev/null
exitCode=1
fi fi
fi fi
# DO WE WANT THIS? if [ "$exitCode" -eq 0 ]
# trap 'rm -f $tmpDir 2>/dev/null; exit $rc' EXIT TERM INT then
"$lemon" "$skel" "-d$tmpDir" "$@" $usingMacros "$parser" "$lemon" "$skel" "-d$tmpDir" "$@" $parserFlags "$parser"
rc=$? exitCode=$?
fi
for src in "$tmpDir"/*.h if [ "$exitCode" -eq 0 ]
do then
dst="${src##*/}" for src in "$tmpDir"/*.h
if [ -f "$src" ] do
then dst="${src##*/}"
if ! cmp "$src" "$dst" 2>/dev/null if [ -f "$src" ]
then then
mv "$src" "$dst" if ! cmp "$src" "$dst" 2>/dev/null
echo "Updating $dst" 1>&2 then
mv "$src" "$dst"
echo "Updating $dst" 1>&2
fi
fi fi
fi done
done fi
rm -rf "$tmpDir" 2>/dev/null rm -rf "$tmpDir" 2>/dev/null
elif [ -n "$usingMacros" ] elif [ "$usingM4" = true ]
then then
# Drop last argument (the parser input file) # Drop last argument (the parser input file)
set -- "${@:1:${#}-1}" set -- "${@:1:${#}-1}"
@ -165,24 +249,25 @@ then
else else
tmpFile="${parser}" tmpFile="${parser}"
fi fi
tmpFile="${tmpFile%.*}$extLemon" # Eg, from .lyy-m4 -> .lyy tmpFile="${tmpFile%.*}$extParser" # Eg, from .lyy-m4 -> .lyy
# DO WE WANT THIS? # We may want this:
# trap 'rm -f $tmpFile 2>/dev/null; exit $rc' EXIT TERM INT # trap 'rm -f $tmpFile 2>/dev/null; exit $exitCode' EXIT TERM INT
if m4 "$parser" > "$tmpFile" && [ -f "$tmpFile" ] if m4 $m4Flags "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
then then
"$lemon" "$skel" "$@" $usingMacros "$tmpFile" "$lemon" "$skel" "$@" $parserFlags "$tmpFile"
rc=$? exitCode=$?
else else
echo "m4 stage failed on $parser" 2>/dev/null echo "m4 stage failed on $parser" 2>/dev/null
exitCode=1
fi fi
if [ -n "$optDebug" ] if [ -n "$optRemoveTmp" ]
then then
echo "Retaining intermediate: $tmpFile" 2>/dev/null
else
rm -f "$tmpFile" 2>/dev/null rm -f "$tmpFile" 2>/dev/null
else
echo "Retaining intermediate: $tmpFile" 2>/dev/null
fi fi
else else
@ -190,10 +275,10 @@ else
# No special handling # No special handling
"$lemon" "$skel" "$@" "$lemon" "$skel" "$@"
rc=$? exitCode=$?
fi fi
exit "$rc" # Exit with lemon return code exit "$exitCode" # Exit with lemon return code
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------