#  Makefile for smoke-testing ftnchek.  Say ``make'' to make all checks.
#
#

EXE		= .exe
CMD		= .cmd

# gawk/nawk specially needed for dcl2inc.awk
NAWK		= gawk.exe
# ordinary awk used to print some messages
AWK		= gawk.exe
# This defn uses version of dcl2inc.awk in the parent directory. 
DCL2INC		= $(NAWK) -f ../dcl2inc.awk

# This defn uses version of ftnchek in the parent directory.
FTNCHEK		= ../ftnchek$(EXE)

# OKAY subdirectory is where the correct output files are stored.
OKAY		= Okay

# VARY subdirectory is where the varying output files are stored.
VARY		= Vary


# COMPARE invokes the comparison script to check new vs archive.
COMPARE		= ./Compare.sh $(OKAY) $(VARY)

# RCFILE is the name of the startup file for checkrc
RCFILE= ftnchek.ini

# DEFAULT_FLAGS is the set of Ftnchek flags used by the default rule.
# Note: The default rule also sets -f77 via the environment mechanism
# in order to check that mechanism.
DEFAULT_FLAGS	= -list -symt -port

MAKE		= make FTNCHEK=$(FTNCHEK) OKAY=$(OKAY) VARY=$(VARY)

CP              = cp.exe
MV		= mv.exe

RM		= rm.exe -f
SHELL		= sh.exe


.SUFFIXES: .chk .f .prj .fcl .fc1 .fc2 .fc3 .fc4 .fc5 .fc6 .fc7 .fc8 .fc9 \
 .fcA .fcB .fcC .fcD .fcE .fcF


#=======================================================================
#
#                   Definitions of File Groups
#
#
# LISTOUT programs are simple, and all use the default options or else the
# options given in their .opt file.  These produce listing files *.fcl
# Note: Those with .opt files may have associated routines in other
# files that do not appear here.

LISTOUT= average.f backslash.f chestnuts.f comclash.f comcmp.f\
 complex.f comtest.f comusage.f correct.f dims.f do_enddo.f\
 help.f include.f namelist.f noblanks.f strings.f unixincluded.f\
 dectab.f intrinstest.f quad.f

# set of files for testing -arguments setting
ARGS= args01.f args02.f args03.f args04.f args05.f args06.f\
 args07.f args08.f args09.f args10.f args11.f args12.f\
 args13.f args14.f args15.f

# set of files for testing -array setting
ARRAY= arrayclash.f

# Set of files for testing -trun -port -f77 options and -word setting
EXPR= assign.f wordsize.f

# set of files for testing -common setting
COMMON= comcmp.f comusage.f

# set of files for testing dcl2inc processing
DCL2INCFILES= t208x.f

# set of files for testing -makedcls setting
MAKEDCLS= builtin.f dcltest.f dims.f namelist.f params.f\
 t208a.f t208b.f t208c.f t208d.f t208e.f t208f.f t208g.f t208h.f \
 t208i.f t208j.f t208k.f t208l.f t208m.f t208n.f t208o.f t208p.f \
 t208q.f t208r.f t208s.f t208t.f t208u.f t208v.f t208w.f t208x.f

# set of files for testing -usage setting
USAGE= usage.f

# set of files for testing -vcg switch (use target checkvcg)
VCGLIST= comcmp.f comusage.f

#=======================================================================
#
#                   Default Rules
#
# Rule for creating source code listing file, suffix .fcl.  Stdout and
# stderr are merged and environment mechanism for setting command
# options is tested.

.f.fcl:
	@if [ -f $*.opt ] ; then \
	  FTNCHEK_F77=1; export FTNCHEK_F77; \
	  $(FTNCHEK) `cat $*.opt` > $@ 2>&1 ; \
	else \
	  FTNCHEK_F77=1; export FTNCHEK_F77; \
	  $(FTNCHEK) $(DEFAULT_FLAGS) $< > $@ 2>&1 ; \
	fi


# Rule for creating project file.  The .fcl file is made as a side-effect.
.f.prj:
	if [ -f $*.opt ] ; then \
	   $(FTNCHEK) -project `cat $*.opt` > $*.fcl 2>&1 ; \
	else \
	   $(FTNCHEK) -project $(DEFAULT_FLAGS) $< > $*.fcl 2>&1 ; \
	fi


