### User customizations

default: daikon

# Put user-specific changes in your own Makefile.user file in this directory.
# Make will silently continue if Makefile.user does not exist.
-include Makefile.user

# Don't let the user override this; it should refer to the current directory.
DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))..)

DAIKONSCRIPTS ?= ${DAIKONDIR}/scripts

PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts
HTMLTOOLS ?= ${DAIKONDIR}/.utils/html-tools

USER ?= daikonbuild

JAVA ?= java -ea
# For debugging, add -verbose flag to javac command
# JAVAC ?= javac -g -Xlint:unchecked
JAVAC ?= javac
JAVADOC ?= javadoc
JAR ?= jar

# The "JAVANN" variables mean "at least version NN", except JAVA8.
JAVA_VERSION_STRING_WITH_EA := $(shell javac -version 2>&1 | head -1 | cut "-d " -f2)
JAVA_VERSION_STRING := $(shell javac -version 2>&1 | head -1 | cut "-d " -f2 | sed 's/-ea//')
ifneq (,$(findstring start1.8,start${JAVA_VERSION_STRING}))
  JAVA8 := 1
  JAVA17 := 0
  JAVA21 := 0
  JAVA24 := 0
  JAVA25 := 0
  JAVA_RELEASE_NUMBER := 8
else
  JAVA8 := 0
  JAVA17 := 0
  JAVA21 := 0
  JAVA24 := 0
  JAVA25 := 0
  JAVA_RELEASE_NUMBER := $(shell echo ${JAVA_VERSION_STRING} | sed 's/\([0-9]*\)\..*/\1/')
endif
ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -ge 17; echo $$?),0)
  JAVA17 := 1
endif
ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -ge 21; echo $$?),0)
  JAVA21 := 1
endif
# Temporary, since Java 24 is not a LTS release.
ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -ge 24; echo $$?),0)
  JAVA24 := 1
endif
ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -ge 25; echo $$?),0)
  JAVA25 := 1
  ifndef JAVA25_HOME
    JAVA25_HOME := ${JAVA_HOME}
  endif
endif

ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -gt 20; echo $$?),0)
  LINT_THIS_ESCAPE=-Xlint:-this-escape
endif

OS_ID := $(shell sed -n -e 's/^NAME="\(.*\)"/\1/p' /etc/os-release)
OS_REL := $(shell sed -n -e 's/^VERSION_ID="\(.*\)"/\1/p' /etc/os-release)

## TODO: It would be better to use "-target 8" for all files EXCEPT those ending in "24.java".
# Users can set JAVAC_TARGET_FLAGS, taking precedence over these settings.
# Use "--source 25 --target 25" because Java 25 is an LTS version.
ifeq (${JAVA25}, 1)
  ifndef JAVA25_HOME
    # If this happens, $JAVA_HOME must also be empty.
    $(error JAVA25_HOME is not set; JAVA_HOME=${JAVA_HOME})
  endif
  JAVAC_TARGET_FLAGS ?= --source 25 --target 25 --system ${JAVA25_HOME}
else ifeq (${JAVA24}, 1)
  JAVAC_TARGET_FLAGS ?= -source 24 -target 24
else
  JAVAC_TARGET_FLAGS ?= -source 8 -target 8
endif

# TODO: -Werror is temporary.
JAVAC_ARGS ?= -g -XDignore.symbol.file -Xmaxerrs 100000 -Xmaxwarns 100000 -Werror -Xlint:-path -Xlint:-options -Xlint:-classfile ${LINT_THIS_ESCAPE} ${JAVAC_TARGET_ARGS} ${JAVAC_TARGET_FLAGS}

INSTALL ?= /usr/bin/install

# By default, if environment variable CHECKERFRAMEWORK is set, that Checker Framework is used.
# To force use of the Checker Framework in java/lib/, run like this:
#   make NO_LOCAL_CHECKERFRAMEWORK=true typecheck-nullness
ifndef NO_LOCAL_CHECKERFRAMEWORK
  ifdef CHECKERFRAMEWORK
    ifneq ("$(wildcard ${CHECKERFRAMEWORK})","")
      CHECKERFRAMEWORK_JAR_DIR ?= ${CHECKERFRAMEWORK}/checker/dist
    endif
  endif
endif
CHECKERFRAMEWORK_JAR_DIR ?= ${DAIKONDIR}/java/lib/checker-framework
CHECKERFRAMEWORK_JAR ?= ${CHECKERFRAMEWORK_JAR_DIR}/checker.jar
CHECKERFRAMEWORK_JAVAC ?= ${CHECKERFRAMEWORK_JAR_DIR}/javac.jar


### end of user customizations


###########################################################################
### Variables
###

## Classpath

## Daikon compiled files
ifeq "$(wildcard ${DAIKONDIR}/java/lib/daikon-plumelib.jar)" "${DAIKONDIR}/java/lib/daikon-plumelib.jar"
  # Add jar files that only exist for the development version, not the
  # distributed version, of Daikon.  The if clause avoids a (harmless but
  # annoying) javac error message that they don't exist.
  # This classpath is a problem, because CHECKERFRAMEWORK_JAR may have
  # a different version of a plume-lib library than java/lib/* does.
  # One (unclean) approach is to update them simultaneously.  Does that even work?
  DAIKON_CLASSPATH := ${CHECKERFRAMEWORK_JAR}:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/java
else
  DAIKON_CLASSPATH := ${DAIKONDIR}/java
endif

## Add tools.jar and rt.jar, if they exist
ifeq ($(shell uname), Darwin)
  JAVA_HOME ?= $(/usr/libexec/java_home)
else
ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found)
  JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::")
else
  $(info Failure: Here is the output of: which javac)
  $(info $(shell which javac))
  $(error 'which javac' had exit status 1)
endif
endif
ifneq "$(wildcard ${JAVA_HOME}/lib/tools.jar)" ""
  DAIKON_CLASSPATH := ${DAIKON_CLASSPATH}:${JAVA_HOME}/lib/tools.jar
endif
ifneq "$(wildcard ${JAVA_HOME}/jre/lib/rt.jar)" ""
  DAIKON_CLASSPATH := ${DAIKON_CLASSPATH}:${JAVA_HOME}/jre/lib/rt.jar
endif

JAVADOC_COMMAND := ${JAVADOC} -cp ${DAIKON_CLASSPATH}
JAVAC_COMMAND := ${JAVAC} -cp ${DAIKON_CLASSPATH} -Xlint -J-Xmx7g ${JAVAC_ARGS}
JAVA_COMMAND := ${JAVA} -cp ${DAIKON_CLASSPATH}

DOCLETPATH := ${DAIKONDIR}/java:$(wildcard ${DAIKONDIR}/java/lib/bcel-util-*.jar):$(wildcard ${DAIKONDIR}/java/lib/plume-util-*.jar):$(wildcard ${DAIKONDIR}/java/lib/reflection-util-*.jar):$(wildcard ${DAIKONDIR}/java/lib/hashmap-util-*.jar):${DAIKONDIR}/java/lib/daikon-plumelib.jar

DOCLET_FLAGS :=
LINKOFFLINE := https://docs.oracle.com/javase/8/docs/api/
ifeq ($(shell expr ${JAVA_RELEASE_NUMBER} \>= 11),1)
  DOCLET_FLAGS := --add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
  LINKOFFLINE := https://docs.oracle.com/en/java/javase/17/docs/api/
endif

# This command should run after the AUTO_GENERATED_FILES are generated, or
# else AUTO_GENERATED_FILES should be appended to it (without duplication).
# Therefore, this assignment uses "=" instead of ":=".
# DO NOT USE THESE in dependencies or the
# find command will get run multiple times.  USE AUTO_GENERATED_FILES instead.
# "-o -path './jakarta-oro*/src/java/examples'" does not work for non-GNU find.
# " | perl -pi -e 's/^\.\///g'" to remove leading "./"
SORT_DIRECTORY_ORDER := ${PLUME_SCRIPTS}/sort-directory-order
ifneq "$(wildcard ${SORT_DIRECTORY_ORDER})" "${SORT_DIRECTORY_ORDER}"
  # Until "make ${PLUME_SCRIPTS}" has been run, sort-directory-order is not available.
  SORT_DIRECTORY_ORDER := sort
endif

ifeq (${JAVA8}, 1)
dummy := $(shell cp -pf daikon/config/InvariantDoclet.java8 daikon/config/InvariantDoclet.java)
dummy := $(shell cp -pf daikon/config/ParameterDoclet.java8 daikon/config/ParameterDoclet.java)
else
dummy := $(shell cp -pf daikon/config/InvariantDoclet.java11 daikon/config/InvariantDoclet.java)
dummy := $(shell cp -pf daikon/config/ParameterDoclet.java11 daikon/config/ParameterDoclet.java)
endif

DAIKON_JAVA_FILES := $(shell find daikon/ -name '*.java' -not -name '*\#*' -print | ${SORT_DIRECTORY_ORDER})
ifeq (${JAVA24}, 0)
  DAIKON_JAVA_FILES :=  $(filter-out %24.java, ${DAIKON_JAVA_FILES})
endif
JAVA_FILES := $(shell find . -follow \( -name '*daikon-java*' -o -name '*daikon-instrumented*' -o -name 'PrototypeChecker.java' -o -name 'VIndexChecker.java' -o -name 'VIndexAnnotatedTypeFactory.java' -o -name 'ReturnBytecodes.java' -o -name 'SplitterFactoryTest.java' -o -name '\.\#*' \) -prune -o -name '*.java' -print | grep -v '/jakarta-oro.*/src/java/examples/' | ${SORT_DIRECTORY_ORDER})
ifeq (${JAVA24}, 0)
  JAVA_FILES :=  $(filter-out %24.java, ${JAVA_FILES})
endif
JAVA_FILES_FOR_DEPENDENCES := $(filter-out daikon/test/split/SplitterFactoryTestUpdater.java, $(filter-out daikon/test/split/SplitterFactoryTest.java, ${JAVA_FILES}))
JAVA_FILES_FOR_STYLE := $(shell find . -follow \( -name '*daikon-java*' -o -name '*daikon-instrumented*' -o -name 'PrototypeChecker.java' -o -name 'VIndexChecker.java' -o -name 'VIndexAnnotatedTypeFactory.java' -o -name 'ReturnBytecodes.java' -o -name 'SplitterFactoryTest.java' -o -name 'WeakHasherMap.java' -o -name 'WeakIdentityHashMap.java' -o -name '\.\#*' -o -path './jtb' -o -path './daikon/dcomp-transfer' \) -prune -o -name '*.java' -print | grep -v '/jakarta-oro.*/src/java/examples/' | ${SORT_DIRECTORY_ORDER})
ifeq (${JAVA24}, 0)
  JAVA_FILES_FOR_STYLE :=  $(filter-out %24.java, ${JAVA_FILES_FOR_STYLE})
endif
# Other find commands should perhaps use the recursive grep form instead
JAVA_FILES_FOR_FORMAT := $(shell grep -r --include '*.java' --exclude-dir '*daikon-java*' --exclude-dir '*daikon-instrumented*' --exclude WeakHasherMap.java --exclude WeakIdentityHashMap.java --exclude InvariantDoclet.java --exclude ParameterDoclet.java -L 'This file is automatically generated' . | grep -v "^./jtb" | ${SORT_DIRECTORY_ORDER})
ifeq (${JAVA24}, 0)
  JAVA_FILES_FOR_FORMAT :=  $(filter-out %24.java, ${JAVA_FILES_FOR_FORMAT})
endif

# Don't exclude the whole ./daikon/test directory.
TAG_FILES :=        $(shell find . -type f -follow \( -name '*daikon-java*' -o -name '*Test.java' -o -name '*Tester.java' -o -name 'Test*.java' -o -name 'GenericTestClass.java' -o -name 'TestQuant.java' -o -name 'DiffDummyInvariant.java' -o -name 'AllTestsSuite.java' \) -prune -o \( -name '*.java' -o -name '*.java.jpp' \) -print | grep -v '/\.\#' | ${SORT_DIRECTORY_ORDER})
TAG_FILES_NO_JTB := $(shell find . -type f -follow \( -name '*daikon-java*' -o -name '*Test.java' -o -name '*Tester.java' -o -name 'Test*.java' -o -name 'GenericTestClass.java' -o -name 'TestQuant.java' -o -name 'DiffDummyInvariant.java' -o -name 'AllTestsSuite.java' \) -prune -o \( -path './jtb' \) -prune -o \( -name '*.java' -o -name '*.java.jpp' \) -print | grep -v '/\.\#' | ${SORT_DIRECTORY_ORDER})

