From nobody Sun Sep 28 17:04:58 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1756380986; cv=none; d=zohomail.com; s=zohoarc; b=le+prSx6qS0sDyEKAtp1DY93Ct1cW01UYX17Q6zTrVMiUfX2KfuJEzBpxjPz2t62UrjzAclWGUQ+rVggN/iiDlNNAt/GFUXa6qfc03bs0kGhLvSIqzNnN71VcyBJUHKYLl1lkEKYbx/1lPO8IrQ6isguPu0SDnuWkPcq6VROmiU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756380986; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=WeDGo2dpz1/Hku7kdli1YSDp3jvOb+KDY3M+EWGKOZs=; b=VxZCsfbdaT7AKN0KIHTlV4udZ32OkS1ApdHLjbkhBlNbfhvXzRNyAjRPre84Usa3lwn0svTNhYaTYEAaOBSQXjhMWJZjdAK2qJrC/ZscWFvW9rEh6mH2zD6ujJk1f9ytc3Y6FwV0qZy8v0k2p5rK4igtuPcemOP04th8uG0fkUY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756380986365264.38747603141155; Thu, 28 Aug 2025 04:36:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1urauR-0003hG-RT; Thu, 28 Aug 2025 07:35:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1urauH-0003Zz-Dh for qemu-devel@nongnu.org; Thu, 28 Aug 2025 07:35:05 -0400 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1urauB-0005pl-MW for qemu-devel@nongnu.org; Thu, 28 Aug 2025 07:35:05 -0400 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-45b629c8035so4899185e9.3 for ; Thu, 28 Aug 2025 04:34:59 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45b79799c33sm28691015e9.5.2025.08.28.04.34.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Aug 2025 04:34:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1756380898; x=1756985698; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=WeDGo2dpz1/Hku7kdli1YSDp3jvOb+KDY3M+EWGKOZs=; b=yMt1AnPwn53C3W6D6Yb+ahguYEYRJa7LwnMMRQDy1uHbMAu4zRNCZw1OtpLf3vIfgJ 4AC4IcMV60g7Vsnr5BdJfpTAhdfSSi6/VIle6qlWsxCkXLSEssGAGvne4xxaipsyKgXG HGKHXE+Xhua91eK3uey6Xhum+bGF5WGPwfkg2v9ug+2plyNKRxaXh/aiaQfZQZKN1GXg BvyGRcj+pzSZxQVcm3Gmf7ZJ/+3jLLhaJ/Py44cYG9Rh/xAzRK8BE9LTnRgi8HjaepvE e+lc5VKwPqKJynvEThaWS7PqTVXZUlL9iqvTqOB+UCtSUdEfezdcI+Js/naEDzdCk1J5 WgaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756380898; x=1756985698; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WeDGo2dpz1/Hku7kdli1YSDp3jvOb+KDY3M+EWGKOZs=; b=krBa4isN7UAbidawNlGIKVfFjR/28brGm5vvPGy2MUHcaYdUZkyETbzp8XhsuRLB8R SOfZPVwdAWx2G1M/ii+SF0T+QuLRCb7mg5ID+piaRFEqZR/E+iK7yZa8S82xAaom2N3f Ilvv90II49obGjnAw6AXysTFDA6BDq6lEmaDgTS70jFF3yH+KJSudJOaUtOqmLROkLts 4wt4TAJIDGIByeBY+gjt2oT+NLDPDAHI6AF2Y9+HkMnN8D+jlF4Bu9+sVzqLchh3Yksa rJeWn1FvnN9rcUMX1WNlDDFfbsY1AeQNMKLUzeR1cRpKSc0oy1Sls6K4C2Ib7i0DDtcI BwRw== X-Gm-Message-State: AOJu0YzzvaEqnMT0aE5nvIJCaEwDx4NHyRDfIqq2bhHXo8+iJdtTrkyo CpP1k8GS0LLDYNBQzuoBDpfFLaIcJsM2vOLvPR1g5WQj5YIn/qxHQ3deEmjdA5OWCNiNWg4IA5q 9NMB+ X-Gm-Gg: ASbGncvE4LOWAQ6vOyJ8DS13ci6Jr04vhqWyfPm7VMwULLZIw9zAPOpo/zavpgNIpv3 kSOtkWLMFRs+1K+NMKCF2AAxWZi9azFvL2TN4PBN7I4i7jJBMWMMZqrlLsTIx6Fm9Wk116czsxh ncSQGSYF2y4deBVlbMPkKMAYwtG8HDkP2eACp13Ny5oVXxL1vDzO/AKos19/7hfQ6tqjV6/fTlI CVrzDN9k3+1vx++ZQYBh+f0otgpXtE0hkqVg4sEnEm53PyXlgYK2vCqnhyg+S2VwqtuCvOM10kk 2tEE8+amTGwhMwgRccOurBYxHBBc0zzLfSDGsKBbDoGyb0NfQYhMded2q0j3bzpdRbFr6C/TKbD pQLL0W8k7uvsXZ+nIpZ3FBpJedi9s X-Google-Smtp-Source: AGHT+IH0i5suXB7lkdFIy+Zdl7yFTDMpa2fLjzwtZlw5Mjuh73M2ilaR9iyR71rxdK6TE0QLG6KNEA== X-Received: by 2002:a05:600c:a46:b0:456:19be:5e8 with SMTP id 5b1f17b1804b1-45b517d459dmr197752615e9.20.1756380897133; Thu, 28 Aug 2025 04:34:57 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 22/32] scripts/kernel-doc: Delete the old Perl kernel-doc script Date: Thu, 28 Aug 2025 12:34:19 +0100 Message-ID: <20250828113430.3214314-23-peter.maydell@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250828113430.3214314-1-peter.maydell@linaro.org> References: <20250828113430.3214314-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1756380988727116600 Content-Type: text/plain; charset="utf-8" We can now delete the old Perl kernel-doc script. For posterity, this is a complete diff of the local changes that we were carrying between the kernel's Perl script as of kernel commit 72b97d0b911872ba (the last time we synced it) and our local copy: Reviewed-by: Mauro Carvalho Chehab Reviewed-by: Paolo Bonzini --- /tmp/kdoc 2025-08-14 10:42:47.620331939 +0100 +++ scripts/kernel-doc 2025-02-17 10:44:34.528421457 +0000 @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only use warnings; use strict; @@ -224,12 +224,12 @@ my $type_fp_param =3D '\@(\w+)\(\)'; # Special RST handling for func ptr = params my $type_fp_param2 =3D '\@(\w+->\S+)\(\)'; # Special RST handling for str= ucts with func ptr params my $type_env =3D '(\$\w+)'; -my $type_enum =3D '\&(enum\s*([_\w]+))'; -my $type_struct =3D '\&(struct\s*([_\w]+))'; -my $type_typedef =3D '\&(typedef\s*([_\w]+))'; -my $type_union =3D '\&(union\s*([_\w]+))'; -my $type_member =3D '\&([_\w]+)(\.|->)([_\w]+)'; -my $type_fallback =3D '\&([_\w]+)'; +my $type_enum =3D '#(enum\s*([_\w]+))'; +my $type_struct =3D '#(struct\s*([_\w]+))'; +my $type_typedef =3D '#(([A-Z][_\w]*))'; +my $type_union =3D '#(union\s*([_\w]+))'; +my $type_member =3D '#([_\w]+)(\.|->)([_\w]+)'; +my $type_fallback =3D '(?!)'; # this never matches my $type_member_func =3D $type_member . '\(\)'; # Output conversion substitutions. @@ -1745,6 +1745,9 @@ )+ \)\)\s+//x; + # Strip QEMU specific compiler annotations + $prototype =3D~ s/QEMU_[A-Z_]+ +//; + # Yes, this truly is vile. We are looking for: # 1. Return type (may be nothing if we're looking at a macro) # 2. Function name @@ -2057,7 +2060,7 @@ } elsif (/$doc_decl/o) { $identifier =3D $1; - if (/\s*([\w\s]+?)(\(\))?\s*-/) { + if (/\s*([\w\s]+?)(\s*-|:)/) { $identifier =3D $1; } @@ -2067,7 +2070,7 @@ $contents =3D ""; $section =3D $section_default; $new_start_line =3D $. + 1; - if (/-(.*)/) { + if (/[-:](.*)/) { # strip leading/trailing/multiple spaces $descr=3D $1; $descr =3D~ s/^\s*//; These changes correspond to: 06e2329636f license: Update deprecated SPDX tag GPL-2.0 to GPL-2.0-only (a bulk change which we won't bother to re-apply to this third-party script) b30df2751e5 scripts/kernel-doc: strip QEMU_ from function definitions 4cf41794411 docs: tweak kernel-doc for QEMU coding standards We have already applied the equivalent of these changes to the Python code in libs/kdoc/ in the preceding commits. Signed-off-by: Peter Maydell Reviewed-by: Mauro Carvalho Chehab Reviewed-by: Paolo Bonzini --- .editorconfig | 2 +- scripts/kernel-doc | 2441 -------------------------------------------- 2 files changed, 1 insertion(+), 2442 deletions(-) delete mode 100755 scripts/kernel-doc diff --git a/.editorconfig b/.editorconfig index a04cb9054cb..258d41ab485 100644 --- a/.editorconfig +++ b/.editorconfig @@ -55,7 +55,7 @@ indent_size =3D 4 emacs_mode =3D perl =20 # but user kernel "style" for imported scripts -[scripts/{kernel-doc,get_maintainer.pl,checkpatch.pl}] +[scripts/{get_maintainer.pl,checkpatch.pl}] indent_style =3D tab indent_size =3D 8 emacs_mode =3D perl diff --git a/scripts/kernel-doc b/scripts/kernel-doc deleted file mode 100755 index 117ec8fcd1f..00000000000 --- a/scripts/kernel-doc +++ /dev/null @@ -1,2441 +0,0 @@ -#!/usr/bin/env perl -# SPDX-License-Identifier: GPL-2.0-only - -use warnings; -use strict; - -## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ## -## Copyright (C) 2000, 1 Tim Waugh ## -## Copyright (C) 2001 Simon Huggins ## -## Copyright (C) 2005-2012 Randy Dunlap ## -## Copyright (C) 2012 Dan Luedtke ## -## ## -## #define enhancements by Armin Kuster ## -## Copyright (c) 2000 MontaVista Software, Inc. ## -## ## -## This software falls under the GNU General Public License. ## -## Please read the COPYING file for more information ## - -# 18/01/2001 - Cleanups -# Functions prototyped as foo(void) same as foo() -# Stop eval'ing where we don't need to. -# -- huggie@earth.li - -# 27/06/2001 - Allowed whitespace after initial "/**" and -# allowed comments before function declarations. -# -- Christian Kreibich - -# Still to do: -# - add perldoc documentation -# - Look more closely at some of the scarier bits :) - -# 26/05/2001 - Support for separate source and object trees. -# Return error code. -# Keith Owens - -# 23/09/2001 - Added support for typedefs, structs, enums and unions -# Support for Context section; can be terminated using empty = line -# Small fixes (like spaces vs. \s in regex) -# -- Tim Jansen - -# 25/07/2012 - Added support for HTML5 -# -- Dan Luedtke - -sub usage { - my $message =3D <<"EOF"; -Usage: $0 [OPTION ...] FILE ... - -Read C language source or header FILEs, extract embedded documentation com= ments, -and print formatted documentation to standard output. - -The documentation comments are identified by "/**" opening comment mark. S= ee -Documentation/doc-guide/kernel-doc.rst for the documentation comment synta= x. - -Output format selection (mutually exclusive): - -man Output troff manual page format. This is the default. - -rst Output reStructuredText format. - -none Do not output documentation, only warnings. - -Output format selection modifier (affects only ReST output): - - -sphinx-version Use the ReST C domain dialect compatible with an - specific Sphinx Version. - If not specified, kernel-doc will auto-detect using - the sphinx-build version found on PATH. - -Output selection (mutually exclusive): - -export Only output documentation for symbols that have been - exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() - in any input FILE or -export-file FILE. - -internal Only output documentation for symbols that have NOT been - exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() - in any input FILE or -export-file FILE. - -function NAME Only output documentation for the given function(s) - or DOC: section title(s). All other functions and DOC: - sections are ignored. May be specified multiple times. - -nosymbol NAME Exclude the specified symbols from the output - documentation. May be specified multiple times. - -Output selection modifiers: - -no-doc-sections Do not output DOC: sections. - -enable-lineno Enable output of #define LINENO lines. Only works = with - reStructuredText format. - -export-file FILE Specify an additional FILE in which to look for - EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be use= d with - -export or -internal. May be specified multiple ti= mes. - -Other parameters: - -v Verbose output, more warnings and other information. - -h Print this help. - -Werror Treat warnings as errors. - -EOF - print $message; - exit 1; -} - -# -# format of comments. -# In the following table, (...)? signifies optional structure. -# (...)* signifies 0 or more structure elements -# /** -# * function_name(:)? (- short description)? -# (* @parameterx: (description of parameter x)?)* -# (* a blank line)? -# * (Description:)? (Description of function)? -# * (section header: (section description)? )* -# (*)?*/ -# -# So .. the trivial example would be: -# -# /** -# * my_function -# */ -# -# If the Description: header tag is omitted, then there must be a blank li= ne -# after the last parameter specification. -# e.g. -# /** -# * my_function - does my stuff -# * @my_arg: its mine damnit -# * -# * Does my stuff explained. -# */ -# -# or, could also use: -# /** -# * my_function - does my stuff -# * @my_arg: its mine damnit -# * Description: Does my stuff explained. -# */ -# etc. -# -# Besides functions you can also write documentation for structs, unions, -# enums and typedefs. Instead of the function name you must write the name -# of the declaration; the struct/union/enum/typedef must always precede -# the name. Nesting of declarations is not supported. -# Use the argument mechanism to document members or constants. -# e.g. -# /** -# * struct my_struct - short description -# * @a: first member -# * @b: second member -# * -# * Longer description -# */ -# struct my_struct { -# int a; -# int b; -# /* private: */ -# int c; -# }; -# -# All descriptions can be multiline, except the short function description. -# -# For really longs structs, you can also describe arguments inside the -# body of the struct. -# eg. -# /** -# * struct my_struct - short description -# * @a: first member -# * @b: second member -# * -# * Longer description -# */ -# struct my_struct { -# int a; -# int b; -# /** -# * @c: This is longer description of C -# * -# * You can use paragraphs to describe arguments -# * using this method. -# */ -# int c; -# }; -# -# This should be use only for struct/enum members. -# -# You can also add additional sections. When documenting kernel functions = you -# should document the "Context:" of the function, e.g. whether the functio= ns -# can be called form interrupts. Unlike other sections you can end it with= an -# empty line. -# A non-void function should have a "Return:" section describing the return -# value(s). -# Example-sections should contain the string EXAMPLE so that they are mark= ed -# appropriately in DocBook. -# -# Example: -# /** -# * user_function - function that can only be called in user context -# * @a: some argument -# * Context: !in_interrupt() -# * -# * Some description -# * Example: -# * user_function(22); -# */ -# ... -# -# -# All descriptive text is further processed, scanning for the following sp= ecial -# patterns, which are highlighted appropriately. -# -# 'funcname()' - function -# '$ENVVAR' - environmental variable -# '&struct_name' - name of a structure (up to two words including 'struct') -# '&struct_name.member' - name of a structure member -# '@parameter' - name of a parameter -# '%CONST' - name of a constant. -# '``LITERAL``' - literal string without any spaces on it. - -## init lots of data - -my $errors =3D 0; -my $warnings =3D 0; -my $anon_struct_union =3D 0; - -# match expressions used to find embedded type information -my $type_constant =3D '\b``([^\`]+)``\b'; -my $type_constant2 =3D '\%([-_\w]+)'; -my $type_func =3D '(\w+)\(\)'; -my $type_param =3D '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; -my $type_param_ref =3D '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; -my $type_fp_param =3D '\@(\w+)\(\)'; # Special RST handling for func ptr = params -my $type_fp_param2 =3D '\@(\w+->\S+)\(\)'; # Special RST handling for str= ucts with func ptr params -my $type_env =3D '(\$\w+)'; -my $type_enum =3D '#(enum\s*([_\w]+))'; -my $type_struct =3D '#(struct\s*([_\w]+))'; -my $type_typedef =3D '#(([A-Z][_\w]*))'; -my $type_union =3D '#(union\s*([_\w]+))'; -my $type_member =3D '#([_\w]+)(\.|->)([_\w]+)'; -my $type_fallback =3D '(?!)'; # this never matches -my $type_member_func =3D $type_member . '\(\)'; - -# Output conversion substitutions. -# One for each output format - -# these are pretty rough -my @highlights_man =3D ( - [$type_constant, "\$1"], - [$type_constant2, "\$1"], - [$type_func, "\\\\fB\$1\\\\fP"], - [$type_enum, "\\\\fI\$1\\\\fP"], - [$type_struct, "\\\\fI\$1\\\\fP"], - [$type_typedef, "\\\\fI\$1\\\\fP"], - [$type_union, "\\\\fI\$1\\\\fP"], - [$type_param, "\\\\fI\$1\\\\fP"], - [$type_param_ref, "\\\\fI\$1\$2\\\\fP"], - [$type_member, "\\\\fI\$1\$2\$3\\\\fP"], - [$type_fallback, "\\\\fI\$1\\\\fP"] - ); -my $blankline_man =3D ""; - -# rst-mode -my @highlights_rst =3D ( - [$type_constant, "``\$1``"], - [$type_constant2, "``\$1``"], - # Note: need to escape () to avoid func matching la= ter - [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\= \\\) <\$1>`"], - [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"], - [$type_fp_param, "**\$1\\\\(\\\\)**"], - [$type_fp_param2, "**\$1\\\\(\\\\)**"], - [$type_func, "\$1()"], - [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"], - [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"], - [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"], - [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"], - # in rst this can refer to any type - [$type_fallback, "\\:c\\:type\\:`\$1`"], - [$type_param_ref, "**\$1\$2**"] - ); -my $blankline_rst =3D "\n"; - -# read arguments -if ($#ARGV =3D=3D -1) { - usage(); -} - -my $kernelversion; -my ($sphinx_major, $sphinx_minor, $sphinx_patch); - -my $dohighlight =3D ""; - -my $verbose =3D 0; -my $Werror =3D 0; -my $output_mode =3D "rst"; -my $output_preformatted =3D 0; -my $no_doc_sections =3D 0; -my $enable_lineno =3D 0; -my @highlights =3D @highlights_rst; -my $blankline =3D $blankline_rst; -my $modulename =3D "Kernel API"; - -use constant { - OUTPUT_ALL =3D> 0, # output all symbols and doc sections - OUTPUT_INCLUDE =3D> 1, # output only specified symbols - OUTPUT_EXPORTED =3D> 2, # output exported symbols - OUTPUT_INTERNAL =3D> 3, # output non-exported symbols -}; -my $output_selection =3D OUTPUT_ALL; -my $show_not_found =3D 0; # No longer used - -my @export_file_list; - -my @build_time; -if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && - (my $seconds =3D `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '= ') { - @build_time =3D gmtime($seconds); -} else { - @build_time =3D localtime; -} - -my $man_date =3D ('January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', - 'November', 'December')[$build_time[4]] . - " " . ($build_time[5]+1900); - -# Essentially these are globals. -# They probably want to be tidied up, made more localised or something. -# CAVEAT EMPTOR! Some of the others I localised may not want to be, which -# could cause "use of undefined value" or other bugs. -my ($function, %function_table, %parametertypes, $declaration_purpose); -my %nosymbol_table =3D (); -my $declaration_start_line; -my ($type, $declaration_name, $return_type); -my ($newsection, $newcontents, $prototype, $brcount, %source_map); - -if (defined($ENV{'KBUILD_VERBOSE'})) { - $verbose =3D "$ENV{'KBUILD_VERBOSE'}"; -} - -if (defined($ENV{'KDOC_WERROR'})) { - $Werror =3D "$ENV{'KDOC_WERROR'}"; -} - -if (defined($ENV{'KCFLAGS'})) { - my $kcflags =3D "$ENV{'KCFLAGS'}"; - - if ($kcflags =3D~ /Werror/) { - $Werror =3D 1; - } -} - -# Generated docbook code is inserted in a template at a point where -# docbook v3.1 requires a non-zero sequence of RefEntry's; see: -# https://www.oasis-open.org/docbook/documentation/reference/html/refentry= .html -# We keep track of number of generated entries and generate a dummy -# if needs be to ensure the expanded template can be postprocessed -# into html. -my $section_counter =3D 0; - -my $lineprefix=3D""; - -# Parser states -use constant { - STATE_NORMAL =3D> 0, # normal code - STATE_NAME =3D> 1, # looking for function name - STATE_BODY_MAYBE =3D> 2, # body - or maybe more description - STATE_BODY =3D> 3, # the body of the comment - STATE_BODY_WITH_BLANK_LINE =3D> 4, # the body, which has a blank line - STATE_PROTO =3D> 5, # scanning prototype - STATE_DOCBLOCK =3D> 6, # documentation block - STATE_INLINE =3D> 7, # gathering doc outside main block -}; -my $state; -my $in_doc_sect; -my $leading_space; - -# Inline documentation state -use constant { - STATE_INLINE_NA =3D> 0, # not applicable ($state !=3D STATE_INLINE) - STATE_INLINE_NAME =3D> 1, # looking for member name (@foo:) - STATE_INLINE_TEXT =3D> 2, # looking for member documentation - STATE_INLINE_END =3D> 3, # done - STATE_INLINE_ERROR =3D> 4, # error - Comment without header was found. - # Spit a warning as it's not - # proper kernel-doc and ignore the rest. -}; -my $inline_doc_state; - -#declaration types: can be -# 'function', 'struct', 'union', 'enum', 'typedef' -my $decl_type; - -my $doc_start =3D '^/\*\*\s*$'; # Allow whitespace at end of comment start. -my $doc_end =3D '\*/'; -my $doc_com =3D '\s*\*\s*'; -my $doc_com_body =3D '\s*\* ?'; -my $doc_decl =3D $doc_com . '(\w+)'; -# @params and a strictly limited set of supported section names -my $doc_sect =3D $doc_com . - '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\= s*:(.*)'; -my $doc_content =3D $doc_com_body . '(.*)'; -my $doc_block =3D $doc_com . 'DOC:\s*(.*)?'; -my $doc_inline_start =3D '^\s*/\*\*\s*$'; -my $doc_inline_sect =3D '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)'; -my $doc_inline_end =3D '^\s*\*/\s*$'; -my $doc_inline_oneline =3D '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$'; -my $export_symbol =3D '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; - -my %parameterdescs; -my %parameterdesc_start_lines; -my @parameterlist; -my %sections; -my @sectionlist; -my %section_start_lines; -my $sectcheck; -my $struct_actual; - -my $contents =3D ""; -my $new_start_line =3D 0; - -# the canonical section names. see also $doc_sect above. -my $section_default =3D "Description"; # default section -my $section_intro =3D "Introduction"; -my $section =3D $section_default; -my $section_context =3D "Context"; -my $section_return =3D "Return"; - -my $undescribed =3D "-- undescribed --"; - -reset_state(); - -while ($ARGV[0] =3D~ m/^--?(.*)/) { - my $cmd =3D $1; - shift @ARGV; - if ($cmd eq "man") { - $output_mode =3D "man"; - @highlights =3D @highlights_man; - $blankline =3D $blankline_man; - } elsif ($cmd eq "rst") { - $output_mode =3D "rst"; - @highlights =3D @highlights_rst; - $blankline =3D $blankline_rst; - } elsif ($cmd eq "none") { - $output_mode =3D "none"; - } elsif ($cmd eq "module") { # not needed for XML, inherits from calli= ng document - $modulename =3D shift @ARGV; - } elsif ($cmd eq "function") { # to only output specific functions - $output_selection =3D OUTPUT_INCLUDE; - $function =3D shift @ARGV; - $function_table{$function} =3D 1; - } elsif ($cmd eq "nosymbol") { # Exclude specific symbols - my $symbol =3D shift @ARGV; - $nosymbol_table{$symbol} =3D 1; - } elsif ($cmd eq "export") { # only exported symbols - $output_selection =3D OUTPUT_EXPORTED; - %function_table =3D (); - } elsif ($cmd eq "internal") { # only non-exported symbols - $output_selection =3D OUTPUT_INTERNAL; - %function_table =3D (); - } elsif ($cmd eq "export-file") { - my $file =3D shift @ARGV; - push(@export_file_list, $file); - } elsif ($cmd eq "v") { - $verbose =3D 1; - } elsif ($cmd eq "Werror") { - $Werror =3D 1; - } elsif (($cmd eq "h") || ($cmd eq "help")) { - usage(); - } elsif ($cmd eq 'no-doc-sections') { - $no_doc_sections =3D 1; - } elsif ($cmd eq 'enable-lineno') { - $enable_lineno =3D 1; - } elsif ($cmd eq 'show-not-found') { - $show_not_found =3D 1; # A no-op but don't fail - } elsif ($cmd eq "sphinx-version") { - my $ver_string =3D shift @ARGV; - if ($ver_string =3D~ m/^(\d+)(\.\d+)?(\.\d+)?/) { - $sphinx_major =3D $1; - if (defined($2)) { - $sphinx_minor =3D substr($2,1); - } else { - $sphinx_minor =3D 0; - } - if (defined($3)) { - $sphinx_patch =3D substr($3,1) - } else { - $sphinx_patch =3D 0; - } - } else { - die "Sphinx version should either major.minor or major.minor.patch fo= rmat\n"; - } - } else { - # Unknown argument - usage(); - } -} - -# continue execution near EOF; - -# The C domain dialect changed on Sphinx 3. So, we need to check the -# version in order to produce the right tags. -sub findprog($) -{ - foreach(split(/:/, $ENV{PATH})) { - return "$_/$_[0]" if(-x "$_/$_[0]"); - } -} - -sub get_sphinx_version() -{ - my $ver; - - my $cmd =3D "sphinx-build"; - if (!findprog($cmd)) { - my $cmd =3D "sphinx-build3"; - if (!findprog($cmd)) { - $sphinx_major =3D 1; - $sphinx_minor =3D 2; - $sphinx_patch =3D 0; - printf STDERR "Warning: Sphinx version not found. Using default (Sphinx= version %d.%d.%d)\n", - $sphinx_major, $sphinx_minor, $sphinx_patch; - return; - } - } - - open IN, "$cmd --version 2>&1 |"; - while () { - if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { - $sphinx_major =3D $1; - $sphinx_minor =3D $2; - $sphinx_patch =3D $3; - last; - } - # Sphinx 1.2.x uses a different format - if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { - $sphinx_major =3D $1; - $sphinx_minor =3D $2; - $sphinx_patch =3D $3; - last; - } - } - close IN; -} - -# get kernel version from env -sub get_kernel_version() { - my $version =3D 'unknown kernel version'; - - if (defined($ENV{'KERNELVERSION'})) { - $version =3D $ENV{'KERNELVERSION'}; - } - return $version; -} - -# -sub print_lineno { - my $lineno =3D shift; - if ($enable_lineno && defined($lineno)) { - print "#define LINENO " . $lineno . "\n"; - } -} -## -# dumps section contents to arrays/hashes intended for that purpose. -# -sub dump_section { - my $file =3D shift; - my $name =3D shift; - my $contents =3D join "\n", @_; - - if ($name =3D~ m/$type_param/) { - $name =3D $1; - $parameterdescs{$name} =3D $contents; - $sectcheck =3D $sectcheck . $name . " "; - $parameterdesc_start_lines{$name} =3D $new_start_line; - $new_start_line =3D 0; - } elsif ($name eq "@\.\.\.") { - $name =3D "..."; - $parameterdescs{$name} =3D $contents; - $sectcheck =3D $sectcheck . $name . " "; - $parameterdesc_start_lines{$name} =3D $new_start_line; - $new_start_line =3D 0; - } else { - if (defined($sections{$name}) && ($sections{$name} ne "")) { - # Only warn on user specified duplicate section names. - if ($name ne $section_default) { - print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; - ++$warnings; - } - $sections{$name} .=3D $contents; - } else { - $sections{$name} =3D $contents; - push @sectionlist, $name; - $section_start_lines{$name} =3D $new_start_line; - $new_start_line =3D 0; - } - } -} - -## -# dump DOC: section after checking that it should go out -# -sub dump_doc_section { - my $file =3D shift; - my $name =3D shift; - my $contents =3D join "\n", @_; - - if ($no_doc_sections) { - return; - } - - return if (defined($nosymbol_table{$name})); - - if (($output_selection =3D=3D OUTPUT_ALL) || - (($output_selection =3D=3D OUTPUT_INCLUDE) && - defined($function_table{$name}))) - { - dump_section($file, $name, $contents); - output_blockhead({'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'module' =3D> $modulename, - 'content-only' =3D> ($output_selection !=3D OUTPUT_ALL), }); - } -} - -## -# output function -# -# parameterdescs, a hash. -# function =3D> "function name" -# parameterlist =3D> @list of parameters -# parameterdescs =3D> %parameter descriptions -# sectionlist =3D> @list of sections -# sections =3D> %section descriptions -# - -sub output_highlight { - my $contents =3D join "\n",@_; - my $line; - -# DEBUG -# if (!defined $contents) { -# use Carp; -# confess "output_highlight got called with no args?\n"; -# } - -# print STDERR "contents b4:$contents\n"; - eval $dohighlight; - die $@ if $@; -# print STDERR "contents af:$contents\n"; - - foreach $line (split "\n", $contents) { - if (! $output_preformatted) { - $line =3D~ s/^\s*//; - } - if ($line eq ""){ - if (! $output_preformatted) { - print $lineprefix, $blankline; - } - } else { - if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { - print "\\&$line"; - } else { - print $lineprefix, $line; - } - } - print "\n"; - } -} - -## -# output function in man -sub output_function_man(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - my $count; - - print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\"= \"Kernel Hacker's Manual\" LINUX\n"; - - print ".SH NAME\n"; - print $args{'function'} . " \\- " . $args{'purpose'} . "\n"; - - print ".SH SYNOPSIS\n"; - if ($args{'functiontype'} ne "") { - print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n"; - } else { - print ".B \"" . $args{'function'} . "\n"; - } - $count =3D 0; - my $parenth =3D "("; - my $post =3D ","; - foreach my $parameter (@{$args{'parameterlist'}}) { - if ($count =3D=3D $#{$args{'parameterlist'}}) { - $post =3D ");"; - } - $type =3D $args{'parametertypes'}{$parameter}; - if ($type =3D~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { - # pointer-to-function - print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post = . "\"\n"; - } else { - $type =3D~ s/([^\*])$/$1 /; - print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n"; - } - $count++; - $parenth =3D ""; - } - - print ".SH ARGUMENTS\n"; - foreach $parameter (@{$args{'parameterlist'}}) { - my $parameter_name =3D $parameter; - $parameter_name =3D~ s/\[.*//; - - print ".IP \"" . $parameter . "\" 12\n"; - output_highlight($args{'parameterdescs'}{$parameter_name}); - } - foreach $section (@{$args{'sectionlist'}}) { - print ".SH \"", uc $section, "\"\n"; - output_highlight($args{'sections'}{$section}); - } -} - -## -# output enum in man -sub output_enum_man(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - my $count; - - print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" = \"API Manual\" LINUX\n"; - - print ".SH NAME\n"; - print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n"; - - print ".SH SYNOPSIS\n"; - print "enum " . $args{'enum'} . " {\n"; - $count =3D 0; - foreach my $parameter (@{$args{'parameterlist'}}) { - print ".br\n.BI \" $parameter\"\n"; - if ($count =3D=3D $#{$args{'parameterlist'}}) { - print "\n};\n"; - last; - } - else { - print ", \n.br\n"; - } - $count++; - } - - print ".SH Constants\n"; - foreach $parameter (@{$args{'parameterlist'}}) { - my $parameter_name =3D $parameter; - $parameter_name =3D~ s/\[.*//; - - print ".IP \"" . $parameter . "\" 12\n"; - output_highlight($args{'parameterdescs'}{$parameter_name}); - } - foreach $section (@{$args{'sectionlist'}}) { - print ".SH \"$section\"\n"; - output_highlight($args{'sections'}{$section}); - } -} - -## -# output struct in man -sub output_struct_man(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - - print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'st= ruct'} . "\" \"$man_date\" \"API Manual\" LINUX\n"; - - print ".SH NAME\n"; - print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose= '} . "\n"; - - my $declaration =3D $args{'definition'}; - $declaration =3D~ s/\t/ /g; - $declaration =3D~ s/\n/"\n.br\n.BI \"/g; - print ".SH SYNOPSIS\n"; - print $args{'type'} . " " . $args{'struct'} . " {\n.br\n"; - print ".BI \"$declaration\n};\n.br\n\n"; - - print ".SH Members\n"; - foreach $parameter (@{$args{'parameterlist'}}) { - ($parameter =3D~ /^#/) && next; - - my $parameter_name =3D $parameter; - $parameter_name =3D~ s/\[.*//; - - ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; - print ".IP \"" . $parameter . "\" 12\n"; - output_highlight($args{'parameterdescs'}{$parameter_name}); - } - foreach $section (@{$args{'sectionlist'}}) { - print ".SH \"$section\"\n"; - output_highlight($args{'sections'}{$section}); - } -} - -## -# output typedef in man -sub output_typedef_man(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - - print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"= API Manual\" LINUX\n"; - - print ".SH NAME\n"; - print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n= "; - - foreach $section (@{$args{'sectionlist'}}) { - print ".SH \"$section\"\n"; - output_highlight($args{'sections'}{$section}); - } -} - -sub output_blockhead_man(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - my $count; - - print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"A= PI Manual\" LINUX\n"; - - foreach $section (@{$args{'sectionlist'}}) { - print ".SH \"$section\"\n"; - output_highlight($args{'sections'}{$section}); - } -} - -## -# output in restructured text -# - -# -# This could use some work; it's used to output the DOC: sections, and -# starts by putting out the name of the doc section itself, but that tends -# to duplicate a header already in the template file. -# -sub output_blockhead_rst(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - - foreach $section (@{$args{'sectionlist'}}) { - next if (defined($nosymbol_table{$section})); - - if ($output_selection !=3D OUTPUT_INCLUDE) { - print "**$section**\n\n"; - } - print_lineno($section_start_lines{$section}); - output_highlight_rst($args{'sections'}{$section}); - print "\n"; - } -} - -# -# Apply the RST highlights to a sub-block of text. -# -sub highlight_block($) { - # The dohighlight kludge requires the text be called $contents - my $contents =3D shift; - eval $dohighlight; - die $@ if $@; - return $contents; -} - -# -# Regexes used only here. -# -my $sphinx_literal =3D '^[^.].*::$'; -my $sphinx_cblock =3D '^\.\.\ +code-block::'; - -sub output_highlight_rst { - my $input =3D join "\n",@_; - my $output =3D ""; - my $line; - my $in_literal =3D 0; - my $litprefix; - my $block =3D ""; - - foreach $line (split "\n",$input) { - # - # If we're in a literal block, see if we should drop out - # of it. Otherwise pass the line straight through unmunged. - # - if ($in_literal) { - if (! ($line =3D~ /^\s*$/)) { - # - # If this is the first non-blank line in a literal - # block we need to figure out what the proper indent is. - # - if ($litprefix eq "") { - $line =3D~ /^(\s*)/; - $litprefix =3D '^' . $1; - $output .=3D $line . "\n"; - } elsif (! ($line =3D~ /$litprefix/)) { - $in_literal =3D 0; - } else { - $output .=3D $line . "\n"; - } - } else { - $output .=3D $line . "\n"; - } - } - # - # Not in a literal block (or just dropped out) - # - if (! $in_literal) { - $block .=3D $line . "\n"; - if (($line =3D~ /$sphinx_literal/) || ($line =3D~ /$sphinx_cblock/)) { - $in_literal =3D 1; - $litprefix =3D ""; - $output .=3D highlight_block($block); - $block =3D "" - } - } - } - - if ($block) { - $output .=3D highlight_block($block); - } - foreach $line (split "\n", $output) { - print $lineprefix . $line . "\n"; - } -} - -sub output_function_rst(%) { - my %args =3D %{$_[0]}; - my ($parameter, $section); - my $oldprefix =3D $lineprefix; - my $start =3D ""; - my $is_macro =3D 0; - - if ($sphinx_major < 3) { - if ($args{'typedef'}) { - print ".. c:type:: ". $args{'function'} . "\n\n"; - print_lineno($declaration_start_line); - print " **Typedef**: "; - $lineprefix =3D ""; - output_highlight_rst($args{'purpose'}); - $start =3D "\n\n**Syntax**\n\n ``"; - $is_macro =3D 1; - } else { - print ".. c:function:: "; - } - } else { - if ($args{'typedef'} || $args{'functiontype'} eq "") { - $is_macro =3D 1; - print ".. c:macro:: ". $args{'function'} . "\n\n"; - } else { - print ".. c:function:: "; - } - - if ($args{'typedef'}) { - print_lineno($declaration_start_line); - print " **Typedef**: "; - $lineprefix =3D ""; - output_highlight_rst($args{'purpose'}); - $start =3D "\n\n**Syntax**\n\n ``"; - } else { - print "``" if ($is_macro); - } - } - if ($args{'functiontype'} ne "") { - $start .=3D $args{'functiontype'} . " " . $args{'function'} . " ("; - } else { - $start .=3D $args{'function'} . " ("; - } - print $start; - - my $count =3D 0; - foreach my $parameter (@{$args{'parameterlist'}}) { - if ($count ne 0) { - print ", "; - } - $count++; - $type =3D $args{'parametertypes'}{$parameter}; - - if ($type =3D~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { - # pointer-to-function - print $1 . $parameter . ") (" . $2 . ")"; - } else { - print $type; - } - } - if ($is_macro) { - print ")``\n\n"; - } else { - print ")\n\n"; - } - if (!$args{'typedef'}) { - print_lineno($declaration_start_line); - $lineprefix =3D " "; - output_highlight_rst($args{'purpose'}); - print "\n"; - } - - print "**Parameters**\n\n"; - $lineprefix =3D " "; - foreach $parameter (@{$args{'parameterlist'}}) { - my $parameter_name =3D $parameter; - $parameter_name =3D~ s/\[.*//; - $type =3D $args{'parametertypes'}{$parameter}; - - if ($type ne "") { - print "``$type``\n"; - } else { - print "``$parameter``\n"; - } - - print_lineno($parameterdesc_start_lines{$parameter_name}); - - if (defined($args{'parameterdescs'}{$parameter_name}) && - $args{'parameterdescs'}{$parameter_name} ne $undescribed) { - output_highlight_rst($args{'parameterdescs'}{$parameter_name}); - } else { - print " *undescribed*\n"; - } - print "\n"; - } - - $lineprefix =3D $oldprefix; - output_section_rst(@_); -} - -sub output_section_rst(%) { - my %args =3D %{$_[0]}; - my $section; - my $oldprefix =3D $lineprefix; - $lineprefix =3D ""; - - foreach $section (@{$args{'sectionlist'}}) { - print "**$section**\n\n"; - print_lineno($section_start_lines{$section}); - output_highlight_rst($args{'sections'}{$section}); - print "\n"; - } - print "\n"; - $lineprefix =3D $oldprefix; -} - -sub output_enum_rst(%) { - my %args =3D %{$_[0]}; - my ($parameter); - my $oldprefix =3D $lineprefix; - my $count; - - if ($sphinx_major < 3) { - my $name =3D "enum " . $args{'enum'}; - print "\n\n.. c:type:: " . $name . "\n\n"; - } else { - my $name =3D $args{'enum'}; - print "\n\n.. c:enum:: " . $name . "\n\n"; - } - print_lineno($declaration_start_line); - $lineprefix =3D " "; - output_highlight_rst($args{'purpose'}); - print "\n"; - - print "**Constants**\n\n"; - $lineprefix =3D " "; - foreach $parameter (@{$args{'parameterlist'}}) { - print "``$parameter``\n"; - if ($args{'parameterdescs'}{$parameter} ne $undescribed) { - output_highlight_rst($args{'parameterdescs'}{$parameter}); - } else { - print " *undescribed*\n"; - } - print "\n"; - } - - $lineprefix =3D $oldprefix; - output_section_rst(@_); -} - -sub output_typedef_rst(%) { - my %args =3D %{$_[0]}; - my ($parameter); - my $oldprefix =3D $lineprefix; - my $name; - - if ($sphinx_major < 3) { - $name =3D "typedef " . $args{'typedef'}; - } else { - $name =3D $args{'typedef'}; - } - print "\n\n.. c:type:: " . $name . "\n\n"; - print_lineno($declaration_start_line); - $lineprefix =3D " "; - output_highlight_rst($args{'purpose'}); - print "\n"; - - $lineprefix =3D $oldprefix; - output_section_rst(@_); -} - -sub output_struct_rst(%) { - my %args =3D %{$_[0]}; - my ($parameter); - my $oldprefix =3D $lineprefix; - - if ($sphinx_major < 3) { - my $name =3D $args{'type'} . " " . $args{'struct'}; - print "\n\n.. c:type:: " . $name . "\n\n"; - } else { - my $name =3D $args{'struct'}; - if ($args{'type'} eq 'union') { - print "\n\n.. c:union:: " . $name . "\n\n"; - } else { - print "\n\n.. c:struct:: " . $name . "\n\n"; - } - } - print_lineno($declaration_start_line); - $lineprefix =3D " "; - output_highlight_rst($args{'purpose'}); - print "\n"; - - print "**Definition**\n\n"; - print "::\n\n"; - my $declaration =3D $args{'definition'}; - $declaration =3D~ s/\t/ /g; - print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration= };\n\n"; - - print "**Members**\n\n"; - $lineprefix =3D " "; - foreach $parameter (@{$args{'parameterlist'}}) { - ($parameter =3D~ /^#/) && next; - - my $parameter_name =3D $parameter; - $parameter_name =3D~ s/\[.*//; - - ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; - $type =3D $args{'parametertypes'}{$parameter}; - print_lineno($parameterdesc_start_lines{$parameter_name}); - print "``" . $parameter . "``\n"; - output_highlight_rst($args{'parameterdescs'}{$parameter_name}); - print "\n"; - } - print "\n"; - - $lineprefix =3D $oldprefix; - output_section_rst(@_); -} - -## none mode output functions - -sub output_function_none(%) { -} - -sub output_enum_none(%) { -} - -sub output_typedef_none(%) { -} - -sub output_struct_none(%) { -} - -sub output_blockhead_none(%) { -} - -## -# generic output function for all types (function, struct/union, typedef, = enum); -# calls the generated, variable output_ function name based on -# functype and output_mode -sub output_declaration { - no strict 'refs'; - my $name =3D shift; - my $functype =3D shift; - my $func =3D "output_${functype}_$output_mode"; - - return if (defined($nosymbol_table{$name})); - - if (($output_selection =3D=3D OUTPUT_ALL) || - (($output_selection =3D=3D OUTPUT_INCLUDE || - $output_selection =3D=3D OUTPUT_EXPORTED) && - defined($function_table{$name})) || - ($output_selection =3D=3D OUTPUT_INTERNAL && - !($functype eq "function" && defined($function_table{$name})))) - { - &$func(@_); - $section_counter++; - } -} - -## -# generic output function - calls the right one based on current output mo= de. -sub output_blockhead { - no strict 'refs'; - my $func =3D "output_blockhead_" . $output_mode; - &$func(@_); - $section_counter++; -} - -## -# takes a declaration (struct, union, enum, typedef) and -# invokes the right handler. NOT called for functions. -sub dump_declaration($$) { - no strict 'refs'; - my ($prototype, $file) =3D @_; - my $func =3D "dump_" . $decl_type; - &$func(@_); -} - -sub dump_union($$) { - dump_struct(@_); -} - -sub dump_struct($$) { - my $x =3D shift; - my $file =3D shift; - - if ($x =3D~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|= ____cacheline_aligned_in_smp|____cacheline_aligned|__attribute__\s*\(\([a-z= 0-9,_\s\(\)]*\)\)))*/) { - my $decl_type =3D $1; - $declaration_name =3D $2; - my $members =3D $3; - - # ignore members marked private: - $members =3D~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; - $members =3D~ s/\/\*\s*private:.*//gosi; - # strip comments: - $members =3D~ s/\/\*.*?\*\///gos; - # strip attributes - $members =3D~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)/ /gi; - $members =3D~ s/\s*__aligned\s*\([^;]*\)/ /gos; - $members =3D~ s/\s*__packed\s*/ /gos; - $members =3D~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; - $members =3D~ s/\s*____cacheline_aligned_in_smp/ /gos; - $members =3D~ s/\s*____cacheline_aligned/ /gos; - - # replace DECLARE_BITMAP - $members =3D~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_B= ITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; - $members =3D~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $= 1\[BITS_TO_LONGS($2)\]/gos; - # replace DECLARE_HASHTABLE - $members =3D~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned lon= g $1\[1 << (($2) - 1)\]/gos; - # replace DECLARE_KFIFO - $members =3D~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \= *$1/gos; - # replace DECLARE_KFIFO_PTR - $members =3D~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; - - my $declaration =3D $members; - - # Split nested struct/union elements as newer ones - while ($members =3D~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*= )\;/) { - my $newmember; - my $maintype =3D $1; - my $ids =3D $4; - my $content =3D $3; - foreach my $id(split /,/, $ids) { - $newmember .=3D "$maintype $id; "; - - $id =3D~ s/[:\[].*//; - $id =3D~ s/^\s*\**(\S+)\s*/$1/; - foreach my $arg (split /;/, $content) { - next if ($arg =3D~ m/^\s*$/); - if ($arg =3D~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) { - # pointer-to-function - my $type =3D $1; - my $name =3D $2; - my $extra =3D $3; - next if (!$name); - if ($id =3D~ m/^\s*$/) { - # anonymous struct/union - $newmember .=3D "$type$name$extra; "; - } else { - $newmember .=3D "$type$id.$name$extra; "; - } - } else { - my $type; - my $names; - $arg =3D~ s/^\s+//; - $arg =3D~ s/\s+$//; - # Handle bitmaps - $arg =3D~ s/:\s*\d+\s*//g; - # Handle arrays - $arg =3D~ s/\[.*\]//g; - # The type may have multiple words, - # and multiple IDs can be defined, like: - # const struct foo, *bar, foobar - # So, we remove spaces when parsing the - # names, in order to match just names - # and commas for the names - $arg =3D~ s/\s*,\s*/,/g; - if ($arg =3D~ m/(.*)\s+([\S+,]+)/) { - $type =3D $1; - $names =3D $2; - } else { - $newmember .=3D "$arg; "; - next; - } - foreach my $name (split /,/, $names) { - $name =3D~ s/^\s*\**(\S+)\s*/$1/; - next if (($name =3D~ m/^\s*$/)); - if ($id =3D~ m/^\s*$/) { - # anonymous struct/union - $newmember .=3D "$type $name; "; - } else { - $newmember .=3D "$type $id.$name; "; - } - } - } - } - } - $members =3D~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/$n= ewmember/; - } - - # Ignore other nested elements, like enums - $members =3D~ s/(\{[^\{\}]*\})//g; - - create_parameterlist($members, ';', $file, $declaration_name); - check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_= actual); - - # Adjust declaration for better display - $declaration =3D~ s/([\{;])/$1\n/g; - $declaration =3D~ s/\}\s+;/};/g; - # Better handle inlined enums - do {} while ($declaration =3D~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/); - - my @def_args =3D split /\n/, $declaration; - my $level =3D 1; - $declaration =3D ""; - foreach my $clause (@def_args) { - $clause =3D~ s/^\s+//; - $clause =3D~ s/\s+$//; - $clause =3D~ s/\s+/ /; - next if (!$clause); - $level-- if ($clause =3D~ m/(\})/ && $level > 1); - if (!($clause =3D~ m/^\s*#/)) { - $declaration .=3D "\t" x $level; - } - $declaration .=3D "\t" . $clause . "\n"; - $level++ if ($clause =3D~ m/(\{)/ && !($clause =3D~m/\}/)); - } - output_declaration($declaration_name, - 'struct', - {'struct' =3D> $declaration_name, - 'module' =3D> $modulename, - 'definition' =3D> $declaration, - 'parameterlist' =3D> \@parameterlist, - 'parameterdescs' =3D> \%parameterdescs, - 'parametertypes' =3D> \%parametertypes, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose, - 'type' =3D> $decl_type - }); - } - else { - print STDERR "${file}:$.: error: Cannot parse struct or union!\n"; - ++$errors; - } -} - - -sub show_warnings($$) { - my $functype =3D shift; - my $name =3D shift; - - return 0 if (defined($nosymbol_table{$name})); - - return 1 if ($output_selection =3D=3D OUTPUT_ALL); - - if ($output_selection =3D=3D OUTPUT_EXPORTED) { - if (defined($function_table{$name})) { - return 1; - } else { - return 0; - } - } - if ($output_selection =3D=3D OUTPUT_INTERNAL) { - if (!($functype eq "function" && defined($function_table{$name}))) { - return 1; - } else { - return 0; - } - } - if ($output_selection =3D=3D OUTPUT_INCLUDE) { - if (defined($function_table{$name})) { - return 1; - } else { - return 0; - } - } - die("Please add the new output type at show_warnings()"); -} - -sub dump_enum($$) { - my $x =3D shift; - my $file =3D shift; - my $members; - - - $x =3D~ s@/\*.*?\*/@@gos; # strip comments. - # strip #define macros inside enums - $x =3D~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; - - if ($x =3D~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) { - $declaration_name =3D $2; - $members =3D $1; - } elsif ($x =3D~ /enum\s+(\w*)\s*\{(.*)\}/) { - $declaration_name =3D $1; - $members =3D $2; - } - - if ($declaration_name) { - my %_members; - - $members =3D~ s/\s+$//; - - foreach my $arg (split ',', $members) { - $arg =3D~ s/^\s*(\w+).*/$1/; - push @parameterlist, $arg; - if (!$parameterdescs{$arg}) { - $parameterdescs{$arg} =3D $undescribed; - if (show_warnings("enum", $declaration_name)) { - print STDERR "${file}:$.: warning: Enum value '$arg' not described in e= num '$declaration_name'\n"; - } - } - $_members{$arg} =3D 1; - } - - while (my ($k, $v) =3D each %parameterdescs) { - if (!exists($_members{$k})) { - if (show_warnings("enum", $declaration_name)) { - print STDERR "${file}:$.: warning: Excess enum value '$k' descripti= on in '$declaration_name'\n"; - } - } - } - - output_declaration($declaration_name, - 'enum', - {'enum' =3D> $declaration_name, - 'module' =3D> $modulename, - 'parameterlist' =3D> \@parameterlist, - 'parameterdescs' =3D> \%parameterdescs, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose - }); - } else { - print STDERR "${file}:$.: error: Cannot parse enum!\n"; - ++$errors; - } -} - -my $typedef_type =3D qr { ((?:\s+[\w\*]+){1,8})\s* }x; -my $typedef_ident =3D qr { \*?\s*(\w\S+)\s* }x; -my $typedef_args =3D qr { \s*\((.*)\); }x; - -my $typedef1 =3D qr { typedef$typedef_type\($typedef_ident\)$typedef_args = }x; -my $typedef2 =3D qr { typedef$typedef_type$typedef_ident$typedef_args }x; - -sub dump_typedef($$) { - my $x =3D shift; - my $file =3D shift; - - $x =3D~ s@/\*.*?\*/@@gos; # strip comments. - - # Parse function typedef prototypes - if ($x =3D~ $typedef1 || $x =3D~ $typedef2) { - $return_type =3D $1; - $declaration_name =3D $2; - my $args =3D $3; - $return_type =3D~ s/^\s+//; - - create_parameterlist($args, ',', $file, $declaration_name); - - output_declaration($declaration_name, - 'function', - {'function' =3D> $declaration_name, - 'typedef' =3D> 1, - 'module' =3D> $modulename, - 'functiontype' =3D> $return_type, - 'parameterlist' =3D> \@parameterlist, - 'parameterdescs' =3D> \%parameterdescs, - 'parametertypes' =3D> \%parametertypes, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose - }); - return; - } - - while (($x =3D~ /\(*.\)\s*;$/) || ($x =3D~ /\[*.\]\s*;$/)) { - $x =3D~ s/\(*.\)\s*;$/;/; - $x =3D~ s/\[*.\]\s*;$/;/; - } - - if ($x =3D~ /typedef.*\s+(\w+)\s*;/) { - $declaration_name =3D $1; - - output_declaration($declaration_name, - 'typedef', - {'typedef' =3D> $declaration_name, - 'module' =3D> $modulename, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose - }); - } - else { - print STDERR "${file}:$.: error: Cannot parse typedef!\n"; - ++$errors; - } -} - -sub save_struct_actual($) { - my $actual =3D shift; - - # strip all spaces from the actual param so that it looks like one str= ing item - $actual =3D~ s/\s*//g; - $struct_actual =3D $struct_actual . $actual . " "; -} - -sub create_parameterlist($$$$) { - my $args =3D shift; - my $splitter =3D shift; - my $file =3D shift; - my $declaration_name =3D shift; - my $type; - my $param; - - # temporarily replace commas inside function pointer definition - while ($args =3D~ /(\([^\),]+),/) { - $args =3D~ s/(\([^\),]+),/$1#/g; - } - - foreach my $arg (split($splitter, $args)) { - # strip comments - $arg =3D~ s/\/\*.*\*\///; - # strip leading/trailing spaces - $arg =3D~ s/^\s*//; - $arg =3D~ s/\s*$//; - $arg =3D~ s/\s+/ /; - - if ($arg =3D~ /^#/) { - # Treat preprocessor directive as a typeless variable just to fill - # corresponding data structures "correctly". Catch it later in - # output_* subs. - push_parameter($arg, "", "", $file); - } elsif ($arg =3D~ m/\(.+\)\s*\(/) { - # pointer-to-function - $arg =3D~ tr/#/,/; - $arg =3D~ m/[^\(]+\(\*?\s*([\w\.]*)\s*\)/; - $param =3D $1; - $type =3D $arg; - $type =3D~ s/([^\(]+\(\*?)\s*$param/$1/; - save_struct_actual($param); - push_parameter($param, $type, $arg, $file, $declaration_name); - } elsif ($arg) { - $arg =3D~ s/\s*:\s*/:/g; - $arg =3D~ s/\s*\[/\[/g; - - my @args =3D split('\s*,\s*', $arg); - if ($args[0] =3D~ m/\*/) { - $args[0] =3D~ s/(\*+)\s*/ $1/; - } - - my @first_arg; - if ($args[0] =3D~ /^(.*\s+)(.*?\[.*\].*)$/) { - shift @args; - push(@first_arg, split('\s+', $1)); - push(@first_arg, $2); - } else { - @first_arg =3D split('\s+', shift @args); - } - - unshift(@args, pop @first_arg); - $type =3D join " ", @first_arg; - - foreach $param (@args) { - if ($param =3D~ m/^(\*+)\s*(.*)/) { - save_struct_actual($2); - - push_parameter($2, "$type $1", $arg, $file, $declaration_name); - } - elsif ($param =3D~ m/(.*?):(\d+)/) { - if ($type ne "") { # skip unnamed bit-fields - save_struct_actual($1); - push_parameter($1, "$type:$2", $arg, $file, $declaration_name) - } - } - else { - save_struct_actual($param); - push_parameter($param, $type, $arg, $file, $declaration_name); - } - } - } - } -} - -sub push_parameter($$$$$) { - my $param =3D shift; - my $type =3D shift; - my $org_arg =3D shift; - my $file =3D shift; - my $declaration_name =3D shift; - - if (($anon_struct_union =3D=3D 1) && ($type eq "") && - ($param eq "}")) { - return; # ignore the ending }; from anon. struct/union - } - - $anon_struct_union =3D 0; - $param =3D~ s/[\[\)].*//; - - if ($type eq "" && $param =3D~ /\.\.\.$/) - { - if ($param =3D~ /\w\.\.\.$/) { - # for named variable parameters of the form `x...`, remove the dots - $param =3D~ s/\.\.\.$//; - } else { - # handles unnamed variable parameters - $param =3D "..."; - } - if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq ""= ) { - $parameterdescs{$param} =3D "variable arguments"; - } - } - elsif ($type eq "" && ($param eq "" or $param eq "void")) - { - $param=3D"void"; - $parameterdescs{void} =3D "no arguments"; - } - elsif ($type eq "" && ($param eq "struct" or $param eq "union")) - # handle unnamed (anonymous) union or struct: - { - $type =3D $param; - $param =3D "{unnamed_" . $param . "}"; - $parameterdescs{$param} =3D "anonymous\n"; - $anon_struct_union =3D 1; - } - - # warn if parameter has no description - # (but ignore ones starting with # as these are not parameters - # but inline preprocessor statements); - # Note: It will also ignore void params and unnamed structs/unions - if (!defined $parameterdescs{$param} && $param !~ /^#/) { - $parameterdescs{$param} =3D $undescribed; - - if (show_warnings($type, $declaration_name) && $param !~ /\./) { - print STDERR - "${file}:$.: warning: Function parameter or member '$param' not d= escribed in '$declaration_name'\n"; - ++$warnings; - } - } - - # strip spaces from $param so that it is one continuous string - # on @parameterlist; - # this fixes a problem where check_sections() cannot find - # a parameter like "addr[6 + 2]" because it actually appears - # as "addr[6", "+", "2]" on the parameter list; - # but it's better to maintain the param string unchanged for output, - # so just weaken the string compare in check_sections() to ignore - # "[blah" in a parameter string; - ###$param =3D~ s/\s*//g; - push @parameterlist, $param; - $org_arg =3D~ s/\s\s+/ /g; - $parametertypes{$param} =3D $org_arg; -} - -sub check_sections($$$$$) { - my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) =3D @_; - my @sects =3D split ' ', $sectcheck; - my @prms =3D split ' ', $prmscheck; - my $err; - my ($px, $sx); - my $prm_clean; # strip trailing "[array size]" and/or beginning "*" - - foreach $sx (0 .. $#sects) { - $err =3D 1; - foreach $px (0 .. $#prms) { - $prm_clean =3D $prms[$px]; - $prm_clean =3D~ s/\[.*\]//; - $prm_clean =3D~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; - # ignore array size in a parameter string; - # however, the original param string may contain - # spaces, e.g.: addr[6 + 2] - # 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~ s/\[.*//; - - ##$prm_clean =3D~ s/^\**//; - if ($prm_clean eq $sects[$sx]) { - $err =3D 0; - last; - } - } - if ($err) { - if ($decl_type eq "function") { - print STDERR "${file}:$.: warning: " . - "Excess function parameter " . - "'$sects[$sx]' " . - "description in '$decl_name'\n"; - ++$warnings; - } - } - } -} - -## -# Checks the section describing the return value of a function. -sub check_return_section { - my $file =3D shift; - my $declaration_name =3D shift; - my $return_type =3D shift; - - # Ignore an empty return type (It's a macro) - # Ignore functions with a "void" return type. (But don't ignore "v= oid *") - if (($return_type eq "") || ($return_type =3D~ /void\s*\w*\s*$/)) { - return; - } - - if (!defined($sections{$section_return}) || - $sections{$section_return} eq "") { - print STDERR "${file}:$.: warning: " . - "No description found for return value of " . - "'$declaration_name'\n"; - ++$warnings; - } -} - -## -# takes a function prototype and the name of the current file being -# processed and spits out all the details stored in the global -# arrays/hashes. -sub dump_function($$) { - my $prototype =3D shift; - my $file =3D shift; - my $noret =3D 0; - - print_lineno($new_start_line); - - $prototype =3D~ s/^static +//; - $prototype =3D~ s/^extern +//; - $prototype =3D~ s/^asmlinkage +//; - $prototype =3D~ s/^inline +//; - $prototype =3D~ s/^__inline__ +//; - $prototype =3D~ s/^__inline +//; - $prototype =3D~ s/^__always_inline +//; - $prototype =3D~ s/^noinline +//; - $prototype =3D~ s/__init +//; - $prototype =3D~ s/__init_or_module +//; - $prototype =3D~ s/__meminit +//; - $prototype =3D~ s/__must_check +//; - $prototype =3D~ s/__weak +//; - $prototype =3D~ s/__sched +//; - $prototype =3D~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//; - my $define =3D $prototype =3D~ s/^#\s*define\s+//; #ak added - $prototype =3D~ s/__attribute__\s*\(\( - (?: - [\w\s]++ # attribute name - (?:\([^)]*+\))? # attribute arguments - \s*+,? # optional comma at the end - )+ - \)\)\s+//x; - - # Strip QEMU specific compiler annotations - $prototype =3D~ s/QEMU_[A-Z_]+ +//; - - # Yes, this truly is vile. We are looking for: - # 1. Return type (may be nothing if we're looking at a macro) - # 2. Function name - # 3. Function parameters. - # - # All the while we have to watch out for function pointer parameters - # (which IIRC is what the two sections are for), C types (these - # regexps don't even start to express all the possibilities), and - # so on. - # - # If you mess with these regexps, it's a good idea to check that - # the following functions' documentation still comes out right: - # - parport_register_device (function pointer parameters) - # - atomic_set (macro) - # - pci_match_device, __copy_to_user (long return type) - - if ($define && $prototype =3D~ m/^()([a-zA-Z0-9_~:]+)\s+/) { - # This is an object-like macro, it has no return type and no param= eter - # list. - # Function-like macros are not allowed to have spaces between - # declaration_name and opening parenthesis (notice the \s+). - $return_type =3D $1; - $declaration_name =3D $2; - $noret =3D 1; - } elsif ($prototype =3D~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || - $prototype =3D~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || - $prototype =3D~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || - $prototype =3D~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || - $prototype =3D~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ = || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ = || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]= *)\)/ || - $prototype =3D~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || - $prototype =3D~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || - $prototype =3D~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || - $prototype =3D~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || - $prototype =3D~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ = || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ = || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]= *)\)/ || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]= *)\)/ || - $prototype =3D~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(= ([^\{]*)\)/ || - $prototype =3D~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s= *\(([^\{]*)\)/) { - $return_type =3D $1; - $declaration_name =3D $2; - my $args =3D $3; - - create_parameterlist($args, ',', $file, $declaration_name); - } else { - print STDERR "${file}:$.: warning: cannot understand function prototype: = '$prototype'\n"; - return; - } - - my $prms =3D join " ", @parameterlist; - check_sections($file, $declaration_name, "function", $sectcheck, $prms= ); - - # This check emits a lot of warnings at the moment, because many - # functions don't have a 'Return' doc section. So until the number - # of warnings goes sufficiently down, the check is only performed in - # verbose mode. - # TODO: always perform the check. - if ($verbose && !$noret) { - check_return_section($file, $declaration_name, $return_type); - } - - # The function parser can be called with a typedef parameter. - # Handle it. - if ($return_type =3D~ /typedef/) { - output_declaration($declaration_name, - 'function', - {'function' =3D> $declaration_name, - 'typedef' =3D> 1, - 'module' =3D> $modulename, - 'functiontype' =3D> $return_type, - 'parameterlist' =3D> \@parameterlist, - 'parameterdescs' =3D> \%parameterdescs, - 'parametertypes' =3D> \%parametertypes, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose - }); - } else { - output_declaration($declaration_name, - 'function', - {'function' =3D> $declaration_name, - 'module' =3D> $modulename, - 'functiontype' =3D> $return_type, - 'parameterlist' =3D> \@parameterlist, - 'parameterdescs' =3D> \%parameterdescs, - 'parametertypes' =3D> \%parametertypes, - 'sectionlist' =3D> \@sectionlist, - 'sections' =3D> \%sections, - 'purpose' =3D> $declaration_purpose - }); - } -} - -sub reset_state { - $function =3D ""; - %parameterdescs =3D (); - %parametertypes =3D (); - @parameterlist =3D (); - %sections =3D (); - @sectionlist =3D (); - $sectcheck =3D ""; - $struct_actual =3D ""; - $prototype =3D ""; - - $state =3D STATE_NORMAL; - $inline_doc_state =3D STATE_INLINE_NA; -} - -sub tracepoint_munge($) { - my $file =3D shift; - my $tracepointname =3D 0; - my $tracepointargs =3D 0; - - if ($prototype =3D~ m/TRACE_EVENT\((.*?),/) { - $tracepointname =3D $1; - } - if ($prototype =3D~ m/DEFINE_SINGLE_EVENT\((.*?),/) { - $tracepointname =3D $1; - } - if ($prototype =3D~ m/DEFINE_EVENT\((.*?),(.*?),/) { - $tracepointname =3D $2; - } - $tracepointname =3D~ s/^\s+//; #strip leading whitespace - if ($prototype =3D~ m/TP_PROTO\((.*?)\)/) { - $tracepointargs =3D $1; - } - if (($tracepointname eq 0) || ($tracepointargs eq 0)) { - print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". - "$prototype\n"; - } else { - $prototype =3D "static inline void trace_$tracepointname($tracepointargs= )"; - } -} - -sub syscall_munge() { - my $void =3D 0; - - $prototype =3D~ s@[\r\n]+@ @gos; # strip newlines/CR's -## if ($prototype =3D~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) { - if ($prototype =3D~ m/SYSCALL_DEFINE0/) { - $void =3D 1; -## $prototype =3D "long sys_$1(void)"; - } - - $prototype =3D~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func= name - if ($prototype =3D~ m/long (sys_.*?),/) { - $prototype =3D~ s/,/\(/; - } elsif ($void) { - $prototype =3D~ s/\)/\(void\)/; - } - - # now delete all of the odd-number commas in $prototype - # so that arg types & arg names don't have a comma between them - my $count =3D 0; - my $len =3D length($prototype); - if ($void) { - $len =3D 0; # skip the for-loop - } - for (my $ix =3D 0; $ix < $len; $ix++) { - if (substr($prototype, $ix, 1) eq ',') { - $count++; - if ($count % 2 =3D=3D 1) { - substr($prototype, $ix, 1) =3D ' '; - } - } - } -} - -sub process_proto_function($$) { - my $x =3D shift; - my $file =3D shift; - - $x =3D~ s@\/\/.*$@@gos; # strip C99-style comments to end of line - - if ($x =3D~ m#\s*/\*\s+MACDOC\s*#io || ($x =3D~ /^#/ && $x !~ /^#\s*de= fine/)) { - # do nothing - } - elsif ($x =3D~ /([^\{]*)/) { - $prototype .=3D $1; - } - - if (($x =3D~ /\{/) || ($x =3D~ /\#\s*define/) || ($x =3D~ /;/)) { - $prototype =3D~ s@/\*.*?\*/@@gos; # strip comments. - $prototype =3D~ s@[\r\n]+@ @gos; # strip newlines/cr's. - $prototype =3D~ s@^\s+@@gos; # strip leading spaces - - # Handle prototypes for function pointers like: - # int (*pcs_config)(struct foo) - $prototype =3D~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos; - - if ($prototype =3D~ /SYSCALL_DEFINE/) { - syscall_munge(); - } - if ($prototype =3D~ /TRACE_EVENT/ || $prototype =3D~ /DEFINE_EVENT/ || - $prototype =3D~ /DEFINE_SINGLE_EVENT/) - { - tracepoint_munge($file); - } - dump_function($prototype, $file); - reset_state(); - } -} - -sub process_proto_type($$) { - my $x =3D shift; - my $file =3D shift; - - $x =3D~ s@[\r\n]+@ @gos; # strip newlines/cr's. - $x =3D~ s@^\s+@@gos; # strip leading spaces - $x =3D~ s@\s+$@@gos; # strip trailing spaces - $x =3D~ s@\/\/.*$@@gos; # strip C99-style comments to end of line - - if ($x =3D~ /^#/) { - # To distinguish preprocessor directive from regular declaration later. - $x .=3D ";"; - } - - while (1) { - if ( $x =3D~ /([^\{\};]*)([\{\};])(.*)/ ) { - if( length $prototype ) { - $prototype .=3D " " - } - $prototype .=3D $1 . $2; - ($2 eq '{') && $brcount++; - ($2 eq '}') && $brcount--; - if (($2 eq ';') && ($brcount =3D=3D 0)) { - dump_declaration($prototype, $file); - reset_state(); - last; - } - $x =3D $3; - } else { - $prototype .=3D $x; - last; - } - } -} - - -sub map_filename($) { - my $file; - my ($orig_file) =3D @_; - - if (defined($ENV{'SRCTREE'})) { - $file =3D "$ENV{'SRCTREE'}" . "/" . $orig_file; - } else { - $file =3D $orig_file; - } - - if (defined($source_map{$file})) { - $file =3D $source_map{$file}; - } - - return $file; -} - -sub process_export_file($) { - my ($orig_file) =3D @_; - my $file =3D map_filename($orig_file); - - if (!open(IN,"<$file")) { - print STDERR "Error: Cannot open file $file\n"; - ++$errors; - return; - } - - while () { - if (/$export_symbol/) { - next if (defined($nosymbol_table{$2})); - $function_table{$2} =3D 1; - } - } - - close(IN); -} - -# -# Parsers for the various processing states. -# -# STATE_NORMAL: looking for the /** to begin everything. -# -sub process_normal() { - if (/$doc_start/o) { - $state =3D STATE_NAME; # next line is always the function name - $in_doc_sect =3D 0; - $declaration_start_line =3D $. + 1; - } -} - -# -# STATE_NAME: Looking for the "name - description" line -# -sub process_name($$) { - my $file =3D shift; - my $identifier; - my $descr; - - if (/$doc_block/o) { - $state =3D STATE_DOCBLOCK; - $contents =3D ""; - $new_start_line =3D $.; - - if ( $1 eq "" ) { - $section =3D $section_intro; - } else { - $section =3D $1; - } - } - elsif (/$doc_decl/o) { - $identifier =3D $1; - if (/\s*([\w\s]+?)(\s*-|:)/) { - $identifier =3D $1; - } - - $state =3D STATE_BODY; - # if there's no @param blocks need to set up default section - # here - $contents =3D ""; - $section =3D $section_default; - $new_start_line =3D $. + 1; - if (/[-:](.*)/) { - # strip leading/trailing/multiple spaces - $descr=3D $1; - $descr =3D~ s/^\s*//; - $descr =3D~ s/\s*$//; - $descr =3D~ s/\s+/ /g; - $declaration_purpose =3D $descr; - $state =3D STATE_BODY_MAYBE; - } else { - $declaration_purpose =3D ""; - } - - if (($declaration_purpose eq "") && $verbose) { - print STDERR "${file}:$.: warning: missing initial short description = on line:\n"; - print STDERR $_; - ++$warnings; - } - - if ($identifier =3D~ m/^struct\b/) { - $decl_type =3D 'struct'; - } elsif ($identifier =3D~ m/^union\b/) { - $decl_type =3D 'union'; - } elsif ($identifier =3D~ m/^enum\b/) { - $decl_type =3D 'enum'; - } elsif ($identifier =3D~ m/^typedef\b/) { - $decl_type =3D 'typedef'; - } else { - $decl_type =3D 'function'; - } - - if ($verbose) { - print STDERR "${file}:$.: info: Scanning doc for $identifier\n"; - } - } else { - print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", - " - I thought it was a doc line\n"; - ++$warnings; - $state =3D STATE_NORMAL; - } -} - - -# -# STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment. -# -sub process_body($$) { - my $file =3D shift; - - # Until all named variable macro parameters are - # documented using the bare name (`x`) rather than with - # dots (`x...`), strip the dots: - if ($section =3D~ /\w\.\.\.$/) { - $section =3D~ s/\.\.\.$//; - - if ($verbose) { - print STDERR "${file}:$.: warning: Variable macro arguments should be= documented without dots\n"; - ++$warnings; - } - } - - if ($state =3D=3D STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { - dump_section($file, $section, $contents); - $section =3D $section_default; - $new_start_line =3D $.; - $contents =3D ""; - } - - if (/$doc_sect/i) { # case insensitive for supported section names - $newsection =3D $1; - $newcontents =3D $2; - - # map the supported section names to the canonical names - if ($newsection =3D~ m/^description$/i) { - $newsection =3D $section_default; - } elsif ($newsection =3D~ m/^context$/i) { - $newsection =3D $section_context; - } elsif ($newsection =3D~ m/^returns?$/i) { - $newsection =3D $section_return; - } elsif ($newsection =3D~ m/^\@return$/) { - # special: @return is a section, not a param description - $newsection =3D $section_return; - } - - if (($contents ne "") && ($contents ne "\n")) { - if (!$in_doc_sect && $verbose) { - print STDERR "${file}:$.: warning: contents before sections\n"; - ++$warnings; - } - dump_section($file, $section, $contents); - $section =3D $section_default; - } - - $in_doc_sect =3D 1; - $state =3D STATE_BODY; - $contents =3D $newcontents; - $new_start_line =3D $.; - while (substr($contents, 0, 1) eq " ") { - $contents =3D substr($contents, 1); - } - if ($contents ne "") { - $contents .=3D "\n"; - } - $section =3D $newsection; - $leading_space =3D undef; - } elsif (/$doc_end/) { - if (($contents ne "") && ($contents ne "\n")) { - dump_section($file, $section, $contents); - $section =3D $section_default; - $contents =3D ""; - } - # look for doc_com + + doc_end: - if ($_ =3D~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { - print STDERR "${file}:$.: warning: suspicious ending line: $_"; - ++$warnings; - } - - $prototype =3D ""; - $state =3D STATE_PROTO; - $brcount =3D 0; - $new_start_line =3D $. + 1; - } elsif (/$doc_content/) { - if ($1 eq "") { - if ($section eq $section_context) { - dump_section($file, $section, $contents); - $section =3D $section_default; - $contents =3D ""; - $new_start_line =3D $.; - $state =3D STATE_BODY; - } else { - if ($section ne $section_default) { - $state =3D STATE_BODY_WITH_BLANK_LINE; - } else { - $state =3D STATE_BODY; - } - $contents .=3D "\n"; - } - } elsif ($state =3D=3D STATE_BODY_MAYBE) { - # Continued declaration purpose - chomp($declaration_purpose); - $declaration_purpose .=3D " " . $1; - $declaration_purpose =3D~ s/\s+/ /g; - } else { - my $cont =3D $1; - if ($section =3D~ m/^@/ || $section eq $section_context) { - if (!defined $leading_space) { - if ($cont =3D~ m/^(\s+)/) { - $leading_space =3D $1; - } else { - $leading_space =3D ""; - } - } - $cont =3D~ s/^$leading_space//; - } - $contents .=3D $cont . "\n"; - } - } else { - # i dont know - bad line? ignore. - print STDERR "${file}:$.: warning: bad line: $_"; - ++$warnings; - } -} - - -# -# STATE_PROTO: reading a function/whatever prototype. -# -sub process_proto($$) { - my $file =3D shift; - - if (/$doc_inline_oneline/) { - $section =3D $1; - $contents =3D $2; - if ($contents ne "") { - $contents .=3D "\n"; - dump_section($file, $section, $contents); - $section =3D $section_default; - $contents =3D ""; - } - } elsif (/$doc_inline_start/) { - $state =3D STATE_INLINE; - $inline_doc_state =3D STATE_INLINE_NAME; - } elsif ($decl_type eq 'function') { - process_proto_function($_, $file); - } else { - process_proto_type($_, $file); - } -} - -# -# STATE_DOCBLOCK: within a DOC: block. -# -sub process_docblock($$) { - my $file =3D shift; - - if (/$doc_end/) { - dump_doc_section($file, $section, $contents); - $section =3D $section_default; - $contents =3D ""; - $function =3D ""; - %parameterdescs =3D (); - %parametertypes =3D (); - @parameterlist =3D (); - %sections =3D (); - @sectionlist =3D (); - $prototype =3D ""; - $state =3D STATE_NORMAL; - } elsif (/$doc_content/) { - if ( $1 eq "" ) { - $contents .=3D $blankline; - } else { - $contents .=3D $1 . "\n"; - } - } -} - -# -# STATE_INLINE: docbook comments within a prototype. -# -sub process_inline($$) { - my $file =3D shift; - - # First line (state 1) needs to be a @parameter - if ($inline_doc_state =3D=3D STATE_INLINE_NAME && /$doc_inline_sect/o)= { - $section =3D $1; - $contents =3D $2; - $new_start_line =3D $.; - if ($contents ne "") { - while (substr($contents, 0, 1) eq " ") { - $contents =3D substr($contents, 1); - } - $contents .=3D "\n"; - } - $inline_doc_state =3D STATE_INLINE_TEXT; - # Documentation block end */ - } elsif (/$doc_inline_end/) { - if (($contents ne "") && ($contents ne "\n")) { - dump_section($file, $section, $contents); - $section =3D $section_default; - $contents =3D ""; - } - $state =3D STATE_PROTO; - $inline_doc_state =3D STATE_INLINE_NA; - # Regular text - } elsif (/$doc_content/) { - if ($inline_doc_state =3D=3D STATE_INLINE_TEXT) { - $contents .=3D $1 . "\n"; - # nuke leading blank lines - if ($contents =3D~ /^\s*$/) { - $contents =3D ""; - } - } elsif ($inline_doc_state =3D=3D STATE_INLINE_NAME) { - $inline_doc_state =3D STATE_INLINE_ERROR; - print STDERR "${file}:$.: warning: "; - print STDERR "Incorrect use of kernel-doc format: $_"; - ++$warnings; - } - } -} - - -sub process_file($) { - my $file; - my $initial_section_counter =3D $section_counter; - my ($orig_file) =3D @_; - - $file =3D map_filename($orig_file); - - if (!open(IN_FILE,"<$file")) { - print STDERR "Error: Cannot open file $file\n"; - ++$errors; - return; - } - - $. =3D 1; - - $section_counter =3D 0; - while () { - while (s/\\\s*$//) { - $_ .=3D ; - } - # Replace tabs by spaces - while ($_ =3D~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; - # Hand this line to the appropriate state handler - if ($state =3D=3D STATE_NORMAL) { - process_normal(); - } elsif ($state =3D=3D STATE_NAME) { - process_name($file, $_); - } elsif ($state =3D=3D STATE_BODY || $state =3D=3D STATE_BODY_MAYBE || - $state =3D=3D STATE_BODY_WITH_BLANK_LINE) { - process_body($file, $_); - } elsif ($state =3D=3D STATE_INLINE) { # scanning for inline parameters - process_inline($file, $_); - } elsif ($state =3D=3D STATE_PROTO) { - process_proto($file, $_); - } elsif ($state =3D=3D STATE_DOCBLOCK) { - process_docblock($file, $_); - } - } - - # Make sure we got something interesting. - if ($initial_section_counter =3D=3D $section_counter && $ - output_mode ne "none") { - if ($output_selection =3D=3D OUTPUT_INCLUDE) { - print STDERR "${file}:1: warning: '$_' not found\n" - for keys %function_table; - } - else { - print STDERR "${file}:1: warning: no structured comments found\n"; - } - } - close IN_FILE; -} - - -if ($output_mode eq "rst") { - get_sphinx_version() if (!$sphinx_major); -} - -$kernelversion =3D get_kernel_version(); - -# generate a sequence of code that will splice in highlighting information -# using the s// operator. -for (my $k =3D 0; $k < @highlights; $k++) { - my $pattern =3D $highlights[$k][0]; - my $result =3D $highlights[$k][1]; -# print STDERR "scanning pattern:$pattern, highlight:($result)\n"; - $dohighlight .=3D "\$contents =3D~ s:$pattern:$result:gs;\n"; -} - -# Read the file that maps relative names to absolute names for -# separate source and object directories and for shadow trees. -if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { - my ($relname, $absname); - while() { - chop(); - ($relname, $absname) =3D (split())[0..1]; - $relname =3D~ s:^/+::; - $source_map{$relname} =3D $absname; - } - close(SOURCE_MAP); -} - -if ($output_selection =3D=3D OUTPUT_EXPORTED || - $output_selection =3D=3D OUTPUT_INTERNAL) { - - push(@export_file_list, @ARGV); - - foreach (@export_file_list) { - chomp; - process_export_file($_); - } -} - -foreach (@ARGV) { - chomp; - process_file($_); -} -if ($verbose && $errors) { - print STDERR "$errors errors\n"; -} -if ($verbose && $warnings) { - print STDERR "$warnings warnings\n"; -} - -if ($Werror && $warnings) { - print STDERR "$warnings warnings as Errors\n"; - exit($warnings); -} else { - exit($output_mode eq "none" ? 0 : $errors) -} --=20 2.43.0