4

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?

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
supmethods
  • 481
  • 6
  • 12
  • 2
    Looks like a bug. I suggest you submit a pull request. And no, it's not a regular expression; it's pattern matching, which works the same as file globs. – Wildcard Oct 04 '18 at 01:56

1 Answers1

9

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.

muru
  • 69,900
  • 13
  • 192
  • 292
  • 1
    Indeed - as one can verify by adding a minimal `AC_INIT([foo])` to the top of the snippet and then executing `autoconf snippet` – steeldriver Oct 04 '18 at 02:27
  • Okay, thanks. I've read about m4 and they used the quote characters ` and ' in those articles. So the must have changed the quotes in the configure.ac to treat [ and ] as quotes. – supmethods Oct 04 '18 at 03:56
  • The link you provided use [ and ] as quotes. Does this depend on M4 version used? – supmethods Oct 04 '18 at 04:01
  • @supmethods you can [change the quote characters in M4](https://www.gnu.org/software/m4/manual/m4.html#Changequote), and it seems `[ ]` are set as quote characters in autoconf scripts. The default quote characters in M4 are `\`' `, as you have seen. – muru Oct 04 '18 at 04:17
  • I updated the post and would like to know the main purpose of the case statement. AC_CANONICAL_HOST computes the host_cpu, host_vendor, and host_os. Doesn't it mean that you don't need assignment of the variables (as in host_cpu=i386 and host_cpu=x86_64), and that you can simply do an "if $host_cpu is false then AC_MSG_ERROR([unsupported CPU type])"? host_cpu should already be set from AC_CANONICAL_HOST, so shell variable can be set straight away (AC_SUBST(host_cpu) without the assignment). – supmethods Oct 09 '18 at 12:51
  • @supmethods since they're matching against i486, i586 and i686, and setting those cases to i386, obviously it's not sufficient. – muru Oct 09 '18 at 12:54
  • ok, makes complete sense. Just wanted to check to ensure it's not my misunderstanding of the language. Thanks. – supmethods Oct 09 '18 at 12:56