diff options
author | Thomas Haller <thaller@redhat.com> | 2021-06-16 20:26:43 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-06-16 20:26:45 +0200 |
commit | 161cf11cb19625c87c8524af0c38f808651f9fdf (patch) | |
tree | 63d4bd8bbb8588e8b60195b3239c77d5d4a305f4 | |
parent | d9c0d43879e8420dda6482b05341dcfeedf7be43 (diff) | |
parent | 35b0b4c93886d75e6d6bdf282845ba3d0fd6ade9 (diff) |
release: bump version to 1.33.1 (development)1.33.1-dev
-rw-r--r-- | CONTRIBUTING.md | 48 | ||||
-rw-r--r-- | Makefile.examples | 1 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rwxr-xr-x | contrib/scripts/NM-log | 2 | ||||
-rwxr-xr-x | contrib/scripts/test-create-many-device-setup.sh | 117 | ||||
-rwxr-xr-x | examples/python/gi/nm-up-many.py | 373 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | src/core/NetworkManagerUtils.c | 6 | ||||
-rw-r--r-- | src/core/nm-core-utils.c | 21 | ||||
-rw-r--r-- | src/libnm-client-impl/nm-libnm-utils.h | 38 | ||||
-rw-r--r-- | src/libnm-core-impl/tests/test-general.c | 201 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-hash-utils.h | 144 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-macros-internal.h | 302 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.h | 38 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-uuid.c | 58 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-uuid.h | 51 | ||||
-rw-r--r-- | src/libnm-std-aux/nm-std-aux.h | 392 | ||||
-rwxr-xr-x | tools/generate-docs-nm-settings-docs-merge.py | 22 |
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 \ @@ -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) |