/* SPDX-License-Identifier: Apache-2.0 */

#ifndef __MACROS_H
#define __MACROS_H

// Internal helpers to concatenate two tokens. Do not use directly
#define __CONCAT_IMPL(x, y) x##y
#define __CONCAT(x, y) __CONCAT_IMPL(x, y)

// Internal helpers to count the number of arguments. Do not use directly
#define __VA_NARGS_IMPL(_1, _2, _3, _4, N, ...) N
#define __VA_NARGS(...) __VA_NARGS_IMPL(__VA_ARGS__, 4, 3, 2, 1)

// Internal helpers to expand the snapshotter's programs. Do not use directly
#define __GADGET_SNAPSHOTTER_PROGRAMS_EXPAND_1(name, type, programName1) \
	const void *gadget_snapshotter_##name##___##type##___##programName1 __attribute__((unused));
#define __GADGET_SNAPSHOTTER_PROGRAMS_EXPAND_2(name, type, programName1, programName2) \
	const void *gadget_snapshotter_##name##___##type##___##programName1##___##programName2 __attribute__((unused));
#define __GADGET_SNAPSHOTTER_PROGRAMS_EXPAND_3(name, type, programName1, programName2, programName3) \
	const void *gadget_snapshotter_##name##___##type##___##programName1##___##programName2##___##programName3 __attribute__((unused));
#define __GADGET_SNAPSHOTTER_PROGRAMS_EXPAND(name, type, nargs, ...) \
	__CONCAT(__GADGET_SNAPSHOTTER_PROGRAMS_EXPAND_, nargs)(name, type, __VA_ARGS__)
#define __GADGET_SNAPSHOTTER_IMPL(name, type, ...) \
	__GADGET_SNAPSHOTTER_PROGRAMS_EXPAND(name, type, __VA_NARGS(__VA_ARGS__), __VA_ARGS__)

// Public macros. Use these in your code
// Keep this aligned with pkg/gadgets/run/types/metadata.go

// GADGET_TRACER is used to define a tracer. Currently only one tracer per eBPF object is allowed.
// name is the tracer's name
// map_name is the name of the perf event array or ring buffer maps used to send events to user
// space
// event_type is the name of the structure that describes the event
#define GADGET_TRACER(name, map_name, event_type) \
	const void *gadget_tracer_##name##___##map_name##___##event_type __attribute__((unused)); \
	const struct event_type *__gadget_tracer_type_##name __attribute__((unused));

// GADGET_PARAM is used to indicate that a given variable is used as a parameter.
// Users of Inspektor Gadget can set these values from userspace
#define GADGET_PARAM(name) \
	const void * gadget_param_##name __attribute__((unused));

// GADGET_SNAPSHOTTER is used to define a snapshotter:
// name is the snapshotter's name
// type is the name of the structure that describes each element in a snapshot
// ... is the variadic list of programs (min 1, max 3) that generate a snapshot
// The snapshotter's output will be the union of the snapshots generated by the programs
#define GADGET_SNAPSHOTTER(name, type, ...) \
	const struct type *unusedevent_##name##___##type __attribute__((unused)); \
    __GADGET_SNAPSHOTTER_IMPL(name, type, __VA_ARGS__)

// GADGET_MAPITER defines maps that IG should periodically fetch into data sources
// - name is the name of the map iterator
// - mapname is the name of the hash map used to send events to user space.
#define GADGET_MAPITER(name, mapname) \
	const void *gadget_mapiter_##name##___##mapname __attribute__((unused));

#endif /* __MACROS_H */
