mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	doc: update Kernel documentation build system
Update the documentation build system according to Linux v5.11-rc1. Deactive the automarkup.py extension module which on Gitlab CI is incompatible with Unicode. With this patch we can build the HTML documentation using either of Sphinx 2 and Sphinx 3. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
		
							parent
							
								
									836049d63e
								
							
						
					
					
						commit
						98f01cf7a2
					
				
							
								
								
									
										139
									
								
								doc/conf.py
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								doc/conf.py
									
									
									
									
									
								
							@ -16,6 +16,8 @@ import sys
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import sphinx
 | 
					import sphinx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from subprocess import check_output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Get Sphinx version
 | 
					# Get Sphinx version
 | 
				
			||||||
major, minor, patch = sphinx.version_info[:3]
 | 
					major, minor, patch = sphinx.version_info[:3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,39 +33,98 @@ from load_config import loadConfig
 | 
				
			|||||||
# If your documentation needs a minimal Sphinx version, state it here.
 | 
					# If your documentation needs a minimal Sphinx version, state it here.
 | 
				
			||||||
needs_sphinx = '1.3'
 | 
					needs_sphinx = '1.3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
latex_engine = 'xelatex'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Add any Sphinx extension module names here, as strings. They can be
 | 
					# Add any Sphinx extension module names here, as strings. They can be
 | 
				
			||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 | 
					# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 | 
				
			||||||
# ones.
 | 
					# ones.
 | 
				
			||||||
extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'kfigure']
 | 
					extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include',
 | 
				
			||||||
 | 
					              'kfigure', 'sphinx.ext.ifconfig', # 'automarkup',
 | 
				
			||||||
 | 
					              'maintainers_include', 'sphinx.ext.autosectionlabel',
 | 
				
			||||||
 | 
					              'kernel_abi', 'kernel_feat']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# cdomain is badly broken in Sphinx 3+. Leaving it out generates *most*
 | 
					# cdomain is badly broken in Sphinx 3+.  Leaving it out generates *most*
 | 
				
			||||||
# of the docs correctly, but not all.
 | 
					# of the docs correctly, but not all.  Scream bloody murder but allow
 | 
				
			||||||
 | 
					# the process to proceed; hopefully somebody will fix this properly soon.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
