projects/linux·blob master · refs

162 lines · 5.8 KiB

1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3# Copyright(c) 2026: Mauro Carvalho Chehab <[email protected]>.
4
5import re
6
7from kdoc.kdoc_re import KernRe
8from kdoc.c_lex import CMatch, CTokenizer
9
10struct_args_pattern = r"([^,)]+)"
11
12
13class CTransforms:
14 """
15 Data class containing a long set of transformations to turn
16 structure member prefixes, and macro invocations and variables
17 into something we can parse and generate kdoc for.
18 """
19
20 #
21 # NOTE:
22 # Due to performance reasons, place CMatch rules before KernRe,
23 # as this avoids running the C parser every time.
24 #
25
26 #: Transforms for structs and unions.
27 struct_xforms = [
28 (CMatch("__attribute__"), ""),
29 (CMatch("__aligned"), ""),
30 (CMatch("__counted_by"), ""),
31 (CMatch("__counted_by_(le|be)"), ""),
32 (CMatch("__counted_by_ptr"), ""),
33 (CMatch("__guarded_by"), ""),
34 (CMatch("__pt_guarded_by"), ""),
35 (CMatch("__packed"), ""),
36 (CMatch("CRYPTO_MINALIGN_ATTR"), ""),
37 (CMatch("__private"), ""),
38 (CMatch("__rcu"), ""),
39 (CMatch("____cacheline_aligned_in_smp"), ""),
40 (CMatch("____cacheline_aligned"), ""),
41 (CMatch("__cacheline_group_(?:begin|end)"), ""),
42 (CMatch("__ETHTOOL_DECLARE_LINK_MODE_MASK"), r"DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)"),
43 (CMatch("DECLARE_PHY_INTERFACE_MASK",),r"DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)"),
44 (CMatch("DECLARE_BITMAP"), r"unsigned long \1[BITS_TO_LONGS(\2)]"),
45 (CMatch("DECLARE_HASHTABLE"), r"unsigned long \1[1 << ((\2) - 1)]"),
46 (CMatch("DECLARE_KFIFO"), r"\2 *\1"),
47 (CMatch("DECLARE_KFIFO_PTR"), r"\2 *\1"),
48 (CMatch("DECLARE_PIDS"), r"struct pid *\1[(\2) + 1]"),
49 (CMatch("(?:__)?DECLARE_FLEX_ARRAY"), r"\1 \2[]"),
50 (CMatch("DEFINE_DMA_UNMAP_ADDR"), r"dma_addr_t \1"),
51 (CMatch("DEFINE_DMA_UNMAP_LEN"), r"__u32 \1"),
52 (CMatch("VIRTIO_DECLARE_FEATURES"), r"union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }"),
53 (CMatch("__SYSFS_FUNCTION_ALTERNATIVE"), r"union { \1+ }"),
54 (CMatch("__attribute__"), ""),
55
56 #
57 # Macro __struct_group() creates a union with an anonymous
58 # and a non-anonymous struct, depending on the parameters. We only
59 # need one of those at kernel-doc, as we won't be documenting the same
60 # members twice.
61 #
62 (CMatch("struct_group"), r"struct { \2+ };"),
63 (CMatch("struct_group_attr"), r"struct { \3+ };"),
64 (CMatch("struct_group_tagged"), r"struct { \3+ };"),
65 (CMatch("__struct_group"), r"struct { \4+ };"),
66 (CMatch("context_lock_struct"), r"struct \1"),
67 ]
68
69 #: Transforms for function prototypes.
70 function_xforms = [
71 (CMatch("static"), ""),
72 (CMatch("extern"), ""),
73 (CMatch("asmlinkage"), ""),
74 (CMatch("inline"), ""),
75 (CMatch("__inline__"), ""),
76 (CMatch("__inline"), ""),
77 (CMatch("__always_inline"), ""),
78 (CMatch("noinline"), ""),
79 (CMatch("__FORTIFY_INLINE"), ""),
80 (CMatch("__init"), ""),
81 (CMatch("__init_or_module"), ""),
82 (CMatch("__exit"), ""),
83 (CMatch("__deprecated"), ""),
84 (CMatch("__flatten"), ""),
85 (CMatch("__meminit"), ""),
86 (CMatch("__must_check"), ""),
87 (CMatch("__weak"), ""),
88 (CMatch("__sched"), ""),
89 (CMatch("__always_unused"), ""),
90 (CMatch("__maybe_unused"), ""),
91 (CMatch("__printf"), ""),
92 (CMatch("__(?:re)?alloc_size"), ""),
93 (CMatch("__diagnose_as"), ""),
94 (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"),
95 (CMatch("DEFINE_IDTENTRY_IRQ"), r"static void \1(struct pt_regs *regs, u32 vector)"),
96 (CMatch("__cond_acquires"), ""),
97 (CMatch("__cond_releases"), ""),
98 (CMatch("__acquires"), ""),
99 (CMatch("__releases"), ""),
100 (CMatch("__must_hold"), ""),
101 (CMatch("__must_not_hold"), ""),
102 (CMatch("__must_hold_shared"), ""),
103 (CMatch("__cond_acquires_shared"), ""),
104 (CMatch("__acquires_shared"), ""),
105 (CMatch("__releases_shared"), ""),
106 (CMatch("__no_context_analysis"), ""),
107 (CMatch("__attribute_const__"), ""),
108 (CMatch("__attribute__"), ""),
109 (CMatch("STATIC_IFN_KUNIT"), ""),
110 (CMatch("INLINE_IFN_KUNIT"), ""),
111
112 #
113 # HACK: this is similar to process_export() hack. It is meant to
114 # drop _noproof from function name. See for instance:
115 # ahash_request_alloc kernel-doc declaration at include/crypto/hash.h.
116 #
117 (KernRe("_noprof"), ""),
118 ]
119
120 #: Transforms for variable prototypes.
121 var_xforms = [
122 (CMatch("__read_mostly"), ""),
123 (CMatch("__ro_after_init"), ""),
124 (CMatch("__guarded_by"), ""),
125 (CMatch("__pt_guarded_by"), ""),
126 (CMatch("LIST_HEAD"), r"struct list_head \1"),
127 (CMatch("DECLARE_PER_CPU"), r"\1 \2[PER_CPU]; }"),
128
129 (KernRe(r"(?://.*)$"), ""),
130 (KernRe(r"(?:/\*.*\*/)"), ""),
131 (KernRe(r";$"), ""),
132 ]
133
134 #: Transforms main dictionary used at apply_transforms().
135 xforms = {
136 "struct": struct_xforms,
137 "func": function_xforms,
138 "var": var_xforms,
139 }
140
141 def apply(self, xforms_type, source):
142 """
143 Apply a set of transforms to a block of source.
144
145 As tokenizer is used here, this function also remove comments
146 at the end.
147 """
148 if xforms_type not in self.xforms:
149 return source
150
151 if isinstance(source, str):
152 source = CTokenizer(source)
153
154 for search, subst in self.xforms[xforms_type]:
155 #
156 # KernRe only accept strings.
157 #
158 if isinstance(search, KernRe):
159 source = str(source)
160
161 source = search.sub(subst, source)
162 return str(source)