From: Prarit Bhargava <[email protected]>

evaluate_configs is a tool that verifies the CONFIG setting heirarchy for
the kernel.  It can display settings for a specific CONFIG, find and
remove extra CONFIG files and synchronize the CONFIG settings between
the common, ark, and fedora directories.

For example, to view a config,

[prarit@prarit configs]$ ./evaluate_configs -p priority.rhel -c 
CONFIG_HEADER_TEST
CONFIG_HEADER_TEST
legend                         g  ga1  ga2  d  da1  da2
common-x86_64                  y  -    -    -  X    -
common-ppc64le                 y  -    X    -  -    X
common-s390x                   y  -    X    -  -    X
common-s390x-zfcpdump          y  -    -    X  X    X
common-aarch64                 y  -    -    -  X    -
ark-x86_64                     y  -    -    -  X    -
ark-ppc64le                    y  -    X    -  -    X
ark-s390x                      y  -    X    -  -    X
ark-s390x-zfcpdump             y  -    -    X  X    X
ark-aarch64                    y  -    -    -  X    -
pending-common-x86_64          -  -    -    -  X    -
pending-common-ppc64le         -  -    X    -  -    X
pending-common-s390x           -  -    X    -  -    X
pending-common-s390x-zfcpdump  -  -    -    X  X    X
pending-common-aarch64         -  -    -    -  X    -

The legend row, shows the subdirectory entries.  These can be mapped
back to the priority.rhel entries, for example, for x86_64

x86_64=generic:generic-x86:generic-x86-x86_64
x86_64-debug=generic:generic-x86:generic-x86-x86_64:debug:debug-x86-x86_64

are combined into one entry for x86_64 where

g maps to "generic"
ga1 maps to "generic-x86"
ga2 maps to "generic-x86-x86-64"
d maps to "debug"
da1 maps to nothing (more on this below)
da2 maps to debug-x86-x86_64

The left hand column indicates the directory and config-variant.  For
example, ark-s390x-zfcpdump is the s390x-zfcpdump variant and the
row beside it shows the config settings in the ark directory.

The data contained in the output can have 5 values:

        y = CONFIG is set to 'y'
        m = CONFIG is set to 'm'
        n = CONFIG is set to 'is not set'
        - = CONFIG file does not exist
        X = CONFIG file entry is not in priority file

As can be seen above in the CONFIG_NUMA output, da1 is not present
in the priority.rhel file and is marked with an 'X'.

The -x option can be used to evaluate all the CONFIGs by executing, for
example

|# evaluate_configs -p priority.rhel -f

or a single CONFIG

|# evaluate_configs -p priority.rhel -f -c CONFIG_HEADER_TEST

and similarily the common, ark and fedora CONFIGs can be verified by
executing

evaluate_configs -j

or

evaluate_configs -j -c CONFIG_HEADER_TEST

The two CONFIG patches in this patchset are runs of

evaluate_configs -p priority.rhel -f
evaluate_configs -p priority.fedora -f

and

evaluate_configs -j

Signed-off-by: Prarit Bhargava <[email protected]>
---
 redhat/configs/README.evaluate_configs |  134 +++
 redhat/configs/evaluate_configs        | 1278 +++++++++++++++---------
 redhat/configs/priority.common         |   28 +
 redhat/configs/priority.fedora         |   16 +-
 redhat/configs/priority.rhel           |   16 +-
 5 files changed, 1015 insertions(+), 457 deletions(-)
 create mode 100644 redhat/configs/README.evaluate_configs
 create mode 100644 redhat/configs/priority.common