if major >= 3:
 | 
					if major >= 3:
 | 
				
			||||||
 | 
					    sys.stderr.write('''WARNING: The kernel documentation build process
 | 
				
			||||||
 | 
					        support for Sphinx v3.0 and above is brand new. Be prepared for
 | 
				
			||||||
 | 
					        possible issues in the generated output.
 | 
				
			||||||
 | 
					        ''')
 | 
				
			||||||
    if (major > 3) or (minor > 0 or patch >= 2):
 | 
					    if (major > 3) or (minor > 0 or patch >= 2):
 | 
				
			||||||
        sys.stderr.write('''The build process with Sphinx 3+ is broken.
 | 
					 | 
				
			||||||
You will have to remove -W in doc/Makefile.
 | 
					 | 
				
			||||||
''')
 | 
					 | 
				
			||||||
        # Sphinx c function parser is more pedantic with regards to type
 | 
					        # Sphinx c function parser is more pedantic with regards to type
 | 
				
			||||||
        # checking. Due to that, having macros at c:function cause problems.
 | 
					        # checking. Due to that, having macros at c:function cause problems.
 | 
				
			||||||
        # Those needed to be escaped by using c_id_attributes[] array
 | 
					        # Those needed to be scaped by using c_id_attributes[] array
 | 
				
			||||||
        c_id_attributes = [
 | 
					        c_id_attributes = [
 | 
				
			||||||
 | 
					            # GCC Compiler types not parsed by Sphinx:
 | 
				
			||||||
 | 
					            "__restrict__",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # include/linux/compiler.h
 | 
					            # include/linux/compiler_types.h:
 | 
				
			||||||
 | 
					            "__iomem",
 | 
				
			||||||
 | 
					            "__kernel",
 | 
				
			||||||
 | 
					            "noinstr",
 | 
				
			||||||
 | 
					            "notrace",
 | 
				
			||||||
 | 
					            "__percpu",
 | 
				
			||||||
 | 
					            "__rcu",
 | 
				
			||||||
 | 
					            "__user",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # include/linux/compiler_attributes.h:
 | 
				
			||||||
 | 
					            "__alias",
 | 
				
			||||||
 | 
					            "__aligned",
 | 
				
			||||||
 | 
					            "__aligned_largest",
 | 
				
			||||||
 | 
					            "__always_inline",
 | 
				
			||||||
 | 
					            "__assume_aligned",
 | 
				
			||||||
 | 
					            "__cold",
 | 
				
			||||||
 | 
					            "__attribute_const__",
 | 
				
			||||||
 | 
					            "__copy",
 | 
				
			||||||
 | 
					            "__pure",
 | 
				
			||||||
 | 
					            "__designated_init",
 | 
				
			||||||
 | 
					            "__visible",
 | 
				
			||||||
 | 
					            "__printf",
 | 
				
			||||||
 | 
					            "__scanf",
 | 
				
			||||||
 | 
					            "__gnu_inline",
 | 
				
			||||||
 | 
					            "__malloc",
 | 
				
			||||||
 | 
					            "__mode",
 | 
				
			||||||
 | 
					            "__no_caller_saved_registers",
 | 
				
			||||||
 | 
					            "__noclone",
 | 
				
			||||||
 | 
					            "__nonstring",
 | 
				
			||||||
 | 
					            "__noreturn",
 | 
				
			||||||
 | 
					            "__packed",
 | 
				
			||||||
 | 
					            "__pure",
 | 
				
			||||||
 | 
					            "__section",
 | 
				
			||||||
 | 
					            "__always_unused",
 | 
				
			||||||
            "__maybe_unused",
 | 
					            "__maybe_unused",
 | 
				
			||||||
 | 
					            "__used",
 | 
				
			||||||
 | 
					            "__weak",
 | 
				
			||||||
 | 
					            "noinline",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # include/efi.h
 | 
					            # include/efi.h
 | 
				
			||||||
            "EFIAPI",
 | 
					            "EFIAPI",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # include/efi_loader.h
 | 
					            # include/efi_loader.h
 | 
				
			||||||
            "__efi_runtime",
 | 
					            "__efi_runtime",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # include/linux/memblock.h:
 | 
				
			||||||
 | 
					            "__init_memblock",
 | 
				
			||||||
 | 
					            "__meminit",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # include/linux/init.h:
 | 
				
			||||||
 | 
					            "__init",
 | 
				
			||||||
 | 
					            "__ref",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # include/linux/linkage.h:
 | 
				
			||||||
 | 
					            "asmlinkage",
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
else:
 | 
					else:
 | 
				
			||||||
    extensions.append('cdomain')
 | 
					    extensions.append('cdomain')
 | 
				
			||||||
 | 
					    if major == 1 and minor < 7:
 | 
				
			||||||
 | 
					        sys.stderr.write('WARNING: Sphinx 1.7 or greater will be required as of '
 | 
				
			||||||
 | 
					                         'the v2021.04 release\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ensure that autosectionlabel will produce unique names
 | 
				
			||||||
 | 
					autosectionlabel_prefix_document = True
 | 
				
			||||||
 | 
					autosectionlabel_maxdepth = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The name of the math extension changed on Sphinx 1.4
 | 
					# The name of the math extension changed on Sphinx 1.4
 | 
				
			||||||
if (major == 1 and minor > 3) or (major > 1):
 | 
					if (major == 1 and minor > 3) or (major > 1):
 | 
				
			||||||
@ -86,9 +147,9 @@ source_suffix = '.rst'
 | 
				
			|||||||
master_doc = 'index'
 | 
					master_doc = 'index'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# General information about the project.
 | 
					# General information about the project.
 | 
				
			||||||
project = 'Das U-Boot'
 | 
					project = 'The Linux Kernel'
 | 
				
			||||||
copyright = 'The U-Boot development community'
 | 
					copyright = 'The kernel development community'
 | 
				
			||||||
author = 'The U-Boot development community'
 | 
					author = 'The kernel development community'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The version info for the project you're documenting, acts as replacement for
 | 
					# The version info for the project you're documenting, acts as replacement for
 | 
				
			||||||
# |version| and |release|, also used in various other places throughout the
 | 
					# |version| and |release|, also used in various other places throughout the
 | 
				
			||||||
@ -199,7 +260,7 @@ except ImportError:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# The name of an image file (relative to this directory) to place at the top
 | 
					# The name of an image file (relative to this directory) to place at the top
 | 
				
			||||||
# of the sidebar.
 | 
					# of the sidebar.
 | 
				
			||||||
html_logo = '../tools/logos/u-boot_logo.svg'
 | 
					#html_logo = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The name of an image file (within the static path) to use as favicon of the
 | 
					# The name of an image file (within the static path) to use as favicon of the
 | 
				
			||||||
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 | 
					# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 | 
				
			||||||
@ -229,7 +290,7 @@ html_context = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# If true, SmartyPants will be used to convert quotes and dashes to
 | 
					# If true, SmartyPants will be used to convert quotes and dashes to
 | 
				
			||||||
# typographically correct entities.
 | 
					# typographically correct entities.
 | 
				
			||||||
#html_use_smartypants = True
 | 
					html_use_smartypants = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Custom sidebar templates, maps document names to template names.
 | 
					# Custom sidebar templates, maps document names to template names.
 | 
				
			||||||
#html_sidebars = {}
 | 
					#html_sidebars = {}
 | 
				
			||||||
@ -279,7 +340,7 @@ html_context = {
 | 
				
			|||||||
#html_search_scorer = 'scorer.js'
 | 
					#html_search_scorer = 'scorer.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Output file base name for HTML help builder.
 | 
					# Output file base name for HTML help builder.
 | 
				
			||||||
htmlhelp_basename = 'TheUBootdoc'
 | 
					htmlhelp_basename = 'TheLinuxKerneldoc'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -- Options for LaTeX output ---------------------------------------------
 | 
					# -- Options for LaTeX output ---------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -288,7 +349,7 @@ latex_elements = {
 | 
				
			|||||||
'papersize': 'a4paper',
 | 
					'papersize': 'a4paper',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The font size ('10pt', '11pt' or '12pt').
 | 
					# The font size ('10pt', '11pt' or '12pt').
 | 
				
			||||||
'pointsize': '8pt',
 | 
					'pointsize': '11pt',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Latex figure (float) alignment
 | 
					# Latex figure (float) alignment
 | 
				
			||||||
#'figure_align': 'htbp',
 | 
					#'figure_align': 'htbp',
 | 
				
			||||||
@ -301,13 +362,24 @@ latex_elements = {
 | 
				
			|||||||
    'preamble': '''
 | 
					    'preamble': '''
 | 
				
			||||||
	% Use some font with UTF-8 support with XeLaTeX
 | 
						% Use some font with UTF-8 support with XeLaTeX
 | 
				
			||||||
        \\usepackage{fontspec}
 | 
					        \\usepackage{fontspec}
 | 
				
			||||||
        \\setsansfont{DejaVu Serif}
 | 
					        \\setsansfont{DejaVu Sans}
 | 
				
			||||||
        \\setromanfont{DejaVu Sans}
 | 
					        \\setromanfont{DejaVu Serif}
 | 
				
			||||||
        \\setmonofont{DejaVu Sans Mono}
 | 
					        \\setmonofont{DejaVu Sans Mono}
 | 
				
			||||||
 | 
					 | 
				
			||||||
     '''
 | 
					     '''
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# At least one book (translations) may have Asian characters
 | 
				
			||||||
 | 
					# with are only displayed if xeCJK is used
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cjk_cmd = check_output(['fc-list', '--format="%{family[0]}\n"']).decode('utf-8', 'ignore')
 | 
				
			||||||
 | 
					if cjk_cmd.find("Noto Sans CJK SC") >= 0:
 | 
				
			||||||
 | 
					    print ("enabling CJK for LaTeX builder")
 | 
				
			||||||
 | 
					    latex_elements['preamble']  += '''
 | 
				
			||||||
 | 
						% This is needed for translations
 | 
				
			||||||
 | 
					        \\usepackage{xeCJK}
 | 
				
			||||||
 | 
					        \\setCJKmainfont{Noto Sans CJK SC}
 | 
				
			||||||
 | 
					     '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Fix reference escape troubles with Sphinx 1.4.x
 | 
					# Fix reference escape troubles with Sphinx 1.4.x
 | 
				
			||||||
if major == 1 and minor > 3:
 | 
					if major == 1 and minor > 3:
 | 
				
			||||||
    latex_elements['preamble']  += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
 | 
					    latex_elements['preamble']  += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
 | 
				
			||||||
@ -398,10 +470,23 @@ if major == 1 and minor < 6:
 | 
				
			|||||||
#  author, documentclass [howto, manual, or own class]).
 | 
					#  author, documentclass [howto, manual, or own class]).
 | 
				
			||||||
# Sorted in alphabetical order
 | 
					# Sorted in alphabetical order
 | 
				
			||||||
latex_documents = [
 | 
					latex_documents = [
 | 
				
			||||||
    ('index', 'u-boot-hacker-manual.tex', 'U-Boot Hacker Manual',
 | 
					 | 
				
			||||||
     'The U-Boot development community', 'manual'),
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add all other index files from Documentation/ subdirectories
 | 
				
			||||||
 | 
					for fn in os.listdir('.'):
 | 
				
			||||||
 | 
					    doc = os.path.join(fn, "index")
 | 
				
			||||||
 | 
					    if os.path.exists(doc + ".rst"):
 | 
				
			||||||
 | 
					        has = False
 | 
				
			||||||
 | 
					        for l in latex_documents:
 | 
				
			||||||
 | 
					            if l[0] == doc:
 | 
				
			||||||
 | 
					                has = True
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					        if not has:
 | 
				
			||||||
 | 
					            latex_documents.append((doc, fn + '.tex',
 | 
				
			||||||
 | 
					                                    'Linux %s Documentation' % fn.capitalize(),
 | 
				
			||||||
 | 
					                                    'The kernel development community',
 | 
				
			||||||
 | 
					                                    'manual'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The name of an image file (relative to this directory) to place at the top of
 | 
					# The name of an image file (relative to this directory) to place at the top of
 | 
				
			||||||
# the title page.
 | 
					# the title page.
 | 
				
			||||||
#latex_logo = None
 | 
					#latex_logo = None
 | 
				
			||||||
@ -428,7 +513,7 @@ latex_documents = [
 | 
				
			|||||||
# One entry per manual page. List of tuples
 | 
					# One entry per manual page. List of tuples
 | 
				
			||||||
# (source start file, name, description, authors, manual section).
 | 
					# (source start file, name, description, authors, manual section).
 | 
				
			||||||
man_pages = [
 | 
					man_pages = [
 | 
				
			||||||
    (master_doc, 'dasuboot', 'The U-Boot Documentation',
 | 
					    (master_doc, 'thelinuxkernel', 'The Linux Kernel Documentation',
 | 
				
			||||||
     [author], 1)
 | 
					     [author], 1)
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -442,8 +527,8 @@ man_pages = [
 | 
				
			|||||||
# (source start file, target name, title, author,
 | 
					# (source start file, target name, title, author,
 | 
				
			||||||
#  dir menu entry, description, category)
 | 
					#  dir menu entry, description, category)
 | 
				
			||||||
texinfo_documents = [
 | 
					texinfo_documents = [
 | 
				
			||||||
    (master_doc, 'DasUBoot', 'The U-Boot Documentation',
 | 
					    (master_doc, 'TheLinuxKernel', 'The Linux Kernel Documentation',
 | 
				
			||||||
     author, 'DasUBoot', 'One line description of project.',
 | 
					     author, 'TheLinuxKernel', 'One line description of project.',
 | 
				
			||||||
     'Miscellaneous'),
 | 
					     'Miscellaneous'),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -535,13 +620,13 @@ epub_exclude_files = ['search.html']
 | 
				
			|||||||
# Grouping the document tree into PDF files. List of tuples
 | 
					# Grouping the document tree into PDF files. List of tuples
 | 
				
			||||||
# (source start file, target name, title, author, options).
 | 
					# (source start file, target name, title, author, options).
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# See the Sphinx chapter of http://ralsina.me/static/manual.pdf
 | 
					# See the Sphinx chapter of https://ralsina.me/static/manual.pdf
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# FIXME: Do not add the index file here; the result will be too big. Adding
 | 
					# FIXME: Do not add the index file here; the result will be too big. Adding
 | 
				
			||||||
# multiple PDF files here actually tries to get the cross-referencing right
 | 
					# multiple PDF files here actually tries to get the cross-referencing right
 | 
				
			||||||
# *between* PDF files.
 | 
					# *between* PDF files.
 | 
				
			||||||
pdf_documents = [
 | 
					pdf_documents = [
 | 
				
			||||||
    ('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'),
 | 
					    ('kernel-documentation', u'Kernel', u'Kernel', u'J. Random Bozo'),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
 | 
					# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										290
									
								
								doc/sphinx/automarkup.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								doc/sphinx/automarkup.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,290 @@
 | 
				
			|||||||
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					# Copyright 2019 Jonathan Corbet <corbet@lwn.net>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Apply kernel-specific tweaks after the initial document processing
 | 
				
			||||||
 | 
					# has been done.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					from docutils import nodes
 | 
				
			||||||
 | 
					import sphinx
 | 
				
			||||||
 | 
					from sphinx import addnodes
 | 
				
			||||||
 | 
					if sphinx.version_info[0] < 2 or \
 | 
				
			||||||
 | 
					   sphinx.version_info[0] == 2 and sphinx.version_info[1] < 1:
 | 
				
			||||||
 | 
					    from sphinx.environment import NoUri
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    from sphinx.errors import NoUri
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					from itertools import chain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Python 2 lacks re.ASCII...
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    ascii_p3 = re.ASCII
 | 
				
			||||||
 | 
					except AttributeError:
 | 
				
			||||||
 | 
					    ascii_p3 = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Regex nastiness.  Of course.
 | 
				
			||||||
 | 
					# Try to identify "function()" that's not already marked up some
 | 
				
			||||||
 | 
					# other way.  Sphinx doesn't like a lot of stuff right after a
 | 
				
			||||||
 | 
					# :c:func: block (i.e. ":c:func:`mmap()`s" flakes out), so the last
 | 
				
			||||||
 | 
					# bit tries to restrict matches to things that won't create trouble.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_function = re.compile(r'\b(([a-zA-Z_]\w+)\(\))', flags=ascii_p3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Sphinx 2 uses the same :c:type role for struct, union, enum and typedef
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_generic_type = re.compile(r'\b(struct|union|enum|typedef)\s+([a-zA-Z_]\w+)',
 | 
				
			||||||
 | 
					                             flags=ascii_p3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Sphinx 3 uses a different C role for each one of struct, union, enum and
 | 
				
			||||||
 | 
					# typedef
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_struct = re.compile(r'\b(struct)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
 | 
				
			||||||
 | 
					RE_union = re.compile(r'\b(union)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
 | 
				
			||||||
 | 
					RE_enum = re.compile(r'\b(enum)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
 | 
				
			||||||
 | 
					RE_typedef = re.compile(r'\b(typedef)\s+([a-zA-Z_]\w+)', flags=ascii_p3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Detects a reference to a documentation page of the form Documentation/... with
 | 
				
			||||||
 | 
					# an optional extension
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_doc = re.compile(r'\bDocumentation(/[\w\-_/]+)(\.\w+)*')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RE_namespace = re.compile(r'^\s*..\s*c:namespace::\s*(\S+)\s*$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Reserved C words that we should skip when cross-referencing
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					Skipnames = [ 'for', 'if', 'register', 'sizeof', 'struct', 'unsigned' ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many places in the docs refer to common system calls.  It is
 | 
				
			||||||
 | 
					# pointless to try to cross-reference them and, as has been known
 | 
				
			||||||
 | 
					# to happen, somebody defining a function by these names can lead
 | 
				
			||||||
 | 
					# to the creation of incorrect and confusing cross references.  So
 | 
				
			||||||
 | 
					# just don't even try with these names.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap',
 | 
				
			||||||
 | 
					              'select', 'poll', 'fork', 'execve', 'clone', 'ioctl',
 | 
				
			||||||
 | 
					              'socket' ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					c_namespace = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def markup_refs(docname, app, node):
 | 
				
			||||||
 | 
					    t = node.astext()
 | 
				
			||||||
 | 
					    done = 0
 | 
				
			||||||
 | 
					    repl = [ ]
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Associate each regex with the function that will markup its matches
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    markup_func_sphinx2 = {RE_doc: markup_doc_ref,
 | 
				
			||||||
 | 
					                           RE_function: markup_c_ref,
 | 
				
			||||||
 | 
					                           RE_generic_type: markup_c_ref}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    markup_func_sphinx3 = {RE_doc: markup_doc_ref,
 | 
				
			||||||
 | 
					                           RE_function: markup_func_ref_sphinx3,
 | 
				
			||||||
 | 
					                           RE_struct: markup_c_ref,
 | 
				
			||||||
 | 
					                           RE_union: markup_c_ref,
 | 
				
			||||||
 | 
					                           RE_enum: markup_c_ref,
 | 
				
			||||||
 | 
					                           RE_typedef: markup_c_ref}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if sphinx.version_info[0] >= 3:
 | 
				
			||||||
 | 
					        markup_func = markup_func_sphinx3
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        markup_func = markup_func_sphinx2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match_iterators = [regex.finditer(t) for regex in markup_func]
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Sort all references by the starting position in text
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    sorted_matches = sorted(chain(*match_iterators), key=lambda m: m.start())
 | 
				
			||||||
 | 
					    for m in sorted_matches:
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # Include any text prior to match as a normal text node.
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        if m.start() > done:
 | 
				
			||||||
 | 
					            repl.append(nodes.Text(t[done:m.start()]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # Call the function associated with the regex that matched this text and
 | 
				
			||||||
 | 
					        # append its return to the text
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        repl.append(markup_func[m.re](docname, app, m))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        done = m.end()
 | 
				
			||||||
 | 
					    if done < len(t):
 | 
				
			||||||
 | 
					        repl.append(nodes.Text(t[done:]))
 | 
				
			||||||
 | 
					    return repl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# In sphinx3 we can cross-reference to C macro and function, each one with its
 | 
				
			||||||
 | 
					# own C role, but both match the same regex, so we try both.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					def markup_func_ref_sphinx3(docname, app, match):
 | 
				
			||||||
 | 
					    class_str = ['c-func', 'c-macro']
 | 
				
			||||||
 | 
					    reftype_str = ['function', 'macro']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cdom = app.env.domains['c']
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Go through the dance of getting an xref out of the C domain
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    base_target = match.group(2)
 | 
				
			||||||
 | 
					    target_text = nodes.Text(match.group(0))
 | 
				
			||||||
 | 
					    xref = None
 | 
				
			||||||
 | 
					    possible_targets = [base_target]
 | 
				
			||||||
 | 
					    # Check if this document has a namespace, and if so, try
 | 
				
			||||||
 | 
					    # cross-referencing inside it first.
 | 
				
			||||||
 | 
					    if c_namespace:
 | 
				
			||||||
 | 
					        possible_targets.insert(0, c_namespace + "." + base_target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if base_target not in Skipnames:
 | 
				
			||||||
 | 
					        for target in possible_targets:
 | 
				
			||||||
 | 
					            if target not in Skipfuncs:
 | 
				
			||||||
 | 
					                for class_s, reftype_s in zip(class_str, reftype_str):
 | 
				
			||||||
 | 
					                    lit_text = nodes.literal(classes=['xref', 'c', class_s])
 | 
				
			||||||
 | 
					                    lit_text += target_text
 | 
				
			||||||
 | 
					                    pxref = addnodes.pending_xref('', refdomain = 'c',
 | 
				
			||||||
 | 
					                                                  reftype = reftype_s,
 | 
				
			||||||
 | 
					                                                  reftarget = target, modname = None,
 | 
				
			||||||
 | 
					                                                  classname = None)
 | 
				
			||||||
 | 
					                    #
 | 
				
			||||||
 | 
					                    # XXX The Latex builder will throw NoUri exceptions here,
 | 
				
			||||||
 | 
					                    # work around that by ignoring them.
 | 
				
			||||||
 | 
					                    #
 | 
				
			||||||
 | 
					                    try:
 | 
				
			||||||
 | 
					                        xref = cdom.resolve_xref(app.env, docname, app.builder,
 | 
				
			||||||
 | 
					                                                 reftype_s, target, pxref,
 | 
				
			||||||
 | 
					                                                 lit_text)
 | 
				
			||||||
 | 
					                    except NoUri:
 | 
				
			||||||
 | 
					                        xref = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if xref:
 | 
				
			||||||
 | 
					                        return xref
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return target_text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def markup_c_ref(docname, app, match):
 | 
				
			||||||
 | 
					    class_str = {# Sphinx 2 only
 | 
				
			||||||
 | 
					                 RE_function: 'c-func',
 | 
				
			||||||
 | 
					                 RE_generic_type: 'c-type',
 | 
				
			||||||
 | 
					                 # Sphinx 3+ only
 | 
				
			||||||
 | 
					                 RE_struct: 'c-struct',
 | 
				
			||||||
 | 
					                 RE_union: 'c-union',
 | 
				
			||||||
 | 
					                 RE_enum: 'c-enum',
 | 
				
			||||||
 | 
					                 RE_typedef: 'c-type',
 | 
				
			||||||
 | 
					                 }
 | 
				
			||||||
 | 
					    reftype_str = {# Sphinx 2 only
 | 
				
			||||||
 | 
					                   RE_function: 'function',
 | 
				
			||||||
 | 
					                   RE_generic_type: 'type',
 | 
				
			||||||
 | 
					                   # Sphinx 3+ only
 | 
				
			||||||
 | 
					                   RE_struct: 'struct',
 | 
				
			||||||
 | 
					                   RE_union: 'union',
 | 
				
			||||||
 | 
					                   RE_enum: 'enum',
 | 
				
			||||||
 | 
					                   RE_typedef: 'type',
 | 
				
			||||||
 | 
					                   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cdom = app.env.domains['c']
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Go through the dance of getting an xref out of the C domain
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    base_target = match.group(2)
 | 
				
			||||||
 | 
					    target_text = nodes.Text(match.group(0))
 | 
				
			||||||
 | 
					    xref = None
 | 
				
			||||||
 | 
					    possible_targets = [base_target]
 | 
				
			||||||
 | 
					    # Check if this document has a namespace, and if so, try
 | 
				
			||||||
 | 
					    # cross-referencing inside it first.
 | 
				
			||||||
 | 
					    if c_namespace:
 | 
				
			||||||
 | 
					        possible_targets.insert(0, c_namespace + "." + base_target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if base_target not in Skipnames:
 | 
				
			||||||
 | 
					        for target in possible_targets:
 | 
				
			||||||
 | 
					            if not (match.re == RE_function and target in Skipfuncs):
 | 
				
			||||||
 | 
					                lit_text = nodes.literal(classes=['xref', 'c', class_str[match.re]])
 | 
				
			||||||
 | 
					                lit_text += target_text
 | 
				
			||||||
 | 
					                pxref = addnodes.pending_xref('', refdomain = 'c',
 | 
				
			||||||
 | 
					                                              reftype = reftype_str[match.re],
 | 
				
			||||||
 | 
					                                              reftarget = target, modname = None,
 | 
				
			||||||
 | 
					                                              classname = None)
 | 
				
			||||||
 | 
					                #
 | 
				
			||||||
 | 
					                # XXX The Latex builder will throw NoUri exceptions here,
 | 
				
			||||||
 | 
					                # work around that by ignoring them.
 | 
				
			||||||
 | 
					                #
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    xref = cdom.resolve_xref(app.env, docname, app.builder,
 | 
				
			||||||
 | 
					                                             reftype_str[match.re], target, pxref,
 | 
				
			||||||
 | 
					                                             lit_text)
 | 
				
			||||||
 | 
					                except NoUri:
 | 
				
			||||||
 | 
					                    xref = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if xref:
 | 
				
			||||||
 | 
					                    return xref
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return target_text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Try to replace a documentation reference of the form Documentation/... with a
 | 
				
			||||||
 | 
					# cross reference to that page
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					def markup_doc_ref(docname, app, match):
 | 
				
			||||||
 | 
					    stddom = app.env.domains['std']
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Go through the dance of getting an xref out of the std domain
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    target = match.group(1)
 | 
				
			||||||
 | 
					    xref = None
 | 
				
			||||||
 | 
					    pxref = addnodes.pending_xref('', refdomain = 'std', reftype = 'doc',
 | 
				
			||||||
 | 
					                                  reftarget = target, modname = None,
 | 
				
			||||||
 | 
					                                  classname = None, refexplicit = False)
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # XXX The Latex builder will throw NoUri exceptions here,
 | 
				
			||||||
 | 
					    # work around that by ignoring them.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        xref = stddom.resolve_xref(app.env, docname, app.builder, 'doc',
 | 
				
			||||||
 | 
					                                   target, pxref, None)
 | 
				
			||||||
 | 
					    except NoUri:
 | 
				
			||||||
 | 
					        xref = None
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # Return the xref if we got it; otherwise just return the plain text.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    if xref:
 | 
				
			||||||
 | 
					        return xref
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return nodes.Text(match.group(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_c_namespace(app, docname):
 | 
				
			||||||
 | 
					    source = app.env.doc2path(docname)
 | 
				
			||||||
 | 
					    with open(source) as f:
 | 
				
			||||||
 | 
					        for l in f:
 | 
				
			||||||
 | 
					            match = RE_namespace.search(l)
 | 
				
			||||||
 | 
					            if match:
 | 
				
			||||||
 | 
					                return match.group(1)
 | 
				
			||||||
 | 
					    return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def auto_markup(app, doctree, name):
 | 
				
			||||||
 | 
					    global c_namespace
 | 
				
			||||||
 | 
					    c_namespace = get_c_namespace(app, name)
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # This loop could eventually be improved on.  Someday maybe we
 | 
				
			||||||
 | 
					    # want a proper tree traversal with a lot of awareness of which
 | 
				
			||||||
 | 
					    # kinds of nodes to prune.  But this works well for now.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # The nodes.literal test catches ``literal text``, its purpose is to
 | 
				
			||||||
 | 
					    # avoid adding cross-references to functions that have been explicitly
 | 
				
			||||||
 | 
					    # marked with cc:func:.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    for para in doctree.traverse(nodes.paragraph):
 | 
				
			||||||
 | 
					        for node in para.traverse(nodes.Text):
 | 
				
			||||||
 | 
					            if not isinstance(node.parent, nodes.literal):
 | 
				
			||||||
 | 
					                node.parent.replace(node, markup_refs(name, app, node))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(app):
 | 
				
			||||||
 | 
					    app.connect('doctree-resolved', auto_markup)
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        'parallel_read_safe': True,
 | 
				
			||||||
 | 
					        'parallel_write_safe': True,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
@ -40,14 +40,94 @@ from sphinx import addnodes
 | 
				
			|||||||
from sphinx.domains.c import c_funcptr_sig_re, c_sig_re
 | 
					from sphinx.domains.c import c_funcptr_sig_re, c_sig_re
 | 
				
			||||||
from sphinx.domains.c import CObject as Base_CObject
 | 
					from sphinx.domains.c import CObject as Base_CObject
 | 
				
			||||||
from sphinx.domains.c import CDomain as Base_CDomain
 | 
					from sphinx.domains.c import CDomain as Base_CDomain
 | 
				
			||||||
 | 
					from itertools import chain
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__  = '1.0'
 | 
					__version__  = '1.1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Get Sphinx version
 | 
					# Get Sphinx version
 | 
				
			||||||
major, minor, patch = sphinx.version_info[:3]
 | 
					major, minor, patch = sphinx.version_info[:3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Namespace to be prepended to the full name
 | 
				
			||||||
 | 
					namespace = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Handle trivial newer c domain tags that are part of Sphinx 3.1 c domain tags
 | 
				
			||||||
 | 
					# - Store the namespace if ".. c:namespace::" tag is found
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_namespace = re.compile(r'^\s*..\s*c:namespace::\s*(\S+)\s*$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def markup_namespace(match):
 | 
				
			||||||
 | 
					    global namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace = match.group(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Handle c:macro for function-style declaration
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_macro = re.compile(r'^\s*..\s*c:macro::\s*(\S+)\s+(\S.*)\s*$')
 | 
				
			||||||
 | 
					def markup_macro(match):
 | 
				
			||||||
 | 
					    return ".. c:function:: " + match.group(1) + ' ' + match.group(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Handle newer c domain tags that are evaluated as .. c:type: for
 | 
				
			||||||
 | 
					# backward-compatibility with Sphinx < 3.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_ctype = re.compile(r'^\s*..\s*c:(struct|union|enum|enumerator|alias)::\s*(.*)$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def markup_ctype(match):
 | 
				
			||||||
 | 
					    return ".. c:type:: " + match.group(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Handle newer c domain tags that are evaluated as :c:type: for
 | 
				
			||||||
 | 
					# backward-compatibility with Sphinx < 3.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_ctype_refs = re.compile(r':c:(var|struct|union|enum|enumerator)::`([^\`]+)`')
 | 
				
			||||||
 | 
					def markup_ctype_refs(match):
 | 
				
			||||||
 | 
					    return ":c:type:`" + match.group(2) + '`'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Simply convert :c:expr: and :c:texpr: into a literal block.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RE_expr = re.compile(r':c:(expr|texpr):`([^\`]+)`')
 | 
				
			||||||
 | 
					def markup_c_expr(match):
 | 
				
			||||||
 | 
					    return '\ ``' + match.group(2) + '``\ '
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Parse Sphinx 3.x C markups, replacing them by backward-compatible ones
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					def c_markups(app, docname, source):
 | 
				
			||||||
 | 
					    result = ""
 | 
				
			||||||
 | 
					    markup_func = {
 | 
				
			||||||
 | 
					        RE_namespace: markup_namespace,
 | 
				
			||||||
 | 
					        RE_expr: markup_c_expr,
 | 
				
			||||||
 | 
					        RE_macro: markup_macro,
 | 
				
			||||||
 | 
					        RE_ctype: markup_ctype,
 | 
				
			||||||
 | 
					        RE_ctype_refs: markup_ctype_refs,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lines = iter(source[0].splitlines(True))
 | 
				
			||||||
 | 
					    for n in lines:
 | 
				
			||||||
 | 
					        match_iterators = [regex.finditer(n) for regex in markup_func]
 | 
				
			||||||
 | 
					        matches = sorted(chain(*match_iterators), key=lambda m: m.start())
 | 
				
			||||||
 | 
					        for m in matches:
 | 
				
			||||||
 | 
					            n = n[:m.start()] + markup_func[m.re](m) + n[m.end():]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = result + n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source[0] = result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Now implements support for the cdomain namespacing logic
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup(app):
 | 
					def setup(app):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Handle easy Sphinx 3.1+ simple new tags: :c:expr and .. c:namespace::
 | 
				
			||||||
 | 
					    app.connect('source-read', c_markups)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (major == 1 and minor < 8):
 | 
					    if (major == 1 and minor < 8):
 | 
				
			||||||
        app.override_domain(CDomain)
 | 
					        app.override_domain(CDomain)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
@ -75,6 +155,8 @@ class CObject(Base_CObject):
 | 
				
			|||||||
        function-like macro, the name of the macro is returned. Otherwise
 | 
					        function-like macro, the name of the macro is returned. Otherwise
 | 
				
			||||||
        ``False`` is returned.  """
 | 
					        ``False`` is returned.  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        global namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not self.objtype == 'function':
 | 
					        if not self.objtype == 'function':
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,11 +189,16 @@ class CObject(Base_CObject):
 | 
				
			|||||||
            param += nodes.emphasis(argname, argname)
 | 
					            param += nodes.emphasis(argname, argname)
 | 
				
			||||||
            paramlist += param
 | 
					            paramlist += param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if namespace:
 | 
				
			||||||
 | 
					            fullname = namespace + "." + fullname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return fullname
 | 
					        return fullname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_signature(self, sig, signode):
 | 
					    def handle_signature(self, sig, signode):
 | 
				
			||||||
        """Transform a C signature into RST nodes."""
 | 
					        """Transform a C signature into RST nodes."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        global namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fullname = self.handle_func_like_macro(sig, signode)
 | 
					        fullname = self.handle_func_like_macro(sig, signode)
 | 
				
			||||||
        if not fullname:
 | 
					        if not fullname:
 | 
				
			||||||
            fullname = super(CObject, self).handle_signature(sig, signode)
 | 
					            fullname = super(CObject, self).handle_signature(sig, signode)
 | 
				
			||||||
@ -122,6 +209,10 @@ class CObject(Base_CObject):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # FIXME: handle :name: value of other declaration types?
 | 
					                # FIXME: handle :name: value of other declaration types?
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if namespace:
 | 
				
			||||||
 | 
					                fullname = namespace + "." + fullname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return fullname
 | 
					        return fullname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_target_and_index(self, name, sig, signode):
 | 
					    def add_target_and_index(self, name, sig, signode):
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										194
									
								
								doc/sphinx/kernel_abi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								doc/sphinx/kernel_abi.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,194 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8; mode: python -*-
 | 
				
			||||||
 | 
					# coding=utf-8
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					u"""
 | 
				
			||||||
 | 
					    kernel-abi
 | 
				
			||||||
 | 
					    ~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Implementation of the ``kernel-abi`` reST-directive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :copyright:  Copyright (C) 2016  Markus Heiser
 | 
				
			||||||
 | 
					    :copyright:  Copyright (C) 2016-2020  Mauro Carvalho Chehab
 | 
				
			||||||
 | 
					    :maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
 | 
				
			||||||
 | 
					    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
 | 
				
			||||||
 | 
					    scripts/get_abi.pl script to parse the Kernel ABI files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Overview of directive's argument and options.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. code-block:: rst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. kernel-abi:: <ABI directory location>
 | 
				
			||||||
 | 
					            :debug:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The argument ``<ABI directory location>`` is required. It contains the
 | 
				
			||||||
 | 
					    location of the ABI files to be parsed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ``debug``
 | 
				
			||||||
 | 
					      Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
 | 
				
			||||||
 | 
					      what reST is generated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import codecs
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import kernellog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from os import path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from docutils import nodes, statemachine
 | 
				
			||||||
 | 
					from docutils.statemachine import ViewList
 | 
				
			||||||
 | 
					from docutils.parsers.rst import directives, Directive
 | 
				
			||||||
 | 
					from docutils.utils.error_reporting import ErrorString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# AutodocReporter is only good up to Sphinx 1.7
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					import sphinx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use_SSI = sphinx.__version__[:3] >= '1.7'
 | 
				
			||||||
 | 
					if Use_SSI:
 | 
				
			||||||
 | 
					    from sphinx.util.docutils import switch_source_input
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    from sphinx.ext.autodoc import AutodocReporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__  = '1.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(app):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app.add_directive("kernel-abi", KernelCmd)
 | 
				
			||||||
 | 
					    return dict(
 | 
				
			||||||
 | 
					        version = __version__
 | 
				
			||||||
 | 
					        , parallel_read_safe = True
 | 
				
			||||||
 | 
					        , parallel_write_safe = True
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class KernelCmd(Directive):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u"""KernelABI (``kernel-abi``) directive"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    required_arguments = 1
 | 
				
			||||||
 | 
					    optional_arguments = 2
 | 
				
			||||||
 | 
					    has_content = False
 | 
				
			||||||
 | 
					    final_argument_whitespace = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    option_spec = {
 | 
				
			||||||
 | 
					        "debug"     : directives.flag,
 | 
				
			||||||
 | 
					        "rst"       : directives.unchanged
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        doc = self.state.document
 | 
				
			||||||
 | 
					        if not doc.settings.file_insertion_enabled:
 | 
				
			||||||
 | 
					            raise self.warning("docutils: file insertion disabled")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        env = doc.settings.env
 | 
				
			||||||
 | 
					        cwd = path.dirname(doc.current_source)
 | 
				
			||||||
 | 
					        cmd = "get_abi.pl rest --enable-lineno --dir "
 | 
				
			||||||
 | 
					        cmd += self.arguments[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'rst' in self.options:
 | 
				
			||||||
 | 
					            cmd += " --rst-source"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        srctree = path.abspath(os.environ["srctree"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fname = cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # extend PATH with $(srctree)/scripts
 | 
				
			||||||
 | 
					        path_env = os.pathsep.join([
 | 
				
			||||||
 | 
					            srctree + os.sep + "scripts",
 | 
				
			||||||
 | 
					            os.environ["PATH"]
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					        shell_env = os.environ.copy()
 | 
				
			||||||
 | 
					        shell_env["PATH"]    = path_env
 | 
				
			||||||
 | 
					        shell_env["srctree"] = srctree
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
 | 
				
			||||||
 | 
					        nodeList = self.nestedParse(lines, self.arguments[0])
 | 
				
			||||||
 | 
					        return nodeList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def runCmd(self, cmd, **kwargs):
 | 
				
			||||||
 | 
					        u"""Run command ``cmd`` and return it's stdout as unicode."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            proc = subprocess.Popen(
 | 
				
			||||||
 | 
					                cmd
 | 
				
			||||||
 | 
					                , stdout = subprocess.PIPE
 | 
				
			||||||
 | 
					                , stderr = subprocess.PIPE
 | 
				
			||||||
 | 
					                , **kwargs
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            out, err = proc.communicate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if proc.returncode != 0:
 | 
				
			||||||
 | 
					                raise self.severe(
 | 
				
			||||||
 | 
					                    u"command '%s' failed with return code %d"
 | 
				
			||||||
 | 
					                    % (cmd, proc.returncode)
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					        except OSError as exc:
 | 
				
			||||||
 | 
					            raise self.severe(u"problems with '%s' directive: %s."
 | 
				
			||||||
 | 
					                              % (self.name, ErrorString(exc)))
 | 
				
			||||||
 | 
					        return out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def nestedParse(self, lines, fname):
 | 
				
			||||||
 | 
					        content = ViewList()
 | 
				
			||||||
 | 
					        node = nodes.section()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if "debug" in self.options:
 | 
				
			||||||
 | 
					            code_block = "\n\n.. code-block:: rst\n    :linenos:\n"
 | 
				
			||||||
 | 
					            for l in lines.split("\n"):
 | 
				
			||||||
 | 
					                code_block += "\n    " + l
 | 
				
			||||||
 | 
					            lines = code_block + "\n\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        line_regex = re.compile("^#define LINENO (\S+)\#([0-9]+)$")
 | 
				
			||||||
 | 
					        ln = 0
 | 
				
			||||||
 | 
					        n = 0
 | 
				
			||||||
 | 
					        f = fname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for line in lines.split("\n"):
 | 
				
			||||||
 | 
					            n = n + 1
 | 
				
			||||||
 | 
					            match = line_regex.search(line)
 | 
				
			||||||
 | 
					            if match:
 | 
				
			||||||
 | 
					                new_f = match.group(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Sphinx parser is lazy: it stops parsing contents in the
 | 
				
			||||||
 | 
					                # middle, if it is too big. So, handle it per input file
 | 
				
			||||||
 | 
					                if new_f != f and content:
 | 
				
			||||||
 | 
					                    self.do_parse(content, node)
 | 
				
			||||||
 | 
					                    content = ViewList()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                f = new_f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # sphinx counts lines from 0
 | 
				
			||||||
 | 
					                ln = int(match.group(2)) - 1
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                content.append(line, f, ln)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if content:
 | 
				
			||||||
 | 
					            self.do_parse(content, node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return node.children
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def do_parse(self, content, node):
 | 
				
			||||||
 | 
					        if Use_SSI:
 | 
				
			||||||
 | 
					            with switch_source_input(self.state, content):
 | 
				
			||||||
 | 
					                self.state.nested_parse(content, 0, node, match_titles=1)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            buf  = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.state.memo.title_styles  = []
 | 
				
			||||||
 | 
					            self.state.memo.section_level = 0
 | 
				
			||||||
 | 
					            self.state.memo.reporter      = AutodocReporter(content, self.state.memo.reporter)
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                self.state.nested_parse(content, 0, node, match_titles=1)
 | 
				
			||||||
 | 
					            finally:
 | 
				
			||||||
 | 
					                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
 | 
				
			||||||
							
								
								
									
										169
									
								
								doc/sphinx/kernel_feat.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								doc/sphinx/kernel_feat.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					# coding=utf-8
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					u"""
 | 
				
			||||||
 | 
					    kernel-feat
 | 
				
			||||||
 | 
					    ~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Implementation of the ``kernel-feat`` reST-directive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :copyright:  Copyright (C) 2016  Markus Heiser
 | 
				
			||||||
 | 
					    :copyright:  Copyright (C) 2016-2019  Mauro Carvalho Chehab
 | 
				
			||||||
 | 
					    :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
 | 
				
			||||||
 | 
					    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
 | 
				
			||||||
 | 
					    scripts/get_feat.pl script to parse the Kernel ABI files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Overview of directive's argument and options.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. code-block:: rst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. kernel-feat:: <ABI directory location>
 | 
				
			||||||
 | 
					            :debug:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The argument ``<ABI directory location>`` is required. It contains the
 | 
				
			||||||
 | 
					    location of the ABI files to be parsed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ``debug``
 | 
				
			||||||
 | 
					      Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
 | 
				
			||||||
 | 
					      what reST is generated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import codecs
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from os import path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from docutils import nodes, statemachine
 | 
				
			||||||
 | 
					from docutils.statemachine import ViewList
 | 
				
			||||||
 | 
					from docutils.parsers.rst import directives, Directive
 | 
				
			||||||
 | 
					from docutils.utils.error_reporting import ErrorString
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# AutodocReporter is only good up to Sphinx 1.7
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					import sphinx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use_SSI = sphinx.__version__[:3] >= '1.7'
 | 
				
			||||||
 | 
					if Use_SSI:
 | 
				
			||||||
 | 
					    from sphinx.util.docutils import switch_source_input
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    from sphinx.ext.autodoc import AutodocReporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__  = '1.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(app):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    app.add_directive("kernel-feat", KernelFeat)
 | 
				
			||||||
 | 
					    return dict(
 | 
				
			||||||
 | 
					        version = __version__
 | 
				
			||||||
 | 
					        , parallel_read_safe = True
 | 
				
			||||||
 | 
					        , parallel_write_safe = True
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class KernelFeat(Directive):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u"""KernelFeat (``kernel-feat``) directive"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    required_arguments = 1
 | 
				
			||||||
 | 
					    optional_arguments = 2
 | 
				
			||||||
 | 
					    has_content = False
 | 
				
			||||||
 | 
					    final_argument_whitespace = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    option_spec = {
 | 
				
			||||||
 | 
					        "debug"     : directives.flag
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def warn(self, message, **replace):
 | 
				
			||||||
 | 
					        replace["fname"]   = self.state.document.current_source
 | 
				
			||||||
 | 
					        replace["line_no"] = replace.get("line_no", self.lineno)
 | 
				
			||||||
 | 
					        message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
 | 
				
			||||||
 | 
					        self.state.document.settings.env.app.warn(message, prefix="")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        doc = self.state.document
 | 
				
			||||||
 | 
					        if not doc.settings.file_insertion_enabled:
 | 
				
			||||||
 | 
					            raise self.warning("docutils: file insertion disabled")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        env = doc.settings.env
 | 
				
			||||||
 | 
					        cwd = path.dirname(doc.current_source)
 | 
				
			||||||
 | 
					        cmd = "get_feat.pl rest --dir "
 | 
				
			||||||
 | 
					        cmd += self.arguments[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(self.arguments) > 1:
 | 
				
			||||||
 | 
					            cmd += " --arch " + self.arguments[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        srctree = path.abspath(os.environ["srctree"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fname = cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # extend PATH with $(srctree)/scripts
 | 
				
			||||||
 | 
					        path_env = os.pathsep.join([
 | 
				
			||||||
 | 
					            srctree + os.sep + "scripts",
 | 
				
			||||||
 | 
					            os.environ["PATH"]
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					        shell_env = os.environ.copy()
 | 
				
			||||||
 | 
					        shell_env["PATH"]    = path_env
 | 
				
			||||||
 | 
					        shell_env["srctree"] = srctree
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
 | 
				
			||||||
 | 
					        nodeList = self.nestedParse(lines, fname)
 | 
				
			||||||
 | 
					        return nodeList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def runCmd(self, cmd, **kwargs):
 | 
				
			||||||
 | 
					        u"""Run command ``cmd`` and return it's stdout as unicode."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            proc = subprocess.Popen(
 | 
				
			||||||
 | 
					                cmd
 | 
				
			||||||
 | 
					                , stdout = subprocess.PIPE
 | 
				
			||||||
 | 
					                , stderr = subprocess.PIPE
 | 
				
			||||||
 | 
					                , **kwargs
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            out, err = proc.communicate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if proc.returncode != 0:
 | 
				
			||||||
 | 
					                raise self.severe(
 | 
				
			||||||
 | 
					                    u"command '%s' failed with return code %d"
 | 
				
			||||||
 | 
					                    % (cmd, proc.returncode)
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					        except OSError as exc:
 | 
				
			||||||
 | 
					            raise self.severe(u"problems with '%s' directive: %s."
 | 
				
			||||||
 | 
					                              % (self.name, ErrorString(exc)))
 | 
				
			||||||
 | 
					        return out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def nestedParse(self, lines, fname):
 | 
				
			||||||
 | 
					        content = ViewList()
 | 
				
			||||||
 | 
					        node    = nodes.section()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if "debug" in self.options:
 | 
				
			||||||
 | 
					            code_block = "\n\n.. code-block:: rst\n    :linenos:\n"
 | 
				
			||||||
 | 
					            for l in lines.split("\n"):
 | 
				
			||||||
 | 
					                code_block += "\n    " + l
 | 
				
			||||||
 | 
					            lines = code_block + "\n\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for c, l in enumerate(lines.split("\n")):
 | 
				
			||||||
 | 
					            content.append(l, fname, c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buf  = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if Use_SSI:
 | 
				
			||||||
 | 
					            with switch_source_input(self.state, content):
 | 
				
			||||||
 | 
					                self.state.nested_parse(content, 0, node, match_titles=1)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.state.memo.title_styles  = []
 | 
				
			||||||
 | 
					            self.state.memo.section_level = 0
 | 
				
			||||||
 | 
					            self.state.memo.reporter      = AutodocReporter(content, self.state.memo.reporter)
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                self.state.nested_parse(content, 0, node, match_titles=1)
 | 
				
			||||||
 | 
					            finally:
 | 
				
			||||||
 | 
					                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return node.children
 | 
				
			||||||
@ -62,6 +62,7 @@ class KernelDocDirective(Directive):
 | 
				
			|||||||
        'export': directives.unchanged,
 | 
					        'export': directives.unchanged,
 | 
				
			||||||
        'internal': directives.unchanged,
 | 
					        'internal': directives.unchanged,
 | 
				
			||||||
        'identifiers': directives.unchanged,
 | 
					        'identifiers': directives.unchanged,
 | 
				
			||||||
 | 
					        'no-identifiers': directives.unchanged,
 | 
				
			||||||
        'functions': directives.unchanged,
 | 
					        'functions': directives.unchanged,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    has_content = False
 | 
					    has_content = False
 | 
				
			||||||
@ -70,6 +71,11 @@ class KernelDocDirective(Directive):
 | 
				
			|||||||
        env = self.state.document.settings.env
 | 
					        env = self.state.document.settings.env
 | 
				
			||||||
        cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
 | 
					        cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Pass the version string to kernel-doc, as it needs to use a different
 | 
				
			||||||
 | 
						# dialect, depending what the C domain supports for each specific
 | 
				
			||||||
 | 
						# Sphinx versions
 | 
				
			||||||
 | 
					        cmd += ['-sphinx-version', sphinx.__version__]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
 | 
					        filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
 | 
				
			||||||
        export_file_patterns = []
 | 
					        export_file_patterns = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,6 +105,12 @@ class KernelDocDirective(Directive):
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                cmd += ['-no-doc-sections']
 | 
					                cmd += ['-no-doc-sections']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'no-identifiers' in self.options:
 | 
				
			||||||
 | 
					            no_identifiers = self.options.get('no-identifiers').split()
 | 
				
			||||||
 | 
					            if no_identifiers:
 | 
				
			||||||
 | 
					                for i in no_identifiers:
 | 
				
			||||||
 | 
					                    cmd += ['-nosymbol', i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for pattern in export_file_patterns:
 | 
					        for pattern in export_file_patterns:
 | 
				
			||||||
            for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
 | 
					            for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
 | 
				
			||||||
                env.note_dependency(os.path.abspath(f))
 | 
					                env.note_dependency(os.path.abspath(f))
 | 
				
			||||||
@ -136,7 +148,8 @@ class KernelDocDirective(Directive):
 | 
				
			|||||||
                    lineoffset = int(match.group(1)) - 1
 | 
					                    lineoffset = int(match.group(1)) - 1
 | 
				
			||||||
                    # we must eat our comments since the upset the markup
 | 
					                    # we must eat our comments since the upset the markup
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    result.append(line, filename, lineoffset)
 | 
					                    doc = env.srcdir + "/" + env.docname + ":" + str(self.lineno)
 | 
				
			||||||
 | 
					                    result.append(line, doc + ": " + filename, lineoffset)
 | 
				
			||||||
                    lineoffset += 1
 | 
					                    lineoffset += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            node = nodes.section()
 | 
					            node = nodes.section()
 | 
				
			||||||
 | 
				
			|||||||
@ -25,4 +25,8 @@ def verbose(app, message):
 | 
				
			|||||||
    else:
 | 
					    else:
 | 
				
			||||||
        app.verbose(message)
 | 
					        app.verbose(message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def info(app, message):
 | 
				
			||||||
 | 
					    if UseLogging:
 | 
				
			||||||
 | 
					        logger.info(message)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        app.info(message)
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ u"""
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Used tools:
 | 
					    Used tools:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not
 | 
					    * ``dot(1)``: Graphviz (https://www.graphviz.org). If Graphviz is not
 | 
				
			||||||
      available, the DOT language is inserted as literal-block.
 | 
					      available, the DOT language is inserted as literal-block.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * SVG to PDF: To generate PDF, you need at least one of this tools:
 | 
					    * SVG to PDF: To generate PDF, you need at least one of this tools:
 | 
				
			||||||
@ -41,7 +41,7 @@ u"""
 | 
				
			|||||||
    * generate PDF from SVG / used by PDF (LaTeX) builder
 | 
					    * generate PDF from SVG / used by PDF (LaTeX) builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * generate SVG (html-builder) and PDF (latex-builder) from DOT files.
 | 
					    * generate SVG (html-builder) and PDF (latex-builder) from DOT files.
 | 
				
			||||||
      DOT: see http://www.graphviz.org/content/dot-language
 | 
					      DOT: see https://www.graphviz.org/content/dot-language
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -182,7 +182,7 @@ def setupTools(app):
 | 
				
			|||||||
        kernellog.verbose(app, "use dot(1) from: " + dot_cmd)
 | 
					        kernellog.verbose(app, "use dot(1) from: " + dot_cmd)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        kernellog.warn(app, "dot(1) not found, for better output quality install "
 | 
					        kernellog.warn(app, "dot(1) not found, for better output quality install "
 | 
				
			||||||
                       "graphviz from http://www.graphviz.org")
 | 
					                       "graphviz from https://www.graphviz.org")
 | 
				
			||||||
    if convert_cmd:
 | 
					    if convert_cmd:
 | 
				
			||||||
        kernellog.verbose(app, "use convert(1) from: " + convert_cmd)
 | 
					        kernellog.verbose(app, "use convert(1) from: " + convert_cmd)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,29 @@ def loadConfig(namespace):
 | 
				
			|||||||
        and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
 | 
					        and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
 | 
				
			||||||
        config_file = os.path.abspath(config_file)
 | 
					        config_file = os.path.abspath(config_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Let's avoid one conf.py file just due to latex_documents
 | 
				
			||||||
 | 
					        start = config_file.find('Documentation/')
 | 
				
			||||||
 | 
					        if start >= 0:
 | 
				
			||||||
 | 
					            start = config_file.find('/', start + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        end = config_file.rfind('/')
 | 
				
			||||||
 | 
					        if start >= 0 and end > 0:
 | 
				
			||||||
 | 
					            dir = config_file[start + 1:end]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print("source directory: %s" % dir)
 | 
				
			||||||
 | 
					            new_latex_docs = []
 | 
				
			||||||
 | 
					            latex_documents = namespace['latex_documents']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for l in latex_documents:
 | 
				
			||||||
 | 
					                if l[0].find(dir + '/') == 0:
 | 
				
			||||||
 | 
					                    has = True
 | 
				
			||||||
 | 
					                    fn = l[0][len(dir) + 1:]
 | 
				
			||||||
 | 
					                    new_latex_docs.append((fn, l[1], l[2], l[3], l[4]))
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            namespace['latex_documents'] = new_latex_docs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If there is an extra conf.py file, load it
 | 
				
			||||||
        if os.path.isfile(config_file):
 | 
					        if os.path.isfile(config_file):
 | 
				
			||||||
            sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
 | 
					            sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
 | 
				
			||||||
            config = namespace.copy()
 | 
					            config = namespace.copy()
 | 
				
			||||||
@ -29,4 +52,6 @@ def loadConfig(namespace):
 | 
				
			|||||||
            del config['__file__']
 | 
					            del config['__file__']
 | 
				
			||||||
            namespace.update(config)
 | 
					            namespace.update(config)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
 | 
					            config = namespace.copy()
 | 
				
			||||||
 | 
					            config['tags'].add("subproject")
 | 
				
			||||||
 | 
					            namespace.update(config)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										197
									
								
								doc/sphinx/maintainers_include.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										197
									
								
								doc/sphinx/maintainers_include.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					# -*- coding: utf-8; mode: python -*-
 | 
				
			||||||
 | 
					# pylint: disable=R0903, C0330, R0914, R0912, E0401
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u"""
 | 
				
			||||||
 | 
					    maintainers-include
 | 
				
			||||||
 | 
					    ~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Implementation of the ``maintainers-include`` reST-directive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :copyright:  Copyright (C) 2019  Kees Cook <keescook@chromium.org>
 | 
				
			||||||
 | 
					    :license:    GPL Version 2, June 1991 see linux/COPYING for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The ``maintainers-include`` reST-directive performs extensive parsing
 | 
				
			||||||
 | 
					    specific to the Linux kernel's standard "MAINTAINERS" file, in an
 | 
				
			||||||
 | 
					    effort to avoid needing to heavily mark up the original plain text.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import os.path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from docutils import statemachine
 | 
				
			||||||
 | 
					from docutils.utils.error_reporting import ErrorString
 | 
				
			||||||
 | 
					from docutils.parsers.rst import Directive
 | 
				
			||||||
 | 
					from docutils.parsers.rst.directives.misc import Include
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__  = '1.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(app):
 | 
				
			||||||
 | 
					    app.add_directive("maintainers-include", MaintainersInclude)
 | 
				
			||||||
 | 
					    return dict(
 | 
				
			||||||
 | 
					        version = __version__,
 | 
				
			||||||
 | 
					        parallel_read_safe = True,
 | 
				
			||||||
 | 
					        parallel_write_safe = True
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MaintainersInclude(Include):
 | 
				
			||||||
 | 
					    u"""MaintainersInclude (``maintainers-include``) directive"""
 | 
				
			||||||
 | 
					    required_arguments = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def parse_maintainers(self, path):
 | 
				
			||||||
 | 
					        """Parse all the MAINTAINERS lines into ReST for human-readability"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = list()
 | 
				
			||||||
 | 
					        result.append(".. _maintainers:")
 | 
				
			||||||
 | 
					        result.append("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Poor man's state machine.
 | 
				
			||||||
 | 
					        descriptions = False
 | 
				
			||||||
 | 
					        maintainers = False
 | 
				
			||||||
 | 
					        subsystems = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Field letter to field name mapping.
 | 
				
			||||||
 | 
					        field_letter = None
 | 
				
			||||||
 | 
					        fields = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        prev = None
 | 
				
			||||||
 | 
					        field_prev = ""
 | 
				
			||||||
 | 
					        field_content = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for line in open(path):
 | 
				
			||||||
 | 
					            if sys.version_info.major == 2:
 | 
				
			||||||
 | 
					                line = unicode(line, 'utf-8')
 | 
				
			||||||
 | 
					            # Have we reached the end of the preformatted Descriptions text?
 | 
				
			||||||
 | 
					            if descriptions and line.startswith('Maintainers'):
 | 
				
			||||||
 | 
					                descriptions = False
 | 
				
			||||||
 | 
					                # Ensure a blank line following the last "|"-prefixed line.
 | 
				
			||||||
 | 
					                result.append("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Start subsystem processing? This is to skip processing the text
 | 
				
			||||||
 | 
					            # between the Maintainers heading and the first subsystem name.
 | 
				
			||||||
 | 
					            if maintainers and not subsystems:
 | 
				
			||||||
 | 
					                if re.search('^[A-Z0-9]', line):
 | 
				
			||||||
 | 
					                    subsystems = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Drop needless input whitespace.
 | 
				
			||||||
 | 
					            line = line.rstrip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Linkify all non-wildcard refs to ReST files in Documentation/.
 | 
				
			||||||
 | 
					            pat = '(Documentation/([^\s\?\*]*)\.rst)'
 | 
				
			||||||
 | 
					            m = re.search(pat, line)
 | 
				
			||||||
 | 
					            if m:
 | 
				
			||||||
 | 
					                # maintainers.rst is in a subdirectory, so include "../".
 | 
				
			||||||
 | 
					                line = re.sub(pat, ':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Check state machine for output rendering behavior.
 | 
				
			||||||
 | 
					            output = None
 | 
				
			||||||
 | 
					            if descriptions:
 | 
				
			||||||
 | 
					                # Escape the escapes in preformatted text.
 | 
				
			||||||
 | 
					                output = "| %s" % (line.replace("\\", "\\\\"))
 | 
				
			||||||
 | 
					                # Look for and record field letter to field name mappings:
 | 
				
			||||||
 | 
					                #   R: Designated *reviewer*: FullName <address@domain>
 | 
				
			||||||
 | 
					                m = re.search("\s(\S):\s", line)
 | 
				
			||||||
 | 
					                if m:
 | 
				
			||||||
 | 
					                    field_letter = m.group(1)
 | 
				
			||||||
 | 
					                if field_letter and not field_letter in fields:
 | 
				
			||||||
 | 
					                    m = re.search("\*([^\*]+)\*", line)
 | 
				
			||||||
 | 
					                    if m:
 | 
				
			||||||
 | 
					                        fields[field_letter] = m.group(1)
 | 
				
			||||||
 | 
					            elif subsystems:
 | 
				
			||||||
 | 
					                # Skip empty lines: subsystem parser adds them as needed.
 | 
				
			||||||
 | 
					                if len(line) == 0:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                # Subsystem fields are batched into "field_content"
 | 
				
			||||||
 | 
					                if line[1] != ':':
 | 
				
			||||||
 | 
					                    # Render a subsystem entry as:
 | 
				
			||||||
 | 
					                    #   SUBSYSTEM NAME
 | 
				
			||||||
 | 
					                    #   ~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Flush pending field content.
 | 
				
			||||||
 | 
					                    output = field_content + "\n\n"
 | 
				
			||||||
 | 
					                    field_content = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Collapse whitespace in subsystem name.
 | 
				
			||||||
 | 
					                    heading = re.sub("\s+", " ", line)
 | 
				
			||||||
 | 
					                    output = output + "%s\n%s" % (heading, "~" * len(heading))
 | 
				
			||||||
 | 
					                    field_prev = ""
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    # Render a subsystem field as:
 | 
				
			||||||
 | 
					                    #   :Field: entry
 | 
				
			||||||
 | 
					                    #           entry...
 | 
				
			||||||
 | 
					                    field, details = line.split(':', 1)
 | 
				
			||||||
 | 
					                    details = details.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Mark paths (and regexes) as literal text for improved
 | 
				
			||||||
 | 
					                    # readability and to escape any escapes.
 | 
				
			||||||
 | 
					                    if field in ['F', 'N', 'X', 'K']:
 | 
				
			||||||
 | 
					                        # But only if not already marked :)
 | 
				
			||||||
 | 
					                        if not ':doc:' in details:
 | 
				
			||||||
 | 
					                            details = '``%s``' % (details)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Comma separate email field continuations.
 | 
				
			||||||
 | 
					                    if field == field_prev and field_prev in ['M', 'R', 'L']:
 | 
				
			||||||
 | 
					                        field_content = field_content + ","
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # Do not repeat field names, so that field entries
 | 
				
			||||||
 | 
					                    # will be collapsed together.
 | 
				
			||||||
 | 
					                    if field != field_prev:
 | 
				
			||||||
 | 
					                        output = field_content + "\n"
 | 
				
			||||||
 | 
					                        field_content = ":%s:" % (fields.get(field, field))
 | 
				
			||||||
 | 
					                    field_content = field_content + "\n\t%s" % (details)
 | 
				
			||||||
 | 
					                    field_prev = field
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                output = line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Re-split on any added newlines in any above parsing.
 | 
				
			||||||
 | 
					            if output != None:
 | 
				
			||||||
 | 
					                for separated in output.split('\n'):
 | 
				
			||||||
 | 
					                    result.append(separated)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Update the state machine when we find heading separators.
 | 
				
			||||||
 | 
					            if line.startswith('----------'):
 | 
				
			||||||
 | 
					                if prev.startswith('Descriptions'):
 | 
				
			||||||
 | 
					                    descriptions = True
 | 
				
			||||||
 | 
					                if prev.startswith('Maintainers'):
 | 
				
			||||||
 | 
					                    maintainers = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Retain previous line for state machine transitions.
 | 
				
			||||||
 | 
					            prev = line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Flush pending field contents.
 | 
				
			||||||
 | 
					        if field_content != "":
 | 
				
			||||||
 | 
					            for separated in field_content.split('\n'):
 | 
				
			||||||
 | 
					                result.append(separated)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        output = "\n".join(result)
 | 
				
			||||||
 | 
					        # For debugging the pre-rendered results...
 | 
				
			||||||
 | 
					        #print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.state_machine.insert_input(
 | 
				
			||||||
 | 
					          statemachine.string2lines(output), path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        """Include the MAINTAINERS file as part of this reST file."""
 | 
				
			||||||
 | 
					        if not self.state.document.settings.file_insertion_enabled:
 | 
				
			||||||
 | 
					            raise self.warning('"%s" directive disabled.' % self.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Walk up source path directories to find Documentation/../
 | 
				
			||||||
 | 
					        path = self.state_machine.document.attributes['source']
 | 
				
			||||||
 | 
					        path = os.path.realpath(path)
 | 
				
			||||||
 | 
					        tail = path
 | 
				
			||||||
 | 
					        while tail != "Documentation" and tail != "":
 | 
				
			||||||
 | 
					            (path, tail) = os.path.split(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Append "MAINTAINERS"
 | 
				
			||||||
 | 
					        path = os.path.join(path, "MAINTAINERS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.state.document.settings.record_dependencies.add(path)
 | 
				
			||||||
 | 
					            lines = self.parse_maintainers(path)
 | 
				
			||||||
 | 
					        except IOError as error:
 | 
				
			||||||
 | 
					            raise self.severe('Problems with "%s" directive path:\n%s.' %
 | 
				
			||||||
 | 
					                      (self.name, ErrorString(error)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
							
								
								
									
										33
									
								
								doc/sphinx/parallel-wrapper.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								doc/sphinx/parallel-wrapper.sh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: GPL-2.0+
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Figure out if we should follow a specific parallelism from the make
 | 
				
			||||||
 | 
					# environment (as exported by scripts/jobserver-exec), or fall back to
 | 
				
			||||||
 | 
					# the "auto" parallelism when "-jN" is not specified at the top-level
 | 
				
			||||||
 | 
					# "make" invocation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sphinx="$1"
 | 
				
			||||||
 | 
					shift || true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parallel="$PARALLELISM"
 | 
				
			||||||
 | 
					if [ -z "$parallel" ] ; then
 | 
				
			||||||
 | 
						# If no parallelism is specified at the top-level make, then
 | 
				
			||||||
 | 
						# fall back to the expected "-jauto" mode that the "htmldocs"
 | 
				
			||||||
 | 
						# target has had.
 | 
				
			||||||
 | 
						auto=$(perl -e 'open IN,"'"$sphinx"' --version 2>&1 |";
 | 
				
			||||||
 | 
								while (<IN>) {
 | 
				
			||||||
 | 
									if (m/([\d\.]+)/) {
 | 
				
			||||||
 | 
										print "auto" if ($1 >= "1.7")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								close IN')
 | 
				
			||||||
 | 
						if [ -n "$auto" ] ; then
 | 
				
			||||||
 | 
							parallel="$auto"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					# Only if some parallelism has been determined do we add the -jN option.
 | 
				
			||||||
 | 
					if [ -n "$parallel" ] ; then
 | 
				
			||||||
 | 
						parallel="-j$parallel"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec "$sphinx" $parallel "$@"
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
#!/usr/bin/perl
 | 
					#!/usr/bin/env perl
 | 
				
			||||||
use strict;
 | 
					use strict;
 | 
				
			||||||
use Text::Tabs;
 | 
					use Text::Tabs;
 | 
				
			||||||
use Getopt::Long;
 | 
					use Getopt::Long;
 | 
				
			||||||
@ -110,7 +110,7 @@ while (<IN>) {
 | 
				
			|||||||
	    ) {
 | 
						    ) {
 | 
				
			||||||
		my $s = $1;
 | 
							my $s = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$structs{$s} = "struct :c:type:`$s`\\ ";
 | 
							$structs{$s} = "struct $s\\ ";
 | 
				
			||||||
		next;
 | 
							next;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -393,7 +393,7 @@ Report bugs to Mauro Carvalho Chehab <mchehab@kernel.org>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
 | 
					Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
 | 
					License GPLv2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is free software: you are free to change and redistribute it.
 | 
					This is free software: you are free to change and redistribute it.
 | 
				
			||||||
There is NO WARRANTY, to the extent permitted by law.
 | 
					There is NO WARRANTY, to the extent permitted by law.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
docutils==0.12
 | 
					docutils
 | 
				
			||||||
Sphinx==1.4.9
 | 
					Sphinx==2.4.4
 | 
				
			||||||
sphinx_rtd_theme
 | 
					sphinx_rtd_theme
 | 
				
			||||||
 | 
					six
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,13 @@ Output format selection (mutually exclusive):
 | 
				
			|||||||
  -rst			Output reStructuredText format.
 | 
					  -rst			Output reStructuredText format.
 | 
				
			||||||
  -none			Do not output documentation, only warnings.
 | 
					  -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):
 | 
					Output selection (mutually exclusive):
 | 
				
			||||||
  -export		Only output documentation for symbols that have been
 | 
					  -export		Only output documentation for symbols that have been
 | 
				
			||||||
			exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
 | 
								exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
 | 
				
			||||||
@ -66,9 +73,8 @@ Output selection (mutually exclusive):
 | 
				
			|||||||
  -function NAME	Only output documentation for the given function(s)
 | 
					  -function NAME	Only output documentation for the given function(s)
 | 
				
			||||||
			or DOC: section title(s). All other functions and DOC:
 | 
								or DOC: section title(s). All other functions and DOC:
 | 
				
			||||||
			sections are ignored. May be specified multiple times.
 | 
								sections are ignored. May be specified multiple times.
 | 
				
			||||||
  -nofunction NAME	Do NOT output documentation for the given function(s);
 | 
					  -nosymbol NAME	Exclude the specified symbols from the output
 | 
				
			||||||
			only output documentation for the other functions and
 | 
							        documentation. May be specified multiple times.
 | 
				
			||||||
			DOC: sections. May be specified multiple times.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Output selection modifiers:
 | 
					Output selection modifiers:
 | 
				
			||||||
  -no-doc-sections	Do not output DOC: sections.
 | 
					  -no-doc-sections	Do not output DOC: sections.
 | 
				
			||||||
@ -81,6 +87,7 @@ Output selection modifiers:
 | 
				
			|||||||
Other parameters:
 | 
					Other parameters:
 | 
				
			||||||
  -v			Verbose output, more warnings and other information.
 | 
					  -v			Verbose output, more warnings and other information.
 | 
				
			||||||
  -h			Print this help.
 | 
					  -h			Print this help.
 | 
				
			||||||
 | 
					  -Werror		Treat warnings as errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
    print $message;
 | 
					    print $message;
 | 
				
			||||||
@ -213,7 +220,9 @@ my $type_constant = '\b``([^\`]+)``\b';
 | 
				
			|||||||
my $type_constant2 = '\%([-_\w]+)';
 | 
					my $type_constant2 = '\%([-_\w]+)';
 | 
				
			||||||
my $type_func = '(\w+)\(\)';
 | 
					my $type_func = '(\w+)\(\)';
 | 
				
			||||||
my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
 | 
					my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
 | 
				
			||||||
 | 
					my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)';
 | 
				
			||||||
my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
 | 
					my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
 | 
				
			||||||
 | 
					my $type_fp_param2 = '\@(\w+->\S+)\(\)';  # Special RST handling for structs with func ptr params
 | 
				
			||||||
my $type_env = '(\$\w+)';
 | 
					my $type_env = '(\$\w+)';
 | 
				
			||||||
my $type_enum = '\&(enum\s*([_\w]+))';
 | 
					my $type_enum = '\&(enum\s*([_\w]+))';
 | 
				
			||||||
my $type_struct = '\&(struct\s*([_\w]+))';
 | 
					my $type_struct = '\&(struct\s*([_\w]+))';
 | 
				
			||||||
@ -236,6 +245,7 @@ my @highlights_man = (
 | 
				
			|||||||
                      [$type_typedef, "\\\\fI\$1\\\\fP"],
 | 
					                      [$type_typedef, "\\\\fI\$1\\\\fP"],
 | 
				
			||||||
                      [$type_union, "\\\\fI\$1\\\\fP"],
 | 
					                      [$type_union, "\\\\fI\$1\\\\fP"],
 | 
				
			||||||
                      [$type_param, "\\\\fI\$1\\\\fP"],
 | 
					                      [$type_param, "\\\\fI\$1\\\\fP"],
 | 
				
			||||||
 | 
					                      [$type_param_ref, "\\\\fI\$1\$2\\\\fP"],
 | 
				
			||||||
                      [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 | 
					                      [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 | 
				
			||||||
                      [$type_fallback, "\\\\fI\$1\\\\fP"]
 | 
					                      [$type_fallback, "\\\\fI\$1\\\\fP"]
 | 
				
			||||||
		     );
 | 
							     );
 | 
				
			||||||
@ -249,14 +259,15 @@ my @highlights_rst = (
 | 
				
			|||||||
                       [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
 | 
					                       [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
 | 
				
			||||||
                       [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
 | 
					                       [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
 | 
				
			||||||
		       [$type_fp_param, "**\$1\\\\(\\\\)**"],
 | 
							       [$type_fp_param, "**\$1\\\\(\\\\)**"],
 | 
				
			||||||
                       [$type_func, "\\:c\\:func\\:`\$1()`"],
 | 
							       [$type_fp_param2, "**\$1\\\\(\\\\)**"],
 | 
				
			||||||
 | 
					                       [$type_func, "\$1()"],
 | 
				
			||||||
                       [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
					                       [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
				
			||||||
                       [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
					                       [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
				
			||||||
                       [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
					                       [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
				
			||||||
                       [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
					                       [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
 | 
				
			||||||
                       # in rst this can refer to any type
 | 
					                       # in rst this can refer to any type
 | 
				
			||||||
                       [$type_fallback, "\\:c\\:type\\:`\$1`"],
 | 
					                       [$type_fallback, "\\:c\\:type\\:`\$1`"],
 | 
				
			||||||
                       [$type_param, "**\$1**"]
 | 
					                       [$type_param_ref, "**\$1\$2**"]
 | 
				
			||||||
		      );
 | 
							      );
 | 
				
			||||||
my $blankline_rst = "\n";
 | 
					my $blankline_rst = "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -266,9 +277,12 @@ if ($#ARGV == -1) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my $kernelversion;
 | 
					my $kernelversion;
 | 
				
			||||||
 | 
					my ($sphinx_major, $sphinx_minor, $sphinx_patch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my $dohighlight = "";
 | 
					my $dohighlight = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my $verbose = 0;
 | 
					my $verbose = 0;
 | 
				
			||||||
 | 
					my $Werror = 0;
 | 
				
			||||||
my $output_mode = "rst";
 | 
					my $output_mode = "rst";
 | 
				
			||||||
my $output_preformatted = 0;
 | 
					my $output_preformatted = 0;
 | 
				
			||||||
my $no_doc_sections = 0;
 | 
					my $no_doc_sections = 0;
 | 
				
			||||||
@ -280,12 +294,11 @@ my $modulename = "Kernel API";
 | 
				
			|||||||
use constant {
 | 
					use constant {
 | 
				
			||||||
    OUTPUT_ALL          => 0, # output all symbols and doc sections
 | 
					    OUTPUT_ALL          => 0, # output all symbols and doc sections
 | 
				
			||||||
    OUTPUT_INCLUDE      => 1, # output only specified symbols
 | 
					    OUTPUT_INCLUDE      => 1, # output only specified symbols
 | 
				
			||||||
    OUTPUT_EXCLUDE      => 2, # output everything except specified symbols
 | 
					    OUTPUT_EXPORTED     => 2, # output exported symbols
 | 
				
			||||||
    OUTPUT_EXPORTED     => 3, # output exported symbols
 | 
					    OUTPUT_INTERNAL     => 3, # output non-exported symbols
 | 
				
			||||||
    OUTPUT_INTERNAL     => 4, # output non-exported symbols
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
my $output_selection = OUTPUT_ALL;
 | 
					my $output_selection = OUTPUT_ALL;
 | 
				
			||||||
my $show_not_found = 0;
 | 
					my $show_not_found = 0;	# No longer used
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my @export_file_list;
 | 
					my @export_file_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -307,6 +320,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
 | 
				
			|||||||
# CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
 | 
					# CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
 | 
				
			||||||
# could cause "use of undefined value" or other bugs.
 | 
					# could cause "use of undefined value" or other bugs.
 | 
				
			||||||
my ($function, %function_table, %parametertypes, $declaration_purpose);
 | 
					my ($function, %function_table, %parametertypes, $declaration_purpose);
 | 
				
			||||||
 | 
					my %nosymbol_table = ();
 | 
				
			||||||
my $declaration_start_line;
 | 
					my $declaration_start_line;
 | 
				
			||||||
my ($type, $declaration_name, $return_type);
 | 
					my ($type, $declaration_name, $return_type);
 | 
				
			||||||
my ($newsection, $newcontents, $prototype, $brcount, %source_map);
 | 
					my ($newsection, $newcontents, $prototype, $brcount, %source_map);
 | 
				
			||||||
@ -315,9 +329,21 @@ if (defined($ENV{'KBUILD_VERBOSE'})) {
 | 
				
			|||||||
	$verbose = "$ENV{'KBUILD_VERBOSE'}";
 | 
						$verbose = "$ENV{'KBUILD_VERBOSE'}";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (defined($ENV{'KDOC_WERROR'})) {
 | 
				
			||||||
 | 
						$Werror = "$ENV{'KDOC_WERROR'}";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (defined($ENV{'KCFLAGS'})) {
 | 
				
			||||||
 | 
						my $kcflags = "$ENV{'KCFLAGS'}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($kcflags =~ /Werror/) {
 | 
				
			||||||
 | 
							$Werror = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Generated docbook code is inserted in a template at a point where
 | 
					# Generated docbook code is inserted in a template at a point where
 | 
				
			||||||
# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
 | 
					# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
 | 
				
			||||||
# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
 | 
					# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
 | 
				
			||||||
# We keep track of number of generated entries and generate a dummy
 | 
					# We keep track of number of generated entries and generate a dummy
 | 
				
			||||||
# if needs be to ensure the expanded template can be postprocessed
 | 
					# if needs be to ensure the expanded template can be postprocessed
 | 
				
			||||||
# into html.
 | 
					# into html.
 | 
				
			||||||
@ -327,13 +353,14 @@ my $lineprefix="";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Parser states
 | 
					# Parser states
 | 
				
			||||||
use constant {
 | 
					use constant {
 | 
				
			||||||
    STATE_NORMAL        => 0, # normal code
 | 
					    STATE_NORMAL        => 0,        # normal code
 | 
				
			||||||
    STATE_NAME          => 1, # looking for function name
 | 
					    STATE_NAME          => 1,        # looking for function name
 | 
				
			||||||
    STATE_BODY_MAYBE    => 2, # body - or maybe more description
 | 
					    STATE_BODY_MAYBE    => 2,        # body - or maybe more description
 | 
				
			||||||
    STATE_BODY          => 3, # the body of the comment
 | 
					    STATE_BODY          => 3,        # the body of the comment
 | 
				
			||||||
    STATE_PROTO         => 4, # scanning prototype
 | 
					    STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line
 | 
				
			||||||
    STATE_DOCBLOCK      => 5, # documentation block
 | 
					    STATE_PROTO         => 5,        # scanning prototype
 | 
				
			||||||
    STATE_INLINE        => 6, # gathering documentation outside main block
 | 
					    STATE_DOCBLOCK      => 6,        # documentation block
 | 
				
			||||||
 | 
					    STATE_INLINE        => 7,        # gathering doc outside main block
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
my $state;
 | 
					my $state;
 | 
				
			||||||
my $in_doc_sect;
 | 
					my $in_doc_sect;
 | 
				
			||||||
@ -413,10 +440,9 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
 | 
				
			|||||||
	$output_selection = OUTPUT_INCLUDE;
 | 
						$output_selection = OUTPUT_INCLUDE;
 | 
				
			||||||
	$function = shift @ARGV;
 | 
						$function = shift @ARGV;
 | 
				
			||||||
	$function_table{$function} = 1;
 | 
						$function_table{$function} = 1;
 | 
				
			||||||
    } elsif ($cmd eq "nofunction") { # output all except specific functions
 | 
					    } elsif ($cmd eq "nosymbol") { # Exclude specific symbols
 | 
				
			||||||
	$output_selection = OUTPUT_EXCLUDE;
 | 
						my $symbol = shift @ARGV;
 | 
				
			||||||
	$function = shift @ARGV;
 | 
						$nosymbol_table{$symbol} = 1;
 | 
				
			||||||
	$function_table{$function} = 1;
 | 
					 | 
				
			||||||
    } elsif ($cmd eq "export") { # only exported symbols
 | 
					    } elsif ($cmd eq "export") { # only exported symbols
 | 
				
			||||||
	$output_selection = OUTPUT_EXPORTED;
 | 
						$output_selection = OUTPUT_EXPORTED;
 | 
				
			||||||
	%function_table = ();
 | 
						%function_table = ();
 | 
				
			||||||
@ -428,6 +454,8 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
 | 
				
			|||||||
	push(@export_file_list, $file);
 | 
						push(@export_file_list, $file);
 | 
				
			||||||
    } elsif ($cmd eq "v") {
 | 
					    } elsif ($cmd eq "v") {
 | 
				
			||||||
	$verbose = 1;
 | 
						$verbose = 1;
 | 
				
			||||||
 | 
					    } elsif ($cmd eq "Werror") {
 | 
				
			||||||
 | 
						$Werror = 1;
 | 
				
			||||||
    } elsif (($cmd eq "h") || ($cmd eq "help")) {
 | 
					    } elsif (($cmd eq "h") || ($cmd eq "help")) {
 | 
				
			||||||
	usage();
 | 
						usage();
 | 
				
			||||||
    } elsif ($cmd eq 'no-doc-sections') {
 | 
					    } elsif ($cmd eq 'no-doc-sections') {
 | 
				
			||||||
@ -435,7 +463,24 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
 | 
				
			|||||||
    } elsif ($cmd eq 'enable-lineno') {
 | 
					    } elsif ($cmd eq 'enable-lineno') {
 | 
				
			||||||
	    $enable_lineno = 1;
 | 
						    $enable_lineno = 1;
 | 
				
			||||||
    } elsif ($cmd eq 'show-not-found') {
 | 
					    } elsif ($cmd eq 'show-not-found') {
 | 
				
			||||||
	$show_not_found = 1;
 | 
						$show_not_found = 1;  # A no-op but don't fail
 | 
				
			||||||
 | 
					    } elsif ($cmd eq "sphinx-version") {
 | 
				
			||||||
 | 
						my $ver_string = shift @ARGV;
 | 
				
			||||||
 | 
						if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) {
 | 
				
			||||||
 | 
						    $sphinx_major = $1;
 | 
				
			||||||
 | 
						    if (defined($2)) {
 | 
				
			||||||
 | 
							$sphinx_minor = substr($2,1);
 | 
				
			||||||
 | 
						    } else {
 | 
				
			||||||
 | 
							$sphinx_minor = 0;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    if (defined($3)) {
 | 
				
			||||||
 | 
							$sphinx_patch = substr($3,1)
 | 
				
			||||||
 | 
						    } else {
 | 
				
			||||||
 | 
							$sphinx_patch = 0;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
						    die "Sphinx version should either major.minor or major.minor.patch format\n";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
	# Unknown argument
 | 
						# Unknown argument
 | 
				
			||||||
        usage();
 | 
					        usage();
 | 
				
			||||||
@ -444,6 +489,51 @@ while ($ARGV[0] =~ m/^--?(.*)/) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# continue execution near EOF;
 | 
					# 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 = "sphinx-build";
 | 
				
			||||||
 | 
						if (!findprog($cmd)) {
 | 
				
			||||||
 | 
							my $cmd = "sphinx-build3";
 | 
				
			||||||
 | 
							if (!findprog($cmd)) {
 | 
				
			||||||
 | 
								$sphinx_major = 1;
 | 
				
			||||||
 | 
								$sphinx_minor = 2;
 | 
				
			||||||
 | 
								$sphinx_patch = 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 (<IN>) {
 | 
				
			||||||
 | 
							if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) {
 | 
				
			||||||
 | 
								$sphinx_major = $1;
 | 
				
			||||||
 | 
								$sphinx_minor = $2;
 | 
				
			||||||
 | 
								$sphinx_patch = $3;
 | 
				
			||||||
 | 
								last;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							# Sphinx 1.2.x uses a different format
 | 
				
			||||||
 | 
							if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) {
 | 
				
			||||||
 | 
								$sphinx_major = $1;
 | 
				
			||||||
 | 
								$sphinx_minor = $2;
 | 
				
			||||||
 | 
								$sphinx_patch = $3;
 | 
				
			||||||
 | 
								last;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						close IN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# get kernel version from env
 | 
					# get kernel version from env
 | 
				
			||||||
sub get_kernel_version() {
 | 
					sub get_kernel_version() {
 | 
				
			||||||
    my $version = 'unknown kernel version';
 | 
					    my $version = 'unknown kernel version';
 | 
				
			||||||
@ -510,11 +600,11 @@ sub dump_doc_section {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if (defined($nosymbol_table{$name}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (($output_selection == OUTPUT_ALL) ||
 | 
					    if (($output_selection == OUTPUT_ALL) ||
 | 
				
			||||||
	($output_selection == OUTPUT_INCLUDE &&
 | 
						(($output_selection == OUTPUT_INCLUDE) &&
 | 
				
			||||||
	 defined($function_table{$name})) ||
 | 
						 defined($function_table{$name})))
 | 
				
			||||||
	($output_selection == OUTPUT_EXCLUDE &&
 | 
					 | 
				
			||||||
	 !defined($function_table{$name})))
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
	dump_section($file, $name, $contents);
 | 
						dump_section($file, $name, $contents);
 | 
				
			||||||
	output_blockhead({'sectionlist' => \@sectionlist,
 | 
						output_blockhead({'sectionlist' => \@sectionlist,
 | 
				
			||||||
@ -597,10 +687,10 @@ sub output_function_man(%) {
 | 
				
			|||||||
	$type = $args{'parametertypes'}{$parameter};
 | 
						$type = $args{'parametertypes'}{$parameter};
 | 
				
			||||||
	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 | 
						if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 | 
				
			||||||
	    # pointer-to-function
 | 
						    # pointer-to-function
 | 
				
			||||||
	    print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
 | 
						    print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n";
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    $type =~ s/([^\*])$/$1 /;
 | 
						    $type =~ s/([^\*])$/$1 /;
 | 
				
			||||||
	    print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
 | 
						    print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	$count++;
 | 
						$count++;
 | 
				
			||||||
	$parenth = "";
 | 
						$parenth = "";
 | 
				
			||||||
@ -740,6 +830,8 @@ sub output_blockhead_rst(%) {
 | 
				
			|||||||
    my ($parameter, $section);
 | 
					    my ($parameter, $section);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    foreach $section (@{$args{'sectionlist'}}) {
 | 
					    foreach $section (@{$args{'sectionlist'}}) {
 | 
				
			||||||
 | 
						next if (defined($nosymbol_table{$section}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($output_selection != OUTPUT_INCLUDE) {
 | 
						if ($output_selection != OUTPUT_INCLUDE) {
 | 
				
			||||||
	    print "**$section**\n\n";
 | 
						    print "**$section**\n\n";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -825,16 +917,37 @@ sub output_function_rst(%) {
 | 
				
			|||||||
    my ($parameter, $section);
 | 
					    my ($parameter, $section);
 | 
				
			||||||
    my $oldprefix = $lineprefix;
 | 
					    my $oldprefix = $lineprefix;
 | 
				
			||||||
    my $start = "";
 | 
					    my $start = "";
 | 
				
			||||||
 | 
					    my $is_macro = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ($args{'typedef'}) {
 | 
					    if ($sphinx_major < 3) {
 | 
				
			||||||
	print ".. c:type:: ". $args{'function'} . "\n\n";
 | 
						if ($args{'typedef'}) {
 | 
				
			||||||
	print_lineno($declaration_start_line);
 | 
						    print ".. c:type:: ". $args{'function'} . "\n\n";
 | 
				
			||||||
	print "   **Typedef**: ";
 | 
						    print_lineno($declaration_start_line);
 | 
				
			||||||
	$lineprefix = "";
 | 
						    print "   **Typedef**: ";
 | 
				
			||||||
	output_highlight_rst($args{'purpose'});
 | 
						    $lineprefix = "";
 | 
				
			||||||
	$start = "\n\n**Syntax**\n\n  ``";
 | 
						    output_highlight_rst($args{'purpose'});
 | 
				
			||||||
 | 
						    $start = "\n\n**Syntax**\n\n  ``";
 | 
				
			||||||
 | 
						    $is_macro = 1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
						    print ".. c:function:: ";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
	print ".. c:function:: ";
 | 
						if ($args{'typedef'} || $args{'functiontype'} eq "") {
 | 
				
			||||||
 | 
						    $is_macro = 1;
 | 
				
			||||||
 | 
						    print ".. c:macro:: ". $args{'function'} . "\n\n";
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
						    print ".. c:function:: ";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($args{'typedef'}) {
 | 
				
			||||||
 | 
						    print_lineno($declaration_start_line);
 | 
				
			||||||
 | 
						    print "   **Typedef**: ";
 | 
				
			||||||
 | 
						    $lineprefix = "";
 | 
				
			||||||
 | 
						    output_highlight_rst($args{'purpose'});
 | 
				
			||||||
 | 
						    $start = "\n\n**Syntax**\n\n  ``";
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
						    print "``" if ($is_macro);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if ($args{'functiontype'} ne "") {
 | 
					    if ($args{'functiontype'} ne "") {
 | 
				
			||||||
	$start .= $args{'functiontype'} . " " . $args{'function'} . " (";
 | 
						$start .= $args{'functiontype'} . " " . $args{'function'} . " (";
 | 
				
			||||||
@ -853,15 +966,17 @@ sub output_function_rst(%) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 | 
						if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 | 
				
			||||||
	    # pointer-to-function
 | 
						    # pointer-to-function
 | 
				
			||||||
	    print $1 . $parameter . ") (" . $2;
 | 
						    print $1 . $parameter . ") (" . $2 . ")";
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    print $type . " " . $parameter;
 | 
						    print $type;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if ($args{'typedef'}) {
 | 
					    if ($is_macro) {
 | 
				
			||||||
	print ");``\n\n";
 | 
						print ")``\n\n";
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
	print ")\n\n";
 | 
						print ")\n\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!$args{'typedef'}) {
 | 
				
			||||||
	print_lineno($declaration_start_line);
 | 
						print_lineno($declaration_start_line);
 | 
				
			||||||
	$lineprefix = "   ";
 | 
						$lineprefix = "   ";
 | 
				
			||||||
	output_highlight_rst($args{'purpose'});
 | 
						output_highlight_rst($args{'purpose'});
 | 
				
			||||||
@ -876,7 +991,7 @@ sub output_function_rst(%) {
 | 
				
			|||||||
	$type = $args{'parametertypes'}{$parameter};
 | 
						$type = $args{'parametertypes'}{$parameter};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($type ne "") {
 | 
						if ($type ne "") {
 | 
				
			||||||
	    print "``$type $parameter``\n";
 | 
						    print "``$type``\n";
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    print "``$parameter``\n";
 | 
						    print "``$parameter``\n";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -917,9 +1032,14 @@ sub output_enum_rst(%) {
 | 
				
			|||||||
    my ($parameter);
 | 
					    my ($parameter);
 | 
				
			||||||
    my $oldprefix = $lineprefix;
 | 
					    my $oldprefix = $lineprefix;
 | 
				
			||||||
    my $count;
 | 
					    my $count;
 | 
				
			||||||
    my $name = "enum " . $args{'enum'};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print "\n\n.. c:type:: " . $name . "\n\n";
 | 
					    if ($sphinx_major < 3) {
 | 
				
			||||||
 | 
						my $name = "enum " . $args{'enum'};
 | 
				
			||||||
 | 
						print "\n\n.. c:type:: " . $name . "\n\n";
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
						my $name = $args{'enum'};
 | 
				
			||||||
 | 
						print "\n\n.. c:enum:: " . $name . "\n\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    print_lineno($declaration_start_line);
 | 
					    print_lineno($declaration_start_line);
 | 
				
			||||||
    $lineprefix = "   ";
 | 
					    $lineprefix = "   ";
 | 
				
			||||||
    output_highlight_rst($args{'purpose'});
 | 
					    output_highlight_rst($args{'purpose'});
 | 
				
			||||||
@ -945,8 +1065,13 @@ sub output_typedef_rst(%) {
 | 
				
			|||||||
    my %args = %{$_[0]};
 | 
					    my %args = %{$_[0]};
 | 
				
			||||||
    my ($parameter);
 | 
					    my ($parameter);
 | 
				
			||||||
    my $oldprefix = $lineprefix;
 | 
					    my $oldprefix = $lineprefix;
 | 
				
			||||||
    my $name = "typedef " . $args{'typedef'};
 | 
					    my $name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($sphinx_major < 3) {
 | 
				
			||||||
 | 
						$name = "typedef " . $args{'typedef'};
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
						$name = $args{'typedef'};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    print "\n\n.. c:type:: " . $name . "\n\n";
 | 
					    print "\n\n.. c:type:: " . $name . "\n\n";
 | 
				
			||||||
    print_lineno($declaration_start_line);
 | 
					    print_lineno($declaration_start_line);
 | 
				
			||||||
    $lineprefix = "   ";
 | 
					    $lineprefix = "   ";
 | 
				
			||||||
@ -961,9 +1086,18 @@ sub output_struct_rst(%) {
 | 
				
			|||||||
    my %args = %{$_[0]};
 | 
					    my %args = %{$_[0]};
 | 
				
			||||||
    my ($parameter);
 | 
					    my ($parameter);
 | 
				
			||||||
    my $oldprefix = $lineprefix;
 | 
					    my $oldprefix = $lineprefix;
 | 
				
			||||||
    my $name = $args{'type'} . " " . $args{'struct'};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print "\n\n.. c:type:: " . $name . "\n\n";
 | 
					    if ($sphinx_major < 3) {
 | 
				
			||||||
 | 
						my $name = $args{'type'} . " " . $args{'struct'};
 | 
				
			||||||
 | 
						print "\n\n.. c:type:: " . $name . "\n\n";
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
						my $name = $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);
 | 
					    print_lineno($declaration_start_line);
 | 
				
			||||||
    $lineprefix = "   ";
 | 
					    $lineprefix = "   ";
 | 
				
			||||||
    output_highlight_rst($args{'purpose'});
 | 
					    output_highlight_rst($args{'purpose'});
 | 
				
			||||||
@ -1022,12 +1156,14 @@ sub output_declaration {
 | 
				
			|||||||
    my $name = shift;
 | 
					    my $name = shift;
 | 
				
			||||||
    my $functype = shift;
 | 
					    my $functype = shift;
 | 
				
			||||||
    my $func = "output_${functype}_$output_mode";
 | 
					    my $func = "output_${functype}_$output_mode";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if (defined($nosymbol_table{$name}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (($output_selection == OUTPUT_ALL) ||
 | 
					    if (($output_selection == OUTPUT_ALL) ||
 | 
				
			||||||
	(($output_selection == OUTPUT_INCLUDE ||
 | 
						(($output_selection == OUTPUT_INCLUDE ||
 | 
				
			||||||
	  $output_selection == OUTPUT_EXPORTED) &&
 | 
						  $output_selection == OUTPUT_EXPORTED) &&
 | 
				
			||||||
	 defined($function_table{$name})) ||
 | 
						 defined($function_table{$name})) ||
 | 
				
			||||||
	(($output_selection == OUTPUT_EXCLUDE ||
 | 
						($output_selection == OUTPUT_INTERNAL &&
 | 
				
			||||||
	  $output_selection == OUTPUT_INTERNAL) &&
 | 
					 | 
				
			||||||
	 !($functype eq "function" && defined($function_table{$name}))))
 | 
						 !($functype eq "function" && defined($function_table{$name}))))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
	&$func(@_);
 | 
						&$func(@_);
 | 
				
			||||||
@ -1062,7 +1198,7 @@ sub dump_struct($$) {
 | 
				
			|||||||
    my $x = shift;
 | 
					    my $x = shift;
 | 
				
			||||||
    my $file = shift;
 | 
					    my $file = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) {
 | 
					    if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) {
 | 
				
			||||||
	my $decl_type = $1;
 | 
						my $decl_type = $1;
 | 
				
			||||||
	$declaration_name = $2;
 | 
						$declaration_name = $2;
 | 
				
			||||||
	my $members = $3;
 | 
						my $members = $3;
 | 
				
			||||||
@ -1073,11 +1209,15 @@ sub dump_struct($$) {
 | 
				
			|||||||
	# strip comments:
 | 
						# strip comments:
 | 
				
			||||||
	$members =~ s/\/\*.*?\*\///gos;
 | 
						$members =~ s/\/\*.*?\*\///gos;
 | 
				
			||||||
	# strip attributes
 | 
						# strip attributes
 | 
				
			||||||
	$members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi;
 | 
						$members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)/ /gi;
 | 
				
			||||||
	$members =~ s/\s*__aligned\s*\([^;]*\)//gos;
 | 
						$members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;
 | 
				
			||||||
	$members =~ s/\s*__packed\s*//gos;
 | 
						$members =~ s/\s*__packed\s*/ /gos;
 | 
				
			||||||
	$members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
 | 
						$members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
 | 
				
			||||||
 | 
						$members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
 | 
				
			||||||
 | 
						$members =~ s/\s*____cacheline_aligned/ /gos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# replace DECLARE_BITMAP
 | 
						# replace DECLARE_BITMAP
 | 
				
			||||||
 | 
						$members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;
 | 
				
			||||||
	$members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
 | 
						$members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
 | 
				
			||||||
	# replace DECLARE_HASHTABLE
 | 
						# replace DECLARE_HASHTABLE
 | 
				
			||||||
	$members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
 | 
						$members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
 | 
				
			||||||
@ -1204,6 +1344,8 @@ sub show_warnings($$) {
 | 
				
			|||||||
	my $functype = shift;
 | 
						my $functype = shift;
 | 
				
			||||||
	my $name = shift;
 | 
						my $name = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0 if (defined($nosymbol_table{$name}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1 if ($output_selection == OUTPUT_ALL);
 | 
						return 1 if ($output_selection == OUTPUT_ALL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($output_selection == OUTPUT_EXPORTED) {
 | 
						if ($output_selection == OUTPUT_EXPORTED) {
 | 
				
			||||||
@ -1227,27 +1369,28 @@ sub show_warnings($$) {
 | 
				
			|||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ($output_selection == OUTPUT_EXCLUDE) {
 | 
					 | 
				
			||||||
		if (!defined($function_table{$name})) {
 | 
					 | 
				
			||||||
			return 1;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	die("Please add the new output type at show_warnings()");
 | 
						die("Please add the new output type at show_warnings()");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub dump_enum($$) {
 | 
					sub dump_enum($$) {
 | 
				
			||||||
    my $x = shift;
 | 
					    my $x = shift;
 | 
				
			||||||
    my $file = shift;
 | 
					    my $file = shift;
 | 
				
			||||||
 | 
					    my $members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
					    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
				
			||||||
    # strip #define macros inside enums
 | 
					    # strip #define macros inside enums
 | 
				
			||||||
    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
 | 
					    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ($x =~ /enum\s+(\w+)\s*\{(.*)\}/) {
 | 
					    if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {
 | 
				
			||||||
 | 
						$declaration_name = $2;
 | 
				
			||||||
 | 
						$members = $1;
 | 
				
			||||||
 | 
					    } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {
 | 
				
			||||||
	$declaration_name = $1;
 | 
						$declaration_name = $1;
 | 
				
			||||||
	my $members = $2;
 | 
						$members = $2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($members) {
 | 
				
			||||||
	my %_members;
 | 
						my %_members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$members =~ s/\s+$//;
 | 
						$members =~ s/\s+$//;
 | 
				
			||||||
@ -1282,27 +1425,31 @@ sub dump_enum($$) {
 | 
				
			|||||||
			    'sections' => \%sections,
 | 
								    'sections' => \%sections,
 | 
				
			||||||
			    'purpose' => $declaration_purpose
 | 
								    'purpose' => $declaration_purpose
 | 
				
			||||||
			   });
 | 
								   });
 | 
				
			||||||
    }
 | 
					    } else {
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
	print STDERR "${file}:$.: error: Cannot parse enum!\n";
 | 
						print STDERR "${file}:$.: error: Cannot parse enum!\n";
 | 
				
			||||||
	++$errors;
 | 
						++$errors;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x;
 | 
				
			||||||
 | 
					my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;
 | 
				
			||||||
 | 
					my $typedef_args = qr { \s*\((.*)\); }x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;
 | 
				
			||||||
 | 
					my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub dump_typedef($$) {
 | 
					sub dump_typedef($$) {
 | 
				
			||||||
    my $x = shift;
 | 
					    my $x = shift;
 | 
				
			||||||
    my $file = shift;
 | 
					    my $file = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
					    $x =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Parse function prototypes
 | 
					    # Parse function typedef prototypes
 | 
				
			||||||
    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
 | 
					    if ($x =~ $typedef1 || $x =~ $typedef2) {
 | 
				
			||||||
	$x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Function typedefs
 | 
					 | 
				
			||||||
	$return_type = $1;
 | 
						$return_type = $1;
 | 
				
			||||||
	$declaration_name = $2;
 | 
						$declaration_name = $2;
 | 
				
			||||||
	my $args = $3;
 | 
						my $args = $3;
 | 
				
			||||||
 | 
						$return_type =~ s/^\s+//;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	create_parameterlist($args, ',', $file, $declaration_name);
 | 
						create_parameterlist($args, ',', $file, $declaration_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1369,25 +1516,27 @@ sub create_parameterlist($$$$) {
 | 
				
			|||||||
    foreach my $arg (split($splitter, $args)) {
 | 
					    foreach my $arg (split($splitter, $args)) {
 | 
				
			||||||
	# strip comments
 | 
						# strip comments
 | 
				
			||||||
	$arg =~ s/\/\*.*\*\///;
 | 
						$arg =~ s/\/\*.*\*\///;
 | 
				
			||||||
 | 
						$arg =~ s/\s*EFIAPI\s*/ /g;
 | 
				
			||||||
	# strip leading/trailing spaces
 | 
						# strip leading/trailing spaces
 | 
				
			||||||
	$arg =~ s/^\s*//;
 | 
						$arg =~ s/^\s*//;
 | 
				
			||||||
	$arg =~ s/\s*$//;
 | 
						$arg =~ s/\s*$//;
 | 
				
			||||||
	$arg =~ s/\s+/ /;
 | 
						$arg =~ s/\s+/ /;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($arg =~ /^#/) {
 | 
						if ($arg =~ /^#/) {
 | 
				
			||||||
	    # Treat preprocessor directive as a typeless variable just to fill
 | 
						    # Treat preprocessor directive as a typeless variable just to fill
 | 
				
			||||||
	    # corresponding data structures "correctly". Catch it later in
 | 
						    # corresponding data structures "correctly". Catch it later in
 | 
				
			||||||
	    # output_* subs.
 | 
						    # output_* subs.
 | 
				
			||||||
	    push_parameter($arg, "", $file);
 | 
						    push_parameter($arg, "", "", $file);
 | 
				
			||||||
	} elsif ($arg =~ m/\(.+\)\s*\(/) {
 | 
						} elsif ($arg =~ m/\(.+\)\s*\(/) {
 | 
				
			||||||
	    # pointer-to-function
 | 
						    # pointer-to-function
 | 
				
			||||||
	    $arg =~ tr/#/,/;
 | 
						    $arg =~ tr/#/,/;
 | 
				
			||||||
	    $arg =~ m/[^\(]+\([\w\s]*\*?\s*([\w\.]*)\s*\)/;
 | 
						    $arg =~ m/[^\(]+\(\s*\*?\s*([\w\.]*)\s*\)/;
 | 
				
			||||||
	    $param = $1;
 | 
						    $param = $1;
 | 
				
			||||||
	    $type = $arg;
 | 
						    $type = $arg;
 | 
				
			||||||
	    $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
 | 
						    $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
 | 
				
			||||||
	    save_struct_actual($param);
 | 
						    save_struct_actual($param);
 | 
				
			||||||
	    push_parameter($param, $type, $file, $declaration_name);
 | 
						    push_parameter($param, $type, $arg, $file, $declaration_name);
 | 
				
			||||||
	} elsif ($arg) {
 | 
						} elsif ($arg) {
 | 
				
			||||||
	    $arg =~ s/\s*:\s*/:/g;
 | 
						    $arg =~ s/\s*:\s*/:/g;
 | 
				
			||||||
	    $arg =~ s/\s*\[/\[/g;
 | 
						    $arg =~ s/\s*\[/\[/g;
 | 
				
			||||||
@ -1412,26 +1561,28 @@ sub create_parameterlist($$$$) {
 | 
				
			|||||||
	    foreach $param (@args) {
 | 
						    foreach $param (@args) {
 | 
				
			||||||
		if ($param =~ m/^(\*+)\s*(.*)/) {
 | 
							if ($param =~ m/^(\*+)\s*(.*)/) {
 | 
				
			||||||
		    save_struct_actual($2);
 | 
							    save_struct_actual($2);
 | 
				
			||||||
		    push_parameter($2, "$type $1", $file, $declaration_name);
 | 
					
 | 
				
			||||||
 | 
							    push_parameter($2, "$type $1", $arg, $file, $declaration_name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		elsif ($param =~ m/(.*?):(\d+)/) {
 | 
							elsif ($param =~ m/(.*?):(\d+)/) {
 | 
				
			||||||
		    if ($type ne "") { # skip unnamed bit-fields
 | 
							    if ($type ne "") { # skip unnamed bit-fields
 | 
				
			||||||
			save_struct_actual($1);
 | 
								save_struct_actual($1);
 | 
				
			||||||
			push_parameter($1, "$type:$2", $file, $declaration_name)
 | 
								push_parameter($1, "$type:$2", $arg, $file, $declaration_name)
 | 
				
			||||||
		    }
 | 
							    }
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
		    save_struct_actual($param);
 | 
							    save_struct_actual($param);
 | 
				
			||||||
		    push_parameter($param, $type, $file, $declaration_name);
 | 
							    push_parameter($param, $type, $arg, $file, $declaration_name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub push_parameter($$$$) {
 | 
					sub push_parameter($$$$$) {
 | 
				
			||||||
	my $param = shift;
 | 
						my $param = shift;
 | 
				
			||||||
	my $type = shift;
 | 
						my $type = shift;
 | 
				
			||||||
 | 
						my $org_arg = shift;
 | 
				
			||||||
	my $file = shift;
 | 
						my $file = shift;
 | 
				
			||||||
	my $declaration_name = shift;
 | 
						my $declaration_name = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1449,6 +1600,10 @@ sub push_parameter($$$$) {
 | 
				
			|||||||
	      # handles unnamed variable parameters
 | 
						      # handles unnamed variable parameters
 | 
				
			||||||
	      $param = "...";
 | 
						      $param = "...";
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
						    elsif ($param =~ /\w\.\.\.$/) {
 | 
				
			||||||
 | 
						      # for named variable parameters of the form `x...`, remove the dots
 | 
				
			||||||
 | 
						      $param =~ s/\.\.\.$//;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
	    if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
 | 
						    if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
 | 
				
			||||||
		$parameterdescs{$param} = "variable arguments";
 | 
							$parameterdescs{$param} = "variable arguments";
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
@ -1491,8 +1646,8 @@ sub push_parameter($$$$) {
 | 
				
			|||||||
	# "[blah" in a parameter string;
 | 
						# "[blah" in a parameter string;
 | 
				
			||||||
	###$param =~ s/\s*//g;
 | 
						###$param =~ s/\s*//g;
 | 
				
			||||||
	push @parameterlist, $param;
 | 
						push @parameterlist, $param;
 | 
				
			||||||
	$type =~ s/\s\s+/ /g;
 | 
						$org_arg =~ s/\s\s+/ /g;
 | 
				
			||||||
	$parametertypes{$param} = $type;
 | 
						$parametertypes{$param} = $org_arg;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub check_sections($$$$$) {
 | 
					sub check_sections($$$$$) {
 | 
				
			||||||
@ -1566,6 +1721,8 @@ sub dump_function($$) {
 | 
				
			|||||||
    my $file = shift;
 | 
					    my $file = shift;
 | 
				
			||||||
    my $noret = 0;
 | 
					    my $noret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print_lineno($new_start_line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $prototype =~ s/^static +//;
 | 
					    $prototype =~ s/^static +//;
 | 
				
			||||||
    $prototype =~ s/^extern +//;
 | 
					    $prototype =~ s/^extern +//;
 | 
				
			||||||
    $prototype =~ s/^asmlinkage +//;
 | 
					    $prototype =~ s/^asmlinkage +//;
 | 
				
			||||||
@ -1580,6 +1737,7 @@ sub dump_function($$) {
 | 
				
			|||||||
    $prototype =~ s/__must_check +//;
 | 
					    $prototype =~ s/__must_check +//;
 | 
				
			||||||
    $prototype =~ s/__weak +//;
 | 
					    $prototype =~ s/__weak +//;
 | 
				
			||||||
    $prototype =~ s/__sched +//;
 | 
					    $prototype =~ s/__sched +//;
 | 
				
			||||||
 | 
					    $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
 | 
				
			||||||
    my $define = $prototype =~ s/^#\s*define\s+//; #ak added
 | 
					    my $define = $prototype =~ s/^#\s*define\s+//; #ak added
 | 
				
			||||||
    $prototype =~ s/__attribute__\s*\(\(
 | 
					    $prototype =~ s/__attribute__\s*\(\(
 | 
				
			||||||
            (?:
 | 
					            (?:
 | 
				
			||||||
@ -1640,30 +1798,48 @@ sub dump_function($$) {
 | 
				
			|||||||
	return;
 | 
						return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	my $prms = join " ", @parameterlist;
 | 
					    my $prms = join " ", @parameterlist;
 | 
				
			||||||
	check_sections($file, $declaration_name, "function", $sectcheck, $prms);
 | 
					    check_sections($file, $declaration_name, "function", $sectcheck, $prms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # This check emits a lot of warnings at the moment, because many
 | 
					    # This check emits a lot of warnings at the moment, because many
 | 
				
			||||||
        # functions don't have a 'Return' doc section. So until the number
 | 
					    # functions don't have a 'Return' doc section. So until the number
 | 
				
			||||||
        # of warnings goes sufficiently down, the check is only performed in
 | 
					    # of warnings goes sufficiently down, the check is only performed in
 | 
				
			||||||
        # verbose mode.
 | 
					    # verbose mode.
 | 
				
			||||||
        # TODO: always perform the check.
 | 
					    # TODO: always perform the check.
 | 
				
			||||||
        if ($verbose && !$noret) {
 | 
					    if ($verbose && !$noret) {
 | 
				
			||||||
                check_return_section($file, $declaration_name, $return_type);
 | 
						    check_return_section($file, $declaration_name, $return_type);
 | 
				
			||||||
        }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    output_declaration($declaration_name,
 | 
					    # The function parser can be called with a typedef parameter.
 | 
				
			||||||
		       'function',
 | 
					    # Handle it.
 | 
				
			||||||
		       {'function' => $declaration_name,
 | 
					    if ($return_type =~ /typedef/) {
 | 
				
			||||||
			'module' => $modulename,
 | 
						output_declaration($declaration_name,
 | 
				
			||||||
			'functiontype' => $return_type,
 | 
								   'function',
 | 
				
			||||||
			'parameterlist' => \@parameterlist,
 | 
								   {'function' => $declaration_name,
 | 
				
			||||||
			'parameterdescs' => \%parameterdescs,
 | 
								    'typedef' => 1,
 | 
				
			||||||
			'parametertypes' => \%parametertypes,
 | 
								    'module' => $modulename,
 | 
				
			||||||
			'sectionlist' => \@sectionlist,
 | 
								    'functiontype' => $return_type,
 | 
				
			||||||
			'sections' => \%sections,
 | 
								    'parameterlist' => \@parameterlist,
 | 
				
			||||||
			'purpose' => $declaration_purpose
 | 
								    'parameterdescs' => \%parameterdescs,
 | 
				
			||||||
		       });
 | 
								    'parametertypes' => \%parametertypes,
 | 
				
			||||||
 | 
								    'sectionlist' => \@sectionlist,
 | 
				
			||||||
 | 
								    'sections' => \%sections,
 | 
				
			||||||
 | 
								    'purpose' => $declaration_purpose
 | 
				
			||||||
 | 
								   });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
						output_declaration($declaration_name,
 | 
				
			||||||
 | 
								   'function',
 | 
				
			||||||
 | 
								   {'function' => $declaration_name,
 | 
				
			||||||
 | 
								    'module' => $modulename,
 | 
				
			||||||
 | 
								    'functiontype' => $return_type,
 | 
				
			||||||
 | 
								    'parameterlist' => \@parameterlist,
 | 
				
			||||||
 | 
								    'parameterdescs' => \%parameterdescs,
 | 
				
			||||||
 | 
								    'parametertypes' => \%parametertypes,
 | 
				
			||||||
 | 
								    'sectionlist' => \@sectionlist,
 | 
				
			||||||
 | 
								    'sections' => \%sections,
 | 
				
			||||||
 | 
								    'purpose' => $declaration_purpose
 | 
				
			||||||
 | 
								   });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub reset_state {
 | 
					sub reset_state {
 | 
				
			||||||
@ -1758,6 +1934,11 @@ sub process_proto_function($$) {
 | 
				
			|||||||
	$prototype =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
						$prototype =~ s@/\*.*?\*/@@gos;	# strip comments.
 | 
				
			||||||
	$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 | 
						$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 | 
				
			||||||
	$prototype =~ s@^\s+@@gos; # strip leading spaces
 | 
						$prototype =~ s@^\s+@@gos; # strip leading spaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 # Handle prototypes for function pointers like:
 | 
				
			||||||
 | 
						 # int (*pcs_config)(struct foo)
 | 
				
			||||||
 | 
						$prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($prototype =~ /SYSCALL_DEFINE/) {
 | 
						if ($prototype =~ /SYSCALL_DEFINE/) {
 | 
				
			||||||
		syscall_munge();
 | 
							syscall_munge();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -1836,6 +2017,7 @@ sub process_export_file($) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    while (<IN>) {
 | 
					    while (<IN>) {
 | 
				
			||||||
	if (/$export_symbol/) {
 | 
						if (/$export_symbol/) {
 | 
				
			||||||
 | 
						    next if (defined($nosymbol_table{$2}));
 | 
				
			||||||
	    $function_table{$2} = 1;
 | 
						    $function_table{$2} = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1867,7 +2049,7 @@ sub process_name($$) {
 | 
				
			|||||||
    if (/$doc_block/o) {
 | 
					    if (/$doc_block/o) {
 | 
				
			||||||
	$state = STATE_DOCBLOCK;
 | 
						$state = STATE_DOCBLOCK;
 | 
				
			||||||
	$contents = "";
 | 
						$contents = "";
 | 
				
			||||||
	$new_start_line = $. + 1;
 | 
						$new_start_line = $.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( $1 eq "" ) {
 | 
						if ( $1 eq "" ) {
 | 
				
			||||||
	    $section = $section_intro;
 | 
						    $section = $section_intro;
 | 
				
			||||||
@ -1935,6 +2117,25 @@ sub process_name($$) {
 | 
				
			|||||||
sub process_body($$) {
 | 
					sub process_body($$) {
 | 
				
			||||||
    my $file = shift;
 | 
					    my $file = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Until all named variable macro parameters are
 | 
				
			||||||
 | 
					    # documented using the bare name (`x`) rather than with
 | 
				
			||||||
 | 
					    # dots (`x...`), strip the dots:
 | 
				
			||||||
 | 
					    if ($section =~ /\w\.\.\.$/) {
 | 
				
			||||||
 | 
						$section =~ s/\.\.\.$//;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($verbose) {
 | 
				
			||||||
 | 
						    print STDERR "${file}:$.: warning: Variable macro arguments should be documented without dots\n";
 | 
				
			||||||
 | 
						    ++$warnings;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) {
 | 
				
			||||||
 | 
						dump_section($file, $section, $contents);
 | 
				
			||||||
 | 
						$section = $section_default;
 | 
				
			||||||
 | 
						$new_start_line = $.;
 | 
				
			||||||
 | 
						$contents = "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (/$doc_sect/i) { # case insensitive for supported section names
 | 
					    if (/$doc_sect/i) { # case insensitive for supported section names
 | 
				
			||||||
	$newsection = $1;
 | 
						$newsection = $1;
 | 
				
			||||||
	$newcontents = $2;
 | 
						$newcontents = $2;
 | 
				
			||||||
@ -1987,19 +2188,23 @@ sub process_body($$) {
 | 
				
			|||||||
	$prototype = "";
 | 
						$prototype = "";
 | 
				
			||||||
	$state = STATE_PROTO;
 | 
						$state = STATE_PROTO;
 | 
				
			||||||
	$brcount = 0;
 | 
						$brcount = 0;
 | 
				
			||||||
 | 
					        $new_start_line = $. + 1;
 | 
				
			||||||
    } elsif (/$doc_content/) {
 | 
					    } elsif (/$doc_content/) {
 | 
				
			||||||
	# miguel-style comment kludge, look for blank lines after
 | 
					 | 
				
			||||||
	# @parameter line to signify start of description
 | 
					 | 
				
			||||||
	if ($1 eq "") {
 | 
						if ($1 eq "") {
 | 
				
			||||||
	    if ($section =~ m/^@/ || $section eq $section_context) {
 | 
						    if ($section eq $section_context) {
 | 
				
			||||||
		dump_section($file, $section, $contents);
 | 
							dump_section($file, $section, $contents);
 | 
				
			||||||
		$section = $section_default;
 | 
							$section = $section_default;
 | 
				
			||||||
		$contents = "";
 | 
							$contents = "";
 | 
				
			||||||
		$new_start_line = $.;
 | 
							$new_start_line = $.;
 | 
				
			||||||
 | 
							$state = STATE_BODY;
 | 
				
			||||||
	    } else {
 | 
						    } else {
 | 
				
			||||||
 | 
							if ($section ne $section_default) {
 | 
				
			||||||
 | 
							    $state = STATE_BODY_WITH_BLANK_LINE;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
							    $state = STATE_BODY;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		$contents .= "\n";
 | 
							$contents .= "\n";
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    $state = STATE_BODY;
 | 
					 | 
				
			||||||
	} elsif ($state == STATE_BODY_MAYBE) {
 | 
						} elsif ($state == STATE_BODY_MAYBE) {
 | 
				
			||||||
	    # Continued declaration purpose
 | 
						    # Continued declaration purpose
 | 
				
			||||||
	    chomp($declaration_purpose);
 | 
						    chomp($declaration_purpose);
 | 
				
			||||||
@ -2131,7 +2336,7 @@ sub process_file($) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $file = map_filename($orig_file);
 | 
					    $file = map_filename($orig_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!open(IN,"<$file")) {
 | 
					    if (!open(IN_FILE,"<$file")) {
 | 
				
			||||||
	print STDERR "Error: Cannot open file $file\n";
 | 
						print STDERR "Error: Cannot open file $file\n";
 | 
				
			||||||
	++$errors;
 | 
						++$errors;
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
@ -2140,9 +2345,9 @@ sub process_file($) {
 | 
				
			|||||||
    $. = 1;
 | 
					    $. = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $section_counter = 0;
 | 
					    $section_counter = 0;
 | 
				
			||||||
    while (<IN>) {
 | 
					    while (<IN_FILE>) {
 | 
				
			||||||
	while (s/\\\s*$//) {
 | 
						while (s/\\\s*$//) {
 | 
				
			||||||
	    $_ .= <IN>;
 | 
						    $_ .= <IN_FILE>;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	# Replace tabs by spaces
 | 
						# Replace tabs by spaces
 | 
				
			||||||
        while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
 | 
					        while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
 | 
				
			||||||
@ -2151,7 +2356,8 @@ sub process_file($) {
 | 
				
			|||||||
	    process_normal();
 | 
						    process_normal();
 | 
				
			||||||
	} elsif ($state == STATE_NAME) {
 | 
						} elsif ($state == STATE_NAME) {
 | 
				
			||||||
	    process_name($file, $_);
 | 
						    process_name($file, $_);
 | 
				
			||||||
	} elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) {
 | 
						} elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE ||
 | 
				
			||||||
 | 
							 $state == STATE_BODY_WITH_BLANK_LINE) {
 | 
				
			||||||
	    process_body($file, $_);
 | 
						    process_body($file, $_);
 | 
				
			||||||
	} elsif ($state == STATE_INLINE) { # scanning for inline parameters
 | 
						} elsif ($state == STATE_INLINE) { # scanning for inline parameters
 | 
				
			||||||
	    process_inline($file, $_);
 | 
						    process_inline($file, $_);
 | 
				
			||||||
@ -2163,17 +2369,24 @@ sub process_file($) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Make sure we got something interesting.
 | 
					    # Make sure we got something interesting.
 | 
				
			||||||
    if ($initial_section_counter == $section_counter) {
 | 
					    if ($initial_section_counter == $section_counter && $
 | 
				
			||||||
	if ($output_mode ne "none") {
 | 
						output_mode ne "none") {
 | 
				
			||||||
 | 
						if ($output_selection == 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";
 | 
						    print STDERR "${file}:1: warning: no structured comments found\n";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
 | 
					 | 
				
			||||||
	    print STDERR "    Was looking for '$_'.\n" for keys %function_table;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    close IN_FILE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($output_mode eq "rst") {
 | 
				
			||||||
 | 
						get_sphinx_version() if (!$sphinx_major);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$kernelversion = get_kernel_version();
 | 
					$kernelversion = get_kernel_version();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# generate a sequence of code that will splice in highlighting information
 | 
					# generate a sequence of code that will splice in highlighting information
 | 
				
			||||||
@ -2220,4 +2433,9 @@ if ($verbose && $warnings) {
 | 
				
			|||||||
  print STDERR "$warnings warnings\n";
 | 
					  print STDERR "$warnings warnings\n";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exit($output_mode eq "none" ? 0 : $errors);
 | 
					if ($Werror && $warnings) {
 | 
				
			||||||
 | 
					    print STDERR "$warnings warnings as Errors\n";
 | 
				
			||||||
 | 
					    exit($warnings);
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					    exit($output_mode eq "none" ? 0 : $errors)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user