#!/usr/bin/env bash

#-----------------------------------------------------------------------------
# Return true if the first word matches any one of the following words.
#-----------------------------------------------------------------------------
function oneof {
    local a
    local s
    s="${1}"
    shift
    for a in "$@"; do
	if [[ "${a}" = "${s}" ]]; then
	    return 0
	fi
    done
    return 1;
}

##############################################################################
function banner {
    cat <<EOF
//-----------------------------------------------------------------------------
// Copyright © 2003 - Philip Howard - 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-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/map
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

EOF
}

##############################################################################
function prefix {
    banner
    cat <<EOF
#include "map_${typename}.h"

EOF
}

##############################################################################
function map_header {
    banner

    cat <<EOF
#include "map_lib.h"

EOF

    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	cat <<EOF
//-----------------------------------------------------------------------------
// struct	map_link_${typename}
// struct	map_node_${typename}
//
// purpose	Define structures needed to keep the AVL trees used to hold
//		a mapping.
//-----------------------------------------------------------------------------
struct map_link_${typename} {
    avl_link		link	;
    ${typecode}		key	;
};

struct map_node_${typename} {
    struct map_mixed		data	;
    struct map_link_${typename}	link	;
};

EOF
    fi

    if oneof "${typename}" map; then
	cat <<EOF
//-----------------------------------------------------------------------------
// struct	map_node_${typename}
//
// purpose	Define structures needed to keep the AVL trees used to hold
//		a mapping.
//-----------------------------------------------------------------------------
struct map_link_gen {
    avl_link		link	;
};

struct map_node_${typename} {
    struct map_mixed	data	;
    struct map_link_gen	link	;
};

EOF
    fi
}

##############################################################################
function map_new {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
//-----------------------------------------------------------------------------
// function	map_${typename}_compare (internal)
//
// purpose	Compare the scalar keys in two AVL tree nodes.  This function
//		is not globally exported.  It is used only to establish the
//		comparison method for the AVL tree used to hold this mapping.
//
// arguments	1 (struct map_link_${typename} *)
//		2 (struct map_link_${typename} *)
//		3 (void *) extra pointer (not used)
//
// returns	(int) comparison status, -1, 0, 1
//-----------------------------------------------------------------------------
static
int
map_${typename}_compare (
    avl_link *		arg_one
    ,
    avl_link *		arg_two
    ,
    AVL *		arg_avl
    )
{
    return ( ((struct map_link_${typename} *) (void *) arg_one)->key
	   < ((struct map_link_${typename} *) (void *) arg_two)->key ) ? -1
	 : ( ((struct map_link_${typename} *) (void *) arg_one)->key
	   > ((struct map_link_${typename} *) (void *) arg_two)->key ) ? 1
	 : 0;
}

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_new
//
// purpose	Create a new mapping with the specific scalar key type.
//
// arguments	-none-
//
// returns	(MAP) handle for the new mapping.
//		(MAP) NULL = error creating new mapping
//-----------------------------------------------------------------------------
MAP
map_${typename}_new ()
__PROTO_END__
{
    MAP		this_map	;

    //-- Allocate a structure for the root of the mapping.
    if ( ! ( this_map = malloc( sizeof (struct map_root) ) ) ) return NULL;

    //-- Record the key type.
    this_map->key_type = ${typesymb};

    if ( ! avl_init( & (this_map->avl_tree), struct map_node_${typename}, link, map_${typename}_compare ) ) return NULL;

    //-- Return the handle to the new mapping.
    return this_map;
}

EOF
    fi
}