diff --git a/redhat/configs/README.evaluate_configs 
b/redhat/configs/README.evaluate_configs
new file mode 100644
index 000000000000..81bd44e2ac7e
--- /dev/null
+++ b/redhat/configs/README.evaluate_configs
@@ -0,0 +1,134 @@
+evaluate_configs is a tool that can verify the settings of kernel
+CONFIGs in the redhat/configs directory.  The data for evaluate_configs
+is a combination of the redhat/configs files and the priority files.
+
+Introduction to Basic Output
+============================
+
+This command demonstrates how to display information about the
+CONFIG_HEADER_TEST option for RHEL.
+
+[prarit@prarit configs]$ ./evaluate_configs -p priority.rhel -c 
CONFIG_HEADER_TEST
+CONFIG_HEADER_TEST
+legend                         g  ga1  ga2  d  da1  da2
+common-x86_64                  y  -    -    -  X    -
+common-ppc64le                 y  -    X    -  -    X
+common-s390x                   y  -    X    -  -    X
+common-s390x-zfcpdump          y  -    -    X  X    X
+common-aarch64                 y  -    -    -  X    -
+ark-x86_64                     y  -    -    -  X    -
+ark-ppc64le                    y  -    X    -  -    X
+ark-s390x                      y  -    X    -  -    X
+ark-s390x-zfcpdump             y  -    -    X  X    X
+ark-aarch64                    y  -    -    -  X    -
+pending-common-x86_64          -  -    -    -  X    -
+pending-common-ppc64le         -  -    X    -  -    X
+pending-common-s390x           -  -    X    -  -    X
+pending-common-s390x-zfcpdump  -  -    -    X  X    X
+pending-common-aarch64         -  -    -    -  X    -
+
+The legend row, shows the subdirectory entries.  These can be mapped
+back to the priority.rhel entries, for example, for x86_64
+
+# x86_64
+x86_64=generic:generic-x86:generic-x86-x86_64
+x86_64-debug=generic:generic-x86:generic-x86-x86_64:debug:debug-x86-x86_64
+
+are combined into one entry for x86_64 where
+
+g maps to "generic"
+ga1 maps to "generic-x86"
+ga2 maps to "generic-x86-x86-64"
+d maps to "debug"
+da1 maps to nothing (more on this below)
+da2 maps to debug-x86-x86_64
+
+The left hand column indicates the directory and config-variant.  For
+example, ark-s390x-zfcpdump is the s390x-zfcpdump variant and the
+row beside it shows the config settings in the ark directory.
+
+The data contained in the output can have 5 values:
+
+       y = CONFIG is set to 'y'
+       m = CONFIG is set to 'm'
+       n = CONFIG is set to 'is not set'
+       - = CONFIG file does not exist
+       X = CONFIG file entry is not in priority file
+
+As can be seen above in the CONFIG_NUMA output, da1 is not present
+in the priority.rhel file and is marked with an 'X'.
+
+Options
+=======
+
+       -c CONFIG
+               Evalulate these specific CONFIGs. This can be a file,
+               or a comma-separated list.  If nothing is specified then
+               all CONFIGs are examined by default.)
+       -d
+               Enable debug
+       -p priority.file
+               Specify a priority.file (no default)
+       -j
+               Evaluate common directory
+       -f
+               Evaluate and fix a priority's CONFIGs
+
+All commands except -j require a -p argument.
+
+Evaluate CONFIGs
+================
+
+The -x option can be used to evaluate all the CONFIGs by executing, for
+example
+
+# evaluate_configs -p priority.rhel -f
+
+or a single CONFIG
+
+# evaluate_configs -p priority.rhel -f -c CONFIG_HEADER_TEST
+
+The Evaluate Output will show a different view than the Basic Output above:
+
+ERROR: (heirarchy) ark/generic/CONFIG_HEADER_TEST : superseding value has y.
+|CONFIG_HEADER_TEST (ark-aarch64)
+|g  ga1  ga2  d  da1  da2  g  ga1  ga2  d  da1  da2  g  ga1  ga2  d  da1  da2
+|y  -    -    -  X    -    y  -    -    -  X    -    -  -    -    -  X    -
+| Deleting ark/generic/CONFIG_HEADER_TEST
+
+This view is the Basic Output's aarch64 data in a single line,  From the
+above output,
+
+common-aarch64                 y  -    -    -  X    -
+ark-aarch64                    y  -    -    -  X    -
+pending-common-aarch64         -  -    -    -  X    -
+
+The Evaluate output makes it easier to visually see a conflict.   One
+can read the line and if there are two y|m|n separated by one or more - or
+X's in a line, then there is the possibility of a conflict.
+
+If the CONFIG setting is found to be incorrect it it automatically removed
+and a message
+
+| Deleting ark/generic/CONFIG_HEADER_TEST
+
+will be output.
+
+Evaluate common Directory
+=========================
+
+This function does a 1-to-1 comparison of CONFIG settings in the
+ark and fedora directories, and checks to see if the CONFIG should be set
+in the common directory.
+
+The output is the same as the Evaluate output.
+
+This functionality uses the priority.common file and can be executed via
+
+evaluate_configs -j
+
+for all CONFIGs, or
+
+evaluate_configs -j -c CONFIG_HEADER_TEST
+
+for a single CONFIG.
diff --git a/redhat/configs/evaluate_configs b/redhat/configs/evaluate_configs
index 5ed3e0407bca..1a45a29f7d6a 100755
--- a/redhat/configs/evaluate_configs
+++ b/redhat/configs/evaluate_configs
@@ -1,528 +1,896 @@
-#!/bin/bash
-#
-# The order of priority is
-#
-#      debug/arch highest (ie, this can override the remaining levels)
-#      debug/
-#      generic/arch
-#      generic/   lowest (ie, this value can be overridden by anything above)
-#
-# however, inheritance is the opposite.  That is if a CONFIG is undefined
-# the lower level's config is inherited at the higher level.
-#
-# ex) Consider CONFIG_MLX4_EN
-# which is set as
-#                                           s390x
-#      arch    aarch64 ppc64le s390x x86_64 zfcpd
-#
-#      d_a       x       x       x      x     x   <<< generic/s390x/zfcpdump
-#      debug     x       x       x      x     |   <<< noop for s390/zfcpdump
-#      gen_a     m       m       m      m     m   <<< same as s390x
-#      gen       n       n       n      n     n
-#
-# where
-#      x = no file/undefined
-#      n = not set
-#      m = module
-#      y = built in
-#      c = character/string setting
-#
-# The arch-debug configs would have m, as it is inherited from gen_a.
-# All the arch configs would have m, because gen_a overrode gen.
-#
-# Obviously, the debug and gen rows will have the same setting as there
-# is one setting for all arches.
-#
-# Rules:
-# 1) If an entire arch row is majority m/y/n, then the generic/debug row should
-# be m/y/n.
-# 2) A column should not have back-to-back identical settings, ex) m followed
-# by an m.
-# 3) debug can have the same setting as gen.  The config set is described
-# in the priority file.
-# 4) make as few as files as possible.  That might sound crazy but consider the
-# example above.  gen_a has separate files which are all =m.  It is more
-# correct to have a single gen file =m.
-#
-# TODO: Inherit priority map from priority file?
-# TODO: What to do with character & string configs?
-# TODO: Can some of the syntax errors be cleaned up?  For example blank lines,
-# or comment on the same line as a config?
-#
-
-DIR=./
-
-usage()
-{
-       echo "evaluate_configs [ -b | -c | -d | -s | -f ]"
-       echo "  -b : balance level (generic, generic/arch, debug, debug/arch) 
CONFIGs"
-       echo "  -c : check arch CONFIGs"
-       echo "  -d : enable debug"
-       echo "  -s : check CONFIGs syntax"
-       echo "  -f : find dead CONFIGs"
+#!/usr/bin/bash
+trap '[ -d "$tempdir" ] && rm -rf "$tempdir"' EXIT INT
+
+# TODO: -c takes a comma separated list or file?
+# TODO: allow for user to specify CONFIGS ^^^ ?
+# TODO: move the undo the p setting to map_configs_to_array
+# TODO: Fix ERROR: message so it only shows when the file is being deleted
+
+DEBUG=false
+
+# global definitions
+CONFIG=
+priority_file=
+ORDER=
+cfgvariants=
+toplevels=
+subdirs=
+rows=
+columns=
+configmap=
+cfgs=
+cfgs_base=
+weightorig=
+numorder=
+longheader=
+weightorig=
+weight=
+
+tempdir=$(mktemp -d)
+
+whatcouldgowrong() {
+       echo ""
+       echo "usage: evaluate_configs [-c CONFIG] [-d] [-j] [ -p priority_file]"
+       echo ""
+       echo "      -c CONFIG          Evalulate specific CONFIGs (file or csl)"
+       echo "      -d                 Enable debug"
+       echo "      -p priority.file   Specify a priority.file (no default)"
+       echo "      -j                 Evaluate common directory"
+       echo "      -f                 Evaluate CONFIGs"
+       echo ""
+       echo "examples)"
+       echo ""
+       echo "To show the status of CONFIG_HEADER_TEST in ARK,"
+       echo "  ./evaluate_configs -p priority.rhel -c CONFIG_HEADER_TEST"
+       echo ""
+       echo "To fix all the CONFIGS in Fedora,"
+       echo "  ./evaluate_configs -p priority.fedora -x"
+       echo ""
+       echo "To fix only CONFIG_HEADER_TEST in RHEL,"
+       echo "  ./evaluate_configs -p priority.fedora -c CONFIG_HEADER_TEST -x"
+       echo ""
+       echo "To fix the common directory entries,"
+       echo " ./evaluate_configs -j"
        echo ""
-       echo "See redhat/docs/editing_CONFIGS.txt for more information"
        exit 1
 }
 
-#
-# read_file: Read a config file and return n (is not set), y (=y), m (=m),
-# c (for a character setting or a file that contains only comments), and
-# x if the file does not exist.
-#
-read_file() # $1 is the full file path
-{
-       filepath=$1
-       if test -e $filepath; then
-               egrep "# CONFIG.*is not set" $filepath >& /dev/null && echo "n" 
&& return
-               egrep "CONFIG.*=" $filepath >& /dev/null
-               if [ $? -eq 0 ]; then
-                       egrep "=y" $filepath >& /dev/null && echo "y" && return
-                       egrep "=m" $filepath >& /dev/null && echo "m" && return
-                       # some files may equal a number or a string
-                       egrep "=*" $filepath >& /dev/null && echo "c" && echo 
$filepath >> $DIR/.strlist && return
+# Get a list of the config-variants
+get_cfgvariants() { # uses priority_file
+       local configvariant
+       local cfgvariant
+
+       # The priority files have a config-variant, followed by a hierarchy of
+       # directories to examine for that config level.  The directories have
+       # '-' instead of '/'.
+       #
+       # For example,
+       #
+       # ppc64le-debug=generic:generic-powerpc:debug:debug-powerpc
+       #
+
+       while read -r configvariant
+       do
+               # ignore any line with whitespace
+               test -z "$configvariant" && continue
+               # ignore any line beginning with a #
+               [[ "$configvariant" == \#* ]] && continue
+               # ignore any line beginning with ORDER
+               [[ "$configvariant" == ORDER* ]] && continue
+               # ignore any line beginning with EMPTY
+               [[ "$configvariant" == EMPTY* ]] && continue
+
+               # -debug variants must include the base variant
+               # does the priority file contain a debug variant?
+               cfgvariant=$(echo "$configvariant" | cut -d "=" -f 1)
+               if grep -q "$cfgvariant-debug" "$priority_file"; then
+                       # if it does, skip this variant and only use -debug
+                       continue
                fi
-       else
-               echo "x" # file does not exist
-               return
-       fi
-       # some files may contain only comments
-       echo "c"
+
+               # if this variant has a -debug, remove the -debug
+               cfgvariant=$(echo "$cfgvariant" | awk -F "-debug" ' { print $1 
} ')
+
+               # output "cfgvariant | configorder"
+               echo "$cfgvariant | $(echo "$configvariant" | cut -d "=" -f 2 | 
tr : " " )"
+       done < $priority_file
 }
 
-#
-# get_arch_files: Read the value of a config for all arches.
-#
-# For example, 'get_arch_files generic CONFIG_FOO' would read
-# the generic/aarch64/CONFIG_FOO, generic/powerpc64le/CONFIG_FOO, etc.
-# and return a string like 'xynnn'.  Note that the last character
-# is the s390x/zfcpdump entry.
-#
-get_arch_files() # $1 is directory, $2 is CONFIG
-{
-       # The second s390x entry is really s390x/zfcpdump
-       for arch in "aarch64" "powerpc64le" "s390x" "x86_64" "s390x"
+# Find top level dirs for each ORDER. These are normally just debug and config.
+get_toplevel_dirs() { # uses cfgvariants
+       local cfg
+       local cfgvariant
+
+       # anything with a dash(-) in it is a subdir
+       echo "$cfgvariants" | while read -r cfgvariant
        do
-               # Need to special case generic powerpc64 & powerpc64le
-               # because they have an extra "hop" between them at
-               # the arch level
-               [ "$arch" == "powerpc64le" ] && [ -e $DIR/$1/powerpc64/$2 ] && 
arch=powerpc64
-               val=$(read_file $DIR/$1/$arch/$2)
-               echo -n $val
-       done
-       echo ""
+               cfg=$(echo "$cfgvariant" | cut -d "|" -f 2)
+               for i in $cfg
+               do
+                       echo "$i" | grep -v "-"
+               done
+       done | sort -u | tr '\n' ' '
 }
 
-#
-# get_config_files: Read the config files and return the data
-# in a matrix.
-# ex) Consider CONFIG_MLX4_EN
-# which is set as
-#                                           s390x
-#      arch    aarch64 ppc64le s390x x86_64 zfcpd
-#
-#      d_a       x       x       x      x     x   <<< generic/s390x/zfcpdump
-#      debug     x       x       x      x     |   <<< noop for s390/zfcpdump
-#      gen_a     m       m       m      m     m   <<< same as s390x
-#      gen       n       n       n      n     n
-#
-# would be returned as
-#
-#      xxxxx
-#      xxxxx
-#      mmmmm
-#      nnnnn
-#
-get_config_files() # $1 is CONFIG
-{
-       generic=$(read_file $DIR/generic/$1)
-       generic_arch=$(get_arch_files generic $1)
-       debug=$(read_file $DIR/debug/$1)
-       debug_arch=$(get_arch_files debug $1)
-       zfcpdump=$(read_file $DIR/generic/s390x/zfcpdump/$1)
-
-       # debug/arch
-       echo "${debug_arch::-1}$zfcpdump"
-       # debug, the 'x' at the end is for s390x/zfcpdump
-       echo "${debug}${debug}${debug}${debug}x"
-       # generic/arch
-       echo $generic_arch
-       # generic
-       echo $generic$generic$generic$generic$generic
+# For each top level count subdirs and find max subdirs for each top level
+get_subdirs() { # uses $cfgvariants and $toplevels
+       local max
+       local LINE
+       local count
+       local toplevel
+
+       for toplevel in $toplevels
+       do
+               max=0
+               count=0
+               OLDIFS=$IFS; IFS=$'\n'; for LINE in "$cfgvariants"
+               do
+                       LINE=$(echo "$LINE" | cut -d "|" -f 2)
+                       count=0
+                       IFS=$' '; for i in $LINE
+                       do
+                               echo "$i" | grep -q -v $toplevel && continue
+                               count=$(echo "$i" | awk -F "-" '{print NF-1}')
+                               [ "$max" -lt "$count" ] && max="$count"
+                       done
+               done
+               IFS=$OLDIFS
+               echo "$toplevel subdirs $((max + 1))"
+       done
 }
 
-#
-# reconstruct_file: return the CONFIG file at a specific location in
-# the matrix.  For example, (1,3) would be generic/powerpc64le.
-#
-reconstruct_file() # $1 is CONFIG, $2 a x-coordinate  $3 is the y-coordinate
-{
-       _dir=$3
-       # X-axis: "aarch64" "powerpc64le" "s390x" "x86_64" "s390x zfcpdump"
-       case $2 in
-       0)      arch="aarch64";;
-       1)      arch="powerpc64le";;
-       2)      arch="s390x";;
-       3)      arch="x86_64";;
-       4)
-               arch="s390x/zfcpdump"
-               #(4,0) is interpreted as generic/s390x/zfcpdump (4,2)
-               [ $_dir -eq 0 ] && _dir=2
-               ;;
-       esac
+# For each config-variant, find missing sub-directories and mark them as 
"EMPTY"
+# This is very helpful for stage 3.
+fix_config_variants() { # uses $toplevels, $subdirs, $cfgvariants
 
-       # Y-axis: debug-arch,debug,generic-arch,generic
-       case $_dir in
-       0)
-               # Need to special case generic powerpc64 & powerpc64le
-               # because they have an extra "hop" between them at
-               # the arch level
-               [ "$arch" == "powerpc64le" ] && [ -e $DIR/debug/powerpc64/$1 ] 
&& arch="powerpc64"
-               dir="debug/$arch";;
-       1)      dir="debug";;
-       2)
-               # Need to special case generic powerpc64 & powerpc64le
-               # because they have an extra "hop" between them at
-               # the arch level
-               [ "$arch" == "powerpc64le" ] && [ -e $DIR/generic/powerpc64/$1 
] && arch="powerpc64"
-               dir="generic/$arch";;
-       3)      dir="generic";;
-       esac
+for toplevel in $toplevels
+do
+       local subdircnt
+       local linenum
+       local cfgvariant
+       local LINE
+       local count
+       local oldentry
+       local newentry
+       local found
+       local dashcount
+       local new
+
+       subdircnt=$(echo "$subdirs" | grep "$toplevel" | awk -F "subdirs" ' { 
print $2 } ')
+       linenum=0
+       echo "$cfgvariants" | while read -r cfgvariant
+       do
+               linenum=$((linenum + 1))
+               # this seems strange to immediately reset cfgvariant but we
+               # want the value from the file, not the one in memory.  The
+               # value in the file may have been modified by a previous
+               # toplevel.
+               cfgvariant=$(sed "${linenum}q;d" "$tempdir"/cfgvariants)
+
+               LINE=$(echo "$cfgvariant" | cut -d "|" -f 2)
+
+               $DEBUG && echo "LINE=$LINE"
+               # get the actual number of subdirs
+               count=$(for i in $LINE
+               do
+                       echo "$i" | grep -q -v "$toplevel" && continue
+                       echo "$i" | awk -F "-" '{print NF-1}'
+               done | wc -l)
 
