1d842057cSMauro Carvalho Chehab#!/usr/bin/env python3 2d842057cSMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0 3d842057cSMauro Carvalho Chehab# Copyright(c) 2026: Mauro Carvalho Chehab <mchehab@kernel.org>. 4d842057cSMauro Carvalho Chehab 5d842057cSMauro Carvalho Chehabimport re 6d842057cSMauro Carvalho Chehab 7600079fdSMauro Carvalho Chehabfrom kdoc.kdoc_re import KernRe 879d881beSMauro Carvalho Chehabfrom kdoc.c_lex import CMatch, CTokenizer 9d842057cSMauro Carvalho Chehab 10*7538df7aSMauro Carvalho Chehabstruct_args_pattern = r"([^,)]+)" 11*7538df7aSMauro Carvalho Chehab 12d842057cSMauro Carvalho Chehab 13d842057cSMauro Carvalho Chehabclass CTransforms: 14d842057cSMauro Carvalho Chehab """ 15d842057cSMauro Carvalho Chehab Data class containing a long set of transformations to turn 16d842057cSMauro Carvalho Chehab structure member prefixes, and macro invocations and variables 17d842057cSMauro Carvalho Chehab into something we can parse and generate kdoc for. 18d842057cSMauro Carvalho Chehab """ 19d842057cSMauro Carvalho Chehab 2079d881beSMauro Carvalho Chehab # 2179d881beSMauro Carvalho Chehab # NOTE: 2279d881beSMauro Carvalho Chehab # Due to performance reasons, place CMatch rules before KernRe, 2379d881beSMauro Carvalho Chehab # as this avoids running the C parser every time. 2479d881beSMauro Carvalho Chehab # 2579d881beSMauro Carvalho Chehab 26d842057cSMauro Carvalho Chehab #: Transforms for structs and unions. 27d842057cSMauro Carvalho Chehab struct_xforms = [ 28*7538df7aSMauro Carvalho Chehab (CMatch("__attribute__"), ""), 29*7538df7aSMauro Carvalho Chehab (CMatch("__aligned"), ""), 30*7538df7aSMauro Carvalho Chehab (CMatch("__counted_by"), ""), 31*7538df7aSMauro Carvalho Chehab (CMatch("__counted_by_(le|be)"), ""), 32*7538df7aSMauro Carvalho Chehab (CMatch("__guarded_by"), ""), 33*7538df7aSMauro Carvalho Chehab (CMatch("__pt_guarded_by"), ""), 34*7538df7aSMauro Carvalho Chehab (CMatch("__packed"), ""), 35*7538df7aSMauro Carvalho Chehab (CMatch("CRYPTO_MINALIGN_ATTR"), ""), 36*7538df7aSMauro Carvalho Chehab (CMatch("__private"), ""), 37*7538df7aSMauro Carvalho Chehab (CMatch("__rcu"), ""), 38*7538df7aSMauro Carvalho Chehab (CMatch("____cacheline_aligned_in_smp"), ""), 39*7538df7aSMauro Carvalho Chehab (CMatch("____cacheline_aligned"), ""), 40*7538df7aSMauro Carvalho Chehab (CMatch("__cacheline_group_(?:begin|end)"), ""), 41*7538df7aSMauro Carvalho Chehab (CMatch("__ETHTOOL_DECLARE_LINK_MODE_MASK"), r"DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)"), 42*7538df7aSMauro Carvalho Chehab (CMatch("DECLARE_PHY_INTERFACE_MASK",),r"DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)"), 43*7538df7aSMauro Carvalho Chehab (CMatch("DECLARE_BITMAP"), r"unsigned long \1[BITS_TO_LONGS(\2)]"), 44*7538df7aSMauro Carvalho Chehab (CMatch("DECLARE_HASHTABLE"), r"unsigned long \1[1 << ((\2) - 1)]"), 45*7538df7aSMauro Carvalho Chehab (CMatch("DECLARE_KFIFO"), r"\2 *\1"), 46*7538df7aSMauro Carvalho Chehab (CMatch("DECLARE_KFIFO_PTR"), r"\2 *\1"), 47*7538df7aSMauro Carvalho Chehab (CMatch("(?:__)?DECLARE_FLEX_ARRAY"), r"\1 \2[]"), 48*7538df7aSMauro Carvalho Chehab (CMatch("DEFINE_DMA_UNMAP_ADDR"), r"dma_addr_t \1"), 49*7538df7aSMauro Carvalho Chehab (CMatch("DEFINE_DMA_UNMAP_LEN"), r"__u32 \1"), 50*7538df7aSMauro Carvalho Chehab (CMatch("VIRTIO_DECLARE_FEATURES"), r"union { u64 \1; u64 \1_array[VIRTIO_FEATURES_U64S]; }"), 51*7538df7aSMauro Carvalho Chehab (CMatch("__cond_acquires"), ""), 52*7538df7aSMauro Carvalho Chehab (CMatch("__cond_releases"), ""), 53*7538df7aSMauro Carvalho Chehab (CMatch("__acquires"), ""), 54*7538df7aSMauro Carvalho Chehab (CMatch("__releases"), ""), 55*7538df7aSMauro Carvalho Chehab (CMatch("__must_hold"), ""), 56*7538df7aSMauro Carvalho Chehab (CMatch("__must_not_hold"), ""), 57*7538df7aSMauro Carvalho Chehab (CMatch("__must_hold_shared"), ""), 58*7538df7aSMauro Carvalho Chehab (CMatch("__cond_acquires_shared"), ""), 59*7538df7aSMauro Carvalho Chehab (CMatch("__acquires_shared"), ""), 60*7538df7aSMauro Carvalho Chehab (CMatch("__releases_shared"), ""), 61*7538df7aSMauro Carvalho Chehab (CMatch("__attribute__"), ""), 62f63e6163SMauro Carvalho Chehab 632f07ddbdSMauro Carvalho Chehab # 642f07ddbdSMauro Carvalho Chehab # Macro __struct_group() creates an union with an anonymous 652f07ddbdSMauro Carvalho Chehab # and a non-anonymous struct, depending on the parameters. We only 662f07ddbdSMauro Carvalho Chehab # need one of those at kernel-doc, as we won't be documenting the same 672f07ddbdSMauro Carvalho Chehab # members twice. 682f07ddbdSMauro Carvalho Chehab # 69*7538df7aSMauro Carvalho Chehab (CMatch("struct_group"), r"struct { \2+ };"), 70*7538df7aSMauro Carvalho Chehab (CMatch("struct_group_attr"), r"struct { \3+ };"), 71*7538df7aSMauro Carvalho Chehab (CMatch("struct_group_tagged"), r"struct { \3+ };"), 72*7538df7aSMauro Carvalho Chehab (CMatch("__struct_group"), r"struct { \4+ };"), 73d842057cSMauro Carvalho Chehab ] 74d842057cSMauro Carvalho Chehab 75d842057cSMauro Carvalho Chehab #: Transforms for function prototypes. 76d842057cSMauro Carvalho Chehab function_xforms = [ 77*7538df7aSMauro Carvalho Chehab (CMatch("static"), ""), 78*7538df7aSMauro Carvalho Chehab (CMatch("extern"), ""), 79*7538df7aSMauro Carvalho Chehab (CMatch("asmlinkage"), ""), 80*7538df7aSMauro Carvalho Chehab (CMatch("inline"), ""), 81*7538df7aSMauro Carvalho Chehab (CMatch("__inline__"), ""), 82*7538df7aSMauro Carvalho Chehab (CMatch("__inline"), ""), 83*7538df7aSMauro Carvalho Chehab (CMatch("__always_inline"), ""), 84*7538df7aSMauro Carvalho Chehab (CMatch("noinline"), ""), 85*7538df7aSMauro Carvalho Chehab (CMatch("__FORTIFY_INLINE"), ""), 86*7538df7aSMauro Carvalho Chehab (CMatch("__init"), ""), 87*7538df7aSMauro Carvalho Chehab (CMatch("__init_or_module"), ""), 88*7538df7aSMauro Carvalho Chehab (CMatch("__exit"), ""), 89*7538df7aSMauro Carvalho Chehab (CMatch("__deprecated"), ""), 90*7538df7aSMauro Carvalho Chehab (CMatch("__flatten"), ""), 91*7538df7aSMauro Carvalho Chehab (CMatch("__meminit"), ""), 92*7538df7aSMauro Carvalho Chehab (CMatch("__must_check"), ""), 93*7538df7aSMauro Carvalho Chehab (CMatch("__weak"), ""), 94*7538df7aSMauro Carvalho Chehab (CMatch("__sched"), ""), 95*7538df7aSMauro Carvalho Chehab (CMatch("__always_unused"), ""), 96*7538df7aSMauro Carvalho Chehab (CMatch("__printf"), ""), 97*7538df7aSMauro Carvalho Chehab (CMatch("__(?:re)?alloc_size"), ""), 98*7538df7aSMauro Carvalho Chehab (CMatch("__diagnose_as"), ""), 99*7538df7aSMauro Carvalho Chehab (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"), 100*7538df7aSMauro Carvalho Chehab (CMatch("__no_context_analysis"), ""), 101*7538df7aSMauro Carvalho Chehab (CMatch("__attribute_const__"), ""), 102*7538df7aSMauro Carvalho Chehab (CMatch("__attribute__"), ""), 103*7538df7aSMauro Carvalho Chehab 104*7538df7aSMauro Carvalho Chehab # 105*7538df7aSMauro Carvalho Chehab # HACK: this is similar to process_export() hack. It is meant to 106*7538df7aSMauro Carvalho Chehab # drop _noproof from function name. See for instance: 107*7538df7aSMauro Carvalho Chehab # ahash_request_alloc kernel-doc declaration at include/crypto/hash.h. 108*7538df7aSMauro Carvalho Chehab # 109*7538df7aSMauro Carvalho Chehab (KernRe("_noprof"), ""), 110d842057cSMauro Carvalho Chehab ] 111d842057cSMauro Carvalho Chehab 112d842057cSMauro Carvalho Chehab #: Transforms for variable prototypes. 113d842057cSMauro Carvalho Chehab var_xforms = [ 114*7538df7aSMauro Carvalho Chehab (CMatch("__read_mostly"), ""), 115*7538df7aSMauro Carvalho Chehab (CMatch("__ro_after_init"), ""), 116*7538df7aSMauro Carvalho Chehab (CMatch("__guarded_by"), ""), 117*7538df7aSMauro Carvalho Chehab (CMatch("__pt_guarded_by"), ""), 118*7538df7aSMauro Carvalho Chehab (CMatch("LIST_HEAD"), r"struct list_head \1"), 119*7538df7aSMauro Carvalho Chehab 120d842057cSMauro Carvalho Chehab (KernRe(r"(?://.*)$"), ""), 121d842057cSMauro Carvalho Chehab (KernRe(r"(?:/\*.*\*/)"), ""), 122d842057cSMauro Carvalho Chehab (KernRe(r";$"), ""), 123d842057cSMauro Carvalho Chehab ] 124d842057cSMauro Carvalho Chehab 125d842057cSMauro Carvalho Chehab #: Transforms main dictionary used at apply_transforms(). 126d842057cSMauro Carvalho Chehab xforms = { 127d842057cSMauro Carvalho Chehab "struct": struct_xforms, 128d842057cSMauro Carvalho Chehab "func": function_xforms, 129d842057cSMauro Carvalho Chehab "var": var_xforms, 130d842057cSMauro Carvalho Chehab } 131d842057cSMauro Carvalho Chehab 13279d881beSMauro Carvalho Chehab def apply(self, xforms_type, source): 133d842057cSMauro Carvalho Chehab """ 13479d881beSMauro Carvalho Chehab Apply a set of transforms to a block of source. 13579d881beSMauro Carvalho Chehab 13679d881beSMauro Carvalho Chehab As tokenizer is used here, this function also remove comments 13779d881beSMauro Carvalho Chehab at the end. 138d842057cSMauro Carvalho Chehab """ 139d842057cSMauro Carvalho Chehab if xforms_type not in self.xforms: 14079d881beSMauro Carvalho Chehab return source 14179d881beSMauro Carvalho Chehab 14279d881beSMauro Carvalho Chehab if isinstance(source, str): 14379d881beSMauro Carvalho Chehab source = CTokenizer(source) 144d842057cSMauro Carvalho Chehab 145d842057cSMauro Carvalho Chehab for search, subst in self.xforms[xforms_type]: 14679d881beSMauro Carvalho Chehab # 14779d881beSMauro Carvalho Chehab # KernRe only accept strings. 14879d881beSMauro Carvalho Chehab # 14979d881beSMauro Carvalho Chehab if isinstance(search, KernRe): 15079d881beSMauro Carvalho Chehab source = str(source) 15179d881beSMauro Carvalho Chehab 15279d881beSMauro Carvalho Chehab source = search.sub(subst, source) 15379d881beSMauro Carvalho Chehab return str(source) 154