##############################################################################
function map_cmp_func {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
//-----------------------------------------------------------------------------
// function	map_${typename}_compare_alt (internal)
//
// purpose	Compare the scalar keys in two AVL tree nodes.  This function
//		is not globally exported.  It is used only to establish the
//		comparison method for the AVL tree used to hold this mapping.
//
// arguments	1 (struct map_link_${typename} *)
//		2 (struct map_link_${typename} *)
//		3 (void *) alternate compare function
//
// returns	(int) comparison status, -1, 0, 1
//-----------------------------------------------------------------------------
static
int
map_${typename}_compare_alt (
    avl_link *		arg_one
    ,
    avl_link *		arg_two
    ,
    AVL *		arg_avl
    )
{
    return ( * map_cmp_func( arg_avl ) )
	    ( ((struct map_link_${typename} *) (void *) arg_one)->key,
	      ((struct map_link_${typename} *) (void *) arg_two)->key );
}

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function     map_${typename}_cmp_func
//
// purpose      Set the comparison function to the caller supplied function.
//
// arguments	1 (MAP) mapping to set function for
//		2 ((*)(${typecode},${typecode}) function ptr
//
// comparison	1 (${typecode}) key value 1
//  arguments	2 (${typecode}) key value 2
//
// comparison	(int) -1: key 1 <  key 2
//    returns	(int)  0: key 1 == key 2
//		(int)  1: key 1  > key 2
//
// returns      (int) -1 : error
//              (int)  0 : OK
//-----------------------------------------------------------------------------
int
map_${typename}_cmp_func (
    MAP         arg_map
    ,
    int		(* arg_compare)( ${typecode}, ${typecode} )
    )
__PROTO_END__
{
    //-- Make sure the mapping is empty.
    map_empty( arg_map );

    //-- Set up for custom comparison.
    arg_map->options = 0;
    arg_map->cmp_func = (int (*)()) arg_compare;

    //-- Re-initialize the AVL layer.
    if ( ! avl_init( & (arg_map->avl_tree), struct map_node_${typename}, link, map_${typename}_compare_alt ) ) return -1;
    return 0;
}

EOF
    fi
}

##############################################################################
function map_cmp_func_opt {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
//-----------------------------------------------------------------------------
// function	map_${typename}_compare_alt_opt (internal)
//
// purpose	Compare the scalar keys in two AVL tree nodes.  This function
//		is not globally exported.  It is used only to establish the
//		comparison method for the AVL tree used to hold this mapping.
//
// arguments	1 (struct map_link_${typename} *)
//		2 (struct map_link_${typename} *)
//		3 (void *) alternate compare function
//
// returns	(int) comparison status, -1, 0, 1
//-----------------------------------------------------------------------------
static
int
map_${typename}_compare_alt_opt (
    avl_link *		arg_one
    ,
    avl_link *		arg_two
    ,
    AVL *		arg_avl
    )
{
    return ( * map_cmp_func( arg_avl ) )
	    ( ((struct map_link_${typename} *) (void *) arg_one)->key,
	      ((struct map_link_${typename} *) (void *) arg_two)->key,
		map_from_avl( arg_avl )->options );
}

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function     map_${typename}_cmp_func_opt
//
// purpose      Set the comparison function to the caller supplied function
//		with a 3rd argument option included.
//
// arguments	1 (MAP) mapping to set function for
//		2 ((*)(${typecode},${typecode},int) function ptr
//		3 (int) option to pass along
//
// comparison	1 (${typecode}) key value 1
//  arguments	2 (${typecode}) key value 2
//		3 (int) option being passed along
//
// comparison	(int) -1: key 1 <  key 2
//    returns	(int)  0: key 1 == key 2
//		(int)  1: key 1  > key 2
//
// returns      (int) -1 : error
//              (int)  0 : OK
//-----------------------------------------------------------------------------
int
map_${typename}_cmp_func_opt (
    MAP         arg_map
    ,
    int		(* arg_compare)( ${typecode}, ${typecode}, int )
    ,
    int		arg_opt
    )
__PROTO_END__
{
    //-- Make sure the mapping is empty.
    map_empty( arg_map );

    //-- Set up for custom comparison.
    arg_map->options = arg_opt;
    arg_map->cmp_func = (int (*)()) arg_compare;

    //-- Re-initialize the AVL layer.
    if ( ! avl_init( & (arg_map->avl_tree), struct map_node_${typename}, link, map_${typename}_compare_alt_opt ) ) return -1;
    return 0;
}

EOF
    fi
}

