remakesd

Annotated makesd-expand-def

23:8e8e8d934afa
2019-06-11 Paul Boddie Fixed erroneous partition reference.
paul@0 1
#!/bin/sh
paul@0 2
paul@21 3
# Search for a definition in the definitions file, expanding it recursively to
paul@21 4
# provide a complete description.
paul@15 5
#
paul@15 6
# Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
paul@15 7
#
paul@15 8
# This program is free software; you can redistribute it and/or modify it under
paul@15 9
# the terms of the GNU General Public License as published by the Free Software
paul@15 10
# Foundation; either version 3 of the License, or (at your option) any later
paul@15 11
# version.
paul@15 12
#
paul@15 13
# This program is distributed in the hope that it will be useful, but WITHOUT
paul@15 14
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@15 15
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@15 16
# details.
paul@15 17
#
paul@15 18
# You should have received a copy of the GNU General Public License along with
paul@15 19
# this program.  If not, see <http://www.gnu.org/licenses/>.
paul@15 20
paul@0 21
paul@0 22
PROGNAME=`basename "$0"`
paul@0 23
THISDIR=`dirname "$0"`
paul@0 24
paul@21 25
COMMON="$THISDIR/makesd-common"
paul@14 26
DEFS="$THISDIR/makesd-defs"
paul@0 27
paul@21 28
. "$COMMON"
paul@21 29
paul@0 30
paul@0 31
paul@21 32
# lookup <definition>
paul@0 33
#
paul@21 34
# Search for the given definition in the definitions file. Emit the full
paul@21 35
# definition.
paul@0 36
paul@0 37
lookup()
paul@0 38
{
paul@0 39
    local LINENUM
paul@0 40
paul@0 41
    # Obtain the line number of the matching definition.
paul@0 42
paul@21 43
    LINENUM=`search "^$1$" "$DEFS"`
paul@0 44
paul@0 45
    if [ "$LINENUM" ] ; then
paul@0 46
paul@21 47
        # Read from the definition until a blank line or the end of file is
paul@21 48
        # encountered. Line continuations are observed.
paul@21 49
paul@21 50
        tail -n "+$(($LINENUM + 1))" "$DEFS" | while read LINE ; do
paul@21 51
paul@21 52
            # Detect end of definition.
paul@0 53
paul@21 54
            if [ ! "$LINE" ] ; then
paul@21 55
                break
paul@21 56
            fi
paul@21 57
paul@21 58
            # Show definition lines.
paul@21 59
paul@0 60
            echo "$LINE"
paul@21 61
        done
paul@0 62
    fi
paul@0 63
}
paul@0 64
paul@21 65
# consolidate
paul@0 66
#
paul@22 67
# Eliminate duplicate properties, preserving only the final definition, except
paul@22 68
# for certain properties.
paul@21 69
paul@21 70
consolidate()
paul@21 71
{
paul@22 72
    sort -k1,1 -t: -s | show_last 'expand'
paul@21 73
}
paul@21 74
paul@22 75
# show_last [ <property> ... ]
paul@22 76
#
paul@22 77
# Show only the last property of any given name, preserving duplicate entries
paul@22 78
# only for any given properties.
paul@22 79
paul@21 80
show_last()
paul@21 81
{
paul@21 82
    local FIELD LAST LASTLINE
paul@21 83
paul@21 84
    LAST=
paul@21 85
    LASTLINE=
paul@21 86
paul@21 87
    while read LINE ; do
paul@21 88
paul@21 89
        # Inspect the property details.
paul@0 90
paul@21 91
        FIELD=`get_field "$LINE"`
paul@21 92
paul@21 93
        # With a differing property from any previous one, emit the previous
paul@22 94
        # one. With a preserved property, also emit the previous line.
paul@21 95
paul@22 96
        if [ "$LAST" ] && [ "$FIELD" != "$LAST" ] || is_in "$FIELD" $* ; then
paul@21 97
            echo "$LASTLINE"
paul@21 98
        fi
paul@21 99
paul@21 100
        # Retain this property definition for possible future emission.
paul@21 101
paul@21 102
        LAST=$FIELD
paul@21 103
        LASTLINE=$LINE
paul@21 104
    done
paul@21 105
paul@21 106
    # Emit any remaining line, also indicating whether any lines were processed.
paul@21 107
paul@21 108
    if [ "$LASTLINE" ] ; then
paul@21 109
        echo "$LASTLINE"
paul@0 110
        return 0
paul@0 111
    else
paul@0 112
        return 1
paul@0 113
    fi
paul@0 114
}
paul@0 115
paul@21 116
# expand <definition>
paul@0 117
#
paul@0 118
# Expand the given definition name to its value, recursively expanding any
paul@0 119
# definition names found in the value text.
paul@0 120
paul@0 121
expand()
paul@0 122
{
paul@21 123
    local TYPE
paul@21 124
paul@21 125
    TYPE=`echo "$1" | cut -d' ' -f1`
paul@0 126
paul@21 127
    # Look up the definition and read each line.
paul@21 128
paul@21 129
    lookup "$1" | expand_def "$TYPE"
paul@21 130
}
paul@0 131
paul@21 132
expand_def()
paul@21 133
{
paul@21 134
    local FIELD LINE RESULT TYPE VALUE
paul@0 135
paul@21 136
    RESULT=1
paul@0 137
paul@21 138
    while read LINE ; do
paul@21 139
        RESULT=0
paul@0 140
paul@21 141
        # Inspect the line and find any references to other definitions.
paul@0 142
paul@21 143
        FIELD=`get_field "$LINE"`
paul@21 144
        VALUE=`get_value "$LINE"`
paul@21 145
paul@21 146
        # Merge definitions that are adapted.
paul@0 147
paul@21 148
        if [ "$FIELD" = 'adapts' ] ; then
paul@21 149
            expand "$TYPE $VALUE"
paul@21 150
paul@21 151
        # Aggregate system components such as partitions and regions.
paul@0 152
paul@21 153
        elif [ "$TYPE" = 'system' ] && (
paul@21 154
           [ "$FIELD" = 'partition' ] || [ "$FIELD" = 'region' ] ) ; then
paul@21 155
paul@21 156
            # Declare regions and partitions in the output.
paul@0 157
paul@21 158
            echo "$FIELD"
paul@21 159
            expand "$FIELD $VALUE" | consolidate
paul@21 160
            echo
paul@0 161
paul@21 162
        # Otherwise, emit properties of the definition.
paul@21 163
paul@0 164
        else
paul@21 165
            echo "$LINE"
paul@0 166
        fi
paul@0 167
    done
paul@0 168
paul@21 169
    return $RESULT
paul@0 170
}
paul@0 171
paul@0 172
paul@0 173
paul@21 174
# Obtain the requested system name.
paul@21 175
paul@21 176
if [ ! "$1" ] || [ "$1" = '--help' ] ; then
paul@21 177
    cat 1>&2 <<EOF
paul@21 178
Usage: $PROGNAME <system>
paul@21 179
       $PROGNAME -a | --all | --defs
paul@21 180
paul@21 181
Search for a definition of the given system in the definitions file:
paul@21 182
paul@21 183
$DEFS
paul@21 184
paul@21 185
If the definition can be found, the value of the definition is emitted and an
paul@21 186
exit value of 0 returned. Otherwise, no output is produced and an exit value of
paul@21 187
1 is returned.
paul@21 188
paul@21 189
$(show_definitions_description)
paul@21 190
EOF
paul@21 191
    exit 1
paul@21 192
fi
paul@21 193
paul@21 194
# Show definitions if requested.
paul@21 195
paul@21 196
if [ "$1" = '-a' ] || [ "$1" = '--all' ] || [ "$1" = '--defs' ] ; then
paul@21 197
    grep '^system' "$DEFS" | sed 's/^system //' | sort
paul@21 198
    exit 0
paul@21 199
fi
paul@21 200
paul@0 201
# Expand the definition and return the result code.
paul@0 202
paul@21 203
DEF=$1
paul@21 204
paul@21 205
expand "system $DEF"
paul@0 206
exit $?