/*
 *	cook - file construction tool
 *	Copyright (C) 1997, 1998, 1999 Peter Miller;
 *	All rights reserved.
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 *
 * MANIFEST: Canned Cookbook Functions
 *
 * This file presents users with some useful functions, defined in terms
 * of the built-in functions.  While useful, they also serve as examples
 * of how to write your own functions.
 *
 * See the ``Functions'' section of the Cook User Guide for more
 * information.  ([arg] and [@1] to [@9] are local variables.)
 */


/*
 * NAME
 *	capitalize
 *
 * SYNOPSIS
 *	[capitalize <word>...]
 *
 * DESCRIPTION
 *	The capitalize function maps all of its arguments into lower
 *	case, and then the first letter of each argument is mapped to
 *	upper case.  Zero, one or more arguments may be given.
 */

function capitalize =
{
	@1 = ;
	@2 = [downcase [arg]];
	loop
	{
		if [not [count [@2]]] then
			loopstop;
		@3 = [head [@2]];
		@2 = [tail [@2]];
		@1 = [@1] [upcase [substr 1 1 [@3]]][substr 2 9999 [@3]];
	}
	return [@1];
}


/*
 * NAME
 *	defined-or-null
 *
 * SYNOPSIS
 *	[defined-or-null <name> ]
 *
 * DESCRIPTION
 *	The defined-or-null function may be used to determine if a
 *	variable has been set (on the command line, for example) and
 *	return its value if so, otherwise return the empty list.
 *
 * ARGUMENTS
 *	This function should only be given one argument - the name of
 *	the variable to look for.  Additional arguments will be ignored.
 *	Too few arguments will produce a complaint about the "" variable
 *	being undefined.
 *
 * RETURNS
 *	The value of the named variable, or the empty list if the
 *	variable is not defined.
 */

function defined-or-null =
{
	if [defined [@1]] then
		return [[@1]];
	return;
}


/*
 * NAME
 *	defined-or-default
 *
 * SYNOPSIS
 *	[defined-or-default <name> <default-value>... ]
 *
 * DESCRIPTION
 *	The defined-or-default function may be used to determine if a
 *	variable has been set (on the command line, for example) and
 *	return its value if so, otherwise return the given default value.
 *
 * ARGUMENTS
 *	The first argument is the name of the variable to look for.
 *
 *	The second and later arguments (if present) are the default
 *	value to be used if the named variable is not defined.  Optional.
 *
 * RETURNS
 *	The value of the named variable, or the default list if the
 *	variable is not defined.
 */

function defined-or-default =
{
	if [defined [@1]] then
		return [[@1]];
	return [tail [arg]];
}


/*
 * NAME
 *	repeat
 *
 * SYNOPSIS
 *	[repeat <unary-function> <arguments>... ]
 *
 * DESCRIPTION
 *	The repeat function is used to repeatedly call another function,
 *	once for each of the specified arguments.  The can be useful
 *	when dealing with functions which do not automaticly accept
 *	argument lists in the form you require.
 *
 *	There are many instances where the repeat function call be used
 *	to elegantly avoid used to the ``loop { loopstop }'' construct.
 *
 * ARGUMENTS
 *	The first argument is the name of the function you want called.
 *	This function must accept a single argument.
 *
 *	The second and subsequent arguments are argument values to be
 *	passed to the named function, one at a time.
 *
 * RETURNS
 *	The results of the invocations of the function are accumulated
 *	in the order in which they were calculated.  The accumulated
 *	results are returned.
 */

function repeat =
{
	@2 = ;
	@3 = [tail [arg]];
	loop
	{
		if [not [count [@3]]] then
			loopstop;
		@4 = [head [@3]];
		@3 = [tail [@3]];
		/* run the named function on this argument */
		@2 = [@2] [[@1] [@4]];
	}
	return [@2];
}


/*
 * NAME
 *	variable_by_path
 *
 * SYNOPSIS
 *	[variable_by_path target prefix filename]
 *
 * DESCRIPTION
 *	The variable_by_path function is used to extract the union
 *	of option settings relevant to a particular compilation or link.
 *	By using a variable suffix, this function may be used to obtain
 *	the setting of a wide variety of options and commands.
 *
 * SIDE EFFECTS
 *	Global variables are searched in a no particular order for the
 *	necessary information.  All are searched, all found are used.
 *
 *	e.g. [variable_by_path cc_flags foo/bar/baz.c]
 *	will hunt for variables with the following names:
 *		cc_flags_foo/bar/baz.c
 *		cc_flags_foo/bar
 *		cc_flags_foo
 *		cc_flags
 *
 *	It is expected that the vast majority of these variables will
 *	not be set.  It will NOT hunt for cc_flags by itself.
 *
 *	Duplicates are removed.
 *
 * ARGUMENTS
 *	The arguments are available in temporary variables numbered
 *	by argument.  The function does not check that you supplied all
 *	of the arguments.  Caveat emptor.
 *
 *	@1	The variable name prefix to use.
 *	@2	The filename to be dismembered.
 */

function variable_by_path =
{
	@9 = ; /* empty result */
	if [defined [@1]] then
		@9 = [[@1]];
	@8 = [split / [@2]];
	@6 = 1 2 3 4 5 6 7 8 9;
	loop
	{
		if [not [count [@6]]] then
			loopstop;
		@7 = [head [@6]];
		@6 = [tail [@6]];

		/* build the variable name */
		@3 = [@1]_[unsplit / [wordlist 1 [@7] [@8]]];

		/* use the variable if it's defined */
		if [defined [@3]] then
			@9 = [@9] [[@3]];
	}
	/* remove duplicates and return */
	return [stringset [@9]];
}