##############################################################################
function map_find {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_find
//
// purpose	Find a node with a matching key, or possibly a nearby key.
//
//		If the influential direction is none, return the first exact
//		match encountered, or return none.
//
//		If the influential direction is low, return the lowest exact
//		match encountered, or if there is no exact match: if the
//		near option is specified, choose the nearest node in the
//		low direction.
//
//		If the influential direction is high, return the lowest exact
//		match encountered, or if there is no exact match: if the
//		near option is specified, choose the nearest node in the
//		high direction.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key
//		3 (int) direction and near option, -2, -1, 0, 1, 2
//			-2 = choose lowest exact, or nearest lower
//			-1 = choose lowest exact only
//			 0 = choose first exact only
//			 1 = choose highest exact only
//			 2 = choose highest exact, or nearest higher
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
int
map_${typename}_find (
    MAP			arg_map
    ,
    ${typecode}		arg_key
    ,
    int			arg_dir_near
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;
    struct map_link_${typename}	finder	;

    //-- Make sure we have a correct mapping.
    if ( ! arg_map ) return -2;
    if ( arg_map->key_type != ${typesymb} ) return -2;

    //-- Set up a search link to pass the key.
    finder.key = arg_key;

    //-- Let the AVL layer do the search.
    node_p = avl_find( & (arg_map->avl_tree), & finder, arg_dir_near );

    //-- Return the found data type or -1 if none found.
    return ( node_p ) ? node_p->data.type : -1;
}

__FMACRO_BEGIN__
//-----------------------------------------------------------------------------
// macro	map_${typename}_find_exact
//
// purpose	Find a member with an exactly matching key of the specific
//		array key type for this mapping.  If multiple members match,
//		this function does not define what particular member will be
//		selected.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
#define map_${typename}_find_exact(m,k) map_${typename}_find((m),(k),0)

//-----------------------------------------------------------------------------
// macro	map_${typename}_find_exact_lo
//
// purpose	Find a node with an exactly matching key of the specific
//		scalar key type for this mapping.  If there is more than
//		one node of the same key, select the one in the lowest
//		position.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
#define map_${typename}_find_exact_lo(m,k) map_${typename}_find((m),(k),-1)

//-----------------------------------------------------------------------------
// macro	map_${typename}_find_lo_or_near
//
// purpose	Find a node with an exactly matching key, or if no exactly
//		matching key present, a node with nearest lower value, of
//		the specific scalar key type for this mapping.  If there is
//		more than one node of the same key, select the one in the
//		lowest position.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
#define map_${typename}_find_lo_or_near(m,k) map_${typename}_find((m),(k),-2)

//-----------------------------------------------------------------------------
// macro	map_${typename}_find_exact_hi
//
// purpose	Find a node with an exactly matching key of the specific
//		scalar key type for this mapping.  If there is more than
//		one node of the same key, select the one in the highest
//		position.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
#define map_${typename}_find_exact_hi(m,k) map_${typename}_find((m),(k),1)

//-----------------------------------------------------------------------------
// macro	map_${typename}_find_hi_or_near
//
// purpose	Find a node with an exactly matching key, or if no exactly
//		matching key present, a node with nearest higher value, of
//		the specific scalar key type for this mapping.  If there is
//		more than one node of the same key, select the one in the
//		highest position.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = no node found
//		(int)  0 = found a node with no data
//		(int) data type of found node
//-----------------------------------------------------------------------------
#define map_${typename}_find_hi_or_near(m,k) map_${typename}_find((m),(k),2)
__FMACRO_END__

EOF
    fi
}

##############################################################################
function map_insert {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_insert
//
// purpose	Insert a new member into a mapping with the specified key and
//		an initial undefined data value, unless one already exists
//		with that exact key, in which case it is made active.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int)  0 = found or inserted a member with no data
//		(int) >0 = data type of found node
//-----------------------------------------------------------------------------
int
map_${typename}_insert (
    MAP			arg_map
    ,
    ${typecode}		arg_key
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;
    int			rc	;

    //-- Make sure we have a correct mapping.
    if ( ! arg_map ) return -2;
    if ( arg_map->key_type != ${typesymb} ) return -2;

    //-- Allocate a combined node and key space.  The key is a scalar
    //-- so there is always just one element and it is in the node.
    if ( ! ( node_p = malloc( sizeof (struct map_node_${typename}) ) ) ) return -2;

    //-- Initialize the node.
    node_p->data.type = 0;
    node_p->link.key = arg_key;

    //-- Insert node or return data type if already exists.
    rc = avl_insert( & (arg_map->avl_tree), node_p );
    if ( rc >= 0 ) return 0;
    free( node_p );
    return map_${typename}_find( arg_map, arg_key, 0 );
}
EOF
    fi
}

