[network-manager-openvpn/th/include-nm-default-bgo761198: 1/8] shared: add "shared" files



commit 8ce299cbf9d1bf4d81cd8219f5c0fd4223be166e
Author: Thomas Haller <thaller redhat com>
Date:   Wed Jan 27 11:52:50 2016 +0100

    shared: add "shared" files
    
    Copied over from NetworkManager's source. These files constitute
    to a minimal availalble set of utility macros/functions. Copy them
    unmodified from NetworkManager source. They should not diverge
    from their origin and kept up to date.
    
    Instead of moving them to "common", place them to "shared" as that
    is like we do it in NetworkManager project.

 Makefile.am                  |    2 +-
 configure.ac                 |    1 +
 shared/Makefile.am           |    6 +
 shared/gsystem-local-alloc.h |  208 +++++++++++++++++++++++
 shared/nm-dbus-compat.h      |   74 +++++++++
 shared/nm-default.h          |  106 ++++++++++++
 shared/nm-glib.h             |  356 ++++++++++++++++++++++++++++++++++++++++
 shared/nm-macros-internal.h  |  374 ++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 1126 insertions(+), 1 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index cab3bab..01d420e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 AUTOMAKE_OPTIONS = foreign
 
-SUBDIRS = common src
+SUBDIRS = shared common src
 
 if WITH_GNOME
 SUBDIRS += auth-dialog properties po
diff --git a/configure.ac b/configure.ac
index 5c1cde7..787fcc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,5 +125,6 @@ properties/Makefile
 properties/tests/Makefile
 properties/tests/conf/Makefile
 po/Makefile.in
+shared/Makefile
 ])
 AC_OUTPUT
