Autoconf, Automake, and Libtool: Functions

| ### 22.2.4 () There are still a great number of shells that, like Steve Bourne's original implementation, do not have functions! So, strictly speaking, you can't use shell functions in your scripts. Luckily, in this day and age, even though ``/bin/sh'` itself may not support shell functions, it is not too far from the truth to say that almost every machine will have some shell that does. Taking this assumption to its logical conclusion, it is a simple matter of writing your script to find a suitable shell, and then feed itself to that shell so that the rest of the script can use functions with impunity:
    #! /bin/sh

    # Zsh is not Bourne compatible without the following:
    if test -n "$ZSH_VERSION"; then
      emulate sh
      NULLCMD=:
    fi

    # Bash is not POSIX compliant without the following:
    test -n "$BASH_VERSION" && set -o posix

    SHELL="${SHELL-/bin/sh}"
    if test x"$1" = x--re-executed; then
      # Functional shell was found.  Remove option and continue
      shift
    elif "$SHELL" -c 'foo () { exit 0; }; foo' 2>/dev/null; then
      # The current shell works already!
      :
    else
      # Try alternative shells that (sometimes) support functions
      for cmd in sh bash ash bsh ksh zsh sh5; do
        set IFS=:; X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb"; echo $X`
        for dir
          shell="$dir/$cmd"
          if (test -f "$shell" || test -f "$shell.exe") &&
            "$shell" -c 'foo () { exit 0; }; foo 2>/dev/null
          then
            # Re-execute with discovered functional shell
            SHELL="$shell" exec "$shell" "$0" --re-executed ${1+"$@"}
          fi
        done
      done
      echo "Unable to locate a shell interpreter with function support" >&2
      exit 1
    fi

    foo () {
        echo "$SHELL: ta da!"
    }

    foo

    exit 0
Note that this script finds a shell that supports functions of the following syntax, since the use of the `function` keyword is much less widely supported:
    foo () { ... }
A notable exception to the assertion that all machines have a shell that can handle functions is 4.3BSD, which has only a single shell: a shell function deprived Bourne shell. There are two ways you can deal with this: Ask 4.3BSD users of your script to install a more featureful shell such as bash, so that the technique above will work. Have your script run itself through `sed`, chopping itself into pieces, with each function written to it's own script file, and then feed what's left into the original shell. Whenever a function call is encountered, one of the fragments from the original script will be executed in a subshell. If you decide to split the script with `sed`, you will need to be careful not to rely on shell variables to communicate between functions, since each `function' will be executed in its own subshell.

This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html