##############################################################################
function map_insert_dup {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_insert_dup
//
// purpose	Insert a new node into a mapping with the specified key and
//		an initial undefined data value.  If a node already exists,
//		insert a duplicate.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) scalar key type
//
// returns	(int) -2 = error, no map, bad type
//		(int) -1 = not inserted
//		(int)  1 = new unique node inserted
//		(int)  2 = duplicate node inserted
//-----------------------------------------------------------------------------
int
map_${typename}_insert_dup (
    MAP			arg_map
    ,
    ${typecode}		arg_key
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;
    int			rc	;

    //-- Make sure we have a correct mapping.
    if ( ! arg_map ) return -2;
    if ( arg_map->key_type != ${typesymb} ) return -2;

    //-- Allocate a combined node and key space.  The key is a scalar
    //-- so there is always just one element and it is in the node.
    if ( ! ( node_p = malloc( sizeof (struct map_node_${typename}) ) ) ) return -2;

    //-- Initialize the node.
    node_p->data.type = 0;
    node_p->link.key = arg_key;

    //-- Insert the node.
    rc = avl_insert_dup( & (arg_map->avl_tree), node_p );

    //-- Return status based on insertion.
    return ( rc == -1 ) ? 0 : rc;
}

EOF
    fi
}

##############################################################################
function map_key {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_key
//
// purpose	Get the key value of the current node in the mapping.
//
// arguments	1 (MAP) mapping handle
//
// return	(${typecode}) key value
//		(${typecode}) 0 cast to the key type of the tree
//-----------------------------------------------------------------------------
${typecode}
map_${typename}_key (
    MAP			arg_map
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;

    //-- Make sure we have a correct mapping and current node.
    if ( ! arg_map ) return (${typecode}) 0;
    if ( arg_map->key_type != ${typesymb} ) return (${typecode}) 0;
    if ( ! ( node_p = avl_find( & (arg_map->avl_tree), NULL, 0 ) ) ) return (${typecode}) 0;

    //-- Return the key.
    return node_p->link.key;
}

EOF
    fi
}

##############################################################################
function map_store {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr map; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_store
//
// purpose	Store the given data into the current node in the mapping.
//
// arguments	1 (MAP) mapping handle
//		2 (${typecode}) data value to store
//
// return	(int) -2 = error, no map, no node
//		(int)  0 = success, data stored
//-----------------------------------------------------------------------------
int
map_${typename}_store (
    MAP			arg_map
    ,
    ${typecode}		arg_data
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;

    //-- Make sure we have a mapping and a current node.
    if ( ! arg_map ) return -2;
    if ( ! ( node_p = avl_find( & (arg_map->avl_tree), NULL, 0 ) ) ) return -2;

    //-- Free any old duplicated data.
    if ( map_type_is_string( node_p->data.type ) && node_p->data.mix.array.dup ) {
	free( node_p->data.mix.array.ptr );
    }

    //-- Store the data type and data value.
    node_p->data.type = ${typesymb};
    node_p->data.mix.scalar.${typename} = arg_data;

    //-- Return success.
    return 0;
}

EOF
    fi
}

##############################################################################
function map_fetch {
    if oneof "${typename}" si ui sl ul sll ull d ld ptr map; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_fetch
//
// purpose	Fetch the data from the current node in the mapping and return
//		directly as a value.  There is no means to indicate an error.
//
// arguments	1 (MAP) mapping handle
//
// return	(${typecode}) data value returned
//		(${typecode}) 0 cast to the data type if error
//-----------------------------------------------------------------------------
${typecode}
map_${typename}_fetch (
    MAP			arg_map
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;

    //-- Make sure we have a mapping and a current node.
    if ( ! arg_map ) return (${typecode}) 0;
    if ( ! ( node_p = avl_find( & (arg_map->avl_tree), NULL, 0 ) ) ) return (${typecode}) 0;

    //-- Make sure data type is correct.
    if ( node_p->data.type != ${typesymb} ) return (${typecode}) 0;

    //-- Return data value.
    return node_p->data.mix.scalar.${typename};
}
EOF
    fi
}

