mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	This change causes the configure script to fail if the C compiler does not support both function attributes constructor and destructor. These were already required as modules cannot function without these attributes and Asterisk requires modules. This also has AST_GCC_ATTRIBUTE set a variable ax_cv_have_func_attribute_$1. This is the same variable name used by autoconf-archive's AX_GCC_FUNC_ATTRIBUTE, used for the same purpose. Change-Id: Id68e8a1447f2a6d707c54b56350e7bfdb33fb663
		
			
				
	
	
		
			273 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Asterisk -- An open source telephony toolkit.
 | |
|  *
 | |
|  * Copyright (C) 2008-2013, Digium, Inc.
 | |
|  *
 | |
|  * Kevin P. Fleming <kpfleming@digium.com>
 | |
|  *
 | |
|  * See http://www.asterisk.org for more information about
 | |
|  * the Asterisk project. Please do not directly contact
 | |
|  * any of the maintainers of this project for assistance;
 | |
|  * the project provides a web site, mailing lists and IRC
 | |
|  * channels for your use.
 | |
|  *
 | |
|  * This program is free software, distributed under the terms of
 | |
|  * the GNU General Public License Version 2. See the LICENSE file
 | |
|  * at the top of the source tree.
 | |
|  */
 | |
| 
 | |
| #ifndef __ASTERISK_OPTIONAL_API_H
 | |
| #define __ASTERISK_OPTIONAL_API_H
 | |
| 
 | |
| /*!
 | |
|  * \file
 | |
|  * \brief Optional API function macros
 | |
|  *
 | |
|  * Some Asterisk API functions are provided by loadable modules, thus,
 | |
|  * they may or may not be available at run time depending on whether the
 | |
|  * providing module has been loaded or not. In addition, there are some
 | |
|  * modules that are consumers of these APIs that *optionally* use them; they
 | |
|  * have only a part of their functionality dependent on the APIs, and can
 | |
|  * provide the remainder even if the APIs are not available.
 | |
|  *
 | |
|  * An example can be found in agi.h:
 | |
|  *
 | |
|  * \code
 | |
|  * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
 | |
|  *                  { return AST_OPTIONAL_API_UNAVAILABLE; });
 | |
|  * \endcode
 | |
|  *
 | |
|  * This defines the 'ast_agi_register' function as an optional API; if a
 | |
|  * consumer of this API is loaded when there is no provider of it, then
 | |
|  * calling this function will actually call the hidden stub, and return
 | |
|  * the value AST_OPTIONAL_API_UNAVAILABLE. This allows the consumer to
 | |
|  * safely know that the API is not available, and to avoid using any
 | |
|  * other APIs from the not-present provider.
 | |
|  *
 | |
|  * In addition to this declaration in the header file, the actual definition of
 | |
|  * the API function must use the AST_OPTIONAL_API_NAME macro to (possibly)
 | |
|  * modify the real name of the API function, depending on the specific
 | |
|  * implementation requirements. The corresponding example from res_agi.c:
 | |
|  *
 | |
|  * \code
 | |
|  * int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
 | |
|  * {
 | |
|  * ...
 | |
|  * }
 | |
|  * \endcode
 | |
|  *
 | |
|  * In the module providing the API, the AST_OPTIONAL_API macro must
 | |
|  * be informed that it should not build the hidden stub function or
 | |
|  * apply special aliases to the function prototype; this can be done
 | |
|  * by defining AST_API_MODULE just before including the header file
 | |
|  * containing the AST_OPTIONAL_API macro calls.
 | |
|  */
 | |
| 
 | |
| /*!
 | |
|  * \brief A common value for optional API stub functions to return
 | |
|  *
 | |
|  * This value is defined as INT_MIN, the minimum value for an integer
 | |
|  * (maximum negative value), which can be used by any optional API
 | |
|  * functions that return a signed integer value and would not be
 | |
|  * able to return such a value under normal circumstances.
 | |
|  */
 | |
| #define AST_OPTIONAL_API_UNAVAILABLE	INT_MIN
 | |
| 
 | |
| /*!
 | |
|  * \def AST_OPTIONAL_API_NAME(name)
 | |
|  * \brief Expands to the name of the implementation function.
 | |
|  */
 | |
| 
 | |
