########################################################################
#                                                                      #
# Standard rulesets for use when compiling and installing this system. #
#                                                                      #
########################################################################
#
# This file expects the following variables to have been defined before
# it is included into any other Makefile on this system:
#
#	BASEDIR 	The relative path from the directory the Makefile
#			is in to the base directory. This is used quite
#			extensively through these definitions, so must be
#			correct.
#
#	USEBCC		Whether to compile using BCC or GCC. If this is
#			set to 'N' it compiles using GCC, otherwise it
#			compiles using BCC.
#
#	CLEANDEP	Any files in the current directory that the
#			`make dep` command is dependent on.
#
#	CLEANME 	Any files in the current directory to be removed
#			by the `make clean` command that are not in the
#			standard list of files matching "*~", "*.bak",
#			"*.a", "*.o", "*.map" or "*.tmp" or named "core".
#			Also removed are any files matching "*.s" for
#			which a "*.c" or "*.S" file also exists.
#
#	DEPEND		Any files in the current directory that the
#			`make dep` command is dependent on.
#
#	DISTFILES	Any files in the current directory that are to
#			be included in a distribution made with the
#			`make dist` command that are not in the standard
#			list. This standard list consists of those files
#			NOT removed by `make clean` that match any of
#			the patterns "*.?", "*.cc", "*.html", "*.in",
#			"*.sh", "*.tk", "*.txt", "Makefile*" or "README*".
#
#	NOINDENT	Any files in the current directory that are NOT
#			to be processed in a `make indent` run. Usually,
#			these files include sections of assembly code,
#			which gets mangled by the `indent` command.
#
# No other variables should be defined before including this file.
#
#########################################################################
# State the current version of this system.

VERSION 	= 0	# (0-255)
PATCHLEVEL	= 2	# (0-255)
SUBLEVEL	= 0	# (0-255)
#PRE		= 1	# (0-255)	If not a pre, comment this line.

#########################################################################
# Specify the architecture we will use.

ARCH		= i86

#########################################################################
# ROOT_DEV specifies the default root-device when making the image.
# This does not yet work under ELKS. See include/linuxmt/config.h to
# change the root device.

ROOT_DEV	= FLOPPY

#########################################################################
# Specify the target for the netboot image.

TARGET_NB_IMAGE	= $(TOPDIR)/nbImage

#########################################################################
#									#
#   From here onwards, it is not normally necessary to edit this file   #
#									#
#########################################################################
# Define variables directly dependant on the current version number.

VSNCODE1	= $(shell printf '0x%02X%02X%02X' \
			$(VERSION) $(PATCHLEVEL) $(SUBLEVEL))

ifeq (x$(PRE), x)

DIST		= $(shell printf '%u.%u.%u' \
			$(VERSION) $(PATCHLEVEL) $(SUBLEVEL))

VSNCODE		= $(VSNCODE1)00

else

DIST		= $(shell printf '%u.%u.%u-pre%u' \
			$(VERSION) $(PATCHLEVEL) $(SUBLEVEL) $(PRE))

VSNCODE		= $(shell printf '0x%06X%02X' $$(($(VSNCODE1)-1)) $(PRE))

endif

#########################################################################
# Specify the root directory.

TOPDIR		= $(shell cd "$(BASEDIR)" ; \
			  if [ -n "$$PWD" ]; \
				then echo $$PWD ; \
				else pwd ; \
			  fi)

#########################################################################
# Specify the various directories.

ARCH_DIR	= arch/$(ARCH)

INCDIR		= $(TOPDIR)/include

MYDIR		= $(shell pwd | sed 's^$(TOPDIR).')

#########################################################################
# Specify the directory we are to create the distribution copy of this
# directory in, in such a way that no . or .. directories occur. This
# also makes this an absolute path, but that fact is not important.

DISTDIR 	= $(shell $(BASEDIR)/scripts/setdir $(TOPDIR)/../elks-$(DIST)/$(MYDIR))

#########################################################################
# Specify the configuration shell to use.

CFG_SHELL	:= $(shell \
	     if [ -x "$$bash" ]; \
		then echo $$bash ; \
		else if [ -x /bin/bash ]; \
			then echo /bin/bash ; \
			else if [ -x /usr/bin/bash ]; \
				then echo /usr/bin/bash ; \
				else if [ -x /usr/local/bin/bash ]; \
					then echo /usr/local/bin/bash ; \
					else echo sh ; \
				     fi ; \
			     fi ; \
		     fi ; \
	     fi)

#########################################################################
# Specify the standard definitions to be given to system programs.

CCDEFS		= -DELKS_VERSION_CODE=$(VSNCODE)		\
		  -DUTS_RELEASE=\"$(DIST)\"			\
		  -D__KERNEL__

#########################################################################
# Set the target environment.