-       echo "$DIR/$dir/$1"
-}
+               [ -z "$count" ] && continue
+               $DEBUG && echo "count=$count"
 
-#
-# create_file: Create a config file
-#
-create_file() # $1 is the CONFIG, $2 is the filename, $3 is the value (m/n/x/y)
-{
-       case $3 in
-       x) rm -f $2;;
-       n) echo "# $1 is not set" > $2 ;;
-       m) echo "$1=m" > $2 ;;
-       y) echo "$1=y" > $2 ;;
-       esac
-}
+               # if the number of subdirs is the same, then bail
+               [ "$count" -eq "$subdircnt" ] && continue
 
-#
-# syntax_check: Check the syntax of a config file.  Files cannot be
-# empty, and must be one of "is not set", "=y", "=m".
-#
-syntax_check() # $1 is the config filename
-{
-       num=$(cat $1 | wc -l)
-       # 0 length is always bad (empty)
-       [ $num -eq 0 ] && echo "$1 has zero length" && return 0
-       # most files are length one, so special case it
-       if [ $num -eq 1 ]; then
-               egrep -E "^#.*is not set" $1 >& /dev/null && return 0
-               egrep -E "^CONFIG.*=" $1 >& /dev/null && return 0
-       fi
+               $DEBUG && echo "missing entries LINE=$LINE"
+               oldentry=$(for i in $LINE
+               do
+                       echo "$i" | grep -q "$toplevel" && echo "$i" | tr "\n" 
" "
+               done| xargs)
+               $DEBUG && echo "oldentry=|$oldentry|"
 
-       # all comments are okay.
-       numcomments=$(egrep "^#" $1 | wc -l)
-       [ $numcomments -eq $num ] && return 0
+               # Find the missing entry
+               found=$(for i in $oldentry
+               do
+                       dashcount=$(echo "$i" | awk -F "-" '{print NF-1}')
+                       dashcount=$((dashcount + 1))
+                       echo $dashcount
+               done | tr "\n" " ")
+               $DEBUG && echo "found=$found"
+
+               # build the missing entry
+               count=1
+               newentry=$(for i in $(seq 1 "$subdircnt")
+               do
+                       if echo "$found" | grep -q "$i"; then
+                               echo "$oldentry" | cut -d " " -f "$count"
+                               count=$((count + 1))
+                       else
+                               echo "${toplevel}-EMPTY$((i - 1))"
+                       fi
+               done | tr "\n" " " | xargs)
+               $DEBUG && echo "newentry=|$newentry|"
 
-       numcomments=$((numcomments + 1))
-       if [ $numcomments -eq $num ]; then
-               option=$(egrep -v "^#" $1)
-               egrep -v "^#" $1 | egrep -E "^CONFIG.*=" >& /dev/null && return 0
-       fi
-       echo "$1 is not correct"
-       cat $1
-       return 1
+               # insert the missing entry
+               if echo "$LINE" | grep -q "$toplevel"; then
+                       new=${cfgvariant//$oldentry/$newentry}
+               else
+                       # Assuming that there is always a generic entry
+                       # followed by a debug entry.  If a debug only config
+                       # variant exists, there is a possibility that this
+                       # screws up badly because the EMPTY tags are always
+                       # added the end of the string. #FIXME
+                       new="$cfgvariant $newentry"
+               fi
+
+               $DEBUG && echo "REPLACED:"
+               $DEBUG && echo "orig=$cfgvariant"
+               $DEBUG && echo " new=$new"
+
+               sed -i "${linenum}s/${cfgvariant}/${new}/" 
"$tempdir"/cfgvariants
+
+               $DEBUG && echo "----------------------------"
+       done
+done
 }
 
-#
-# check_overrides: Do the requested arch overrides need to be set?
-#
-# On any column, if a higher level has the same option as a lower level, and is
-# separated from the lower level by 0 or more unset configs, then the higher
-# level option is not necessary.
-#
-check_overrides()
-{
-       local CONFIG=$1
-       config_data=$(get_config_files $CONFIG)
-
-       # some examples of rules
-       # - arch/generic can be a mix of y/m/n/c and generic can be xxxx
-       # - arch/generic can be all y/m/n/c and generic cannot be xxxx
-       # - arch/generic cannot be the same as generic
-       # - debug cannot be the same as arch/generic
-       # - debug cannot be the same as generic if arch/generic is the same
-       #   as generic or if arch/generic is xxxx
-       # - arch/debug cannot be the same as debug
-       # - arch/debug can be a mix of y/m/n/c and debug can be xxxx
-       # - arch/debug can be all y/m/n/c and debug cannot be xxxx
-
-       # x/y/m/n/c are valid values
-       # find the errors
-       # look at each entry in debug_arch and work "down" to generic.
-
-       echo "$config_data" | grep "c" >& /dev/null
-       [ $? -eq 0 ] && return 0
-
-       x=0
-       # All four arches must vote to remove a debug or generic entry
-       configvote=( 1 4 1 5 )
-       while [ $x -le 4 ]
+# create a configmap
+get_configmap() { # uses $ORDER and $cfgvariants
+       local configvariant
+       local arch
+       local _configorder
+       local configorder
+       local order
+
+       for order in $ORDER
        do
-               y=0
-               old="x"
-               while [ $y -le 3 ]
-               do
-                       str=$(echo "$config_data" | sed -n "$((y + 1)){p;q}")
-                       new=${str:$x:1}
-
-                       if [ "$old" == "x" ]; then
-                               old=$new
-                               oldx=$x
-                               oldy=$y
-                       elif [ "$old" == "$new" ]; then
-                               configvote[$oldy]=$((configvote[$oldy] - 1))
-                               [ "$DEBUG" ] && echo "$CONFIG: warning $old 
($oldx, $oldy) and $new ($x,$y) is invalid!"
-                               [ "$DEBUG" ] && echo 
"configvote[$oldy]=${configvote[$oldy]}"
-                               [ "$DEBUG" ] && echo "$config_data"
-                               if [ ${configvote[$oldy]} -eq 0 ]; then
-                                       # the old coordinates point to the error
-                                       filename=$(reconstruct_file $CONFIG 
$oldx $oldy)
-                                       [ "$DEBUG" ] && echo "file $filename 
deleted!"
-                                       rm -f $(reconstruct_file $CONFIG $oldx 
$oldy)
-                                       return 1
-                               fi
+               # jforbes: pending-fedora can be dropped.  It should be empty
+               # most of the time.
+               [ "$order" == "pending-fedora" ] && continue
 
-                       elif [ "$new" != "x" ]; then
-                               old=$new
-                               oldx=$x
-                               oldy=$y
-                       fi
-                       y=$((y + 1))
+               echo "$cfgvariants" | while read -r configvariant
+               do
+                       arch=$(echo "$configvariant" | cut -d "|" -f 1)
+                       _configorder=$(echo "$configvariant" | cut -d "|" -f 2 
| tr : " " )
+                       configorder=$(for c in $_configorder
+                       do
+                               echo -n "${order}-${c} "
+                       done; echo "")
+
+                       echo "${order}-$arch | $configorder"
                done
-               x=$((x + 1))
        done
-
-       return 0
 }
 
-#
-# balance_check: Are the requested config files optimally set?
-#
-# On any row, if a higher level has a majority of set options that are the
-# opposite (for example, y vs n, or m vs n) of a lower level, and is only
-# separated by 0 or more rows of unset configs, then the lower level's value
-# should be set to the majority value of the higher level. (balance)
-#
-balance_check() # $1 is CONFIG, $2 is generic or debug arch string,
-               # $3 is the y-axis (ie, generic arch(2) or debug arch(0))
-{
-       local CONFIG=$1
-       local _arch=$2
-       local _yaxis=$3
+# pretty output
+output_pretty_cfgs() { # uses cfgs and configmap, rows, and columns
+       local x
+       local index
+       local _configmap
 
-       # if this is a character setting then return
-       echo $_arch | grep c >& /dev/null
-       [ $? -eq 0 ] && return
+       index=0
+       for x in $(seq 1 $rows)
+       do
+               [ "$x" == 1 ] && echo "legend" "$1"
+               _configmap=$(echo "$configmap" | sed "${x}q;d" | cut -d "|" -f 
1)
+                       echo "$_configmap ${cfgs[@]:$index:$columns}"
+               index=$((index + columns))
+       done | column -t
+}
 
-       [ $_yaxis -eq 0 ] && _path="debug" || _path="generic"
+# helper function to remove a CONFIG file
+delete_file() {
+       local position
+       local configentry
+
+       position=$1
+       configentry=$2
+       # if the entry doesn't exist, decrease weight by 1
+       weight[$position]=$((weight[$position] - 1))
+       if [ "${weight[$position]}" -le 0 ]; then
+               if [ -e "$configentry" ]; then
+                       $DEBUG && echo "| Deleting $configentry 
${weight[$position]})" || echo "| Deleting $configentry"
+                       rm -f "$configentry"
+               fi
+       else
+               $DEBUG && echo "| Not deleted.  Required by other config 
variants (${weight[$position]})"
+       fi
+}
 
-       # are there 3 of the same character in the string?
-       for mnxy in 'm' 'n' 'y' 'x'
+# find duplicate entries
+fix_broken_arches() { # uses ORDER, crows, columns, and configmap
+       local row
+       local x
+       local y
+       local value
+       local _value
+       local char
+       local position
+       local curr
+
+       # See comment about weight in create_output_header()
+       weight=("${weightorig[@]}")
+
+       # This search is handled differently than
+       # output_pretty_cfgs().  A string is created that
+       # is only for the specific cfg-variant (row * numorder
+       # long).  This string is easier to evaluate.
+       for row in $(seq 0 $((crows - 1)))
        do
-               res="${_arch//[^${mnxy}]}"
-               [ ${#res} -ge 3 ] && break
-       done
-       [ "$mnxy" == 'x' ] && return
-
-       # in theory the CHECKOVERRIDES case has taken care of the
-       # possiblity of $mnxy being the same $level.  Better to
-       # be safe than sorry.
-       level=$(read_file $DIR/$_path/$CONFIG)
-       if [ "$mnxy" != "$level" ]; then
-               [ "$DEBUG" ] && echo "balancing $CONFIG"
-               [ "$DEBUG" ] && echo "$CONFIG (mnxy=$mnxy)"
-               [ "$DEBUG" ] && echo "OLD:"
-               [ "$DEBUG" ] && get_config_files $CONFIG
-               # demote level to x-arch
-               if [ $_yaxis -eq 2 ] && [ "$level" != "x" ]; then
-                       level_cap=$(echo $level | tr '[:lower:]' '[:upper:]')
+               # construct the string of values to view
+               value=$(for order in $(seq 0 $((numorder - 1)))
+               do
+                       index=$(((order * (crows * columns)) + (row * columns)))
+                       echo -n "${cfgs[@]:$index:$columns} "
+               done
+               echo "")
+               $DEBUG && echo "row=$row $value"
+
+               # check to see if there is a config setting conflict
+               _value=$(echo "$value" | tr -d " X-")
+               if echo "$_value" | grep -q "yy\|mm\|nn"; then
+                       # go through the value string, ex) y-y-Xm-,
+                       # and find the characters that match the
+                       # previous character.
+                       curr="p"
+                       position=0
+                       # use value here as each character is
+                       # separated by a space
+                       for char in $value
+                       do
+                               index=$(( ((crows * columns) * (position / 
columns)) + (row * columns) + (position % columns) ))
+                               # sed is 1-based so add 1 to x and y
+                               y=$(((index / columns) + 1))
+                               # configmap contains the cfgvariant and a
+                               # pipe (+3), and needs to be 1-based
+                               x=$(((index % columns) + 4))
+                               $DEBUG && echo "($x,$y) $index"
+
+                               configentry="$(echo "$configmap" | sed 
"${y}q;d" | cut -d " " -f "$x" | tr "-" "/")/$CONFIG"
+                               cfgvariant=$(echo "$configmap" | sed "${y}q;d" 
| cut -d " " -f 1)
+
+                               # if this, char, is the same as curr then
+                               # there is a conflict and char needs to
+                               # be changed.
+                               if [ "$char" == "$curr" ]; then
+                                       echo ""
+                                       echo "ERROR: (heirarchy) $configentry : 
superseding value has $curr."
+                                       echo "|$CONFIG ($cfgvariant)"
+                                       printf "|$longheader\n|$value" | column 
-t
+                                       $DEBUG && echo "position=$position | 
$(echo "$value" | cut -d " " -f $((position + 1)) ) | 
weight=${weight[$position]}"
+
+                                       # See comment about weight in
+                                       # create_output_header()
+                                       delete_file "$position" "$configentry"
+                                       break
+                               fi
+                               case "$char" in
+                               '-')
+                                       ;;
+                               'X')
+                                       # See comment about weight in
+                                       # create_output_header()
+                                       delete_file "$position" "$configentry"
+                                       ;;
+                               * )
+                                       curr=$char
+                                       ;;
+                               esac
+                               position=$((position + 1))
+                       done
                else
-                       level_cap="N"
+                       # still have to examine this string because it may
+                       # contain "X", which has to be accounted for in
+                       # the weights.
+                       echo "$value" | grep -q "X" || continue
+                       position=0
+                       for char in $value
+                       do
+                               if [ "$char" == 'X' ]; then
+                                       index=$(( ((crows * columns) * 
(position / columns)) + (row * columns) + (position % columns) ))
+                                       # sed is 1-based so add 1 to x and y
+                                       y=$(((index / columns) + 1))
+                                       # configmap contains the cfgvariant and
+                                       # a pipe (+3), and needs to be 1-based
+                                       x=$(((index % columns) + 4))
+                                       $DEBUG && echo "($x,$y) $index"
+
+                                       configentry="$(echo "$configmap" | sed 
"${y}q;d" | cut -d " " -f "$x" | tr "-" "/")/$CONFIG"
+                                       cfgvariant=$(echo "$configmap" | sed 
"${y}q;d" | cut -d " " -f 1)
+                                       # See comment about weight in
+                                       # create_output_header()
+                                       delete_file "$position" "$configentry"
+                               fi
+                               position=$((position + 1))
+                       done
                fi