# When removing files from this list, add them to OLD_AUTO_GENERATED_FILES.
AUTO_GENERATED_FILES := \
	daikon/PptSlice1.java \
	daikon/PptSlice2.java \
	daikon/PptSlice3.java \
	daikon/Quant.java \
	daikon/inv/ternary/threeScalar/FunctionBinary.java \
	daikon/inv/ternary/threeScalar/FunctionBinaryFloat.java \
	daikon/inv/ternary/threeScalar/ThreeScalar.java \
	daikon/inv/ternary/threeScalar/ThreeFloat.java \
	daikon/inv/ternary/threeScalar/LinearTernaryCore.java \
	daikon/inv/ternary/threeScalar/LinearTernaryCoreFloat.java \
	daikon/inv/ternary/threeScalar/LinearTernary.java \
	daikon/inv/ternary/threeScalar/LinearTernaryFloat.java \
	daikon/inv/unary/LowerBoundCore.java \
	daikon/inv/unary/UpperBoundCore.java \
	daikon/inv/unary/LowerBoundCoreFloat.java \
	daikon/inv/unary/UpperBoundCoreFloat.java \
	daikon/inv/unary/scalar/LowerBound.java \
	daikon/inv/unary/scalar/UpperBound.java \
	daikon/inv/unary/scalar/LowerBoundFloat.java \
	daikon/inv/unary/scalar/UpperBoundFloat.java \
	daikon/inv/unary/scalar/OneOfScalar.java \
	daikon/inv/unary/scalar/OneOfFloat.java \
	daikon/inv/unary/string/OneOfString.java \
	daikon/inv/unary/scalar/NonZero.java \
	daikon/inv/unary/scalar/NonZeroFloat.java \
	daikon/inv/unary/scalar/RangeInt.java \
	daikon/inv/unary/scalar/RangeFloat.java \
	daikon/inv/unary/sequence/EltRangeInt.java \
	daikon/inv/unary/sequence/EltRangeFloat.java \
	daikon/inv/unary/sequence/OneOfSequence.java \
	daikon/inv/unary/sequence/OneOfFloatSequence.java \
	daikon/inv/unary/sequence/EltOneOf.java \
	daikon/inv/unary/sequence/EltOneOfFloat.java \
	daikon/inv/unary/sequence/EltLowerBound.java \
	daikon/inv/unary/sequence/EltLowerBoundFloat.java \
	daikon/inv/unary/sequence/EltUpperBound.java \
	daikon/inv/unary/sequence/EltUpperBoundFloat.java \
	daikon/inv/unary/sequence/NoDuplicates.java \
	daikon/inv/unary/sequence/NoDuplicatesFloat.java \
	daikon/inv/unary/sequence/SeqIndexIntEqual.java \
	daikon/inv/unary/sequence/SeqIndexIntNonEqual.java \
	daikon/inv/unary/sequence/SeqIndexIntGreaterThan.java \
	daikon/inv/unary/sequence/SeqIndexIntGreaterEqual.java \
	daikon/inv/unary/sequence/SeqIndexIntLessThan.java \
	daikon/inv/unary/sequence/SeqIndexIntLessEqual.java \
	daikon/inv/unary/sequence/SeqIndexFloatEqual.java \
	daikon/inv/unary/sequence/SeqIndexFloatNonEqual.java \
	daikon/inv/unary/sequence/SeqIndexFloatGreaterThan.java \
	daikon/inv/unary/sequence/SeqIndexFloatGreaterEqual.java \
	daikon/inv/unary/sequence/SeqIndexFloatLessThan.java \
	daikon/inv/unary/sequence/SeqIndexFloatLessEqual.java \
	daikon/inv/unary/sequence/CommonSequence.java \
	daikon/inv/unary/sequence/CommonFloatSequence.java \
	daikon/inv/unary/sequence/EltNonZero.java \
	daikon/inv/unary/sequence/EltNonZeroFloat.java \
	daikon/inv/unary/sequence/EltwiseIntComparison.java \
	daikon/inv/unary/sequence/EltwiseFloatComparison.java \
	daikon/inv/unary/sequence/EltwiseIntEqual.java \
	daikon/inv/unary/sequence/EltwiseIntLessThan.java \
	daikon/inv/unary/sequence/EltwiseIntLessEqual.java \
	daikon/inv/unary/sequence/EltwiseIntGreaterThan.java \
	daikon/inv/unary/sequence/EltwiseIntGreaterEqual.java \
	daikon/inv/unary/sequence/EltwiseFloatEqual.java \
	daikon/inv/unary/sequence/EltwiseFloatLessThan.java \
	daikon/inv/unary/sequence/EltwiseFloatLessEqual.java \
	daikon/inv/unary/sequence/EltwiseFloatGreaterThan.java \
	daikon/inv/unary/sequence/EltwiseFloatGreaterEqual.java \
	daikon/inv/unary/stringsequence/EltOneOfString.java \
	daikon/inv/unary/stringsequence/OneOfStringSequence.java \
	daikon/inv/binary/sequenceScalar/Member.java \
	daikon/inv/binary/sequenceString/MemberString.java \
	daikon/inv/binary/sequenceString/SequenceString.java \
	daikon/inv/binary/sequenceScalar/MemberFloat.java \
	daikon/inv/binary/sequenceScalar/SeqIntLessThan.java \
	daikon/inv/binary/sequenceScalar/SeqIntGreaterThan.java \
	daikon/inv/binary/sequenceScalar/SeqIntLessEqual.java \
	daikon/inv/binary/sequenceScalar/SeqIntGreaterEqual.java\
	daikon/inv/binary/sequenceScalar/SeqIntEqual.java \
	daikon/inv/binary/sequenceScalar/SeqFloatLessThan.java \
	daikon/inv/binary/sequenceScalar/SeqFloatGreaterThan.java \
	daikon/inv/binary/sequenceScalar/SeqFloatLessEqual.java \
	daikon/inv/binary/sequenceScalar/SeqFloatGreaterEqual.java \
	daikon/inv/binary/sequenceScalar/SeqFloatEqual.java \
	daikon/inv/binary/sequenceScalar/SequenceScalar.java \
	daikon/inv/binary/sequenceScalar/SequenceFloat.java \
	daikon/inv/binary/twoScalar/IntEqual.java \
	daikon/inv/binary/twoScalar/FloatEqual.java \
	daikon/inv/binary/twoScalar/IntNonEqual.java \
	daikon/inv/binary/twoScalar/FloatNonEqual.java \
	daikon/inv/binary/twoScalar/IntLessThan.java \
	daikon/inv/binary/twoScalar/FloatLessThan.java \
	daikon/inv/binary/twoScalar/IntLessEqual.java \
	daikon/inv/binary/twoScalar/FloatLessEqual.java \
	daikon/inv/binary/twoScalar/IntGreaterThan.java \
	daikon/inv/binary/twoScalar/FloatGreaterThan.java \
	daikon/inv/binary/twoScalar/IntGreaterEqual.java \
	daikon/inv/binary/twoScalar/FloatGreaterEqual.java \
	daikon/inv/binary/twoScalar/NumericInt.java \
	daikon/inv/binary/twoScalar/NumericFloat.java \
	daikon/inv/binary/twoString/StdString.java \
	daikon/inv/binary/twoScalar/LinearBinaryCore.java \
	daikon/inv/binary/twoScalar/LinearBinaryCoreFloat.java \
	daikon/inv/binary/twoScalar/LinearBinary.java \
	daikon/inv/binary/twoScalar/LinearBinaryFloat.java \
	daikon/inv/binary/twoScalar/TwoScalar.java \
	daikon/inv/binary/twoScalar/TwoFloat.java \
	daikon/inv/binary/twoString/TwoString.java \
	daikon/inv/binary/twoString/StringEqual.java \
	daikon/inv/binary/twoString/StringNonEqual.java \
	daikon/inv/binary/twoString/StringLessThan.java \
	daikon/inv/binary/twoString/StringLessEqual.java \
	daikon/inv/binary/twoString/StringGreaterThan.java \
	daikon/inv/binary/twoString/StringGreaterEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqIntEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqIntLessThan.java \
	daikon/inv/binary/twoSequence/SeqSeqIntGreaterThan.java \
	daikon/inv/binary/twoSequence/SeqSeqIntLessEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqIntGreaterEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqFloatEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqFloatLessThan.java \
	daikon/inv/binary/twoSequence/SeqSeqFloatGreaterThan.java \
	daikon/inv/binary/twoSequence/SeqSeqFloatLessEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqFloatGreaterEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqStringEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqStringLessThan.java \
	daikon/inv/binary/twoSequence/SeqSeqStringGreaterThan.java \
	daikon/inv/binary/twoSequence/SeqSeqStringLessEqual.java \
	daikon/inv/binary/twoSequence/SeqSeqStringGreaterEqual.java \
	daikon/inv/binary/twoSequence/Reverse.java \
	daikon/inv/binary/twoSequence/ReverseFloat.java \
	daikon/inv/binary/twoSequence/SubSequence.java \
	daikon/inv/binary/twoSequence/SubSequenceFloat.java \
	daikon/inv/binary/twoSequence/SuperSequence.java \
	daikon/inv/binary/twoSequence/SuperSequenceFloat.java \
	daikon/inv/binary/twoSequence/SubSet.java \
	daikon/inv/binary/twoSequence/SubSetFloat.java \
	daikon/inv/binary/twoSequence/SuperSet.java \
	daikon/inv/binary/twoSequence/SuperSetFloat.java \
	daikon/inv/binary/twoSequence/PairwiseIntEqual.java \
	daikon/inv/binary/twoSequence/PairwiseIntLessThan.java \
	daikon/inv/binary/twoSequence/PairwiseIntGreaterThan.java \
	daikon/inv/binary/twoSequence/PairwiseIntLessEqual.java \
	daikon/inv/binary/twoSequence/PairwiseIntGreaterEqual.java \
	daikon/inv/binary/twoSequence/PairwiseFloatEqual.java \
	daikon/inv/binary/twoSequence/PairwiseFloatLessThan.java \
	daikon/inv/binary/twoSequence/PairwiseFloatGreaterThan.java \
	daikon/inv/binary/twoSequence/PairwiseFloatLessEqual.java \
	daikon/inv/binary/twoSequence/PairwiseFloatGreaterEqual.java \
	daikon/inv/binary/twoSequence/PairwiseLinearBinary.java \
	daikon/inv/binary/twoSequence/PairwiseLinearBinaryFloat.java \
	daikon/inv/binary/twoSequence/PairwiseStringEqual.java \
	daikon/inv/binary/twoSequence/PairwiseStringLessThan.java \
	daikon/inv/binary/twoSequence/PairwiseStringGreaterThan.java \
	daikon/inv/binary/twoSequence/PairwiseStringLessEqual.java \
	daikon/inv/binary/twoSequence/PairwiseStringGreaterEqual.java \
	daikon/inv/binary/twoSequence/PairwiseLinearBinary.java \
	daikon/inv/binary/twoSequence/PairwiseLinearBinaryFloat.java \
	daikon/inv/binary/twoSequence/PairwiseNumericInt.java \
	daikon/inv/binary/twoSequence/PairwiseNumericFloat.java \
	daikon/inv/binary/twoSequence/PairwiseString.java \
	daikon/inv/binary/twoSequence/TwoSequence.java \
	daikon/inv/binary/twoSequence/TwoSequenceFloat.java \
	daikon/inv/binary/twoSequence/TwoSequenceString.java \
	daikon/inv/binary/twoSequence/TwoSequenceString.java \
	daikon/derive/ternary/SequenceScalarArbitrarySubsequence.java \
	daikon/derive/ternary/SequenceFloatArbitrarySubsequence.java \
	daikon/derive/ternary/SequenceStringArbitrarySubsequence.java \
	daikon/derive/ternary/SequenceScalarArbitrarySubsequenceFactory.java \
	daikon/derive/ternary/SequenceFloatArbitrarySubsequenceFactory.java \
	daikon/derive/ternary/SequenceStringArbitrarySubsequenceFactory.java \
	daikon/derive/binary/SequenceScalarSubscript.java \
	daikon/derive/binary/SequenceFloatSubscript.java \
	daikon/derive/binary/SequenceStringSubscript.java \
	daikon/derive/binary/SequenceScalarSubsequence.java \
	daikon/derive/binary/SequenceFloatSubsequence.java \
	daikon/derive/binary/SequenceStringSubsequence.java \
	daikon/derive/binary/SequenceScalarSubscriptFactory.java \
	daikon/derive/binary/SequenceFloatSubscriptFactory.java \
	daikon/derive/binary/SequenceStringSubscriptFactory.java \
	daikon/derive/binary/SequenceScalarIntersection.java \
	daikon/derive/binary/SequenceFloatIntersection.java \
	daikon/derive/binary/SequenceStringIntersection.java \
	daikon/derive/binary/SequenceScalarIntersectionFactory.java \
	daikon/derive/binary/SequenceFloatIntersectionFactory.java \
	daikon/derive/binary/SequenceStringIntersectionFactory.java \
	daikon/derive/binary/SequenceScalarUnion.java \
	daikon/derive/binary/SequenceFloatUnion.java \
	daikon/derive/binary/SequenceStringUnion.java \
	daikon/derive/binary/SequenceScalarUnionFactory.java \
	daikon/derive/binary/SequenceFloatUnionFactory.java \
	daikon/derive/binary/SequenceStringUnionFactory.java \
	daikon/derive/binary/SequencesPredicate.java \
	daikon/derive/binary/SequencesPredicateFloat.java \
	daikon/derive/binary/SequencesPredicateFactory.java \
	daikon/derive/binary/SequencesPredicateFactoryFloat.java \
	daikon/derive/binary/SequencesJoin.java \
	daikon/derive/binary/SequencesJoinFloat.java \
	daikon/derive/binary/SequencesJoinFactory.java \
	daikon/derive/binary/SequencesJoinFactoryFloat.java \
	daikon/derive/unary/SequenceInitial.java \
	daikon/derive/unary/SequenceInitialFloat.java \
	daikon/derive/unary/SequenceInitialFactory.java \
	daikon/derive/unary/SequenceInitialFactoryFloat.java \
	daikon/config/InvariantDoclet.java \
	daikon/config/ParameterDoclet.java \