| /*!
 | |
|  * \def AST_OPTIONAL_API(result, name, proto, stub)
 | |
|  * \brief Declare an optional API function
 | |
|  *
 | |
|  * \param result The type of result the function returns
 | |
|  * \param name The name of the function
 | |
|  * \param proto The prototype (arguments) of the function
 | |
|  * \param stub The code block that will be used by the hidden stub when needed
 | |
|  *
 | |
|  * Example usage:
 | |
|  * \code
 | |
|  * AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
 | |
|  *                  { return AST_OPTIONAL_API_UNAVAILABLE; });
 | |
|  * \endcode
 | |
|  */
 | |
| 
 | |
| /*!
 | |
|  * \def AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)
 | |
|  * \brief Declare an optional API function with compiler attributes
 | |
|  *
 | |
|  * \param result The type of result the function returns
 | |
|  * \param attr Any compiler attributes to be applied to the function (without the __attribute__ wrapper)
 | |
|  * \param name The name of the function
 | |
|  * \param proto The prototype (arguments) of the function
 | |
|  * \param stub The code block that will be used by the hidden stub when needed
 | |
|  */
 | |
| 
 | |
| #if defined(OPTIONAL_API)
 | |
| 
 | |
| /*!
 | |
|  * \internal
 | |
|  * \brief Function pointer to an optional API function.
 | |
|  *
 | |
|  * Functions that are declared as optional may have any signature they want;
 | |
|  * they are cast to this type as needed. We don't use a \c void pointer, because
 | |
|  * technically data and function pointers are incompatible.
 | |
|  *
 | |
|  * \note
 | |
|  * The may_alias attribute is to avoid type punning/strict aliasing warnings
 | |
|  * with older GCC's.
 | |
|  */
 | |
| typedef void (*ast_optional_fn)(void) attribute_may_alias;
 | |
| 
 | |
| /*!
 | |
|  * \internal
 | |
|  * \brief Provide an implementation of an optional API.
 | |
|  *
 | |
|  * Any declared usages of this function are linked.
 | |
|  *
 | |
|  * \param symname Name of the provided function.
 | |
|  * \param impl Function pointer to the implementation function.
 | |
|  */
 | |
| void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
 | |
| 
 | |
| /*!
 | |
|  * \internal
 | |
|  * \brief Remove an implementation of an optional API.
 | |
|  *
 | |
|  * Any declared usages of this function are unlinked.
 | |
|  *
 | |
|  * \param symname Name of the provided function.
 | |
|  * \param impl Function pointer to the implementation function.
 | |
|  */
 | |
| void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
 | |
| 
 | |
| /*!
 | |
|  * \internal
 | |
|  * \brief Define a usage of an optional API.
 | |
|  *
 | |
|  * If the API has been provided, it will be linked into \a optional_ref.
 | |
|  * Otherwise, it will be linked to \a stub until an implementation is provided.
 | |
|  *
 | |
|  * \param symname Name of the function to use.
 | |
|  * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
 | |
|  * \param stub Stub function to link to when impl is not available.
 | |
|  * \param module Name of the module requesting the API.
 | |
|  */
 | |
| void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
 | |
| 	ast_optional_fn stub, const char *module);
 | |
| 
 | |
| /*!
 | |
|  * \internal
 | |
|  * \brief Remove a usage of an optional API.
 | |
|  *
 | |
|  * The \a optional_ref will be linked to the \a stub provided at use time,
 | |
|  * will no longer be updated if the API is provided/removed.
 | |
|  *
 | |
|  * \param symname Name of the function to use.
 | |
|  * \param optional_ref Pointer-to-function-pointer to link to impl/stub.
 | |
|  * \param module Name of the module requesting the API.
 | |
|  */
 | |
| void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
 | |
| 	const char *module);
 | |
| 
 | |
| #define AST_OPTIONAL_API_NAME(name) __##name
 | |
| 
 | |
| #define AST_OPTIONAL_API_INIT_IMPL(name)				\
 | |
| 	static void __attribute__((constructor)) __init__##name##_impl(void) { \
 | |
| 		ast_optional_api_provide(#name,				\
 | |
| 			(ast_optional_fn)AST_OPTIONAL_API_NAME(name));	\
 | |
| 	}								\
 | |
| 	static void __attribute__((destructor)) __dtor__##name##_impl(void) { \
 | |
| 		ast_optional_api_unprovide(#name,			\
 | |
| 			(ast_optional_fn)AST_OPTIONAL_API_NAME(name));	\
 | |
| 	}
 | |
| 
 | |
| #define AST_OPTIONAL_API_INIT_USER(name)				\
 | |