-               _arch=$(echo $_arch | sed "s/x/$level_cap/g")
 
-               # promote and replace
+       done
+}
 
-               # set new level
-               level=$mnxy
-               _arch=$(echo $_arch | tr "$level" 'x' | tr  '[:upper:]' 
'[:lower:]')
-               for x in 0 1 2 3
+# compare the common, fedora, and ark configs.
+# By default this function uses the priority.common file
+fix_common() { # uses cfgs, CONFIG, and ORDER
+       local index
+       local value
+       local _value
+       local x
+       local y
+       local configentry
+       local _configentry
+       local order
+
+       # the priority.common array is
+       #       common configs
+       #       ark configs
+       #       fedora configs
+       for index in $(seq 0 $(((crows * columns) - 1)))
+       do
+               # this string is the concatenation of the
+               # common, ark, and fedora config values
+               value=$(for order in $(seq 0 $((numorder -1)))
                do
-                       filename=$(reconstruct_file $CONFIG $x $_yaxis)
-                       _arch_val="${_arch:$x:1}"
-                       create_file $CONFIG $filename $_arch_val
+                       echo -n "${cfgs[$(( (order * crows * columns) + 
index))]}"
                done
-               filename=$(reconstruct_file $CONFIG $x $((_yaxis + 1)))
-               create_file $CONFIG $filename $level
-               # run CHECKOVERRIDES
-               check_overrides $CONFIG
-               [ "$DEBUG" ] && echo "NEW:"
-               [ "$DEBUG" ] && get_config_files $CONFIG
-       else
-               echo "$CONFIG needs to run CHECKOVERRIDES"
-               echo "  ./evaluate_configs -c $CONFIG"
+               echo "")
+
+               # It doesn't matter what common is set to so
+               # trim it off.
+               _value="${value:1}"
+               if echo "$_value" | grep -q "yy\|mm\|nn"; then
+
+                       # set _value to just y|m|n
+                       _value="${_value:1}"
+
+                       # create a long array to see if the change is valid
+                       checkvalue=$(for order in $(seq 0 $((numorder -1)))
+                       do
+                               step=$(( order * crows * columns))
+                               # this seems weird but it rounds off to columns
+                               row=$(( (step + index) / columns * columns))
+                               echo -n "${cfgs[@]:$row:$columns} "
+                       done; echo "")
+
+                       $DEBUG && echo "checkvalue=$checkvalue"
+
+                       IFS=', ' read -r -a checkvalue <<< "$checkvalue"
+                       _index=$((index % columns))
+
+                       for order in $(seq 1 $((numorder -1)))
+                       do
+                               checkvalue[$((( order * columns ) + 
_index))]='-'
+                       done
+                       $DEBUG && echo "updated checkvalue=${checkvalue[@]}"
+
+                       # set the common entry to _value, so that an analysis
+                       # can be run on the other entries
+                       checkvalue[$_index]="$_value"
+
+                       count=0
+                       cfgvalue=${checkvalue[0]}
+                       warning=false
+                       for i in ${checkvalue[@]}
+                       do
+                               echo "$i" | grep -q 'm\|n\|y' && cfgvalue=$i
+                               if [ $count == $_index ]; then
+                                       if [ "$cfgvalue" != "$_value" ]; then
+                                               $DEBUG && echo "$CONFIG 
override will not work."
+                                               warning=true
+                                               break;
+                                       fi
+                                       _index=$((_index + columns))
+                               fi
+                               count=$((count + 1))
+                       done
+
+                       $warning && break
+
+                       echo "$CONFIG found a match where common should be set."
+
+                       # sed is 1-based so add 1 to x and y
+                       y=$(((index / columns) + 1))
+                       # configmap contains the cfgvariant and a
+                       # pipe (+3), and needs to be 1-based
+                       x=$(((index % columns) + 4))
+                       $DEBUG && echo "($x,$y) $index"
+
+                       # remove the existing ark and fedora configs
+                       configentry="$(echo "$configmap" | sed "${y}q;d" | cut 
-d " " -f "$x" | tr "-" "/")/$CONFIG"
+                       for order in $ORDER
+                       do
+                               [ "$order" == "common" ] && continue
+                               _configentry=${configentry//common/$order}
+                               [ -e "$_configentry" ] && rm -f "$_configentry"
+                       done
+
+                       # create a new common config
+                       echo "$_value" in "$configentry"
+                       case "$_value" in
+                       m)
+                               echo "${CONFIG}=m" > "$configentry"
+                               ;;
+                       y)
+                               echo "${CONFIG}=y" > "$configentry"
+                               ;;
+                       n)
+                               echo "# $CONFIG is not set" > "$configentry"
+                               ;;
+                       esac
+               fi
+       done
+}
+
+# Check that ccolumns is consistent
+debug_cfgvariants() { # uses $cfgvariants and sets crows and ccolumns
+       local LINE
+
+       crows=$(echo "$cfgvariants" | wc -l)
+
+       ccolumns=$(echo "$cfgvariants" | while read -r LINE
+       do
+               LINE=$(echo "$LINE" | cut -d "|" -f 2)
+               echo "$LINE" | wc -w
+       done | sort -u)
+
+       # Error check columns
+       if [ "$(echo "$ccolumns" | wc -l)" != "1" ]; then
+               echo "ERROR in parser.  There were multiple length columns 
found."
+               echo "$ccolumns"
                exit 1
        fi
 }
 