ifeq (wildcard($(BASEDIR)/.config), $(BASEDIR)/.config)
    MK_ARCH	= $(shell grep '^CONFIG_ARCH_' $(BASEDIR)/.config \
			| cut -d = -f 1 | cut -d _ -f 3- | tr A-Z a-z)
    MK_CPU	= $(shell grep '^CONFIG_CPU_' $(BASEDIR)/.config \
			| cut -d = -f 1 | cut -d _ -f 3- | tr A-Z a-z)
else
    MK_ARCH	= ibmpc
    MK_CPU	= 8086
endif

#########################################################################
# Define architecture-specific flags.

ifeq ($(MK_ARCH), ibmpc)
    ARCH_AS	=
    ARCH_CC	=
    ARCH_LD	=
endif

ifeq ($(MK_ARCH), sibo)
    ARCH_AS	=
    ARCH_CC	=
    ARCH_LD	= -D 0xC00 -H 0x480
endif

#########################################################################
# Define CPU-specific flags.

ifeq ($(MK_CPU), 8086)
    CPU_AS	= -0
    CPU_CC	= -0
    CPU_LD	= -0
endif

ifeq ($(MK_CPU), 80186)
    CPU_AS	= -1
    CPU_CC	= -0
    CPU_LD	= -0
endif

ifeq ($(MK_CPU), 80286)
    CPU_AS	= -2
    CPU_CC	= -0
    CPU_LD	= -0
endif

ifeq ($(MK_CPU), 80386)
    CPU_AS	= -3
    CPU_CC	= -3
    CPU_LD	= -3
endif

ifeq ($(MK_CPU), 80486)
    CPU_AS	= -3
    CPU_CC	= -3
    CPU_LD	= -3
endif

#########################################################################
# Export all variables.

.EXPORT_ALL_VARIABLES:

#########################################################################
# Specify the tools to use, with their flags.

################################
# Common definitions

AR		= ar
CC_PROTO	= gcc -I$(INCDIR) -M -MG $(CCDEFS)
CFLBASE 	= -O -I$(INCDIR) $(CCDEFS) -ansi
CPP		= $(CC) -I$(INCDIR) -E $(CCDEFS)
LINT		= splint
LINTLEVEL	= -weak
LCFLAGS 	= -I$(INCDIR) $(CCDEFS)
LHFLAGS 	= $(LCFLAGS) -exportfcn -declundef -fcnuse -fielduse \
		  -exportheader -varuse -exporttype -exportconst \
		  -exportvar -typeuse -enummemuse -constuse

ifneq ($(USEBCC), N)

################################
# Definitions using BCC compiler

AS		= as86
ASFLAGS 	= $(CPU_AS) $(ARCH_AS)
CC		= bcc
CFLAGS		= $(CPU_CC) $(ARCH_CC) $(CFLBASE)
LD		= ld86
LDFLAGS 	= $(CPU_LD) -s

else

################################
# Definitions using GCC compiler

AS		= as
ASFLAGS 	= 
CC		= gcc
CFLAGS		= -i $(CFLBASE)
LD		= ld
LDFLAGS 	= -s -x

endif

#########################################################################
# general construction rules

.c.s:
	$(CC) $(CFLAGS) -S -o $*.s $<

.s.o:
	$(AS) $(ASFLAGS) -o $*.o $<

.S.s:
	gcc -E -traditional -I$(INCDIR) $(CCDEFS) -o $*.s $<

.c.o:
	$(CC) $(CFLAGS) -c -o $*.o $<

#########################################################################
# Default target, to allow standard targets to be included. This simply
# allows `make elks` to be called from any directory in the tree, and
# results in `make all` being called in the root directory of the tree.

elks:
	${MAKE} -C $(BASEDIR) all

#########################################################################
# Standard commands.

doclean: $(CLEANDEP)
	rm -fv *~ *.a *.bak *.lint *.map *.o *.tmp core $(CLEANME)
	@for FILE in *.s ; do \
		BASE=`basename "$$FILE" .s` ; \
		if [ -f "$$BASE.c" -o -f "$$BASE.S" ]; then \
			echo rm -fv "$$FILE" ; \
			rm -fv "$$FILE" ; \
		fi ; \
	done
	@for DIR in */ ; do \
		if [ -f "$$DIR/Makefile" ]; then \
			${MAKE} -C "$$DIR" doclean ; \
		fi ; \
	done

dodep:	$(DEPEND)
	@if \ls *.c > /dev/null 2>&1 ; then \
		${MAKE} mkdep ; \
	fi
	@for DIR in */ ; do \
		if [ -f "$$DIR/Makefile" ]; then \
			${MAKE} -C "$$DIR" dodep ; \
		fi ; \
	done

