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@21 | 67 | # Eliminate duplicate properties, preserving only the final definition. |
paul@21 | 68 | |
paul@21 | 69 | consolidate() |
paul@21 | 70 | { |
paul@21 | 71 | sort -k1,1 -t: -s | show_last |
paul@21 | 72 | } |
paul@21 | 73 | |
paul@21 | 74 | show_last() |
paul@21 | 75 | { |
paul@21 | 76 | local FIELD LAST LASTLINE |
paul@21 | 77 | |
paul@21 | 78 | LAST= |
paul@21 | 79 | LASTLINE= |
paul@21 | 80 | |
paul@21 | 81 | while read LINE ; do |
paul@21 | 82 | |
paul@21 | 83 | # Inspect the property details. |
paul@0 | 84 | |
paul@21 | 85 | FIELD=`get_field "$LINE"` |
paul@21 | 86 | |
paul@21 | 87 | # With a differing property from any previous one, emit the previous |
paul@21 | 88 | # one. |
paul@21 | 89 | |
paul@21 | 90 | if [ "$LAST" ] && [ "$FIELD" != "$LAST" ] ; then |
paul@21 | 91 | echo "$LASTLINE" |
paul@21 | 92 | fi |
paul@21 | 93 | |
paul@21 | 94 | # Retain this property definition for possible future emission. |
paul@21 | 95 | |
paul@21 | 96 | LAST=$FIELD |
paul@21 | 97 | LASTLINE=$LINE |
paul@21 | 98 | done |
paul@21 | 99 | |
paul@21 | 100 | # Emit any remaining line, also indicating whether any lines were processed. |
paul@21 | 101 | |
paul@21 | 102 | if [ "$LASTLINE" ] ; then |
paul@21 | 103 | echo "$LASTLINE" |
paul@0 | 104 | return 0 |
paul@0 | 105 | else |
paul@0 | 106 | return 1 |
paul@0 | 107 | fi |
paul@0 | 108 | } |
paul@0 | 109 | |
paul@21 | 110 | # expand <definition> |
paul@0 | 111 | # |
paul@0 | 112 | # Expand the given definition name to its value, recursively expanding any |
paul@0 | 113 | # definition names found in the value text. |
paul@0 | 114 | |
paul@0 | 115 | expand() |
paul@0 | 116 | { |
paul@21 | 117 | local TYPE |
paul@21 | 118 | |
paul@21 | 119 | TYPE=`echo "$1" | cut -d' ' -f1` |
paul@0 | 120 | |
paul@21 | 121 | # Look up the definition and read each line. |
paul@21 | 122 | |
paul@21 | 123 | lookup "$1" | expand_def "$TYPE" |
paul@21 | 124 | } |
paul@0 | 125 | |
paul@21 | 126 | expand_def() |
paul@21 | 127 | { |
paul@21 | 128 | local FIELD LINE RESULT TYPE VALUE |
paul@0 | 129 | |
paul@21 | 130 | RESULT=1 |
paul@0 | 131 | |
paul@21 | 132 | while read LINE ; do |
paul@21 | 133 | RESULT=0 |
paul@0 | 134 | |
paul@21 | 135 | # Inspect the line and find any references to other definitions. |
paul@0 | 136 | |
paul@21 | 137 | FIELD=`get_field "$LINE"` |
paul@21 | 138 | VALUE=`get_value "$LINE"` |
paul@21 | 139 | |
paul@21 | 140 | # Merge definitions that are adapted. |
paul@0 | 141 | |
paul@21 | 142 | if [ "$FIELD" = 'adapts' ] ; then |
paul@21 | 143 | expand "$TYPE $VALUE" |
paul@21 | 144 | |
paul@21 | 145 | # Aggregate system components such as partitions and regions. |
paul@0 | 146 | |
paul@21 | 147 | elif [ "$TYPE" = 'system' ] && ( |
paul@21 | 148 | [ "$FIELD" = 'partition' ] || [ "$FIELD" = 'region' ] ) ; then |
paul@21 | 149 | |
paul@21 | 150 | # Declare regions and partitions in the output. |
paul@0 | 151 | |
paul@21 | 152 | echo "$FIELD" |
paul@21 | 153 | expand "$FIELD $VALUE" | consolidate |
paul@21 | 154 | echo |
paul@0 | 155 | |
paul@21 | 156 | # Otherwise, emit properties of the definition. |
paul@21 | 157 | |
paul@0 | 158 | else |
paul@21 | 159 | echo "$LINE" |
paul@0 | 160 | fi |
paul@0 | 161 | done |
paul@0 | 162 | |
paul@21 | 163 | return $RESULT |
paul@0 | 164 | } |
paul@0 | 165 | |
paul@0 | 166 | |
paul@0 | 167 | |
paul@21 | 168 | # Obtain the requested system name. |
paul@21 | 169 | |
paul@21 | 170 | if [ ! "$1" ] || [ "$1" = '--help' ] ; then |
paul@21 | 171 | cat 1>&2 <<EOF |
paul@21 | 172 | Usage: $PROGNAME <system> |
paul@21 | 173 | $PROGNAME -a | --all | --defs |
paul@21 | 174 | |
paul@21 | 175 | Search for a definition of the given system in the definitions file: |
paul@21 | 176 | |
paul@21 | 177 | $DEFS |
paul@21 | 178 | |
paul@21 | 179 | If the definition can be found, the value of the definition is emitted and an |
paul@21 | 180 | exit value of 0 returned. Otherwise, no output is produced and an exit value of |
paul@21 | 181 | 1 is returned. |
paul@21 | 182 | |
paul@21 | 183 | $(show_definitions_description) |
paul@21 | 184 | EOF |
paul@21 | 185 | exit 1 |
paul@21 | 186 | fi |
paul@21 | 187 | |
paul@21 | 188 | # Show definitions if requested. |
paul@21 | 189 | |
paul@21 | 190 | if [ "$1" = '-a' ] || [ "$1" = '--all' ] || [ "$1" = '--defs' ] ; then |
paul@21 | 191 | grep '^system' "$DEFS" | sed 's/^system //' | sort |
paul@21 | 192 | exit 0 |
paul@21 | 193 | fi |
paul@21 | 194 | |
paul@0 | 195 | # Expand the definition and return the result code. |
paul@0 | 196 | |
paul@21 | 197 | DEF=$1 |
paul@21 | 198 | |
paul@21 | 199 | expand "system $DEF" |
paul@0 | 200 | exit $? |