-# where am i?
-if [ ! -d "generic" ] || [ ! -d "debug" ]; then
-       echo "This script must be run in the redhat/configs directory."
-       exit 1
-fi
+# Create an output header, a fancy long header for fix_broken_arches, and the
+# weights
+create_output_header() { # uses $ORDER, $configmap, and sets output_header
+                        # and weightorig
+
+       local order
+       local dir
+       local convert
+       local f
+       local configline
+
+       # We know that the configmap now contains correct sized entries for
+       # each arch.  The arch doesn't really matter and we just need the
+       # information to make a header.
+       order=$(echo "$ORDER" | cut -d " " -f 1)
+       configline=$(echo "$configmap" | head -1 | cut -d "|" -f 2 | sed 
"s/${order}-//g")
+       for dir in $configline
+       do
+               convert=false
+               if echo "$dir" | grep -q "-"; then
+                       if echo "$dir" | grep -q "EMPTY0"; then
+                               dir=$(echo "$dir" | awk -F "-EMPTY0" ' { print 
$1 } ')
+                               convert=true
+                       fi
+               else
+                       convert=true
+               fi
 
-CHECKOVERRIDES=""
-SYNTAXCHECK=""
-DEBUG=""
-BALANCECHECK=""
-FINDDEAD=""
+               ! $convert && continue
 
-while [[ $# -gt 0 ]]
-do
-       key="$1"
-       case $key in
-       -b) BALANCECHECK="x";;
-       -c) CHECKOVERRIDES="x";;
-       -d) DEBUG="x";;
-       -s) SYNTAXCHECK="x";;
-       -f) FINDDEAD="x";;
-       -h) usage;;
-       *) break;;
-       esac
-       shift
-done
+               # get the first letter of each word
+               f=$(echo "$dir" | head -c 1)
+               $DEBUG && echo "directory $dir entries will be converted to $f"
+               configline=${configline//$dir/$f}
+       done
 
-if [ "$CHECKOVERRIDES" ] && [ "$1" ]; then
-       ret=1
-       while [ $ret -eq 1 ]
+       # Go through the configline and convert the directory names into header
+       # names For example,
+       #    generic generic-x86 generic-x86-x86_64 generic-EMPTY3 debug-EMPTY0 
debug-EMPTY1 debug-EMPTY2
+       # will be converted to
+       #    g ga1 ga2 ga3 d da1 da2
+       output_header=$(for dir in $configline
        do
-               check_overrides $1
-               ret=$?
+               # convert dirs with no dashes to the same thing
+               if ! echo "$dir" | grep -q "-"; then
+                       echo "$dir"
+                       continue
+               fi
+               f=$(echo "$dir" | cut -d "-" -f 1)
+               # convert g-x86 to ga, and g-x86-x86_64 to ga2, etc.
+               if echo "$dir" | grep -q "EMPTY"; then
+                       numempty=$(echo "$dir" | awk -F "EMPTY" ' { print $2 } 
')
+                       if [ "$numempty" -eq 0 ]; then
+                               echo "$f"
+                       else
+                               echo "${f}a${numempty}"
+                       fi
+               else
+                       numdashes=$(echo "$dir"| grep -o "-" | wc -l)
+                       echo "${f}a${numdashes}"
+               fi
+       done | tr "\n" " ")
+
+       # create a weightorig array that contains the weights of change for
+       # each directory.  This is useful for the -x option display
+       for entry in $output_header
+       do
+               if echo "$entry" | grep -q 'a'; then
+                       _weightorig+=(1)
+               else
+                       _weightorig+=("$crows")
+               fi
        done
-       exit 1
-fi
 
-if [ "$CHECKOVERRIDES" ]; then
-       rm -f $DIR/.strlist
-       # only look for CONFIGs that are defined in multiple locations
-       find $DIR -name CONFIG* -exec basename {} \; | sort | uniq -c | grep -v 
' 1 '|sed 's/.*CONFIG/CONFIG/' > .configlist
-       while [ $(cat .configlist | wc -l) -ne 0 ]
+       # It is possible (and valid) to have an subdir arch followed by
+       # a debug entry.  The -x checker would have flagged this and
+       # removed the file.  As a solution there is a weight associated
+       # with each entry's CONFIG file.  A debug or generic entry has
+       # a weight equal the number of columns, and the arch entries all
+       # have a weight of one.  The -x tracker subtracts one for each "hit"
+       # and only removes the file if the weight is 1.
+
+       weightorig=""
+       longheader=""
+       for order in $(seq 1 $numorder)
+       do
+               weightorig="${weightorig[@]} ${_weightorig[@]}"
+               longheader="${longheader}${output_header}"
+       done
+       IFS=', ' read -r -a weightorig <<< "$weightorig"
+}
+
+# initialize the array to '-' (undefined) and 'X' (not present/EMPTY)
+init_cfgs() { #uses cfgs, rows, and columns
+       unset cfgs
+       eval "$(eval echo "cfgs[{1..$((rows * columns))}]='-'\;")"
+       # the -'s can be a problem when being parsed by other commands.  I
+       # tried using +, o, ., X, etc. but none of the output was as clear as
+       # a dash.  Initialize the 0th element to an unused letter.  If still
+       # 'p' it can be changed back later on.
+       cfgs[0]=p
+
+       # set EMPTY configs to X
+       for row in $(seq 0 $((rows - 1)))
        do
-               [ "$DEBUG" ] && cat .configlist | wc -l
-               CONFIG=$(head -1 .configlist)
-               ret=1
-               while [ $ret -eq 1 ]
+               index=$((row * columns))
+               num=0
+               for entry in $(echo "$cfgvariants" | sed "$(((row % crows) + 
1))q;d" | cut -d "|" -f 2)
                do
-                       check_overrides $CONFIG
-                       ret=$?
+                       echo "$entry" | grep -q EMPTY && cfgs[$((index + 
num))]='X'
+                       num=$((num + 1))
                done
-               # this has to be "exact" pattern
-               sed -i "/\<$CONFIG\>/d" .configlist
        done
-fi
+       cfgs_base=("${cfgs[@]}")
+}
 