# These files were auto-generated previously; they still might exist in
# some user's directory.
OLD_AUTO_GENERATED_FILES := \
	daikon/inv/binary/twoScalar/FloatComparisonCore.java \
	daikon/inv/binary/twoScalar/FunctionUnary.java \
	daikon/inv/binary/twoScalar/FunctionUnaryCore.java \
	daikon/inv/binary/twoScalar/FunctionUnaryCoreFloat.java \
	daikon/inv/binary/twoScalar/FunctionUnaryFloat.java \
	daikon/inv/binary/twoScalar/IntComparisonCore.java \
	daikon/inv/binary/twoSequence/PairwiseFunctionUnary.java \
	daikon/inv/binary/twoSequence/PairwiseFunctionUnaryFloat.java \
	daikon/inv/unary/sequence/SeqIndexComparison.java \
	daikon/inv/unary/sequence/SeqIndexComparisonFloat.java \
	daikon/inv/unary/sequence/SeqIndexNonEqual.java \
	daikon/inv/unary/sequence/SeqIndexNonEqualFloat.java \
	daikon/inv/binary/twoScalar/NonEqualCore.java \
	daikon/inv/binary/twoScalar/NonEqualCoreFloat.java \
	daikon/inv/binary/sequenceScalar/SequenceScalarFactory.java \
	daikon/inv/binary/sequenceScalar/SequenceFloatFactory.java \
	daikon/inv/binary/twoScalar/TwoScalarFactory.java \
	daikon/inv/binary/twoScalar/TwoFloatFactory.java \
	daikon/inv/binary/twoSequence/TwoSequenceFactory.java \
	daikon/inv/binary/twoSequence/TwoSequenceFactoryFloat.java \
	daikon/inv/unary/sequence/SingleScalarSequenceFactory.java \
	daikon/inv/unary/sequence/SingleFloatSequenceFactory.java \
	daikon/inv/ternary/threeScalar/ThreeScalarFactory.java \
	daikon/inv/binary/sequenceString/Member.java \
	daikon/inv/ternary/threeScalar/FunctionBinaryCore.java \
	daikon/inv/Functions.java \
	daikon/inv/FunctionsFloat.java \
	daikon/inv/ternary/threeScalar/FunctionBinaryCoreFloat.java \
	utilMDE/MathMDE.java \
	lib/utilMDE.jar

OLD_AUTO_GENERATED_CLASSES := $(subst .java,.class,${OLD_AUTO_GENERATED_FILES})

# These files cannot be generated until everything else has been compiled.
# (But, a problem is that it can get out of date and cause the compilation
# to fail during pass 1.)
AUTO_GENERATED_FILES_2 := \
	daikon/test/split/SplitterFactoryTest.java

AUTO_GENERATED_CLASSES_2 := $(subst .java,.class,${AUTO_GENERATED_FILES_2})

ALL_GENERATED_FILES := ${AUTO_GENERATED_FILES} ${AUTO_GENERATED_FILES_2}


###########################################################################
### Variables passed down to subshells
###

export DAIKON_CLASSPATH
export CHECKERJAR
export DAIKONDIR


###########################################################################
### Test targets
###

.PHONY: default all
default: daikon
all: daikon

.PHONY: daikon
daikon: showvars-brief update-libs ${AUTO_GENERATED_FILES}
	${MAKE} smoke-test

smoke-test: junit chicory-test dyncomp-test

showvars-brief:
	@echo "CLASSPATH = ${CLASSPATH}"
	@echo "DAIKON_CLASSPATH = ${DAIKON_CLASSPATH}"
	@echo "JAVA_RELEASE_NUMBER = ${JAVA_RELEASE_NUMBER}"
	@echo "JAVA_VERSION_STRING_WITH_EA = ${JAVA_VERSION_STRING_WITH_EA}"

.PHONY: xlint
xlint: daikon/Daikon.class
	@${JAVAC_COMMAND} -Xlint -Xmaxwarns 1000 ${DAIKON_JAVA_FILES} 2>&1

update-libs:
	${MAKE} -C .. update-libs


###########################################################################
### Compilation targets
###

# The timestamp of Daikon.class indicates the last time the system was recompiled.
compile compile-java compile-daikon: daikon/Daikon.class
daikon/Daikon.class: daikon/Daikon.java ${AUTO_GENERATED_FILES} ${JAVA_FILES_FOR_DEPENDENCES}
	@echo 'echo $${JAVA_FILES} > java_files.txt'
	@echo ${JAVA_FILES} > java_files.txt
	${JAVAC_COMMAND} @java_files.txt
	rm -f java_files.txt
	touch $@
	${MAKE} rename-dcruntime ${AUTO_GENERATED_CLASSES_2}
# on some systems chmod with symbolic arguments pays attention to umask.  so use 444 instead of -w
	@chmod 444 ${AUTO_GENERATED_FILES}
# These can't be prerequisites because they depend on .class files from Daikon itself.
	${MAKE} ChicoryPremain.jar dcomp_premain.jar

.PHONY: rename-dcruntime
rename-dcruntime:
# Post JDK 21, additional restrictions have been introduced that prevent developers
# from explicitly creating or modifying classes in the java.lang package (or any
# package in java.base) at compile time. However, runtime class redefinition with
# Instrumentation.redefineClasses() still works, so we declare the package to be
# "jaxa.lang" instead of "java.lang" and then use sed to edit the classfile after
# compilation back to "java.lang".
	@if test -e ${DAIKONDIR}/java/daikon/dcomp-transfer/DCRuntime.class; then \
	  echo sed -e's/jaxa/java/g' -i -b ${DAIKONDIR}/java/daikon/dcomp-transfer/DCRuntime.class; \
	  sed -e's/jaxa/java/g' -i -b ${DAIKONDIR}/java/daikon/dcomp-transfer/DCRuntime.class; \
	else \
	  echo sed -e's/jaxa/java/g' -i -b ${DAIKONDIR}/java/daikon/dcomp-dummy/DCRuntime.class; \
	  sed -e's/jaxa/java/g' -i -b ${DAIKONDIR}/java/daikon/dcomp-dummy/DCRuntime.class; \
	fi;