##############################################################################
function map_fetch_cast {
    if oneof "${typename}" si ui sl ul sll ull d ld; then
	prefix
	cat <<EOF
__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	map_${typename}_fetch_cast
//
// purpose	Fetch the data from the current node in the mapping and return
//		directly as a value cast or converted to the type expected by
//		caller if the stored data value is a compatible type.  There
//		is no means to indicate an error.  Valid values may be changed
//		depending on the difference in sign and/or scale of the value
//		and the target type.  An error will result in the value 0.
//
// arguments	1 (MAP) mapping handle
//
// return	(${typecode}) data value returned
//		(${typecode}) 0 cast to the data type if error
//-----------------------------------------------------------------------------
${typecode}
map_${typename}_fetch_cast (
    MAP			arg_map
    )
__PROTO_END__
{
    struct map_node_${typename} *	node_p	;

    //-- Make sure we have a mapping and a current node.
    if ( ! arg_map ) return (${typecode}) 0;
    if ( ! ( node_p = avl_find( & (arg_map->avl_tree), NULL, 0 ) ) ) return (${typecode}) 0;

    //-- Cast to correct type and return data value.
    switch ( node_p->data.type ) {
    case MAP_DATA_SI:
        return (${typecode}) ( node_p->data.mix.scalar.si );
    case MAP_DATA_UI:
        return (${typecode}) ( node_p->data.mix.scalar.ui );
#if ULONG_MAX>UINT_MAX
    case MAP_DATA_SL:
        return (${typecode}) ( node_p->data.mix.scalar.sl );
    case MAP_DATA_UL:
        return (${typecode}) ( node_p->data.mix.scalar.ul );
#endif
#if (defined(ULLONG_MAX)&&(ULLONG_MAX>ULONG_MAX)) || (defined(ULONG_LONG_MAX)&&(ULONG_LONG_MAX>ULONG_MAX))
    case MAP_DATA_SLL:
        return (${typecode}) ( node_p->data.mix.scalar.sll );
    case MAP_DATA_ULL:
        return (${typecode}) ( node_p->data.mix.scalar.ull );
#endif
    case MAP_DATA_D:
        return (${typecode}) ( node_p->data.mix.scalar.d );
#if LDBL_MANT_DIG!=DBL_MANT_DIG || LDBL_MAX_EXP!=DBL_MAX_EXP
    case MAP_DATA_LD:
        return (${typecode}) ( node_p->data.mix.scalar.ld );
#endif
    default:
        return (${typecode}) 0;
    }
}
EOF
    fi
}

##############################################################################

#-----------------------------------------------------------------------------
# Generate code into a specified file and list that file.
#-----------------------------------------------------------------------------
function srcfile {
    call="${1}"
    file="${2}"

    "${call}" >"${file}.tmp"
    if [[ $( wc -l < "${file}.tmp" ) -gt 20 ]]; then
	touch -r "${script}" "${file}.tmp"
	chmod 644 "${file}.tmp"
	mv -f "${file}.tmp" "${file}"
	ls -ld --full-time "${file}"
    else
	rm -f "${file}.tmp"
    fi
}
script="$0"

function code {
    typename="${1}"
    typecode="${2}"
    typesymb=$( echo "map_data_${typename}" | tr 'a-z' 'A-Z' )

    srcfile map_header		"map_${typename}.h"
    srcfile map_new		"map_${typename}_new.c"
    srcfile map_cmp_func	"map_${typename}_cmp_func.c"
    srcfile map_cmp_func_opt	"map_${typename}_cmp_func_opt.c"
    srcfile map_find		"map_${typename}_find.c"
    srcfile map_insert		"map_${typename}_insert.c"
    srcfile map_insert_dup	"map_${typename}_insert_dup.c"
    srcfile map_key		"map_${typename}_key.c"
    srcfile map_store		"map_${typename}_store.c"
    srcfile map_fetch		"map_${typename}_fetch.c"
    srcfile map_fetch_cast	"map_${typename}_fetch_cast.c"

    return
}

#-----------------------------------------------------------------------------
# Generate code for each different scalar type.
#-----------------------------------------------------------------------------
code	si	"signed int"
code	ui	"unsigned int"
code	sl	"signed long"
code	ul	"unsigned long"
code	sll	"signed long long"
code	ull	"unsigned long long"
code	d	"double"
code	ld	"long double"
code	ptr	"void *"
code	map	"MAP"

exit 0