-if [ "$SYNTAXCHECK" ] && [ "$1" ]; then
+# reset the configs to default
+reset_cfgs() {
+       unset cfgs
+       cfgs=("${cfgs_base[@]}")
+}
 
-       CONFIG=$1
+# map the CONFIG files to the array
+map_configs_to_array() { #uses CONFIG, configmap, cfgs
 
-       echo "Issues found by the syntax check are not auto-corrected.  You 
must make"
-       echo "manual changes and execute the syntax check again."
-       syntax_check $CONFIG
-       exit $?
-fi
+       local LINE
+       local contents
+       local _LINE
+       local row
+       local cols
+       local col
 
-if [ "$SYNTAXCHECK" ]; then
-       echo "Issues found by the syntax check are not auto-corrected.  You 
must make"
-       echo "manual changes and execute the syntax check again."
-       find $DIR -name CONFIG_* | while read CONFIG
+       for LINE in $(find ./ -name $CONFIG -printf '%P\n' | awk -F "/$CONFIG" 
' { print $1 } ')
+       # loop through the CONFIG files
        do
-               syntax_check $CONFIG
+               $DEBUG && echo "+-------------------"
+               $DEBUG && echo "found: $LINE"
+
+               contents=$(grep "^# $CONFIG is not set\|^$CONFIG=" 
"$LINE"/"$CONFIG")
+               case $contents in
+               "# $CONFIG is not set")
+                       contents=n
+                       ;;
+               "${CONFIG}=y")
+                       contents=y
+                       ;;
+               "${CONFIG}=m")
+                       contents=m
+                       ;;
+               *)
+                       echo "$LINE/$CONFIG has a strange entry ... skipping"
+                       return 1
+                       break;;
+               esac
+
+               $DEBUG && echo "contents=$contents"
+
+               _LINE=$(echo "$LINE" | tr "/" "-")
+               $DEBUG && echo "_LINE=$_LINE"
+               # set each cfg to $contents
+               OLDIFS=$IFS; IFS=$'\n'; for rowandcol in $(echo "$configmap" | 
grep -n " $_LINE ")
+               do
+                       row=$(echo "$rowandcol" | cut -d ":" -f 1)
+                       # grep is 1 based and we need a 0 based number
+                       row=$((row - 1))
+                       cols=$(echo "$rowandcol" | cut -d "|" -f 2)
+                       $DEBUG && echo "row=$row"
+                       $DEBUG && echo "cols=$cols"
+
+                       col=$(echo "$cols" | awk -F "$_LINE" ' { print $1 }' | 
wc -w)
+                       $DEBUG && echo "($col, $row) = $contents"
+                       # convert the (col,row) to an index in the array
+                       $DEBUG && echo "setting element $(($((row * columns)) + 
col)) = $contents"
+                       # set the config
+                       cfgs[$(($((row * columns)) + col))]=$contents
+               done
+               IFS=$OLDIFS
        done
