0001 #!/usr/bin/env bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 # Manipulate options in a .config file from the command line
0004
0005 myname=${0##*/}
0006
0007 # If no prefix forced, use the default CONFIG_
0008 CONFIG_="${CONFIG_-CONFIG_}"
0009
0010 # We use an uncommon delimiter for sed substitutions
0011 SED_DELIM=$(echo -en "\001")
0012
0013 usage() {
0014 cat >&2 <<EOL
0015 Manipulate options in a .config file from the command line.
0016 Usage:
0017 $myname options command ...
0018 commands:
0019 --enable|-e option Enable option
0020 --disable|-d option Disable option
0021 --module|-m option Turn option into a module
0022 --set-str option string
0023 Set option to "string"
0024 --set-val option value
0025 Set option to value
0026 --undefine|-u option Undefine option
0027 --state|-s option Print state of option (n,y,m,undef)
0028
0029 --enable-after|-E beforeopt option
0030 Enable option directly after other option
0031 --disable-after|-D beforeopt option
0032 Disable option directly after other option
0033 --module-after|-M beforeopt option
0034 Turn option into module directly after other option
0035
0036 commands can be repeated multiple times
0037
0038 options:
0039 --file config-file .config file to change (default .config)
0040 --keep-case|-k Keep next symbols' case (dont' upper-case it)
0041
0042 $myname doesn't check the validity of the .config file. This is done at next
0043 make time.
0044
0045 By default, $myname will upper-case the given symbol. Use --keep-case to keep
0046 the case of all following symbols unchanged.
0047
0048 $myname uses 'CONFIG_' as the default symbol prefix. Set the environment
0049 variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ...
0050 EOL
0051 exit 1
0052 }
0053
0054 checkarg() {
0055 ARG="$1"
0056 if [ "$ARG" = "" ] ; then
0057 usage
0058 fi
0059 case "$ARG" in
0060 ${CONFIG_}*)
0061 ARG="${ARG/${CONFIG_}/}"
0062 ;;
0063 esac
0064 if [ "$MUNGE_CASE" = "yes" ] ; then
0065 ARG="`echo $ARG | tr a-z A-Z`"
0066 fi
0067 }
0068
0069 txt_append() {
0070 local anchor="$1"
0071 local insert="$2"
0072 local infile="$3"
0073 local tmpfile="$infile.swp"
0074
0075 # sed append cmd: 'a\' + newline + text + newline
0076 cmd="$(printf "a\\%b$insert" "\n")"
0077
0078 sed -e "/$anchor/$cmd" "$infile" >"$tmpfile"
0079 # replace original file with the edited one
0080 mv "$tmpfile" "$infile"
0081 }
0082
0083 txt_subst() {
0084 local before="$1"
0085 local after="$2"
0086 local infile="$3"
0087 local tmpfile="$infile.swp"
0088
0089 sed -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile" >"$tmpfile"
0090 # replace original file with the edited one
0091 mv "$tmpfile" "$infile"
0092 }
0093
0094 txt_delete() {
0095 local text="$1"
0096 local infile="$2"
0097 local tmpfile="$infile.swp"
0098
0099 sed -e "/$text/d" "$infile" >"$tmpfile"
0100 # replace original file with the edited one
0101 mv "$tmpfile" "$infile"
0102 }
0103
0104 set_var() {
0105 local name=$1 new=$2 before=$3
0106
0107 name_re="^($name=|# $name is not set)"
0108 before_re="^($before=|# $before is not set)"
0109 if test -n "$before" && grep -Eq "$before_re" "$FN"; then
0110 txt_append "^$before=" "$new" "$FN"
0111 txt_append "^# $before is not set" "$new" "$FN"
0112 elif grep -Eq "$name_re" "$FN"; then
0113 txt_subst "^$name=.*" "$new" "$FN"
0114 txt_subst "^# $name is not set" "$new" "$FN"
0115 else
0116 echo "$new" >>"$FN"
0117 fi
0118 }
0119
0120 undef_var() {
0121 local name=$1
0122
0123 txt_delete "^$name=" "$FN"
0124 txt_delete "^# $name is not set" "$FN"
0125 }
0126
0127 if [ "$1" = "--file" ]; then
0128 FN="$2"
0129 if [ "$FN" = "" ] ; then
0130 usage
0131 fi
0132 shift 2
0133 else
0134 FN=.config
0135 fi
0136
0137 if [ "$1" = "" ] ; then
0138 usage
0139 fi
0140
0141 MUNGE_CASE=yes
0142 while [ "$1" != "" ] ; do
0143 CMD="$1"
0144 shift
0145 case "$CMD" in
0146 --keep-case|-k)
0147 MUNGE_CASE=no
0148 continue
0149 ;;
0150 --refresh)
0151 ;;
0152 --*-after|-E|-D|-M)
0153 checkarg "$1"
0154 A=$ARG
0155 checkarg "$2"
0156 B=$ARG
0157 shift 2
0158 ;;
0159 -*)
0160 checkarg "$1"
0161 shift
0162 ;;
0163 esac
0164 case "$CMD" in
0165 --enable|-e)
0166 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=y"
0167 ;;
0168
0169 --disable|-d)
0170 set_var "${CONFIG_}$ARG" "# ${CONFIG_}$ARG is not set"
0171 ;;
0172
0173 --module|-m)
0174 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=m"
0175 ;;
0176
0177 --set-str)
0178 # sed swallows one level of escaping, so we need double-escaping
0179 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=\"${1//\"/\\\\\"}\""
0180 shift
0181 ;;
0182
0183 --set-val)
0184 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=$1"
0185 shift
0186 ;;
0187 --undefine|-u)
0188 undef_var "${CONFIG_}$ARG"
0189 ;;
0190
0191 --state|-s)
0192 if grep -q "# ${CONFIG_}$ARG is not set" $FN ; then
0193 echo n
0194 else
0195 V="$(grep "^${CONFIG_}$ARG=" $FN)"
0196 if [ $? != 0 ] ; then
0197 echo undef
0198 else
0199 V="${V/#${CONFIG_}$ARG=/}"
0200 V="${V/#\"/}"
0201 V="${V/%\"/}"
0202 V="${V//\\\"/\"}"
0203 echo "${V}"
0204 fi
0205 fi
0206 ;;
0207
0208 --enable-after|-E)
0209 set_var "${CONFIG_}$B" "${CONFIG_}$B=y" "${CONFIG_}$A"
0210 ;;
0211
0212 --disable-after|-D)
0213 set_var "${CONFIG_}$B" "# ${CONFIG_}$B is not set" "${CONFIG_}$A"
0214 ;;
0215
0216 --module-after|-M)
0217 set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A"
0218 ;;
0219
0220 # undocumented because it ignores --file (fixme)
0221 --refresh)
0222 yes "" | make oldconfig
0223 ;;
0224
0225 *)
0226 echo "bad command: $CMD" >&2
0227 usage
0228 ;;
0229 esac
0230 done