#
# Chicory java front end for Daikon
#
CHICORY_JAVA_FILES := daikon/Chicory.java $(wildcard daikon/chicory/*.java)
ifeq (${JAVA24}, 0)
CHICORY_JAVA_FILES := $(filter-out %24.java, ${CHICORY_JAVA_FILES})
endif

# Note that this compiles all of Chicory even though all we need for
# this step is chicory/ChicoryPremain.java.
# Also note that it always compiles all of Chicory, to handle changing
# between different JDKs.  Changing JDKs changes which files are
# compiled, but changing JDKs doesn't cause this Makefile to otherwise
# trigger re-execution.
.PRECIOUS: ChicoryPremain.jar
ChicoryPremain.jar : daikon/Chicory.class daikon/chicory/manifest.txt
	${JAR} cfm ChicoryPremain.jar daikon/chicory/manifest.txt \
	  daikon/chicory/ChicoryPremain.class

.PHONY: chicory chicory-test
chicory chicory-test : daikon/chicory/inv_out.diff
daikon/chicory/inv_out.diff : ChicoryPremain.jar daikon/Daikon.class
	cd daikon/chicory && rm -f ChicoryTest.log ChicoryTest.dtrace.gz ChicoryTest.inv.gz ChicoryTest.inv.out
	cd daikon/chicory && ${JAVA_COMMAND} daikon.Chicory --verbose --debug daikon.chicory.ChicoryTest > ChicoryTest.log || (cat ChicoryTest.log; false)
	cd daikon/chicory && ${JAVA_COMMAND} daikon.Daikon --no_text_output --no_show_progress ChicoryTest.dtrace.gz
	cd daikon/chicory && ${JAVA_COMMAND} daikon.PrintInvariants ChicoryTest.inv.gz > ChicoryTest.inv.out
	-diff -uw daikon/chicory/ChicoryTest.inv.out.goal daikon/chicory/ChicoryTest.inv.out \
	  > daikon/chicory/ChicoryTest.inv.out.diff
	@if test ! -s daikon/chicory/ChicoryTest.inv.out.diff ; then echo No Errors; \
	else echo Errors: more daikon/chicory/ChicoryTest.inv.out.diff for details; fi

#
# Dynamic Comparability (DynComp/Java; also Chicory)
#
INSTRUMENTATION_JAVA_FILES := daikon/DynComp.java $(wildcard daikon/dcomp/*.java daikon/chicory/*.java)
ifeq (${JAVA24}, 0)
INSTRUMENTATION_JAVA_FILES := $(filter-out %24.java, ${INSTRUMENTATION_JAVA_FILES})
endif

DCOMP_ARGS := --ppt-select-pattern=daikon.dcomp.DcompTest
DCOMP_DIR := daikon/dcomp

# Note that this compiles all of dcomp even though all we need for
# this step is dcomp/Premain.java.
dcomp_premain.jar : ${INSTRUMENTATION_JAVA_FILES} daikon/dcomp/manifest.txt
	${MAKE} plume-import-check
	@${JAVAC_COMMAND} ${INSTRUMENTATION_JAVA_FILES}
	${JAR} cfm dcomp_premain.jar daikon/dcomp/manifest.txt \
	  daikon/dcomp/Premain.class

# Build DynComp/Java, check the DF summary info and run a sanity test.
# Runs a simple sanity test on DynComp/Java without an instrumented JDK
# Also creates file ./DcompTest.decls-DynComp
# To debug a problem, change '--dump' to '--debug'
.PHONY: dyncomp-test dcomp-test
dyncomp-test dcomp-test : daikon/dcomp/std_dcomp_out.diff
daikon/dcomp/std_dcomp_out.diff : dcomp_premain.jar
	/bin/rm -rf /tmp/${USER}/bin/* /tmp/${USER}/orig/*
	cd daikon/dcomp && ${JAVA_COMMAND} \
	  daikon.DynComp ${DCOMP_ARGS} --verbose --dump \
	  --comparability-file=std_dcomp_out.txt --rt-file=NONE \
	  daikon.dcomp.DcompTest > DcompTest.log 2>&1
	-diff -uw daikon/dcomp/std_dcomp_out.goal daikon/dcomp/std_dcomp_out.txt \
	  > daikon/dcomp/std_dcomp_out.diff
	@if test ! -s daikon/dcomp/std_dcomp_out.diff ; then echo No Errors; \
	else echo Errors: more daikon/dcomp/std_dcomp_out.diff for details; fi

dyncomp-test-jdk dcomp-test-jdk : dcomp_premain.jar
	/bin/rm -rf /tmp/${USER}/bin/* /tmp/${USER}/orig/*
	${JAVA_COMMAND} \
	   daikon.DynComp ${DCOMP_ARGS} \
	   --comparability-file=daikon/dcomp/jdk_dcomp_out.txt daikon/dcomp/DcompTest
	-diff -u daikon/dcomp/jdk_dcomp_out.goal daikon/dcomp/jdk_dcomp_out.txt \
	  > daikon/dcomp/jdk_dcomp_out.diff
	@if test ! -s daikon/dcomp/jdk_dcomp_out.diff ; then echo No Errors; \
	else echo Errors: more daikon/dcomp/jdk_dcomp_out.diff for details; fi

dyncomp-update-goals dcomp-update-goals:
	cp daikon/dcomp/std_dcomp_out.txt daikon/dcomp/std_dcomp_out.goal
	cp daikon/dcomp/jdk_dcomp_out.txt daikon/dcomp/jdk_dcomp_out.goal
#
# Rules to build the instrumented JDK for DynComp/Java
#
DCOMP_RT	:= dcomp-rt
dyncomp-jdk dcomp-jdk   : dcomp_rt.jar
${DCOMP_RT} dcomp_rt.jar : dcomp_premain.jar
	/bin/rm -rf ${DCOMP_RT}
	${INSTALL} -d ${DCOMP_RT}
	${JAVA_COMMAND} -Xmx7g daikon.dcomp.BuildJDK ${DCOMP_RT}
# "then" clause is Java 8, "else" clause is Java 9+.
# For Java 9+, there appears to be a bug in the Java reflection invoke code that it
# does not check that the arg list matches.  Hence, it tries to invoke
# our instrumented version from non instrumented code.  This causes a
# failure during java initialization of boot layer.  It also causes additional
# failures during some java class loading.  Thus we must remove
# the problem classes from dcomp_rt.jar.
	@if test -f ${DCOMP_RT}/META-INF/MANIFEST.MF; then \
	  ${JAR} cmf ${DCOMP_RT}/META-INF/MANIFEST.MF dcomp_rt.jar -C ${DCOMP_RT} .; \
	else \
	  rm ${DCOMP_RT}/java/lang/invoke/VarHandle*Field*.class; \
	  cp daikon/dcomp-dummy/DCRuntime.class.dummy ${DCOMP_RT}/java/lang/DCRuntime.class; \
	  ${JAR} cf dcomp_rt.jar -C ${DCOMP_RT} .; \
	fi

# Install the local version of the dyncomp specific rt.jar
install-dyncomp-jdk install-dcomp-jdk : dcomp_rt.jar
	cp dcomp_rt.jar ${pag}/software/arch/common/pkg/DynComp/

# Only rebuild the jar file, don't recreate the contents of ${DCOMP_RT}.
# Useful if editing only one file in the jar.
dyncomp-jdk-only dcomp-jdk-only :
	@if test -f ${DCOMP_RT}/META-INF/MANIFEST.MF; then \
	  ${JAR} cmf ${DCOMP_RT}/META-INF/MANIFEST.MF dcomp_rt.jar -C ${DCOMP_RT} .; \
	else \
	  rm ${DCOMP_RT}/java/lang/invoke/VarHandleInts?Field*.class; \
	  ${JAR} cf dcomp_rt.jar -C ${DCOMP_RT} .; \
	fi

## These two rules create the directories if absent but don't update them.
${PLUME_SCRIPTS}:
	${MAKE} -C .. update-plume-scripts-in-utils

../.utils/html-tools:
	${MAKE} -C .. update-html-tools

.PHONY: update-plume-scripts-in-utils
update-plume-scripts-in-utils:
	${MAKE} -C .. update-plume-scripts-in-utils

# Checks that daikon.plumelib, rather than plume, is imported by source files
# that do instrumentation.  Should also check that daikon.plumelib is never
# imported by non-instrumentation files.
.PHONY: plume-import-check
plume-import-check :
	@echo -n "Checking that imports of plume and daikon.plumelib are correct..."
	@if [ -n "`grep '^import org.plumelib' ${INSTRUMENTATION_JAVA_FILES}`" ]; then \
	echo ""; \
	echo "*** ERROR: Do not import org.plumelib.* from DynComp code. It would be"; \
	echo " instrumented when DynComp or Chicory is run. Please use the"; \
	echo " (identical) daikon.plumelib package, which will not be instrumented."; \
	echo "The following files import from plume:"; \
	grep -n '^import org.plumelib.*' ${INSTRUMENTATION_JAVA_FILES}; \
	false; \
	else \
	echo "done"; \
	fi

## Use this when you don't want $inv/tests makefiles to restart
JAVA_FILES_EXCEPT_DAIKON := $(subst ./daikon/Daikon.java,,${JAVA_FILES})
all_except_daikon: ${PLUME_SCRIPTS} ${AUTO_GENERATED_FILES}
	@echo ${JAVAC_COMMAND} '*.java ... (except Daikon.java)'
	@${JAVAC_COMMAND} ${JAVA_FILES_EXCEPT_DAIKON}
	@chmod a-w ${AUTO_GENERATED_FILES}


###########################################################################
### Cleaning (removing generated files
###

# TODO:
# 	rm -f `find daikon -path "*/debug*/bin" -prune -o -path "*/debug*/orig" -prune -o -path "*/debug*/instrumented" -prune -o -path "*/debug*/uninstrumented" -prune -o -name "*.class" -print`


# It's good to run "make clean" occasionally, because it costs little to
# regenerate .class files and it's bad to continue to use an orphaned class
# file (whose source file was renamed).  Or, run "orphaned-class-files".
# The (slight) downside is that the regenerated .class files might cause some
# Make rules to unnecessarily re-run, if the code hasn't actually changed.
clean_class_files:
# remove 'bin' and 'orig' after versions stabilize
	-rm -f `find . -path "*/debug*/bin" -prune -o -path "*/debug*/orig" -prune -o -path "*/debug*/instrumented" -prune -o -path "*/debug*/uninstrumented" -prune -o -name "*.class" -print`
	# java/daikon might be a symbolic link; the alternative is to pass
	# "-follow" to the above find command, but I don't necessarily
	# want to remove everything reachable through symbolic links.
# remove 'bin' and 'orig' after versions stabilize
	-rm -f `find daikon -follow -path "*/debug*/bin" -prune -o -path "*/debug*/orig" -prune -o -path "*/debug*/instrumented" -prune -o -path "*/debug*/uninstrumented" -prune -o -name "*.class" -print`
	-rm -f ${OLD_AUTO_GENERATED_FILES}

clean:
	${MAKE} clean_class_files
	-rm -f ChicoryPremain.jar
	-rm -f daikon/chicory/ChicoryTest.log

clean-generated-files:
	-rm -f ${AUTO_GENERATED_FILES} ${AUTO_GENERATED_FILES_2}

# Could/should remove .utils here, too.
veryclean: very_clean
very_clean: very-clean
very-clean: clean clean-generated-files
	-rm -f TAGS
	-rm -rf api/
	-rm -rf daikon/chicory/ChicoryTest.inv.out
	-rm -rf daikon/chicory/debug/
	-rm -rf daikon/dcomp/DcompTest.decls-DynComp daikon/dcomp/DcompTest.log
	-rm -rf daikon/dcomp/debug/
	-rm -rf daikon/dcomp/std_dcomp_out.diff daikon/dcomp/std_dcomp_out.txt
	-rm -rf dcomp_premain.jar dcomp_rt.jar ${DCOMP_RT}

run:	all
	${JAVA_COMMAND} daikon.Daikon

ifneq (,$(shell which etags))
## The etags program exists
ifneq (,$(findstring Exuberant, $(shell etags --version 2>&1)))
ETAGS := etags --language-force=java
else
ETAGS := etags --language=java
endif
endif

TAGS:	tags
.PHONY: etags tags
etags:	tags
tags: ${PLUME_SCRIPTS}
ifndef ETAGS
	$(error etags is not available, please install it)
endif
	@echo etags '*.java ...'
	@${ETAGS} ${TAG_FILES}

# A TAGS file that does not contain generated files
# When doing certain search/replace tasks, it's better to omit generated files
tags-nogen: tags-without-generated-files
tags-sans-generated: tags-without-generated-files
tags-without-generated-files: clean-generated-files
	${MAKE} tags
	${MAKE} compile

# A TAGS file that does not contain jtb-generated files.
tags-nojtb: ${PLUME_SCRIPTS}
ifndef ETAGS
	$(error etags is not available, please install it)
endif
	@echo etags '*.java ...'
	@${ETAGS} ${TAG_FILES_NO_JTB}


###########################################################################
### Code quality (static checks of the code)
###

# See version numbers at https://github.com/google/error-prone/releases
# and https://errorprone.info/docs/installation.
# Only run under Java 21+.
error-prone-version := 2.46.0
# "-XDaddTypeAnnotationsToSymbol=true" is only required under exactly Java 21,
# but it's harmless (has no effect) on later versions of Java.
extra-error-prone-args-1 := --should-stop=ifError=FLOW -XDaddTypeAnnotationsToSymbol=true

ERRORPRONE_PROCESSOR_PATH := ${DAIKONDIR}/java/lib/error-prone/error_prone_core-${error-prone-version}-with-dependencies.jar:${DAIKONDIR}/java/lib/error-prone/dataflow-errorprone-3.49.3-eisop1.jar

JAVAC_ANNOTATION_PROCESSOR_ARGS ?= \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
	-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
	-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
	-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

error-prone: errorprone
errorprone: compile errorprone-nocompile
# Some of the -Xep are temporary
#   -Xep:PatternMatchingInstanceof:OFF  requires Java 17 source code
errorprone-nocompile:
ifneq (${JAVA21}, 1)
	@echo "Error Prone is only run under Java 21+"
else
	@echo "Using Error Prone version ${error-prone-version}"
## MutablePublicArray is off because it suggests a dependency on Google Guava.
	javac -cp ${DAIKON_CLASSPATH} \
	  ${JAVAC_ANNOTATION_PROCESSOR_ARGS} \
	  -XDcompilePolicy=simple -processorpath ${ERRORPRONE_PROCESSOR_PATH} \
	  '-Xplugin:ErrorProne -Xep:ReferenceEquality:OFF -Xep:StringSplitter:OFF -Xep:AnnotateFormatMethod:OFF -Xep:MutablePublicArray:OFF -Xep:DoNotCallSuggester:OFF -Xep:InlineMeSuggester:OFF -Xep:CanIgnoreReturnValueSuggester:OFF -Xep:ExtendsObject:OFF -Xep:PatternMatchingInstanceof:OFF -Xep:StatementSwitchToExpressionSwitch:OFF' \
	  -Xmaxwarns 100000 \
	  -Werror \
	  ${extra-error-prone-args-1} \
	  ${JAVA_FILES_FOR_STYLE}
endif

# THIS IS BROKEN - IS IT EVER USED?
# Create an `error-prone.patch` file.
errorprone-replacements:
	javac -cp ${DAIKON_CLASSPATH} \
	  --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
	  --add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
	  -XDcompilePolicy=simple -processorpath ${ERRORPRONE_PROCESSOR_PATH} \
	  '-Xplugin:ErrorProne -XepPatchChecks:UnnecessaryParentheses,ArrayToString -XepPatchLocation:${DAIKONDIR}/java' \
	  -Xmaxwarns 100000 \
	  ${extra-error-prone-args-1} \
	  ${JAVA_FILES_FOR_STYLE}

findbugs: .findbugs-output
.PHONY: findbugs

# Takes about 20 minutes on manioc as of June 2005.
.findbugs-output: ../daikon.jar
	${MAKE} findbugs-nocompile

# WARNING: This does not use the class files, but the .jar file.
# So make sure it's up to date before using this.
# WARNING: I don't think this will work unless you're logged on as Michael Ernst.
findbugs-nocompile:
	rm -f .findbugs-output
	~mernst/bin/share/findbugs -emacs -textui -property "findbugs.maskedfields.locals=true" -property "findbugs.de.comment=true" -exclude .findbugs-exclude.xml -maxHeap 750 ../daikon.jar | tee .findbugs-output

# This target is aimed at M-x compile in Emacs.  The output is misleading
# if the .findbugs-output file might be old, or the daikon.jar file is old.
findbugs-cat:
	cat .findbugs-output

.PHONY: jar
jar: ../daikon.jar
../daikon.jar: ${PLUME_SCRIPTS} ${AUTO_GENERATED_FILES} compile
	${MAKE} -C .. daikon.jar

jlint:
	jlint . | grep -v "Value of referenced variable '.*' may be NULL" | grep -v "Compare strings as object references" | perl -p -e 's:^daikon/::'

# "(cd $inv; maudit daikon)" does not work; I don't understand why.
# Unfortunately, this is way too much output; I need to filter it.
# Maybe write my own script to do that...
audit:
	cd ${HOME}/java && maudit daikon | perl -p -e 's/^daikon\///'


.PHONY: reformat check-format

format: reformat
reformat:
ifeq (${JAVA17}, 0)
	echo "Formatting is not run under Java ${JAVA_VERSION_STRING}"
else
	${MAKE} -C .. update-run-google-java-format
	@../.utils/run-google-java-format/run-google-java-format.py \
	  ${JAVA_FILES_FOR_FORMAT}
endif

check-format:
ifeq (${JAVA17}, 0)
	echo "Formatting is not run under Java ${JAVA_VERSION_STRING}"
else
	${MAKE} -C .. update-run-google-java-format
	@../.utils/run-google-java-format/check-google-java-format.py \
	  ${JAVA_FILES_FOR_FORMAT} || (echo "Try running:  make reformat" && /bin/false)
endif


###########################################################################
### Pluggable type checkers
###

# (Don't run these until after you have compiled Daikon at least once.)

# Note about CHECKER_ARGS: if this contains any -Alint option, it will
# override (not augment) any other use of -Alint in this Makefile.
# "-proc:only" prevents generation of .class files (so generated classfiles are
# version 8 rather than version 9, and so typecheck jobs can be run in parallel).
# JAVACHECK_EXTRA_ARGS is set only by the user (and is currently used by Travis).
CHECKER_ARGS_ALL_JDK_VERSIONS ?= -Xmaxerrs 10000 -Xmaxwarns 10000 -Aversion -ArequirePrefixInWarningSuppressions -AwarnUnneededSuppressions -AwarnRedundantAnnotations -XDignore.symbol.file -Xlint:deprecation -proc:only -processorpath ${CHECKERFRAMEWORK_JAR} ${JAVACHECK_EXTRA_ARGS}
ifneq (,$(findstring 1.8.,$(shell java -version 2>&1)))
  CHECKER_ARGS ?= ${CHECKER_ARGS_ALL_JDK_VERSIONS} -J-Xbootclasspath/p:${CHECKERFRAMEWORK_JAVAC}
else
  CHECKER_ARGS ?= ${CHECKER_ARGS_ALL_JDK_VERSIONS} \
    ${JAVAC_ANNOTATION_PROCESSOR_ARGS}
endif

## All of the following targets need to depend on "compile".

## Code in dcomp directory is not called directly; annotations would be useless.
INDEX_SKIPDEFS := ^daikon\.dcomp\|^jtb\.
INTERNING_SKIPDEFS := ^daikon\.dcomp\|^jtb\.
ALLSYSTEMS_SKIPDEFS := ^jtb\.

# Just check that the Index Checker doesn't crash -- -AsuppressWarnings="index"
# command-line argument suppresses all type-checking errors.
JAVAC_RESOURCELEAK_ARGS := -processor org.checkerframework.checker.resourceleak.ResourceLeakChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}' -ApermitStaticOwning -ApermitInitializationLeak
JAVAC_FORMATTER_ARGS := -processor org.checkerframework.checker.formatter.FormatterChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_INDEX_ARGS := -processor org.checkerframework.checker.index.IndexChecker -implicit:class -Xlint:-processing -AskipDefs='${INDEX_SKIPDEFS}' -AassumeAssertionsAreEnabled -AsuppressWarnings="index"
# JAVAC_INTERNING_ARGS := -processor org.checkerframework.checker.interning.InterningChecker -implicit:class -Xlint:-processing
JAVAC_INTERNING_ARGS := -processor org.checkerframework.checker.interning.InterningChecker -Alint=-dotequals -implicit:class -Xlint:-processing -AskipDefs='${INTERNING_SKIPDEFS}'
JAVAC_NULLNESS_ARGS := -processor org.checkerframework.checker.nullness.NullnessChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_PROTOTYPE_ARGS := -processor org.checkerframework.common.subtyping.SubtypingChecker -Aquals=typequals.Prototype,typequals.NonPrototype -implicit:class -Xlint:-processing -J-Dcheckers.skipUses='^java\.'
JAVAC_REGEX_ARGS := -processor org.checkerframework.checker.regex.RegexChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_REGEX_QUAL_ARGS := -processor org.checkerframework.checker.experimental.regex_qual.RegexCheckerAdapter -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_SIGNATURE_ARGS := -processor org.checkerframework.checker.signature.SignatureChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_SIGNEDNESS_ARGS := -processor org.checkerframework.checker.signedness.SignednessChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_VINDEX_ARGS := -processor org.checkerframework.common.subtyping.SubtypingChecker -Aquals=typequals.VIndexTop,typequals.ValueIndex,typequals.VarIndex,typequals.VIndexUnqualified,typequals.VIndexBottom -implicit:class -Xlint:-processing -J-Dcheckers.skipUses='^java\.'
# -AsuppressWarnings=lock:method.guarantee.violated,lock:override.sideeffect is temporary.
# Once the Purity Checker and -AsuggestPureMethods are fixed, they can be run on plume-lib
# and Daikon and this can be removed. The method.guarantee.violated warning is issued by
# the Lock Checker when a method calls another method with a weaker side effect guarantee.
# The override.sideeffect warning is issued by the Lock Checker when the side effect
# annotation on the overridder method is weaker than that on the overridden method.
JAVAC_LOCK_ARGS := -processor org.checkerframework.checker.lock.LockChecker -AsuppressWarnings=lock:method.guarantee.violated,lock:override.sideeffect -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_JAVARI_ARGS := -processor org.checkerframework.checker.javari.JavariChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
JAVAC_IGJ_ARGS := -processor org.checkerframework.checker.igj.IGJChecker -implicit:class -Xlint:-processing -AskipDefs='${ALLSYSTEMS_SKIPDEFS}'
INDEX_JAVA_FILES := ${DAIKON_JAVA_FILES}
# Intern.java implements interning and so has very many annotations.  VarInfoName
# is obsolescent, retained for backward compatibility only; it is of flawed design
# and has 60 @Interned annotations and quite a few SuppressWarnings.
INTERNING_JAVA_FILES_SKIP_COUNTS := Intern.java\|VarInfoName.java\|daikon/dcomp
## Which files to check.
INTERNING_JAVA_FILES := ${DAIKON_JAVA_FILES}
INTERNING_JAVA_FILES_COUNTS := $(shell find . -type f -name '*.java' | egrep -v ${INTERNING_JAVA_FILES_SKIP_COUNTS} | xargs grep -l -i '@Interned' | ${SORT_DIRECTORY_ORDER})
NULLNESS_JAVA_FILES := ${DAIKON_JAVA_FILES}

