williamr@2: /* GLIB - Library of useful routines for C programming williamr@2: * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald williamr@2: * williamr@2: * This library is free software; you can redistribute it and/or williamr@2: * modify it under the terms of the GNU Lesser General Public williamr@2: * License as published by the Free Software Foundation; either williamr@2: * version 2 of the License, or (at your option) any later version. williamr@2: * williamr@2: * This library is distributed in the hope that it will be useful, williamr@2: * but WITHOUT ANY WARRANTY; without even the implied warranty of williamr@2: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU williamr@2: * Lesser General Public License for more details. williamr@2: * williamr@2: * You should have received a copy of the GNU Lesser General Public williamr@2: * License along with this library; if not, write to the williamr@2: * Free Software Foundation, Inc., 59 Temple Place - Suite 330, williamr@2: * Boston, MA 02111-1307, USA. williamr@2: */ williamr@2: williamr@2: /* williamr@2: * Modified by the GLib Team and others 1997-2000. See the AUTHORS williamr@2: * file for a list of people on the GLib Team. See the ChangeLog williamr@2: * files for a list of changes. These files are distributed with williamr@2: * GLib at ftp://ftp.gtk.org/pub/gtk/. williamr@2: */ williamr@2: williamr@2: /* This file must not include any other glib header file and must thus williamr@2: * not refer to variables from glibconfig.h williamr@2: */ williamr@2: williamr@2: #ifndef __G_MACROS_H__ williamr@2: #define __G_MACROS_H__ williamr@2: williamr@2: /* We include stddef.h to get the system's definition of NULL williamr@2: */ williamr@2: #include williamr@2: williamr@2: /* Here we provide G_GNUC_EXTENSION as an alias for __extension__, williamr@2: * where this is valid. This allows for warningless compilation of williamr@2: * "long long" types even in the presence of '-ansi -pedantic'. williamr@2: */ williamr@2: #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) williamr@2: # define G_GNUC_EXTENSION __extension__ williamr@2: #else williamr@2: # define G_GNUC_EXTENSION williamr@2: #endif williamr@2: williamr@2: /* Provide macros to feature the GCC function attribute. williamr@2: */ williamr@2: #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) williamr@2: #define G_GNUC_PURE \ williamr@2: __attribute__((__pure__)) williamr@2: #define G_GNUC_MALLOC \ williamr@2: __attribute__((__malloc__)) williamr@2: #else williamr@2: #define G_GNUC_PURE williamr@2: #define G_GNUC_MALLOC williamr@2: #endif williamr@2: williamr@2: #if __GNUC__ >= 4 williamr@2: #define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) williamr@2: #else williamr@2: #define G_GNUC_NULL_TERMINATED williamr@2: #endif williamr@2: williamr@2: #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) williamr@2: #define G_GNUC_PRINTF( format_idx, arg_idx ) \ williamr@2: __attribute__((__format__ (__printf__, format_idx, arg_idx))) williamr@2: #define G_GNUC_SCANF( format_idx, arg_idx ) \ williamr@2: __attribute__((__format__ (__scanf__, format_idx, arg_idx))) williamr@2: #define G_GNUC_FORMAT( arg_idx ) \ williamr@2: __attribute__((__format_arg__ (arg_idx))) williamr@2: #define G_GNUC_NORETURN \ williamr@2: __attribute__((__noreturn__)) williamr@2: #define G_GNUC_CONST \ williamr@2: __attribute__((__const__)) williamr@2: #define G_GNUC_UNUSED \ williamr@2: __attribute__((__unused__)) williamr@2: #define G_GNUC_NO_INSTRUMENT \ williamr@2: __attribute__((__no_instrument_function__)) williamr@2: #else /* !__GNUC__ */ williamr@2: #define G_GNUC_PRINTF( format_idx, arg_idx ) williamr@2: #define G_GNUC_SCANF( format_idx, arg_idx ) williamr@2: #define G_GNUC_FORMAT( arg_idx ) williamr@2: #define G_GNUC_NORETURN williamr@2: #define G_GNUC_CONST williamr@2: #define G_GNUC_UNUSED williamr@2: #define G_GNUC_NO_INSTRUMENT williamr@2: #endif /* !__GNUC__ */ williamr@2: williamr@2: #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) williamr@2: #define G_GNUC_DEPRECATED \ williamr@2: __attribute__((__deprecated__)) williamr@2: #else williamr@2: #define G_GNUC_DEPRECATED williamr@2: #endif /* __GNUC__ */ williamr@2: williamr@2: #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) williamr@2: #define G_GNUC_WARN_UNUSED_RESULT \ williamr@2: __attribute__((warn_unused_result)) williamr@2: #else williamr@2: #define G_GNUC_WARN_UNUSED_RESULT williamr@2: #endif /* __GNUC__ */ williamr@2: williamr@2: /* Wrap the gcc __PRETTY_FUNCTION__ and __FUNCTION__ variables with williamr@2: * macros, so we can refer to them as strings unconditionally. williamr@2: * usage not-recommended since gcc-3.0 williamr@2: */ williamr@2: #if defined (__GNUC__) && (__GNUC__ < 3) williamr@2: #define G_GNUC_FUNCTION __FUNCTION__ williamr@2: #define G_GNUC_PRETTY_FUNCTION __PRETTY_FUNCTION__ williamr@2: #else /* !__GNUC__ */ williamr@2: #define G_GNUC_FUNCTION "" williamr@2: #define G_GNUC_PRETTY_FUNCTION "" williamr@2: #endif /* !__GNUC__ */ williamr@2: williamr@2: #define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string) williamr@2: #define G_STRINGIFY_ARG(contents) #contents williamr@2: williamr@2: /* Provide a string identifying the current code position */ williamr@2: #if defined(__GNUC__) && (__GNUC__ < 3) && !defined(__cplusplus) williamr@2: # define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()" williamr@2: #else williamr@2: # define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) williamr@2: #endif williamr@2: williamr@2: /* Provide a string identifying the current function, non-concatenatable */ williamr@2: #if defined (__GNUC__) williamr@2: # define G_STRFUNC ((const char*) (__PRETTY_FUNCTION__)) williamr@2: #elif defined (G_HAVE_ISO_VARARGS) williamr@2: # define G_STRFUNC ((const char*) (__func__)) williamr@2: #else williamr@2: # define G_STRFUNC ((const char*) ("???")) williamr@2: #endif williamr@2: williamr@2: /* Guard C code in headers, while including them from C++ */ williamr@2: #ifdef __cplusplus williamr@2: # define G_BEGIN_DECLS extern "C" { williamr@2: # define G_END_DECLS } williamr@2: #else williamr@2: # define G_BEGIN_DECLS williamr@2: # define G_END_DECLS williamr@2: #endif williamr@2: williamr@2: /* Provide definitions for some commonly used macros. williamr@2: * Some of them are only provided if they haven't already williamr@2: * been defined. It is assumed that if they are already williamr@2: * defined then the current definition is correct. williamr@2: */ williamr@2: #ifndef NULL williamr@2: # ifdef __cplusplus williamr@2: # define NULL (0L) williamr@2: # else /* !__cplusplus */ williamr@2: # define NULL ((void*) 0) williamr@2: # endif /* !__cplusplus */ williamr@2: #endif williamr@2: williamr@2: #ifndef FALSE williamr@2: #define FALSE (0) williamr@2: #endif williamr@2: williamr@2: #ifndef TRUE williamr@2: #define TRUE (!FALSE) williamr@2: #endif williamr@2: williamr@2: #undef MAX williamr@2: #define MAX(a, b) (((a) > (b)) ? (a) : (b)) williamr@2: williamr@2: #undef MIN williamr@2: #define MIN(a, b) (((a) < (b)) ? (a) : (b)) williamr@2: williamr@2: #undef ABS williamr@2: #define ABS(a) (((a) < 0) ? -(a) : (a)) williamr@2: williamr@2: #undef CLAMP williamr@2: #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) williamr@2: williamr@2: /* Count the number of elements in an array. The array must be defined williamr@2: * as such; using this with a dynamically allocated array will give williamr@2: * incorrect results. williamr@2: */ williamr@2: #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) williamr@2: williamr@2: /* Macros by analogy to GINT_TO_POINTER, GPOINTER_TO_INT williamr@2: */ williamr@2: #define GPOINTER_TO_SIZE(p) ((gsize) (p)) williamr@2: #define GSIZE_TO_POINTER(s) ((gpointer) (gsize) (s)) williamr@2: williamr@2: /* Provide convenience macros for handling structure williamr@2: * fields through their offsets. williamr@2: */ williamr@2: #define G_STRUCT_OFFSET(struct_type, member) \ williamr@2: ((glong) ((guint8*) &((struct_type*) 0)->member)) williamr@2: #define G_STRUCT_MEMBER_P(struct_p, struct_offset) \ williamr@2: ((gpointer) ((guint8*) (struct_p) + (glong) (struct_offset))) williamr@2: #define G_STRUCT_MEMBER(member_type, struct_p, struct_offset) \ williamr@2: (*(member_type*) G_STRUCT_MEMBER_P ((struct_p), (struct_offset))) williamr@2: williamr@2: /* Provide simple macro statement wrappers (adapted from Perl): williamr@2: * G_STMT_START { statements; } G_STMT_END; williamr@2: * can be used as a single statement, as in williamr@2: * if (x) G_STMT_START { ... } G_STMT_END; else ... williamr@2: * williamr@2: * When GCC is compiling C code in non-ANSI mode, it will use the williamr@2: * compiler __extension__ to wrap the statements wihin `({' and '})' braces. williamr@2: * When compiling on platforms where configure has defined williamr@2: * HAVE_DOWHILE_MACROS, statements will be wrapped with `do' and `while (0)'. williamr@2: * For any other platforms (SunOS4 is known to have this issue), wrap the williamr@2: * statements with `if (1)' and `else (void) 0'. williamr@2: */ williamr@2: #if !(defined (G_STMT_START) && defined (G_STMT_END)) williamr@2: # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) williamr@2: # define G_STMT_START (void) __extension__ ( williamr@2: # define G_STMT_END ) williamr@2: # else /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */ williamr@2: # if defined (HAVE_DOWHILE_MACROS) williamr@2: # define G_STMT_START do williamr@2: # define G_STMT_END while (0) williamr@2: # else /* !HAVE_DOWHILE_MACROS */ williamr@2: # define G_STMT_START if (1) williamr@2: # define G_STMT_END else (void) 0 williamr@2: # endif /* !HAVE_DOWHILE_MACROS */ williamr@2: # endif /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */ williamr@2: #endif williamr@2: williamr@2: /* Allow the app programmer to select whether or not return values williamr@2: * (usually char*) are const or not. Don't try using this feature for williamr@2: * functions with C++ linkage. williamr@2: */ williamr@2: #ifdef G_DISABLE_CONST_RETURNS williamr@2: #define G_CONST_RETURN williamr@2: #else williamr@2: #define G_CONST_RETURN const williamr@2: #endif williamr@2: williamr@2: /* williamr@2: * The G_LIKELY and G_UNLIKELY macros let the programmer give hints to williamr@2: * the compiler about the expected result of an expression. Some compilers williamr@2: * can use this information for optimizations. williamr@2: * williamr@2: * The _G_BOOLEAN_EXPR macro is intended to trigger a gcc warning when williamr@2: * putting assignments in g_return_if_fail (). williamr@2: */ williamr@2: #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) williamr@2: #define _G_BOOLEAN_EXPR(expr) \ williamr@2: __extension__ ({ \ williamr@2: int _g_boolean_var_; \ williamr@2: if (expr) \ williamr@2: _g_boolean_var_ = 1; \ williamr@2: else \ williamr@2: _g_boolean_var_ = 0; \ williamr@2: _g_boolean_var_; \ williamr@2: }) williamr@2: #define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1)) williamr@2: #define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0)) williamr@2: #else williamr@2: #define G_LIKELY(expr) (expr) williamr@2: #define G_UNLIKELY(expr) (expr) williamr@2: #endif williamr@2: williamr@2: #endif /* __G_MACROS_H__ */