did_you_mean 0.9.2 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/ext/did_you_mean/extconf.rb +0 -23
- data/ext/did_you_mean/method_missing.c +8 -97
- data/ext/did_you_mean/org/yukinishijima/ReceiverCapturer.java +1 -2
- data/lib/did_you_mean/finders/similar_method_finder.rb +2 -1
- data/lib/did_you_mean/version.rb +1 -1
- data/test/no_method_error_extension_test.rb +1 -1
- metadata +2 -105
- data/ext/did_you_mean/ruby_headers/193/debug.h +0 -41
- data/ext/did_you_mean/ruby_headers/193/id.h +0 -171
- data/ext/did_you_mean/ruby_headers/193/internal.h +0 -242
- data/ext/did_you_mean/ruby_headers/193/method.h +0 -105
- data/ext/did_you_mean/ruby_headers/193/node.h +0 -504
- data/ext/did_you_mean/ruby_headers/193/ruby_atomic.h +0 -122
- data/ext/did_you_mean/ruby_headers/193/thread_pthread.h +0 -51
- data/ext/did_you_mean/ruby_headers/193/thread_win32.h +0 -40
- data/ext/did_you_mean/ruby_headers/193/vm_core.h +0 -763
- data/ext/did_you_mean/ruby_headers/193/vm_opts.h +0 -51
- data/ext/did_you_mean/ruby_headers/200/id.h +0 -171
- data/ext/did_you_mean/ruby_headers/200/internal.h +0 -392
- data/ext/did_you_mean/ruby_headers/200/method.h +0 -138
- data/ext/did_you_mean/ruby_headers/200/node.h +0 -539
- data/ext/did_you_mean/ruby_headers/200/ruby_atomic.h +0 -165
- data/ext/did_you_mean/ruby_headers/200/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/200/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/200/vm_core.h +0 -1013
- data/ext/did_you_mean/ruby_headers/200/vm_debug.h +0 -41
- data/ext/did_you_mean/ruby_headers/200/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/210/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/210/internal.h +0 -889
- data/ext/did_you_mean/ruby_headers/210/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/210/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/210/ruby_atomic.h +0 -165
- data/ext/did_you_mean/ruby_headers/210/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/210/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/210/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/210/vm_core.h +0 -1043
- data/ext/did_you_mean/ruby_headers/210/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/210/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/211/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/211/internal.h +0 -889
- data/ext/did_you_mean/ruby_headers/211/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/211/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/211/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/211/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/211/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/211/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/211/vm_core.h +0 -1043
- data/ext/did_you_mean/ruby_headers/211/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/211/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/212/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/212/internal.h +0 -889
- data/ext/did_you_mean/ruby_headers/212/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/212/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/212/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/212/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/212/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/212/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/212/vm_core.h +0 -1043
- data/ext/did_you_mean/ruby_headers/212/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/212/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/213/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/213/internal.h +0 -892
- data/ext/did_you_mean/ruby_headers/213/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/213/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/213/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/213/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/213/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/213/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/213/vm_core.h +0 -1052
- data/ext/did_you_mean/ruby_headers/213/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/213/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/214/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/214/internal.h +0 -892
- data/ext/did_you_mean/ruby_headers/214/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/214/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/214/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/214/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/214/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/214/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/214/vm_core.h +0 -1055
- data/ext/did_you_mean/ruby_headers/214/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/214/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/215/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/215/internal.h +0 -892
- data/ext/did_you_mean/ruby_headers/215/method.h +0 -142
- data/ext/did_you_mean/ruby_headers/215/node.h +0 -543
- data/ext/did_you_mean/ruby_headers/215/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/215/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/215/thread_pthread.h +0 -56
- data/ext/did_you_mean/ruby_headers/215/thread_win32.h +0 -45
- data/ext/did_you_mean/ruby_headers/215/vm_core.h +0 -1055
- data/ext/did_you_mean/ruby_headers/215/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/215/vm_opts.h +0 -56
- data/ext/did_you_mean/ruby_headers/220/ccan/check_type/check_type.h +0 -63
- data/ext/did_you_mean/ruby_headers/220/ccan/container_of/container_of.h +0 -106
- data/ext/did_you_mean/ruby_headers/220/ccan/list/list.h +0 -602
- data/ext/did_you_mean/ruby_headers/220/ccan/str/str.h +0 -16
- data/ext/did_you_mean/ruby_headers/220/id.h +0 -173
- data/ext/did_you_mean/ruby_headers/220/internal.h +0 -1106
- data/ext/did_you_mean/ruby_headers/220/method.h +0 -141
- data/ext/did_you_mean/ruby_headers/220/node.h +0 -544
- data/ext/did_you_mean/ruby_headers/220/ruby_atomic.h +0 -170
- data/ext/did_you_mean/ruby_headers/220/symbol.h +0 -87
- data/ext/did_you_mean/ruby_headers/220/thread_native.h +0 -23
- data/ext/did_you_mean/ruby_headers/220/thread_pthread.h +0 -54
- data/ext/did_you_mean/ruby_headers/220/thread_win32.h +0 -36
- data/ext/did_you_mean/ruby_headers/220/vm_core.h +0 -1160
- data/ext/did_you_mean/ruby_headers/220/vm_debug.h +0 -37
- data/ext/did_you_mean/ruby_headers/220/vm_opts.h +0 -56
- data/ext/did_you_mean/vm_method.c +0 -28
@@ -1,37 +0,0 @@
|
|
1
|
-
/**********************************************************************
|
2
|
-
|
3
|
-
vm_debug.h - YARV Debug function interface
|
4
|
-
|
5
|
-
$Author$
|
6
|
-
created at: 04/08/25 02:33:49 JST
|
7
|
-
|
8
|
-
Copyright (C) 2004-2007 Koichi Sasada
|
9
|
-
|
10
|
-
**********************************************************************/
|
11
|
-
|
12
|
-
#ifndef RUBY_DEBUG_H
|
13
|
-
#define RUBY_DEBUG_H
|
14
|
-
|
15
|
-
#include "ruby/ruby.h"
|
16
|
-
#include "node.h"
|
17
|
-
|
18
|
-
RUBY_SYMBOL_EXPORT_BEGIN
|
19
|
-
|
20
|
-
#define dpv(h,v) ruby_debug_print_value(-1, 0, (h), (v))
|
21
|
-
#define dp(v) ruby_debug_print_value(-1, 0, "", (v))
|
22
|
-
#define dpi(i) ruby_debug_print_id(-1, 0, "", (i))
|
23
|
-
#define dpn(n) ruby_debug_print_node(-1, 0, "", (n))
|
24
|
-
|
25
|
-
#define bp() ruby_debug_breakpoint()
|
26
|
-
|
27
|
-
VALUE ruby_debug_print_value(int level, int debug_level, const char *header, VALUE v);
|
28
|
-
ID ruby_debug_print_id(int level, int debug_level, const char *header, ID id);
|
29
|
-
NODE *ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node);
|
30
|
-
int ruby_debug_print_indent(int level, int debug_level, int indent_level);
|
31
|
-
void ruby_debug_breakpoint(void);
|
32
|
-
void ruby_debug_gc_check_func(void);
|
33
|
-
void ruby_set_debug_option(const char *str);
|
34
|
-
|
35
|
-
RUBY_SYMBOL_EXPORT_END
|
36
|
-
|
37
|
-
#endif /* RUBY_DEBUG_H */
|
@@ -1,56 +0,0 @@
|
|
1
|
-
/*-*-c-*-*/
|
2
|
-
/**********************************************************************
|
3
|
-
|
4
|
-
vm_opts.h - VM optimize option
|
5
|
-
|
6
|
-
$Author$
|
7
|
-
|
8
|
-
Copyright (C) 2004-2007 Koichi Sasada
|
9
|
-
|
10
|
-
**********************************************************************/
|
11
|
-
|
12
|
-
|
13
|
-
#ifndef RUBY_VM_OPTS_H
|
14
|
-
#define RUBY_VM_OPTS_H
|
15
|
-
|
16
|
-
/* Compile options.
|
17
|
-
* You can change these options at runtime by VM::CompileOption.
|
18
|
-
* Following definitions are default values.
|
19
|
-
*/
|
20
|
-
|
21
|
-
#define OPT_TRACE_INSTRUCTION 1
|
22
|
-
#define OPT_TAILCALL_OPTIMIZATION 0
|
23
|
-
#define OPT_PEEPHOLE_OPTIMIZATION 1
|
24
|
-
#define OPT_SPECIALISED_INSTRUCTION 1
|
25
|
-
#define OPT_INLINE_CONST_CACHE 1
|
26
|
-
|
27
|
-
|
28
|
-
/* Build Options.
|
29
|
-
* You can't change these options at runtime.
|
30
|
-
*/
|
31
|
-
|
32
|
-
/* C compiler dependent */
|
33
|
-
#define OPT_DIRECT_THREADED_CODE 1
|
34
|
-
#define OPT_TOKEN_THREADED_CODE 0
|
35
|
-
#define OPT_CALL_THREADED_CODE 0
|
36
|
-
|
37
|
-
/* VM running option */
|
38
|
-
#define OPT_CHECKED_RUN 1
|
39
|
-
#define OPT_INLINE_METHOD_CACHE 1
|
40
|
-
#define OPT_GLOBAL_METHOD_CACHE 1
|
41
|
-
#define OPT_BLOCKINLINING 0
|
42
|
-
|
43
|
-
/* architecture independent, affects generated code */
|
44
|
-
#define OPT_OPERANDS_UNIFICATION 1
|
45
|
-
#define OPT_INSTRUCTIONS_UNIFICATION 0
|
46
|
-
#define OPT_UNIFY_ALL_COMBINATION 0
|
47
|
-
#define OPT_STACK_CACHING 0
|
48
|
-
|
49
|
-
/* misc */
|
50
|
-
#define SUPPORT_JOKE 0
|
51
|
-
|
52
|
-
#ifndef VM_COLLECT_USAGE_DETAILS
|
53
|
-
#define VM_COLLECT_USAGE_DETAILS 0
|
54
|
-
#endif
|
55
|
-
|
56
|
-
#endif /* RUBY_VM_OPTS_H */
|
@@ -1,63 +0,0 @@
|
|
1
|
-
/* CC0 (Public domain) - see ccan/licenses/CC0 file for details */
|
2
|
-
#ifndef CCAN_CHECK_TYPE_H
|
3
|
-
#define CCAN_CHECK_TYPE_H
|
4
|
-
|
5
|
-
/**
|
6
|
-
* check_type - issue a warning or build failure if type is not correct.
|
7
|
-
* @expr: the expression whose type we should check (not evaluated).
|
8
|
-
* @type: the exact type we expect the expression to be.
|
9
|
-
*
|
10
|
-
* This macro is usually used within other macros to try to ensure that a macro
|
11
|
-
* argument is of the expected type. No type promotion of the expression is
|
12
|
-
* done: an unsigned int is not the same as an int!
|
13
|
-
*
|
14
|
-
* check_type() always evaluates to 0.
|
15
|
-
*
|
16
|
-
* If your compiler does not support typeof, then the best we can do is fail
|
17
|
-
* to compile if the sizes of the types are unequal (a less complete check).
|
18
|
-
*
|
19
|
-
* Example:
|
20
|
-
* // They should always pass a 64-bit value to _set_some_value!
|
21
|
-
* #define set_some_value(expr) \
|
22
|
-
* _set_some_value((check_type((expr), uint64_t), (expr)))
|
23
|
-
*/
|
24
|
-
|
25
|
-
/**
|
26
|
-
* check_types_match - issue a warning or build failure if types are not same.
|
27
|
-
* @expr1: the first expression (not evaluated).
|
28
|
-
* @expr2: the second expression (not evaluated).
|
29
|
-
*
|
30
|
-
* This macro is usually used within other macros to try to ensure that
|
31
|
-
* arguments are of identical types. No type promotion of the expressions is
|
32
|
-
* done: an unsigned int is not the same as an int!
|
33
|
-
*
|
34
|
-
* check_types_match() always evaluates to 0.
|
35
|
-
*
|
36
|
-
* If your compiler does not support typeof, then the best we can do is fail
|
37
|
-
* to compile if the sizes of the types are unequal (a less complete check).
|
38
|
-
*
|
39
|
-
* Example:
|
40
|
-
* // Do subtraction to get to enclosing type, but make sure that
|
41
|
-
* // pointer is of correct type for that member.
|
42
|
-
* #define container_of(mbr_ptr, encl_type, mbr) \
|
43
|
-
* (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
|
44
|
-
* ((encl_type *) \
|
45
|
-
* ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
|
46
|
-
*/
|
47
|
-
#if HAVE_TYPEOF
|
48
|
-
#define check_type(expr, type) \
|
49
|
-
((typeof(expr) *)0 != (type *)0)
|
50
|
-
|
51
|
-
#define check_types_match(expr1, expr2) \
|
52
|
-
((typeof(expr1) *)0 != (typeof(expr2) *)0)
|
53
|
-
#else
|
54
|
-
#include "ccan/build_assert/build_assert.h"
|
55
|
-
/* Without typeof, we can only test the sizes. */
|
56
|
-
#define check_type(expr, type) \
|
57
|
-
BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
|
58
|
-
|
59
|
-
#define check_types_match(expr1, expr2) \
|
60
|
-
BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
|
61
|
-
#endif /* HAVE_TYPEOF */
|
62
|
-
|
63
|
-
#endif /* CCAN_CHECK_TYPE_H */
|
@@ -1,106 +0,0 @@
|
|
1
|
-
/* CC0 (Public domain) - see ccan/licenses/CC0 file for details */
|
2
|
-
#ifndef CCAN_CONTAINER_OF_H
|
3
|
-
#define CCAN_CONTAINER_OF_H
|
4
|
-
#include "ccan/check_type/check_type.h"
|
5
|
-
|
6
|
-
/**
|
7
|
-
* container_of - get pointer to enclosing structure
|
8
|
-
* @member_ptr: pointer to the structure member
|
9
|
-
* @containing_type: the type this member is within
|
10
|
-
* @member: the name of this member within the structure.
|
11
|
-
*
|
12
|
-
* Given a pointer to a member of a structure, this macro does pointer
|
13
|
-
* subtraction to return the pointer to the enclosing type.
|
14
|
-
*
|
15
|
-
* Example:
|
16
|
-
* struct foo {
|
17
|
-
* int fielda, fieldb;
|
18
|
-
* // ...
|
19
|
-
* };
|
20
|
-
* struct info {
|
21
|
-
* int some_other_field;
|
22
|
-
* struct foo my_foo;
|
23
|
-
* };
|
24
|
-
*
|
25
|
-
* static struct info *foo_to_info(struct foo *foo)
|
26
|
-
* {
|
27
|
-
* return container_of(foo, struct info, my_foo);
|
28
|
-
* }
|
29
|
-
*/
|
30
|
-
#define container_of(member_ptr, containing_type, member) \
|
31
|
-
((containing_type *) \
|
32
|
-
((char *)(member_ptr) \
|
33
|
-
- container_off(containing_type, member)) \
|
34
|
-
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
|
35
|
-
|
36
|
-
/**
|
37
|
-
* container_off - get offset to enclosing structure
|
38
|
-
* @containing_type: the type this member is within
|
39
|
-
* @member: the name of this member within the structure.
|
40
|
-
*
|
41
|
-
* Given a pointer to a member of a structure, this macro does
|
42
|
-
* typechecking and figures out the offset to the enclosing type.
|
43
|
-
*
|
44
|
-
* Example:
|
45
|
-
* struct foo {
|
46
|
-
* int fielda, fieldb;
|
47
|
-
* // ...
|
48
|
-
* };
|
49
|
-
* struct info {
|
50
|
-
* int some_other_field;
|
51
|
-
* struct foo my_foo;
|
52
|
-
* };
|
53
|
-
*
|
54
|
-
* static struct info *foo_to_info(struct foo *foo)
|
55
|
-
* {
|
56
|
-
* size_t off = container_off(struct info, my_foo);
|
57
|
-
* return (void *)((char *)foo - off);
|
58
|
-
* }
|
59
|
-
*/
|
60
|
-
#define container_off(containing_type, member) \
|
61
|
-
offsetof(containing_type, member)
|
62
|
-
|
63
|
-
/**
|
64
|
-
* container_of_var - get pointer to enclosing structure using a variable
|
65
|
-
* @member_ptr: pointer to the structure member
|
66
|
-
* @container_var: a pointer of same type as this member's container
|
67
|
-
* @member: the name of this member within the structure.
|
68
|
-
*
|
69
|
-
* Given a pointer to a member of a structure, this macro does pointer
|
70
|
-
* subtraction to return the pointer to the enclosing type.
|
71
|
-
*
|
72
|
-
* Example:
|
73
|
-
* static struct info *foo_to_i(struct foo *foo)
|
74
|
-
* {
|
75
|
-
* struct info *i = container_of_var(foo, i, my_foo);
|
76
|
-
* return i;
|
77
|
-
* }
|
78
|
-
*/
|
79
|
-
#if HAVE_TYPEOF
|
80
|
-
#define container_of_var(member_ptr, container_var, member) \
|
81
|
-
container_of(member_ptr, typeof(*container_var), member)
|
82
|
-
#else
|
83
|
-
#define container_of_var(member_ptr, container_var, member) \
|
84
|
-
((void *)((char *)(member_ptr) - \
|
85
|
-
container_off_var(container_var, member)))
|
86
|
-
#endif
|
87
|
-
|
88
|
-
/**
|
89
|
-
* container_off_var - get offset of a field in enclosing structure
|
90
|
-
* @container_var: a pointer to a container structure
|
91
|
-
* @member: the name of a member within the structure.
|
92
|
-
*
|
93
|
-
* Given (any) pointer to a structure and a its member name, this
|
94
|
-
* macro does pointer subtraction to return offset of member in a
|
95
|
-
* structure memory layout.
|
96
|
-
*
|
97
|
-
*/
|
98
|
-
#if HAVE_TYPEOF
|
99
|
-
#define container_off_var(var, member) \
|
100
|
-
container_off(typeof(*var), member)
|
101
|
-
#else
|
102
|
-
#define container_off_var(var, member) \
|
103
|
-
((char *)&(var)->member - (char *)(var))
|
104
|
-
#endif
|
105
|
-
|
106
|
-
#endif /* CCAN_CONTAINER_OF_H */
|
@@ -1,602 +0,0 @@
|
|
1
|
-
/* Licensed under BSD-MIT - see ccan/licenses/BSD-MIT file for details */
|
2
|
-
#ifndef CCAN_LIST_H
|
3
|
-
#define CCAN_LIST_H
|
4
|
-
#include <assert.h>
|
5
|
-
#include "ccan/str/str.h"
|
6
|
-
#include "ccan/container_of/container_of.h"
|
7
|
-
#include "ccan/check_type/check_type.h"
|
8
|
-
|
9
|
-
/**
|
10
|
-
* struct list_node - an entry in a doubly-linked list
|
11
|
-
* @next: next entry (self if empty)
|
12
|
-
* @prev: previous entry (self if empty)
|
13
|
-
*
|
14
|
-
* This is used as an entry in a linked list.
|
15
|
-
* Example:
|
16
|
-
* struct child {
|
17
|
-
* const char *name;
|
18
|
-
* // Linked list of all us children.
|
19
|
-
* struct list_node list;
|
20
|
-
* };
|
21
|
-
*/
|
22
|
-
struct list_node
|
23
|
-
{
|
24
|
-
struct list_node *next, *prev;
|
25
|
-
};
|
26
|
-
|
27
|
-
/**
|
28
|
-
* struct list_head - the head of a doubly-linked list
|
29
|
-
* @h: the list_head (containing next and prev pointers)
|
30
|
-
*
|
31
|
-
* This is used as the head of a linked list.
|
32
|
-
* Example:
|
33
|
-
* struct parent {
|
34
|
-
* const char *name;
|
35
|
-
* struct list_head children;
|
36
|
-
* unsigned int num_children;
|
37
|
-
* };
|
38
|
-
*/
|
39
|
-
struct list_head
|
40
|
-
{
|
41
|
-
struct list_node n;
|
42
|
-
};
|
43
|
-
|
44
|
-
#define LIST_LOC __FILE__ ":" stringify(__LINE__)
|
45
|
-
#define list_debug(h, loc) (h)
|
46
|
-
#define list_debug_node(n, loc) (n)
|
47
|
-
|
48
|
-
/**
|
49
|
-
* LIST_HEAD_INIT - initializer for an empty list_head
|
50
|
-
* @name: the name of the list.
|
51
|
-
*
|
52
|
-
* Explicit initializer for an empty list.
|
53
|
-
*
|
54
|
-
* See also:
|
55
|
-
* LIST_HEAD, list_head_init()
|
56
|
-
*
|
57
|
-
* Example:
|
58
|
-
* static struct list_head my_list = LIST_HEAD_INIT(my_list);
|
59
|
-
*/
|
60
|
-
#define LIST_HEAD_INIT(name) { { &name.n, &name.n } }
|
61
|
-
|
62
|
-
/**
|
63
|
-
* LIST_HEAD - define and initialize an empty list_head
|
64
|
-
* @name: the name of the list.
|
65
|
-
*
|
66
|
-
* The LIST_HEAD macro defines a list_head and initializes it to an empty
|
67
|
-
* list. It can be prepended by "static" to define a static list_head.
|
68
|
-
*
|
69
|
-
* See also:
|
70
|
-
* LIST_HEAD_INIT, list_head_init()
|
71
|
-
*
|
72
|
-
* Example:
|
73
|
-
* static LIST_HEAD(my_global_list);
|
74
|
-
*/
|
75
|
-
#define LIST_HEAD(name) \
|
76
|
-
struct list_head name = LIST_HEAD_INIT(name)
|
77
|
-
|
78
|
-
/**
|
79
|
-
* list_head_init - initialize a list_head
|
80
|
-
* @h: the list_head to set to the empty list
|
81
|
-
*
|
82
|
-
* Example:
|
83
|
-
* ...
|
84
|
-
* struct parent *parent = malloc(sizeof(*parent));
|
85
|
-
*
|
86
|
-
* list_head_init(&parent->children);
|
87
|
-
* parent->num_children = 0;
|
88
|
-
*/
|
89
|
-
static inline void list_head_init(struct list_head *h)
|
90
|
-
{
|
91
|
-
h->n.next = h->n.prev = &h->n;
|
92
|
-
}
|
93
|
-
|
94
|
-
/**
|
95
|
-
* list_add - add an entry at the start of a linked list.
|
96
|
-
* @h: the list_head to add the node to
|
97
|
-
* @n: the list_node to add to the list.
|
98
|
-
*
|
99
|
-
* The list_node does not need to be initialized; it will be overwritten.
|
100
|
-
* Example:
|
101
|
-
* struct child *child = malloc(sizeof(*child));
|
102
|
-
*
|
103
|
-
* child->name = "marvin";
|
104
|
-
* list_add(&parent->children, &child->list);
|
105
|
-
* parent->num_children++;
|
106
|
-
*/
|
107
|
-
#define list_add(h, n) list_add_(h, n, LIST_LOC)
|
108
|
-
static inline void list_add_(struct list_head *h,
|
109
|
-
struct list_node *n,
|
110
|
-
const char *abortstr)
|
111
|
-
{
|
112
|
-
n->next = h->n.next;
|
113
|
-
n->prev = &h->n;
|
114
|
-
h->n.next->prev = n;
|
115
|
-
h->n.next = n;
|
116
|
-
(void)list_debug(h, abortstr);
|
117
|
-
}
|
118
|
-
|
119
|
-
/**
|
120
|
-
* list_add_tail - add an entry at the end of a linked list.
|
121
|
-
* @h: the list_head to add the node to
|
122
|
-
* @n: the list_node to add to the list.
|
123
|
-
*
|
124
|
-
* The list_node does not need to be initialized; it will be overwritten.
|
125
|
-
* Example:
|
126
|
-
* list_add_tail(&parent->children, &child->list);
|
127
|
-
* parent->num_children++;
|
128
|
-
*/
|
129
|
-
#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC)
|
130
|
-
static inline void list_add_tail_(struct list_head *h,
|
131
|
-
struct list_node *n,
|
132
|
-
const char *abortstr)
|
133
|
-
{
|
134
|
-
n->next = &h->n;
|
135
|
-
n->prev = h->n.prev;
|
136
|
-
h->n.prev->next = n;
|
137
|
-
h->n.prev = n;
|
138
|
-
(void)list_debug(h, abortstr);
|
139
|
-
}
|
140
|
-
|
141
|
-
/**
|
142
|
-
* list_empty - is a list empty?
|
143
|
-
* @h: the list_head
|
144
|
-
*
|
145
|
-
* If the list is empty, returns true.
|
146
|
-
*
|
147
|
-
* Example:
|
148
|
-
* assert(list_empty(&parent->children) == (parent->num_children == 0));
|
149
|
-
*/
|
150
|
-
#define list_empty(h) list_empty_(h, LIST_LOC)
|
151
|
-
static inline int list_empty_(const struct list_head *h, const char* abortstr)
|
152
|
-
{
|
153
|
-
(void)list_debug(h, abortstr);
|
154
|
-
return h->n.next == &h->n;
|
155
|
-
}
|
156
|
-
|
157
|
-
/**
|
158
|
-
* list_empty_nodebug - is a list empty (and don't perform debug checks)?
|
159
|
-
* @h: the list_head
|
160
|
-
*
|
161
|
-
* If the list is empty, returns true.
|
162
|
-
* This differs from list_empty() in that if CCAN_LIST_DEBUG is set it
|
163
|
-
* will NOT perform debug checks. Only use this function if you REALLY
|
164
|
-
* know what you're doing.
|
165
|
-
*
|
166
|
-
* Example:
|
167
|
-
* assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0));
|
168
|
-
*/
|
169
|
-
#ifndef CCAN_LIST_DEBUG
|
170
|
-
#define list_empty_nodebug(h) list_empty(h)
|
171
|
-
#else
|
172
|
-
static inline int list_empty_nodebug(const struct list_head *h)
|
173
|
-
{
|
174
|
-
return h->n.next == &h->n;
|
175
|
-
}
|
176
|
-
#endif
|
177
|
-
|
178
|
-
/**
|
179
|
-
* list_del - delete an entry from an (unknown) linked list.
|
180
|
-
* @n: the list_node to delete from the list.
|
181
|
-
*
|
182
|
-
* Note that this leaves @n in an undefined state; it can be added to
|
183
|
-
* another list, but not deleted again.
|
184
|
-
*
|
185
|
-
* See also:
|
186
|
-
* list_del_from()
|
187
|
-
*
|
188
|
-
* Example:
|
189
|
-
* list_del(&child->list);
|
190
|
-
* parent->num_children--;
|
191
|
-
*/
|
192
|
-
#define list_del(n) list_del_(n, LIST_LOC)
|
193
|
-
static inline void list_del_(struct list_node *n, const char* abortstr)
|
194
|
-
{
|
195
|
-
(void)list_debug_node(n, abortstr);
|
196
|
-
n->next->prev = n->prev;
|
197
|
-
n->prev->next = n->next;
|
198
|
-
#ifdef CCAN_LIST_DEBUG
|
199
|
-
/* Catch use-after-del. */
|
200
|
-
n->next = n->prev = NULL;
|
201
|
-
#endif
|
202
|
-
}
|
203
|
-
|
204
|
-
/**
|
205
|
-
* list_del_from - delete an entry from a known linked list.
|
206
|
-
* @h: the list_head the node is in.
|
207
|
-
* @n: the list_node to delete from the list.
|
208
|
-
*
|
209
|
-
* This explicitly indicates which list a node is expected to be in,
|
210
|
-
* which is better documentation and can catch more bugs.
|
211
|
-
*
|
212
|
-
* See also: list_del()
|
213
|
-
*
|
214
|
-
* Example:
|
215
|
-
* list_del_from(&parent->children, &child->list);
|
216
|
-
* parent->num_children--;
|
217
|
-
*/
|
218
|
-
static inline void list_del_from(struct list_head *h, struct list_node *n)
|
219
|
-
{
|
220
|
-
#ifdef CCAN_LIST_DEBUG
|
221
|
-
{
|
222
|
-
/* Thorough check: make sure it was in list! */
|
223
|
-
struct list_node *i;
|
224
|
-
for (i = h->n.next; i != n; i = i->next)
|
225
|
-
assert(i != &h->n);
|
226
|
-
}
|
227
|
-
#endif /* CCAN_LIST_DEBUG */
|
228
|
-
|
229
|
-
/* Quick test that catches a surprising number of bugs. */
|
230
|
-
assert(!list_empty(h));
|
231
|
-
list_del(n);
|
232
|
-
}
|
233
|
-
|
234
|
-
/**
|
235
|
-
* list_entry - convert a list_node back into the structure containing it.
|
236
|
-
* @n: the list_node
|
237
|
-
* @type: the type of the entry
|
238
|
-
* @member: the list_node member of the type
|
239
|
-
*
|
240
|
-
* Example:
|
241
|
-
* // First list entry is children.next; convert back to child.
|
242
|
-
* child = list_entry(parent->children.n.next, struct child, list);
|
243
|
-
*
|
244
|
-
* See Also:
|
245
|
-
* list_top(), list_for_each()
|
246
|
-
*/
|
247
|
-
#define list_entry(n, type, member) container_of(n, type, member)
|
248
|
-
|
249
|
-
/**
|
250
|
-
* list_top - get the first entry in a list
|
251
|
-
* @h: the list_head
|
252
|
-
* @type: the type of the entry
|
253
|
-
* @member: the list_node member of the type
|
254
|
-
*
|
255
|
-
* If the list is empty, returns NULL.
|
256
|
-
*
|
257
|
-
* Example:
|
258
|
-
* struct child *first;
|
259
|
-
* first = list_top(&parent->children, struct child, list);
|
260
|
-
* if (!first)
|
261
|
-
* printf("Empty list!\n");
|
262
|
-
*/
|
263
|
-
#define list_top(h, type, member) \
|
264
|
-
((type *)list_top_((h), list_off_(type, member)))
|
265
|
-
|
266
|
-
static inline const void *list_top_(const struct list_head *h, size_t off)
|
267
|
-
{
|
268
|
-
if (list_empty(h))
|
269
|
-
return NULL;
|
270
|
-
return (const char *)h->n.next - off;
|
271
|
-
}
|
272
|
-
|
273
|
-
/**
|
274
|
-
* list_pop - remove the first entry in a list
|
275
|
-
* @h: the list_head
|
276
|
-
* @type: the type of the entry
|
277
|
-
* @member: the list_node member of the type
|
278
|
-
*
|
279
|
-
* If the list is empty, returns NULL.
|
280
|
-
*
|
281
|
-
* Example:
|
282
|
-
* struct child *one;
|
283
|
-
* one = list_pop(&parent->children, struct child, list);
|
284
|
-
* if (!one)
|
285
|
-
* printf("Empty list!\n");
|
286
|
-
*/
|
287
|
-
#define list_pop(h, type, member) \
|
288
|
-
((type *)list_pop_((h), list_off_(type, member)))
|
289
|
-
|
290
|
-
static inline const void *list_pop_(const struct list_head *h, size_t off)
|
291
|
-
{
|
292
|
-
struct list_node *n;
|
293
|
-
|
294
|
-
if (list_empty(h))
|
295
|
-
return NULL;
|
296
|
-
n = h->n.next;
|
297
|
-
list_del(n);
|
298
|
-
return (const char *)n - off;
|
299
|
-
}
|
300
|
-
|
301
|
-
/**
|
302
|
-
* list_tail - get the last entry in a list
|
303
|
-
* @h: the list_head
|
304
|
-
* @type: the type of the entry
|
305
|
-
* @member: the list_node member of the type
|
306
|
-
*
|
307
|
-
* If the list is empty, returns NULL.
|
308
|
-
*
|
309
|
-
* Example:
|
310
|
-
* struct child *last;
|
311
|
-
* last = list_tail(&parent->children, struct child, list);
|
312
|
-
* if (!last)
|
313
|
-
* printf("Empty list!\n");
|
314
|
-
*/
|
315
|
-
#define list_tail(h, type, member) \
|
316
|
-
((type *)list_tail_((h), list_off_(type, member)))
|
317
|
-
|
318
|
-
static inline const void *list_tail_(const struct list_head *h, size_t off)
|
319
|
-
{
|
320
|
-
if (list_empty(h))
|
321
|
-
return NULL;
|
322
|
-
return (const char *)h->n.prev - off;
|
323
|
-
}
|
324
|
-
|
325
|
-
/**
|
326
|
-
* list_for_each - iterate through a list.
|
327
|
-
* @h: the list_head (warning: evaluated multiple times!)
|
328
|
-
* @i: the structure containing the list_node
|
329
|
-
* @member: the list_node member of the structure
|
330
|
-
*
|
331
|
-
* This is a convenient wrapper to iterate @i over the entire list. It's
|
332
|
-
* a for loop, so you can break and continue as normal.
|
333
|
-
*
|
334
|
-
* Example:
|
335
|
-
* list_for_each(&parent->children, child, list)
|
336
|
-
* printf("Name: %s\n", child->name);
|
337
|
-
*/
|
338
|
-
#define list_for_each(h, i, member) \
|
339
|
-
list_for_each_off(h, i, list_off_var_(i, member))
|
340
|
-
|
341
|
-
/**
|
342
|
-
* list_for_each_rev - iterate through a list backwards.
|
343
|
-
* @h: the list_head
|
344
|
-
* @i: the structure containing the list_node
|
345
|
-
* @member: the list_node member of the structure
|
346
|
-
*
|
347
|
-
* This is a convenient wrapper to iterate @i over the entire list. It's
|
348
|
-
* a for loop, so you can break and continue as normal.
|
349
|
-
*
|
350
|
-
* Example:
|
351
|
-
* list_for_each_rev(&parent->children, child, list)
|
352
|
-
* printf("Name: %s\n", child->name);
|
353
|
-
*/
|
354
|
-
#define list_for_each_rev(h, i, member) \
|
355
|
-
for (i = container_of_var(list_debug(h, LIST_LOC)->n.prev, i, member); \
|
356
|
-
&i->member != &(h)->n; \
|
357
|
-
i = container_of_var(i->member.prev, i, member))
|
358
|
-
|
359
|
-
/**
|
360
|
-
* list_for_each_safe - iterate through a list, maybe during deletion
|
361
|
-
* @h: the list_head
|
362
|
-
* @i: the structure containing the list_node
|
363
|
-
* @nxt: the structure containing the list_node
|
364
|
-
* @member: the list_node member of the structure
|
365
|
-
*
|
366
|
-
* This is a convenient wrapper to iterate @i over the entire list. It's
|
367
|
-
* a for loop, so you can break and continue as normal. The extra variable
|
368
|
-
* @nxt is used to hold the next element, so you can delete @i from the list.
|
369
|
-
*
|
370
|
-
* Example:
|
371
|
-
* struct child *next;
|
372
|
-
* list_for_each_safe(&parent->children, child, next, list) {
|
373
|
-
* list_del(&child->list);
|
374
|
-
* parent->num_children--;
|
375
|
-
* }
|
376
|
-
*/
|
377
|
-
#define list_for_each_safe(h, i, nxt, member) \
|
378
|
-
list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
|
379
|
-
|
380
|
-
/**
|
381
|
-
* list_next - get the next entry in a list
|
382
|
-
* @h: the list_head
|
383
|
-
* @i: a pointer to an entry in the list.
|
384
|
-
* @member: the list_node member of the structure
|
385
|
-
*
|
386
|
-
* If @i was the last entry in the list, returns NULL.
|
387
|
-
*
|
388
|
-
* Example:
|
389
|
-
* struct child *second;
|
390
|
-
* second = list_next(&parent->children, first, list);
|
391
|
-
* if (!second)
|
392
|
-
* printf("No second child!\n");
|
393
|
-
*/
|
394
|
-
#define list_next(h, i, member) \
|
395
|
-
((list_typeof(i))list_entry_or_null(list_debug(h, \
|
396
|
-
__FILE__ ":" stringify(__LINE__)), \
|
397
|
-
(i)->member.next, \
|
398
|
-
list_off_var_((i), member)))
|
399
|
-
|
400
|
-
/**
|
401
|
-
* list_prev - get the previous entry in a list
|
402
|
-
* @h: the list_head
|
403
|
-
* @i: a pointer to an entry in the list.
|
404
|
-
* @member: the list_node member of the structure
|
405
|
-
*
|
406
|
-
* If @i was the first entry in the list, returns NULL.
|
407
|
-
*
|
408
|
-
* Example:
|
409
|
-
* first = list_prev(&parent->children, second, list);
|
410
|
-
* if (!first)
|
411
|
-
* printf("Can't go back to first child?!\n");
|
412
|
-
*/
|
413
|
-
#define list_prev(h, i, member) \
|
414
|
-
((list_typeof(i))list_entry_or_null(list_debug(h, \
|
415
|
-
__FILE__ ":" stringify(__LINE__)), \
|
416
|
-
(i)->member.prev, \
|
417
|
-
list_off_var_((i), member)))
|
418
|
-
|
419
|
-
/**
|
420
|
-
* list_append_list - empty one list onto the end of another.
|
421
|
-
* @to: the list to append into
|
422
|
-
* @from: the list to empty.
|
423
|
-
*
|
424
|
-
* This takes the entire contents of @from and moves it to the end of
|
425
|
-
* @to. After this @from will be empty.
|
426
|
-
*
|
427
|
-
* Example:
|
428
|
-
* struct list_head adopter;
|
429
|
-
*
|
430
|
-
* list_append_list(&adopter, &parent->children);
|
431
|
-
* assert(list_empty(&parent->children));
|
432
|
-
* parent->num_children = 0;
|
433
|
-
*/
|
434
|
-
#define list_append_list(t, f) list_append_list_(t, f, \
|
435
|
-
__FILE__ ":" stringify(__LINE__))
|
436
|
-
static inline void list_append_list_(struct list_head *to,
|
437
|
-
struct list_head *from,
|
438
|
-
const char *abortstr)
|
439
|
-
{
|
440
|
-
struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
|
441
|
-
struct list_node *to_tail = list_debug(to, abortstr)->n.prev;
|
442
|
-
|
443
|
-
/* Sew in head and entire list. */
|
444
|
-
to->n.prev = from_tail;
|
445
|
-
from_tail->next = &to->n;
|
446
|
-
to_tail->next = &from->n;
|
447
|
-
from->n.prev = to_tail;
|
448
|
-
|
449
|
-
/* Now remove head. */
|
450
|
-
list_del(&from->n);
|
451
|
-
list_head_init(from);
|
452
|
-
}
|
453
|
-
|
454
|
-
/**
|
455
|
-
* list_prepend_list - empty one list into the start of another.
|
456
|
-
* @to: the list to prepend into
|
457
|
-
* @from: the list to empty.
|
458
|
-
*
|
459
|
-
* This takes the entire contents of @from and moves it to the start
|
460
|
-
* of @to. After this @from will be empty.
|
461
|
-
*
|
462
|
-
* Example:
|
463
|
-
* list_prepend_list(&adopter, &parent->children);
|
464
|
-
* assert(list_empty(&parent->children));
|
465
|
-
* parent->num_children = 0;
|
466
|
-
*/
|
467
|
-
#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC)
|
468
|
-
static inline void list_prepend_list_(struct list_head *to,
|
469
|
-
struct list_head *from,
|
470
|
-
const char *abortstr)
|
471
|
-
{
|
472
|
-
struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
|
473
|
-
struct list_node *to_head = list_debug(to, abortstr)->n.next;
|
474
|
-
|
475
|
-
/* Sew in head and entire list. */
|
476
|
-
to->n.next = &from->n;
|
477
|
-
from->n.prev = &to->n;
|
478
|
-
to_head->prev = from_tail;
|
479
|
-
from_tail->next = to_head;
|
480
|
-
|
481
|
-
/* Now remove head. */
|
482
|
-
list_del(&from->n);
|
483
|
-
list_head_init(from);
|
484
|
-
}
|
485
|
-
|
486
|
-
/**
|
487
|
-
* list_for_each_off - iterate through a list of memory regions.
|
488
|
-
* @h: the list_head
|
489
|
-
* @i: the pointer to a memory region wich contains list node data.
|
490
|
-
* @off: offset(relative to @i) at which list node data resides.
|
491
|
-
*
|
492
|
-
* This is a low-level wrapper to iterate @i over the entire list, used to
|
493
|
-
* implement all oher, more high-level, for-each constructs. It's a for loop,
|
494
|
-
* so you can break and continue as normal.
|
495
|
-
*
|
496
|
-
* WARNING! Being the low-level macro that it is, this wrapper doesn't know
|
497
|
-
* nor care about the type of @i. The only assumtion made is that @i points
|
498
|
-
* to a chunk of memory that at some @offset, relative to @i, contains a
|
499
|
-
* properly filled `struct node_list' which in turn contains pointers to
|
500
|
-
* memory chunks and it's turtles all the way down. Whith all that in mind
|
501
|
-
* remember that given the wrong pointer/offset couple this macro will
|
502
|
-
* happilly churn all you memory untill SEGFAULT stops it, in other words
|
503
|
-
* caveat emptor.
|
504
|
-
*
|
505
|
-
* It is worth mentioning that one of legitimate use-cases for that wrapper
|
506
|
-
* is operation on opaque types with known offset for `struct list_node'
|
507
|
-
* member(preferably 0), because it allows you not to disclose the type of
|
508
|
-
* @i.
|
509
|
-
*
|
510
|
-
* Example:
|
511
|
-
* list_for_each_off(&parent->children, child,
|
512
|
-
* offsetof(struct child, list))
|
513
|
-
* printf("Name: %s\n", child->name);
|
514
|
-
*/
|
515
|
-
#define list_for_each_off(h, i, off) \
|
516
|
-
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.next, \
|
517
|
-
(off)); \
|
518
|
-
list_node_from_off_((void *)i, (off)) != &(h)->n; \
|
519
|
-
i = list_node_to_off_(list_node_from_off_((void *)i, (off))->next, \
|
520
|
-
(off)))
|
521
|
-
|
522
|
-
/**
|
523
|
-
* list_for_each_safe_off - iterate through a list of memory regions, maybe
|
524
|
-
* during deletion
|
525
|
-
* @h: the list_head
|
526
|
-
* @i: the pointer to a memory region wich contains list node data.
|
527
|
-
* @nxt: the structure containing the list_node
|
528
|
-
* @off: offset(relative to @i) at which list node data resides.
|
529
|
-
*
|
530
|
-
* For details see `list_for_each_off' and `list_for_each_safe'
|
531
|
-
* descriptions.
|
532
|
-
*
|
533
|
-
* Example:
|
534
|
-
* list_for_each_safe_off(&parent->children, child,
|
535
|
-
* next, offsetof(struct child, list))
|
536
|
-
* printf("Name: %s\n", child->name);
|
537
|
-
*/
|
538
|
-
#define list_for_each_safe_off(h, i, nxt, off) \
|
539
|
-
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.next, \
|
540
|
-
(off)), \
|
541
|
-
nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
|
542
|
-
(off)); \
|
543
|
-
list_node_from_off_(i, (off)) != &(h)->n; \
|
544
|
-
i = nxt, \
|
545
|
-
nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
|
546
|
-
(off)))
|
547
|
-
|
548
|
-
|
549
|
-
/* Other -off variants. */
|
550
|
-
#define list_entry_off(n, type, off) \
|
551
|
-
((type *)list_node_from_off_((n), (off)))
|
552
|
-
|
553
|
-
#define list_head_off(h, type, off) \
|
554
|
-
((type *)list_head_off((h), (off)))
|
555
|
-
|
556
|
-
#define list_tail_off(h, type, off) \
|
557
|
-
((type *)list_tail_((h), (off)))
|
558
|
-
|
559
|
-
#define list_add_off(h, n, off) \
|
560
|
-
list_add((h), list_node_from_off_((n), (off)))
|
561
|
-
|
562
|
-
#define list_del_off(n, off) \
|
563
|
-
list_del(list_node_from_off_((n), (off)))
|
564
|
-
|
565
|
-
#define list_del_from_off(h, n, off) \
|
566
|
-
list_del_from(h, list_node_from_off_((n), (off)))
|
567
|
-
|
568
|
-
/* Offset helper functions so we only single-evaluate. */
|
569
|
-
static inline void *list_node_to_off_(struct list_node *node, size_t off)
|
570
|
-
{
|
571
|
-
return (void *)((char *)node - off);
|
572
|
-
}
|
573
|
-
static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
|
574
|
-
{
|
575
|
-
return (struct list_node *)((char *)ptr + off);
|
576
|
-
}
|
577
|
-
|
578
|
-
/* Get the offset of the member, but make sure it's a list_node. */
|
579
|
-
#define list_off_(type, member) \
|
580
|
-
(container_off(type, member) + \
|
581
|
-
check_type(((type *)0)->member, struct list_node))
|
582
|
-
|
583
|
-
#define list_off_var_(var, member) \
|
584
|
-
(container_off_var(var, member) + \
|
585
|
-
check_type(var->member, struct list_node))
|
586
|
-
|
587
|
-
#if HAVE_TYPEOF
|
588
|
-
#define list_typeof(var) typeof(var)
|
589
|
-
#else
|
590
|
-
#define list_typeof(var) void *
|
591
|
-
#endif
|
592
|
-
|
593
|
-
/* Returns member, or NULL if at end of list. */
|
594
|
-
static inline void *list_entry_or_null(const struct list_head *h,
|
595
|
-
const struct list_node *n,
|
596
|
-
size_t off)
|
597
|
-
{
|
598
|
-
if (n == &h->n)
|
599
|
-
return NULL;
|
600
|
-
return (char *)n - off;
|
601
|
-
}
|
602
|
-
#endif /* CCAN_LIST_H */
|