#  $(shell find daikon -name '*.java' -a -exec grep -L "^@SuppressWarnings.*nullness" {} \; | sort)
#   $(shell find typequals/ -name '*.java')

show_nullness_java_files:
	@echo NULLNESS_JAVA_FILES:
	@echo ${NULLNESS_JAVA_FILES}
	@echo DAIKON_JAVA_FILES:
	@echo ${DAIKON_JAVA_FILES}

## TODO: Reinstate these dependencies later:  typecheck-prototype typecheck-vindex
# Check is in multiple parts because Travis won't run jobs longer than 50 minutes
# and because CI memory can get exhausted on multiple CI platforms (why?).
# Index Checker takes much longer than any other checker.
# Typechecking times (in minutes, as of 2025-11-03):
# formatter 1.25
# index 9
# interning 1.25
# nullness 3
# lock 1.75
# regex 1.25
# resourceleak 3.5
# signature 1.25
# signedness 3
# total: 25.5
# It is essential that "compile" completes before any typechecking commences.
typecheck-part1: ${ALL_GENERATED_FILES} compile compile-typequals
	${MAKE} typecheck-part1-nocompile
typecheck-part1-nocompile: typecheck-formatter-nocompile typecheck-interning-nocompile typecheck-nullness-nocompile typecheck-lock-nocompile typecheck-regex-nocompile
typecheck-part2: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-part2-nocompile
typecheck-part2-nocompile: typecheck-index-nocompile
typecheck-part3: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-part3-nocompile
typecheck-part3-nocompile: typecheck-resourceleak-nocompile typecheck-signature-nocompile typecheck-signedness-nocompile
typecheck-all: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-all-nocompile
typecheck-all-nocompile: typecheck-part1 typecheck-part2 typecheck-part3
typecheck: typecheck-all

typecheck-formatter: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-formatter-nocompile
typecheck-formatter-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_FORMATTER_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_FORMATTER_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-index: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-index-nocompile
typecheck-index-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_INDEX_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_INDEX_ARGS} ${CHECKER_ARGS} ${INDEX_JAVA_FILES}

# Run the index checker on all Java files, not just those in the daikon package.
# For instance, this includes jtb, which is not annotated with @Interned.
typecheck-index-all: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-index-all-nocompile
typecheck-index-all-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_INDEX_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_INDEX_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

# This target runs the Index checker on just one file.
# Typical command:
# INDEX_ONEFILE="daikon/derive/binary/SequenceStringIntersection.java daikon/derive/binary/SequenceStringUnion.java daikon/inv/unary/stringsequence/CommonStringSequence.java daikon/Quant.java" make typecheck-index-onefile
INDEX_ONEFILE ?= daikon/PptTopLevel.java
typecheck-index-onefile: ${ALL_GENERATED_FILES} compile
	${JAVAC_COMMAND} ${JAVAC_INDEX_ARGS} ${CHECKER_ARGS} ${INDEX_ONEFILE}

typecheck-interning: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-interning-nocompile
typecheck-interning-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} ${CHECKER_ARGS} ${INTERNING_JAVA_FILES}

# Run the interning checker on all Java files, not just those in the daikon package.
# For instance, this includes jtb, which is not annotated with @Interned.
typecheck-interning-all: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-interning-all-nocompile
typecheck-interning-all-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

# This target runs the Interning checker on just one file.
# Typical command:
# INTERNING_ONEFILE="daikon/derive/binary/SequenceStringIntersection.java daikon/derive/binary/SequenceStringUnion.java daikon/inv/unary/stringsequence/CommonStringSequence.java daikon/Quant.java" make typecheck-interning-onefile
INTERNING_ONEFILE ?= daikon/PptTopLevel.java
typecheck-interning-onefile: ${ALL_GENERATED_FILES} compile
	${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} ${CHECKER_ARGS} ${INTERNING_ONEFILE}

typecheck-lock: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-lock-nocompile
typecheck-lock-nocompile:
	@echo ${JAVAC_COMMAND} ${CHECKER_ARGS} ${JAVAC_LOCK_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_LOCK_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-nullness: compile compile-typequals
	${MAKE} typecheck-nullness-nocompile
typecheck-nullness-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_NULLNESS_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_NULLNESS_ARGS} ${CHECKER_ARGS} ${NULLNESS_JAVA_FILES}

# These targets run the Nullness checker on just one file.
# Typical command:
# NULLNESS_ONEFILE="daikon/derive/binary/SequenceStringIntersection.java daikon/derive/binary/SequenceStringUnion.java daikon/inv/unary/stringsequence/CommonStringSequence.java daikon/Quant.java" make typecheck-nullness-onefile
# NULLNESS_ONEFILE ?= daikon/derive/binary/SequenceStringUnion.java
# NULLNESS_ONEFILE ?= daikon/FileIO.java
NULLNESS_ONEFILE ?= daikon/Daikon.java
typecheck-nullness-onefile: compile compile-typequals
	${MAKE} typecheck-nullness-onefile-norecompile
typecheck-nullness-onefile-norecompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_NULLNESS_ARGS} ${CHECKER_ARGS} ${NULLNESS_ONEFILE}
	@${JAVAC_COMMAND} ${JAVAC_NULLNESS_ARGS} ${CHECKER_ARGS} ${NULLNESS_ONEFILE}

typecheck-prototype: compile compile-typequals
	${MAKE} typecheck-prototype-nocompile
typecheck-prototype-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_PROTOTYPE_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_PROTOTYPE_ARGS} ${CHECKER_ARGS} ${NULLNESS_JAVA_FILES}

typecheck-regex: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-regex-nocompile
typecheck-regex-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_REGEX_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_REGEX_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-regex-qual: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-regex-qual-nocompile
typecheck-regex-qual-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_REGEX_QUAL_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_REGEX_QUAL_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-resourceleak: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-resourceleak-nocompile
typecheck-resourceleak-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_RESOURCELEAK_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_RESOURCELEAK_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-signature: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-signature-nocompile
typecheck-signature-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_SIGNATURE_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_SIGNATURE_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

# This target runs the Signature checker on just one file.
# Typical command:
# SIGNATURE_ONEFILE="daikon/derive/binary/SequenceStringIntersection.java daikon/derive/binary/SequenceStringUnion.java daikon/inv/unary/stringsequence/CommonStringSequence.java daikon/Quant.java" make typecheck-signature-onefile
# SIGNATURE_ONEFILE ?= daikon/chicory/Instrument.java daikon/dcomp/DCInstrument.java
SIGNATURE_ONEFILE ?= daikon/dcomp/DCInstrument.java
typecheck-signature-onefile: ${ALL_GENERATED_FILES} compile
	${JAVAC_COMMAND} ${JAVAC_SIGNATURE_ARGS} ${CHECKER_ARGS} ${SIGNATURE_ONEFILE}

typecheck-signedness: ${ALL_GENERATED_FILES} compile
	${MAKE} typecheck-signedness-nocompile
typecheck-signedness-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_SIGNEDNESS_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_SIGNEDNESS_ARGS} ${CHECKER_ARGS} ${JAVA_FILES}

typecheck-vindex: compile compile-typequals
	${MAKE} typecheck-vindex-nocompile
typecheck-vindex-nocompile:
	@echo ${JAVAC_COMMAND} ${JAVAC_VINDEX_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} -Xbootclasspath/p:${DAIKONDIR}/java ${JAVAC_VINDEX_ARGS} ${CHECKER_ARGS} ${NULLNESS_JAVA_FILES}

