summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-06-16 20:26:43 +0200
committerThomas Haller <thaller@redhat.com>2021-06-16 20:26:45 +0200
commit161cf11cb19625c87c8524af0c38f808651f9fdf (patch)
tree63d4bd8bbb8588e8b60195b3239c77d5d4a305f4
parentd9c0d43879e8420dda6482b05341dcfeedf7be43 (diff)
parent35b0b4c93886d75e6d6bdf282845ba3d0fd6ade9 (diff)
release: bump version to 1.33.1 (development)1.33.1-dev
-rw-r--r--CONTRIBUTING.md48
-rw-r--r--Makefile.examples1
-rw-r--r--NEWS10
-rw-r--r--configure.ac4
-rwxr-xr-xcontrib/scripts/NM-log2
-rwxr-xr-xcontrib/scripts/test-create-many-device-setup.sh117
-rwxr-xr-xexamples/python/gi/nm-up-many.py373
-rw-r--r--meson.build2
-rw-r--r--src/core/NetworkManagerUtils.c6
-rw-r--r--src/core/nm-core-utils.c21
-rw-r--r--src/libnm-client-impl/nm-libnm-utils.h38
-rw-r--r--src/libnm-core-impl/tests/test-general.c201
-rw-r--r--src/libnm-glib-aux/nm-hash-utils.h144
-rw-r--r--src/libnm-glib-aux/nm-macros-internal.h302
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h38
-rw-r--r--src/libnm-glib-aux/nm-uuid.c58
-rw-r--r--src/libnm-glib-aux/nm-uuid.h51
-rw-r--r--src/libnm-std-aux/nm-std-aux.h392
-rwxr-xr-xtools/generate-docs-nm-settings-docs-merge.py22
19 files changed, 1164 insertions, 666 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2ee06fd29b..bc57f962ed 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -230,3 +230,51 @@ source code and navigate it. These tools can integrate with editors like `Vim` a
- http://cscope.sourceforge.net/cscope_vim_tutorial.html
- https://www.emacswiki.org/emacs/CScopeAndEmacs
+
+
+Miscellaneous
+---------------------------
+
+### GObject Properties
+
+We use GObjects and GObject Properties in various cases. For example:
+
+1. In public API in libnm they are used and useful for providing a standard
+ GObject API. One advantage of GObject properties is that they work well
+ with introspection and bindings.
+
+1. `NMSetting` properties commonly are GObject properties. While we provide
+ C getters, they commonly don't have a setter. That is, settings can often
+ only set via `g_object_set()`.
+
+1. Our D-Bus API uses glue code. For the daemon, this is
+ [`nm-dbus-manager.[ch]`](src/core/nm-dbus-manager.c) and
+ [`nm-dbus-object.[ch]`](src/core/nm-dbus-object.c). For libnm's
+ `NMClient`, this is [`nm-object.c`](src/libnm-client-impl/nm-object.c).
+ These bindings rely on GObject properties.
+
+1. Sometimes it is convenient to use the functionality that GObject
+ properties provide. In particular, `notify::` property changed signals
+ or the ability to freeze/thaw the signals.
+
+1. Immutable objects are great, so there is a desire to have `G_PARAM_CONSTRUCT_ONLY`
+ properties. In that case, avoid adding a getter too, the property only needs to be
+ writable and you should access it via the C wrapper.
+
+In general, use GObject sparsely and avoid them (unless you need them for one of the
+reasons above).
+
+Almost always add a `#define` for the property name, and use for example
+`g_signal_connect(obj, "notify::"NM_TARGET_SOME_PROPERTY", ...)`. The goal is to
+be able to search the use of all properties.
+
+Almost always add C getter and setters and prefer them over `g_object_get()`
+and `g_object_set()`. This also stresses the point that you usually wouldn't use
+a GObject property aside the reasons above.
+
+When adding a GObject properties, do it for only one of the reasons above.
+For example, the property `NM_MANAGER_DEVICES` in the daemon is added to bind
+the property to D-Bus. Don't use that property otherwise and don't register
+a `notify::NM_MANAGER_DEVICES` for your own purpose. The reason is that GObject
+properties are harder to understand and they should be used sparsely and for
+one specific reason.
diff --git a/Makefile.examples b/Makefile.examples
index 437b1e0ed7..18114a6d0b 100644
--- a/Makefile.examples
+++ b/Makefile.examples
@@ -187,6 +187,7 @@ EXTRA_DIST += \
examples/python/gi/nm-add-connection2.py \
examples/python/gi/nm-connection-update-stable-id.py \
examples/python/gi/nm-keyfile.py \
+ examples/python/gi/nm-up-many.py \
examples/python/gi/nm-update2.py \
examples/python/gi/nm-wg-set \
examples/python/gi/ovs-external-ids.py \
diff --git a/NEWS b/NEWS
index ea2fa7e98d..45042fbf47 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,14 @@
=============================================
+NetworkManager-1.34
+Overview of changes since NetworkManager-1.32
+=============================================
+
+This is a snapshot of NetworkManager development. The API is
+subject to change and not guaranteed to be compatible with
+the later release.
+USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
+
+=============================================
NetworkManager-1.32
Overview of changes since NetworkManager-1.30
=============================================
diff --git a/configure.ac b/configure.ac
index 9f4224c096..15179c1adc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,8 +7,8 @@ dnl - add corresponding NM_VERSION_x_y_z macros in
dnl "shared/nm-version-macros.h.in"
dnl - update number in meson.build
m4_define([nm_major_version], [1])
-m4_define([nm_minor_version], [32])
-m4_define([nm_micro_version], [0])
+m4_define([nm_minor_version], [33])
+m4_define([nm_micro_version], [1])
m4_define([nm_version],
[nm_major_version.nm_minor_version.nm_micro_version])
diff --git a/contrib/scripts/NM-log b/contrib/scripts/NM-log
index 65453a7e24..85d40b3524 100755
--- a/contrib/scripts/NM-log
+++ b/contrib/scripts/NM-log
@@ -38,7 +38,7 @@ NM-colorize() {
GREP_COLOR='01;31' grep -a --color=always '^\|^\(.* \)\?<\(warn> \|error>\) \[[0-9.]*\]' | \
GREP_COLOR='01;33' grep -a --color=always '^\|^\(.* \)\?<info> \[[0-9.]*\]\( .*\<is starting\>.*$\)\?' | \
GREP_COLOR='01;37' grep -a --color=always '^\|\<platform:\( (.*)\)\? signal: .*$' | \
- GREP_COLOR='01;34' grep -a --color=always '^\|\<platform\(-linux\)\?:\( (.*)\)\? link: \(add\|adding\|change\|setting\|deleting\)\>\|\<platform: routing-rule: \(adding or updating:\|delete \)\|\<platform:\( (.*)\)\? address: \(deleting\|adding or updating\) IPv. address:\? \|\<platform:\( (.*)\)\? \(route\|ip4-route\|ip6-route\|qdisc\|tfilter\): \([a-z]\+\|adding or updating\|new\[0x[0-9A-Za-z]*\]\) \|\<platform-linux: sysctl: setting ' | \
+ GREP_COLOR='01;34' grep -a --color=always '^\|\<platform\(-linux\)\?:\( (.*)\)\? link: \(add\|adding\|change\|setting\|deleting\|enslaving to master\)\>\|\<platform: routing-rule: \(adding or updating:\|delete \)\|\<platform:\( (.*)\)\? address: \(deleting\|adding or updating\) IPv. address:\? \|\<platform:\( (.*)\)\? \(route\|ip4-route\|ip6-route\|qdisc\|tfilter\): \([a-z]\+\|adding or updating\|new\[0x[0-9A-Za-z]*\]\) \|\<platform-linux: sysctl: setting ' | \
GREP_COLOR='01;35' grep -a --color=always '^\|\<audit: .*$' | \
GREP_COLOR='01;32' grep -a --color=always '^\|\<device (.*): state change: ' |
if [[ "$NM_LOG_GREP" != "" ]]; then
diff --git a/contrib/scripts/test-create-many-device-setup.sh b/contrib/scripts/test-create-many-device-setup.sh
new file mode 100755
index 0000000000..230833ff24
--- /dev/null
+++ b/contrib/scripts/test-create-many-device-setup.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+set -x
+
+die() {
+ printf '%s\n' "$*" >&1
+ exit 1
+}
+
+ARG_OP="$1"
+shift
+test -n "$ARG_OP" || die "specify the operation (setup, cleanup)"
+
+test "$USER" = root || die "must run as root"
+
+NUM_DEVS="${NUM_DEVS:-50}"
+
+
+DNSMASQ_PIDFILE="/tmp/nm-test-create-many-device-setup.dnsmasq.pid"
+NM_TEST_CONF="/etc/NetworkManager/conf.d/99-my-test.conf"
+TEST_NETNS="T"
+
+
+_dnsmasq_kill() {
+ pkill -F "$DNSMASQ_PIDFILE"
+ rm -rf "$DNSMASQ_PIDFILE"
+}
+
+_link_delete_all() {
+ ip link | sed -n 's/^[0-9]\+:.*\(t-[^@:]\+\)@.*/\1/p' | xargs -n 1 ip link delete
+}
+
+cleanup_base() {
+ ip netns delete "$TEST_NETNS"
+ _dnsmasq_kill
+ _link_delete_all
+ rm -rf "$NM_TEST_CONF"
+ rm -rf /run/NetworkManager/system-connections/c-*.nmconnection
+}
+
+cmd_cleanup() {
+ systemctl stop NetworkManager
+ cleanup_base
+ systemctl unmask NetworkManager-dispatcher
+ systemctl enable NetworkManager-dispatcher
+ systemctl start NetworkManager
+}
+
+cmd_setup() {
+
+ systemctl stop NetworkManager
+ systemctl mask NetworkManager-dispatcher
+ systemctl stop NetworkManager-dispatcher
+
+ cleanup_base
+
+ ip netns add "$TEST_NETNS"
+ ip --netns "$TEST_NETNS" link add t-br0 type bridge
+ ip --netns "$TEST_NETNS" link set t-br0 type bridge stp_state 0
+ ip --netns "$TEST_NETNS" link set t-br0 up
+ ip --netns "$TEST_NETNS" addr add 172.16.0.1/16 dev t-br0
+ ip netns exec "$TEST_NETNS" \
+ dnsmasq \
+ --conf-file=/dev/null \
+ --pid-file="$DNSMASQ_PIDFILE" \
+ --no-hosts \
+ --keep-in-foreground \
+ --bind-interfaces \
+ --except-interface=lo \
+ --clear-on-reload \
+ --listen-address=172.16.0.1 \
+ --dhcp-range=172.16.1.1,172.16.20.1,60 \
+ --no-ping \
+ &
+ disown
+ for i in `seq "$NUM_DEVS"`; do
+ ip --netns "$TEST_NETNS" link add t-a$i type veth peer t-b$i
+ ip --netns "$TEST_NETNS" link set t-a$i up
+ ip --netns "$TEST_NETNS" link set t-b$i up master t-br0
+ done
+
+ cat <<EOF > "$NM_TEST_CONF"
+[main]
+dhcp=internal
+no-auto-default=interface-name:t-a*
+[device-99-my-test]
+match-device=interface-name:t-a*
+managed=1
+[logging]
+level=INFO
+[connectivity]
+enabled=0
+EOF
+
+ systemctl start NetworkManager
+
+ for i in `seq "$NUM_DEVS"`; do
+ ip --netns "$TEST_NETNS" link set t-a$i netns $$
+ done
+
+ for i in `seq "$NUM_DEVS"`; do
+ nmcli connection add save no type ethernet con-name c-a$i ifname t-a$i autoconnect no ipv4.method auto ipv6.method auto
+ done
+}
+
+
+case "$ARG_OP" in
+ "setup")
+ cmd_setup
+ ;;
+ "cleanup")
+ cmd_cleanup
+ ;;
+ *)
+ die "Unknown command \"$ARG_OP\""
+ ;;
+esac
diff --git a/examples/python/gi/nm-up-many.py b/examples/python/gi/nm-up-many.py
new file mode 100755
index 0000000000..9fd86631bb
--- /dev/null
+++ b/examples/python/gi/nm-up-many.py
@@ -0,0 +1,373 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+# A example script to activate many profiles in parallel.
+#
+# It uses entirely asynchronous API. At various points the
+# script explicitly iterates the main context, which is unlike
+# a more complex application that uses the GMainContext, which
+# probably would run the context only at one point as long as
+# the application is running (from the main function).
+
+import sys
+import os
+import gi
+import time
+
+gi.require_version("NM", "1.0")
+from gi.repository import NM, GLib, Gio
+
+
+start_time = time.monotonic()
+
+
+class MyError(Exception):
+ pass
+
+
+def log(msg):
+ # use nm_utils_print(), so that the log messages are in synch with
+ # LIBNM_CLIENT_DEBUG=trace messages.
+ NM.utils_print(0, "[%015.10f] %s\n" % (time.monotonic() - start_time, msg))
+
+
+def nmc_new(io_priority=GLib.PRIORITY_DEFAULT, cancellable=None):
+ # create a NMClient instance using the async initialization
+ # (but the function itself iterates the main context until
+ # the initialization completes).
+
+ result = []
+
+ def cb(source_object, res):
+
+ try:
+ source_object.init_finish(res)
+ except Exception as e:
+ result.append(e)
+ else:
+ result.append(None)
+
+ nmc = NM.Client()
+ nmc.init_async(io_priority, cancellable, cb)
+ while not result:
+ nmc.get_main_context().iteration(may_block=True)
+
+ if result[0]:
+ raise result[0]
+
+ log("initialized NMClient cache")
+
+ return nmc
+
+
+def nmc_destroy(nmc_transfer_ref):
+
+ # Just for fun, show how to completely cleanup a NMClient instance.
+ # An NMClient instance registers D-Bus signals and unrefing the instance
+ # will cancel/unsubscribe those signals, but there might still be some
+ # pending operations scheduled on the main context. That means, after
+ # unrefing the NMClient instance, we may need to iterate the GMainContext
+ # a bit longer, go get rid of all resources (otherwise, the GMainContext
+ # itself cannot be destroyed and leaks).
+ #
+ # We can use nm_client_get_context_busy_watcher() for that, by subscribing
+ # a weak reference and iterating the context as long as the object is
+ # alive.
+
+ nmc = nmc_transfer_ref[0]
+ del nmc_transfer_ref[0]
+
+ alive = [1]
+
+ def weak_ref_cb(alive):
+ del alive[0]
+
+ nmc.get_context_busy_watcher().weak_ref(weak_ref_cb, alive)
+ main_context = nmc.get_main_context()
+
+ del nmc
+
+ while alive:
+ main_context.iteration(may_block=True)
+
+ log("NMClient instance cleaned up")
+
+
+def find_connections(nmc, argv):
+
+ # parse the inpurt argv and select the connection profiles to activate.
+ # The arguments are either "connection.id" or "connection.uuid", possibly
+ # qualified by "id" or "uuid".
+
+ result = []
+
+ while True:
+ if not argv:
+ break
+ arg_type = argv.pop(0)
+ if arg_type in ["id", "uuid"]:
+ if not argv:
+ raise MyError('missing specifier after "%s"' % (arg_type))
+ arg_param = argv.pop(0)
+ else:
+ arg_param = arg_type
+ arg_type = "*"
+
+ cc = []
+ for c in nmc.get_connections():
+ if arg_type in ["id", "*"] and arg_param == c.get_id():
+ cc.append(c)
+ if arg_type in ["uuid", "*"] and arg_param == c.get_uuid():
+ cc.append(c)
+
+ if not cc:
+ raise MyError(
+ 'Could not find a matching connection "%s" "%s"' % (arg_type, arg_param)
+ )
+ if len(cc) > 1:
+ raise MyError(
+ 'Could not find a unique matching connection "%s" "%s", instead %d profiles found'
+ % (arg_type, arg_param, len(cc))
+ )
+
+ if cc[0] not in result:
+ # we allow duplicates, but combine them.
+ result.extend(cc)
+
+ for c in result:
+ log(
+ "requested connection: %s (%s) (%s)"
+ % (c.get_id(), c.get_uuid(), c.get_path())
+ )
+
+ return result
+
+
+def nmc_activate_start(nmc, con):
+
+ # Call nmc.activate_connection_async() and return a user data
+ # with the information about the pending operation.
+
+ activation = {
+ "con": con,
+ "result": None,
+ "result_msg": None,
+ "result_ac": None,
+ "ac_result": None,
+ }
+
+ log("activation %s (%s) start asynchronously" % (con.get_id(), con.get_uuid()))
+
+ def cb(source_object, res, activation):
+ # The callback does not call other code for signaling the
+ # completion. Instead, we remember in "activation" that
+ # the callback was completed.
+ #
+ # Other code will repeatedly go through the "activation_list"
+ # and find those that are completed (nmc_activate_find_completed()).
+ try:
+ ac = nmc.activate_connection_finish(res)
+ except Exception as e:
+ activation["result"] = False
+ activation["result_msg"] = str(e)
+ else:
+ activation["result"] = True
+ activation["result_msg"] = "success"
+ activation["result_ac"] = ac
+
+ nmc.activate_connection_async(con, None, None, None, cb, activation)
+
+ return activation
+
+
+def nmc_activate_find_completed(activation_list):
+
+ # Iterate over list of "activation" data, find the first
+ # one that is completed, remove it from the list and return
+ # it.
+
+ for idx, activation in enumerate(activation_list):
+ if activation["result"] is not None:
+ del activation_list[idx]
+ return activation
+
+ return None
+
+
+def nmc_activate_complete(
+ nmc, activation_list, completed_list, num_parallel_invocations
+):
+
+ # We schedule activations asynchronously and in parallel. However, we
+ # still want to rate limit the number of parallel activations. This
+ # function does that: if there are more than "num_parallel_invocations" activations
+ # in progress, then wait until the excess number of them completed.
+ # The completed ones move from "activation_list" over to "completed_list".
+
+ completed = 0
+ while True:
+
+ need_to_wait = len(activation_list) > num_parallel_invocations
+
+ # Even if we don't need to wait (that is, the list of pending activations
+ # is reasonably short), we still tentatively iterate the GMainContext a bit.
+ if not nmc.get_main_context().iteration(may_block=need_to_wait):
+ if need_to_wait:
+ continue
+ # Ok, nothing ready yet.
+ break
+
+ # this is not efficient after each iteration(), but it's good enough.
+ # The activation list is supposed to be short.
+ activation = nmc_activate_find_completed(activation_list)
+
+ if activation is None:
+ continue
+
+ con = activation["con"]
+ log(
+ "activation %s (%s) start complete: %s%s"
+ % (
+ con.get_id(),
+ con.get_uuid(),
+ activation["result_msg"],
+ (
+ ""
+ if not activation["result"]
+ else (" (%s)" % (activation["result_ac"].get_path()))
+ ),
+ )
+ )
+ completed += 1
+
+ completed_list.append(activation)
+
+ if completed > 0:
+ log(
+ "completed %d activations, %d activations still pending"
+ % (completed, len(activation_list))
+ )
+
+
+def nmc_activate_all(nmc, cons):
+
+ # iterate of all connections ("cons") and activate them
+ # in parallel. nmc_activate_complete() is used to rate limits
+ # how many parallel invocations we allow.
+
+ num_parallel_invocations = 100
+
+ activation_list = []
+ completed_list = []
+ for c in cons:
+ activation = nmc_activate_start(nmc, c)
+ activation_list.append(activation)
+ nmc_activate_complete(
+ nmc, activation_list, completed_list, num_parallel_invocations
+ )
+ nmc_activate_complete(nmc, activation_list, completed_list, 0)
+ assert not activation_list
+ assert len(completed_list) == len(cons)
+
+ return completed_list
+
+
+def nmc_activate_wait_for_pending(nmc, completed_list):
+
+ # go through the list of activations and wait that they
+ # all reach a final state. That is, either that they are failed
+ # or fully ACTIVATED state.
+
+ log("wait for all active connection to either reach ACTIVATED state or fail...")
+
+ def log_result(activation, message):
+ activation["ac_result"] = message
+ log(
+ "connection %s (%s) activation fully completed: %s"
+ % (ac.get_id(), ac.get_uuid(), message)
+ )
+
+ while True:
+
+ # again, it's not efficient to check the entire list for completion
+ # after each g_main_context_iteration(). But "completed_list" should
+ # be reasonably small.
+
+ activation = None
+ for idx, activ in enumerate(completed_list):
+ if activ["ac_result"] is not None:
+ continue
+ if activ["result"] is False:
+ log_result(activ, "failed to start activation")
+ continue
+ ac = activ["result_ac"]
+ if ac.get_client() is None:
+ log_result(activ, "active connection disappeared")
+ continue
+ if ac.get_state() == NM.ActiveConnectionState.ACTIVATED:
+ log_result(activ, "connection successfully activated")
+ continue
+ if ac.get_state() > NM.ActiveConnectionState.ACTIVATED:
+ log_result(
+ activ, "connection failed to activate (state %s)" % (ac.get_state())
+ )
+ continue
+ activation = activ
+ break
+
+ if activation is None:
+ log("no more activation to wait for")
+ break
+
+ nmc.get_main_context().iteration(may_block=True)
+
+
+def nmc_activate_check_good(nmc, completed_list):
+
+ # go through the list of activations and check that all of them are
+ # in a good state.
+
+ n_good = 0
+ n_bad = 0
+
+ for activ in completed_list:
+ if activ["result"] is False:
+ n_bad += 1
+ continue
+ ac = activ["result_ac"]
+ if ac.get_client() is None:
+ n_bad += 1
+ continue
+ if ac.get_state() != NM.ActiveConnectionState.ACTIVATED:
+ n_bad += 1
+ continue
+ n_good += 1
+
+ log(
+ "%d out of %d activations are now successfully activated"
+ % (n_good, n_good + n_bad)
+ )
+
+ return n_bad == 0
+
+
+def main():
+ nmc = nmc_new()
+
+ cons = find_connections(nmc, sys.argv[1:])
+
+ completed_list = nmc_activate_all(nmc, cons)
+
+ nmc_activate_wait_for_pending(nmc, completed_list)
+
+ all_good = nmc_activate_check_good(nmc, completed_list)
+
+ nmc_transfer_ref = [nmc]
+ del nmc
+ nmc_destroy(nmc_transfer_ref)
+
+ sys.exit(0 if all_good else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meson.build b/meson.build
index ac6c8a6565..6082828194 100644
--- a/meson.build
+++ b/meson.build
@@ -6,7 +6,7 @@ project(
# - add corresponding NM_VERSION_x_y_z macros in
# "src/libnm-core-public/nm-version-macros.h.in"
# - update number in configure.ac
- version: '1.32.0',
+ version: '1.33.1',
license: 'GPL2+',
default_options: [
'buildtype=debugoptimized',
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c
index 7d3e80be4c..34ddf9fb1a 100644
--- a/src/core/NetworkManagerUtils.c
+++ b/src/core/NetworkManagerUtils.c
@@ -1051,6 +1051,12 @@ nm_shutdown_wait_obj_register_full(gpointer watched_obj,
if (G_UNLIKELY(!_shutdown_waitobj_lst_head.next))
c_list_init(&_shutdown_waitobj_lst_head);
+ /* Beware: there are callers with g_main_context_get_thread_default()
+ * not being g_main_context_get_default(). For example _fw_nft_call().
+ *
+ * If you schedule any sources or async operations, you probably need to
+ * make sure to use the default context. */
+
handle = g_slice_new(NMShutdownWaitObjHandle);
*handle = (NMShutdownWaitObjHandle){
/* depending on @free_msg_reason, we take ownership of @msg_reason.
diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c
index 41d2256550..364625159e 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -2378,8 +2378,6 @@ out:
typedef struct {
NMUuid bin;
- char
- _nul_sentinel; /* just for safety, if somebody accidentally uses the binary in a string context. */
/* depending on whether the string is packed or not (with/without hyphens),
* it's 32 or 36 characters long (plus the trailing NUL).
@@ -2397,9 +2395,8 @@ _uuid_data_init(UuidData *uuid_data, gboolean packed, gboolean is_fake, const NM
nm_assert(uuid_data);
nm_assert(uuid);
- uuid_data->bin = *uuid;
- uuid_data->_nul_sentinel = '\0';
- uuid_data->is_fake = is_fake;
+ uuid_data->bin = *uuid;
+ uuid_data->is_fake = is_fake;
if (packed) {
G_STATIC_ASSERT_EXPR(sizeof(uuid_data->str) >= (sizeof(*uuid) * 2 + 1));
nm_utils_bin2hexstr_full(uuid, sizeof(*uuid), '\0', FALSE, uuid_data->str);
@@ -2467,7 +2464,7 @@ again:
if (is_fake) {
const guint8 *seed_bin;
- const char * hash_seed;
+ const NMUuid *hash_seed;
gsize seed_len;
if (!allow_fake) {
@@ -2477,6 +2474,9 @@ again:
}
if (nm_utils_host_id_get(&seed_bin, &seed_len)) {
+ static const NMUuid u =
+ NM_UUID_INIT(ab, 08, 5f, 06, b6, 29, 46, d1, a5, 53, 84, ee, ba, 56, 83, b6);
+
/* We have no valid machine-id but we have a valid secrey_key.
* Generate a fake machine ID by hashing the secret-key. The secret_key
* is commonly persisted, so it should be stable across reboots (despite
@@ -2489,8 +2489,11 @@ again:
* will call _machine_id_get(FALSE), so it won't allow accessing a fake
* machine-id, thus avoiding the problem. */
fake_type = "secret-key";
- hash_seed = "ab085f06-b629-46d1-a553-84eeba5683b6";
+ hash_seed = &u;
} else {
+ static const NMUuid u =
+ NM_UUID_INIT(7f, f0, c8, f5, 53, 99, 49, 01, ab, 63, 61, bf, 59, 4a, be, 8b);
+
/* the secret-key is not valid/persistent either. That happens when we fail
* to read/write the secret-key to disk. Fallback to boot-id. The boot-id
* itself may be fake and randomly generated ad-hoc, but that is as best
@@ -2498,7 +2501,7 @@ again:
seed_bin = (const guint8 *) nm_utils_boot_id_bin();
seed_len = sizeof(NMUuid);
fake_type = "boot-id";
- hash_seed = "7ff0c8f5-5399-4901-ab63-61bf594abe8b";
+ hash_seed = &u;
}
/* the fake machine-id is based on secret-key/boot-id, but we hash it
@@ -2507,7 +2510,7 @@ again:
(const char *) seed_bin,
seed_len,
NM_UUID_TYPE_VERSION5,
- (gpointer) hash_seed);
+ hash_seed);
}
if (!g_once_init_enter(&lock))
diff --git a/src/libnm-client-impl/nm-libnm-utils.h b/src/libnm-client-impl/nm-libnm-utils.h
index 3fd3b679e8..ef80bb4292 100644
--- a/src/libnm-client-impl/nm-libnm-utils.h
+++ b/src/libnm-client-impl/nm-libnm-utils.h
@@ -758,21 +758,29 @@ struct _NMObjectClass {
} \
G_STMT_END
-#define _NM_OBJECT_CLASS_INIT_FIELD_INFO(_nm_object_class, _field_name, _offset, _num) \
- G_STMT_START \
- { \
- (_nm_object_class)->_field_name = ({ \
- static _NMObjectClassFieldInfo _f; \
- \
- _f = (_NMObjectClassFieldInfo){ \
- .parent = (_nm_object_class)->_field_name, \
- .klass = (_nm_object_class), \
- .offset = _offset, \
- .num = _num, \
- }; \
- &_f; \
- }); \
- } \
+#define _NM_OBJECT_CLASS_INIT_FIELD_INFO(nm_object_class, field_name, _offset, _num) \
+ G_STMT_START \
+ { \
+ NMObjectClass *const _klass = (nm_object_class); \
+ \
+ _klass->field_name = ({ \
+ static _NMObjectClassFieldInfo _f; \
+ \
+ /* this code is called inside a _class_init() function, it thus
+ * is only executed once, so we are fine to initialize a static
+ * variable here. */ \
+ nm_assert(!_f.klass); \
+ \
+ _f = (_NMObjectClassFieldInfo){ \
+ .parent = _klass->field_name, \
+ .klass = _klass, \
+ .offset = (_offset), \
+ .num = (_num), \
+ }; \
+ \
+ &_f; \
+ }); \
+ } \
G_STMT_END
#define _NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_1(nm_object_class, type_name, field_name) \
diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c
index f9cc5e54e4..51411b6feb 100644
--- a/src/libnm-core-impl/tests/test-general.c
+++ b/src/libnm-core-impl/tests/test-general.c
@@ -478,6 +478,36 @@ test_nm_hash(void)
g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031);
g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031);
g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 1, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x131);
+ g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1),
+ ==,
+ 0x131);
+ g_assert_cmpint(NM_HASH_COMBINE_BOOLS(guint16, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1),
+ ==,
+ 0x8131);
+ g_assert_cmpint(
+ NM_HASH_COMBINE_BOOLS(guint32, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1),
+ ==,
+ 0x8131);
+ g_assert_cmpint(
+ NM_HASH_COMBINE_BOOLS(guint32, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1),
+ ==,
+ 0x28131);
+
+#if _NM_CC_SUPPORT_AUTO_TYPE
+ {
+ _nm_auto_type x = NM_HASH_COMBINE_BOOLS(guint8, 0, 0, 1, 1, 0, 0, 0, 1);
+
+ G_STATIC_ASSERT(sizeof(x) == 1);
+ g_assert(((typeof(x)) -1) > 0);
+ }
+
+ {
+ _nm_auto_type x = NM_HASH_COMBINE_BOOLS(guint16, 0, 0, 1, 1, 0, 0, 0, 1);
+
+ G_STATIC_ASSERT(sizeof(x) == 2);
+ g_assert(((typeof(x)) -1) > 0);
+ }
+#endif
}
/*****************************************************************************/
@@ -7208,11 +7238,10 @@ test_nm_strquote(void)
/*****************************************************************************/
-#define UUID_NS_ZERO "00000000-0000-0000-0000-000000000000"
-#define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
-#define UUID_NS_URL "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
-#define UUID_NS_OID "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
-#define UUID_NS_X500 "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
+#define NM_UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
+#define NM_UUID_NS_URL "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
+#define NM_UUID_NS_OID "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
+#define NM_UUID_NS_X500 "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
static const NMUuid *
_uuid(const char *str)
@@ -7229,11 +7258,18 @@ _test_uuid(int uuid_type,
const char *expected_uuid,
const char *str,
gssize slen,
- gpointer type_args)
+ const char *type_args)
{
- gs_free char *uuid_test = NULL;
+ gs_free char *uuid_test = NULL;
+ NMUuid type_args_u = NM_UUID_INIT_ZERO();
- uuid_test = nm_uuid_generate_from_string_str(str, slen, uuid_type, type_args);
+ if (type_args) {
+ if (!nm_uuid_parse(type_args, &type_args_u))
+ g_assert_not_reached();
+ }
+
+ uuid_test =
+ nm_uuid_generate_from_string_str(str, slen, uuid_type, type_args ? &type_args_u : NULL);
g_assert(uuid_test);
g_assert(nm_utils_is_uuid(uuid_test));
@@ -7244,7 +7280,7 @@ _test_uuid(int uuid_type,
str,
(long long) slen,
NM_IN_SET(uuid_type, NM_UUID_TYPE_VERSION3, NM_UUID_TYPE_VERSION5)
- ? (((const char *) type_args) ?: "(all-zero)")
+ ? (type_args ?: "(all-zero)")
: (type_args ? "(unknown)" : "(null)"),
uuid_test,
expected_uuid);
@@ -7259,8 +7295,8 @@ _test_uuid(int uuid_type,
}
if (NM_IN_SET(uuid_type, NM_UUID_TYPE_VERSION3, NM_UUID_TYPE_VERSION5) && !type_args) {
- /* For version3 and version5, a missing @type_args is equal to UUID_NS_ZERO */
- _test_uuid(uuid_type, expected_uuid, str, slen, UUID_NS_ZERO);
+ /* For version3 and version5, a missing @type_args is equal to NM_UUID_NS_ZERO */
+ _test_uuid(uuid_type, expected_uuid, str, slen, NM_UUID_NS_ZERO);
}
}
@@ -7694,33 +7730,53 @@ test_nm_utils_uuid_generate_from_string(void)
_test_uuid(NM_UUID_TYPE_VERSION3, "96e17d7a-ac89-38cf-95e1-bf5098da34e1", "test", -1, NULL);
_test_uuid(NM_UUID_TYPE_VERSION3, "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", "a\0b", 3, NULL);
- _test_uuid(NM_UUID_TYPE_VERSION3, "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", "", -1, UUID_NS_DNS);
- _test_uuid(NM_UUID_TYPE_VERSION3, "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", "a", -1, UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION3,
+ "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3",
+ "",
+ -1,
+ NM_UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION3,
+ "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d",
+ "a",
+ -1,
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION3,
"45a113ac-c7f2-30b0-90a5-a399ab912716",
"test",
-1,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION3,
"002a0ada-f547-375a-bab5-896a11d1927e",
"a\0b",
3,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION3,
"9a75f5f2-195e-31a9-9d07-8c18b5d3b285",
"test123",
-1,
- UUID_NS_DNS);
- _test_uuid(NM_UUID_TYPE_VERSION3, "ec794efe-a384-3b11-a0b6-ec8995bc6acc", "x", -1, UUID_NS_DNS);
+ NM_UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION3,
+ "ec794efe-a384-3b11-a0b6-ec8995bc6acc",
+ "x",
+ -1,
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION5, "a7650b9f-f19f-5300-8a13-91160ea8de2c", "a\0b", 3, NULL);
- _test_uuid(NM_UUID_TYPE_VERSION5, "4f3f2898-69e3-5a0d-820a-c4e87987dbce", "a", -1, UUID_NS_DNS);
- _test_uuid(NM_UUID_TYPE_VERSION5, "05b16a01-46c6-56dd-bd6e-c6dfb4a1427a", "x", -1, UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION5,
+ "4f3f2898-69e3-5a0d-820a-c4e87987dbce",
+ "a",
+ -1,
+ NM_UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION5,
+ "05b16a01-46c6-56dd-bd6e-c6dfb4a1427a",
+ "x",
+ -1,
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION5,
"c9ed566a-6b79-5d3a-b2b7-96a936b48cf3",
"test123",
-1,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
for (i = 0; i < G_N_ELEMENTS(zero_uuids); i++) {
nm_sprintf_buf(i_str, "%u", i),
@@ -7729,8 +7785,8 @@ test_nm_utils_uuid_generate_from_string(void)
}
for (i = 0; i < G_N_ELEMENTS(dns_uuids); i++) {
nm_sprintf_buf(i_str, "%u", i),
- _test_uuid(NM_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, UUID_NS_DNS);
- _test_uuid(NM_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, NM_UUID_NS_DNS);
+ _test_uuid(NM_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, NM_UUID_NS_DNS);
}
/* examples from cpython unit tests: */
@@ -7738,48 +7794,48 @@ test_nm_utils_uuid_generate_from_string(void)
"6fa459ea-ee8a-3ca4-894e-db77e160355e",
"python.org",
-1,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION5,
"886313e1-3b8a-5372-9b90-0c9aee199e5d",
"python.org",
-1,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
_test_uuid(NM_UUID_TYPE_VERSION3,
"9fe8e8c4-aaa8-32a9-a55c-4535a88b748d",
"http://python.org/",
-1,
- UUID_NS_URL);
+ NM_UUID_NS_URL);
_test_uuid(NM_UUID_TYPE_VERSION5,
"4c565f0d-3f5a-5890-b41b-20cf47701c5e",
"http://python.org/",
-1,
- UUID_NS_URL);
+ NM_UUID_NS_URL);
_test_uuid(NM_UUID_TYPE_VERSION3,
"dd1a1cef-13d5-368a-ad82-eca71acd4cd1",
"1.3.6.1",
-1,
- UUID_NS_OID);
+ NM_UUID_NS_OID);
_test_uuid(NM_UUID_TYPE_VERSION5,
"1447fa61-5277-5fef-a9b3-fbc6e44f4af3",
"1.3.6.1",
-1,
- UUID_NS_OID);
+ NM_UUID_NS_OID);
_test_uuid(NM_UUID_TYPE_VERSION3,
"658d3002-db6b-3040-a1d1-8ddd7d189a4d",
"c=ca",
-1,
- UUID_NS_X500);
+ NM_UUID_NS_X500);
_test_uuid(NM_UUID_TYPE_VERSION5,
"cc957dd1-a972-5349-98cd-874190002798",
"c=ca",
-1,
- UUID_NS_X500);
+ NM_UUID_NS_X500);
_test_uuid(NM_UUID_TYPE_VERSION5,
"74738ff5-5367-5958-9aee-98fffdcd1876",
"www.example.org",
-1,
- UUID_NS_DNS);
+ NM_UUID_NS_DNS);
}
/*****************************************************************************/
@@ -7799,7 +7855,7 @@ __test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_
}
g_free(uuid_test);
- uuid_test = nm_uuid_generate_from_string_str(str, slen, NM_UUID_TYPE_VERSION3, NM_UUID_NS1);
+ uuid_test = nm_uuid_generate_from_string_str(str, slen, NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1);
g_assert(uuid_test);
g_assert(nm_utils_is_uuid(uuid_test));
@@ -7820,15 +7876,23 @@ __test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_
static void
test_nm_utils_uuid_generate_from_strings(void)
{
- const NMUuid uuid0 = {};
+ const NMUuid uuid0 = NM_UUID_INIT_ZERO();
+ const NMUuid uuid1 = {};
+ char buf[37];
g_assert_cmpmem(&uuid0, sizeof(uuid0), _uuid("00000000-0000-0000-0000-000000000000"), 16);
+ g_assert_cmpmem(&uuid0, sizeof(NMUuid), &uuid1, sizeof(NMUuid));
+
g_assert(nm_uuid_is_null(NULL));
g_assert(nm_uuid_is_null(&uuid0));
+ g_assert(nm_uuid_is_null(&nm_uuid_ns_zero));
g_assert(nm_uuid_is_null(_uuid("00000000-0000-0000-0000-000000000000")));
g_assert(!nm_uuid_is_null(_uuid("10000000-0000-0000-0000-000000000000")));
+ g_assert_cmpstr(NM_UUID_NS_1, ==, nm_uuid_unparse(&nm_uuid_ns_1, buf));
+ g_assert_cmpstr(NM_UUID_NS_ZERO, ==, nm_uuid_unparse(&nm_uuid_ns_zero, buf));
+
_test_uuid("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL);
_test_uuid("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, "");
_test_uuid("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a");
@@ -7845,6 +7909,32 @@ test_nm_utils_uuid_generate_from_strings(void)
_test_uuid("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b");
}
+static void
+test_nm_uuid_init(void)
+{
+ char buf[37];
+
+ {
+ NMUuid u;
+
+ u = NM_UUID_INIT(47, c4, d7, f9, 2c, 81, 4f, 7b, be, ed, 63, 0a, 7f, 65, cc, 02);
+ g_assert_cmpstr("47c4d7f9-2c81-4f7b-beed-630a7f65cc02", ==, nm_uuid_unparse(&u, buf));
+ }
+ {
+ const NMUuid u =
+ NM_UUID_INIT(47, c4, d7, f9, 2c, 81, 4f, 7b, be, ed, 63, 0a, 7f, 65, cc, 02);
+
+ g_assert_cmpstr("47c4d7f9-2c81-4f7b-beed-630a7f65cc02", ==, nm_uuid_unparse(&u, buf));
+ }
+ {
+ const struct {
+ NMUuid u;
+ } u = {NM_UUID_INIT(47, c4, d7, f9, 2c, 81, 4f, 7b, be, ed, 63, 0a, 7f, 65, cc, 02)};
+
+ g_assert_cmpstr("47c4d7f9-2c81-4f7b-beed-630a7f65cc02", ==, nm_uuid_unparse(&u.u, buf));
+ }
+}
+
/*****************************************************************************/
static void
@@ -9773,11 +9863,53 @@ test_nm_va_args_macros(void)
g_assert_cmpint(7, ==, GET_NARG_1(x, x, x, x, x, x, x));
g_assert_cmpint(8, ==, GET_NARG_1(x, x, x, x, x, x, x, x));
g_assert_cmpint(9, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x));
- g_assert_cmpint(10, ==, GET_NARG_1(x, x, x, x, x, x, x, x, x, x));
+ g_assert_cmpint(10, ==, NM_NARG(x, x, x, x, x, x, x, x, x, x));
G_STATIC_ASSERT_EXPR(0 == GET_NARG_1());
G_STATIC_ASSERT_EXPR(1 == GET_NARG_1(x));
G_STATIC_ASSERT_EXPR(2 == GET_NARG_1(x, x));
+
+ /* clang-format off */
+ G_STATIC_ASSERT_EXPR(NM_NARG(
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,20,
+ 1,2,3,4,5,6,7,8,9,30
+ ) == 30);
+ G_STATIC_ASSERT_EXPR(NM_NARG(
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,20,
+ 1,2,3,4,5,6,7,8,9,30,
+ 1,2,3,4,5,6,7,8,9,40,
+ 1,2,3,4,5,6,7,8,9,50,
+ 1,2,3,4,5,6,7,8,9,60,
+ 1,2,3,4,5,6,7,8,9,70,
+ 1,2,3,4,5,6,7,8,9,80
+ ) == 80);
+ G_STATIC_ASSERT_EXPR(NM_NARG(
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,20,
+ 1,2,3,4,5,6,7,8,9,30,
+ 1,2,3,4,5,6,7,8,9,40,
+ 1,2,3,4,5,6,7,8,9,50,
+ 1,2,3,4,5,6,7,8,9,60,
+ 1,2,3,4,5,6,7,8,9,70,
+ 1,2,3,4,5,6,7,8,9,80,
+ 1,2,3,4,5,6,7,8,9,90,
+ 1,2,3,4,5,6,7,8,9,100,
+ 1,2,3,4,5,6,7,8,9,110,
+ 1,2,3,4,5,6,7,8,9,120
+ ) == 120);
+ /* clang-format on */
+
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX1() == 0);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX1(1) == 1);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX1(1, 2) == 1);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX1(1, 2, 3) == 1);
+
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX2() == 0);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX2(1) == 1);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX2(1, 2) == 2);
+ G_STATIC_ASSERT_EXPR(NM_NARG_MAX2(1, 2, 3) == 2);
}
/*****************************************************************************/
@@ -10796,6 +10928,7 @@ main(int argc, char **argv)
test_nm_utils_uuid_generate_from_string);
g_test_add_func("/core/general/nm_uuid_generate_from_strings",
test_nm_utils_uuid_generate_from_strings);
+ g_test_add_func("/core/general/test_nm_uuid_init", test_nm_uuid_init);
g_test_add_func("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
g_test_add_func("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h
index e79fb894eb..52e3430503 100644
--- a/src/libnm-glib-aux/nm-hash-utils.h
+++ b/src/libnm-glib-aux/nm-hash-utils.h
@@ -122,138 +122,32 @@ nm_hash_update_bool(NMHashState *state, bool val)
nm_hash_update(state, &val, sizeof(val));
}
-#define _NM_HASH_COMBINE_BOOLS_x_1(t, y) ((y) ? ((t) (1ull << 0)) : ((t) 0ull))
-#define _NM_HASH_COMBINE_BOOLS_x_2(t, y, ...) \
- ((y) ? ((t) (1ull << 1)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_1(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_3(t, y, ...) \
- ((y) ? ((t) (1ull << 2)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_2(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_4(t, y, ...) \
- ((y) ? ((t) (1ull << 3)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_3(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_5(t, y, ...) \
- ((y) ? ((t) (1ull << 4)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_4(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_6(t, y, ...) \
- ((y) ? ((t) (1ull << 5)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_5(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_7(t, y, ...) \
- ((y) ? ((t) (1ull << 6)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_6(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_8(t, y, ...) \
- ((y) ? ((t) (1ull << 7)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_7(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_9(t, y, ...) \
- ((y) ? ((t) (1ull << 8)) : ((t) 0ull)) \
- | (G_STATIC_ASSERT_EXPR(sizeof(t) >= 2), (_NM_HASH_COMBINE_BOOLS_x_8(t, __VA_ARGS__)))
-#define _NM_HASH_COMBINE_BOOLS_x_10(t, y, ...) \
- ((y) ? ((t) (1ull << 9)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_9(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_11(t, y, ...) \
- ((y) ? ((t) (1ull << 10)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_10(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_n2(t, n, ...) _NM_HASH_COMBINE_BOOLS_x_##n(t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_n(t, n, ...) _NM_HASH_COMBINE_BOOLS_n2(t, n, __VA_ARGS__)
-
-#define NM_HASH_COMBINE_BOOLS(type, ...) \
- ((type) (_NM_HASH_COMBINE_BOOLS_n(type, NM_NARG(__VA_ARGS__), __VA_ARGS__)))
+#define _NM_HASH_COMBINE_BOOLS_OP(x, n) \
+ ((x) ? ((_nm_hash_combine_bools_type) NM_BIT((n))) : ((_nm_hash_combine_bools_type) 0))
+
+#define NM_HASH_COMBINE_BOOLS(type, ...) \
+ ({ \
+ typedef type _nm_hash_combine_bools_type; \
+ \
+ G_STATIC_ASSERT(NM_NARG(__VA_ARGS__) <= 8 * sizeof(_nm_hash_combine_bools_type)); \
+ \
+ (_nm_hash_combine_bools_type)( \
+ NM_VA_ARGS_FOREACH(, , |, _NM_HASH_COMBINE_BOOLS_OP, __VA_ARGS__)); \
+ })
#define nm_hash_update_bools(state, ...) \
nm_hash_update_val(state, NM_HASH_COMBINE_BOOLS(guint8, __VA_ARGS__))
-#define _NM_HASH_COMBINE_VALS_typ_x_1(y) typeof(y) _v1;
-#define _NM_HASH_COMBINE_VALS_typ_x_2(y, ...) \
- typeof(y) _v2; \
- _NM_HASH_COMBINE_VALS_typ_x_1(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_3(y, ...) \
- typeof(y) _v3; \
- _NM_HASH_COMBINE_VALS_typ_x_2(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_4(y, ...) \
- typeof(y) _v4; \
- _NM_HASH_COMBINE_VALS_typ_x_3(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_5(y, ...) \
- typeof(y) _v5; \
- _NM_HASH_COMBINE_VALS_typ_x_4(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_6(y, ...) \
- typeof(y) _v6; \
- _NM_HASH_COMBINE_VALS_typ_x_5(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_7(y, ...) \
- typeof(y) _v7; \
- _NM_HASH_COMBINE_VALS_typ_x_6(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_8(y, ...) \
- typeof(y) _v8; \
- _NM_HASH_COMBINE_VALS_typ_x_7(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_9(y, ...) \
- typeof(y) _v9; \
- _NM_HASH_COMBINE_VALS_typ_x_8(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_10(y, ...) \
- typeof(y) _v10; \
- _NM_HASH_COMBINE_VALS_typ_x_9(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_11(y, ...) \
- typeof(y) _v11; \
- _NM_HASH_COMBINE_VALS_typ_x_10(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_12(y, ...) \
- typeof(y) _v12; \
- _NM_HASH_COMBINE_VALS_typ_x_11(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_13(y, ...) \
- typeof(y) _v13; \
- _NM_HASH_COMBINE_VALS_typ_x_12(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_14(y, ...) \
- typeof(y) _v14; \
- _NM_HASH_COMBINE_VALS_typ_x_13(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_15(y, ...) \
- typeof(y) _v15; \
- _NM_HASH_COMBINE_VALS_typ_x_14(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_16(y, ...) \
- typeof(y) _v16; \
- _NM_HASH_COMBINE_VALS_typ_x_15(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_17(y, ...) \
- typeof(y) _v17; \
- _NM_HASH_COMBINE_VALS_typ_x_16(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_18(y, ...) \
- typeof(y) _v18; \
- _NM_HASH_COMBINE_VALS_typ_x_17(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_19(y, ...) \
- typeof(y) _v19; \
- _NM_HASH_COMBINE_VALS_typ_x_18(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_20(y, ...) \
- typeof(y) _v20; \
- _NM_HASH_COMBINE_VALS_typ_x_19(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_n2(n, ...) _NM_HASH_COMBINE_VALS_typ_x_##n(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_n(n, ...) _NM_HASH_COMBINE_VALS_typ_n2(n, __VA_ARGS__)
-
-#define _NM_HASH_COMBINE_VALS_val_x_1(y) ._v1 = (y),
-#define _NM_HASH_COMBINE_VALS_val_x_2(y, ...) ._v2 = (y), _NM_HASH_COMBINE_VALS_val_x_1(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_3(y, ...) ._v3 = (y), _NM_HASH_COMBINE_VALS_val_x_2(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_4(y, ...) ._v4 = (y), _NM_HASH_COMBINE_VALS_val_x_3(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_5(y, ...) ._v5 = (y), _NM_HASH_COMBINE_VALS_val_x_4(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_6(y, ...) ._v6 = (y), _NM_HASH_COMBINE_VALS_val_x_5(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_7(y, ...) ._v7 = (y), _NM_HASH_COMBINE_VALS_val_x_6(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_8(y, ...) ._v8 = (y), _NM_HASH_COMBINE_VALS_val_x_7(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_9(y, ...) ._v9 = (y), _NM_HASH_COMBINE_VALS_val_x_8(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_10(y, ...) \
- ._v10 = (y), _NM_HASH_COMBINE_VALS_val_x_9(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_11(y, ...) \
- ._v11 = (y), _NM_HASH_COMBINE_VALS_val_x_10(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_12(y, ...) \
- ._v12 = (y), _NM_HASH_COMBINE_VALS_val_x_11(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_13(y, ...) \
- ._v13 = (y), _NM_HASH_COMBINE_VALS_val_x_12(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_14(y, ...) \
- ._v14 = (y), _NM_HASH_COMBINE_VALS_val_x_13(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_15(y, ...) \
- ._v15 = (y), _NM_HASH_COMBINE_VALS_val_x_14(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_16(y, ...) \
- ._v16 = (y), _NM_HASH_COMBINE_VALS_val_x_15(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_17(y, ...) \
- ._v17 = (y), _NM_HASH_COMBINE_VALS_val_x_16(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_18(y, ...) \
- ._v18 = (y), _NM_HASH_COMBINE_VALS_val_x_17(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_19(y, ...) \
- ._v19 = (y), _NM_HASH_COMBINE_VALS_val_x_18(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_20(y, ...) \
- ._v20 = (y), _NM_HASH_COMBINE_VALS_val_x_19(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_n2(n, ...) _NM_HASH_COMBINE_VALS_val_x_##n(__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_n(n, ...) _NM_HASH_COMBINE_VALS_val_n2(n, __VA_ARGS__)
+#define _NM_HASH_COMBINE_VALS_TYPE_OP(x, idx) typeof(x) _v##idx;
+#define _NM_HASH_COMBINE_VALS_INIT_OP(x, idx) ._v##idx = (x),
/* NM_HASH_COMBINE_VALS() is faster then nm_hash_update_val() as it combines multiple
* calls to nm_hash_update() using a packed structure. */
-#define NM_HASH_COMBINE_VALS(var, ...) \
- const struct _nm_packed { \
- _NM_HASH_COMBINE_VALS_typ_n(NM_NARG(__VA_ARGS__), __VA_ARGS__) \
- } var _nm_alignas(guint64) = {_NM_HASH_COMBINE_VALS_val_n(NM_NARG(__VA_ARGS__), __VA_ARGS__)}
+#define NM_HASH_COMBINE_VALS(var, ...) \
+ const struct _nm_packed { \
+ NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_TYPE_OP, __VA_ARGS__) \
+ } var _nm_alignas(guint64) = { \
+ NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_INIT_OP, __VA_ARGS__)}
/* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple
* calls to nm_hash_update() using a packed structure. */
diff --git a/src/libnm-glib-aux/nm-macros-internal.h b/src/libnm-glib-aux/nm-macros-internal.h
index 39197ecf3a..23cf2f55a7 100644
--- a/src/libnm-glib-aux/nm-macros-internal.h
+++ b/src/libnm-glib-aux/nm-macros-internal.h
@@ -163,280 +163,6 @@ _nm_auto_freev(gpointer ptr)
/*****************************************************************************/
-#define _NM_MACRO_SELECT_ARG_64(_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
-
-/* http://stackoverflow.com/a/2124385/354393
- * https://stackoverflow.com/questions/11317474/macro-to-count-number-of-arguments
- */
-
-#define NM_NARG(...) \
- _NM_MACRO_SELECT_ARG_64(, \
- ##__VA_ARGS__, \
- 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)
-#define NM_NARG_MAX1(...) \
- _NM_MACRO_SELECT_ARG_64(, \
- ##__VA_ARGS__, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 1, \
- 0)
-#define NM_NARG_MAX2(...) \
- _NM_MACRO_SELECT_ARG_64(, \
- ##__VA_ARGS__, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 2, \
- 1, \
- 0)
-
-#define _NM_MACRO_CALL(macro, ...) macro(__VA_ARGS__)
-
-/*****************************************************************************/
-
#define _NM_MACRO_COMMA_IF_ARGS(...) \
_NM_MACRO_CALL(G_PASTE(__NM_MACRO_COMMA_IF_ARGS_, NM_NARG_MAX1(__VA_ARGS__)), __VA_ARGS__)
#define __NM_MACRO_COMMA_IF_ARGS_0()
@@ -1253,27 +979,21 @@ nm_g_variant_take_ref(GVariant *v)
return (v); \
}
#define NM_UTILS_LOOKUP_ITEM(v, n) \
- (void) 0; \
case v: \
- return (n); \
- (void) 0
+ return (n);
#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, "" n "")
#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) \
- (void) 0; \
case v: \
- break; \
- (void) 0
+ break;
#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() \
- (void) 0; \
default: \
- break; \
- (void) 0
+ break;
#define NM_UTILS_LOOKUP_DEFINE(fcn_name, lookup_type, result_type, unknown_val, ...) \
result_type fcn_name(lookup_type val) \
{ \
switch (val) { \
- (void) 0, __VA_ARGS__(void) 0; \
+ NM_VA_ARGS_JOIN(, __VA_ARGS__) \
}; \
{ \
unknown_val; \
@@ -1479,17 +1199,15 @@ nm_strcmp_p(gconstpointer a, gconstpointer b)
/*****************************************************************************/
static inline int
-_NM_IN_STRSET_ASCII_CASE_op_streq(const char *x, const char *s)
+_NM_IN_STRSET_EVAL_op_streq_ascii_case(const char *x1, const char *x)
{
- return s && g_ascii_strcasecmp(x, s) == 0;
+ return x && g_ascii_strcasecmp(x1, x) == 0;
}
-#define NM_IN_STRSET_ASCII_CASE(x, ...) \
- _NM_IN_STRSET_EVAL_N(||, \
- _NM_IN_STRSET_ASCII_CASE_op_streq, \
- x, \
- NM_NARG(__VA_ARGS__), \
- __VA_ARGS__)
+#define _NM_IN_STRSET_EVAL_OP_STREQ_ASCII_CASE(x, idx) \
+ _NM_IN_STRSET_EVAL_op_streq_ascii_case(_x1, x)
+#define NM_IN_STRSET_ASCII_CASE(x1, ...) \
+ _NM_IN_STRSET_EVAL(||, _NM_IN_STRSET_EVAL_OP_STREQ_ASCII_CASE, x1, __VA_ARGS__)
#define NM_STR_HAS_SUFFIX_ASCII_CASE(str, suffix) \
({ \
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index 0c2303656e..2e4215fdf7 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -1068,16 +1068,12 @@ const char *nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs,
/*****************************************************************************/
#define NM_UTILS_ENUM2STR(v, n) \
- (void) 0; \
case v: \
s = "" n ""; \
- break; \
- (void) 0
+ break;
#define NM_UTILS_ENUM2STR_IGNORE(v) \
- (void) 0; \
case v: \
- break; \
- (void) 0
+ break;
#define NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, int_fmt, ...) \
const char *fcn_name(lookup_type val, char *buf, gsize len) \
@@ -1086,7 +1082,7 @@ case v: \
if (len) { \
const char *s = NULL; \
switch (val) { \
- (void) 0, __VA_ARGS__(void) 0; \
+ NM_VA_ARGS_JOIN(, __VA_ARGS__) \
}; \
if (s) \
g_strlcpy(buf, s, len); \
@@ -1106,14 +1102,26 @@ case v: \
static inline void _nm_g_slice_free_fcn_##mem_size(gpointer mem_block) \
{ \
g_slice_free1(mem_size, mem_block); \
- }
+ } \
+ _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-_nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_fcn_define(4)
- _nm_g_slice_free_fcn_define(8) _nm_g_slice_free_fcn_define(10) _nm_g_slice_free_fcn_define(12)
- _nm_g_slice_free_fcn_define(16) _nm_g_slice_free_fcn_define(32)
+_nm_g_slice_free_fcn_define(1);
+_nm_g_slice_free_fcn_define(2);
+_nm_g_slice_free_fcn_define(4);
+_nm_g_slice_free_fcn_define(8);
+_nm_g_slice_free_fcn_define(10);
+_nm_g_slice_free_fcn_define(12);
+_nm_g_slice_free_fcn_define(16);
+_nm_g_slice_free_fcn_define(32);
+
+_nm_warn_unused_result static inline GDestroyNotify
+_nm_get_warn_unused_result_gdestroynotify(GDestroyNotify f)
+{
+ return f;
+}
#define nm_g_slice_free_fcn1(mem_size) \
- ({ \
+ _nm_get_warn_unused_result_gdestroynotify(({ \
void (*_fcn)(gpointer); \
\
/* If mem_size is a compile time constant, the compiler
@@ -1152,8 +1160,9 @@ _nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_f
_fcn = NULL; \
break; \
} \
+ \
_fcn; \
- })
+ }))
/**
* nm_g_slice_free_fcn:
@@ -1184,7 +1193,8 @@ _nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_f
_error && _error->domain == (err_domain) && NM_IN_SET(_error->code, __VA_ARGS__); \
})
- static inline void nm_g_set_error_take(GError **error, GError *error_take)
+static inline void
+nm_g_set_error_take(GError **error, GError *error_take)
{
if (!error_take)
g_return_if_reached();
diff --git a/src/libnm-glib-aux/nm-uuid.c b/src/libnm-glib-aux/nm-uuid.c
index 2c6e218a7c..0e3f4673e7 100644
--- a/src/libnm-glib-aux/nm-uuid.c
+++ b/src/libnm-glib-aux/nm-uuid.c
@@ -9,6 +9,13 @@
/*****************************************************************************/
+const NMUuid nm_uuid_ns_zero =
+ NM_UUID_INIT(00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00);
+
+/* arbitrarily chosen namespace UUID for nm_uuid_generate_from_strings() */
+const NMUuid nm_uuid_ns_1 =
+ NM_UUID_INIT(b4, 25, e9, fb, 75, 98, 44, b4, 9e, 3b, 5a, 2e, 3a, aa, 49, 05);
+
char *
nm_uuid_unparse_case(const NMUuid *uuid, char out_str[static 37], gboolean upper_case)
{
@@ -239,11 +246,12 @@ nm_uuid_is_valid_nm(const char *str,
str_lower[i] = g_ascii_tolower(str_lower[i]);
/* The namespace UUID is chosen randomly. */
- nm_uuid_generate_from_string(&uuid,
- str_lower,
- -1,
- NM_UUID_TYPE_VERSION5,
- "4e72f709-ca95-4405-9053-1f43294a618c");
+ nm_uuid_generate_from_string(
+ &uuid,
+ str_lower,
+ -1,
+ NM_UUID_TYPE_VERSION5,
+ &NM_UUID_INIT(4e, 72, f7, 09, ca, 95, 44, 05, 90, 53, 1f, 43, 29, 4a, 61, 8c));
nm_uuid_unparse(&uuid, out_normalized_str);
}
return TRUE;
@@ -299,11 +307,11 @@ nm_uuid_generate_random_str(char buf[static 37])
* Returns: the input @uuid. This function cannot fail.
**/
NMUuid *
-nm_uuid_generate_from_string(NMUuid * uuid,
- const char *s,
- gssize slen,
- NMUuidType uuid_type,
- gpointer type_args)
+nm_uuid_generate_from_string(NMUuid * uuid,
+ const char * s,
+ gssize slen,
+ NMUuidType uuid_type,
+ const NMUuid *type_args)
{
g_return_val_if_fail(uuid, FALSE);
g_return_val_if_fail(slen == 0 || s, FALSE);
@@ -313,26 +321,20 @@ nm_uuid_generate_from_string(NMUuid * uuid,
switch (uuid_type) {
case NM_UUID_TYPE_LEGACY:
- g_return_val_if_fail(!type_args, NULL);
+ nm_assert(!type_args);
nm_crypto_md5_hash(NULL, 0, (guint8 *) s, slen, (guint8 *) uuid, sizeof(*uuid));
break;
case NM_UUID_TYPE_VERSION3:
case NM_UUID_TYPE_VERSION5:
{
- NMUuid ns_uuid;
-
- if (type_args) {
- /* type_args can be a name space UUID. Interpret it as (char *) */
- if (!nm_uuid_parse(type_args, &ns_uuid))
- g_return_val_if_reached(NULL);
- } else
- ns_uuid = (NMUuid){};
+ if (!type_args)
+ type_args = &nm_uuid_ns_zero;
if (uuid_type == NM_UUID_TYPE_VERSION3) {
nm_crypto_md5_hash((guint8 *) s,
slen,
- (guint8 *) &ns_uuid,
- sizeof(ns_uuid),
+ (guint8 *) type_args,
+ sizeof(*type_args),
(guint8 *) uuid,
sizeof(*uuid));
} else {
@@ -343,7 +345,7 @@ nm_uuid_generate_from_string(NMUuid * uuid,
} digest;
sum = g_checksum_new(G_CHECKSUM_SHA1);
- g_checksum_update(sum, (guchar *) &ns_uuid, sizeof(ns_uuid));
+ g_checksum_update(sum, (guchar *) type_args, sizeof(*type_args));
g_checksum_update(sum, (guchar *) s, slen);
nm_utils_checksum_get_digest(sum, digest.sha1);
@@ -377,10 +379,10 @@ nm_uuid_generate_from_string(NMUuid * uuid,
* object's #NMSettingConnection:id: property
**/
char *
-nm_uuid_generate_from_string_str(const char *s,
- gssize slen,
- NMUuidType uuid_type,
- gpointer type_args)
+nm_uuid_generate_from_string_str(const char * s,
+ gssize slen,
+ NMUuidType uuid_type,
+ const NMUuid *type_args)
{
NMUuid uuid;
@@ -405,7 +407,7 @@ char *
nm_uuid_generate_from_strings(const char *string1, ...)
{
if (!string1)
- return nm_uuid_generate_from_string_str(NULL, 0, NM_UUID_TYPE_VERSION3, NM_UUID_NS1);
+ return nm_uuid_generate_from_string_str(NULL, 0, NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1);
{
nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
@@ -425,6 +427,6 @@ nm_uuid_generate_from_strings(const char *string1, ...)
return nm_uuid_generate_from_string_str(nm_str_buf_get_str_unsafe(&str),
str.len,
NM_UUID_TYPE_VERSION3,
- NM_UUID_NS1);
+ &nm_uuid_ns_1);
}
}
diff --git a/src/libnm-glib-aux/nm-uuid.h b/src/libnm-glib-aux/nm-uuid.h
index 10302bd87a..504ec789be 100644
--- a/src/libnm-glib-aux/nm-uuid.h
+++ b/src/libnm-glib-aux/nm-uuid.h
@@ -7,6 +7,28 @@ typedef struct _NMUuid {
guint8 uuid[16];
} NMUuid;
+#define NM_UUID_INIT_ZERO() ((NMUuid){.uuid = {0}})
+
+#define NM_UUID_INIT(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \
+ ((NMUuid){ \
+ .uuid = {(0x##a0), \
+ (0x##a1), \
+ (0x##a2), \
+ (0x##a3), \
+ (0x##a4), \
+ (0x##a5), \
+ (0x##a6), \
+ (0x##a7), \
+ (0x##a8), \
+ (0x##a9), \
+ (0x##a10), \
+ (0x##a11), \
+ (0x##a12), \
+ (0x##a13), \
+ (0x##a14), \
+ (0x##a15)}, \
+ })
+
char *nm_uuid_unparse_case(const NMUuid *uuid, char out_str[static 37], gboolean upper_case);
static inline char *
@@ -73,25 +95,30 @@ char *nm_uuid_generate_random_str(char buf[static 37]);
/*****************************************************************************/
+extern const NMUuid nm_uuid_ns_zero;
+extern const NMUuid nm_uuid_ns_1;
+
+#define NM_UUID_NS_ZERO "00000000-0000-0000-0000-000000000000"
+#define NM_UUID_NS_1 "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
+
+/*****************************************************************************/
+
typedef enum {
NM_UUID_TYPE_LEGACY = 0,
NM_UUID_TYPE_VERSION3 = 3,
NM_UUID_TYPE_VERSION5 = 5,
} NMUuidType;
-NMUuid *nm_uuid_generate_from_string(NMUuid * uuid,
- const char *s,
- gssize slen,
- NMUuidType uuid_type,
- gpointer type_args);
-
-char *nm_uuid_generate_from_string_str(const char *s,
- gssize slen,
- NMUuidType uuid_type,
- gpointer type_args);
+NMUuid *nm_uuid_generate_from_string(NMUuid * uuid,
+ const char * s,
+ gssize slen,
+ NMUuidType uuid_type,
+ const NMUuid *type_args);
-/* arbitrarily chosen namespace UUID for nm_uuid_generate_from_strings() */
-#define NM_UUID_NS1 "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
+char *nm_uuid_generate_from_string_str(const char * s,
+ gssize slen,
+ NMUuidType uuid_type,
+ const NMUuid *type_args);
char *nm_uuid_generate_from_strings(const char *string1, ...) G_GNUC_NULL_TERMINATED;
diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h
index b153866fd8..7ad6294d71 100644
--- a/src/libnm-std-aux/nm-std-aux.h
+++ b/src/libnm-std-aux/nm-std-aux.h
@@ -13,17 +13,18 @@
/*****************************************************************************/
-#define _nm_packed __attribute__((__packed__))
-#define _nm_unused __attribute__((__unused__))
-#define _nm_used __attribute__((__used__))
-#define _nm_pure __attribute__((__pure__))
-#define _nm_const __attribute__((__const__))
-#define _nm_printf(a, b) __attribute__((__format__(__printf__, a, b)))
-#define _nm_align(s) __attribute__((__aligned__(s)))
-#define _nm_section(s) __attribute__((__section__(s)))
-#define _nm_alignof(type) __alignof(type)
-#define _nm_alignas(type) _nm_align(_nm_alignof(type))
-#define nm_auto(fcn) __attribute__((__cleanup__(fcn)))
+#define _nm_packed __attribute__((__packed__))
+#define _nm_unused __attribute__((__unused__))
+#define _nm_used __attribute__((__used__))
+#define _nm_pure __attribute__((__pure__))
+#define _nm_const __attribute__((__const__))
+#define _nm_warn_unused_result __attribute__((__warn_unused_result__))
+#define _nm_printf(a, b) __attribute__((__format__(__printf__, a, b)))
+#define _nm_align(s) __attribute__((__aligned__(s)))
+#define _nm_section(s) __attribute__((__section__(s)))
+#define _nm_alignof(type) __alignof(type)
+#define _nm_alignas(type) _nm_align(_nm_alignof(type))
+#define nm_auto(fcn) __attribute__((__cleanup__(fcn)))
/* This is required to make LTO working.
*
@@ -81,6 +82,10 @@ typedef uint64_t _nm_bitwise nm_be64_t;
/*****************************************************************************/
+#define NM_BIT(n) (1ull << (n))
+
+/*****************************************************************************/
+
#define NM_PASTE_ARGS(identifier1, identifier2) identifier1##identifier2
#define NM_PASTE(identifier1, identifier2) NM_PASTE_ARGS(identifier1, identifier2)
@@ -187,6 +192,12 @@ typedef uint64_t _nm_bitwise nm_be64_t;
#define NM_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
+/* This does a compile time check that "type" is a suitable C type. It either
+ * returns a compile time constant of 1 or it fails compilation. The point
+ * is only in macros to check that a macro parameter (what we might pass to
+ * sizeof() is really a type, and not a variable. */
+#define NM_ENSURE_IS_TYPE(type) (sizeof(void (*)(type[])) == sizeof(void (*)(void *)))
+
/*****************************************************************************/
static inline uint32_t
@@ -404,50 +415,230 @@ nm_streq0(const char *s1, const char *s2)
/*****************************************************************************/
-#define _NM_IN_SET_EVAL_1(op, _x, y) (_x == (y))
-#define _NM_IN_SET_EVAL_2(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_1(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_3(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_2(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_4(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_3(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_5(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_4(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_6(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_5(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_7(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_6(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_8(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_7(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_9(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_8(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_10(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_9(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_11(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_10(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_12(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_11(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_13(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_12(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_14(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_13(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_15(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_14(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_16(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_15(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_17(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_16(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_18(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_17(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_19(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_18(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_20(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_19(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_21(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_20(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_22(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_21(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_23(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_22(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_24(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_23(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_25(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_24(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_26(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_25(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_27(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_26(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_28(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_27(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_29(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_28(op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_30(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_29(op, _x, __VA_ARGS__)
-
-#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, type, x, n, ...) \
- ({ \
- type _x = (x); \
- \
- /* trigger a -Wenum-compare warning */ \
- nm_assert(true || _x == (x)); \
- \
- !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__); \
- })
+/* clang-format off */
+#define _NM_MACRO_SELECT_ARG_120(_empty, \
+ _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, _64, _65, _66, _67, _68, _69, _70, \
+ _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \
+ _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \
+ _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, \
+ _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, \
+ _111, _112, _113, _114, _115, _116, _117, _118, _119, _120, \
+ N, \
+ ...) \
+ N
+
+#define NM_NARG(...) \
+ _NM_MACRO_SELECT_ARG_120(, ##__VA_ARGS__, \
+ 120, \
+ 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, \
+ 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, \
+ 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, \
+ 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
+ 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, \
+ 69, 68, 67, 66, 65, 64, 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)
+#define NM_NARG_MAX1(...) \
+ _NM_MACRO_SELECT_ARG_120(, ##__VA_ARGS__, \
+ 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 110 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 100 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
+#define NM_NARG_MAX2(...) \
+ _NM_MACRO_SELECT_ARG_120(, ##__VA_ARGS__, \
+ 2, \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 110 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 100 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 90 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 80 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 70 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 60 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 50 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 40 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 30 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 20 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 10 */ \
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 0)
+/* clang-format on */
+
+/*****************************************************************************/
+
+#define _NM_MACRO_IDENTITY(...) __VA_ARGS__
+
+#define _NM_MACRO_SELECT_FIRST(...) _NM_MACRO_SELECT_FIRST_IMPL(__VA_ARGS__, throwaway)
+#define _NM_MACRO_SELECT_FIRST_IMPL(first, ...) first
+
+#define _NM_MACRO_CALL(macro, ...) macro(__VA_ARGS__)
+#define _NM_MACRO_CALL2(macro, ...) macro(__VA_ARGS__)
+
+/*****************************************************************************/
+
+/* clang-format off */
+#define _NM_VA_ARGS_FOREACH_0(prefix, postfix, sep, op)
+#define _NM_VA_ARGS_FOREACH_1(prefix, postfix, sep, op, x) prefix _NM_MACRO_CALL2(op, x, 0 ) postfix
+#define _NM_VA_ARGS_FOREACH_2(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 1 ) postfix sep _NM_VA_ARGS_FOREACH_1(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_3(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 2 ) postfix sep _NM_VA_ARGS_FOREACH_2(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_4(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 3 ) postfix sep _NM_VA_ARGS_FOREACH_3(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_5(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 4 ) postfix sep _NM_VA_ARGS_FOREACH_4(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_6(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 5 ) postfix sep _NM_VA_ARGS_FOREACH_5(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_7(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 6 ) postfix sep _NM_VA_ARGS_FOREACH_6(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_8(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 7 ) postfix sep _NM_VA_ARGS_FOREACH_7(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_9(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 8 ) postfix sep _NM_VA_ARGS_FOREACH_8(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_10(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 9 ) postfix sep _NM_VA_ARGS_FOREACH_9(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_11(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 10 ) postfix sep _NM_VA_ARGS_FOREACH_10(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_12(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 11 ) postfix sep _NM_VA_ARGS_FOREACH_11(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_13(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 12 ) postfix sep _NM_VA_ARGS_FOREACH_12(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_14(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 13 ) postfix sep _NM_VA_ARGS_FOREACH_13(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_15(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 14 ) postfix sep _NM_VA_ARGS_FOREACH_14(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_16(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 15 ) postfix sep _NM_VA_ARGS_FOREACH_15(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_17(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 16 ) postfix sep _NM_VA_ARGS_FOREACH_16(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_18(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 17 ) postfix sep _NM_VA_ARGS_FOREACH_17(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_19(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 18 ) postfix sep _NM_VA_ARGS_FOREACH_18(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_20(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 19 ) postfix sep _NM_VA_ARGS_FOREACH_19(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_21(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 20 ) postfix sep _NM_VA_ARGS_FOREACH_20(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_22(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 21 ) postfix sep _NM_VA_ARGS_FOREACH_21(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_23(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 22 ) postfix sep _NM_VA_ARGS_FOREACH_22(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_24(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 23 ) postfix sep _NM_VA_ARGS_FOREACH_23(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_25(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 24 ) postfix sep _NM_VA_ARGS_FOREACH_24(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_26(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 25 ) postfix sep _NM_VA_ARGS_FOREACH_25(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_27(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 26 ) postfix sep _NM_VA_ARGS_FOREACH_26(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_28(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 27 ) postfix sep _NM_VA_ARGS_FOREACH_27(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_29(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 28 ) postfix sep _NM_VA_ARGS_FOREACH_28(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_30(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 29 ) postfix sep _NM_VA_ARGS_FOREACH_29(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_31(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 30 ) postfix sep _NM_VA_ARGS_FOREACH_30(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_32(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 31 ) postfix sep _NM_VA_ARGS_FOREACH_31(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_33(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 32 ) postfix sep _NM_VA_ARGS_FOREACH_32(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_34(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 33 ) postfix sep _NM_VA_ARGS_FOREACH_33(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_35(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 34 ) postfix sep _NM_VA_ARGS_FOREACH_34(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_36(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 35 ) postfix sep _NM_VA_ARGS_FOREACH_35(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_37(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 36 ) postfix sep _NM_VA_ARGS_FOREACH_36(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_38(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 37 ) postfix sep _NM_VA_ARGS_FOREACH_37(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_39(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 38 ) postfix sep _NM_VA_ARGS_FOREACH_38(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_40(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 39 ) postfix sep _NM_VA_ARGS_FOREACH_39(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_41(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 40 ) postfix sep _NM_VA_ARGS_FOREACH_40(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_42(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 41 ) postfix sep _NM_VA_ARGS_FOREACH_41(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_43(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 42 ) postfix sep _NM_VA_ARGS_FOREACH_42(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_44(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 43 ) postfix sep _NM_VA_ARGS_FOREACH_43(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_45(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 44 ) postfix sep _NM_VA_ARGS_FOREACH_44(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_46(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 45 ) postfix sep _NM_VA_ARGS_FOREACH_45(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_47(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 46 ) postfix sep _NM_VA_ARGS_FOREACH_46(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_48(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 47 ) postfix sep _NM_VA_ARGS_FOREACH_47(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_49(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 48 ) postfix sep _NM_VA_ARGS_FOREACH_48(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_50(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 49 ) postfix sep _NM_VA_ARGS_FOREACH_49(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_51(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 50 ) postfix sep _NM_VA_ARGS_FOREACH_50(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_52(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 51 ) postfix sep _NM_VA_ARGS_FOREACH_51(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_53(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 52 ) postfix sep _NM_VA_ARGS_FOREACH_52(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_54(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 53 ) postfix sep _NM_VA_ARGS_FOREACH_53(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_55(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 54 ) postfix sep _NM_VA_ARGS_FOREACH_54(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_56(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 55 ) postfix sep _NM_VA_ARGS_FOREACH_55(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_57(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 56 ) postfix sep _NM_VA_ARGS_FOREACH_56(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_58(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 57 ) postfix sep _NM_VA_ARGS_FOREACH_57(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_59(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 58 ) postfix sep _NM_VA_ARGS_FOREACH_58(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_60(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 59 ) postfix sep _NM_VA_ARGS_FOREACH_59(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_61(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 10 ) postfix sep _NM_VA_ARGS_FOREACH_60(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_62(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 61 ) postfix sep _NM_VA_ARGS_FOREACH_61(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_63(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 62 ) postfix sep _NM_VA_ARGS_FOREACH_62(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_64(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 63 ) postfix sep _NM_VA_ARGS_FOREACH_63(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_65(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 64 ) postfix sep _NM_VA_ARGS_FOREACH_64(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_66(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 65 ) postfix sep _NM_VA_ARGS_FOREACH_65(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_67(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 66 ) postfix sep _NM_VA_ARGS_FOREACH_66(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_68(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 67 ) postfix sep _NM_VA_ARGS_FOREACH_67(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_69(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 68 ) postfix sep _NM_VA_ARGS_FOREACH_68(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_70(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 69 ) postfix sep _NM_VA_ARGS_FOREACH_69(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_71(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 70 ) postfix sep _NM_VA_ARGS_FOREACH_70(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_72(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 71 ) postfix sep _NM_VA_ARGS_FOREACH_71(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_73(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 72 ) postfix sep _NM_VA_ARGS_FOREACH_72(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_74(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 73 ) postfix sep _NM_VA_ARGS_FOREACH_73(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_75(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 74 ) postfix sep _NM_VA_ARGS_FOREACH_74(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_76(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 75 ) postfix sep _NM_VA_ARGS_FOREACH_75(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_77(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 76 ) postfix sep _NM_VA_ARGS_FOREACH_76(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_78(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 77 ) postfix sep _NM_VA_ARGS_FOREACH_77(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_79(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 78 ) postfix sep _NM_VA_ARGS_FOREACH_78(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_80(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 79 ) postfix sep _NM_VA_ARGS_FOREACH_79(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_81(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 80 ) postfix sep _NM_VA_ARGS_FOREACH_80(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_82(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 81 ) postfix sep _NM_VA_ARGS_FOREACH_81(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_83(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 82 ) postfix sep _NM_VA_ARGS_FOREACH_82(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_84(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 83 ) postfix sep _NM_VA_ARGS_FOREACH_83(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_85(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 84 ) postfix sep _NM_VA_ARGS_FOREACH_84(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_86(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 85 ) postfix sep _NM_VA_ARGS_FOREACH_85(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_87(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 86 ) postfix sep _NM_VA_ARGS_FOREACH_86(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_88(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 87 ) postfix sep _NM_VA_ARGS_FOREACH_87(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_89(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 88 ) postfix sep _NM_VA_ARGS_FOREACH_88(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_90(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 89 ) postfix sep _NM_VA_ARGS_FOREACH_89(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_91(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 90 ) postfix sep _NM_VA_ARGS_FOREACH_90(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_92(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 91 ) postfix sep _NM_VA_ARGS_FOREACH_91(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_93(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 92 ) postfix sep _NM_VA_ARGS_FOREACH_92(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_94(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 93 ) postfix sep _NM_VA_ARGS_FOREACH_93(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_95(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 94 ) postfix sep _NM_VA_ARGS_FOREACH_94(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_96(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 95 ) postfix sep _NM_VA_ARGS_FOREACH_95(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_97(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 96 ) postfix sep _NM_VA_ARGS_FOREACH_96(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_98(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 97 ) postfix sep _NM_VA_ARGS_FOREACH_97(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_99(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 98 ) postfix sep _NM_VA_ARGS_FOREACH_98(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_100(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 99 ) postfix sep _NM_VA_ARGS_FOREACH_99(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_101(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 100) postfix sep _NM_VA_ARGS_FOREACH_100(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_102(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 101) postfix sep _NM_VA_ARGS_FOREACH_101(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_103(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 102) postfix sep _NM_VA_ARGS_FOREACH_102(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_104(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 103) postfix sep _NM_VA_ARGS_FOREACH_103(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_105(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 104) postfix sep _NM_VA_ARGS_FOREACH_104(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_106(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 105) postfix sep _NM_VA_ARGS_FOREACH_105(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_107(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 106) postfix sep _NM_VA_ARGS_FOREACH_106(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_108(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 107) postfix sep _NM_VA_ARGS_FOREACH_107(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_109(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 108) postfix sep _NM_VA_ARGS_FOREACH_108(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_110(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 109) postfix sep _NM_VA_ARGS_FOREACH_109(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_111(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 100) postfix sep _NM_VA_ARGS_FOREACH_110(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_112(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 111) postfix sep _NM_VA_ARGS_FOREACH_111(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_113(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 112) postfix sep _NM_VA_ARGS_FOREACH_112(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_114(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 113) postfix sep _NM_VA_ARGS_FOREACH_113(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_115(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 114) postfix sep _NM_VA_ARGS_FOREACH_114(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_116(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 115) postfix sep _NM_VA_ARGS_FOREACH_115(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_117(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 116) postfix sep _NM_VA_ARGS_FOREACH_116(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_118(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 117) postfix sep _NM_VA_ARGS_FOREACH_117(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_119(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 118) postfix sep _NM_VA_ARGS_FOREACH_118(prefix, postfix, sep, op, __VA_ARGS__)
+#define _NM_VA_ARGS_FOREACH_120(prefix, postfix, sep, op, x, ...) prefix _NM_MACRO_CALL2(op, x, 119) postfix sep _NM_VA_ARGS_FOREACH_119(prefix, postfix, sep, op, __VA_ARGS__)
+/* clang-format on */
+#define NM_VA_ARGS_FOREACH(prefix, postfix, sep, op, ...) \
+ _NM_MACRO_CALL(NM_PASTE(_NM_VA_ARGS_FOREACH_, NM_NARG(__VA_ARGS__)), \
+ prefix, \
+ postfix, \
+ sep, \
+ op, \
+ ##__VA_ARGS__)
+
+/*****************************************************************************/
+
+#define NM_VA_ARGS_JOIN(sep, ...) NM_VA_ARGS_FOREACH(, , sep, _NM_MACRO_SELECT_FIRST, __VA_ARGS__)
+
+/*****************************************************************************/
-#define _NM_IN_SET(op, type, x, ...) \
- _NM_IN_SET_EVAL_N(op, type, x, NM_NARG(__VA_ARGS__), __VA_ARGS__)
+#define _NM_IN_SET_OP(x, idx) (_x == (x))
+#define _NM_IN_SET(op, type, x, ...) \
+ ({ \
+ type _x = (x); \
+ \
+ /* trigger a -Wenum-compare warning */ \
+ nm_assert(true || _x == (x)); \
+ \
+ !!(NM_VA_ARGS_FOREACH(, , op, _NM_IN_SET_OP, __VA_ARGS__)); \
+ })
/* Beware that this does short-circuit evaluation (use "||" instead of "|")
* which has a possibly unexpected non-function-like behavior.
@@ -468,96 +659,31 @@ nm_streq0(const char *s1, const char *s2)
/*****************************************************************************/
-#define _NM_IN_SETOP_EVAL_1(op, op_eq, _x, y) (op_eq(_x, y))
-#define _NM_IN_SETOP_EVAL_2(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_1(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_3(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_2(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_4(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_3(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_5(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_4(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_6(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_5(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_7(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_6(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_8(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_7(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_9(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_8(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_10(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_9(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_11(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_10(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_12(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_11(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_13(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_12(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_14(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_13(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_15(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_14(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_16(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_15(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_17(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_16(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_18(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_17(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_19(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_18(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_20(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_19(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_21(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_20(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_22(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_21(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_23(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_22(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_24(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_23(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_25(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_24(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_26(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_25(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_27(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_26(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_28(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_27(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_29(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_28(op, op_eq, _x, __VA_ARGS__)
-#define _NM_IN_SETOP_EVAL_30(op, op_eq, _x, y, ...) \
- (op_eq(_x, y)) op _NM_IN_SETOP_EVAL_29(op, op_eq, _x, __VA_ARGS__)
-
-/*****************************************************************************/
-
-#define _NM_IN_STRSET_EVAL_N2(op, op_ed, _x, n, ...) \
- (_NM_IN_SETOP_EVAL_##n(op, op_ed, _x, __VA_ARGS__))
-#define _NM_IN_STRSET_EVAL_N(op, op_ed, x, n, ...) \
- ({ \
- const char *_x = (x); \
- (((_x == NULL) && _NM_IN_SET_EVAL_N2(op, ((const char *) NULL), n, __VA_ARGS__)) \
- || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2(op, op_ed, _x, n, __VA_ARGS__))); \
- })
-
-/*****************************************************************************/
-
static inline int
-_NM_IN_STRSET_op_streq(const char *x, const char *s)
+_NM_IN_STRSET_EVAL_op_streq(const char *x1, const char *x)
{
- return s && strcmp(x, s) == 0;
+ return x && nm_streq(x1, x);
}
+#define _NM_IN_STRSET_EVAL_OP_NULL(x, idx) (((const char *) NULL) == (x))
+#define _NM_IN_STRSET_EVAL_OP_STREQ(x, idx) _NM_IN_STRSET_EVAL_op_streq(_x1, x)
+#define _NM_IN_STRSET_EVAL(op, eval_op, x1, ...) \
+ ({ \
+ const char *const _x1 = (x1); \
+ \
+ !!(_x1 ? (NM_VA_ARGS_FOREACH(, , op, eval_op, __VA_ARGS__)) \
+ : (NM_VA_ARGS_FOREACH(, , op, _NM_IN_STRSET_EVAL_OP_NULL, __VA_ARGS__))); \
+ })
+
/* Beware that this does short-circuit evaluation (use "||" instead of "|")
* which has a possibly unexpected non-function-like behavior.
* Use NM_IN_STRSET_SE if you need all arguments to be evaluated. */
-#define NM_IN_STRSET(x, ...) \
- _NM_IN_STRSET_EVAL_N(||, _NM_IN_STRSET_op_streq, x, NM_NARG(__VA_ARGS__), __VA_ARGS__)
+#define NM_IN_STRSET(x1, ...) _NM_IN_STRSET_EVAL(||, _NM_IN_STRSET_EVAL_OP_STREQ, x1, __VA_ARGS__)
/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do
* short-circuit evaluation, which can make a difference if the arguments have
* side-effects. */
-#define NM_IN_STRSET_SE(x, ...) \
- _NM_IN_STRSET_EVAL_N(|, _NM_IN_STRSET_op_streq, x, NM_NARG(__VA_ARGS__), __VA_ARGS__)
+#define NM_IN_STRSET_SE(x1, ...) _NM_IN_STRSET_EVAL(|, _NM_IN_STRSET_EVAL_OP_STREQ, x1, __VA_ARGS__)
/*****************************************************************************/
diff --git a/tools/generate-docs-nm-settings-docs-merge.py b/tools/generate-docs-nm-settings-docs-merge.py
index a478ae75a3..33c8eff0df 100755
--- a/tools/generate-docs-nm-settings-docs-merge.py
+++ b/tools/generate-docs-nm-settings-docs-merge.py
@@ -9,6 +9,14 @@ import xml.etree.ElementTree as ET
###############################################################################
+
+def dbg(msg):
+ pass
+ # print("%s" % (msg,))
+
+
+###############################################################################
+
_setting_name_order = [
"connection",
"6lowpan",
@@ -123,6 +131,9 @@ gl_input_files = list(argv[1:])
###############################################################################
+for f in gl_input_files:
+ dbg("> input file %s" % (f))
+
xml_roots = list([ET.parse(f).getroot() for f in gl_input_files])
assert all([root.tag == "nm-setting-docs" for root in xml_roots])
@@ -133,14 +144,18 @@ root_node = ET.Element("nm-setting-docs")
for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name):
+ dbg("> > setting_name: %s" % (setting_name))
+
settings = list([d.get(setting_name) for d in settings_roots])
if gl_only_from_first and settings[0] is None:
+ dbg("> > > skip (only-from-first")
continue
properties = list([node_to_dict(s, "property", "name") for s in settings])
if gl_only_from_first and not properties[0]:
+ dbg("> > > skip (no properties")
continue
setting_node = ET.SubElement(root_node, "setting")
@@ -151,17 +166,24 @@ for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name):
node_set_attr(setting_node, "name_upper", settings)
node_set_attr(setting_node, "alias", settings)
+ dbg("> > > create node")
+
for property_name in iter_keys_of_dicts(properties):
+ dbg("> > > > property_name: %s" % (property_name))
+
properties_attrs = list([p.get(property_name) for p in properties])
if gl_only_from_first and properties_attrs[0] is None:
+ dbg("> > > > skip (only-from-first")
continue
property_node = ET.SubElement(setting_node, "property")
property_node.set("name", property_name)
property_node.set("name_upper", property_name.upper().replace("-", "_"))
+ dbg("> > > > > create node")
+
x = node_get_attr(properties_attrs, "format")
if x:
property_node.set("type", x)