1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
+ use core:: fmt;
3
4
use proc_macro:: { token_stream, Delimiter , Group , TokenStream , TokenTree } ;
4
5
5
6
fn try_ident ( it : & mut token_stream:: IntoIter ) -> Option < String > {
@@ -110,93 +111,6 @@ fn get_byte_string(it: &mut token_stream::IntoIter, expected_name: &str) -> Stri
110
111
byte_string
111
112
}
112
113
113
- fn __build_modinfo_string_base (
114
- module : & str ,
115
- field : & str ,
116
- content : & str ,
117
- variable : & str ,
118
- builtin : bool ,
119
- ) -> String {
120
- let string = if builtin {
121
- // Built-in modules prefix their modinfo strings by `module.`.
122
- format ! (
123
- "{module}.{field}={content}" ,
124
- module = module,
125
- field = field,
126
- content = content
127
- )
128
- } else {
129
- // Loadable modules' modinfo strings go as-is.
130
- format ! ( "{field}={content}" , field = field, content = content)
131
- } ;
132
-
133
- format ! (
134
- "
135
- {cfg}
136
- #[link_section = \" .modinfo\" ]
137
- #[used]
138
- pub static {variable}: [u8; {length}] = *b\" {string}\\ 0\" ;
139
- " ,
140
- cfg = if builtin {
141
- "#[cfg(not(MODULE))]"
142
- } else {
143
- "#[cfg(MODULE)]"
144
- } ,
145
- variable = variable,
146
- length = string. len( ) + 1 ,
147
- string = string,
148
- )
149
- }
150
-
151
- fn __build_modinfo_string_variable ( module : & str , field : & str ) -> String {
152
- format ! ( "__{module}_{field}" , module = module, field = field)
153
- }
154
-
155
- fn build_modinfo_string_only_builtin ( module : & str , field : & str , content : & str ) -> String {
156
- __build_modinfo_string_base (
157
- module,
158
- field,
159
- content,
160
- & __build_modinfo_string_variable ( module, field) ,
161
- true ,
162
- )
163
- }
164
-
165
- fn build_modinfo_string_only_loadable ( module : & str , field : & str , content : & str ) -> String {
166
- __build_modinfo_string_base (
167
- module,
168
- field,
169
- content,
170
- & __build_modinfo_string_variable ( module, field) ,
171
- false ,
172
- )
173
- }
174
-
175
- fn build_modinfo_string ( module : & str , field : & str , content : & str ) -> String {
176
- build_modinfo_string_only_builtin ( module, field, content)
177
- + & build_modinfo_string_only_loadable ( module, field, content)
178
- }
179
-
180
- fn build_modinfo_string_optional ( module : & str , field : & str , content : Option < & str > ) -> String {
181
- if let Some ( content) = content {
182
- build_modinfo_string ( module, field, content)
183
- } else {
184
- "" . to_string ( )
185
- }
186
- }
187
-
188
- fn build_modinfo_string_param ( module : & str , field : & str , param : & str , content : & str ) -> String {
189
- let variable = format ! (
190
- "__{module}_{field}_{param}" ,
191
- module = module,
192
- field = field,
193
- param = param
194
- ) ;
195
- let content = format ! ( "{param}:{content}" , param = param, content = content) ;
196
- __build_modinfo_string_base ( module, field, & content, & variable, true )
197
- + & __build_modinfo_string_base ( module, field, & content, & variable, false )
198
- }
199
-
200
114
fn permissions_are_readonly ( perms : & str ) -> bool {
201
115
let ( radix, digits) = if let Some ( n) = perms. strip_prefix ( "0x" ) {
202
116
( 16 , n)
@@ -298,6 +212,118 @@ fn generated_array_ops_name(vals: &str, max_length: usize) -> String {
298
212
)
299
213
}
300
214
215
+ struct ModuleInfoStringBuilder < ' a > {
216
+ counter : usize ,
217
+ module : & ' a str ,
218
+ }
219
+
220
+ impl < ' a > ModuleInfoStringBuilder < ' a > {
221
+ fn new ( module_str : & ' a str ) -> ModuleInfoStringBuilder < ' a > {
222
+ ModuleInfoStringBuilder {
223
+ module : module_str,
224
+ counter : 0 ,
225
+ }
226
+ }
227
+
228
+ fn build_modinfo_string_base (
229
+ & self ,
230
+ field : & str ,
231
+ content : & str ,
232
+ variable : & str ,
233
+ builtin : bool ,
234
+ ) -> String {
235
+ let string = if builtin {
236
+ // Built-in modules prefix their modinfo strings by `module.`.
237
+ format ! (
238
+ "{module}.{field}={content}" ,
239
+ module = self . module,
240
+ field = field,
241
+ content = content
242
+ )
243
+ } else {
244
+ // Loadable modules' modinfo strings go as-is.
245
+ format ! ( "{field}={content}" , field = field, content = content)
246
+ } ;
247
+
248
+ format ! (
249
+ "
250
+ {cfg}
251
+ #[link_section = \" .modinfo\" ]
252
+ #[used]
253
+ pub static {variable}: [u8; {length}] = *b\" {string}\\ 0\" ;
254
+ " ,
255
+ cfg = if builtin {
256
+ "#[cfg(not(MODULE))]"
257
+ } else {
258
+ "#[cfg(MODULE)]"
259
+ } ,
260
+ variable = variable,
261
+ length = string. len( ) + 1 ,
262
+ string = string,
263
+ )
264
+ }
265
+
266
+ fn build_modinfo_string_variable ( & mut self , field : & str ) -> String {
267
+ self . counter += 1 ;
268
+ format ! (
269
+ "__{module}_{field}{counter}" ,
270
+ module = self . module,
271
+ field = field,
272
+ counter = self . counter,
273
+ )
274
+ }
275
+
276
+ fn build_modinfo_string_only_builtin ( & mut self , field : & str , content : & str ) -> String {
277
+ let str_var = self . build_modinfo_string_variable ( field) ;
278
+ self . build_modinfo_string_base ( field, content, & str_var, true )
279
+ }
280
+
281
+ fn build_modinfo_string_only_loadable ( & mut self , field : & str , content : & str ) -> String {
282
+ let str_var = self . build_modinfo_string_variable ( field) ;
283
+ self . build_modinfo_string_base ( field, content, & str_var, false )
284
+ }
285
+
286
+ fn build_modinfo_string ( & mut self , field : & str , content : & str ) -> String {
287
+ self . build_modinfo_string_only_builtin ( field, content)
288
+ + & self . build_modinfo_string_only_loadable ( field, content)
289
+ }
290
+
291
+ fn build_modinfo_string_optional ( & mut self , field : & str , content : Option < & str > ) -> String {
292
+ if let Some ( content) = content {
293
+ self . build_modinfo_string ( field, content)
294
+ } else {
295
+ "" . to_string ( )
296
+ }
297
+ }
298
+
299
+ fn build_modinfo_string_param ( & mut self , field : & str , param : & str , content : & str ) -> String {
300
+ let variable = format ! (
301
+ "__{module}_{field}_{param}" ,
302
+ module = self . module,
303
+ field = field,
304
+ param = param
305
+ ) ;
306
+ let content = format ! ( "{param}:{content}" , param = param, content = content) ;
307
+ self . build_modinfo_string_base ( field, & content, & variable, true )
308
+ + & self . build_modinfo_string_base ( field, & content, & variable, false )
309
+ }
310
+ }
311
+
312
+ #[ derive( Debug ) ]
313
+ enum Softdep {
314
+ Pre ( String ) ,
315
+ Post ( String ) ,
316
+ }
317
+
318
+ impl fmt:: Display for Softdep {
319
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
320
+ match self {
321
+ Softdep :: Pre ( ref module) => write ! ( f, "pre: {}" , module) ,
322
+ Softdep :: Post ( ref module) => write ! ( f, "post: {}" , module) ,
323
+ }
324
+ }
325
+ }
326
+
301
327
#[ derive( Debug , Default ) ]
302
328
struct ModuleInfo {
303
329
type_ : String ,
@@ -307,6 +333,7 @@ struct ModuleInfo {
307
333
description : Option < String > ,
308
334
alias : Option < String > ,
309
335
params : Option < Group > ,
336
+ softdeps : Option < Vec < Softdep > > ,
310
337
}
311
338
312
339
impl ModuleInfo {
@@ -322,6 +349,7 @@ impl ModuleInfo {
322
349
"alias" ,
323
350
"alias_rtnl_link" ,
324
351
"params" ,
352
+ "softdeps" ,
325
353
] ;
326
354
const REQUIRED_KEYS : & [ & str ] = & [ "type" , "name" , "license" ] ;
327
355
let mut seen_keys = Vec :: new ( ) ;
@@ -353,6 +381,9 @@ impl ModuleInfo {
353
381
info. alias = Some ( format ! ( "rtnl-link-{}" , expect_byte_string( it) ) )
354
382
}
355
383
"params" => info. params = Some ( expect_group ( it) ) ,
384
+ "softdeps" => {
385
+ info. softdeps = Some ( Self :: parse_softdeps ( expect_group ( it) ) ) ;
386
+ }
356
387
_ => panic ! (
357
388
"Unknown key \" {}\" . Valid keys are: {:?}." ,
358
389
key, EXPECTED_KEYS
@@ -388,17 +419,58 @@ impl ModuleInfo {
388
419
389
420
info
390
421
}
422
+
423
+ fn parse_softdeps ( group : Group ) -> Vec < Softdep > {
424
+ assert_eq ! ( group. delimiter( ) , Delimiter :: Brace ) ;
425
+
426
+ let mut it = group. stream ( ) . into_iter ( ) ;
427
+
428
+ let mut res = vec ! [ ] ;
429
+
430
+ while let Some ( order) = try_ident ( & mut it) {
431
+ res. push ( Self :: parse_softdep ( & mut it, & order) ) ;
432
+ }
433
+
434
+ expect_end ( & mut it) ;
435
+
436
+ res
437
+ }
438
+
439
+ fn parse_softdep ( it : & mut token_stream:: IntoIter , order : & str ) -> Softdep {
440
+ assert_eq ! ( expect_punct( it) , ':' ) ;
441
+ let module = expect_ident ( it) ;
442
+ let softdep = match & * order {
443
+ "pre" => Softdep :: Pre ( module) ,
444
+ "post" => Softdep :: Post ( module) ,
445
+ _ => panic ! ( "failed to parse invalid softdep '{}: {}" , order, module) ,
446
+ } ;
447
+ assert_eq ! ( expect_punct( it) , ',' ) ;
448
+ softdep
449
+ }
450
+
451
+ fn encode_softdeps < ' a > ( & self , str_builder : & mut ModuleInfoStringBuilder < ' a > ) -> String {
452
+ match self . softdeps {
453
+ Some ( ref softdeps) => softdeps. iter ( ) . fold ( String :: new ( ) , |mut acc, new| {
454
+ acc. push_str ( & str_builder. build_modinfo_string ( "softdep" , & format ! ( "{}" , new) ) ) ;
455
+ acc
456
+ } ) ,
457
+ None => String :: new ( ) ,
458
+ }
459
+ }
391
460
}
392
461
393
462
pub fn module ( ts : TokenStream ) -> TokenStream {
394
463
let mut it = ts. into_iter ( ) ;
395
464
396
465
let info = ModuleInfo :: parse ( & mut it) ;
466
+ let mut str_builder = ModuleInfoStringBuilder :: new ( & info. name ) ;
397
467
398
468
let name = info. name . clone ( ) ;
399
469
400
470
let mut array_types_to_generate = Vec :: new ( ) ;
401
471
let mut params_modinfo = String :: new ( ) ;
472
+ let softdeps = info. encode_softdeps ( & mut str_builder) ;
473
+
402
474
if let Some ( params) = info. params {
403
475
assert_eq ! ( params. delimiter( ) , Delimiter :: Brace ) ;
404
476
@@ -443,14 +515,12 @@ pub fn module(ts: TokenStream) -> TokenStream {
443
515
}
444
516
} ;
445
517
446
- params_modinfo. push_str ( & build_modinfo_string_param (
447
- & name,
518
+ params_modinfo. push_str ( & str_builder. build_modinfo_string_param (
448
519
"parmtype" ,
449
520
& param_name,
450
521
& param_kernel_type,
451
522
) ) ;
452
- params_modinfo. push_str ( & build_modinfo_string_param (
453
- & name,
523
+ params_modinfo. push_str ( & str_builder. build_modinfo_string_param (
454
524
"parm" ,
455
525
& param_name,
456
526
& param_description,
@@ -672,16 +742,18 @@ pub fn module(ts: TokenStream) -> TokenStream {
672
742
{params_modinfo}
673
743
674
744
{generated_array_types}
745
+ {softdeps}
675
746
" ,
676
747
type_ = info. type_,
677
748
name = info. name,
678
- author = & build_modinfo_string_optional( & name , "author" , info. author. as_deref( ) ) ,
679
- description = & build_modinfo_string_optional( & name , "description" , info. description. as_deref( ) ) ,
680
- license = & build_modinfo_string( & name , "license" , & info. license) ,
681
- alias = & build_modinfo_string_optional( & name , "alias" , info. alias. as_deref( ) ) ,
682
- file = & build_modinfo_string_only_builtin( & name , "file" , & file) ,
749
+ author = & str_builder . build_modinfo_string_optional( "author" , info. author. as_deref( ) ) ,
750
+ description = & str_builder . build_modinfo_string_optional( "description" , info. description. as_deref( ) ) ,
751
+ license = & str_builder . build_modinfo_string( "license" , & info. license) ,
752
+ alias = & str_builder . build_modinfo_string_optional( "alias" , info. alias. as_deref( ) ) ,
753
+ file = & str_builder . build_modinfo_string_only_builtin( "file" , & file) ,
683
754
params_modinfo = params_modinfo,
684
755
generated_array_types = generated_array_types,
756
+ softdeps = softdeps,
685
757
initcall_section = ".initcall6.init"
686
758
) . parse ( ) . expect ( "Error parsing formatted string into token stream." )
687
759
}
0 commit comments