Commit | Line | Data |
---|---|---|
d58b8198 MW |
1 | dnl -*-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 | ||
51 | AC_DEFUN([FINALLY_GCC_NESTED_FUNCTIONS_TEST_PROGRAM], [AC_LANG_PROGRAM([], [ | |
52 | __extension__ __inline__ void nested(void) { ; } | |
53 | nested(); | |
54 | ])]) | |
55 | AC_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 | ||
63 | dnl Decide whether we can define a plausible `FINALLY' macro. | |
64 | AC_DEFUN([FINALLY_CHECK], | |
65 | [finally_flavour=undecided finally_result="not supported" | |
66 | ||
67 | dnl We're going to want to test C code. | |
68 | AC_LANG_PUSH([C]) | |
69 | ||
70 | case $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 | ;; | |
84 | esac | |
85 | ||
86 | case $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 | ;; | |
107 | esac | |
108 | ||
109 | case $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 | ;; | |
114 | esac | |
115 | ||
116 | AC_LANG_POP([C]) | |
117 | ||
118 | dnl Pass the results on to the implementation machinery. | |
119 | AC_MSG_CHECKING([how to implement deferred cleanup code]) | |
120 | AC_DEFINE_UNQUOTED([FINALLY_CONFIG_FLAVOUR], | |
121 | [$finally_flavour], | |
122 | [Select one of the implementation strategies for the `FINALLY' macro.]) | |
123 | AC_SUBST(FINALLY_CFLAGS) AC_SUBST(FINALLY_LIBS) | |
124 | AC_MSG_RESULT([$finally_result]) | |
125 | ||
126 | dnl Invoke the caller's shell fragments according to our findings. | |
127 | case $finally_flavour in | |
128 | nil) | |
129 | $2 | |
130 | ;; | |
131 | *) | |
132 | $1 | |
133 | ;; | |
134 | esac | |
135 | ]) |