295 lines
7.5 KiB
Bash
Executable File
295 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
|
#------------------------------------------------------------------------------
|
|
# ========= |
|
|
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
# \\ / O peration |
|
|
# \\ / A nd | www.openfoam.com
|
|
# \\/ M anipulation |
|
|
#-------------------------------------------------------------------------------
|
|
# Copyright (C) 2019-2021 OpenCFD Ltd.
|
|
#-------------------------------------------------------------------------------
|
|
# License
|
|
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
|
#
|
|
# Script
|
|
# wrap-lemon
|
|
#
|
|
# Usage
|
|
# wrap-lemon [options] [lemon options/args]
|
|
#
|
|
# Description
|
|
# A wrapper to use lemon compiled with OpenFOAM with the appropriate
|
|
# 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/platforms/tools/$WM_ARCH$WM_COMPILER}"
|
|
etcDir="${WM_DIR:-$WM_PROJECT_DIR/wmake}/etc"
|
|
|
|
# Executable and skeleton locations
|
|
lemon="${binDir}/lemon"
|
|
skel="-T${etcDir}/lempar.c"
|
|
|
|
printHelp() {
|
|
cat<<USAGE
|
|
|
|
Usage: ${0##*/} [options] [lemon args/options]
|
|
|
|
options:
|
|
-header Generate header only, suppressing other output
|
|
-dry-run Process m4 only (output on stdout)
|
|
-grammar Output grammar tables (stdout)
|
|
-no-tmp Do not retain temporary m4 processed files
|
|
-h, -help Print the usage
|
|
|
|
A lemon wrapper using predefined executable and skeleton locations.
|
|
Files ending with 'm4' (eg, .lyym4, .lyy-m4) will be filtered through
|
|
the m4(1) macro processor and lemon will be called with 'm4' as a macro
|
|
definition, which can be used in conditions (%ifdef m4, %ifndef m4)
|
|
|
|
USAGE
|
|
exit 0 # Clean exit
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Parse arguments and options
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Eg, wrap-lemon -header
|
|
unset optDryRun optHeader optGrammar optRemoveTmp m4Flags
|
|
while [ "$#" -gt 0 ]
|
|
do
|
|
case "$1" in
|
|
(-h | -help*) printHelp ;;
|
|
|
|
(-dry-run) optDryRun=true ;;
|
|
(-head*) optHeader=true ;;
|
|
(-gram*) optGrammar=true ;;
|
|
(-no-tmp) optRemoveTmp=true ;;
|
|
|
|
(*) break ;;
|
|
esac
|
|
shift
|
|
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
|
|
# * '-dXX' for the output directory
|
|
# * '-eXX' for the output extension
|
|
# The last argument is the input file
|
|
|
|
unset tmpDir tmpFile outputDir parser extCode
|
|
findLemonOptions()
|
|
{
|
|
while [ "$#" -gt 1 ]
|
|
do
|
|
case "$1" in
|
|
(-d*) outputDir="${1#-d}" ;;
|
|
(-e*) extCode="${1#-e}" ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ "$#" -eq 1 ]
|
|
then
|
|
parser="$1"
|
|
fi
|
|
}
|
|
|
|
findLemonOptions "$@"
|
|
|
|
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
|
|
|
|
if [ -n "$optGrammar" ]
|
|
then
|
|
parserFlags="${parserFlags}${parserFlags:+ }-g"
|
|
fi
|
|
|
|
|
|
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" ]
|
|
then
|
|
## echo "${0##*/} : generate header" 1>&2
|
|
|
|
# Drop last argument (the parser input file)
|
|
set -- "${@:1:${#}-1}"
|
|
|
|
# Header only, which means we create a temp directory for the output
|
|
tmpDir="lemonWrapper-$$"
|
|
rm -rf "$tmpDir" 2>/dev/null
|
|
mkdir "$tmpDir" 2>/dev/null
|
|
|
|
trap 'rm -rf $tmpDir; exit $exitCode' EXIT TERM INT
|
|
|
|
if [ "$usingM4" = true ]
|
|
then
|
|
# Using m4 - redirect to a temporary file
|
|
tmpFile="$tmpDir/${parser##*/}"
|
|
tmpFile="${tmpFile%.*}$extParser" # Eg, from .lyy-m4 -> .lyy
|
|
|
|
if m4 $m4Flags "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
|
|
then
|
|
parser="$tmpFile"
|
|
else
|
|
echo "m4 stage failed on $parser" 2>/dev/null
|
|
exitCode=1
|
|
fi
|
|
fi
|
|
|
|
if [ "$exitCode" -eq 0 ]
|
|
then
|
|
"$lemon" "$skel" "-d$tmpDir" "$@" $parserFlags "$parser"
|
|
exitCode=$?
|
|
fi
|
|
|
|
if [ "$exitCode" -eq 0 ]
|
|
then
|
|
for src in "$tmpDir"/*.h
|
|
do
|
|
dst="${src##*/}"
|
|
if [ -f "$src" ]
|
|
then
|
|
if ! cmp "$src" "$dst" 2>/dev/null
|
|
then
|
|
mv "$src" "$dst"
|
|
echo "Updating $dst" 1>&2
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
|
|
elif [ "$usingM4" = true ]
|
|
then
|
|
## echo "${0##*/} : generate code (with m4 filtering)" 1>&2
|
|
|
|
# Drop last argument (the parser input file)
|
|
set -- "${@:1:${#}-1}"
|
|
|
|
# Filter via m4
|
|
if [ -n "$outputDir" ]
|
|
then
|
|
tmpFile="$outputDir/${parser##*/}"
|
|
else
|
|
tmpFile="${parser}"
|
|
fi
|
|
tmpFile="${tmpFile%.*}$extParser" # Eg, from .lyy-m4 -> .lyy
|
|
|
|
if [ -n "$optRemoveTmp" ]
|
|
then
|
|
trap 'rm -f $tmpFile; exit $exitCode' EXIT TERM INT
|
|
fi
|
|
|
|
if m4 $m4Flags "$parser" > "$tmpFile" && [ -f "$tmpFile" ]
|
|
then
|
|
"$lemon" "$skel" "$@" $parserFlags "$tmpFile"
|
|
exitCode=$?
|
|
else
|
|
echo "m4 stage failed on $parser" 2>/dev/null
|
|
exitCode=1
|
|
fi
|
|
|
|
if [ -z "$optRemoveTmp" ]
|
|
then
|
|
echo 2>/dev/null
|
|
echo "Retaining intermediate: $tmpFile" 2>/dev/null
|
|
fi
|
|
|
|
else
|
|
|
|
# No special handling
|
|
## echo "${0##*/} : generate code" 1>&2
|
|
|
|
"$lemon" "$skel" "$@"
|
|
exitCode=$?
|
|
fi
|
|
|
|
|
|
exit "$exitCode" # Exit with lemon return code
|
|
|
|
#------------------------------------------------------------------------------
|