| #!/usr/bin/env bash |
| # Manipulate options in a .config file from the command line |
| |
| myname=${0##*/} |
| |
| # If no prefix forced, use the default CONFIG_ |
| CONFIG_="${CONFIG_-CONFIG_}" |
| |
| # We use an uncommon delimiter for sed substitutions |
| SED_DELIM=$(echo -en "\001") |
| |
| usage() { |
| cat >&2 <<EOL |
| Manipulate options in a .config file from the command line. |
| Usage: |
| $myname options command ... |
| commands: |
| --enable|-e option Enable option |
| --disable|-d option Disable option |
| --module|-m option Turn option into a module |
| --set-str option string |
| Set option to "string" |
| --set-val option value |
| Set option to value |
| --undefine|-u option Undefine option |
| --state|-s option Print state of option (n,y,m,undef) |
| |
| --enable-after|-E beforeopt option |
| Enable option directly after other option |
| --disable-after|-D beforeopt option |
| Disable option directly after other option |
| --module-after|-M beforeopt option |
| Turn option into module directly after other option |
| |
| commands can be repeated multiple times |
| |
| options: |
| --file config-file .config file to change (default .config) |
| --keep-case|-k Keep next symbols' case (dont' upper-case it) |
| |
| $myname doesn't check the validity of the .config file. This is done at next |
| make time. |
| |
| By default, $myname will upper-case the given symbol. Use --keep-case to keep |
| the case of all following symbols unchanged. |
| |
| $myname uses 'CONFIG_' as the default symbol prefix. Set the environment |
| variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" $myname ... |
| EOL |
| exit 1 |
| } |
| |
| checkarg() { |
| ARG="$1" |
| if [ "$ARG" = "" ] ; then |
| usage |
| fi |
| case "$ARG" in |
| ${CONFIG_}*) |
| ARG="${ARG/${CONFIG_}/}" |
| ;; |
| esac |
| if [ "$MUNGE_CASE" = "yes" ] ; then |
| ARG="`echo $ARG | tr a-z A-Z`" |
| fi |
| } |
| |
| txt_append() { |
| local anchor="$1" |
| local insert="$2" |
| local infile="$3" |
| local tmpfile="$infile.swp" |
| |
| # sed append cmd: 'a\' + newline + text + newline |
| cmd="$(printf "a\\%b$insert" "\n")" |
| |
| sed -e "/$anchor/$cmd" "$infile" >"$tmpfile" |
| # replace original file with the edited one |
| mv "$tmpfile" "$infile" |
| } |
| |
| txt_subst() { |
| local before="$1" |
| local after="$2" |
| local infile="$3" |
| local tmpfile="$infile.swp" |
| |
| sed -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile" >"$tmpfile" |
| # replace original file with the edited one |
| mv "$tmpfile" "$infile" |
| } |
| |
| txt_delete() { |
| local text="$1" |
| local infile="$2" |
| local tmpfile="$infile.swp" |
| |
| sed -e "/$text/d" "$infile" >"$tmpfile" |
| # replace original file with the edited one |
| mv "$tmpfile" "$infile" |
| } |
| |
| set_var() { |
| local name=$1 new=$2 before=$3 |
| |
| name_re="^($name=|# $name is not set)" |
| before_re="^($before=|# $before is not set)" |
| if test -n "$before" && grep -Eq "$before_re" "$FN"; then |
| txt_append "^$before=" "$new" "$FN" |
| txt_append "^# $before is not set" "$new" "$FN" |
| elif grep -Eq "$name_re" "$FN"; then |
| txt_subst "^$name=.*" "$new" "$FN" |
| txt_subst "^# $name is not set" "$new" "$FN" |
| else |
| echo "$new" >>"$FN" |
| fi |
| } |
| |
| undef_var() { |
| local name=$1 |
| |
| txt_delete "^$name=" "$FN" |
| txt_delete "^# $name is not set" "$FN" |
| } |
| |
| if [ "$1" = "--file" ]; then |
| FN="$2" |
| if [ "$FN" = "" ] ; then |
| usage |
| fi |
| shift 2 |
| else |
| FN=.config |
| fi |
| |
| if [ "$1" = "" ] ; then |
| usage |
| fi |
| |
| MUNGE_CASE=yes |
| while [ "$1" != "" ] ; do |
| CMD="$1" |
| shift |
| case "$CMD" in |
| --keep-case|-k) |
| MUNGE_CASE=no |
| continue |
| ;; |
| --refresh) |
| ;; |
| --*-after|-E|-D|-M) |
| checkarg "$1" |
| A=$ARG |
| checkarg "$2" |
| B=$ARG |
| shift 2 |
| ;; |
| -*) |
| checkarg "$1" |
| shift |
| ;; |
| esac |
| case "$CMD" in |
| --enable|-e) |
| set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=y" |
| ;; |
| |
| --disable|-d) |
| set_var "${CONFIG_}$ARG" "# ${CONFIG_}$ARG is not set" |
| ;; |
| |
| --module|-m) |
| set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=m" |
| ;; |
| |
| --set-str) |
| # sed swallows one level of escaping, so we need double-escaping |
| set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=\"${1//\"/\\\\\"}\"" |
| shift |
| ;; |
| |
| --set-val) |
| set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=$1" |
| shift |
| ;; |
| --undefine|-u) |
| undef_var "${CONFIG_}$ARG" |
| ;; |
| |
| --state|-s) |
| if grep -q "# ${CONFIG_}$ARG is not set" $FN ; then |
| echo n |
| else |
| V="$(grep "^${CONFIG_}$ARG=" $FN)" |
| if [ $? != 0 ] ; then |
| echo undef |
| else |
| V="${V/#${CONFIG_}$ARG=/}" |
| V="${V/#\"/}" |
| V="${V/%\"/}" |
| V="${V//\\\"/\"}" |
| echo "${V}" |
| fi |
| fi |
| ;; |
| |
| --enable-after|-E) |
| set_var "${CONFIG_}$B" "${CONFIG_}$B=y" "${CONFIG_}$A" |
| ;; |
| |
| --disable-after|-D) |
| set_var "${CONFIG_}$B" "# ${CONFIG_}$B is not set" "${CONFIG_}$A" |
| ;; |
| |
| --module-after|-M) |
| set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A" |
| ;; |
| |
| # undocumented because it ignores --file (fixme) |
| --refresh) |
| yes "" | make oldconfig |
| ;; |
| |
| *) |
| usage |
| ;; |
| esac |
| done |