From nobody Fri Dec 19 22:07:08 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA4E426560E; Tue, 8 Apr 2025 10:09:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744106999; cv=none; b=hyWhJQnTpJjakaLBlE7w6SBry/PLeF3QapWsx/ntzVyRRao3FB7FxbzxnyddqnZhjXLeR0UI1+JL5mdUlCTMSJm+lPf6xFAH/gkkLnR/+S+MDdZrZYmU8n9B676gHrmESn8HX71INjDw2/hI8goqnQcWaGujSKcaqjtCNftVlW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744106999; c=relaxed/simple; bh=SszucMXEdc/sou+xc8alSD8raZAiM5Q3h/x3KVgAi8Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NCicaTa2QRjAk2M/YvS0EhRUwV0yofkOL0ZNsCXJoLDbQQktiKRS5D+fEWa5fm2w2NoWGcG29T3HuIiilq/y6IIwdQ1wkfEsUTnzaf5GapPDk4D+vH3Q+ZTMS/Y45ACIJ4kEa6wwDu+Rdfc4wQaF5OQQNpkiW2Z0XFBxNvJatCs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oPtVmZJv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oPtVmZJv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9FE03C4CEF4; Tue, 8 Apr 2025 10:09:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744106999; bh=SszucMXEdc/sou+xc8alSD8raZAiM5Q3h/x3KVgAi8Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oPtVmZJvNmTIb7w7HHWkz9iDfi6d02/FAg3jtko4psFSyMRVfVfnyC6kL0KfAnb0Q 0VIB/Xaz794TvZ/658FddqQhEvV64zboUdJEpjNFxZmZ5R5gaV7W39j3GcExZdlNRK n+E1/4RNwu36sKUHLQw21mNtj0Q3upm8Wn4sUuGB99h14gaeQo3hs0bZ9Q5grbjglk ACF3xo8+pZcY+z2P2vAlE6Owaa87fHoEaYFJRSuelF/eP6yDEXhccjKfYAqp7frlRj JYUXCaTl0Wjt579tvKtITfGLRwhoeg9/YdkSHZZC4W83q9V47wPGomZQCqFbYBD9Gy XmrZrwsj1hlfw== Received: from mchehab by mail.kernel.org with local (Exim 4.98.2) (envelope-from ) id 1u25tt-00000008RWn-2ujm; Tue, 08 Apr 2025 18:09:49 +0800 From: Mauro Carvalho Chehab To: Linux Doc Mailing List , Jonathan Corbet Cc: Mauro Carvalho Chehab , "Gustavo A. R. Silva" , Kees Cook , Sean Anderson , linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 32/33] scripts/kernel-doc.py: Rename the kernel doc Re class to KernRe Date: Tue, 8 Apr 2025 18:09:35 +0800 Message-ID: <4e095ecd5235a3e811ddcf5bad4cfb92f1da0a4a.1744106242.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" Using just "Re" makes it harder to distinguish from the native "re" class. So, let's rename it. Signed-off-by: Mauro Carvalho Chehab --- scripts/lib/kdoc/kdoc_output.py | 50 +++--- scripts/lib/kdoc/kdoc_parser.py | 264 ++++++++++++++++---------------- scripts/lib/kdoc/kdoc_re.py | 4 +- 3 files changed, 159 insertions(+), 159 deletions(-) diff --git a/scripts/lib/kdoc/kdoc_output.py b/scripts/lib/kdoc/kdoc_output= .py index c352b7f8d3fd..86102e628d91 100755 --- a/scripts/lib/kdoc/kdoc_output.py +++ b/scripts/lib/kdoc/kdoc_output.py @@ -20,31 +20,31 @@ import re from datetime import datetime =20 from kdoc_parser import KernelDoc, type_param -from kdoc_re import Re +from kdoc_re import KernRe =20 =20 -function_pointer =3D Re(r"([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)", cache=3DFalse) +function_pointer =3D KernRe(r"([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)", cache=3DF= alse) =20 # match expressions used to find embedded type information -type_constant =3D Re(r"\b``([^\`]+)``\b", cache=3DFalse) -type_constant2 =3D Re(r"\%([-_*\w]+)", cache=3DFalse) -type_func =3D Re(r"(\w+)\(\)", cache=3DFalse) -type_param_ref =3D Re(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cac= he=3DFalse) +type_constant =3D KernRe(r"\b``([^\`]+)``\b", cache=3DFalse) +type_constant2 =3D KernRe(r"\%([-_*\w]+)", cache=3DFalse) +type_func =3D KernRe(r"(\w+)\(\)", cache=3DFalse) +type_param_ref =3D KernRe(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)",= cache=3DFalse) =20 # Special RST handling for func ptr params -type_fp_param =3D Re(r"\@(\w+)\(\)", cache=3DFalse) +type_fp_param =3D KernRe(r"\@(\w+)\(\)", cache=3DFalse) =20 # Special RST handling for structs with func ptr params -type_fp_param2 =3D Re(r"\@(\w+->\S+)\(\)", cache=3DFalse) +type_fp_param2 =3D KernRe(r"\@(\w+->\S+)\(\)", cache=3DFalse) =20 -type_env =3D Re(r"(\$\w+)", cache=3DFalse) -type_enum =3D Re(r"\&(enum\s*([_\w]+))", cache=3DFalse) -type_struct =3D Re(r"\&(struct\s*([_\w]+))", cache=3DFalse) -type_typedef =3D Re(r"\&(typedef\s*([_\w]+))", cache=3DFalse) -type_union =3D Re(r"\&(union\s*([_\w]+))", cache=3DFalse) -type_member =3D Re(r"\&([_\w]+)(\.|->)([_\w]+)", cache=3DFalse) -type_fallback =3D Re(r"\&([_\w]+)", cache=3DFalse) -type_member_func =3D type_member + Re(r"\(\)", cache=3DFalse) +type_env =3D KernRe(r"(\$\w+)", cache=3DFalse) +type_enum =3D KernRe(r"\&(enum\s*([_\w]+))", cache=3DFalse) +type_struct =3D KernRe(r"\&(struct\s*([_\w]+))", cache=3DFalse) +type_typedef =3D KernRe(r"\&(typedef\s*([_\w]+))", cache=3DFalse) +type_union =3D KernRe(r"\&(union\s*([_\w]+))", cache=3DFalse) +type_member =3D KernRe(r"\&([_\w]+)(\.|->)([_\w]+)", cache=3DFalse) +type_fallback =3D KernRe(r"\&([_\w]+)", cache=3DFalse) +type_member_func =3D type_member + KernRe(r"\(\)", cache=3DFalse) =20 =20 class OutputFormat: @@ -257,8 +257,8 @@ class RestFormat(OutputFormat): ] blankline =3D "\n" =20 - sphinx_literal =3D Re(r'^[^.].*::$', cache=3DFalse) - sphinx_cblock =3D Re(r'^\.\.\ +code-block::', cache=3DFalse) + sphinx_literal =3D KernRe(r'^[^.].*::$', cache=3DFalse) + sphinx_cblock =3D KernRe(r'^\.\.\ +code-block::', cache=3DFalse) =20 def __init__(self): """ @@ -299,14 +299,14 @@ class RestFormat(OutputFormat): # If this is the first non-blank line in a literal blo= ck, # figure out the proper indent. if not litprefix: - r =3D Re(r'^(\s*)') + r =3D KernRe(r'^(\s*)') if r.match(line): litprefix =3D '^' + r.group(1) else: litprefix =3D "" =20 output +=3D line + "\n" - elif not Re(litprefix).match(line): + elif not KernRe(litprefix).match(line): in_literal =3D False else: output +=3D line + "\n" @@ -429,7 +429,7 @@ class RestFormat(OutputFormat): self.data +=3D f"{self.lineprefix}**Parameters**\n\n" =20 for parameter in parameterlist: - parameter_name =3D Re(r'\[.*').sub('', parameter) + parameter_name =3D KernRe(r'\[.*').sub('', parameter) dtype =3D args['parametertypes'].get(parameter, "") =20 if dtype: @@ -626,7 +626,7 @@ class ManFormat(OutputFormat): contents =3D "\n".join(contents) =20 for line in contents.strip("\n").split("\n"): - line =3D Re(r"^\s*").sub("", line) + line =3D KernRe(r"^\s*").sub("", line) if not line: continue =20 @@ -680,7 +680,7 @@ class ManFormat(OutputFormat): # Pointer-to-function self.data +=3D f'".BI "{parenth}{function_pointer.group(1)= }" " ") ({function_pointer.group(2)}){post}"' + "\n" else: - dtype =3D Re(r'([^\*])$').sub(r'\1 ', dtype) + dtype =3D KernRe(r'([^\*])$').sub(r'\1 ', dtype) =20 self.data +=3D f'.BI "{parenth}{dtype}" "{post}"' + "\n" count +=3D 1 @@ -727,7 +727,7 @@ class ManFormat(OutputFormat): self.data +=3D ".SH Constants\n" =20 for parameter in parameterlist: - parameter_name =3D Re(r'\[.*').sub('', parameter) + parameter_name =3D KernRe(r'\[.*').sub('', parameter) self.data +=3D f'.IP "{parameter}" 12' + "\n" self.output_highlight(args['parameterdescs'].get(parameter_nam= e, "")) =20 @@ -769,7 +769,7 @@ class ManFormat(OutputFormat): =20 # Replace tabs with two spaces and handle newlines declaration =3D definition.replace("\t", " ") - declaration =3D Re(r"\n").sub('"\n.br\n.BI "', declaration) + declaration =3D KernRe(r"\n").sub('"\n.br\n.BI "', declaration) =20 self.data +=3D ".SH SYNOPSIS\n" self.data +=3D f"{struct_type} {struct_name} " + "{" + "\n.br\n" diff --git a/scripts/lib/kdoc/kdoc_parser.py b/scripts/lib/kdoc/kdoc_parser= .py index 33f00c77dd5f..f60722bcc687 100755 --- a/scripts/lib/kdoc/kdoc_parser.py +++ b/scripts/lib/kdoc/kdoc_parser.py @@ -16,7 +16,7 @@ import argparse import re from pprint import pformat =20 -from kdoc_re import NestedMatch, Re +from kdoc_re import NestedMatch, KernRe =20 =20 # @@ -29,12 +29,12 @@ from kdoc_re import NestedMatch, Re # =20 # Allow whitespace at end of comment start. -doc_start =3D Re(r'^/\*\*\s*$', cache=3DFalse) +doc_start =3D KernRe(r'^/\*\*\s*$', cache=3DFalse) =20 -doc_end =3D Re(r'\*/', cache=3DFalse) -doc_com =3D Re(r'\s*\*\s*', cache=3DFalse) -doc_com_body =3D Re(r'\s*\* ?', cache=3DFalse) -doc_decl =3D doc_com + Re(r'(\w+)', cache=3DFalse) +doc_end =3D KernRe(r'\*/', cache=3DFalse) +doc_com =3D KernRe(r'\s*\*\s*', cache=3DFalse) +doc_com_body =3D KernRe(r'\s*\* ?', cache=3DFalse) +doc_decl =3D doc_com + KernRe(r'(\w+)', cache=3DFalse) =20 # @params and a strictly limited set of supported section names # Specifically: @@ -44,22 +44,22 @@ doc_decl =3D doc_com + Re(r'(\w+)', cache=3DFalse) # while trying to not match literal block starts like "example::" # doc_sect =3D doc_com + \ - Re(r'\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?= |examples?)\s*:([^:].*)?$', + KernRe(r'\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|no= tes?|examples?)\s*:([^:].*)?$', flags=3Dre.I, cache=3DFalse) =20 -doc_content =3D doc_com_body + Re(r'(.*)', cache=3DFalse) -doc_block =3D doc_com + Re(r'DOC:\s*(.*)?', cache=3DFalse) -doc_inline_start =3D Re(r'^\s*/\*\*\s*$', cache=3DFalse) -doc_inline_sect =3D Re(r'\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)', cache=3DFalse) -doc_inline_end =3D Re(r'^\s*\*/\s*$', cache=3DFalse) -doc_inline_oneline =3D Re(r'^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$', cac= he=3DFalse) -attribute =3D Re(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", +doc_content =3D doc_com_body + KernRe(r'(.*)', cache=3DFalse) +doc_block =3D doc_com + KernRe(r'DOC:\s*(.*)?', cache=3DFalse) +doc_inline_start =3D KernRe(r'^\s*/\*\*\s*$', cache=3DFalse) +doc_inline_sect =3D KernRe(r'\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)', cache=3DF= alse) +doc_inline_end =3D KernRe(r'^\s*\*/\s*$', cache=3DFalse) +doc_inline_oneline =3D KernRe(r'^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$',= cache=3DFalse) +attribute =3D KernRe(r"__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)", flags=3Dre.I | re.S, cache=3DFalse) =20 -export_symbol =3D Re(r'^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*', cac= he=3DFalse) -export_symbol_ns =3D Re(r'^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"= \S+"\)\s*', cache=3DFalse) +export_symbol =3D KernRe(r'^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*',= cache=3DFalse) +export_symbol_ns =3D KernRe(r'^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,= \s*"\S+"\)\s*', cache=3DFalse) =20 -type_param =3D Re(r"\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=3DFalse) +type_param =3D KernRe(r"\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=3DFalse) =20 =20 class KernelDoc: @@ -278,10 +278,10 @@ class KernelDoc: =20 self.entry.anon_struct_union =3D False =20 - param =3D Re(r'[\[\)].*').sub('', param, count=3D1) + param =3D KernRe(r'[\[\)].*').sub('', param, count=3D1) =20 if dtype =3D=3D "" and param.endswith("..."): - if Re(r'\w\.\.\.$').search(param): + if KernRe(r'\w\.\.\.$').search(param): # For named variable parameters of the form `x...`, # remove the dots param =3D param[:-3] @@ -335,7 +335,7 @@ class KernelDoc: # to ignore "[blah" in a parameter string. =20 self.entry.parameterlist.append(param) - org_arg =3D Re(r'\s\s+').sub(' ', org_arg) + org_arg =3D KernRe(r'\s\s+').sub(' ', org_arg) self.entry.parametertypes[param] =3D org_arg =20 def save_struct_actual(self, actual): @@ -344,7 +344,7 @@ class KernelDoc: one string item. """ =20 - actual =3D Re(r'\s*').sub("", actual, count=3D1) + actual =3D KernRe(r'\s*').sub("", actual, count=3D1) =20 self.entry.struct_actual +=3D actual + " " =20 @@ -355,20 +355,20 @@ class KernelDoc: """ =20 # temporarily replace all commas inside function pointer definition - arg_expr =3D Re(r'(\([^\),]+),') + arg_expr =3D KernRe(r'(\([^\),]+),') while arg_expr.search(args): args =3D arg_expr.sub(r"\1#", args) =20 for arg in args.split(splitter): # Strip comments - arg =3D Re(r'\/\*.*\*\/').sub('', arg) + arg =3D KernRe(r'\/\*.*\*\/').sub('', arg) =20 # Ignore argument attributes - arg =3D Re(r'\sPOS0?\s').sub(' ', arg) + arg =3D KernRe(r'\sPOS0?\s').sub(' ', arg) =20 # Strip leading/trailing spaces arg =3D arg.strip() - arg =3D Re(r'\s+').sub(' ', arg, count=3D1) + arg =3D KernRe(r'\s+').sub(' ', arg, count=3D1) =20 if arg.startswith('#'): # Treat preprocessor directive as a typeless variable just= to fill @@ -379,63 +379,63 @@ class KernelDoc: self.push_parameter(ln, decl_type, arg, "", "", declaration_name) =20 - elif Re(r'\(.+\)\s*\(').search(arg): + elif KernRe(r'\(.+\)\s*\(').search(arg): # Pointer-to-function =20 arg =3D arg.replace('#', ',') =20 - r =3D Re(r'[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)') + r =3D KernRe(r'[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)') if r.match(arg): param =3D r.group(1) else: self.emit_warning(ln, f"Invalid param: {arg}") param =3D arg =20 - dtype =3D Re(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r= '\1', arg) + dtype =3D KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).s= ub(r'\1', arg) self.save_struct_actual(param) self.push_parameter(ln, decl_type, param, dtype, arg, declaration_name) =20 - elif Re(r'\(.+\)\s*\[').search(arg): + elif KernRe(r'\(.+\)\s*\[').search(arg): # Array-of-pointers =20 arg =3D arg.replace('#', ',') - r =3D Re(r'[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[\w]+= \s*\]\s*)*\)') + r =3D KernRe(r'[^\(]+\(\s*\*\s*([\w\[\]\.]*?)\s*(\s*\[\s*[= \w]+\s*\]\s*)*\)') if r.match(arg): param =3D r.group(1) else: self.emit_warning(ln, f"Invalid param: {arg}") param =3D arg =20 - dtype =3D Re(r'([^\(]+\(\*?)\s*' + re.escape(param)).sub(r= '\1', arg) + dtype =3D KernRe(r'([^\(]+\(\*?)\s*' + re.escape(param)).s= ub(r'\1', arg) =20 self.save_struct_actual(param) self.push_parameter(ln, decl_type, param, dtype, arg, declaration_name) =20 elif arg: - arg =3D Re(r'\s*:\s*').sub(":", arg) - arg =3D Re(r'\s*\[').sub('[', arg) + arg =3D KernRe(r'\s*:\s*').sub(":", arg) + arg =3D KernRe(r'\s*\[').sub('[', arg) =20 - args =3D Re(r'\s*,\s*').split(arg) + args =3D KernRe(r'\s*,\s*').split(arg) if args[0] and '*' in args[0]: args[0] =3D re.sub(r'(\*+)\s*', r' \1', args[0]) =20 first_arg =3D [] - r =3D Re(r'^(.*\s+)(.*?\[.*\].*)$') + r =3D KernRe(r'^(.*\s+)(.*?\[.*\].*)$') if args[0] and r.match(args[0]): args.pop(0) first_arg.extend(r.group(1)) first_arg.append(r.group(2)) else: - first_arg =3D Re(r'\s+').split(args.pop(0)) + first_arg =3D KernRe(r'\s+').split(args.pop(0)) =20 args.insert(0, first_arg.pop()) dtype =3D ' '.join(first_arg) =20 for param in args: - if Re(r'^(\*+)\s*(.*)').match(param): - r =3D Re(r'^(\*+)\s*(.*)') + if KernRe(r'^(\*+)\s*(.*)').match(param): + r =3D KernRe(r'^(\*+)\s*(.*)') if not r.match(param): self.emit_warning(ln, f"Invalid param: {param}= ") continue @@ -447,8 +447,8 @@ class KernelDoc: f"{dtype} {r.group(1)}", arg, declaration_name) =20 - elif Re(r'(.*?):(\w+)').search(param): - r =3D Re(r'(.*?):(\w+)') + elif KernRe(r'(.*?):(\w+)').search(param): + r =3D KernRe(r'(.*?):(\w+)') if not r.match(param): self.emit_warning(ln, f"Invalid param: {param}= ") continue @@ -477,7 +477,7 @@ class KernelDoc: err =3D True for px in range(len(prms)): # pylint: disable=3D= C0200 prm_clean =3D prms[px] - prm_clean =3D Re(r'\[.*\]').sub('', prm_clean) + prm_clean =3D KernRe(r'\[.*\]').sub('', prm_clean) prm_clean =3D attribute.sub('', prm_clean) =20 # ignore array size in a parameter string; @@ -486,7 +486,7 @@ class KernelDoc: # and this appears in @prms as "addr[6" since the # parameter list is split at spaces; # hence just ignore "[..." for the sections check; - prm_clean =3D Re(r'\[.*').sub('', prm_clean) + prm_clean =3D KernRe(r'\[.*').sub('', prm_clean) =20 if prm_clean =3D=3D sects[sx]: err =3D False @@ -512,7 +512,7 @@ class KernelDoc: =20 # Ignore an empty return type (It's a macro) # Ignore functions with a "void" return type (but not "void *") - if not return_type or Re(r'void\s*\w*\s*$').search(return_type): + if not return_type or KernRe(r'void\s*\w*\s*$').search(return_type= ): return =20 if not self.entry.sections.get("Return", None): @@ -535,20 +535,20 @@ class KernelDoc: ] =20 definition_body =3D r'\{(.*)\}\s*' + "(?:" + '|'.join(qualifiers) = + ")?" - struct_members =3D Re(type_pattern + r'([^\{\};]+)(\{)([^\{\}]*)(\= })([^\{\}\;]*)(\;)') + struct_members =3D KernRe(type_pattern + r'([^\{\};]+)(\{)([^\{\}]= *)(\})([^\{\}\;]*)(\;)') =20 # Extract struct/union definition members =3D None declaration_name =3D None decl_type =3D None =20 - r =3D Re(type_pattern + r'\s+(\w+)\s*' + definition_body) + r =3D KernRe(type_pattern + r'\s+(\w+)\s*' + definition_body) if r.search(proto): decl_type =3D r.group(1) declaration_name =3D r.group(2) members =3D r.group(3) else: - r =3D Re(r'typedef\s+' + type_pattern + r'\s*' + definition_bo= dy + r'\s*(\w+)\s*;') + r =3D KernRe(r'typedef\s+' + type_pattern + r'\s*' + definitio= n_body + r'\s*(\w+)\s*;') =20 if r.search(proto): decl_type =3D r.group(1) @@ -567,21 +567,21 @@ class KernelDoc: args_pattern =3D r'([^,)]+)' =20 sub_prefixes =3D [ - (Re(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', re.S | re.I), = ''), - (Re(r'\/\*\s*private:.*', re.S | re.I), ''), + (KernRe(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', re.S | re.= I), ''), + (KernRe(r'\/\*\s*private:.*', re.S | re.I), ''), =20 # Strip comments - (Re(r'\/\*.*?\*\/', re.S), ''), + (KernRe(r'\/\*.*?\*\/', re.S), ''), =20 # Strip attributes (attribute, ' '), - (Re(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), - (Re(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), - (Re(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), - (Re(r'\s*__packed\s*', re.S), ' '), - (Re(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), - (Re(r'\s*____cacheline_aligned_in_smp', re.S), ' '), - (Re(r'\s*____cacheline_aligned', re.S), ' '), + (KernRe(r'\s*__aligned\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__counted_by\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__counted_by_(le|be)\s*\([^;]*\)', re.S), ' '), + (KernRe(r'\s*__packed\s*', re.S), ' '), + (KernRe(r'\s*CRYPTO_MINALIGN_ATTR', re.S), ' '), + (KernRe(r'\s*____cacheline_aligned_in_smp', re.S), ' '), + (KernRe(r'\s*____cacheline_aligned', re.S), ' '), =20 # Unwrap struct_group macros based on this definition: # __struct_group(TAG, NAME, ATTRS, MEMBERS...) @@ -616,10 +616,10 @@ class KernelDoc: # matched. So, the implementation to drop STRUCT_GROUP() will = be # handled in separate. =20 - (Re(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP('), - (Re(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUCT_GR= OUP('), - (Re(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), r'st= ruct \1 \2; STRUCT_GROUP('), - (Re(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_GROUP= ('), + (KernRe(r'\bstruct_group\s*\(([^,]*,)', re.S), r'STRUCT_GROUP(= '), + (KernRe(r'\bstruct_group_attr\s*\(([^,]*,){2}', re.S), r'STRUC= T_GROUP('), + (KernRe(r'\bstruct_group_tagged\s*\(([^,]*),([^,]*),', re.S), = r'struct \1 \2; STRUCT_GROUP('), + (KernRe(r'\b__struct_group\s*\(([^,]*,){3}', re.S), r'STRUCT_G= ROUP('), =20 # Replace macros # @@ -628,15 +628,15 @@ class KernelDoc: # it is better to also move those to the NestedMatch logic, # to ensure that parenthesis will be properly matched. =20 - (Re(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re.S),= r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), - (Re(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), r'DEC= LARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), - (Re(r'DECLARE_BITMAP\s*\(' + args_pattern + r',\s*' + args_pat= tern + r'\)', re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), - (Re(r'DECLARE_HASHTABLE\s*\(' + args_pattern + r',\s*' + args_= pattern + r'\)', re.S), r'unsigned long \1[1 << ((\2) - 1)]'), - (Re(r'DECLARE_KFIFO\s*\(' + args_pattern + r',\s*' + args_patt= ern + r',\s*' + args_pattern + r'\)', re.S), r'\2 *\1'), - (Re(r'DECLARE_KFIFO_PTR\s*\(' + args_pattern + r',\s*' + args_= pattern + r'\)', re.S), r'\2 *\1'), - (Re(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + args_pattern + r',\s*'= + args_pattern + r'\)', re.S), r'\1 \2[]'), - (Re(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + args_pattern + r'\)', re.S= ), r'dma_addr_t \1'), - (Re(r'DEFINE_DMA_UNMAP_LEN\s*\(' + args_pattern + r'\)', re.S)= , r'__u32 \1'), + (KernRe(r'__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)', re= .S), r'DECLARE_BITMAP(\1, __ETHTOOL_LINK_MODE_MASK_NBITS)'), + (KernRe(r'DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)', re.S), r= 'DECLARE_BITMAP(\1, PHY_INTERFACE_MODE_MAX)'), + (KernRe(r'DECLARE_BITMAP\s*\(' + args_pattern + r',\s*' + args= _pattern + r'\)', re.S), r'unsigned long \1[BITS_TO_LONGS(\2)]'), + (KernRe(r'DECLARE_HASHTABLE\s*\(' + args_pattern + r',\s*' + a= rgs_pattern + r'\)', re.S), r'unsigned long \1[1 << ((\2) - 1)]'), + (KernRe(r'DECLARE_KFIFO\s*\(' + args_pattern + r',\s*' + args_= pattern + r',\s*' + args_pattern + r'\)', re.S), r'\2 *\1'), + (KernRe(r'DECLARE_KFIFO_PTR\s*\(' + args_pattern + r',\s*' + a= rgs_pattern + r'\)', re.S), r'\2 *\1'), + (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + args_pattern + r',= \s*' + args_pattern + r'\)', re.S), r'\1 \2[]'), + (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + args_pattern + r'\)', = re.S), r'dma_addr_t \1'), + (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + args_pattern + r'\)', r= e.S), r'__u32 \1'), ] =20 # Regexes here are guaranteed to have the end limiter matching @@ -689,8 +689,8 @@ class KernelDoc: s_id =3D s_id.strip() =20 newmember +=3D f"{maintype} {s_id}; " - s_id =3D Re(r'[:\[].*').sub('', s_id) - s_id =3D Re(r'^\s*\**(\S+)\s*').sub(r'\1', s_id) + s_id =3D KernRe(r'[:\[].*').sub('', s_id) + s_id =3D KernRe(r'^\s*\**(\S+)\s*').sub(r'\1', s_id) =20 for arg in content.split(';'): arg =3D arg.strip() @@ -698,7 +698,7 @@ class KernelDoc: if not arg: continue =20 - r =3D Re(r'^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)') + r =3D KernRe(r'^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)= ') if r.match(arg): # Pointer-to-function dtype =3D r.group(1) @@ -717,15 +717,15 @@ class KernelDoc: else: arg =3D arg.strip() # Handle bitmaps - arg =3D Re(r':\s*\d+\s*').sub('', arg) + arg =3D KernRe(r':\s*\d+\s*').sub('', arg) =20 # Handle arrays - arg =3D Re(r'\[.*\]').sub('', arg) + arg =3D KernRe(r'\[.*\]').sub('', arg) =20 # Handle multiple IDs - arg =3D Re(r'\s*,\s*').sub(',', arg) + arg =3D KernRe(r'\s*,\s*').sub(',', arg) =20 - r =3D Re(r'(.*)\s+([\S+,]+)') + r =3D KernRe(r'(.*)\s+([\S+,]+)') =20 if r.search(arg): dtype =3D r.group(1) @@ -735,7 +735,7 @@ class KernelDoc: continue =20 for name in names.split(','): - name =3D Re(r'^\s*\**(\S+)\s*').sub(r'\1',= name).strip() + name =3D KernRe(r'^\s*\**(\S+)\s*').sub(r'= \1', name).strip() =20 if not name: continue @@ -757,12 +757,12 @@ class KernelDoc: self.entry.sectcheck, self.entry.struct_actual) =20 # Adjust declaration for better display - declaration =3D Re(r'([\{;])').sub(r'\1\n', declaration) - declaration =3D Re(r'\}\s+;').sub('};', declaration) + declaration =3D KernRe(r'([\{;])').sub(r'\1\n', declaration) + declaration =3D KernRe(r'\}\s+;').sub('};', declaration) =20 # Better handle inlined enums while True: - r =3D Re(r'(enum\s+\{[^\}]+),([^\n])') + r =3D KernRe(r'(enum\s+\{[^\}]+),([^\n])') if not r.search(declaration): break =20 @@ -774,7 +774,7 @@ class KernelDoc: for clause in def_args: =20 clause =3D clause.strip() - clause =3D Re(r'\s+').sub(' ', clause, count=3D1) + clause =3D KernRe(r'\s+').sub(' ', clause, count=3D1) =20 if not clause: continue @@ -782,7 +782,7 @@ class KernelDoc: if '}' in clause and level > 1: level -=3D 1 =20 - if not Re(r'^\s*#').match(clause): + if not KernRe(r'^\s*#').match(clause): declaration +=3D "\t" * level =20 declaration +=3D "\t" + clause + "\n" @@ -807,24 +807,24 @@ class KernelDoc: """ =20 # Ignore members marked private - proto =3D Re(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', flags=3Dr= e.S).sub('', proto) - proto =3D Re(r'\/\*\s*private:.*}', flags=3Dre.S).sub('}', proto) + proto =3D KernRe(r'\/\*\s*private:.*?\/\*\s*public:.*?\*\/', flags= =3Dre.S).sub('', proto) + proto =3D KernRe(r'\/\*\s*private:.*}', flags=3Dre.S).sub('}', pro= to) =20 # Strip comments - proto =3D Re(r'\/\*.*?\*\/', flags=3Dre.S).sub('', proto) + proto =3D KernRe(r'\/\*.*?\*\/', flags=3Dre.S).sub('', proto) =20 # Strip #define macros inside enums - proto =3D Re(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags=3Dre= .S).sub('', proto) + proto =3D KernRe(r'#\s*((define|ifdef|if)\s+|endif)[^;]*;', flags= =3Dre.S).sub('', proto) =20 members =3D None declaration_name =3D None =20 - r =3D Re(r'typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;') + r =3D KernRe(r'typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;') if r.search(proto): declaration_name =3D r.group(2) members =3D r.group(1).rstrip() else: - r =3D Re(r'enum\s+(\w*)\s*\{(.*)\}') + r =3D KernRe(r'enum\s+(\w*)\s*\{(.*)\}') if r.match(proto): declaration_name =3D r.group(1) members =3D r.group(2).rstrip() @@ -847,12 +847,12 @@ class KernelDoc: =20 member_set =3D set() =20 - members =3D Re(r'\([^;]*?[\)]').sub('', members) + members =3D KernRe(r'\([^;]*?[\)]').sub('', members) =20 for arg in members.split(','): if not arg: continue - arg =3D Re(r'^\s*(\w+).*').sub(r'\1', arg) + arg =3D KernRe(r'^\s*(\w+).*').sub(r'\1', arg) self.entry.parameterlist.append(arg) if arg not in self.entry.parameterdescs: self.entry.parameterdescs[arg] =3D self.undescribed @@ -947,10 +947,10 @@ class KernelDoc: ] =20 for search, sub, flags in sub_prefixes: - prototype =3D Re(search, flags).sub(sub, prototype) + prototype =3D KernRe(search, flags).sub(sub, prototype) =20 # Macros are a special case, as they change the prototype format - new_proto =3D Re(r"^#\s*define\s+").sub("", prototype) + new_proto =3D KernRe(r"^#\s*define\s+").sub("", prototype) if new_proto !=3D prototype: is_define_proto =3D True prototype =3D new_proto @@ -987,7 +987,7 @@ class KernelDoc: found =3D False =20 if is_define_proto: - r =3D Re(r'^()(' + name + r')\s+') + r =3D KernRe(r'^()(' + name + r')\s+') =20 if r.search(prototype): return_type =3D '' @@ -1004,7 +1004,7 @@ class KernelDoc: ] =20 for p in patterns: - r =3D Re(p) + r =3D KernRe(p) =20 if r.match(prototype): =20 @@ -1071,11 +1071,11 @@ class KernelDoc: typedef_ident =3D r'\*?\s*(\w\S+)\s*' typedef_args =3D r'\s*\((.*)\);' =20 - typedef1 =3D Re(r'typedef' + typedef_type + r'\(' + typedef_ident = + r'\)' + typedef_args) - typedef2 =3D Re(r'typedef' + typedef_type + typedef_ident + typede= f_args) + typedef1 =3D KernRe(r'typedef' + typedef_type + r'\(' + typedef_id= ent + r'\)' + typedef_args) + typedef2 =3D KernRe(r'typedef' + typedef_type + typedef_ident + ty= pedef_args) =20 # Strip comments - proto =3D Re(r'/\*.*?\*/', flags=3Dre.S).sub('', proto) + proto =3D KernRe(r'/\*.*?\*/', flags=3Dre.S).sub('', proto) =20 # Parse function typedef prototypes for r in [typedef1, typedef2]: @@ -1109,12 +1109,12 @@ class KernelDoc: return =20 # Handle nested parentheses or brackets - r =3D Re(r'(\(*.\)\s*|\[*.\]\s*);$') + r =3D KernRe(r'(\(*.\)\s*|\[*.\]\s*);$') while r.search(proto): proto =3D r.sub('', proto) =20 # Parse simple typedefs - r =3D Re(r'typedef.*\s+(\w+)\s*;') + r =3D KernRe(r'typedef.*\s+(\w+)\s*;') if r.match(proto): declaration_name =3D r.group(1) =20 @@ -1195,12 +1195,12 @@ class KernelDoc: decl_end =3D r"(?:[-:].*)" # end of the name part =20 # test for pointer declaration type, foo * bar() - desc - r =3D Re(fr"^{decl_start}([\w\s]+?){parenthesis}?\s*{decl_end}= ?$") + r =3D KernRe(fr"^{decl_start}([\w\s]+?){parenthesis}?\s*{decl_= end}?$") if r.search(line): self.entry.identifier =3D r.group(1) =20 # Test for data declaration - r =3D Re(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)") + r =3D KernRe(r"^\s*\*?\s*(struct|union|enum|typedef)\b\s*(\w*)= ") if r.search(line): self.entry.decl_type =3D r.group(1) self.entry.identifier =3D r.group(2) @@ -1209,15 +1209,15 @@ class KernelDoc: # Look for foo() or static void foo() - description; # or misspelt identifier =20 - r1 =3D Re(fr"^{decl_start}{fn_type}(\w+)\s*{parenthesis}\s= *{decl_end}?$") - r2 =3D Re(fr"^{decl_start}{fn_type}(\w+[^-:]*){parenthesis= }\s*{decl_end}$") + r1 =3D KernRe(fr"^{decl_start}{fn_type}(\w+)\s*{parenthesi= s}\s*{decl_end}?$") + r2 =3D KernRe(fr"^{decl_start}{fn_type}(\w+[^-:]*){parenth= esis}\s*{decl_end}$") =20 for r in [r1, r2]: if r.search(line): self.entry.identifier =3D r.group(1) self.entry.decl_type =3D "function" =20 - r =3D Re(r"define\s+") + r =3D KernRe(r"define\s+") self.entry.identifier =3D r.sub("", self.entry.ide= ntifier) self.entry.is_kernel_comment =3D True break @@ -1230,12 +1230,12 @@ class KernelDoc: self.entry.section =3D self.section_default self.entry.new_start_line =3D ln + 1 =20 - r =3D Re("[-:](.*)") + r =3D KernRe("[-:](.*)") if r.search(line): # strip leading/trailing/multiple spaces self.entry.descr =3D r.group(1).strip(" ") =20 - r =3D Re(r"\s+") + r =3D KernRe(r"\s+") self.entry.descr =3D r.sub(" ", self.entry.descr) self.entry.declaration_purpose =3D self.entry.descr self.state =3D self.STATE_BODY_MAYBE @@ -1272,7 +1272,7 @@ class KernelDoc: """ =20 if self.state =3D=3D self.STATE_BODY_WITH_BLANK_LINE: - r =3D Re(r"\s*\*\s?\S") + r =3D KernRe(r"\s*\*\s?\S") if r.match(line): self.dump_section() self.entry.section =3D self.section_default @@ -1318,7 +1318,7 @@ class KernelDoc: self.dump_section() =20 # Look for doc_com + + doc_end: - r =3D Re(r'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') + r =3D KernRe(r'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') if r.match(line): self.emit_warning(ln, f"suspicious ending line: {line}") =20 @@ -1351,7 +1351,7 @@ class KernelDoc: self.entry.declaration_purpose =3D self.entry.declaration_= purpose.rstrip() self.entry.declaration_purpose +=3D " " + cont =20 - r =3D Re(r"\s+") + r =3D KernRe(r"\s+") self.entry.declaration_purpose =3D r.sub(' ', self.entry.declarat= ion_purpose) =20 @@ -1359,7 +1359,7 @@ class KernelDoc: if self.entry.section.startswith('@') or \ self.entry.section =3D=3D self.section_context: if self.entry.leading_space is None: - r =3D Re(r'^(\s+)') + r =3D KernRe(r'^(\s+)') if r.match(cont): self.entry.leading_space =3D len(r.group(1)) else: @@ -1436,13 +1436,13 @@ class KernelDoc: is_void =3D True =20 # Replace SYSCALL_DEFINE with correct return type & function name - proto =3D Re(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto) + proto =3D KernRe(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto) =20 - r =3D Re(r'long\s+(sys_.*?),') + r =3D KernRe(r'long\s+(sys_.*?),') if r.search(proto): - proto =3D Re(',').sub('(', proto, count=3D1) + proto =3D KernRe(',').sub('(', proto, count=3D1) elif is_void: - proto =3D Re(r'\)').sub('(void)', proto, count=3D1) + proto =3D KernRe(r'\)').sub('(void)', proto, count=3D1) =20 # Now delete all of the odd-numbered commas in the proto # so that argument types & names don't have a comma between them @@ -1469,22 +1469,22 @@ class KernelDoc: tracepointargs =3D None =20 # Match tracepoint name based on different patterns - r =3D Re(r'TRACE_EVENT\((.*?),') + r =3D KernRe(r'TRACE_EVENT\((.*?),') if r.search(proto): tracepointname =3D r.group(1) =20 - r =3D Re(r'DEFINE_SINGLE_EVENT\((.*?),') + r =3D KernRe(r'DEFINE_SINGLE_EVENT\((.*?),') if r.search(proto): tracepointname =3D r.group(1) =20 - r =3D Re(r'DEFINE_EVENT\((.*?),(.*?),') + r =3D KernRe(r'DEFINE_EVENT\((.*?),(.*?),') if r.search(proto): tracepointname =3D r.group(2) =20 if tracepointname: tracepointname =3D tracepointname.lstrip() =20 - r =3D Re(r'TP_PROTO\((.*?)\)') + r =3D KernRe(r'TP_PROTO\((.*?)\)') if r.search(proto): tracepointargs =3D r.group(1) =20 @@ -1501,43 +1501,43 @@ class KernelDoc: """Ancillary routine to process a function prototype""" =20 # strip C99-style comments to end of line - r =3D Re(r"\/\/.*$", re.S) + r =3D KernRe(r"\/\/.*$", re.S) line =3D r.sub('', line) =20 - if Re(r'\s*#\s*define').match(line): + if KernRe(r'\s*#\s*define').match(line): self.entry.prototype =3D line elif line.startswith('#'): # Strip other macros like #ifdef/#ifndef/#endif/... pass else: - r =3D Re(r'([^\{]*)') + r =3D KernRe(r'([^\{]*)') if r.match(line): self.entry.prototype +=3D r.group(1) + " " =20 - if '{' in line or ';' in line or Re(r'\s*#\s*define').match(line): + if '{' in line or ';' in line or KernRe(r'\s*#\s*define').match(li= ne): # strip comments - r =3D Re(r'/\*.*?\*/') + r =3D KernRe(r'/\*.*?\*/') self.entry.prototype =3D r.sub('', self.entry.prototype) =20 # strip newlines/cr's - r =3D Re(r'[\r\n]+') + r =3D KernRe(r'[\r\n]+') self.entry.prototype =3D r.sub(' ', self.entry.prototype) =20 # strip leading spaces - r =3D Re(r'^\s+') + r =3D KernRe(r'^\s+') self.entry.prototype =3D r.sub('', self.entry.prototype) =20 # Handle self.entry.prototypes for function pointers like: # int (*pcs_config)(struct foo) =20 - r =3D Re(r'^(\S+\s+)\(\s*\*(\S+)\)') + r =3D KernRe(r'^(\S+\s+)\(\s*\*(\S+)\)') self.entry.prototype =3D r.sub(r'\1\2', self.entry.prototype) =20 if 'SYSCALL_DEFINE' in self.entry.prototype: self.entry.prototype =3D self.syscall_munge(ln, self.entry.proto= type) =20 - r =3D Re(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT') + r =3D KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT') if r.search(self.entry.prototype): self.entry.prototype =3D self.tracepoint_munge(ln, self.entry.pr= ototype) @@ -1549,22 +1549,22 @@ class KernelDoc: """Ancillary routine to process a type""" =20 # Strip newlines/cr's. - line =3D Re(r'[\r\n]+', re.S).sub(' ', line) + line =3D KernRe(r'[\r\n]+', re.S).sub(' ', line) =20 # Strip leading spaces - line =3D Re(r'^\s+', re.S).sub('', line) + line =3D KernRe(r'^\s+', re.S).sub('', line) =20 # Strip trailing spaces - line =3D Re(r'\s+$', re.S).sub('', line) + line =3D KernRe(r'\s+$', re.S).sub('', line) =20 # Strip C99-style comments to the end of the line - line =3D Re(r"\/\/.*$", re.S).sub('', line) + line =3D KernRe(r"\/\/.*$", re.S).sub('', line) =20 # To distinguish preprocessor directive from regular declaration l= ater. if line.startswith('#'): line +=3D ";" =20 - r =3D Re(r'([^\{\};]*)([\{\};])(.*)') + r =3D KernRe(r'([^\{\};]*)([\{\};])(.*)') while True: if r.search(line): if self.entry.prototype: diff --git a/scripts/lib/kdoc/kdoc_re.py b/scripts/lib/kdoc/kdoc_re.py index d28485ff94d6..e81695b273bf 100755 --- a/scripts/lib/kdoc/kdoc_re.py +++ b/scripts/lib/kdoc/kdoc_re.py @@ -14,7 +14,7 @@ import re re_cache =3D {} =20 =20 -class Re: +class KernRe: """ Helper class to simplify regex declaration and usage, =20 @@ -59,7 +59,7 @@ class Re: Allows adding two regular expressions into one. """ =20 - return Re(str(self) + str(other), cache=3Dself.cache or other.cach= e, + return KernRe(str(self) + str(other), cache=3Dself.cache or other.= cache, flags=3Dself.regex.flags | other.regex.flags) =20 def match(self, string): --=20 2.49.0