| 	static void __attribute__((constructor)) __init__##name(void) {	\
 | |
| 		ast_optional_api_use(#name, (ast_optional_fn *)&name,	\
 | |
| 			(ast_optional_fn)__stub__##name,		\
 | |
| 			AST_MODULE);					\
 | |
| 	}								\
 | |
| 	static void __attribute__((destructor)) __dtor__##name(void) {	\
 | |
| 		ast_optional_api_unuse(#name, (ast_optional_fn *)&name, \
 | |
| 			AST_MODULE);					\
 | |
| 	}
 | |
| 
 | |
| #define AST_OPTIONAL_API_IMPL(result, name, proto, stub)			\
 | |
| 	result AST_OPTIONAL_API_NAME(name) proto;			\
 | |
| 	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
 | |
| 	     name = AST_OPTIONAL_API_NAME(name);			\
 | |
| 	AST_OPTIONAL_API_INIT_IMPL(name)
 | |
| 
 | |
| #define AST_OPTIONAL_API_USER(result, name, proto, stub)			\
 | |
| 	static result __stub__##name proto stub;			\
 | |
| 	static attribute_unused						\
 | |
| 		typeof(__stub__##name) * name;				\
 | |
| 	AST_OPTIONAL_API_INIT_USER(name)
 | |
| 
 | |
| 
 | |
| /* AST_OPTIONAL_API_ATTR */
 | |
| #define AST_OPTIONAL_API_ATTR_IMPL(result, attr, name, proto, stub)		\
 | |
| 	result  __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
 | |
| 	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
 | |
| 	     name = AST_OPTIONAL_API_NAME(name);			\
 | |
| 	AST_OPTIONAL_API_INIT_IMPL(name)
 | |
| 
 | |
| #define AST_OPTIONAL_API_ATTR_USER(result, attr, name, proto, stub)		\
 | |
| 	static __attribute__((attr)) result __stub__##name proto stub;	\
 | |
| 	static attribute_unused	__attribute__((attr))			\
 | |
| 		typeof(__stub__##name) * name;				\
 | |
| 	AST_OPTIONAL_API_INIT_USER(name)
 | |
| 
 | |
| #else /* defined(OPTIONAL_API) */
 | |
| 
 | |
| /* Non-optional API */
 | |
| 
 | |
| #define AST_OPTIONAL_API_NAME(name) name
 | |
| 
 | |
| #define AST_OPTIONAL_API(result, name, proto, stub)	\
 | |
| 	result AST_OPTIONAL_API_NAME(name) proto
 | |
| 
 | |
| #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)	\
 | |
| 	result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
 | |
| 
 | |
| #endif /* defined(OPTIONAL_API) */
 | |
| 
 | |
| #endif /* __ASTERISK_OPTIONAL_API_H */
 | |
| 
 | |
| /*
 | |
|  * Some Asterisk sources are both consumer and provider of optional API's.  The
 | |
|  * following definitons are intentionally outside the include protected portion
 | |
|  * of this header so AST_OPTIONAL_API and AST_OPTIONAL_API_ATTR can be redefined
 | |
|  * each time the header is included.  This also ensures that AST_API_MODULE is
 | |
|  * undefined after every include of this header.
 | |
|  */
 | |
| #if defined(OPTIONAL_API)
 | |
| 
 | |
| #undef AST_OPTIONAL_API
 | |
| #undef AST_OPTIONAL_API_ATTR
 | |
| 
 | |
| #if defined(AST_API_MODULE)
 | |
| 
 | |
| #define AST_OPTIONAL_API(result, name, proto, stub) \
 | |
| 	AST_OPTIONAL_API_IMPL(result, name, proto, stub)
 | |
| 
 | |
| #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
 | |
| 	AST_OPTIONAL_API_ATTR_IMPL(result, attr, name, proto, stub)
 | |
| 
 | |
| #else
 | |
| 
 | |
| #define AST_OPTIONAL_API(result, name, proto, stub) \
 | |
| 	AST_OPTIONAL_API_USER(result, name, proto, stub)
 | |
| 
 | |
| #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
 | |
| 	AST_OPTIONAL_API_ATTR_USER(result, attr, name, proto, stub)
 | |
| 
 | |
| #endif /* defined(AST_API_MODULE) */
 | |
| 
 | |
| #endif /* defined(OPTIONAL_API) */
 | |
| 
 | |
| #undef AST_API_MODULE
 |