# defn.sh
# -----------------------------------------------------------------------------
#
# mingw-get module providing the defining functions for the implementation
# of the action routines for all request handlers.
#
# -----------------------------------------------------------------------------
#
# $Id: defn.sh,v a57bbf0187da 2020/08/20 16:29:01 keith $
#
# Written by Keith Marshall <keithmarshall@users.sourceforge.net>
# Copyright (C) 2011-2013, 2018, 2020, MinGW.org Project
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# -----------------------------------------------------------------------------
#
# Function: defn <name>
#
# Declare <name> as a valid action keyword, to be identified by the action
# dispatcher, (see below); does NOT provide the implementation for this action.
#
  defn() {
    actions="${actions+"$actions "}$1"
    eval action_$1'() { invoke_action_hooks '$1'; }'
  }

# Function: defn_set_hook <action> <phase> "<function-list>"
#
  defn_set_hook() { eval ${1}_${2}_hooks='"$3"'; }

# Function: defn_add_hook <action> <phase> "<function-list>"
#
  defn_add_hook() { eval ${1}_${2}_hooks='"`echo $'${1}_${2}_hooks' $3`"'; }

# Function: defn_enum_hooks <action> "<phase-list>"
#
# Enumerate the list of handler functions specified for <action>,
# which have been assigned to the sequence specified for <phase-list>;
# unlike defn_enum_required_hooks(), below, this simply returns an
# empty list, if no handler has been assigned for any phase which
# is specified in <phase-list>.
#
  defn_enum_hooks() {
    for hooked in $2; do eval 'echo $'${1}_${hooked}_hooks; done;
  }

# Function: defn_enum_required_hooks <action> "<phase-list>"
#
# Enumerate the list of handler functions specified for <action>,
# preferring the sequence specified for <phase-list>, or if none are
# assigned for any specified phase, fall back to the default list;
# if that too is unassigned, fall back to "action_unimplemented".
#
  defn_enum_required_hooks() { hooked="`defn_enum_hooks $1 "$2"`"
    test "x$hooked" = x && hooked="`defn_enum_hooks $1 default`"
    test "x$hooked" = x && echo action_unimplemented || echo $hooked
  }

# Function: defn_parameter_list "<parameter>" ...
#
# Construct a space-separated list of parameters from the specified
# sequence of <parameter> arguments; (do not use this; it doesn't do
# anything, beyond obfuscating references to "echo"; thus, it is now
# marked as deprecated; please use "echo" instead).
#
  defn_parameter_list() { echo "$@"; }

# Function: invoke_action_hooks <action>
#
# Invoked via dispatch(): process the sequence of hooks associated
# with <action>, preferring the begin --> plugin --> end sequence, or
# the default sequence, if the former is unassigned.
#
  invoke_action_hooks() {
    for hooked in `defn_enum_required_hooks $1 "begin plugin end"`
    do $hooked "$1"; done
  }

# Function: action_unimplemented <action>
#
# Fallback handler for actions which have been defn()'d, but for which
# no implementation has been provided.
#
  action_unimplemented() {
    die "no handler implemented for action '$1'"
  }

# Function: dispatch <argv ...>
#
# For each action keyword in <argv ...> which has been declared using defn(),
# invoke the associated action_<action> function; (by default, this will invoke
# invoke_action_hooks(), to process the sequence of hooks associated with the
# declared action.
#
  dispatch() {
    request="$1" action=
    case $request in
    # Handle -ise vs. -ize conflicts, to accommodate users who
    # favour the common British spelling of "initialise".
    #
      initialis | initialise ) request=initialize ;;
    esac
    for keyword in $actions
    do case $keyword in ${request}*)
	 test "x$action" = x || die "action keyword '$request' is ambiguous"
	 action=$keyword
       esac
    done
    test "x$action" = x && die "unknown action keyword '$request'"
    action_$action
  }
#
# -----------------------------------------------------------------------------
# $RCSfile: defn.sh,v $: end of file
