162306a36Sopenharmony_ci#!/usr/bin/env bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci# Manipulate options in a .config file from the command line
462306a36Sopenharmony_ci
562306a36Sopenharmony_cimyname=${0##*/}
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci# If no prefix forced, use the default CONFIG_
862306a36Sopenharmony_ciCONFIG_="${CONFIG_-CONFIG_}"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci# We use an uncommon delimiter for sed substitutions
1162306a36Sopenharmony_ciSED_DELIM=$(echo -en "\001")
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ciusage() {
1462306a36Sopenharmony_ci	cat >&2 <<EOL
1562306a36Sopenharmony_ciManipulate options in a .config file from the command line.
1662306a36Sopenharmony_ciUsage:
1762306a36Sopenharmony_ci$myname options command ...
1862306a36Sopenharmony_cicommands:
1962306a36Sopenharmony_ci	--enable|-e option   Enable option
2062306a36Sopenharmony_ci	--disable|-d option  Disable option
2162306a36Sopenharmony_ci	--module|-m option   Turn option into a module
2262306a36Sopenharmony_ci	--set-str option string
2362306a36Sopenharmony_ci	                     Set option to "string"
2462306a36Sopenharmony_ci	--set-val option value
2562306a36Sopenharmony_ci	                     Set option to value
2662306a36Sopenharmony_ci	--undefine|-u option Undefine option
2762306a36Sopenharmony_ci	--state|-s option    Print state of option (n,y,m,undef)
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	--enable-after|-E beforeopt option
3062306a36Sopenharmony_ci                             Enable option directly after other option
3162306a36Sopenharmony_ci	--disable-after|-D beforeopt option
3262306a36Sopenharmony_ci                             Disable option directly after other option
3362306a36Sopenharmony_ci	--module-after|-M beforeopt option
3462306a36Sopenharmony_ci                             Turn option into module directly after other option
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	commands can be repeated multiple times
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cioptions:
3962306a36Sopenharmony_ci	--file config-file   .config file to change (default .config)
4062306a36Sopenharmony_ci	--keep-case|-k       Keep next symbols' case (dont' upper-case it)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci$myname doesn't check the validity of the .config file. This is done at next
4362306a36Sopenharmony_cimake time.
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ciBy default, $myname will upper-case the given symbol. Use --keep-case to keep
4662306a36Sopenharmony_cithe case of all following symbols unchanged.
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci$myname uses 'CONFIG_' as the default symbol prefix. Set the environment
4962306a36Sopenharmony_civariable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ...
5062306a36Sopenharmony_ciEOL
5162306a36Sopenharmony_ci	exit 1
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cicheckarg() {
5562306a36Sopenharmony_ci	ARG="$1"
5662306a36Sopenharmony_ci	if [ "$ARG" = "" ] ; then
5762306a36Sopenharmony_ci		usage
5862306a36Sopenharmony_ci	fi
5962306a36Sopenharmony_ci	case "$ARG" in
6062306a36Sopenharmony_ci	${CONFIG_}*)
6162306a36Sopenharmony_ci		ARG="${ARG/${CONFIG_}/}"
6262306a36Sopenharmony_ci		;;
6362306a36Sopenharmony_ci	esac
6462306a36Sopenharmony_ci	if [ "$MUNGE_CASE" = "yes" ] ; then
6562306a36Sopenharmony_ci		ARG="`echo $ARG | tr a-z A-Z`"
6662306a36Sopenharmony_ci	fi
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_citxt_append() {
7062306a36Sopenharmony_ci	local anchor="$1"
7162306a36Sopenharmony_ci	local insert="$2"
7262306a36Sopenharmony_ci	local infile="$3"
7362306a36Sopenharmony_ci	local tmpfile="$infile.swp"
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	# sed append cmd: 'a\' + newline + text + newline
7662306a36Sopenharmony_ci	cmd="$(printf "a\\%b$insert" "\n")"
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	sed -e "/$anchor/$cmd" "$infile" >"$tmpfile"
7962306a36Sopenharmony_ci	# replace original file with the edited one
8062306a36Sopenharmony_ci	mv "$tmpfile" "$infile"
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_citxt_subst() {
8462306a36Sopenharmony_ci	local before="$1"
8562306a36Sopenharmony_ci	local after="$2"
8662306a36Sopenharmony_ci	local infile="$3"
8762306a36Sopenharmony_ci	local tmpfile="$infile.swp"
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	sed -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile" >"$tmpfile"
9062306a36Sopenharmony_ci	# replace original file with the edited one
9162306a36Sopenharmony_ci	mv "$tmpfile" "$infile"
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_citxt_delete() {
9562306a36Sopenharmony_ci	local text="$1"
9662306a36Sopenharmony_ci	local infile="$2"
9762306a36Sopenharmony_ci	local tmpfile="$infile.swp"
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	sed -e "/$text/d" "$infile" >"$tmpfile"
10062306a36Sopenharmony_ci	# replace original file with the edited one
10162306a36Sopenharmony_ci	mv "$tmpfile" "$infile"
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciset_var() {
10562306a36Sopenharmony_ci	local name=$1 new=$2 before=$3
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	name_re="^($name=|# $name is not set)"
10862306a36Sopenharmony_ci	before_re="^($before=|# $before is not set)"
10962306a36Sopenharmony_ci	if test -n "$before" && grep -Eq "$before_re" "$FN"; then
11062306a36Sopenharmony_ci		txt_append "^$before=" "$new" "$FN"
11162306a36Sopenharmony_ci		txt_append "^# $before is not set" "$new" "$FN"
11262306a36Sopenharmony_ci	elif grep -Eq "$name_re" "$FN"; then
11362306a36Sopenharmony_ci		txt_subst "^$name=.*" "$new" "$FN"
11462306a36Sopenharmony_ci		txt_subst "^# $name is not set" "$new" "$FN"
11562306a36Sopenharmony_ci	else
11662306a36Sopenharmony_ci		echo "$new" >>"$FN"
11762306a36Sopenharmony_ci	fi
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciundef_var() {
12162306a36Sopenharmony_ci	local name=$1
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	txt_delete "^$name=" "$FN"
12462306a36Sopenharmony_ci	txt_delete "^# $name is not set" "$FN"
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciif [ "$1" = "--file" ]; then
12862306a36Sopenharmony_ci	FN="$2"
12962306a36Sopenharmony_ci	if [ "$FN" = "" ] ; then
13062306a36Sopenharmony_ci		usage
13162306a36Sopenharmony_ci	fi
13262306a36Sopenharmony_ci	shift 2
13362306a36Sopenharmony_cielse
13462306a36Sopenharmony_ci	FN=.config
13562306a36Sopenharmony_cifi
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ciif [ "$1" = "" ] ; then
13862306a36Sopenharmony_ci	usage
13962306a36Sopenharmony_cifi
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ciMUNGE_CASE=yes
14262306a36Sopenharmony_ciwhile [ "$1" != "" ] ; do
14362306a36Sopenharmony_ci	CMD="$1"
14462306a36Sopenharmony_ci	shift
14562306a36Sopenharmony_ci	case "$CMD" in
14662306a36Sopenharmony_ci	--keep-case|-k)
14762306a36Sopenharmony_ci		MUNGE_CASE=no
14862306a36Sopenharmony_ci		continue
14962306a36Sopenharmony_ci		;;
15062306a36Sopenharmony_ci	--refresh)
15162306a36Sopenharmony_ci		;;
15262306a36Sopenharmony_ci	--*-after|-E|-D|-M)
15362306a36Sopenharmony_ci		checkarg "$1"
15462306a36Sopenharmony_ci		A=$ARG
15562306a36Sopenharmony_ci		checkarg "$2"
15662306a36Sopenharmony_ci		B=$ARG
15762306a36Sopenharmony_ci		shift 2
15862306a36Sopenharmony_ci		;;
15962306a36Sopenharmony_ci	-*)
16062306a36Sopenharmony_ci		checkarg "$1"
16162306a36Sopenharmony_ci		shift
16262306a36Sopenharmony_ci		;;
16362306a36Sopenharmony_ci	esac
16462306a36Sopenharmony_ci	case "$CMD" in
16562306a36Sopenharmony_ci	--enable|-e)
16662306a36Sopenharmony_ci		set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=y"
16762306a36Sopenharmony_ci		;;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	--disable|-d)
17062306a36Sopenharmony_ci		set_var "${CONFIG_}$ARG" "# ${CONFIG_}$ARG is not set"
17162306a36Sopenharmony_ci		;;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	--module|-m)
17462306a36Sopenharmony_ci		set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=m"
17562306a36Sopenharmony_ci		;;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	--set-str)
17862306a36Sopenharmony_ci		# sed swallows one level of escaping, so we need double-escaping
17962306a36Sopenharmony_ci		set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=\"${1//\"/\\\\\"}\""
18062306a36Sopenharmony_ci		shift
18162306a36Sopenharmony_ci		;;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	--set-val)
18462306a36Sopenharmony_ci		set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=$1"
18562306a36Sopenharmony_ci		shift
18662306a36Sopenharmony_ci		;;
18762306a36Sopenharmony_ci	--undefine|-u)
18862306a36Sopenharmony_ci		undef_var "${CONFIG_}$ARG"
18962306a36Sopenharmony_ci		;;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	--state|-s)
19262306a36Sopenharmony_ci		if grep -q "# ${CONFIG_}$ARG is not set" $FN ; then
19362306a36Sopenharmony_ci			echo n
19462306a36Sopenharmony_ci		else
19562306a36Sopenharmony_ci			V="$(grep "^${CONFIG_}$ARG=" $FN)"
19662306a36Sopenharmony_ci			if [ $? != 0 ] ; then
19762306a36Sopenharmony_ci				echo undef
19862306a36Sopenharmony_ci			else
19962306a36Sopenharmony_ci				V="${V/#${CONFIG_}$ARG=/}"
20062306a36Sopenharmony_ci				V="${V/#\"/}"
20162306a36Sopenharmony_ci				V="${V/%\"/}"
20262306a36Sopenharmony_ci				V="${V//\\\"/\"}"
20362306a36Sopenharmony_ci				echo "${V}"
20462306a36Sopenharmony_ci			fi
20562306a36Sopenharmony_ci		fi
20662306a36Sopenharmony_ci		;;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	--enable-after|-E)
20962306a36Sopenharmony_ci		set_var "${CONFIG_}$B" "${CONFIG_}$B=y" "${CONFIG_}$A"
21062306a36Sopenharmony_ci		;;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	--disable-after|-D)
21362306a36Sopenharmony_ci		set_var "${CONFIG_}$B" "# ${CONFIG_}$B is not set" "${CONFIG_}$A"
21462306a36Sopenharmony_ci		;;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	--module-after|-M)
21762306a36Sopenharmony_ci		set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A"
21862306a36Sopenharmony_ci		;;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	# undocumented because it ignores --file (fixme)
22162306a36Sopenharmony_ci	--refresh)
22262306a36Sopenharmony_ci		yes "" | make oldconfig
22362306a36Sopenharmony_ci		;;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	*)
22662306a36Sopenharmony_ci		echo "bad command: $CMD" >&2
22762306a36Sopenharmony_ci		usage
22862306a36Sopenharmony_ci		;;
22962306a36Sopenharmony_ci	esac
23062306a36Sopenharmony_cidone
231