1.1 --- a/makesd-expand-def Tue May 28 00:30:18 2019 +0200
1.2 +++ b/makesd-expand-def Mon Jun 10 01:37:46 2019 +0200
1.3 @@ -1,7 +1,7 @@
1.4 #!/bin/sh
1.5
1.6 -# Search for a definition in the definitions file, expanding it to the recorded
1.7 -# value, recursively expanding any definition references.
1.8 +# Search for a definition in the definitions file, expanding it recursively to
1.9 +# provide a complete description.
1.10 #
1.11 # Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
1.12 #
1.13 @@ -22,45 +22,17 @@
1.14 PROGNAME=`basename "$0"`
1.15 THISDIR=`dirname "$0"`
1.16
1.17 +COMMON="$THISDIR/makesd-common"
1.18 DEFS="$THISDIR/makesd-defs"
1.19
1.20 +. "$COMMON"
1.21 +
1.22
1.23
1.24 -# Test for options.
1.25 -
1.26 -if [ "$1" = '--original' ] ; then
1.27 - FLAT=$1
1.28 - shift 1
1.29 -else
1.30 - FLAT=
1.31 -fi
1.32 -
1.33 -# Obtain the requested definition name.
1.34 -
1.35 -DEF=$1
1.36 -
1.37 -if [ ! "$DEF" ] || [ "$DEF" = '--help' ] ; then
1.38 - cat 1>&2 <<EOF
1.39 -Usage: $PROGNAME <definition name>
1.40 -
1.41 -Search for a definition of the given name in the definitions file:
1.42 -
1.43 -$DEFS
1.44 -
1.45 -If the definition can be found, the value of the definition is emitted and an
1.46 -exit value of 0 returned. Otherwise, no output is produced and an exit value of
1.47 -1 is returned.
1.48 -EOF
1.49 - exit 1
1.50 -fi
1.51 -
1.52 -
1.53 -
1.54 -# lookup <definition name>
1.55 +# lookup <definition>
1.56 #
1.57 -# Search for a definition of the given name in the definitions file. Emit the
1.58 -# full definition, incorporating multiple lines if continuation characters are
1.59 -# present.
1.60 +# Search for the given definition in the definitions file. Emit the full
1.61 +# definition.
1.62
1.63 lookup()
1.64 {
1.65 @@ -68,105 +40,161 @@
1.66
1.67 # Obtain the line number of the matching definition.
1.68
1.69 - LINENUM=`grep -h -n "^$1\s" "$DEFS" | cut -d: -f1`
1.70 + LINENUM=`search "^$1$" "$DEFS"`
1.71
1.72 if [ "$LINENUM" ] ; then
1.73
1.74 - # Read from the definition line. Line continuations are observed.
1.75 + # Read from the definition until a blank line or the end of file is
1.76 + # encountered. Line continuations are observed.
1.77 +
1.78 + tail -n "+$(($LINENUM + 1))" "$DEFS" | while read LINE ; do
1.79 +
1.80 + # Detect end of definition.
1.81
1.82 - tail -n "+$LINENUM" "$DEFS" | if read LINE ; then
1.83 + if [ ! "$LINE" ] ; then
1.84 + break
1.85 + fi
1.86 +
1.87 + # Show definition lines.
1.88 +
1.89 echo "$LINE"
1.90 - break
1.91 - fi
1.92 + done
1.93 fi
1.94 }
1.95
1.96 -# match <string> <pattern>
1.97 +# consolidate
1.98 #
1.99 -# Attempt to match pattern in string, emitting the string if successful.
1.100 +# Eliminate duplicate properties, preserving only the final definition.
1.101 +
1.102 +consolidate()
1.103 +{
1.104 + sort -k1,1 -t: -s | show_last
1.105 +}
1.106 +
1.107 +show_last()
1.108 +{
1.109 + local FIELD LAST LASTLINE
1.110 +
1.111 + LAST=
1.112 + LASTLINE=
1.113 +
1.114 + while read LINE ; do
1.115 +
1.116 + # Inspect the property details.
1.117
1.118 -match()
1.119 -{
1.120 - if `echo "$1" | grep -q "$2"` ; then
1.121 - echo "$1"
1.122 + FIELD=`get_field "$LINE"`
1.123 +
1.124 + # With a differing property from any previous one, emit the previous
1.125 + # one.
1.126 +
1.127 + if [ "$LAST" ] && [ "$FIELD" != "$LAST" ] ; then
1.128 + echo "$LASTLINE"
1.129 + fi
1.130 +
1.131 + # Retain this property definition for possible future emission.
1.132 +
1.133 + LAST=$FIELD
1.134 + LASTLINE=$LINE
1.135 + done
1.136 +
1.137 + # Emit any remaining line, also indicating whether any lines were processed.
1.138 +
1.139 + if [ "$LASTLINE" ] ; then
1.140 + echo "$LASTLINE"
1.141 return 0
1.142 else
1.143 return 1
1.144 fi
1.145 }
1.146
1.147 -# defname <prefixed name>
1.148 -#
1.149 -# Return the actual definition name from the given prefixed name.
1.150 -
1.151 -defname()
1.152 -{
1.153 - echo "$1" | sed 's/^\$//'
1.154 -}
1.155 -
1.156 -# expand <definition name>
1.157 +# expand <definition>
1.158 #
1.159 # Expand the given definition name to its value, recursively expanding any
1.160 # definition names found in the value text.
1.161
1.162 expand()
1.163 {
1.164 - local FOUND VALUE
1.165 + local TYPE
1.166 +
1.167 + TYPE=`echo "$1" | cut -d' ' -f1`
1.168
1.169 - FOUND=
1.170 - VALUE=
1.171 + # Look up the definition and read each line.
1.172 +
1.173 + lookup "$1" | expand_def "$TYPE"
1.174 +}
1.175
1.176 - for WORD in `lookup "$1"`; do
1.177 - if [ ! "$FOUND" ] ; then
1.178 - FOUND=$WORD
1.179 - continue
1.180 - fi
1.181 +expand_def()
1.182 +{
1.183 + local FIELD LINE RESULT TYPE VALUE
1.184
1.185 - # Prevent recursive expansion if flat mode is selected.
1.186 -
1.187 - if [ ! "$FLAT" ] ; then
1.188 + RESULT=1
1.189
1.190 - # Identify definition names by looking for a $ prefix.
1.191 + while read LINE ; do
1.192 + RESULT=0
1.193
1.194 - DEFNAME=`match "$WORD" '^\\$'`
1.195 + # Inspect the line and find any references to other definitions.
1.196
1.197 - # Attempt to expand definition names.
1.198 + FIELD=`get_field "$LINE"`
1.199 + VALUE=`get_value "$LINE"`
1.200 +
1.201 + # Merge definitions that are adapted.
1.202
1.203 - if [ "$DEFNAME" ] ; then
1.204 - DEFNAME=`defname "$DEFNAME"`
1.205 - EXPANDED=`expand "$DEFNAME"`
1.206 + if [ "$FIELD" = 'adapts' ] ; then
1.207 + expand "$TYPE $VALUE"
1.208 +
1.209 + # Aggregate system components such as partitions and regions.
1.210
1.211 - if [ "$EXPANDED" ] ; then
1.212 - WORD=$EXPANDED
1.213 - fi
1.214 - fi
1.215 - fi
1.216 + elif [ "$TYPE" = 'system' ] && (
1.217 + [ "$FIELD" = 'partition' ] || [ "$FIELD" = 'region' ] ) ; then
1.218 +
1.219 + # Declare regions and partitions in the output.
1.220
1.221 - # Incorporate expansions into the final value.
1.222 + echo "$FIELD"
1.223 + expand "$FIELD $VALUE" | consolidate
1.224 + echo
1.225
1.226 - if [ ! "$VALUE" ] ; then
1.227 - VALUE=$WORD
1.228 + # Otherwise, emit properties of the definition.
1.229 +
1.230 else
1.231 - VALUE="$VALUE $WORD"
1.232 + echo "$LINE"
1.233 fi
1.234 done
1.235
1.236 - # Show the expanded definition value.
1.237 -
1.238 - echo "$VALUE"
1.239 -
1.240 - # Return a result value of 0 if successful, 1 otherwise.
1.241 -
1.242 - if [ "$VALUE" ] ; then
1.243 - return 0
1.244 - else
1.245 - return 1
1.246 - fi
1.247 + return $RESULT
1.248 }
1.249
1.250
1.251
1.252 +# Obtain the requested system name.
1.253 +
1.254 +if [ ! "$1" ] || [ "$1" = '--help' ] ; then
1.255 + cat 1>&2 <<EOF
1.256 +Usage: $PROGNAME <system>
1.257 + $PROGNAME -a | --all | --defs
1.258 +
1.259 +Search for a definition of the given system in the definitions file:
1.260 +
1.261 +$DEFS
1.262 +
1.263 +If the definition can be found, the value of the definition is emitted and an
1.264 +exit value of 0 returned. Otherwise, no output is produced and an exit value of
1.265 +1 is returned.
1.266 +
1.267 +$(show_definitions_description)
1.268 +EOF
1.269 + exit 1
1.270 +fi
1.271 +
1.272 +# Show definitions if requested.
1.273 +
1.274 +if [ "$1" = '-a' ] || [ "$1" = '--all' ] || [ "$1" = '--defs' ] ; then
1.275 + grep '^system' "$DEFS" | sed 's/^system //' | sort
1.276 + exit 0
1.277 +fi
1.278 +
1.279 # Expand the definition and return the result code.
1.280
1.281 -expand "$DEF"
1.282 +DEF=$1
1.283 +
1.284 +expand "system $DEF"
1.285 exit $?