-fi
 
-if [ "$BALANCECHECK" ] && [ "$1" ]; then
+       # undo the 'p' setting of the initial element
+       # (setting to 'p' done in init_cfgs)
+       [ "${cfgs[0]}" == "p" ] && cfgs[0]="-"
 
-       CONFIG=$1
+       return 0
+}
 
-       debug_arch=$(get_arch_files debug $CONFIG)
-       # trim off s390x: It is handled in CHECKOVERRIDES
-       debug_arch=$(echo ${debug_arch::-1})
+#
+#
+# MAIN
+#
+#
 
-       balance_check $CONFIG $debug_arch 0
+# PROCESS ARGUMENTS
+FINDFIXES=false
+FIXCOMMON=false
+configs=
+while getopts "c:dfhjp:" opt; do
+       case ${opt} in
+       c )
+               configs=$OPTARG
+               ;;
+       d )
+               DEBUG=true
+               ;;
+       f )
+               # Find fixes per config-variant
+               FINDFIXES=true
+               ;;
+       h )
+               whatcouldgowrong
+               ;;
+       j )
+               # jforbes mode
+               priority_file=priority.common
+               FIXCOMMON=true
+               ;;
+       p )
+               # Get the high level order from the priority file
+               priority_file=$OPTARG
+               ;;
+       *)
+               whatcouldgowrong
+               ;;
+       esac
+done
 
-       generic_arch=$(get_arch_files generic $CONFIG)
-       # trim off s390x: It is not needed at this level
-       generic_arch=$(echo ${generic_arch::-1})
+$DEBUG && echo "priority_file=$priority_file"
+$DEBUG && echo "configs=$CONFIG"
+$DEBUG && echo "FINDFIXES=$FINDFIXES"
+$DEBUG && echo "FIXCOMMON=$FIXCOMMON"
 
-       balance_check $CONFIG $generic_arch 2
-       exit
+# Do some simple error checking
+if [ -z "$priority_file" ]; then
+       echo "Specify a priority.* file"
+       whatcouldgowrong
 fi
 
-if [ "$BALANCECHECK" ]; then
-       # only look for CONFIGs that are defined in multiple locations
-       find $DIR -name CONFIG* -exec basename {} \; | sort | uniq -c | grep -v 
' 1 '|sed 's/.*CONFIG/CONFIG/' > .configlist
-       while [ $(cat .configlist | wc -l) -ne 0 ]
-       do
-               [ "$DEBUG" ] && cat .configlist | wc -l
-               CONFIG=$(head -1 .configlist)
-
-               debug_arch=$(get_arch_files debug $CONFIG)
-               # trim off s390x: It is handled in CHECKOVERRIDES
-               debug_arch=$(echo ${debug_arch::-1})
-
-               balance_check $CONFIG $debug_arch 0
-
-               generic_arch=$(get_arch_files generic $CONFIG)
-               # trim off s390x: It is not needed at this level
-               generic_arch=$(echo ${generic_arch::-1})
-
-               balance_check $CONFIG $generic_arch 2
+# if configs is not set then do all CONFIGS
+if [ -z "$configs" ]; then
+       find ./ -name "CONFIG*" -type f -printf "%f\n" | sort -u > 
"$tempdir"/CONFIGS
+       configs=$tempdir/CONFIGS
+fi
 
