|
| 1 | +# =========================================================================== |
| 2 | +# https://www.gnu.org/software/autoconf-archive/ax_prototype.html |
| 3 | +# =========================================================================== |
| 4 | +# |
| 5 | +# SYNOPSIS |
| 6 | +# |
| 7 | +# AX_PROTOTYPE(function, includes, code, TAG1, values1 [, TAG2, values2 [...]]) |
| 8 | +# |
| 9 | +# DESCRIPTION |
| 10 | +# |
| 11 | +# Try all the combinations of <TAG1>, <TAG2>... to successfully compile |
| 12 | +# <code>. <TAG1>, <TAG2>, ... are substituted in <code> and <include> with |
| 13 | +# values found in <values1>, <values2>, ... respectively. <values1>, |
| 14 | +# <values2>, ... contain a list of possible values for each corresponding |
| 15 | +# tag and all combinations are tested. When AC_TRY_COMPILE(include, code) |
| 16 | +# is successfull for a given substitution, the macro stops and defines the |
| 17 | +# following macros: FUNCTION_TAG1, FUNCTION_TAG2, ... using AC_DEFINE() |
| 18 | +# with values set to the current values of <TAG1>, <TAG2>, ... If no |
| 19 | +# combination is successfull the configure script is aborted with a |
| 20 | +# message. |
| 21 | +# |
| 22 | +# Intended purpose is to find which combination of argument types is |
| 23 | +# acceptable for a given function <function>. It is recommended to list |
| 24 | +# the most specific types first. For instance ARG1, [size_t, int] instead |
| 25 | +# of ARG1, [int, size_t]. |
| 26 | +# |
| 27 | +# Generic usage pattern: |
| 28 | +# |
| 29 | +# 1) add a call in configure.in |
| 30 | +# |
| 31 | +# AX_PROTOTYPE(...) |
| 32 | +# |
| 33 | +# 2) call autoheader to see which symbols are not covered |
| 34 | +# |
| 35 | +# 3) add the lines in acconfig.h |
| 36 | +# |
| 37 | +# /* Type of Nth argument of function */ |
| 38 | +# #undef FUNCTION_ARGN |
| 39 | +# |
| 40 | +# 4) Within the code use FUNCTION_ARGN instead of an hardwired type |
| 41 | +# |
| 42 | +# Complete example: |
| 43 | +# |
| 44 | +# 1) configure.in |
| 45 | +# |
| 46 | +# AX_PROTOTYPE(getpeername, |
| 47 | +# [ |
| 48 | +# #include <sys/types.h> |
| 49 | +# #include <sys/socket.h> |
| 50 | +# ], |
| 51 | +# [ |
| 52 | +# int a = 0; |
| 53 | +# ARG2 * b = 0; |
| 54 | +# ARG3 * c = 0; |
| 55 | +# getpeername(a, b, c); |
| 56 | +# ], |
| 57 | +# ARG2, [struct sockaddr, void], |
| 58 | +# ARG3, [socklen_t, size_t, int, unsigned int, long unsigned int]) |
| 59 | +# |
| 60 | +# 2) call autoheader |
| 61 | +# |
| 62 | +# autoheader: Symbol `GETPEERNAME_ARG2' is not covered by ./acconfig.h |
| 63 | +# autoheader: Symbol `GETPEERNAME_ARG3' is not covered by ./acconfig.h |
| 64 | +# |
| 65 | +# 3) acconfig.h |
| 66 | +# |
| 67 | +# /* Type of second argument of getpeername */ |
| 68 | +# #undef GETPEERNAME_ARG2 |
| 69 | +# |
| 70 | +# /* Type of third argument of getpeername */ |
| 71 | +# #undef GETPEERNAME_ARG3 |
| 72 | +# |
| 73 | +# 4) in the code |
| 74 | +# |
| 75 | +# ... |
| 76 | +# GETPEERNAME_ARG2 name; |
| 77 | +# GETPEERNAME_ARG3 namelen; |
| 78 | +# ... |
| 79 | +# ret = getpeername(socket, &name, &namelen); |
| 80 | +# ... |
| 81 | +# |
| 82 | +# Implementation notes: generating all possible permutations of the |
| 83 | +# arguments is not easily done with the usual mixture of shell and m4, |
| 84 | +# that is why this macro is almost 100% m4 code. It generates long but |
| 85 | +# simple to read code. |
| 86 | +# |
| 87 | +# LICENSE |
| 88 | +# |
| 89 | +# Copyright (c) 2009 Loic Dachary <[email protected]> |
| 90 | +# |
| 91 | +# This program is free software; you can redistribute it and/or modify it |
| 92 | +# under the terms of the GNU General Public License as published by the |
| 93 | +# Free Software Foundation; either version 2 of the License, or (at your |
| 94 | +# option) any later version. |
| 95 | +# |
| 96 | +# This program is distributed in the hope that it will be useful, but |
| 97 | +# WITHOUT ANY WARRANTY; without even the implied warranty of |
| 98 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
| 99 | +# Public License for more details. |
| 100 | +# |
| 101 | +# You should have received a copy of the GNU General Public License along |
| 102 | +# with this program. If not, see <https://www.gnu.org/licenses/>. |
| 103 | +# |
| 104 | +# As a special exception, the respective Autoconf Macro's copyright owner |
| 105 | +# gives unlimited permission to copy, distribute and modify the configure |
| 106 | +# scripts that are the output of Autoconf when processing the Macro. You |
| 107 | +# need not follow the terms of the GNU General Public License when using |
| 108 | +# or distributing such scripts, even though portions of the text of the |
| 109 | +# Macro appear in them. The GNU General Public License (GPL) does govern |
| 110 | +# all other use of the material that constitutes the Autoconf Macro. |
| 111 | +# |
| 112 | +# This special exception to the GPL applies to versions of the Autoconf |
| 113 | +# Macro released by the Autoconf Archive. When you make and distribute a |
| 114 | +# modified version of the Autoconf Macro, you may extend this special |
| 115 | +# exception to the GPL to apply to your modified version as well. |
| 116 | + |
| 117 | +#serial 6 |
| 118 | + |
| 119 | +AU_ALIAS([AC_PROTOTYPE], [AX_PROTOTYPE]) |
| 120 | +AC_DEFUN([AX_PROTOTYPE],[ |
| 121 | +dnl |
| 122 | +dnl Upper case function name |
| 123 | +dnl |
| 124 | + pushdef([function],translit([$1], [a-z], [A-Z])) |
| 125 | +dnl |
| 126 | +dnl Collect tags that will be substituted |
| 127 | +dnl |
| 128 | + pushdef([tags],[AX_PROTOTYPE_TAGS(builtin([shift],builtin([shift],builtin([shift],$@))))]) |
| 129 | +dnl |
| 130 | +dnl Wrap in a 1 time loop, when a combination is found break to stop the combinatory exploration |
| 131 | +dnl |
| 132 | + for i in 1 |
| 133 | + do |
| 134 | + AX_PROTOTYPE_LOOP(AX_PROTOTYPE_REVERSE($1, AX_PROTOTYPE_SUBST($2,tags),AX_PROTOTYPE_SUBST($3,tags),builtin([shift],builtin([shift],builtin([shift],$@))))) |
| 135 | + AC_MSG_ERROR($1 unable to find a working combination) |
| 136 | + done |
| 137 | + popdef([tags]) |
| 138 | + popdef([function]) |
| 139 | +]) |
| 140 | + |
| 141 | +dnl |
| 142 | +dnl AX_PROTOTYPE_REVERSE(list) |
| 143 | +dnl |
| 144 | +dnl Reverse the order of the <list> |
| 145 | +dnl |
| 146 | +AC_DEFUN([AX_PROTOTYPE_REVERSE],[ifelse($#,0,,$#,1,[[$1]],[AX_PROTOTYPE_REVERSE(builtin([shift],$@)),[$1]])]) |
| 147 | + |
| 148 | +dnl |
| 149 | +dnl AX_PROTOTYPE_SUBST(string, tag) |
| 150 | +dnl |
| 151 | +dnl Substitute all occurence of <tag> in <string> with <tag>_VAL. |
| 152 | +dnl Assumes that tag_VAL is a macro containing the value associated to tag. |
| 153 | +dnl |
| 154 | +AC_DEFUN([AX_PROTOTYPE_SUBST],[ifelse($2,,[$1],[AX_PROTOTYPE_SUBST(patsubst([$1],[$2],[$2[]_VAL]),builtin([shift],builtin([shift],$@)))])]) |
| 155 | + |
| 156 | +dnl |
| 157 | +dnl AX_PROTOTYPE_TAGS([tag, values, [tag, values ...]]) |
| 158 | +dnl |
| 159 | +dnl Generate a list of <tag> by skipping <values>. |
| 160 | +dnl |
| 161 | +AC_DEFUN([AX_PROTOTYPE_TAGS],[ifelse($1,,[],[$1, AX_PROTOTYPE_TAGS(builtin([shift],builtin([shift],$@)))])]) |
| 162 | + |
| 163 | +dnl |
| 164 | +dnl AX_PROTOTYPE_DEFINES(tags) |
| 165 | +dnl |
| 166 | +dnl Generate a AC_DEFINE(function_tag, tag_VAL) for each tag in <tags> list |
| 167 | +dnl Assumes that function is a macro containing the name of the function in upper case |
| 168 | +dnl and that tag_VAL is a macro containing the value associated to tag. |
| 169 | +dnl |
| 170 | +AC_DEFUN([AX_PROTOTYPE_DEFINES],[ifelse($1,,[], |
| 171 | + [AC_DEFINE(function[]_$1, $1_VAL) |
| 172 | + AC_SUBST(function[]_$1, "$1_VAL") |
| 173 | + AX_PROTOTYPE_DEFINES(builtin([shift],$@))])]) |
| 174 | + |
| 175 | +dnl |
| 176 | +dnl AX_PROTOTYPE_STATUS(tags) |
| 177 | +dnl |
| 178 | +dnl Generates a message suitable for argument to AC_MSG_* macros. For each tag |
| 179 | +dnl in the <tags> list the message tag => tag_VAL is generated. |
| 180 | +dnl Assumes that tag_VAL is a macro containing the value associated to tag. |
| 181 | +dnl |
| 182 | +AC_DEFUN([AX_PROTOTYPE_STATUS],[ifelse($1,,[],[$1 => $1_VAL AX_PROTOTYPE_STATUS(builtin([shift],$@))])]) |
| 183 | + |
| 184 | +dnl |
| 185 | +dnl AX_PROTOTYPE_EACH(tag, values) |
| 186 | +dnl |
| 187 | +dnl Call AX_PROTOTYPE_LOOP for each values and define the macro tag_VAL to |
| 188 | +dnl the current value. |
| 189 | +dnl |
| 190 | +AC_DEFUN([AX_PROTOTYPE_EACH],[ |
| 191 | + ifelse($2,, [ |
| 192 | + ], [ |
| 193 | + pushdef([$1_VAL], $2) |
| 194 | + AX_PROTOTYPE_LOOP(rest) |
| 195 | + popdef([$1_VAL]) |
| 196 | + AX_PROTOTYPE_EACH($1, builtin([shift], builtin([shift], $@))) |
| 197 | + ]) |
| 198 | +]) |
| 199 | + |
| 200 | +dnl |
| 201 | +dnl AX_PROTOTYPE_LOOP([tag, values, [tag, values ...]], code, include, function) |
| 202 | +dnl |
| 203 | +dnl If there is a tag/values pair, call AX_PROTOTYPE_EACH with it. |
| 204 | +dnl If there is no tag/values pair left, tries to compile the code and include |
| 205 | +dnl using AC_TRY_COMPILE. If it compiles, AC_DEFINE all the tags to their |
| 206 | +dnl current value and exit with success. |
| 207 | +dnl |
| 208 | +AC_DEFUN([AX_PROTOTYPE_LOOP],[ |
| 209 | + ifelse(builtin([eval], $# > 3), 1, |
| 210 | + [ |
| 211 | + pushdef([rest],[builtin([shift],builtin([shift],$@))]) |
| 212 | + AX_PROTOTYPE_EACH($2,$1) |
| 213 | + popdef([rest]) |
| 214 | + ], [ |
| 215 | + AC_MSG_CHECKING($3 AX_PROTOTYPE_STATUS(tags)) |
| 216 | +dnl |
| 217 | +dnl Activate fatal warnings if possible, gives better guess |
| 218 | +dnl |
| 219 | + ac_save_CPPFLAGS="$CPPFLAGS" |
| 220 | + if test "$GCC" = "yes" ; then CPPFLAGS="$CPPFLAGS -Werror" ; fi |
| 221 | + AC_TRY_COMPILE($2, $1, [ |
| 222 | + CPPFLAGS="$ac_save_CPPFLAGS" |
| 223 | + AC_MSG_RESULT(ok) |
| 224 | + AX_PROTOTYPE_DEFINES(tags) |
| 225 | + break; |
| 226 | + ], [ |
| 227 | + CPPFLAGS="$ac_save_CPPFLAGS" |
| 228 | + AC_MSG_RESULT(not ok) |
| 229 | + ]) |
| 230 | + ] |
| 231 | + ) |
| 232 | +]) |
0 commit comments