dofixme:
	@for FILE in $${USEME:-*.[ch]} ; do \
	    if [ -f "$${FILE}" ]; then \
		if fgrep -q FIXME "$${FILE}" ; then \
		    echo WARNING: "$${FILE}" includes a FIXME comment. ; \
		fi ; \
	    fi ; \
	done
	@if [ -z "$${USEME}" ]; then \
		for DIR in */ ; do \
			if [ -f "$$DIR/Makefile" ]; then \
				${MAKE} -C "$$DIR" dolint ; \
			fi ; \
		done ; \
	fi

doindent:
	$(BASEDIR)/scripts/reindent $(NOINDENT)

dolint:
	@for FILE in $${USEME:-*.[ch]} ; do \
	    if [ -f "$${FILE}" ]; then \
		    echo $(LINT) ... "$${FILE}" ; \
		    SLEEP=N ; \
		    if fgrep -q FIXME "$${FILE}" ; then \
			echo WARNING: "$${FILE}" includes a FIXME comment. ; \
			SLEEP=Y ; \
		    fi ; \
		    if fgrep -q '#asm' "$${FILE}" ; then \
			echo WARNING: "$${FILE}" includes assembler section. ; \
			SLEEP=Y ; \
		    fi ; \
		    if fgrep -q '#ifndef S_SPLINT_S' "$${FILE}" ; then \
			echo WARNING: "$${FILE}" includes disabled section. ; \
			SLEEP=Y ; \
		    fi ; \
		    if fgrep -q '/*@ignore@*/' "$${FILE}" ; then \
			echo WARNING: "$${FILE}" includes section ignored by splint ; \
			SLEEP=Y ; \
		    fi ; \
		    if [ $SLEEP != N ]; then \
			sleep 1 ; \
		    fi ; \
		    if echo "$${FILE}" | grep -q '\.h$$' ; then \
			$(LINT) $(LINTLEVEL) $(LHFLAGS) "$${FILE}" \
				> "$${FILE}.lint" 2>&1 ; \
		    else \
			$(LINT) $(LINTLEVEL) $(LCFLAGS) "$${FILE}" \
				> "$${FILE}.lint" 2>&1 ; \
		    fi ; \
		    if [ $$? -eq 0 ]; then \
			rm -f "$${FILE}.lint" ; \
		    else \
			cat "$${FILE}.lint" ; \
		    fi ; \
	    fi ; \
	done
	@if [ -z "$${USEME}" ]; then \
		for DIR in */ ; do \
			if [ -f "$$DIR/Makefile" ]; then \
				${MAKE} -C "$$DIR" dolint ; \
			fi ; \
		done ; \
	fi

fixme:	dofixme
	@echo
	@echo Those are all the FIXME comments in this tree.
	@echo

indent:	doindent
	@for DIR in */ ; do \
		if [ -f "$$DIR/Makefile" ]; then \
			${MAKE} -C "$$DIR" indent ; \
		fi ; \
	done

lint:	dolint
	@echo
	@echo " * All files in and under this directory have now been checked. Where problems"
	@echo " * were found, they will be found in the relevant *.lint file in the same"
	@echo " * directory. However, where no problems were found, this file is deleted."
	@echo

mkdep:
	@sed '/\#\#\# Dependencies:/q' < Makefile > make.tmp
	@echo >> make.tmp
	@for FILE in *.c ; do \
		$(CC_PROTO) "$${FILE}" >> make.tmp ; \
		printf '\n\n' >> make.tmp ; \
	done
	@if ! diff Makefile make.tmp > /dev/null ; then \
		echo -n 'Assigning dependencies: ' ; \
		mv -fv make.tmp Makefile ; \
	else \
		rm -f make.tmp ; \
	fi

nodep:
	sed '/\#\#\# Dependencies:/q' < Makefile > make.tmp
	@if ! diff Makefile make.tmp > /dev/null ; then \
		echo -n 'Removing dependencies: ' ; \
		mv -fv make.tmp Makefile ; \
	else \
		rm -f make.tmp ; \
	fi
	@for DIR in */ ; do \
		if [ -f "$$DIR/Makefile" ]; then \
			${MAKE} -C "$$DIR" nodep ; \
		fi ; \
	done

#########################################################################
# Recreate autoconf.h if it's missing.

$(BASEDIR)/include/linuxmt/autoconf.h:
	@yes '' | make -C $(BASEDIR) config

#########################################################################
# Sub-command used by the `make dist` command in the toplevel Makefile.

MKDIST	= $(shell export allow_null_glob_expansion=Y ; \
	  echo *.? *.cc *.html *.in *.png *.sh *.tk *.txt Makefile* README*)

mkdist:
	mkdir -m 755 -p $(DISTDIR)
	cp -pf $(MKDIST) $(DISTFILES) $(DISTDIR)
	@for DIR in */ ; do \
		if [ -f "$${DIR}/Makefile" ]; then \
			${MAKE} -C "$${DIR}" mkdist ; \
		fi ; \
	done

#########################################################################
# End of standard rules file.