# Rule for running checks on source code listing.  If OKAY directory does
# not exist, it is created.  If OKAY code listing does not exist, it
# is created and moved into OKAY.  Note: In this case, you must examine
# the results to see if it is really OK!
.f.chk:
	@-$(RM) $*.fcl
	@$(MAKE) FTNCHEK='$(FTNCHEK)' $*.fcl "DEFAULT_FLAGS=$(DEFAULT_FLAGS)"
	@$(COMPARE) $*.fcl



#=======================================================================
#
#		Targets.
#
#

all:	check

check:	announce clearfail checkall checkfail

announce:
	@echo "============================================================"
	@echo "There should be no file differences reported by these tests."
	@echo "Output files matching master output files will be removed,"
	@echo "leaving any erroneous output files in directory $(VARY)"
	@echo "for manual examination.  If you built ftnchek with non-"
	@echo "standard compilation options, there may be some differences."
	@echo "============================================================"

# Remove signal file created by Compare.sh
clearfail:
	@-$(RM) CHECK_FAILED

# Look for CHECK_FAILED file -- if found, then Compare.sh found diffs.
checkfail:
	@if [ -f CHECK_FAILED ] ; \
	then \
	  echo "===============================================" ; \
	  echo "===> There were differences.  Check failed. <==" ; \
	  echo "===============================================" ; \
	  $(RM) CHECK_FAILED ; \
	else \
	    echo "No differences found.  Check successful." ; \
	fi

checkall:	checksyntax checksettings checkother

checksyntax:	checklistings checkexpr
checksettings:	checkargs checkarray checkcommon checkoutput checkusage
checkother:	checkproject checkrc checkmakedcls checkvcg checkdcl2inc

#  User should make precheck before running checks.  It looks out for
#  situations that will cause the check to fail: ftnchek not built,
#  user has an rc file in home directory, or FTNCHEK_* environment
#  variables are set.
precheck:
	@-$(RM) $(RCFILE)
	@errorcode=0 ; \
	if [ ! -f "$(FTNCHEK)" ] ; then \
	   echo "ERROR ===> Cannot run checks: no ftnchek found <==="; \
	   errorcode=1 ; \
	fi ; \
	if [ -f "$$HOME/.ftnchekrc" ] ; then \
	   echo "WARNING ===> $$HOME/.ftnchekrc exists <==="; \
	   echo "delete or rename it before running check" ; \
	   errorcode=1 ; \
	fi ; \
	if [ -f "$$HOME/ftnchek.ini" ] ; then \
	   echo "WARNING ===> $$HOME/ftnchek.ini exists <==="; \
	   echo "delete or rename it before running check" ; \
	   errorcode=1 ; \
	fi ; \
	if printenv | grep '^FTNCHEK_' >/dev/null 2>&1 ; then \
	   echo "WARNING ===> environment variables set:"; \
	   printenv | grep '^FTNCHEK_' ; \
	   echo "unset them before running check" ; \
	   errorcode=1 ; \
	fi ; \
	if [ "$$errorcode" = 0 ] ; then \
	   true ; \
	else \
	   false ; \
	fi

