Bash – Double Square Bracket in ‘case’ in ‘configure.ac’

autoconfbashshell

I am trying to understand the following code snippet.

host_cpu='i386'

case "$host_cpu" in
   i[[3456]]86)
       echo "host_cpu=i386"
   ;;
   x86_64)
       echo "host_cpu=x86_64"
   ;;
   *)
       echo "AC_MSG_ERROR([unsupported CPU type]) "
   ;;
esac

I added the variable host_cpu='i386' myself to test the code and it switched to the third case of echo "AC_MSG_ERROR([unsupported CPU type]) ".

If I change the double bracket in i[[3456]]86) to a single bracket as in i[3456]86), it switches to the first option yielding i386. This seems correct to me.

I understand that [ and [[ are the test options. The test condition doesn't seem to apply here as the switch cases are expecting a character to be outputted. So I'm assuming for bash to pick it up as a test condition, it needs to be separated by a space as in [ a < b ] or [[ a << b ]]. Because there are no spaces in these case statement, it'll be treated as a regular expression. Is this correct?

So my question is why was the double square bracket was used here by the code writer? It didn't work when I tried to run the code, so what was their intention.

Note: The code was taken from a configure.ac in the GRUB source code.

Also the $host_cpu and host_cpu=i386 line seem unnecessary, can you explain why the writer would have done this:

AC_CANONICAL_HOST

case "$host_cpu" in
    i[[3456]]86) host_cpu=i386 ;;
    x86_64) host_cpu=x86_64 ;;
    *) AC_MSG_ERROR([unsupported CPU type]) ;;
esac

AC_SUBST(host_cpu)
AC_SUBST(host_vendor)

I'm thinking of using AC_SUBST($host_cpu). Why wouldn't you do it this way?

Best Answer

If that's a from a configure.ac file, then it's not a pure shell script, but is an Autoconf script using M4, where [] are quote characters.:

To fully understand where proper quotation is important, you first need to know what the special characters are in Autoconf: ‘#’ introduces a comment inside which no macro expansion is performed, ‘,’ separates arguments, ‘[’ and ‘]’ are the quotes themselves, ‘(’ and ‘)’ (which M4 tries to match by pairs), and finally ‘$’ inside a macro definition.

Each time there can be a macro expansion, there is a quotation expansion, i.e., one level of quotes is stripped:

 int tab[10];
 ⇒int tab10;
 [int tab[10];]
 ⇒int tab[10];

That [[3456]] should be expanded by autoconf to [3456], which would be the correct output for use as a shell script.