-               # this has to be "exact" pattern
-               sed -i "/\<$CONFIG\>/d" .configlist
+# if configs is still not set, then parse the argument provided
+if [ ! -e "$configs" ]; then
+# assume the user is smart enough to specify CONFIGs
+       for config in ${configs//,/ }
+       do
+               # Allow users to specify configs without CONFIG_
+               if ! echo "$config" | grep -q CONFIG; then
+                       config="CONFIG_${config}"
+               fi
+               echo "$config" >> "$tempdir"/CONFIGS
        done
-       rm -f .configlist
+       configs=$tempdir/CONFIGS
+else
+       # if the file exists just copy it
+       [ ! -e "$tempdir"/CONFIGS ] && cp "$configs" "$tempdir"/CONFIGS
 fi
 
-#
-# Find configs that are requested but do not exist in the final .configs
-#
-if [ "$FINDDEAD" ]; then
-       (cd ..; make dist-configs)
-
-       awk '
-               /is not set/ {
-                       split ($0, a, "#");
-                       split(a[2], b);
-                       print b[1] ;
-               }
-               /=/ {
-                       split ($0, a, "=");
-                       print a[1];
-               }
-       ' *.config | sort -u > .finalconfiglist
-
-       find ./ -name CONFIG_* | sed 's!.*/!!' | sort -u > .configlist
-
-       echo "These CONFIGS defined in redhat/configs but not the final 
.configs have been deleted:"
-       diff -u .finalconfiglist .configlist | grep "^+CONFIG" | sed 's/^+//g' 
| while read FILENAME
+ORDER=$(grep "^ORDER" "$priority_file"| cut -d "=" -f 2)
+
+# STEP 1.  Parse the priority file
+
+cfgvariants=$(get_cfgvariants)
+$DEBUG && echo "----------------------------------------"
+$DEBUG && echo "cfgvariants:"
+$DEBUG && echo "$cfgvariants"
+$DEBUG && echo "----------------------------------------"
+toplevels=$(get_toplevel_dirs "$cfgvariants")
+$DEBUG && echo "Top level directories in priority file: $toplevels"
+subdirs=$(get_subdirs)
+$DEBUG && echo "Top-level sub-directories:"
+$DEBUG && echo "$subdirs"
+
+# Add EMPTY entries for each missing subdirectory level in the config
+# variants
+echo "$cfgvariants" > "$tempdir"/cfgvariants
+fix_config_variants
+$DEBUG && echo ""
+$DEBUG && echo ""
+$DEBUG && echo "Fixed: cfgvariants"
+$DEBUG && cat "$tempdir"/cfgvariants
+
+# Reset cfgvariants to new values with EMPTYs.
+# cfgvariants now contains the config-variant data with EMPTY subdirs.
+cfgvariants=$(cat "$tempdir"/cfgvariants)
+crows=
+ccolumns=
+debug_cfgvariants
+$DEBUG && echo "For the config-variants there are $crows rows and $ccolumns 
columns."
+
+# STEP 2.  Now that we have fixed the list of config variants, create a config
+# map that contains all entries wrt the ORDER specified in the priority file.
+
+numorder=$(echo "$ORDER" | wc -w)
+# jforbes: pending-fedora can be dropped.  It should be empty
+# most of the time.
+echo "$ORDER" | grep -q "pending-fedora" && numorder=$((numorder -1))
+
+# configmap is the list of config-variants used for displaying and analyzing
+# the CONFIGs.
+configmap=$(get_configmap)
+$DEBUG && echo " "
+$DEBUG && echo "The configmap is:"
+$DEBUG && echo "$configmap"
+$DEBUG && echo " "
+
+# STEP 3.  Create an array and header to hold the configmap data.
+
+rows=$(echo "$configmap" | wc -l)
+columns=$(echo "$configmap" | head -1 | cut -d "|" -f 2 | wc -w)
+$DEBUG && echo "There are $rows rows and $columns columns in the configmap."
+
+create_output_header # sets output_header
+$DEBUG && echo "output_header=|$output_header|"
+$DEBUG && echo "longheader=|$longheader|"
+$DEBUG && echo "output_header has weights ${weightorig[@]}"
+
+# create the cfgs array and initialize it to '-' (not found)
+init_cfgs
+
+if $FINDFIXES; then
+       while read -r CONFIG
        do
-               echo $FILENAME
-               find ./ -name $FILENAME | xargs rm -f
-       done
+               reset_cfgs
+               map_configs_to_array || continue
+
+               fix_broken_arches "$output_header"
+       done < "$tempdir"/CONFIGS
+       exit
+fi
 
-       rm -f .configlist .finalconfiglist
+if $FIXCOMMON; then
+       while read -r CONFIG
+       do
+               reset_cfgs
+               map_configs_to_array || continue
+               fix_common
+       done < "$tempdir"/CONFIGS
+       exit
 fi
 
+# only display the configs
+       while read -r CONFIG
+       do
+               reset_cfgs
+               map_configs_to_array || continue
+               echo ""
+               echo "$CONFIG"
+               output_pretty_cfgs "$output_header"
+       done < "$tempdir"/CONFIGS
 exit
diff --git a/redhat/configs/priority.common b/redhat/configs/priority.common
new file mode 100644
index 000000000000..d4b907182446
--- /dev/null
+++ b/redhat/configs/priority.common
@@ -0,0 +1,28 @@
+ORDER=common ark fedora
+
+# x86_64
+x86_64=generic:generic-x86:generic-x86-x86_64
+x86_64-debug=generic:generic-x86:generic-x86-x86_64:debug:debug-x86-x86_64
+
+# i686
+i686=generic:generic-x86:generic-x86-i686
+i686-debug=generic:generic-x86:generic-x86-i686:debug:debug-x86
+
+# ppc64le
+ppc64le=generic:generic-powerpc
+ppc64le-debug=generic:generic-powerpc:debug:debug-powerpc
+
+# s390x
+s390x=generic:generic-s390x
+s390x-debug=generic:generic-s390x:debug:debug-s390x
+s390x-zfcpdump=generic:generic-s390x:generic-s390x-zfcpdump
+
+# aarch64
+aarch64=generic:generic-arm:generic-arm-aarch64
+aarch64-debug=generic:generic-arm:generic-arm-aarch64:debug:debug-arm-aarch64
+
+# arm
+armv7hl=generic:generic-arm:generic-arm-armv7:generic-arm-armv7-armv7
+armv7hl-debug=generic:generic-arm:generic-arm-armv7:generic-arm-armv7-armv7:debug:debug-arm
+armv7hl-lpae=generic:generic-arm:generic-arm-armv7:generic-arm-armv7-lpae
+armv7hl-lpae-debug=generic:generic-arm:generic-arm-armv7:generic-arm-armv7-lpae:debug:debug-arm
diff --git a/redhat/configs/priority.fedora b/redhat/configs/priority.fedora
index 362d7ff6c332..73fa2bad2d1f 100644
--- a/redhat/configs/priority.fedora
+++ b/redhat/configs/priority.fedora
@@ -1,4 +1,18 @@
-# config-variant=config:config:config
+# Entries must be ordered as base and debug (if the debug variant exists)
+# ie) config-variant-arch
+#     config-variant-arch-debug (if the -debug variant exists)
+
+# Individual entries must be ordered as
+# config-variant=config-1:config-2:config-3 in a descending order through
+# the hierarchy
+
+# -debug variants must include the entirety of the base variant
+# For example,
+#
+# config-foo: generic:generic-foo:generic-foo-bar
+# config-foo-debug: generic:generic-foo:debug:debug-foo
+# is not a valid -debug variant
+
 # kernel.config files are build on the fly based on this config,
 # the first arg is arch and variant, the second is a hierarchy of
 # config options, lowest priority to highest
diff --git a/redhat/configs/priority.rhel b/redhat/configs/priority.rhel
index 0800c8cb9381..73ae53a8122e 100644
--- a/redhat/configs/priority.rhel
+++ b/redhat/configs/priority.rhel
@@ -1,4 +1,18 @@
-# config-variant=config:config:config
+# Entries must be ordered as base and debug (if the debug variant exists)
+# ie) config-variant-arch
+#     config-variant-arch-debug (if the -debug variant exists)
+
+# Individual entries must be ordered as
+# config-variant=config-1:config-2:config-3 in a descending order through
+# the hierarchy
+
+# -debug variants must include the entirety of the base variant
+# For example,
+#
+# config-foo: generic:generic-foo:generic-foo-bar
+# config-foo-debug: generic:generic-foo:debug:debug-foo
+# is not a valid -debug variant
+
 # kernel.config files are build on the fly based on this config,
 # the first arg is arch and variant, the second is a hierarchy of
 # config options, lowest priority to highest
-- 
GitLab
_______________________________________________
kernel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedoraproject.org/archives/list/[email protected]

Reply via email to