clean mostlyclean clobber distclean realclean spotless:
	-$(RM) *.dc[ln0-9] *.fc[l0-9A-F] *.fc[0-3][0-3][0-3]
	-$(RM) *.pcl *.prj *.inc *.vcg
	-$(RM) $(RCFILE)
	-$(RM) *.i *.o
	-$(RM) *~ \#*
	-$(RM) a.out core
	-$(RM) CHECK_FAILED
	-$(RM) $(VARY)/*

# checklistings checks listing output on programs in LISTOUT
checklistings: announcelistings $(LISTOUT:.f=.chk)
	@-echo "done"

# Some systems do not have echo -n option, so to suppress newline
# in a portable way, we use this `awk'ward kluge.
announcelistings:
	@-echo|$(AWK) '{printf("%s","checking listing output:");}'

# Next series of targets checks variations of output as options change.
# The output files are named *.fc[1-9A-F] for different cases.  Note that
# in some instances the same source file is also in a set that is used
# to check source listing as usual, with output file named *.fcl

# checkexpr checks listing output for various size & type clashes in
# expressions and assignment stmts
checkexpr:
	@-echo |$(AWK) '{printf("%s","checking size and type mismatch:");}'
	@for f in $(EXPR:.f=) ; \
	do \
	 $(FTNCHEK) -notrun -noport -nof77 -lis    $$f.f > $$f.fc1 ; \
	 $(COMPARE) $$f.fc1 ; \
	 $(FTNCHEK) -notrun -noport   -f77         $$f.f > $$f.fc2 ; \
	 $(COMPARE) $$f.fc2 ; \
	 $(FTNCHEK) -notrun   -port -nof77         $$f.f > $$f.fc3 ; \
	 $(COMPARE) $$f.fc3 ; \
	 $(FTNCHEK) -notrun   -port   -f77         $$f.f > $$f.fc4 ; \
	 $(COMPARE) $$f.fc4 ; \
	 $(FTNCHEK)   -trun -noport -nof77         $$f.f > $$f.fc5 ; \
	 $(COMPARE) $$f.fc5 ; \
	 $(FTNCHEK)   -trun -noport   -f77         $$f.f > $$f.fc6 ; \
	 $(COMPARE) $$f.fc6 ; \
	 $(FTNCHEK)   -trun   -port -nof77         $$f.f > $$f.fc7 ; \
	 $(COMPARE) $$f.fc7 ; \
	 $(FTNCHEK)   -trun   -port   -f77         $$f.f > $$f.fc8 ; \
	 $(COMPARE) $$f.fc8 ; \
	 $(FTNCHEK)   -trun   -port -nof77 -word=2 $$f.f > $$f.fcA ; \
	 $(COMPARE) $$f.fcA ; \
	 $(FTNCHEK)   -trun   -port -nof77 -word=4 $$f.f > $$f.fcB ; \
	 $(COMPARE) $$f.fcB ; \
	 $(FTNCHEK)   -trun   -port -nof77 -word=8 $$f.f > $$f.fcC ; \
	 $(COMPARE) $$f.fcC ; \
	 $(FTNCHEK)   -trun   -noport -nof77 -word=2 $$f.f > $$f.fcD ; \
	 $(COMPARE) $$f.fcD ; \
	 $(FTNCHEK)   -trun   -noport -nof77 -word=4 $$f.f > $$f.fcE ; \
	 $(COMPARE) $$f.fcE ; \
	 $(FTNCHEK)   -trun   -noport -nof77 -word=8 $$f.f > $$f.fcF ; \
	 $(COMPARE) $$f.fcF ; \
	done
	@-echo "done"

# checkargs checks the -args=n setting
checkargs:
	@-echo |$(AWK) '{printf("%s","checking -args setting:");}'
	@$(MAKE) FTNCHEK='$(FTNCHEK)' \
		CheckSetting "SETTING=-args" "RANGE=0 1 2 3" \
		"FLIST=$(ARGS)" "FLAGS="
	@-echo "done"

# checkarray checks the -array=n setting
checkarray:
	@-echo |$(AWK) '{printf("%s","checking -array setting:");}'
	@$(MAKE) FTNCHEK='$(FTNCHEK)' \
		CheckSetting "SETTING=-array" "RANGE=0 1 2 3" \
		"FLIST=$(ARRAY)" "FLAGS=-port"
	@-echo "done"

#checkcommon checks the -common=n setting
checkcommon:
	@-echo |$(AWK) '{printf("%s","checking -common setting:");}'
	@$(MAKE) FTNCHEK='$(FTNCHEK)' \
		CheckSetting "SETTING=-common" "RANGE=0 1 2 3" \
		"FLIST=$(COMMON)" "FLAGS=-nof77"
	@-echo "done"

checkdcl2inc:
	@-echo |$(AWK) '{printf("%s","checking dcl2inc processing:");}'
	@for f in $(DCL2INCFILES) ; \
	do \
		b=`basename $$f .f` ; \
		$(RM) $$b.dcl $$b.dcn $$b.err $$b.mak ; \
		$(RM) *.inc ; \
		$(FTNCHEK) -nocheck -makedcls=1 $$f 1>/dev/null 2>/dev/null ; \
		$(DCL2INC) $$b.dcl >$$b.mak 2>$$b.err ; \
		for g in $$b.dcl $$b.dcn $$b.mak $$b.err *.inc ; \
		do \
			$(COMPARE) $$g ; \
		done ; \
	done
	@-echo "done"

# checkoutput checks the -output=file string setting
checkoutput:
	@-echo |$(AWK) '{printf("%s","checking -output setting:");}'
	@$(FTNCHEK) -symt -list -port -out=average.out average.f 2> average.fc2
	@-$(COMPARE) average.out
	@-$(COMPARE) average.fc2
	@-echo "done"

# checkusage checks the -usage=n setting
checkusage:
	@-echo |$(AWK) '{printf("%s","checking -usage setting:");}'
	@$(MAKE) FTNCHEK='$(FTNCHEK)' \
		CheckSetting "SETTING=-usage" "RANGE=000 111 222 333" \
		"FLIST=$(USAGE)" "FLAGS="
	@-echo "done"

# checkproject checks creation and use of project files
# Note that correct.f is used in LISTOUT also, but with default
# compilation options.  So we make listing file suffix .fc1 here

checkproject:
	@-echo |$(AWK) '{printf("%s","checking project files:");}'
	@$(RM) correct.prj correct.fc1 correct.pcl
	@$(MAKE) FTNCHEK='$(FTNCHEK)' correct.prj
	@$(MAKE) FTNCHEK='$(FTNCHEK)' correct.pcl
	@-for f in correct.fc1 correct.prj correct.pcl ; \
	do \
	    $(COMPARE) $$f ; \
	done
	@-echo "done"


# Need explicit rule since the default rule is used by listing-file check
correct.prj: correct.f
	@$(FTNCHEK) -project correct.f > correct.fc1 2>&1

#  This target creates output listing file from project file input
correct.pcl: correct.f
	@$(FTNCHEK) correct.prj > correct.pcl 2>&1

# Check the reading of startup file
checkrc:
	@-echo |$(AWK) '{printf("%s","checking reading rc file:");}'
	@-echo "f77=all" > $(RCFILE)
	@-echo "symtab" >> $(RCFILE)
	@$(FTNCHEK) -f77=no-long-name,no-name-underscore do_enddo.f > rc.fcl 2>&1
	@$(COMPARE) rc.fcl
	@$(RM) $(RCFILE)
	@-echo "done"


# Check the generation of declarations files.  Listing goes to /dev/null.
# The values in MAKEDCLS_VALS are used as 3rd char in .fc? suffix.  They
# are converted to -makedcls=num values by raising 2 to the power.  Thus
# file.dc0 contains -makedcls=1, ... file.dc9 contains -makedcls=512.
# There is also a test to be sure that empty .dcl files are removed
# automatically as they should be.
MAKEDCLS_VALS	= 0 1 2 3 4 5 6 7 8 9
checkmakedcls:
	@-echo |$(AWK) '{printf("%s","checking -makedcls setting:");}'
	@for n in $(MAKEDCLS_VALS) ; \
	do \
	    dcl=dc$$n ;\
	    val=`echo 2 \^ $$n | bc` ;\
	    for f in $(MAKEDCLS:.f=) ;\
	    do \
		$(FTNCHEK) -nocheck -makedcls=$$val $$f.f 1>/dev/null 2>/dev/null ; \
		if [ -f $$f.dcl ] ; \
		then \
		  if [ `wc -c $$f.dcl | $(AWK) '{printf("%s",$$1);}'` -eq 0 ] ; \
		  then \
		    $(CP) $$f.dcl $(VARY)/$$f.$$dcl ; \
		    echo ; echo "Empty declarations file" \
			 $(VARY)/$$f.$$dcl "should have been deleted" ; \
		  fi ; \
		else \
		   touch $$f.dcl ; \
		fi ; \
		$(MV) $$f.dcl $$f.$$dcl ; \
		$(COMPARE) $$f.$$dcl ; \
	    done ; \
	done
	@echo "done"


checkvcg:
	@-echo |$(AWK) '{printf("%s","checking -vcg setting:");}'
	@-for f in $(VCGLIST:.f=) ; \
	do \
	  $(FTNCHEK) -vcg $$f.f 1>/dev/null 2>/dev/null ; \
	  $(COMPARE) $$f.vcg ; \
	done
	@echo "done"

# CheckSetting is a "subroutine" with parameters SETTING=name of setting,
# RANGE=list of setting values, FLIST=list of files to check, and
# FLAGS=set of ftnchek flags to use for each case.  "Call" this routine
# by invoking make with appropriate macro definitions on command line.

CheckSetting:
	@for val in $(RANGE) ; \
	do \
	  for f in $(FLIST:.f=) ; \
	  do \
	    $(FTNCHEK) $(SETTING)=$$val $(FLAGS) $$f.f > $$f.fc$$val ; \
	    $(COMPARE) $$f.fc$$val ; \
	  done ; \
	done