TYPEQUALS_JAVA_FILES := $(wildcard typequals/*.java)
TYPEQUALS_CLASSES := $(subst .java,.class,${TYPEQUALS_JAVA_FILES})

compile-typequals: ${TYPEQUALS_CLASSES}
${TYPEQUALS_CLASSES}: ${TYPEQUALS_JAVA_FILES}
	${JAVAC_COMMAND} ${JAVAC_ARGS} ${TYPEQUALS_JAVA_FILES}

# These targets run the Interning checker on just one file.  They use ${JAVAC}
# instead of ${JAVAC_COMMAND}, to display a shorter, easier-to-read command.
typecheck-interning-varinfo:
	${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} daikon/VarInfo.java
typecheck-interning-fileio:
	${JAVAC_COMMAND} ${JAVAC_INTERNING_ARGS} daikon/FileIO.java

# "tail -1" is required when wc is given multiple arguments
interning-counts:
	@echo -n "Annotated files: "
	@echo ${INTERNING_JAVA_FILES_COUNTS} | sed 's/ /\n/g' | wc -l
#	@echo ${INTERNING_JAVA_FILES_COUNTS}
	@echo -n "Lines in annotated files: "
	@wc -l ${INTERNING_JAVA_FILES_COUNTS} | tail -1
	@echo -n "Lines with @Interned annotations: "
	@grep "@Interned" ${INTERNING_JAVA_FILES_COUNTS} | wc -l
	@echo -n "Lines with commented @Interned annotations: "
	@grep -E "//.*@Interned" ${INTERNING_JAVA_FILES_COUNTS} | wc -l
	@echo -n "@SuppressWarnings annotations: "
	@grep -n '@SuppressWarnings("interning")' ${INTERNING_JAVA_FILES_COUNTS} | wc -l
	@grep -n '@SuppressWarnings("interning")' ${INTERNING_JAVA_FILES_COUNTS}
	@echo -n "Daikon total files: "
	@echo ${DAIKON_JAVA_FILES} | sed 's/ /\n/g' | wc -l
	@echo -n "Daikon total lines: "
	@wc -l ${DAIKON_JAVA_FILES} | tail -1

# This counts annotations in comments, etc.
# "tail -1" is required when wc is given multiple arguments
nullness-counts:
	@echo -n "Annotated files (lines, blank, comments, NCSL, AESL): "
	@echo ${NULLNESS_JAVA_FILES} | xargs sclc | tail -1
	@echo -n "Total files (lines, blank, comments, NCSL, AESL): "
	@echo ${DAIKON_JAVA_FILES} | xargs sclc | tail -1
# 	@echo -n "Annotated files: "
# 	@echo ${NULLNESS_JAVA_FILES} | sed 's/ /\n/g' | wc -l
# 	@echo -n " / "
# 	@echo ${DAIKON_JAVA_FILES} | sed 's/ /\n/g' | wc -l
# #	@echo ${NULLNESS_JAVA_FILES}
# 	@echo -n "Lines in annotated files: "
# 	@echo ${NULLNESS_JAVA_FILES} | xargs wc -l | tail -1 | cut -d ' ' -f 2
# 	@echo -n " / "
# 	@echo ${DAIKON_JAVA_FILES} | xargs wc -l | tail -1 | cut -d ' ' -f 2
	@echo -n "Lines with nullness annotations: "
	@grep '@AssertNonNullIfFalse\|@AssertNonNullIfTrue\|@AssertParametersNonNull\|@KeyFor\|@LazyNonNull\|@NonNull\|@NonNullOnEntry\|@Nullable\|@PolyNull\|@Pure' ${NULLNESS_JAVA_FILES} | wc -l
	@echo -n "Lines with @SuppressWarnings annotation or castNonNull method call: "
	@grep '@SuppressWarnings.*nullness\|castNonNull' ${NULLNESS_JAVA_FILES} | wc -l
	@grep -n '@SuppressWarnings.*nullness\|castNonNull' ${NULLNESS_JAVA_FILES}


# Count the total possible locations at which a type annotation could be written.
JAVAC_COUNT_ARGS := -processor org.checkerframework.common.util.count.Locations -implicit:class -Xlint:-processing
possible-annos: ${ALL_GENERATED_FILES} compile-typequals compile
	@echo ${JAVAC_COMMAND} ${JAVAC_COUNT_ARGS} ${CHECKER_ARGS} ...
	@${JAVAC_COMMAND} ${JAVAC_COUNT_ARGS} ${CHECKER_ARGS} ${NULLNESS_JAVA_FILES}



###########################################################################
### Testing
###

.PHONY: test tests
test tests: daikon-tests
daikon-tests: smoke-test
	${MAKE} -C ../tests all

# run a static check on currently-compiled classes
# ensure serialized classes have a date-style UID assigned
check-serialize:
#	for each non-gui class, run serialver
#	accept only "is not Serializable" or "UID = 200#####" as output
# TODO: This produces output in nondeterministic order
	@find daikon -follow -name 'gui' -prune -o -name '*.class' -print | perl -ne 's|\.class\n$$||; s|/|.|g; print "Checking $$_... \t"; $$_ =~ s|\$$|\\\$$|g; $$msg =`serialver -J-Djava.compiler=NONE $$_ 2>&1`; if ($$msg =~ m/is not Serializable/) { print "ok (not serialized)\n"; next; } if ($$msg =~m/UID = (200\d[01]\d[0123]\d)L;/) { print "ok ($$1)\n"; next; }  print "WARNING: incorrect: $$msg";'


.PHONY: junit
junit: daikon/Daikon.class
	@echo "Running unit (not system) tests..."
	LC_ALL=en_US.UTF-8 ${JAVA_COMMAND} org.junit.runner.JUnitCore daikon.test.AllTestsSuite

## TODO:  This target is never used!!!
junit-all: junit
	@# Alternately, MasterUnitTester could run SplitterFactoryTest,
	@# but I'm having trouble with that, apparently due to hard-coded
	@# directory paths.  And these tests are slow, so we want them to
	@# be separate anyway.
	${JAVA_COMMAND} daikon.test.split.SplitterFactoryTest

###
### Clover (code coverage)
###

CLOVER := ${HOME}/clover
CLOVER_CMD := ${JAVA_COMMAND} -cp ${CLOVER}/clover-1.3.1/lib/clover.jar \
									com.cenqua.clover.CloverInstr -jdk14
CLOVER_CP := $(subst ${DAIKONDIR}/java,${CLOVER}/java,${DAIKON_CLASSPATH})
CLOVER_CP := ${CLOVER_CP}:${CLOVER}/clover-1.3.1/lib/clover.jar

clover: all_directly
	/bin/rm -rf ${CLOVER}/java
	mkdir ${CLOVER}/java
	cd ${CLOVER}/java; ln -s ${DAIKONDIR}/java/jtb
	cd ${CLOVER}/java; ln -s ${DAIKONDIR}/java/lib
	cp Makefile ${CLOVER}/java
	mkdir ${CLOVER}/java/daikon
	(cd daikon; tar cf - .) | (cd ${CLOVER}/java/daikon; tar xfBp -)
	chmod -R a+w ${CLOVER}/java/daikon
	mkdir ${CLOVER}/java/utilMDE
	(cd utilMDE; tar cf - .) | (cd ${CLOVER}/java/utilMDE; tar xfBp -)
	chmod -R a+w ${CLOVER}/java/utilMDE
	${CLOVER_CMD} -i ${CLOVER}/clover.db -s daikon -d ${CLOVER}/java/daikon
	${CLOVER_CMD} -i ${CLOVER}/clover.db -s utilMDE -d ${CLOVER}/java/utilMDE
	cd ${CLOVER}/java; \
	  ${JAVAC_COMMAND} -classpath ${CLOVER_CP} -g -target 1.1 daikon/Daikon.java


###########################################################################
### Documentation
###

JAVADOC_DEST := api
# ${DAIKONDIR}/java should not be in classpath, to avoid Javadoc error
# "Multiple sources of package comments found for package".
# It also keeps javadoc from finding "*24.java"
# Removed "-source 8" because it causes a crash under JDK 11:  https://bugzilla.redhat.com/show_bug.cgi?id=1874672
JAVADOC_FLAGS_COMMON := -breakiterator -quiet -linksource -noqualifier all \
                -Xmaxerrs 100000 -Xmaxwarns 100000 \
                -d ${JAVADOC_DEST} \
                -linkoffline ${LINKOFFLINE} ${LINKOFFLINE} \
		-notimestamp \
                -classpath "$(subst *:${DAIKONDIR}/java,*,${DAIKON_CLASSPATH})"
JAVADOC_FLAGS := ${JAVADOC_FLAGS_COMMON} \
                -docletpath "${DOCLETPATH}"

# Daikon packages except for util (which is just a copy of plume), plume,
# and dummy packages such as daikon.dcomp-dummy and daikon.dcomp-transfer.
DAIKON_PACKAGES := $(shell ls -F daikon | grep / | egrep -v 'util' | egrep -v 'dcomp-' \
				   | sed s./.. | sed s/^/daikon./ | tr '\n' ':')

# Don't run Javadoc on files that require the Checker Framework.
# .PHONY means regenerate even if the file exists.
.PHONY: javadoc-files.txt
javadoc-files.txt:
	${MAKE} ${AUTO_GENERATED_FILES}
	find * \( -name 'PrototypeChecker.java' -o -name 'VIndexChecker.java' -o -name 'VIndexAnnotatedTypeFactory.java' -o -path 'daikon/dcomp-transfer' \) -prune -o -name "*24.java" -prune -o -name "*.java" -print | ${SORT_DIRECTORY_ORDER} > javadoc-files.txt
ifeq (${JAVA24}, 1)
	find * -name "*24.java" -print | ${SORT_DIRECTORY_ORDER} >> javadoc-files.txt
endif

# If Java 8, don't run javadoc; a bug in javadoc causes it to crash.
ifeq (${JAVA8}, 1)
  SKIP_JAVADOC=1
endif

# Build javadoc using the daikon package and all subpackages of daikon.
javadoc: api
.PHONY: api
api: ${PLUME_SCRIPTS} ../.utils/html-tools ${AUTO_GENERATED_FILES}
ifeq (${SKIP_JAVADOC},1)
	java -version
	@echo SKIP_JAVADOC=${SKIP_JAVADOC}
	@echo Skipping javadoc on JDK 1.8 because of https://bugs.openjdk.java.net/browse/JDK-8215542
else
	mkdir -p ${JAVADOC_DEST}
	@make javadoc-files.txt
	${JAVADOC_COMMAND} -J-Xmx7g -J-ea ${JAVADOC_FLAGS} -Xdoclint:all ${DOCLET_FLAGS} \
		@javadoc-files.txt
	@rm -f javadoc-files.txt
	cd ${JAVADOC_DEST} && ${PLUME_SCRIPTS}/preplace '^ *&#64;cindex.*' ''
	cp -pf ../doc/daikon-favicon.png ${JAVADOC_DEST}
	cd ${JAVADOC_DEST} && ${HTMLTOOLS}/html-add-favicon . daikon-favicon.png
endif

# Run Javadoc on each file individually, to determine which one is crashing Javadoc.
# Search the *-javadoc-output.txt files to find out which one contains the crash log.
# Then, you need to do binary search on that file.
api-test-each: ${PLUME_SCRIPTS} ../.utils/html-tools ${AUTO_GENERATED_FILES}
ifeq (${SKIP_JAVADOC},1)
	java -version
	@echo SKIP_JAVADOC=${SKIP_JAVADOC}
	@echo Skipping javadoc on JDK 1.8 because of https://bugs.openjdk.java.net/browse/JDK-8215542
else
	mkdir -p ${JAVADOC_DEST}
	@make javadoc-files.txt
	while read filename ; do echo "filename: $$filename" ; ${JAVADOC_COMMAND} -J-Xmx7g -J-ea ${JAVADOC_FLAGS} ${DOCLET_FLAGS} $$filename > $$filename-javadoc-output.txt 2>&1 ; done < javadoc-files.txt
	@rm -f javadoc-files.txt
endif

## Make Javadoc with private fields for people working on source code.
## It is generated in the standard location, directory api/
api-private: ${PLUME_SCRIPTS} ${AUTO_GENERATED_FILES}
ifeq ($(shell test ${JAVA_RELEASE_NUMBER} -eq 8; echo $$?),0)
	@echo "Skipping api-private target under Java 8"
else
	mkdir -p ${JAVADOC_DEST}
	${JAVADOC_COMMAND} ${extra-javadoc-args} -J-Xmx7g -J-ea ${JAVADOC_FLAGS} -private -Xdoclint:all ${DOCLET_FLAGS} \
	  daikon -subpackages ${DAIKON_PACKAGES}
	cd ${JAVADOC_DEST} && ${PLUME_SCRIPTS}/preplace '^ *&#64;cindex.*' ''
endif

## Test that each program component is documented with Javadoc.
## You should regenerate api/ after running this.
requireJavadoc: ${JAVA_FILES}
# For refactorings that touch a lot of code that you don't understand, create
# top-level file SKIP-REQUIRE-JAVADOC.  Delete it after the pull request is merged.
	if [ ! -f SKIP-REQUIRE-JAVADOC ]; then \
	  ${JAVA} \
	    --add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
	    --add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
	    --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
	    --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
	    --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
	    --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
	    --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
	    --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
	    -jar $(wildcard ${DAIKONDIR}/java/lib/require-javadoc/require-javadoc-*-all.jar) \
	    --exclude="dcomp-transfer" \
	    ${DAIKON_JAVA_FILES} ; \
	fi

../doc/invariants-doc.texinfo: ${PLUME_SCRIPTS} daikon/config/InvariantDoclet.class daikon/config/HtmlToTexinfo.class
	@make javadoc-files.txt
	${JAVADOC_COMMAND} ${extra-javadoc-args} -J-Xmx7g -J-ea -docletpath "${DOCLETPATH}" -classpath "${DAIKON_CLASSPATH}" -doclet daikon.config.InvariantDoclet ${DOCLET_FLAGS} \
		--texinfo $@.tmp \
		@javadoc-files.txt
	mv -f $@.tmp $@
	@rm -f javadoc-files.txt

# This fails if both . and pwd are on CLASSPATH:  classes are found twice
# resulting in a duplicate class warning.

../doc/config-options.texinfo: ${PLUME_SCRIPTS} daikon/config/ParameterDoclet.class daikon/config/HtmlToTexinfo.class
	@make javadoc-files.txt
	${JAVADOC_COMMAND} ${extra-javadoc-args} -J-Xmx7g -J-ea -docletpath "${DOCLETPATH}" -classpath "${DAIKON_CLASSPATH}" -doclet daikon.config.ParameterDoclet ${DOCLET_FLAGS} \
		--texinfo $@.tmp \
		@javadoc-files.txt
	perl -pi -e 's/&#64;cindex/\@cindex/g' $@.tmp
	mv -f $@.tmp $@
	@rm -f javadoc-files.txt

daikon/config/InvariantDoclet.class: daikon/config/InvariantDoclet.java
	${MAKE} compile

daikon/config/ParameterDoclet.class: daikon/config/ParameterDoclet.java
	${MAKE} compile

daikon/config/HtmlToTexinfo.class: daikon/config/HtmlToTexinfo.java
	${MAKE} compile


###########################################################################
### For debugging the Makefile.
###

showvars:
	@echo PWD = $(shell pwd)
	@echo OSTYPE = $${OSTYPE}
	@echo PATH = $${PATH}

	@echo JAVA_HOME = ${JAVA_HOME}
	which java
	java -version 2>&1
	which javac
	javac -version
	@echo JAVA = ${JAVA}
	@echo JAVA_COMMAND = ${JAVA_COMMAND}
	@echo JAVAC = ${JAVAC}
	@echo JAVAC_ARGS = ${JAVAC_ARGS}
	@echo JAVAC_COMMAND = ${JAVAC_COMMAND}
	@echo SKIP_JAVADOC = ${SKIP_JAVADOC}
	@echo JAVA24 = ${JAVA24}

	@echo CLASSPATH = "${CLASSPATH}"
	@echo DAIKON_CLASSPATH = "${DAIKON_CLASSPATH}"
	@echo DOCLETPATH = "${DOCLETPATH}"

	@echo AUTO_GENERATED_FILES = ${AUTO_GENERATED_FILES}
	@echo DAIKONDIR = "${DAIKONDIR}"
	@echo DAIKONSCRIPTS = ${DAIKONSCRIPTS}
	@echo PLUME_SCRIPTS = ${PLUME_SCRIPTS}

	@echo DAIKON_PACKAGES = ${DAIKON_PACKAGES}
	@echo DAIKON_JAVA_FILES = ${DAIKON_JAVA_FILES}
	@echo JAVA_FILES = ${JAVA_FILES}
	@echo JAVA_FILES_FOR_STYLE = ${JAVA_FILES_FOR_STYLE}
	@echo JAVA_FILES_FOR_FORMAT = ${JAVA_FILES_FOR_FORMAT}
	@echo TAG_FILES = ${TAG_FILES}
	@echo INTERNING_JAVA_FILES = ${INTERNING_JAVA_FILES}
	@echo INTERNING_JAVA_FILES_COUNTS = ${INTERNING_JAVA_FILES_COUNTS}
	@echo CHICORY_JAVA_FILES = ${CHICORY_JAVA_FILES}

	@echo CHECKERFRAMEWORK = ${CHECKERFRAMEWORK}
	@echo CHECKERFRAMEWORK_JAR_DIR = ${CHECKERFRAMEWORK_JAR_DIR}
	@echo CHECKERFRAMEWORK_JAR = ${CHECKERFRAMEWORK_JAR}
	@echo CHECKERFRAMEWORK_JAVAC = ${CHECKERFRAMEWORK_JAVAC}


dump: showvars

showvar_JAVA_FILES:
	@echo ${JAVA_FILES}

showvar_CLASS_FILES:
	@echo $(subst .java,.class,${JAVA_FILES})

showvar_JAVA_FILES_FOR_FORMAT:
	@echo ${JAVA_FILES_FOR_FORMAT}

list_java_files: showvar_JAVA_FILES


###########################################################################
### Automatically generated files
###

# This must NOT depend on "daikon/Daikon.class", as that would lead to infinite regress.
daikon/test/split/SplitterFactoryTestUpdater.class: daikon/test/split/SplitterFactoryTestUpdater.java
	${JAVAC_COMMAND} $<

## First, a file not generated via java-cpp.
daikon/test/split/SplitterFactoryTest.java: daikon/test/split/SplitterFactoryTestUpdater.class
	rm -f $@
# Has expected errors while compiling splitter files.
# Suppress output unless whole command fails.
	(${JAVA_COMMAND} daikon.test.split.SplitterFactoryTestUpdater > /dev/null 2>&1) || ${JAVA_COMMAND} daikon.test.split.SplitterFactoryTestUpdater
	chmod a-w $@

${AUTO_GENERATED_CLASSES_2}: ${AUTO_GENERATED_FILES_2}
	${JAVAC_COMMAND} ${AUTO_GENERATED_FILES_2}

# Create the auto-generated files with jpp
.PHONY: jpp
jpp: ${PLUME_SCRIPTS} ${AUTO_GENERATED_FILES}

# Use this rule if you do not have cpp or for some other reason do not want
# to refresh the automatically generated .java files.  You should not do
# this if those files are not up-to-date (that is, if you have modified the
# .jpp files).  It is safe to do this with a distribution that you have
# just unpacked.
avoid-jpp:
	@echo "Any recent changes in the .jpp files will not get propagated."
	touch ${AUTO_GENERATED_FILES}


# ":=" does not work here; the variables get expanded too soon.
# "-e" means exit immediately if any error, rather than returning
# the status of the last command.

# This rule does not work with make 3.77, but does work with make 3.78.
JAVA_CPP ?= (rm -f $@; ${DAIKONSCRIPTS}/java-cpp -DDEFINEDVAR $< 2>&1 > $@ && chmod a-w $@)
# Like the above, but also makes a backup file
# JAVA_CPP = (mv -f $@ $@-bak; set -e; ${PLUME_SCRIPTS}/java-cpp -DDEFINEDVAR $< > $@; chmod a-w $@)

# JAVA_CPP = (cp -pf $@ $@-bak; set -e; java-cpp $< -DDEFINEDVAR > $@-postproc; mv -f $@-postproc $@; chmod a-w $@)
## Here are alternate ways of writing the same command:
## I could use "define", but that's specific to GNU Make
## I can't do this because the CPP defined variable changes.
# JAVA_CPP = (mv -f $@ $@-bak; set -e; java-cpp $< -DDEFINEDVAR > $@; chmod a-w $@)
## These are used like:	${JAVA_CPP_START} -DLOWER ${JAVA_CPP_END}
# JAVA_CPP_START = (cp -pf $@ $@-bak; set -e; java-cpp $<
# JAVA_CPP_END = > $@-postproc; mv -f $@-postproc $@; chmod a-w $@)

daikon/PptSlice1.java: daikon/PptSlice.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ARITY1)

daikon/PptSlice2.java: daikon/PptSlice.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ARITY2)

daikon/PptSlice3.java: daikon/PptSlice.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ARITY3)

daikon/Quant.java: daikon/Quant.java.jpp daikon/QuantBody.java.jpp
	${JAVA_CPP}

daikon/inv/ternary/threeScalar/FunctionBinary.java: daikon/inv/ternary/threeScalar/FunctionBinary.java.jpp daikon/inv/ternary/threeScalar/FunctionBinaryGeneric.java.jpp daikon/inv/ternary/threeScalar/FunctionBinarySymmetric.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/ternary/threeScalar/FunctionBinaryFloat.java: daikon/inv/ternary/threeScalar/FunctionBinary.java.jpp daikon/inv/ternary/threeScalar/FunctionBinaryGeneric.java.jpp daikon/inv/ternary/threeScalar/FunctionBinarySymmetric.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/ternary/threeScalar/ThreeScalar.java: daikon/inv/ternary/threeScalar/ThreeScalar.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/ternary/threeScalar/ThreeFloat.java: daikon/inv/ternary/threeScalar/ThreeScalar.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/ternary/threeScalar/LinearTernaryCore.java: daikon/inv/ternary/threeScalar/LinearTernaryCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/ternary/threeScalar/LinearTernaryCoreFloat.java: daikon/inv/ternary/threeScalar/LinearTernaryCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/ternary/threeScalar/LinearTernary.java: daikon/inv/ternary/threeScalar/LinearTernary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/ternary/threeScalar/LinearTernaryFloat.java: daikon/inv/ternary/threeScalar/LinearTernary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/unary/LowerBoundCore.java: daikon/inv/unary/BoundCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LOWER)

daikon/inv/unary/UpperBoundCore.java: daikon/inv/unary/BoundCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=UPPER)

daikon/inv/unary/LowerBoundCoreFloat.java: daikon/inv/unary/BoundCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LOWERFLOAT)

daikon/inv/unary/UpperBoundCoreFloat.java: daikon/inv/unary/BoundCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=UPPERFLOAT)

daikon/inv/unary/scalar/NonZero.java: daikon/inv/unary/scalar/NonZero.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/inv/unary/scalar/NonZeroFloat.java: daikon/inv/unary/scalar/NonZero.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/inv/unary/scalar/RangeInt.java: daikon/inv/unary/scalar/Range.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/inv/unary/scalar/RangeFloat.java: daikon/inv/unary/scalar/Range.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/inv/unary/scalar/LowerBound.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LOWER)

daikon/inv/unary/scalar/UpperBound.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=UPPER)

daikon/inv/unary/scalar/LowerBoundFloat.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LOWERFLOAT)

daikon/inv/unary/scalar/UpperBoundFloat.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=UPPERFLOAT)

daikon/inv/unary/scalar/OneOfScalar.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/inv/unary/scalar/OneOfFloat.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/inv/unary/string/OneOfString.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/inv/unary/sequence/EltRangeInt.java: daikon/inv/unary/scalar/Range.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALARSEQ)

daikon/inv/unary/sequence/EltRangeFloat.java: daikon/inv/unary/scalar/Range.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOATSEQ)

daikon/inv/unary/sequence/OneOfSequence.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SEQUENCE)

daikon/inv/unary/sequence/OneOfFloatSequence.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOATSEQUENCE)

daikon/inv/unary/sequence/EltOneOf.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELT)

daikon/inv/unary/sequence/EltOneOfFloat.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTFLOAT)

daikon/inv/unary/sequence/EltLowerBound.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTLOWER)

daikon/inv/unary/sequence/EltLowerBoundFloat.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTLOWERFLOAT)

daikon/inv/unary/sequence/EltUpperBound.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTUPPER)

daikon/inv/unary/sequence/EltUpperBoundFloat.java: daikon/inv/unary/scalar/Bound.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTUPPERFLOAT)

daikon/inv/unary/sequence/NoDuplicates.java: daikon/inv/unary/sequence/NoDuplicates.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/unary/sequence/NoDuplicatesFloat.java: daikon/inv/unary/sequence/NoDuplicates.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/unary/sequence/SeqIndexIntEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/unary/sequence/SeqIndexFloatEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/unary/sequence/SeqIndexIntNonEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=NONEQUAL)

daikon/inv/unary/sequence/SeqIndexFloatNonEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=NONEQUALFLOAT)

daikon/inv/unary/sequence/SeqIndexIntLessThan.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/unary/sequence/SeqIndexFloatLessThan.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/unary/sequence/SeqIndexIntLessEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/unary/sequence/SeqIndexFloatLessEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/unary/sequence/SeqIndexIntGreaterThan.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/unary/sequence/SeqIndexFloatGreaterThan.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/unary/sequence/SeqIndexIntGreaterEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/unary/sequence/SeqIndexFloatGreaterEqual.java: daikon/inv/unary/sequence/SeqIndexComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/unary/sequence/CommonSequence.java: daikon/inv/unary/sequence/CommonSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/unary/sequence/CommonFloatSequence.java: daikon/inv/unary/sequence/CommonSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/unary/sequence/EltNonZero.java: daikon/inv/unary/sequence/EltNonZero.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/unary/sequence/EltNonZeroFloat.java: daikon/inv/unary/sequence/EltNonZero.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/unary/sequence/EltwiseIntComparison.java: daikon/inv/unary/sequence/EltwiseIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/unary/sequence/EltwiseFloatComparison.java: daikon/inv/unary/sequence/EltwiseIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/unary/sequence/EltwiseIntEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/unary/sequence/EltwiseIntLessThan.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/unary/sequence/EltwiseIntLessEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/unary/sequence/EltwiseIntGreaterThan.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/unary/sequence/EltwiseIntGreaterEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/unary/sequence/EltwiseFloatEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/unary/sequence/EltwiseFloatLessThan.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/unary/sequence/EltwiseFloatLessEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/unary/sequence/EltwiseFloatGreaterThan.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/unary/sequence/EltwiseFloatGreaterEqual.java: daikon/inv/unary/sequence/EltwiseIntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/unary/stringsequence/EltOneOfString.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=ELTSTRING)

daikon/inv/unary/stringsequence/OneOfStringSequence.java: daikon/inv/unary/OneOf.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRINGSEQUENCE)

daikon/inv/binary/sequenceScalar/Member.java: daikon/inv/binary/Member.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/inv/binary/sequenceScalar/MemberFloat.java: daikon/inv/binary/Member.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/inv/binary/sequenceString/MemberString.java: daikon/inv/binary/Member.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/inv/binary/sequenceString/SequenceString.java: daikon/inv/binary/sequenceScalar/SequenceScalar.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPESTRING)

daikon/inv/binary/sequenceScalar/SeqIntLessThan.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/binary/sequenceScalar/SeqIntGreaterThan.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/binary/sequenceScalar/SeqIntLessEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/binary/sequenceScalar/SeqIntGreaterEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/binary/sequenceScalar/SeqIntEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/binary/sequenceScalar/SeqFloatLessThan.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/binary/sequenceScalar/SeqFloatGreaterThan.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/binary/sequenceScalar/SeqFloatLessEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/binary/sequenceScalar/SeqFloatGreaterEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/binary/sequenceScalar/SeqFloatEqual.java: daikon/inv/binary/sequenceScalar/SeqIntComparison.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/binary/sequenceScalar/SequenceScalar.java: daikon/inv/binary/sequenceScalar/SequenceScalar.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/sequenceScalar/SequenceFloat.java: daikon/inv/binary/sequenceScalar/SequenceScalar.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoScalar/TwoScalar.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoScalar/TwoFloat.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoScalar/IntEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/binary/twoScalar/FloatEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/binary/twoString/TwoString.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPESTRING)

daikon/inv/binary/twoString/StringEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALSTRING)

daikon/inv/binary/twoScalar/IntNonEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=NONEQUAL)

daikon/inv/binary/twoScalar/FloatNonEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=NONEQUALFLOAT)

daikon/inv/binary/twoString/StringNonEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=NONEQUALSTRING)

daikon/inv/binary/twoScalar/IntLessThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/binary/twoScalar/FloatLessThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/binary/twoString/StringLessThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANSTRING)

daikon/inv/binary/twoScalar/IntLessEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/binary/twoScalar/FloatLessEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/binary/twoString/StringLessEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALSTRING)

daikon/inv/binary/twoScalar/IntGreaterThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/binary/twoScalar/FloatGreaterThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/binary/twoString/StringGreaterThan.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANSTRING)

daikon/inv/binary/twoScalar/IntGreaterEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/binary/twoScalar/FloatGreaterEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/binary/twoString/StringGreaterEqual.java: daikon/inv/binary/twoScalar/IntComparisons.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALSTRING)

daikon/inv/binary/twoScalar/NumericInt.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoScalar/NumericFloat.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoString/StdString.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPESTRING)

daikon/inv/binary/twoScalar/LinearBinaryCore.java: daikon/inv/binary/twoScalar/LinearBinaryCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoScalar/LinearBinaryCoreFloat.java: daikon/inv/binary/twoScalar/LinearBinaryCore.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoScalar/LinearBinary.java: daikon/inv/binary/twoScalar/LinearBinary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoScalar/LinearBinaryFloat.java: daikon/inv/binary/twoScalar/LinearBinary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoSequence/TwoSequence.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONGSEQ)

daikon/inv/binary/twoSequence/TwoSequenceFloat.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLESEQ)

daikon/inv/binary/twoSequence/TwoSequenceString.java: daikon/inv/binary/BinaryInvariant.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPESTRINGSEQ)

daikon/inv/binary/twoSequence/SeqSeqIntEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/binary/twoSequence/SeqSeqIntLessThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/binary/twoSequence/SeqSeqIntGreaterThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/binary/twoSequence/SeqSeqIntLessEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/binary/twoSequence/SeqSeqIntGreaterEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/binary/twoSequence/SeqSeqFloatEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/binary/twoSequence/SeqSeqFloatLessThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/binary/twoSequence/SeqSeqFloatGreaterThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/binary/twoSequence/SeqSeqFloatLessEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/binary/twoSequence/SeqSeqFloatGreaterEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/binary/twoSequence/SeqSeqStringEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALSTRING)

daikon/inv/binary/twoSequence/SeqSeqStringLessThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANSTRING)

daikon/inv/binary/twoSequence/SeqSeqStringGreaterThan.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANSTRING)

daikon/inv/binary/twoSequence/SeqSeqStringLessEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALSTRING)

daikon/inv/binary/twoSequence/SeqSeqStringGreaterEqual.java: daikon/inv/binary/twoSequence/SeqComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALSTRING)

daikon/inv/binary/twoSequence/Reverse.java: daikon/inv/binary/twoSequence/Reverse.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoSequence/ReverseFloat.java: daikon/inv/binary/twoSequence/Reverse.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoSequence/SubSequence.java: daikon/inv/binary/twoSequence/SubSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUBLONG)

daikon/inv/binary/twoSequence/SuperSequence.java: daikon/inv/binary/twoSequence/SubSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUPERLONG)

daikon/inv/binary/twoSequence/SubSequenceFloat.java: daikon/inv/binary/twoSequence/SubSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUBDOUBLE)

daikon/inv/binary/twoSequence/SuperSequenceFloat.java: daikon/inv/binary/twoSequence/SubSequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUPERDOUBLE)

daikon/inv/binary/twoSequence/SubSet.java: daikon/inv/binary/twoSequence/SubSet.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUB)

daikon/inv/binary/twoSequence/SubSetFloat.java: daikon/inv/binary/twoSequence/SubSet.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUBFLOAT)

daikon/inv/binary/twoSequence/SuperSet.java: daikon/inv/binary/twoSequence/SubSet.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUP)

daikon/inv/binary/twoSequence/SuperSetFloat.java: daikon/inv/binary/twoSequence/SubSet.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SUPFLOAT)

daikon/inv/binary/twoSequence/PairwiseIntEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUAL)

daikon/inv/binary/twoSequence/PairwiseIntLessThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHAN)

daikon/inv/binary/twoSequence/PairwiseIntGreaterThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHAN)

daikon/inv/binary/twoSequence/PairwiseIntLessEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUAL)

daikon/inv/binary/twoSequence/PairwiseIntGreaterEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUAL)

daikon/inv/binary/twoSequence/PairwiseFloatEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALFLOAT)

daikon/inv/binary/twoSequence/PairwiseFloatLessThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANFLOAT)

daikon/inv/binary/twoSequence/PairwiseFloatGreaterThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANFLOAT)

daikon/inv/binary/twoSequence/PairwiseFloatLessEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALFLOAT)

daikon/inv/binary/twoSequence/PairwiseFloatGreaterEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALFLOAT)

daikon/inv/binary/twoSequence/PairwiseStringEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=EQUALSTRING)

daikon/inv/binary/twoSequence/PairwiseStringLessThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSTHANSTRING)

daikon/inv/binary/twoSequence/PairwiseStringGreaterThan.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATERTHANSTRING)

daikon/inv/binary/twoSequence/PairwiseStringLessEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=LESSEQUALSTRING)

daikon/inv/binary/twoSequence/PairwiseStringGreaterEqual.java: daikon/inv/binary/twoSequence/PairwiseIntComparison.java.jpp daikon/inv/suppressionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=GREATEREQUALSTRING)

daikon/inv/binary/twoSequence/PairwiseLinearBinary.java: daikon/inv/binary/twoSequence/PairwiseLinearBinary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/inv/binary/twoSequence/PairwiseLinearBinaryFloat.java: daikon/inv/binary/twoSequence/PairwiseLinearBinary.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/inv/binary/twoSequence/PairwiseNumericInt.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONGSEQ)

daikon/inv/binary/twoSequence/PairwiseNumericFloat.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLESEQ)

daikon/inv/binary/twoSequence/PairwiseString.java: daikon/inv/binary/twoScalar/Numeric.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPESTRINGSEQ)

daikon/derive/ternary/SequenceScalarArbitrarySubsequence.java: daikon/derive/ternary/SequenceArbitrarySubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/ternary/SequenceFloatArbitrarySubsequence.java: daikon/derive/ternary/SequenceArbitrarySubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/ternary/SequenceStringArbitrarySubsequence.java: daikon/derive/ternary/SequenceArbitrarySubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/ternary/SequenceScalarArbitrarySubsequenceFactory.java: daikon/derive/ternary/SequenceArbitrarySubsequenceFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/ternary/SequenceFloatArbitrarySubsequenceFactory.java: daikon/derive/ternary/SequenceArbitrarySubsequenceFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/ternary/SequenceStringArbitrarySubsequenceFactory.java: daikon/derive/ternary/SequenceArbitrarySubsequenceFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarSubscript.java: daikon/derive/binary/SequenceSubscript.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatSubscript.java: daikon/derive/binary/SequenceSubscript.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringSubscript.java: daikon/derive/binary/SequenceSubscript.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarSubsequence.java: daikon/derive/binary/SequenceSubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatSubsequence.java: daikon/derive/binary/SequenceSubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringSubsequence.java: daikon/derive/binary/SequenceSubsequence.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarSubscriptFactory.java: daikon/derive/binary/SequenceSubscriptFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatSubscriptFactory.java: daikon/derive/binary/SequenceSubscriptFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringSubscriptFactory.java: daikon/derive/binary/SequenceSubscriptFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarIntersection.java: daikon/derive/binary/SequencesIntersection.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatIntersection.java: daikon/derive/binary/SequencesIntersection.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringIntersection.java: daikon/derive/binary/SequencesIntersection.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarIntersectionFactory.java: daikon/derive/binary/SequencesIntersectionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatIntersectionFactory.java: daikon/derive/binary/SequencesIntersectionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringIntersectionFactory.java: daikon/derive/binary/SequencesIntersectionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarUnion.java: daikon/derive/binary/SequencesUnion.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatUnion.java: daikon/derive/binary/SequencesUnion.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringUnion.java: daikon/derive/binary/SequencesUnion.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequenceScalarUnionFactory.java: daikon/derive/binary/SequencesUnionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=SCALAR)

daikon/derive/binary/SequenceFloatUnionFactory.java: daikon/derive/binary/SequencesUnionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=FLOAT)

daikon/derive/binary/SequenceStringUnionFactory.java: daikon/derive/binary/SequencesUnionFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=STRING)

daikon/derive/binary/SequencesPredicate.java: daikon/derive/binary/SequencesPredicate.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/binary/SequencesPredicateFloat.java: daikon/derive/binary/SequencesPredicate.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/derive/binary/SequencesPredicateFactory.java: daikon/derive/binary/SequencesPredicateFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/binary/SequencesPredicateFactoryFloat.java: daikon/derive/binary/SequencesPredicateFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/derive/binary/SequencesJoin.java: daikon/derive/binary/SequencesJoin.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/binary/SequencesJoinFloat.java: daikon/derive/binary/SequencesJoin.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/derive/binary/SequencesJoinFactory.java: daikon/derive/binary/SequencesJoinFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/binary/SequencesJoinFactoryFloat.java: daikon/derive/binary/SequencesJoinFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/derive/unary/SequenceInitial.java: daikon/derive/unary/SequenceInitial.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/unary/SequenceInitialFloat.java: daikon/derive/unary/SequenceInitial.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)

daikon/derive/unary/SequenceInitialFactory.java: daikon/derive/unary/SequenceInitialFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPELONG)

daikon/derive/unary/SequenceInitialFactoryFloat.java: daikon/derive/unary/SequenceInitialFactory.java.jpp
	$(JAVA_CPP:DEFINEDVAR=TYPEDOUBLE)


###########################################################################
### Delete-on-error
###

# Existence of this rule means that a target is deleted if has just changed
# and its rule commands exit with nonzero status.  It's needed for the
# java-cpp rules above.
# (Actually, it isn't anymore, for I arrange not to overwrite the file
# unless success.  But leave it in for now anyway.)
.DELETE_ON_ERROR:
