chiark / gitweb /
Initial sketch.
[finally] / m4 / finally.m4
CommitLineData
d58b8198
MW
1dnl -*-autoconf-*-
2
3### SYNOPSIS
4###
5### FINALLY([IF-SUCCEEDED], [IF-FAILED])
6###
7### DESCRIPTION
8###
9### Probe at the C compiler to determine how, if at all, to implement the
10### `FINALLY' macro, which arranges to run some code when control leaves a
11### given scope. This isn't at all a standard C feature, so we need to use
12### compiler-specific hacks, and this is the main machinery for deciding
13### which hacks to deploy.
14###
15### On exit, the shell variable `finally_flavour' is set to an uppercase
16### word naming the chosen implementation strategy: it will be `NIL' if the
17### macro failed and no strategy could be found. The preprocessor define
18### `FINALLY_CONFIG_FLAVOUR' is set to `FINALLY_CONFIG_FLAVOUR_...'
19### followed by the same word: this is the main input to the selection
20### machinery in `finally.h'.
21###
22### The substitution variables `FINALLY_CFLAGS' and `FINALLY_LIBS' are set
23### to any additional compiler flags or libraries needed to support the
24### `FINALLY' macro. They can be set per-target in the `Makefile', or
25### stuffed into the global variables by the `configure' script.
26###
27### If the macro managed to find a workable strategy, then the shell
28### fragment IF-SUCCEEDED is run; otherwise, (if `finally_flavour' is
29### `NIL'), the shell fragment IF-FAILED is run.
30###
31### LICENSE
32###
33### Copyright (c) 2023 Mark Wooding <mdw@distorted.org.uk>
34###
35### This program is free software: you can redistribute it and/or modify it
36### under the terms of the GNU General Public License as published by the
37### Free Software Foundation, either version 2 of the License, or (at your
38### option) any later version.
39###
40### This program is distributed in the hope that it will be useful, but
41### WITHOUT ANY WARRANTY; without even the implied warranty of
42### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43### General Public License for more details.
44###
45### You should have received a copy of the GNU General Public License along
46### with this program. If not, see <http://www.gnu.org/licenses/>.
47###
48### In particular, no exception to the GPL is granted regarding generated
49### `configure' scripts which are the output of Autoconf.
50
51AC_DEFUN([FINALLY_GCC_NESTED_FUNCTIONS_TEST_PROGRAM], [AC_LANG_PROGRAM([], [
52 __extension__ __inline__ void nested(void) { ; }
53 nested();
54])])
55AC_DEFUN([FINALLY_GCC_ATTRIBUTE_CLEANUP_TEST_PROGRAM], [AC_LANG_PROGRAM([
56 extern void cleanup_fn(const int *x);
57 extern void bamboozle(int *x_inout);
58], [
59 __attribute__((cleanup(cleanup_fn))) int x = 0;
60 bamboozle(&x);
61])])
62
63dnl Decide whether we can define a plausible `FINALLY' macro.
64AC_DEFUN([FINALLY_CHECK],
65[finally_flavour=undecided finally_result="not supported"
66
67dnl We're going to want to test C code.
68AC_LANG_PUSH([C])
69
70case $finally_flavour,$GCC in
71 undecided,yes)
72 dnl Our GCC-ish strategies have a common factor: they depend on
73 dnl `__attribute__((cleanup(...)))' working. So let's check for that.
74
75 AC_CACHE_CHECK([whether the alleged GNU C compiler supports \`__attribute__((cleanup(...)))'],
76 [finally_cv_gcc_attribute_cleanup_p], [
77 AC_COMPILE_IFELSE([FINALLY_GCC_ATTRIBUTE_CLEANUP_TEST_PROGRAM],
78 [finally_cv_gcc_attribute_cleanup_p=yes],
79 [finally_cv_gcc_attribute_cleanup_p=no])])
80 case $finally_cv_gcc_attribute_cleanup_p in
81 no) finally_flavour=NIL ;;
82 esac
83 ;;
84esac
85
86case $finally_flavour,$GCC in
87 undecided,yes)
88 dnl Autoconf has decided that the compiler smells a bit like GCC, and it
89 dnl certainly seems to support a GCC extension. But many compilers
90 dnl impersonate GCC, in more or less convincing ways. Our GCC-flavoured
91 dnl `FINALLY' code depends on nested functions, which GCC has supported
92 dnl pretty much forever, but other compilers don't even though they lie
93 dnl about being compatible.
94
95 AC_CACHE_CHECK([whether the alleged GNU C compiler supports nested functions],
96 [finally_cv_gcc_nested_functions_p], [
97 AC_COMPILE_IFELSE([FINALLY_GCC_NESTED_FUNCTIONS_TEST_PROGRAM],
98 [finally_cv_gcc_nested_functions_p=yes],
99 [finally_cv_gcc_nested_functions_p=no])])
100 case $finally_cv_gcc_nested_functions_p in
101 yes)
102 finally_flavour=GCC_NESTED_FUNCTIONS
103 finally_result="GCC nested functions"
104 ;;
105 esac
106 ;;
107esac
108
109case $finally_flavour in
110 undecided)
111 dnl We've got this far and we've drawn a blank. Give up.
112 finally_flavour=NIL
113 ;;
114esac
115
116AC_LANG_POP([C])
117
118dnl Pass the results on to the implementation machinery.
119AC_MSG_CHECKING([how to implement deferred cleanup code])
120AC_DEFINE_UNQUOTED([FINALLY_CONFIG_FLAVOUR],
121 [$finally_flavour],
122 [Select one of the implementation strategies for the `FINALLY' macro.])
123AC_SUBST(FINALLY_CFLAGS) AC_SUBST(FINALLY_LIBS)
124AC_MSG_RESULT([$finally_result])
125
126dnl Invoke the caller's shell fragments according to our findings.
127case $finally_flavour in
128 nil)
129 $2
130 ;;
131 *)
132 $1
133 ;;
134esac
135])