#! /usr/bin/ksh
#
#       @(#)u4ftdev_setprops	1.2     98/07/08
#
#   Script to add or set properties on a specified devinfo node
#

export PATH=${CMSHOME:+"$CMSHOME/lib:"}$PATH

usage()
{
    echo "Usage: ${0##*/} <tag> <propfile>" >&2
    exit 1
}

error()
{
    [[ -n "$*" ]] && echo "${0##*/}:" "$@" >&2
    exit 2
}

propcheck()
{
    # Usage: propcheck "$mynode" "$name"
    u4ftctl prop_lookup_bytes "$1" "$2" > /dev/null 2>&1
}

propset()
{
    # Usage: propset "$op" "$mynode" "$name" "$value"
    u4ftctl "prop_$1" "$2" "\$$3" ${4:+"$4;"} > /dev/null 2>&1
    [[ $? -eq 0 ]] || error "could not update property \"$3\""
}

if [[ $# -ne 2 ]]
then
    usage
fi

typeset -l mode "${0##*/}"
tag="$1"
propfile="$2"

#
#   Find the devinfo node
#
set -A nodes $(u4ftctl find / "$tag")
if [[ ${#nodes[@]} -eq 0 ]]
then
    error "node not found"
elif [[ ${#nodes[@]} -gt 1 ]]
then
    error "tag ambiguous"
else
    mynode="${nodes[0]}"
fi

[[ "$propfile" != "-" ]] && exec < "$propfile"
nawk -v count=0 '
    function badprop(code)
    {
        print "error malformed property definition at line " NR;
        exit 2;
    }

    $1 ~ /#.*/  {
                    next;
                }
                {
                    #
                    #   Accumulate input up to a ";"
                    #
                    count += 1;
                    for (line = ""; (line = line " " $0) !~ /.*;[ \t]*$/; )
                        if (getline <= 0)
                            badprop(1);

                    #
                    #   Check "=", ";", and datatype
                    #
                    $0 = line;
                    # print $0 > "/dev/stderr";
                    if (sub("=", " = ") < 1)
                        badprop(2);
                    if ($2 != "=")
                        badprop(3);
                    if (sub("[ \t]*;[ \t]*$", " ;") < 1)
                        badprop(4);
                    if ($NF != ";")
                        badprop(5);

                    if ($3 ~ /^".*/)
                        op[count] = "update_strings";
                    else if ($3 ~ /^\$.*/)
                        op[count] = "update_bytes";
                    else if ($3 ~ /[0-9].*/)
                        op[count] = "update_ints";
                    else if ($3 ~ /#/ && NF == 4)
                    {
                        op[count] = "undefine";
                        $3 = $4 = "";
                    }
                    else if ($3 ~ /\?/ && NF == 4)
                    {
                        op[count] = "reset";
                        $3 = $4 = "";
                    }
                    else
                        badprop(6);

                    #
                    #   OK -  stash the definition for later
                    #
                    names[count] = $1;
                    $1 = $2 = $NF = "";
                    props[count] = $0;
                }
    END         {
                    #
                    #   All lines validated; return OK status (":")
                    #   followed by definitions in standard format
                    #
                    print ":";
                    for (count in props)
                        print op[count], names[count], props[count];
                    exit 0;
                }' |
{
    read status
    eval ${status:-"error internal error"}
    while read op name value
    do
        if [[ $mode = *add* ]] && propcheck "$mynode" "$name"
        then
            : "already defined, so nothing to do"
        else
            propset "$op" "$mynode" "$name" "$value"
        fi
    done
}
