1 /* The meat of this file is a copy of the FreeBSD sys/link_set.h */
2 /*
3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4  *
5  * Copyright (c) 1999 John D. Polstra
6  * Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 
33 #include <stdio.h>
34 
35 #define	MAKE_SET(set, sym)					\
36 	__asm__(".globl __start_set_" #set);			\
37 	__asm__(".globl __stop_set_" #set);			\
38 	static __attribute__((section("set_" #set), used))	\
39 	void const *__set_##set##_sym_##sym = &(sym)
40 
41 /*
42  * Initialize before referring to a given linker set.
43  */
44 #define	SET_DECLARE(set, ptype)						\
45 	extern  __attribute__((weak)) ptype *__start_set_ ## set;	\
46 	extern __attribute__((weak)) ptype *__stop_set_ ## set
47 
48 #define	SET_BEGIN(set)	(&__start_set_ ## set)
49 #define	SET_LIMIT(set)	(&__stop_set_ ## set)
50 
51 /*
52  * Iterate over all the elements of a set.
53  *
54  * Sets always contain addresses of things, and "pvar" points to words
55  * containing those addresses.  Thus is must be declared as "type **pvar",
56  * and the address of each set item is obtained inside the loop by "*pvar".
57  */
58 #define	SET_FOREACH(pvar, set)						\
59 	for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
60 
61 #define	SET_ITEM(set, i)						\
62 	((SET_BEGIN(set))[i])
63 
64 /*
65  * Provide a count of the items in a set.
66  */
67 #define	SET_COUNT(set)							\
68 	(SET_LIMIT(set) - SET_BEGIN(set))
69 
70 struct foo {
71 	char buf[128];
72 };
73 
74 SET_DECLARE(foo, struct foo);
75 
76 struct foo a = { "foo" };
77 struct foo b = { "bar" };
78 struct foo c = { "baz" };
79 
80 MAKE_SET(foo, a);
81 MAKE_SET(foo, b);
82 MAKE_SET(foo, c);
83 
84 int
85 main(int __attribute__((unused)) argc, char __attribute__((unused)) **argv)
86 {
87 	struct foo **c;
88 	int i = 0;
89 
90 	printf("Set count: %d\n", SET_COUNT(foo));
91 
92 
93 	printf("a: %s\n", ((struct foo *)__set_foo_sym_a)->buf);
94 	printf("b: %s\n", ((struct foo *)__set_foo_sym_b)->buf);
95 	printf("c: %s\n", ((struct foo *)__set_foo_sym_c)->buf);
96 
97 	printf("item(foo, 0): %s\n", SET_ITEM(foo, 0)->buf);
98 	printf("item(foo, 1): %s\n", SET_ITEM(foo, 1)->buf);
99 	printf("item(foo, 2): %s\n", SET_ITEM(foo, 2)->buf);
100 
101 	SET_FOREACH(c, foo) {
102 		printf("foo[%d]: %s\n", i, (*c)->buf);
103 		i++;
104 	}
105 }
106