diff --git a/shared/Makefile.am b/shared/Makefile.am
new file mode 100644
index 0000000..7b84a4b
--- /dev/null
+++ b/shared/Makefile.am
@@ -0,0 +1,6 @@
+EXTRA_DIST = \
+     gsystem-local-alloc.h \
+     nm-dbus-compat.h \
+     nm-default.h \
+     nm-glib.h \
+     nm-macros-internal.h
diff --git a/shared/gsystem-local-alloc.h b/shared/gsystem-local-alloc.h
new file mode 100644
index 0000000..51b6251
--- /dev/null
+++ b/shared/gsystem-local-alloc.h
@@ -0,0 +1,208 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Colin Walters <walters verbum org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSYSTEM_LOCAL_ALLOC_H__
+#define __GSYSTEM_LOCAL_ALLOC_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GS_DEFINE_CLEANUP_FUNCTION(Type, name, func) \
+  static inline void name (void *v) \
+  { \
+    func (*(Type*)v); \
+  }
+
+#define GS_DEFINE_CLEANUP_FUNCTION0(Type, name, func) \
+  static inline void name (void *v) \
+  { \
+    if (*(Type*)v) \
+      func (*(Type*)v); \
+  }
+
+/* These functions shouldn't be invoked directly;
+ * they are stubs that:
+ * 1) Take a pointer to the location (typically itself a pointer).
+ * 2) Provide %NULL-safety where it doesn't exist already (e.g. g_object_unref)
+ */
+
+/**
+ * gs_free:
+ *
+ * Call g_free() on a variable location when it goes out of scope.
+ */
+#define gs_free __attribute__ ((cleanup(gs_local_free)))
+GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
+
+/**
+ * gs_unref_object:
+ *
+ * Call g_object_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_object_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_object __attribute__ ((cleanup(gs_local_obj_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref)
+
+/**
+ * gs_unref_variant:
+ *
+ * Call g_variant_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_variant_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_variant __attribute__ ((cleanup(gs_local_variant_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GVariant*, gs_local_variant_unref, g_variant_unref)
+
+/**
+ * gs_free_variant_iter:
+ *
+ * Call g_variant_iter_free() on a variable location when it goes out of
+ * scope.
+ */
+#define gs_free_variant_iter __attribute__ ((cleanup(gs_local_variant_iter_free)))
+GS_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, gs_local_variant_iter_free, g_variant_iter_free)
+
+/**
+ * gs_free_variant_builder:
+ *
+ * Call g_variant_builder_unref() on a variable location when it goes out of
+ * scope.
+ */
+#define gs_unref_variant_builder __attribute__ ((cleanup(gs_local_variant_builder_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GVariantBuilder*, gs_local_variant_builder_unref, g_variant_builder_unref)
+
+/**
+ * gs_unref_array:
+ *
+ * Call g_array_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_array __attribute__ ((cleanup(gs_local_array_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GArray*, gs_local_array_unref, g_array_unref)
+
+/**
+ * gs_unref_ptrarray:
+ *
+ * Call g_ptr_array_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_ptr_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_ptrarray __attribute__ ((cleanup(gs_local_ptrarray_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GPtrArray*, gs_local_ptrarray_unref, g_ptr_array_unref)
+
+/**
+ * gs_unref_hashtable:
+ *
+ * Call g_hash_table_unref() on a variable location when it goes out
+ * of scope.  Note that unlike g_hash_table_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_hashtable __attribute__ ((cleanup(gs_local_hashtable_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_unref)
+
+/**
+ * gs_free_list:
+ *
+ * Call g_list_free() on a variable location when it goes out
+ * of scope.
+ */
+#define gs_free_list __attribute__ ((cleanup(gs_local_free_list)))
+GS_DEFINE_CLEANUP_FUNCTION(GList*, gs_local_free_list, g_list_free)
+
+/**
+ * gs_free_slist:
+ *
+ * Call g_slist_free() on a variable location when it goes out
+ * of scope.
+ */
+#define gs_free_slist __attribute__ ((cleanup(gs_local_free_slist)))
+GS_DEFINE_CLEANUP_FUNCTION(GSList*, gs_local_free_slist, g_slist_free)
+
+/**
+ * gs_free_checksum:
+ *
+ * Call g_checksum_free() on a variable location when it goes out
+ * of scope.  Note that unlike g_checksum_free(), the variable may
+ * be %NULL.
+ */
+#define gs_free_checksum __attribute__ ((cleanup(gs_local_checksum_free)))
+GS_DEFINE_CLEANUP_FUNCTION0(GChecksum*, gs_local_checksum_free, g_checksum_free)
+
+/**
+ * gs_unref_bytes:
+ *
+ * Call g_bytes_unref() on a variable location when it goes out
+ * of scope.  Note that unlike g_bytes_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_bytes __attribute__ ((cleanup(gs_local_bytes_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GBytes*, gs_local_bytes_unref, g_bytes_unref)
+
+/**
+ * gs_strfreev:
+ *
+ * Call g_strfreev() on a variable location when it goes out of scope.
+ */
+#define gs_strfreev __attribute__ ((cleanup(gs_local_strfreev)))
+GS_DEFINE_CLEANUP_FUNCTION(char**, gs_local_strfreev, g_strfreev)
+
+/**
+ * gs_free_error:
+ *
+ * Call g_error_free() on a variable location when it goes out of scope.
+ */
+#define gs_free_error __attribute__ ((cleanup(gs_local_free_error)))
+GS_DEFINE_CLEANUP_FUNCTION0(GError*, gs_local_free_error, g_error_free)
+
+/**
+ * gs_unref_keyfile:
+ *
+ * Call g_key_file_unref() on a variable location when it goes out of scope.
+ */
+#define gs_unref_keyfile __attribute__ ((cleanup(gs_local_keyfile_unref)))
+GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_keyfile_unref, g_key_file_unref)
+
+static inline void
+gs_cleanup_close_fdp (int *fdp)
+{
+  int fd;
+
+  g_assert (fdp);
+  
+  fd = *fdp;
+  if (fd != -1)
+    (void) close (fd);
+}
+
+/**
+ * gs_fd_close:
+ *
+ * Call close() on a variable location when it goes out of scope.
+ */
+#define gs_fd_close __attribute__((cleanup(gs_cleanup_close_fdp)))
+
+G_END_DECLS
+
+#endif
diff --git a/shared/nm-dbus-compat.h b/shared/nm-dbus-compat.h
new file mode 100644
index 0000000..dd97b5f
--- /dev/null
+++ b/shared/nm-dbus-compat.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_DBUS_COMPAT_H__
+#define __NM_DBUS_COMPAT_H__
+
+/* Copied from <dbus/dbus-shared.h> */
+
+/* Bus names */
+
+/** The bus name used to talk to the bus itself. */
+#define DBUS_SERVICE_DBUS      "org.freedesktop.DBus"
+
+/* Paths */
+/** The object path used to talk to the bus itself. */
+#define DBUS_PATH_DBUS  "/org/freedesktop/DBus"
+/** The object path used in local/in-process-generated messages. */
+#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
+
+/* Interfaces, these #define don't do much other than
+ * catch typos at compile time
+ */
+/** The interface exported by the object with #DBUS_SERVICE_DBUS and #DBUS_PATH_DBUS */
+#define DBUS_INTERFACE_DBUS           "org.freedesktop.DBus"
+/** The interface supported by introspectable objects */
+#define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
+/** The interface supported by objects with properties */
+#define DBUS_INTERFACE_PROPERTIES     "org.freedesktop.DBus.Properties"
+/** The interface supported by most dbus peers */
+#define DBUS_INTERFACE_PEER           "org.freedesktop.DBus.Peer"
+
+/** This is a special interface whose methods can only be invoked
+ * by the local implementation (messages from remote apps aren't
+ * allowed to specify this interface).
+ */
+#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local"
+
+/* Owner flags */
+#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if 
requested */
+#define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
+#define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in 
the queue */
+
+/* Replies to request for a name */
+#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested 
name */
+#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has 
been placed in the queue */
+#define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
+#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
+
+/* Replies to releasing a name */
+#define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
+#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
+#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
+
+/* Replies to service starts */
+#define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
+#define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
+
+#endif  /* __NM_DBUS_COMPAT_H__ */
diff --git a/shared/nm-default.h b/shared/nm-default.h
new file mode 100644
index 0000000..de613af
--- /dev/null
+++ b/shared/nm-default.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_DEFAULT_H__
+#define __NM_DEFAULT_H__
+
+/* makefiles define NETWORKMANAGER_COMPILATION for compiling NetworkManager.
+ * Depending on which parts are compiled, different values are set. */
+#define NM_NETWORKMANAGER_COMPILATION_DEFAULT             0x0001
+#define NM_NETWORKMANAGER_COMPILATION_LIB                 0x0002
+
+#ifndef NETWORKMANAGER_COMPILATION
+/* For convenience, we don't require our Makefile.am to define
+ * -DNETWORKMANAGER_COMPILATION. As we now include this internal header,
+ *  we know we do a NETWORKMANAGER_COMPILATION. */
+#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_DEFAULT
+#endif
+
+/*****************************************************************************/
+
+/* always include these headers for our internal source files. */
+
+#include "nm-glib.h"
+#include "nm-version.h"
+#include "gsystem-local-alloc.h"
+
+/*****************************************************************************/
+
+#if (NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB
+
+#include <glib/gi18n-lib.h>
+
+#else
+
+#include <glib/gi18n.h>
+
+#endif /* NM_NETWORKMANAGER_COMPILATION_LIB */
+
+/*****************************************************************************/
+
+/**
+ * The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too
+ * convinient to miss and is effectively available in gcc and clang. So, just use it.
+ *
+ * Usually, one would include "stdbool.h" to get the "bool" define which aliases
+ * _Bool. We provide this define here, because we want to make use of it anywhere.
+ * (also, stdbool.h is again C99).
+ *
+ * Using _Bool has advantages over gboolean:
+ *
+ * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean
+ *   is a typedef for gint). Especially when having boolean fields in a struct, we can
+ *   thereby easily save some space.
+ *
+ * - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing
+ *   will not work:
+ *        gboolean v1 = 1;
+ *        gboolean v2 = 2;
+ *        g_assert_cmpint (v1, ==, v2); // will fail
+ *   For that, we often to use !! to coerce gboolean values to 0 or 1:
+ *        g_assert_cmpint (!!v2, ==, TRUE);
+ *   With _Bool type, this will be handled properly by the compiler.
+ *
+ * - For structs, we might want to safe even more space and use bitfields:
+ *       struct s1 {
+ *           gboolean v1:1;
+ *       };
+ *   But the problem here is that gboolean is signed, so that
+ *   v1 will be either 0 or -1 (not 1, TRUE). Thus, the following
+ *   fails:
+ *      struct s1 s = { .v1 = TRUE, };
+ *      g_assert_cmpint (s1.v1, ==, TRUE);
+ *   It will however work just fine with bool/_Bool while retaining the
+ *   notion of having a boolean value.
+ *
+ * Also, add the defines for "true" and "false". Those are nicely highlighted by the editor
+ * as special types, contrary to glib's "TRUE"/"FALSE".
+ */
+
+#ifndef bool
+#define bool _Bool
+#define true    1
+#define false   0
+#endif
+
+/*****************************************************************************/
+
+#endif /* __NM_DEFAULT_H__ */
diff --git a/shared/nm-glib.h b/shared/nm-glib.h
new file mode 100644
index 0000000..c75e91b
--- /dev/null
+++ b/shared/nm-glib.h
@@ -0,0 +1,356 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ */
+
+#ifndef __NM_GLIB_H__
+#define __NM_GLIB_H__
+
+
+#include <gio/gio.h>
+#include <string.h>
+
+#ifdef __clang__
+
+#undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+#undef G_GNUC_END_IGNORE_DEPRECATIONS
+
+#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+    _Pragma("clang diagnostic push") \
+    _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+
+#define G_GNUC_END_IGNORE_DEPRECATIONS \
+    _Pragma("clang diagnostic pop")
+
+#endif
+
+static inline void
+__g_type_ensure (GType type)
+{
+#if !GLIB_CHECK_VERSION(2,34,0)
+       if (G_UNLIKELY (type == (GType)-1))
+               g_error ("can't happen");
+#else
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+       g_type_ensure (type);
+       G_GNUC_END_IGNORE_DEPRECATIONS;
+#endif
+}
+#define g_type_ensure __g_type_ensure
+
+#if !GLIB_CHECK_VERSION(2,34,0)
+
+#define g_clear_pointer(pp, destroy) \
+    G_STMT_START {                                                                 \
+        G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer));                       \
+        /* Only one access, please */                                              \
+        gpointer *_pp = (gpointer *) (pp);                                         \
+        gpointer _p;                                                               \
+        /* This assignment is needed to avoid a gcc warning */                     \
+        GDestroyNotify _destroy = (GDestroyNotify) (destroy);                      \
+                                                                                   \
+        _p = *_pp;                                                                 \
+        if (_p)                                                                    \
+        {                                                                          \
+            *_pp = NULL;                                                           \
+            _destroy (_p);                                                         \
+        }                                                                          \
+    } G_STMT_END
+
+/* These are used to clean up the output of test programs; we can just let
+ * them no-op in older glib.
+ */
+#define g_test_expect_message(log_domain, log_level, pattern)
+#define g_test_assert_expected_messages()
+
+#else
+
+/* We build with -DGLIB_MAX_ALLOWED_VERSION set to 2.32 to make sure we don't
+ * accidentally use new API that we shouldn't. But we don't want warnings for
+ * the APIs that we emulate above.
+ */
+
+#define g_test_expect_message(domain, level, format...) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_test_expect_message (domain, level, format); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+
+#define g_test_assert_expected_messages_internal(domain, file, line, func) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_test_assert_expected_messages_internal (domain, file, line, func); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+
+#endif
+
+
+#if GLIB_CHECK_VERSION (2, 35, 0)
+/* For glib >= 2.36, g_type_init() is deprecated.
+ * But since 2.35.1 (7c42ab23b55c43ab96d0ac2124b550bf1f49c1ec) this function
+ * does nothing. Replace the call with empty statement. */
+#define nm_g_type_init()     G_STMT_START { (void) 0; } G_STMT_END
+#else
+#define nm_g_type_init()     G_STMT_START { g_type_init (); } G_STMT_END
+#endif
+
+
+/* g_test_initialized() is only available since glib 2.36. */
+#if !GLIB_CHECK_VERSION (2, 36, 0)
+#define g_test_initialized() (g_test_config_vars->test_initialized)
+#endif
+
+/* Rumtime check for glib version. First do a compile time check which
+ * (if satisfied) shortcuts the runtime check. */
+#define nm_glib_check_version(major, minor, micro) \
+    (   GLIB_CHECK_VERSION ((major), (minor), (micro)) \
+     || (   (   glib_major_version > (major)) \
+         || (   glib_major_version == (major) \
+             && glib_minor_version > (minor)) \
+         || (   glib_major_version == (major) \
+             && glib_minor_version == (minor) \
+             && glib_micro_version >= (micro))))
+
+/* g_test_skip() is only available since glib 2.38. Add a compatibility wrapper. */
+inline static void
+__nmtst_g_test_skip (const gchar *msg)
+{
+#if GLIB_CHECK_VERSION (2, 38, 0)
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+       g_test_skip (msg);
+       G_GNUC_END_IGNORE_DEPRECATIONS
+#else
+       g_debug ("%s", msg);
+#endif
+}
+#define g_test_skip __nmtst_g_test_skip
+
+
+/* g_test_add_data_func_full() is only available since glib 2.34. Add a compatibility wrapper. */
+inline static void
+__g_test_add_data_func_full (const char     *testpath,
+                             gpointer        test_data,
+                             GTestDataFunc   test_func,
+                             GDestroyNotify  data_free_func)
+{
+#if GLIB_CHECK_VERSION (2, 34, 0)
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+       g_test_add_data_func_full (testpath, test_data, test_func, data_free_func);
+       G_GNUC_END_IGNORE_DEPRECATIONS
+#else
+       g_return_if_fail (testpath != NULL);
+       g_return_if_fail (testpath[0] == '/');
+       g_return_if_fail (test_func != NULL);
+
+       g_test_add_vtable (testpath, 0, test_data, NULL,
+                          (GTestFixtureFunc) test_func,
+                          (GTestFixtureFunc) data_free_func);
+#endif
+}
+#define g_test_add_data_func_full __g_test_add_data_func_full
+
+
+#if !GLIB_CHECK_VERSION (2, 34, 0)
+#define G_DEFINE_QUARK(QN, q_n)               \
+GQuark                                        \
+q_n##_quark (void)                            \
+{                                             \
+       static GQuark q;                          \
+                                              \
+       if G_UNLIKELY (q == 0)                    \
+               q = g_quark_from_static_string (#QN); \
+                                              \
+       return q;                                 \
+}
+#endif
+
+
+static inline gboolean
+nm_g_hash_table_replace (GHashTable *hash, gpointer key, gpointer value)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_replace (hash, key, value);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_replace (hash, key, value);
+       return !contained;
+#endif
+}
+
+static inline gboolean
+nm_g_hash_table_insert (GHashTable *hash, gpointer key, gpointer value)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_insert (hash, key, value);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_insert (hash, key, value);
+       return !contained;
+#endif
+}
+
+static inline gboolean
+nm_g_hash_table_add (GHashTable *hash, gpointer key)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_add (hash, key);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_add (hash, key);
+       return !contained;
+#endif
+}
+
+#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
+static inline void
+_nm_g_ptr_array_insert (GPtrArray *array,
+                        gint       index_,
+                        gpointer   data)
+{
+       g_return_if_fail (array);
+       g_return_if_fail (index_ >= -1);
+       g_return_if_fail (index_ <= (gint) array->len);
+
+       g_ptr_array_add (array, data);
+
+       if (index_ != -1 && index_ != (gint) (array->len - 1)) {
+               memmove (&(array->pdata[index_ + 1]),
+                        &(array->pdata[index_]),
+                        (array->len - index_ - 1) * sizeof (gpointer));
+               array->pdata[index_] = data;
+       }
+}
+#endif
+#if !GLIB_CHECK_VERSION(2, 40, 0)
+#define g_ptr_array_insert(array, index, data) G_STMT_START { _nm_g_ptr_array_insert (array, index, data); } 
G_STMT_END
+#else
+#define g_ptr_array_insert(array, index, data) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_ptr_array_insert (array, index, data); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+#endif
+
+
+#if !GLIB_CHECK_VERSION (2, 40, 0)
+inline static gboolean
+_g_key_file_save_to_file (GKeyFile     *key_file,
+                          const gchar  *filename,
+                          GError      **error)
+{
+       gchar *contents;
+       gboolean success;
+       gsize length;
+
+       g_return_val_if_fail (key_file != NULL, FALSE);
+       g_return_val_if_fail (filename != NULL, FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+       contents = g_key_file_to_data (key_file, &length, NULL);
+       g_assert (contents != NULL);
+
+       success = g_file_set_contents (filename, contents, length, error);
+       g_free (contents);
+
+       return success;
+}
+#define g_key_file_save_to_file(key_file, filename, error) \
+       _g_key_file_save_to_file (key_file, filename, error)
+#else
+#define g_key_file_save_to_file(key_file, filename, error) \
+       ({ \
+               gboolean _success; \
+               \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               _success = g_key_file_save_to_file (key_file, filename, error); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+               _success; \
+       })
+#endif
+
+
+#if GLIB_CHECK_VERSION (2, 36, 0)
+#define g_credentials_get_unix_pid(creds, error) \
+       G_GNUC_EXTENSION ({ \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+                       (g_credentials_get_unix_pid) ((creds), (error)); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       })
+#else
+#define g_credentials_get_unix_pid(creds, error) \
+       G_GNUC_EXTENSION ({ \
+               struct ucred *native_creds; \
+                \
+               native_creds = g_credentials_get_native ((creds), G_CREDENTIALS_TYPE_LINUX_UCRED); \
+               g_assert (native_creds); \
+               native_creds->pid; \
+       })
+#endif
+
+
+#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
+static inline gpointer *
+_nm_g_hash_table_get_keys_as_array (GHashTable *hash_table,
+                                    guint      *length)
+{
+       GHashTableIter iter;
+       gpointer key, *ret;
+       guint i = 0;
+
+       g_return_val_if_fail (hash_table, NULL);
+
+       ret = g_new0 (gpointer, g_hash_table_size (hash_table) + 1);
+       g_hash_table_iter_init (&iter, hash_table);
+
+       while (g_hash_table_iter_next (&iter, &key, NULL))
+               ret[i++] = key;
+
+       ret[i] = NULL;
+
+       if (length)
+               *length = i;
+
+       return ret;
+}
+#endif
+#if !GLIB_CHECK_VERSION(2, 40, 0)
+#define g_hash_table_get_keys_as_array(hash_table, length) \
+       G_GNUC_EXTENSION ({ \
+               _nm_g_hash_table_get_keys_as_array (hash_table, length); \
+       })
+#else
+#define g_hash_table_get_keys_as_array(hash_table, length) \
+       G_GNUC_EXTENSION ({ \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+                       (g_hash_table_get_keys_as_array) ((hash_table), (length)); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       })
+#endif
+
+#endif  /* __NM_GLIB_H__ */
diff --git a/shared/nm-macros-internal.h b/shared/nm-macros-internal.h
new file mode 100644
index 0000000..c178758
--- /dev/null
+++ b/shared/nm-macros-internal.h
@@ -0,0 +1,374 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_MACROS_INTERNAL_H__
+#define __NM_MACROS_INTERNAL_H__
+
+#include "nm-default.h"
+
+/********************************************************/
+
+/* http://stackoverflow.com/a/11172679 */
+#define  _NM_UTILS_MACRO_FIRST(...)                           __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, 
throwaway)
+#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...)             first
+
+#define  _NM_UTILS_MACRO_REST(...)                            
__NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__)
+#define __NM_UTILS_MACRO_REST_HELPER(qty, ...)                __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__)
+#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...)               __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__)
+#define __NM_UTILS_MACRO_REST_HELPER_ONE(first)
+#define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...)    , __VA_ARGS__
+#define __NM_UTILS_MACRO_REST_NUM(...) \
+    __NM_UTILS_MACRO_REST_SELECT_20TH(__VA_ARGS__, \
+                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
+                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
+                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
+                TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
+#define __NM_UTILS_MACRO_REST_SELECT_20TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, 
a16, a17, a18, a19, a20, ...) a20
+
+/********************************************************/
+
+/* http://stackoverflow.com/a/2124385/354393 */
+
+#define NM_NARG(...) \
+         _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
+#define _NM_NARG(...) \
+         _NM_NARG_ARG_N(__VA_ARGS__)
+#define _NM_NARG_ARG_N( \
+          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+         _61,_62,_63,N,...) N
+#define _NM_NARG_RSEQ_N() \
+         63,62,61,60,                   \
+         59,58,57,56,55,54,53,52,51,50, \
+         49,48,47,46,45,44,43,42,41,40, \
+         39,38,37,36,35,34,33,32,31,30, \
+         29,28,27,26,25,24,23,22,21,20, \
+         19,18,17,16,15,14,13,12,11,10, \
+         9,8,7,6,5,4,3,2,1,0
+
+/********************************************************/
+
+#if defined (__GNUC__)
+#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(GCC diagnostic ignored warning)
+#elif defined (__clang__)
+#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(clang diagnostic ignored warning)
+#endif
+
+/* you can only suppress a specific warning that the compiler
+ * understands. Otherwise you will get another compiler warning
+ * about invalid pragma option.
+ * It's not that bad however, because gcc and clang often have the
+ * same name for the same warning. */
+
+#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define NM_PRAGMA_WARNING_DISABLE(warning) \
+        _Pragma("GCC diagnostic push") \
+        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
+#elif defined (__clang__)
+#define NM_PRAGMA_WARNING_DISABLE(warning) \
+        _Pragma("clang diagnostic push") \
+        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
+#else
+#define NM_PRAGMA_WARNING_DISABLE(warning)
+#endif
+
+#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define NM_PRAGMA_WARNING_REENABLE \
+    _Pragma("GCC diagnostic pop")
+#elif defined (__clang__)
+#define NM_PRAGMA_WARNING_REENABLE \
+    _Pragma("clang diagnostic pop")
+#else
+#define NM_PRAGMA_WARNING_REENABLE
+#endif
+
+/********************************************************/
+
+/* macro to return strlen() of a compile time string. */
+#define STRLEN(str)     ( sizeof ("" str) - 1 )
+
+#define NM_SET_OUT(out_val, value) \
+       G_STMT_START { \
+               typeof(*(out_val)) *_out_val = (out_val); \
+               \
+               if (_out_val) { \
+                       *_out_val = (value); \
+               } \
+       } G_STMT_END
+
+/********************************************************/
+
+#define _NM_IN_SET_EVAL_1(op, x, y1)                              \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_2(op, x, y1, y2)                          \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_3(op, x, y1, y2, y3)                      \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_4(op, x, y1, y2, y3, y4)                  \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+         op (_x == (y4))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_5(op, x, y1, y2, y3, y4, y5)              \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+         op (_x == (y4))                                          \
+         op (_x == (y5))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_N2(op, x, n, ...)        _NM_IN_SET_EVAL_##n(op, x, __VA_ARGS__)
+#define _NM_IN_SET_EVAL_N(op, x, n, ...)         _NM_IN_SET_EVAL_N2(op, x, n, __VA_ARGS__)
+
+/* Beware that this does short-circuit evaluation (use "||" instead of "|")
+ * which has a possibly unexpected non-function-like behavior.
+ * Use NM_IN_SET_SE if you need all arguments to be evaluted. */
+#define NM_IN_SET(x, ...)               _NM_IN_SET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+
+/* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do
+ * short-circuit evaluation, which can make a difference if the arguments have
+ * side-effects. */
+#define NM_IN_SET_SE(x, ...)            _NM_IN_SET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+
+/*****************************************************************************/
+
+#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
+       (cond) ? (prefix) : "", \
+       (cond) ? (str) : (str_else), \
+       (cond) ? (suffix) : ""
+#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)")
+
+/*****************************************************************************/
+
+#if NM_MORE_ASSERTS
+#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
+#else
+#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END
+#endif
+
+/*****************************************************************************/
+
+#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
+typedef enum { \
+       _PROPERTY_ENUMS_0, \
+       __VA_ARGS__ \
+       _PROPERTY_ENUMS_LAST, \
+} _PropertyEnums; \
+static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, }; \
+static inline void \
+_notify (obj_type *obj, _PropertyEnums prop) \
+{ \
+       nm_assert (G_IS_OBJECT (obj)); \
+       nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
+       g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
+}
+
+/*****************************************************************************/
+
+static inline gboolean
+nm_clear_g_source (guint *id)
+{
+       if (id && *id) {
+               g_source_remove (*id);
+               *id = 0;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_signal_handler (gpointer self, gulong *id)
+{
+       if (id && *id) {
+               g_signal_handler_disconnect (self, *id);
+               *id = 0;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_variant (GVariant **variant)
+{
+       if (variant && *variant) {
+               g_variant_unref (*variant);
+               *variant = NULL;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_cancellable (GCancellable **cancellable)
+{
+       if (cancellable && *cancellable) {
+               g_cancellable_cancel (*cancellable);
+               g_object_unref (*cancellable);
+               *cancellable = NULL;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/*****************************************************************************/
+
+/* Determine whether @x is a power of two (@x being an integer type).
+ * For the special cases @x equals zero or one, it also returns true.
+ * For negative @x, always returns FALSE. That only applies, if the data
+ * type of @x is signed. */
+#define nm_utils_is_power_of_two(x) ({ \
+               typeof(x) __x = (x); \
+               \
+               /* Check if the value is negative. In that case, return FALSE.
+                * The first expression is a compile time constant, depending on whether
+                * the type is signed. The second expression is a clumsy way for (__x >= 0),
+                * which causes a compiler warning for unsigned types. */ \
+                   ( ( ((typeof(__x)) -1) > ((typeof(__x)) 0) ) || (__x > 0) || (__x == 0) ) \
+                && ((__x & (__x - 1)) == 0); \
+       })
+
+/*****************************************************************************/
+
+/* check if @flags has exactly one flag (@check) set. You should call this
+ * only with @check being a compile time constant and a power of two. */
+#define NM_FLAGS_HAS(flags, check)  \
+    ( (G_STATIC_ASSERT_EXPR ( ((check) != 0) && ((check) & ((check)-1)) == 0 )), (NM_FLAGS_ANY ((flags), 
(check))) )
+
+#define NM_FLAGS_ANY(flags, check)  ( ( ((flags) & (check)) != 0       ) ? TRUE : FALSE )
+#define NM_FLAGS_ALL(flags, check)  ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE )
+
+#define NM_FLAGS_SET(flags, val)  ({ \
+               const typeof(flags) _flags = (flags); \
+               const typeof(flags) _val = (val); \
+               \
+               _flags | _val; \
+       })
+
+#define NM_FLAGS_UNSET(flags, val)  ({ \
+               const typeof(flags) _flags = (flags); \
+               const typeof(flags) _val = (val); \
+               \
+               _flags & (~_val); \
+       })
+
+#define NM_FLAGS_ASSIGN(flags, val, assign)  ({ \
+               const typeof(flags) _flags = (flags); \
+               const typeof(flags) _val = (val); \
+               \
+               (assign) \
+                       ? _flags | (_val) \
+                       : _flags & (~_val); \
+       })
+
+/*****************************************************************************/
+
+#define _NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, ORIG_FUNC, VERSIONED_FUNC, ARGS_TYPED, ARGS) \
+RETURN_TYPE VERSIONED_FUNC ARGS_TYPED; \
+RETURN_TYPE VERSIONED_FUNC ARGS_TYPED \
+{ \
+    return ORIG_FUNC ARGS; \
+} \
+RETURN_TYPE ORIG_FUNC ARGS_TYPED; \
+__asm__(".symver "G_STRINGIFY(VERSIONED_FUNC)", "G_STRINGIFY(ORIG_FUNC)"@"G_STRINGIFY(VERSION))
+
+#define NM_BACKPORT_SYMBOL(VERSION, RETURN_TYPE, FUNC, ARGS_TYPED, ARGS) \
+_NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, FUNC, _##FUNC##_##VERSION, ARGS_TYPED, ARGS)
+
+/*****************************************************************************/
+
+static inline char *
+nm_strstrip (char *str)
+{
+       /* g_strstrip doesn't like NULL. */
+       return str ? g_strstrip (str) : NULL;
+}
+
+/*****************************************************************************/
+
+static inline guint
+nm_encode_version (guint major, guint minor, guint micro) {
+       /* analog to the preprocessor macro NM_ENCODE_VERSION(). */
+       return (major << 16) | (minor << 8) | micro;
+}
+
+static inline void
+nm_decode_version (guint version, guint *major, guint *minor, guint *micro) {
+       *major = (version & 0xFFFF0000u) >> 16;
+       *minor = (version & 0x0000FF00u) >>  8;
+       *micro = (version & 0x000000FFu);
+}
+/*****************************************************************************/
+
+#define nm_sprintf_buf(buf, format, ...) ({ \
+               char * _buf = (buf); \
+               \
+               /* some static assert trying to ensure that the buffer is statically allocated.
+                * It disallows a buffer size of sizeof(gpointer) to catch that. */ \
+               G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \
+               g_snprintf (_buf, sizeof (buf), \
+                           ""format"", __VA_ARGS__); \
+               _buf; \
+       })
+
+#define nm_sprintf_bufa(n_elements, format, ...) \
+       ({ \
+               char *_buf; \
+               \
+               G_STATIC_ASSERT (sizeof (char[MAX ((n_elements), 1)]) == (n_elements)); \
+               _buf = g_alloca (n_elements); \
+               g_snprintf (_buf, n_elements, \
+                           ""format"", __VA_ARGS__); \
+               _buf; \
+       })
+
+/*****************************************************************************/
+
+#endif /* __NM_MACROS_INTERNAL_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]