| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 | #!/bin/bash
ini() {
    #
    # do ini operation
    #
    local op=$1
    local arg=$2
    local fn
    local limit=_ini_cat
    case $op in
        lskeys) fn=_ini_lskeys   ;;
        sec)    fn=_ini_grepsec  ;;
        values) fn=_ini_greppath ;;
        1value) fn=_ini_greppath; limit="tail -1" ;;
        *)      die "incorrect use of \`ini()\`"
    esac
    <"$MKIT_INI" $fn "$arg" | $limit
}
_ini_cat() {
    #
    # A no-op for text stream
    #
    while read line;
    do
        printf -- "%s\n" "$line"
    done
}
_ini_expand() {
    #
    # Expand reference value (prefix only)
    #
    local line suffix ref value
    while read line;                        # [foo:bar]/path
    do
        suffix="${line#\[*\]}"              # /path
        ref="${line%$suffix}"               # [foo:bar]
        ref="${ref%\]}"                     # [foo:bar
        ref="${ref#\[}"                     # foo:bar
        value="$(ini 1value "$ref")"        # foo_bar_value
        printf -- "%s\n" "$value$suffix"    # foo_bar_value/path
    done
}
_ini_grepkey() {
    #
    # Read key from a section
    #
    local wnt=$1
    grep '.' \
      | grep -v '\s*#' \
      | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
      | grep -e "^$wnt=" \
      | cut -d= -f2- \
      | _ini_maybe_expand
}
_ini_greppath() {
    #
    # Read key from the right section
    #
    # E.g. `files:share:my/lib.sh` should read
    #
    #     [files:share]
    #         my/lib.sh   = proj/my/lib.sh
    #
    local wnt="$1"
    local wntkey="${wnt##*:}"
    local wntsec="${wnt%:$wntkey}"
    if test "$wntsec" = 'ENV';
    then
        local override="${!wntkey}"
        if test -n "$override";
        then
            echo "$override"
            return
        fi
    fi
    _ini_grepsec "$wntsec" | _ini_grepkey "$wntkey"
}
_ini_grepsec() {
    #
    # Read one INI section
    #
    local wnt="$1"
    local ok=false
    grep '.' \
      | grep -v '\s*#' \
      | while read line;
        do
            case "$line" in
                \[$wnt\]) ok=true;  continue ;;
                \[*\])    ok=false; continue ;;
            esac
            $ok || continue
            printf -- "%s\n" "$line"
        done \
      | sed -e 's/ *= */=/; s/ +$//; s/^//;'
}
_ini_lskeys() {
    #
    # List keys from a section
    #
    local sct="$1"
    _ini_grepsec "$sct" | cut -d= -f1 | sort | uniq
}
_ini_maybe_expand() {
    #
    # Decide whether or not to expand
    #
    if test "$MKIT_INI_EXPAND" -gt 0;
    then
        MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) _ini_expand
    else
        _ini_cat
    fi
}
 |