# file      : build/frame.make
# author    : Boris Kolpackov <boris@kolpackov.net>
# copyright : Copyright (c) 2004-2009 Boris Kolpackov
# license   : GNU GPL v2; see accompanying LICENSE file

%frame_exclude% += CURDIR SHELL MAKEFILE_LIST MAKEFLAGS
%frame_include% := #.DEFAULT_GOAL - for some reason it is already in the list


# return only vars with 'file' origin
#
%frame_exclude% += frame-vars-stage
define frame-vars-stage
$(foreach v,$(.VARIABLES),$(if $(findstring file,$(origin $v)),$v))
endef


# $1 holds exclusion list
#
%frame_exclude% += frame-vars
define frame-vars
$(filter-out \%% $(%frame_exclude%) $1,\
$(call frame-vars-stage) $(%frame_include%))
endef


%frame% := %frame


%frame_exclude% += frame-set-recursive
define frame-set-recursive
define $1
$2
endef
endef


%frame_exclude% += frame-save
define frame-save
$(eval $(if $(filter simple,$(flavor $1)),\
$(%frame%)/$1% := $(value $1),\
$(call frame-set-recursive,$(%frame%)/$1%,$(value $1))))
endef

%frame_exclude% += frame-restore
define frame-restore
$(eval $(if $(filter simple,$(flavor $(%frame%)/$1%)),\
$1 := $(value $(%frame%)/$1%),\
$(call frame-set-recursive,$1,$(value $(%frame%)/$1%))))
endef

#@@ It would be cleaner to have something like 'undefine' but
#   this is good enough for now.
#
%frame_exclude% += frame-undefine
define frame-undefine
$(eval $$1 :=)
endef

# Use debug messages to check for garbage being framed.
#

#$$(warning framing $$(value $(%frame%)_vars%))

%frame_exclude% += frame-enter-body
define frame-enter-body
$(%frame%)_vars% := $(call frame-vars,$1)
$(%frame%)_excl% := $1
$$(foreach v,$$(value $(%frame%)_vars%),$$(call frame-save,$$v))
%frame% := $(%frame%)/frame
endef

%frame_exclude% += frame-enter
define frame-enter
$(eval $(call frame-enter-body,$1))
endef


#$$(warning restoring $$(value $$(%frame%)_vars%))

%frame_exclude% += frame-leave-body
define frame-leave-body
%frame% := $(patsubst %/,%,$(dir $(%frame%)))
$$(foreach v,$$(value $$(%frame%)_vars%),$$(call frame-restore,$$v))
$$(foreach v,\
$$(filter-out $$(value $$(%frame%)_vars%),$$(call frame-vars,$$(value $$(%frame%)_excl%))),\
$$(call frame-undefine,$$v))
endef

%frame_exclude% += frame-leave
define frame-leave
$(eval $(call frame-leave-body))
endef
