@@ -12,6 +12,7 @@ use std::sync::{Arc, Mutex, RwLock};
12
12
struct MacroCallback {
13
13
macros : Arc < RwLock < HashSet < String > > > ,
14
14
seen_hellos : Mutex < u32 > ,
15
+ seen_funcs : Mutex < u32 > ,
15
16
}
16
17
17
18
impl ParseCallbacks for MacroCallback {
@@ -45,6 +46,10 @@ impl ParseCallbacks for MacroCallback {
45
46
46
47
fn str_macro ( & self , name : & str , value : & [ u8 ] ) {
47
48
match name {
49
+ "TESTMACRO_STRING_EXPR" => {
50
+ assert_eq ! ( value, b"string" ) ;
51
+ * self . seen_hellos . lock ( ) . unwrap ( ) += 1 ;
52
+ }
48
53
"TESTMACRO_STRING_EXPANDED" |
49
54
"TESTMACRO_STRING" |
50
55
"TESTMACRO_INTEGER" => {
@@ -70,15 +75,64 @@ impl ParseCallbacks for MacroCallback {
70
75
_ => None ,
71
76
}
72
77
}
78
+
79
+ fn func_macro ( & self , name : & str , value : & [ & [ u8 ] ] ) {
80
+ match name {
81
+ "TESTMACRO_NONFUNCTIONAL" => {
82
+ panic ! ( "func_macro was called for a non-functional macro" ) ;
83
+ }
84
+ "TESTMACRO_FUNCTIONAL_NONEMPTY(TESTMACRO_INTEGER)" => {
85
+ // Spaces are inserted into the right-hand side of a functional
86
+ // macro during reconstruction from the tokenization. This might
87
+ // change in the future, but it is safe by the definition of a
88
+ // token in C, whereas leaving the spaces out could change
89
+ // tokenization.
90
+ assert_eq ! ( value, & [ b"-" as & [ u8 ] , b"TESTMACRO_INTEGER" ] ) ;
91
+ * self . seen_funcs . lock ( ) . unwrap ( ) += 1 ;
92
+ }
93
+ "TESTMACRO_FUNCTIONAL_EMPTY(TESTMACRO_INTEGER)" => {
94
+ assert_eq ! ( value, & [ ] as & [ & [ u8 ] ] ) ;
95
+ * self . seen_funcs . lock ( ) . unwrap ( ) += 1 ;
96
+ }
97
+ "TESTMACRO_FUNCTIONAL_TOKENIZED(a,b,c,d,e)" => {
98
+ assert_eq ! (
99
+ value,
100
+ & [ b"a" as & [ u8 ] , b"/" , b"b" , b"c" , b"d" , b"##" , b"e" ]
101
+ ) ;
102
+ * self . seen_funcs . lock ( ) . unwrap ( ) += 1 ;
103
+ }
104
+ "TESTMACRO_FUNCTIONAL_SPLIT(a,b)" => {
105
+ assert_eq ! ( value, & [ b"b" , b"," , b"a" ] ) ;
106
+ * self . seen_funcs . lock ( ) . unwrap ( ) += 1 ;
107
+ }
108
+ "TESTMACRO_STRING_FUNC_NON_UTF8(x)" => {
109
+ assert_eq ! (
110
+ value,
111
+ & [ b"(" as & [ u8 ] , b"x" , b"\" \xff \xff \" " , b")" ]
112
+ ) ;
113
+ * self . seen_funcs . lock ( ) . unwrap ( ) += 1 ;
114
+ }
115
+ _ => {
116
+ // The system might provide lots of functional macros.
117
+ // Ensure we did not miss handling one that we meant to handle.
118
+ assert ! ( !name. starts_with( "TESTMACRO_" ) , "name = {}" , name) ;
119
+ }
120
+ }
121
+ }
73
122
}
74
123
75
124
impl Drop for MacroCallback {
76
125
fn drop ( & mut self ) {
77
126
assert_eq ! (
78
127
* self . seen_hellos. lock( ) . unwrap( ) ,
79
- 2 ,
128
+ 3 ,
80
129
"str_macro handle was not called once for all relevant macros"
81
- )
130
+ ) ;
131
+ assert_eq ! (
132
+ * self . seen_funcs. lock( ) . unwrap( ) ,
133
+ 5 ,
134
+ "func_macro handle was not called once for all relevant macros"
135
+ ) ;
82
136
}
83
137
}
84
138
@@ -102,6 +156,7 @@ fn main() {
102
156
. parse_callbacks ( Box :: new ( MacroCallback {
103
157
macros : macros. clone ( ) ,
104
158
seen_hellos : Mutex :: new ( 0 ) ,
159
+ seen_funcs : Mutex :: new ( 0 ) ,
105
160
} ) )
106
161
. blacklist_function ( "my_prefixed_function_to_remove" )
107
162
. generate ( )
0 commit comments