projects/linux·blob master · refs

240 lines · 4.8 KiB

1#!/usr/bin/env bash
2# SPDX-License-Identifier: GPL-2.0
3# Manipulate options in a .config file from the command line
4
5myname=${0##*/}
6
7# If no prefix forced, use the default CONFIG_
8CONFIG_="${CONFIG_-CONFIG_}"
9
10# We use an uncommon delimiter for sed substitutions
11SED_DELIM=$(echo -en "\001")
12
13usage() {
14 cat >&2 <<EOL
15Manipulate options in a .config file from the command line.
16Usage:
17$myname options command ...
18commands:
19 --enable|-e option Enable option
20 --disable|-d option Disable option
21 --module|-m option Turn option into a module
22 --set-str option string
23 Set option to "string"
24 --set-val option value
25 Set option to value
26 --undefine|-u option Undefine option
27 --state|-s option Print state of option (n,y,m,undef)
28
29 --enable-after|-E beforeopt option
30 Enable option directly after other option
31 --disable-after|-D beforeopt option
32 Disable option directly after other option
33 --module-after|-M beforeopt option
34 Turn option into module directly after other option
35 --refresh Refresh the config using old settings
36
37 commands can be repeated multiple times
38
39options:
40 --file config-file .config file to change (default .config)
41 --keep-case|-k Keep next symbols' case (don't upper-case it)
42
43$myname doesn't check the validity of the .config file. This is done at next
44make time.
45
46By default, $myname will upper-case the given symbol. Use --keep-case to keep
47the case of all following symbols unchanged.
48
49$myname uses 'CONFIG_' as the default symbol prefix. Set the environment
50variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ...
51EOL
52 exit 1
53}
54
55checkarg() {
56 ARG="$1"
57 if [ "$ARG" = "" ] ; then
58 usage
59 fi
60 case "$ARG" in
61 ${CONFIG_}*)
62 ARG="${ARG/${CONFIG_}/}"
63 ;;
64 esac
65 if [ "$MUNGE_CASE" = "yes" ] ; then
66 ARG="`echo $ARG | tr a-z A-Z`"
67 fi
68}
69
70txt_append() {
71 local anchor="$1"
72 local insert="$2"
73 local infile="$3"
74
75 # sed append cmd: 'a\' + newline + text + newline
76 cmd="$(printf "a\\%b$insert" "\n")"
77
78 # We don't really need a backup file, but in-place editing with backup
79 # skipped is not portable due to different implementations parsing
80 # arguments in incompatible manners.
81 # Create a backup file anyway to ensure portability. The file will be
82 # deleted on exit.
83 sed -E -i.swp -e "/$anchor/$cmd" "$infile"
84 SED_EDITED=1
85}
86
87txt_subst() {
88 local before="$1"
89 local after="$2"
90 local infile="$3"
91
92 sed -E -i.swp -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile"
93 SED_EDITED=1
94}
95
96txt_delete() {
97 local text="$1"
98 local infile="$2"
99
100 sed -E -i.swp -e "/$text/d" "$infile"
101 SED_EDITED=1
102}
103
104set_var() {
105 local name=$1 new=$2 before=$3
106
107 name_re="^($name=.*|# $name is not set)"
108 before_re="^($before=|# $before is not set)"
109 if test -n "$before" && grep -Eq "$before_re" "$FN"; then
110 txt_append "$before_re" "$new" "$FN"
111 elif grep -Eq "$name_re" "$FN"; then
112 txt_subst "$name_re" "$new" "$FN"
113 else
114 echo "$new" >>"$FN"
115 fi
116}
117
118undef_var() {
119 local name=$1
120
121 txt_delete "^($name=|# $name is not set)" "$FN"
122}
123
124SED_EDITED=0
125on_exit() {
126 if [ "$SED_EDITED" -ge 1 ]; then
127 rm -f "$FN.swp"
128 fi
129}
130trap on_exit EXIT
131
132FN=.config
133CMDS=()
134while [[ $# -gt 0 ]]; do
135 if [ "$1" = "--file" ]; then
136 if [ "$2" = "" ]; then
137 usage
138 fi
139 FN="$2"
140 shift 2
141 else
142 CMDS+=("$1")
143 shift
144 fi
145done
146
147set -- "${CMDS[@]}"
148if [ "$1" = "" ] ; then
149 usage
150fi
151
152MUNGE_CASE=yes
153while [ "$1" != "" ] ; do
154 CMD="$1"
155 shift
156 case "$CMD" in
157 --keep-case|-k)
158 MUNGE_CASE=no
159 continue
160 ;;
161 --refresh)
162 ;;
163 --*-after|-E|-D|-M)
164 checkarg "$1"
165 A=$ARG
166 checkarg "$2"
167 B=$ARG
168 shift 2
169 ;;
170 -*)
171 checkarg "$1"
172 shift
173 ;;
174 esac
175 case "$CMD" in
176 --enable|-e)
177 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=y"
178 ;;
179
180 --disable|-d)
181 set_var "${CONFIG_}$ARG" "# ${CONFIG_}$ARG is not set"
182 ;;
183
184 --module|-m)
185 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=m"
186 ;;
187
188 --set-str)
189 # sed swallows one level of escaping, so we need double-escaping
190 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=\"${1//\"/\\\\\"}\""
191 shift
192 ;;
193
194 --set-val)
195 set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=$1"
196 shift
197 ;;
198 --undefine|-u)
199 undef_var "${CONFIG_}$ARG"
200 ;;
201
202 --state|-s)
203 if grep -q "# ${CONFIG_}$ARG is not set" $FN ; then
204 echo n
205 else
206 V="$(grep "^${CONFIG_}$ARG=" $FN)"
207 if [ $? != 0 ] ; then
208 echo undef
209 else
210 V="${V/#${CONFIG_}$ARG=/}"
211 V="${V/#\"/}"
212 V="${V/%\"/}"
213 V="${V//\\\"/\"}"
214 echo "${V}"
215 fi
216 fi
217 ;;
218
219 --enable-after|-E)
220 set_var "${CONFIG_}$B" "${CONFIG_}$B=y" "${CONFIG_}$A"
221 ;;
222
223 --disable-after|-D)
224 set_var "${CONFIG_}$B" "# ${CONFIG_}$B is not set" "${CONFIG_}$A"
225 ;;
226
227 --module-after|-M)
228 set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A"
229 ;;
230
231 --refresh)
232 yes "" | make oldconfig KCONFIG_CONFIG=$FN
233 ;;
234
235 *)
236 echo "bad command: $CMD" >&2
237 usage
238 ;;
239 esac
240done