[U-Boot] [PATCH] doc: Replace DocBook with sphinx-based docs
Mario Six
mario.six at gdsys.cc
Tue Jul 10 06:40:17 UTC 2018
The Linux kernel moved to sphinx-based documentation and got rid of the
DocBook based documentation quite a while ago. Hence, the DocBook
documentation for U-Boot should be converted as well.
To achieve this, import the necessary files from Linux v4.17, and
convert the current DocBook documentation (three files altogether) to
sphinx/reStructuredText.
For now, all old DocBook documentation was merged into a single
handbook, tentatively named "U-Boot Hacker Manual".
For some source files, the documentation style was changed to comply
with kernel-doc; no functional changes were applied.
Signed-off-by: Mario Six <mario.six at gdsys.cc>
---
Documentation/.gitignore | 2 +
Documentation/Makefile | 124 +
Documentation/conf.py | 528 +++++
Documentation/index.rst | 117 +
Documentation/media/Makefile | 38 +
Documentation/media/linker_lists.h.rst.exceptions | 0
Documentation/sphinx-static/theme_overrides.css | 89 +
Documentation/sphinx/cdomain.py | 165 ++
Documentation/sphinx/kernel_include.py | 190 ++
Documentation/sphinx/kerneldoc.py | 146 ++
Documentation/sphinx/kfigure.py | 551 +++++
Documentation/sphinx/load_config.py | 32 +
Documentation/sphinx/parse-headers.pl | 401 ++++
Documentation/sphinx/requirements.txt | 3 +
Documentation/sphinx/rstFlatTable.py | 376 +++
Makefile | 8 +-
doc/DocBook/.gitignore | 15 -
doc/DocBook/Makefile | 222 --
doc/DocBook/docbook.css | 16 -
doc/DocBook/efi.tmpl | 17 -
doc/DocBook/linker_lists.tmpl | 46 -
doc/DocBook/stdio.tmpl | 46 -
doc/DocBook/stylesheet.xsl | 10 -
include/linker_lists.h | 164 +-
lib/efi_loader/efi_boottime.c | 946 ++++----
scripts/kernel-doc | 2527 +++++++++------------
26 files changed, 4375 insertions(+), 2404 deletions(-)
create mode 100644 Documentation/.gitignore
create mode 100644 Documentation/Makefile
create mode 100644 Documentation/conf.py
create mode 100644 Documentation/index.rst
create mode 100644 Documentation/media/Makefile
create mode 100644 Documentation/media/linker_lists.h.rst.exceptions
create mode 100644 Documentation/sphinx-static/theme_overrides.css
create mode 100644 Documentation/sphinx/cdomain.py
create mode 100755 Documentation/sphinx/kernel_include.py
create mode 100644 Documentation/sphinx/kerneldoc.py
create mode 100644 Documentation/sphinx/kfigure.py
create mode 100644 Documentation/sphinx/load_config.py
create mode 100755 Documentation/sphinx/parse-headers.pl
create mode 100644 Documentation/sphinx/requirements.txt
create mode 100755 Documentation/sphinx/rstFlatTable.py
delete mode 100644 doc/DocBook/.gitignore
delete mode 100644 doc/DocBook/Makefile
delete mode 100644 doc/DocBook/docbook.css
delete mode 100644 doc/DocBook/efi.tmpl
delete mode 100644 doc/DocBook/linker_lists.tmpl
delete mode 100644 doc/DocBook/stdio.tmpl
delete mode 100644 doc/DocBook/stylesheet.xsl
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644
index 0000000000..e74fec8693
--- /dev/null
+++ b/Documentation/.gitignore
@@ -0,0 +1,2 @@
+output
+*.pyc
diff --git a/Documentation/Makefile b/Documentation/Makefile
new file mode 100644
index 0000000000..2ca77ad0f2
--- /dev/null
+++ b/Documentation/Makefile
@@ -0,0 +1,124 @@
+# -*- makefile -*-
+# Makefile for Sphinx documentation
+#
+
+subdir-y :=
+
+# You can set these variables from the command line.
+SPHINXBUILD = sphinx-build
+SPHINXOPTS =
+SPHINXDIRS = .
+_SPHINXDIRS = $(patsubst $(srctree)/Documentation/%/conf.py,%,$(wildcard $(srctree)/Documentation/*/conf.py))
+SPHINX_CONF = conf.py
+PAPER =
+BUILDDIR = $(obj)/output
+PDFLATEX = xelatex
+LATEXOPTS = -interaction=batchmode
+
+# User-friendly check for sphinx-build
+HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
+
+ifeq ($(HAVE_SPHINX),0)
+
+.DEFAULT:
+ $(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.)
+ @echo
+ @./scripts/sphinx-pre-install
+ @echo " SKIP Sphinx $@ target."
+
+else # HAVE_SPHINX
+
+# User-friendly check for pdflatex
+HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi)
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+KERNELDOC = $(srctree)/scripts/kernel-doc
+KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC)
+ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+# commands; the 'cmd' from scripts/Kbuild.include is not *loopable*
+loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit;
+
+# $2 sphinx builder e.g. "html"
+# $3 name of the build subfolder / e.g. "media", used as:
+# * dest folder relative to $(BUILDDIR) and
+# * cache folder relative to $(BUILDDIR)/.doctrees
+# $4 dest subfolder e.g. "man" for man pages at media/man
+# $5 reST source folder relative to $(srctree)/$(src),
+# e.g. "media" for the linux-tv book-set at ./Documentation/media
+
+quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
+ cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2 && \
+ PYTHONDONTWRITEBYTECODE=1 \
+ BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
+ $(SPHINXBUILD) \
+ -b $2 \
+ -c $(abspath $(srctree)/$(src)) \
+ -d $(abspath $(BUILDDIR)/.doctrees/$3) \
+ -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \
+ $(ALLSPHINXOPTS) \
+ $(abspath $(srctree)/$(src)/$5) \
+ $(abspath $(BUILDDIR)/$3/$4)
+
+htmldocs:
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+
+linkcheckdocs:
+ @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
+
+latexdocs:
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
+
+ifeq ($(HAVE_PDFLATEX),0)
+
+pdfdocs:
+ $(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
+ @echo " SKIP Sphinx $@ target."
+
+else # HAVE_PDFLATEX
+
+pdfdocs: latexdocs
+ $(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit;)
+
+endif # HAVE_PDFLATEX
+
+epubdocs:
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var)))
+
+xmldocs:
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var)))
+
+endif # HAVE_SPHINX
+
+# The following targets are independent of HAVE_SPHINX, and the rules should
+# work or silently pass without Sphinx.
+
+refcheckdocs:
+ $(Q)cd $(srctree);scripts/documentation-file-ref-check
+
+cleandocs:
+ $(Q)rm -rf $(BUILDDIR)
+ $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media clean
+
+dochelp:
+ @echo ' Linux kernel internal documentation in different formats from ReST:'
+ @echo ' htmldocs - HTML'
+ @echo ' latexdocs - LaTeX'
+ @echo ' pdfdocs - PDF'
+ @echo ' epubdocs - EPUB'
+ @echo ' xmldocs - XML'
+ @echo ' linkcheckdocs - check for broken external links (will connect to external hosts)'
+ @echo ' refcheckdocs - check for references to non-existing files under Documentation'
+ @echo ' cleandocs - clean all generated files'
+ @echo
+ @echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2'
+ @echo ' valid values for SPHINXDIRS are: $(_SPHINXDIRS)'
+ @echo
+ @echo ' make SPHINX_CONF={conf-file} [target] use *additional* sphinx-build'
+ @echo ' configuration. This is e.g. useful to build with nit-picking config.'
+ @echo
+ @echo ' Default location for the generated documents is Documentation/output'
diff --git a/Documentation/conf.py b/Documentation/conf.py
new file mode 100644
index 0000000000..168c31346b
--- /dev/null
+++ b/Documentation/conf.py
@@ -0,0 +1,528 @@
+# -*- coding: utf-8 -*-
+#
+# The U-Boot documentation build configuration file, created by
+# sphinx-quickstart on Fri Feb 12 13:51:46 2016.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import sphinx
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('sphinx'))
+from load_config import loadConfig
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.3'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure']
+
+# The name of the math extension changed on Sphinx 1.4
+if major == 1 and minor > 3:
+ extensions.append("sphinx.ext.imgmath")
+else:
+ extensions.append("sphinx.ext.pngmath")
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'Das U-Boot'
+copyright = 'The U-Boot development community'
+author = 'The U-Boot development community'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# In a normal build, version and release are are set to KERNELVERSION and
+# KERNELRELEASE, respectively, from the Makefile via Sphinx command line
+# arguments.
+#
+# The following code tries to extract the information by reading the Makefile,
+# when Sphinx is run directly (e.g. by Read the Docs).
+try:
+ makefile_version = None
+ makefile_patchlevel = None
+ for line in open('../Makefile'):
+ key, val = [x.strip() for x in line.split('=', 2)]
+ if key == 'VERSION':
+ makefile_version = val
+ elif key == 'PATCHLEVEL':
+ makefile_patchlevel = val
+ if makefile_version and makefile_patchlevel:
+ break
+except:
+ pass
+finally:
+ if makefile_version and makefile_patchlevel:
+ version = release = makefile_version + '.' + makefile_patchlevel
+ else:
+ version = release = "unknown version"
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['output']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+primary_domain = 'c'
+highlight_language = 'none'
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+
+# The Read the Docs theme is available from
+# - https://github.com/snide/sphinx_rtd_theme
+# - https://pypi.python.org/pypi/sphinx_rtd_theme
+# - python-sphinx-rtd-theme package (on Debian)
+try:
+ import sphinx_rtd_theme
+ html_theme = 'sphinx_rtd_theme'
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+except ImportError:
+ sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n')
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# 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
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+
+html_static_path = ['sphinx-static']
+
+html_context = {
+ 'css_files': [
+ '_static/theme_overrides.css',
+ ],
+}
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'TheUBootdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+'pointsize': '8pt',
+
+# Latex figure (float) alignment
+#'figure_align': 'htbp',
+
+# Don't mangle with UTF-8 chars
+'inputenc': '',
+'utf8extra': '',
+
+# Additional stuff for the LaTeX preamble.
+ 'preamble': '''
+ % Use some font with UTF-8 support with XeLaTeX
+ \\usepackage{fontspec}
+ \\setsansfont{DejaVu Serif}
+ \\setromanfont{DejaVu Sans}
+ \\setmonofont{DejaVu Sans Mono}
+
+ '''
+}
+
+# Fix reference escape troubles with Sphinx 1.4.x
+if major == 1 and minor > 3:
+ latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
+
+if major == 1 and minor <= 4:
+ latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}'
+elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)):
+ latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in'
+ latex_elements['preamble'] += '\\fvset{fontsize=auto}\n'
+
+# Customize notice background colors on Sphinx < 1.6:
+if major == 1 and minor < 6:
+ latex_elements['preamble'] += '''
+ \\usepackage{ifthen}
+
+ % Put notes in color and let them be inside a table
+ \\definecolor{NoteColor}{RGB}{204,255,255}
+ \\definecolor{WarningColor}{RGB}{255,204,204}
+ \\definecolor{AttentionColor}{RGB}{255,255,204}
+ \\definecolor{ImportantColor}{RGB}{192,255,204}
+ \\definecolor{OtherColor}{RGB}{204,204,204}
+ \\newlength{\\mynoticelength}
+ \\makeatletter\\newenvironment{coloredbox}[1]{%
+ \\setlength{\\fboxrule}{1pt}
+ \\setlength{\\fboxsep}{7pt}
+ \\setlength{\\mynoticelength}{\\linewidth}
+ \\addtolength{\\mynoticelength}{-2\\fboxsep}
+ \\addtolength{\\mynoticelength}{-2\\fboxrule}
+ \\begin{lrbox}{\\@tempboxa}\\begin{minipage}{\\mynoticelength}}{\\end{minipage}\\end{lrbox}%
+ \\ifthenelse%
+ {\\equal{\\py at noticetype}{note}}%
+ {\\colorbox{NoteColor}{\\usebox{\\@tempboxa}}}%
+ {%
+ \\ifthenelse%
+ {\\equal{\\py at noticetype}{warning}}%
+ {\\colorbox{WarningColor}{\\usebox{\\@tempboxa}}}%
+ {%
+ \\ifthenelse%
+ {\\equal{\\py at noticetype}{attention}}%
+ {\\colorbox{AttentionColor}{\\usebox{\\@tempboxa}}}%
+ {%
+ \\ifthenelse%
+ {\\equal{\\py at noticetype}{important}}%
+ {\\colorbox{ImportantColor}{\\usebox{\\@tempboxa}}}%
+ {\\colorbox{OtherColor}{\\usebox{\\@tempboxa}}}%
+ }%
+ }%
+ }%
+ }\\makeatother
+
+ \\makeatletter
+ \\renewenvironment{notice}[2]{%
+ \\def\\py at noticetype{#1}
+ \\begin{coloredbox}{#1}
+ \\bf\\it
+ \\par\\strong{#2}
+ \\csname py at noticestart@#1\\endcsname
+ }
+ {
+ \\csname py at noticeend@\\py at noticetype\\endcsname
+ \\end{coloredbox}
+ }
+ \\makeatother
+
+ '''
+
+# With Sphinx 1.6, it is possible to change the Bg color directly
+# by using:
+# \definecolor{sphinxnoteBgColor}{RGB}{204,255,255}
+# \definecolor{sphinxwarningBgColor}{RGB}{255,204,204}
+# \definecolor{sphinxattentionBgColor}{RGB}{255,255,204}
+# \definecolor{sphinximportantBgColor}{RGB}{192,255,204}
+#
+# However, it require to use sphinx heavy box with:
+#
+# \renewenvironment{sphinxlightbox} {%
+# \\begin{sphinxheavybox}
+# }
+# \\end{sphinxheavybox}
+# }
+#
+# Unfortunately, the implementation is buggy: if a note is inside a
+# table, it isn't displayed well. So, for now, let's use boring
+# black and white notes.
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+# Sorted in alphabetical order
+latex_documents = [
+ ('index', 'u-boot-hacker-manual.tex', 'U-Boot Hacker Manual',
+ 'The U-Boot development community', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'dasuboot', 'The U-Boot Documentation',
+ [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'DasUBoot', 'The U-Boot Documentation',
+ author, 'DasUBoot', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not
+# optimized for small screen space, using the same theme for HTML and epub
+# output is usually not wise. This defaults to 'epub', a theme designed to save
+# visual space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files that should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
+
+#=======
+# rst2pdf
+#
+# Grouping the document tree into PDF files. List of tuples
+# (source start file, target name, title, author, options).
+#
+# See the Sphinx chapter of http://ralsina.me/static/manual.pdf
+#
+# 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
+# *between* PDF files.
+pdf_documents = [
+ ('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'),
+]
+
+# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
+# the Docs). In a normal build, these are supplied from the Makefile via command
+# line arguments.
+kerneldoc_bin = '../scripts/kernel-doc'
+kerneldoc_srctree = '..'
+
+# ------------------------------------------------------------------------------
+# Since loadConfig overwrites settings from the global namespace, it has to be
+# the last statement in the conf.py file
+# ------------------------------------------------------------------------------
+loadConfig(globals())
diff --git a/Documentation/index.rst b/Documentation/index.rst
new file mode 100644
index 0000000000..a7b0ee4e87
--- /dev/null
+++ b/Documentation/index.rst
@@ -0,0 +1,117 @@
+====================
+U-Boot Hacker Manual
+====================
+
+Linker-Generated Arrays
+=======================
+
+A linker list is constructed by grouping together linker input
+sections, each containing one entry of the list. Each input section
+contains a constant initialized variable which holds the entry's
+content. Linker list input sections are constructed from the list
+and entry names, plus a prefix which allows grouping all lists
+together. Assuming _list and _entry are the list and entry names,
+then the corresponding input section name is
+
+::
+
+ .u_boot_list_ + 2_ + @_list + _2_ + @_entry
+
+and the C variable name is
+
+::
+
+ _u_boot_list + _2_ + @_list + _2_ + @_entry
+
+This ensures uniqueness for both input section and C variable name.
+
+Note that the names differ only in the first character, "." for the
+section and "_" for the variable, so that the linker cannot confuse
+section and symbol names. From now on, both names will be referred
+to as
+
+::
+
+ %u_boot_list_ + 2_ + @_list + _2_ + @_entry
+
+Entry variables need never be referred to directly.
+
+The naming scheme for input sections allows grouping all linker lists
+into a single linker output section and grouping all entries for a
+single list.
+
+Note the two '_2_' constant components in the names: their presence
+allows putting a start and end symbols around a list, by mapping
+these symbols to sections names with components "1" (before) and
+"3" (after) instead of "2" (within).
+Start and end symbols for a list can generally be defined as
+
+::
+
+ %u_boot_list_2_ + @_list + _1_...
+ %u_boot_list_2_ + @_list + _3_...
+
+Start and end symbols for the whole of the linker lists area can be
+defined as
+
+::
+
+ %u_boot_list_1_...
+ %u_boot_list_3_...
+
+Here is an example of the sorted sections which result from a list
+"array" made up of three entries : "first", "second" and "third",
+iterated at least once.
+
+::
+
+ .u_boot_list_2_array_1
+ .u_boot_list_2_array_2_first
+ .u_boot_list_2_array_2_second
+ .u_boot_list_2_array_2_third
+ .u_boot_list_2_array_3
+
+If lists must be divided into sublists (e.g. for iterating only on
+part of a list), one can simply give the list a name of the form
+'outer_2_inner', where 'outer' is the global list name and 'inner'
+is the sub-list name. Iterators for the whole list should use the
+global list name ("outer"); iterators for only a sub-list should use
+the full sub-list name ("outer_2_inner").
+
+Here is an example of the sections generated from a global list
+named "drivers", two sub-lists named "i2c" and "pci", and iterators
+defined for the whole list and each sub-list:
+
+::
+
+ %u_boot_list_2_drivers_1
+ %u_boot_list_2_drivers_2_i2c_1
+ %u_boot_list_2_drivers_2_i2c_2_first
+ %u_boot_list_2_drivers_2_i2c_2_first
+ %u_boot_list_2_drivers_2_i2c_2_second
+ %u_boot_list_2_drivers_2_i2c_2_third
+ %u_boot_list_2_drivers_2_i2c_3
+ %u_boot_list_2_drivers_2_pci_1
+ %u_boot_list_2_drivers_2_pci_2_first
+ %u_boot_list_2_drivers_2_pci_2_second
+ %u_boot_list_2_drivers_2_pci_2_third
+ %u_boot_list_2_drivers_2_pci_3
+ %u_boot_list_2_drivers_3
+
+.. kernel-doc:: include/linker_lists.h
+ :internal:
+
+Serial system
+=============
+
+.. kernel-doc:: drivers/serial/serial.c
+ :internal:
+
+The U-Boot EFI subsystem
+========================
+
+Boot services
+-------------
+
+.. kernel-doc:: lib/efi_loader/efi_boottime.c
+ :internal:
diff --git a/Documentation/media/Makefile b/Documentation/media/Makefile
new file mode 100644
index 0000000000..0efd18ab4d
--- /dev/null
+++ b/Documentation/media/Makefile
@@ -0,0 +1,38 @@
+# Rules to convert a .h file to inline RST documentation
+
+SRC_DIR=$(srctree)/Documentation/media
+PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
+API = $(srctree)/include
+
+FILES = linker_lists.h.rst
+
+TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
+
+gen_rst = \
+ echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
+ ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
+
+quiet_gen_rst = echo ' PARSE $(patsubst $(srctree)/%,%,$<)'; \
+ ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
+
+silent_gen_rst = ${gen_rst}
+
+$(BUILDDIR)/linker_lists.h.rst: ${API}/linker_lists.h ${PARSER} $(SRC_DIR)/linker_lists.h.rst.exceptions
+ @$($(quiet)gen_rst)
+
+# Media build rules
+
+.PHONY: all html epub xml latex
+
+all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
+html: all
+epub: all
+xml: all
+latex: $(IMGPDF) all
+linkcheck:
+
+clean:
+ -rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
+
+$(BUILDDIR):
+ $(Q)mkdir -p $@
diff --git a/Documentation/media/linker_lists.h.rst.exceptions b/Documentation/media/linker_lists.h.rst.exceptions
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Documentation/sphinx-static/theme_overrides.css b/Documentation/sphinx-static/theme_overrides.css
new file mode 100644
index 0000000000..522b6d4c49
--- /dev/null
+++ b/Documentation/sphinx-static/theme_overrides.css
@@ -0,0 +1,89 @@
+/* -*- coding: utf-8; mode: css -*-
+ *
+ * Sphinx HTML theme customization: read the doc
+ *
+ */
+
+/* Interim: Code-blocks with line nos - lines and line numbers don't line up.
+ * see: https://github.com/rtfd/sphinx_rtd_theme/issues/419
+ */
+
+div[class^="highlight"] pre {
+ line-height: normal;
+}
+.rst-content .highlight > pre {
+ line-height: normal;
+}
+
+ at media screen {
+
+ /* content column
+ *
+ * RTD theme's default is 800px as max width for the content, but we have
+ * tables with tons of columns, which need the full width of the view-port.
+ */
+
+ .wy-nav-content{max-width: none; }
+
+ /* table:
+ *
+ * - Sequences of whitespace should collapse into a single whitespace.
+ * - make the overflow auto (scrollbar if needed)
+ * - align caption "left" ("center" is unsuitable on vast tables)
+ */
+
+ .wy-table-responsive table td { white-space: normal; }
+ .wy-table-responsive { overflow: auto; }
+ .rst-content table.docutils caption { text-align: left; font-size: 100%; }
+
+ /* captions:
+ *
+ * - captions should have 100% (not 85%) font size
+ * - hide the permalink symbol as long as link is not hovered
+ */
+
+ .toc-title {
+ font-size: 150%;
+ font-weight: bold;
+ }
+
+ caption, .wy-table caption, .rst-content table.field-list caption {
+ font-size: 100%;
+ }
+ caption a.headerlink { opacity: 0; }
+ caption a.headerlink:hover { opacity: 1; }
+
+ /* Menu selection and keystrokes */
+
+ span.menuselection {
+ color: blue;
+ font-family: "Courier New", Courier, monospace
+ }
+
+ code.kbd, code.kbd span {
+ color: white;
+ background-color: darkblue;
+ font-weight: bold;
+ font-family: "Courier New", Courier, monospace
+ }
+
+ /* fix bottom margin of lists items */
+
+ .rst-content .section ul li:last-child, .rst-content .section ul li p:last-child {
+ margin-bottom: 12px;
+ }
+
+ /* inline literal: drop the borderbox, padding and red color */
+
+ code, .rst-content tt, .rst-content code {
+ color: inherit;
+ border: none;
+ padding: unset;
+ background: inherit;
+ font-size: 85%;
+ }
+
+ .rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
+ color: inherit;
+ }
+}
diff --git a/Documentation/sphinx/cdomain.py b/Documentation/sphinx/cdomain.py
new file mode 100644
index 0000000000..cf13ff3a65
--- /dev/null
+++ b/Documentation/sphinx/cdomain.py
@@ -0,0 +1,165 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=W0141,C0113,C0103,C0325
+u"""
+ cdomain
+ ~~~~~~~
+
+ Replacement for the sphinx c-domain.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :license: GPL Version 2, June 1991 see Linux/COPYING for details.
+
+ List of customizations:
+
+ * Moved the *duplicate C object description* warnings for function
+ declarations in the nitpicky mode. See Sphinx documentation for
+ the config values for ``nitpick`` and ``nitpick_ignore``.
+
+ * Add option 'name' to the "c:function:" directive. With option 'name' the
+ ref-name of a function can be modified. E.g.::
+
+ .. c:function:: int ioctl( int fd, int request )
+ :name: VIDIOC_LOG_STATUS
+
+ The func-name (e.g. ioctl) remains in the output but the ref-name changed
+ from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by::
+
+ * :c:func:`VIDIOC_LOG_STATUS` or
+ * :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3)
+
+ * Handle signatures of function-like macros well. Don't try to deduce
+ arguments types of function-like macros.
+
+"""
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+import sphinx
+from sphinx import addnodes
+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 CDomain as Base_CDomain
+
+__version__ = '1.0'
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+
+def setup(app):
+
+ app.override_domain(CDomain)
+
+ return dict(
+ version = __version__,
+ parallel_read_safe = True,
+ parallel_write_safe = True
+ )
+
+class CObject(Base_CObject):
+
+ """
+ Description of a C language object.
+ """
+ option_spec = {
+ "name" : directives.unchanged
+ }
+
+ def handle_func_like_macro(self, sig, signode):
+ u"""Handles signatures of function-like macros.
+
+ If the objtype is 'function' and the the signature ``sig`` is a
+ function-like macro, the name of the macro is returned. Otherwise
+ ``False`` is returned. """
+
+ if not self.objtype == 'function':
+ return False
+
+ m = c_funcptr_sig_re.match(sig)
+ if m is None:
+ m = c_sig_re.match(sig)
+ if m is None:
+ raise ValueError('no match')
+
+ rettype, fullname, arglist, _const = m.groups()
+ arglist = arglist.strip()
+ if rettype or not arglist:
+ return False
+
+ arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
+ arglist = [a.strip() for a in arglist.split(",")]
+
+ # has the first argument a type?
+ if len(arglist[0].split(" ")) > 1:
+ return False
+
+ # This is a function-like macro, it's arguments are typeless!
+ signode += addnodes.desc_name(fullname, fullname)
+ paramlist = addnodes.desc_parameterlist()
+ signode += paramlist
+
+ for argname in arglist:
+ param = addnodes.desc_parameter('', '', noemph=True)
+ # separate by non-breaking space in the output
+ param += nodes.emphasis(argname, argname)
+ paramlist += param
+
+ return fullname
+
+ def handle_signature(self, sig, signode):
+ """Transform a C signature into RST nodes."""
+
+ fullname = self.handle_func_like_macro(sig, signode)
+ if not fullname:
+ fullname = super(CObject, self).handle_signature(sig, signode)
+
+ if "name" in self.options:
+ if self.objtype == 'function':
+ fullname = self.options["name"]
+ else:
+ # FIXME: handle :name: value of other declaration types?
+ pass
+ return fullname
+
+ def add_target_and_index(self, name, sig, signode):
+ # for C API items we add a prefix since names are usually not qualified
+ # by a module name and so easily clash with e.g. section titles
+ targetname = 'c.' + name
+ if targetname not in self.state.document.ids:
+ signode['names'].append(targetname)
+ signode['ids'].append(targetname)
+ signode['first'] = (not self.names)
+ self.state.document.note_explicit_target(signode)
+ inv = self.env.domaindata['c']['objects']
+ if (name in inv and self.env.config.nitpicky):
+ if self.objtype == 'function':
+ if ('c:func', name) not in self.env.config.nitpick_ignore:
+ self.state_machine.reporter.warning(
+ 'duplicate C object description of %s, ' % name +
+ 'other instance in ' + self.env.doc2path(inv[name][0]),
+ line=self.lineno)
+ inv[name] = (self.env.docname, self.objtype)
+
+ indextext = self.get_index_text(name)
+ if indextext:
+ if major == 1 and minor < 4:
+ # indexnode's tuple changed in 1.4
+ # https://github.com/sphinx-doc/sphinx/commit/e6a5a3a92e938fcd75866b4227db9e0524d58f7c
+ self.indexnode['entries'].append(
+ ('single', indextext, targetname, ''))
+ else:
+ self.indexnode['entries'].append(
+ ('single', indextext, targetname, '', None))
+
+class CDomain(Base_CDomain):
+
+ """C language domain."""
+ name = 'c'
+ label = 'C'
+ directives = {
+ 'function': CObject,
+ 'member': CObject,
+ 'macro': CObject,
+ 'type': CObject,
+ 'var': CObject,
+ }
diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py
new file mode 100755
index 0000000000..f523aa68a3
--- /dev/null
+++ b/Documentation/sphinx/kernel_include.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=R0903, C0330, R0914, R0912, E0401
+
+u"""
+ kernel-include
+ ~~~~~~~~~~~~~~
+
+ Implementation of the ``kernel-include`` reST-directive.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :license: GPL Version 2, June 1991 see linux/COPYING for details.
+
+ The ``kernel-include`` reST-directive is a replacement for the ``include``
+ directive. The ``kernel-include`` directive expand environment variables in
+ the path name and allows to include files from arbitrary locations.
+
+ .. hint::
+
+ Including files from arbitrary locations (e.g. from ``/etc``) is a
+ security risk for builders. This is why the ``include`` directive from
+ docutils *prohibit* pathnames pointing to locations *above* the filesystem
+ tree where the reST document with the include directive is placed.
+
+ Substrings of the form $name or ${name} are replaced by the value of
+ environment variable name. Malformed variable names and references to
+ non-existing variables are left unchanged.
+"""
+
+# ==============================================================================
+# imports
+# ==============================================================================
+
+import os.path
+
+from docutils import io, nodes, statemachine
+from docutils.utils.error_reporting import SafeString, ErrorString
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
+from docutils.parsers.rst.directives.misc import Include
+
+__version__ = '1.0'
+
+# ==============================================================================
+def setup(app):
+# ==============================================================================
+
+ app.add_directive("kernel-include", KernelInclude)
+ return dict(
+ version = __version__,
+ parallel_read_safe = True,
+ parallel_write_safe = True
+ )
+
+# ==============================================================================
+class KernelInclude(Include):
+# ==============================================================================
+
+ u"""KernelInclude (``kernel-include``) directive"""
+
+ def run(self):
+ path = os.path.realpath(
+ os.path.expandvars(self.arguments[0]))
+
+ # to get a bit security back, prohibit /etc:
+ if path.startswith(os.sep + "etc"):
+ raise self.severe(
+ 'Problems with "%s" directive, prohibited path: %s'
+ % (self.name, path))
+
+ self.arguments[0] = path
+
+ #return super(KernelInclude, self).run() # won't work, see HINTs in _run()
+ return self._run()
+
+ def _run(self):
+ """Include a file as part of the content of this reST file."""
+
+ # HINT: I had to copy&paste the whole Include.run method. I'am not happy
+ # with this, but due to security reasons, the Include.run method does
+ # not allow absolute or relative pathnames pointing to locations *above*
+ # the filesystem tree where the reST document is placed.
+
+ if not self.state.document.settings.file_insertion_enabled:
+ raise self.warning('"%s" directive disabled.' % self.name)
+ source = self.state_machine.input_lines.source(
+ self.lineno - self.state_machine.input_offset - 1)
+ source_dir = os.path.dirname(os.path.abspath(source))
+ path = directives.path(self.arguments[0])
+ if path.startswith('<') and path.endswith('>'):
+ path = os.path.join(self.standard_include_path, path[1:-1])
+ path = os.path.normpath(os.path.join(source_dir, path))
+
+ # HINT: this is the only line I had to change / commented out:
+ #path = utils.relative_path(None, path)
+
+ path = nodes.reprunicode(path)
+ encoding = self.options.get(
+ 'encoding', self.state.document.settings.input_encoding)
+ e_handler=self.state.document.settings.input_encoding_error_handler
+ tab_width = self.options.get(
+ 'tab-width', self.state.document.settings.tab_width)
+ try:
+ self.state.document.settings.record_dependencies.add(path)
+ include_file = io.FileInput(source_path=path,
+ encoding=encoding,
+ error_handler=e_handler)
+ except UnicodeEncodeError as error:
+ raise self.severe('Problems with "%s" directive path:\n'
+ 'Cannot encode input file path "%s" '
+ '(wrong locale?).' %
+ (self.name, SafeString(path)))
+ except IOError as error:
+ raise self.severe('Problems with "%s" directive path:\n%s.' %
+ (self.name, ErrorString(error)))
+ startline = self.options.get('start-line', None)
+ endline = self.options.get('end-line', None)
+ try:
+ if startline or (endline is not None):
+ lines = include_file.readlines()
+ rawtext = ''.join(lines[startline:endline])
+ else:
+ rawtext = include_file.read()
+ except UnicodeError as error:
+ raise self.severe('Problem with "%s" directive:\n%s' %
+ (self.name, ErrorString(error)))
+ # start-after/end-before: no restrictions on newlines in match-text,
+ # and no restrictions on matching inside lines vs. line boundaries
+ after_text = self.options.get('start-after', None)
+ if after_text:
+ # skip content in rawtext before *and incl.* a matching text
+ after_index = rawtext.find(after_text)
+ if after_index < 0:
+ raise self.severe('Problem with "start-after" option of "%s" '
+ 'directive:\nText not found.' % self.name)
+ rawtext = rawtext[after_index + len(after_text):]
+ before_text = self.options.get('end-before', None)
+ if before_text:
+ # skip content in rawtext after *and incl.* a matching text
+ before_index = rawtext.find(before_text)
+ if before_index < 0:
+ raise self.severe('Problem with "end-before" option of "%s" '
+ 'directive:\nText not found.' % self.name)
+ rawtext = rawtext[:before_index]
+
+ include_lines = statemachine.string2lines(rawtext, tab_width,
+ convert_whitespace=True)
+ if 'literal' in self.options:
+ # Convert tabs to spaces, if `tab_width` is positive.
+ if tab_width >= 0:
+ text = rawtext.expandtabs(tab_width)
+ else:
+ text = rawtext
+ literal_block = nodes.literal_block(rawtext, source=path,
+ classes=self.options.get('class', []))
+ literal_block.line = 1
+ self.add_name(literal_block)
+ if 'number-lines' in self.options:
+ try:
+ startline = int(self.options['number-lines'] or 1)
+ except ValueError:
+ raise self.error(':number-lines: with non-integer '
+ 'start value')
+ endline = startline + len(include_lines)
+ if text.endswith('\n'):
+ text = text[:-1]
+ tokens = NumberLines([([], text)], startline, endline)
+ for classes, value in tokens:
+ if classes:
+ literal_block += nodes.inline(value, value,
+ classes=classes)
+ else:
+ literal_block += nodes.Text(value, value)
+ else:
+ literal_block += nodes.Text(text, text)
+ return [literal_block]
+ if 'code' in self.options:
+ self.options['source'] = path
+ codeblock = CodeBlock(self.name,
+ [self.options.pop('code')], # arguments
+ self.options,
+ include_lines, # content
+ self.lineno,
+ self.content_offset,
+ self.block_text,
+ self.state,
+ self.state_machine)
+ return codeblock.run()
+ self.state_machine.insert_input(include_lines, path)
+ return []
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py
new file mode 100644
index 0000000000..fbedcc3946
--- /dev/null
+++ b/Documentation/sphinx/kerneldoc.py
@@ -0,0 +1,146 @@
+# coding=utf-8
+#
+# Copyright © 2016 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Authors:
+# Jani Nikula <jani.nikula at intel.com>
+#
+# Please make sure this works on both python2 and python3.
+#
+
+import codecs
+import os
+import subprocess
+import sys
+import re
+import glob
+
+from docutils import nodes, statemachine
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives, Directive
+from sphinx.ext.autodoc import AutodocReporter
+
+__version__ = '1.0'
+
+class KernelDocDirective(Directive):
+ """Extract kernel-doc comments from the specified file"""
+ required_argument = 1
+ optional_arguments = 4
+ option_spec = {
+ 'doc': directives.unchanged_required,
+ 'functions': directives.unchanged_required,
+ 'export': directives.unchanged,
+ 'internal': directives.unchanged,
+ }
+ has_content = False
+
+ def run(self):
+ env = self.state.document.settings.env
+ cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
+
+ filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
+ export_file_patterns = []
+
+ # Tell sphinx of the dependency
+ env.note_dependency(os.path.abspath(filename))
+
+ tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
+
+ # FIXME: make this nicer and more robust against errors
+ if 'export' in self.options:
+ cmd += ['-export']
+ export_file_patterns = str(self.options.get('export')).split()
+ elif 'internal' in self.options:
+ cmd += ['-internal']
+ export_file_patterns = str(self.options.get('internal')).split()
+ elif 'doc' in self.options:
+ cmd += ['-function', str(self.options.get('doc'))]
+ elif 'functions' in self.options:
+ for f in str(self.options.get('functions')).split():
+ cmd += ['-function', f]
+
+ for pattern in export_file_patterns:
+ for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
+ env.note_dependency(os.path.abspath(f))
+ cmd += ['-export-file', f]
+
+ cmd += [filename]
+
+ try:
+ env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
+
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+
+ out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+
+ if p.returncode != 0:
+ sys.stderr.write(err)
+
+ env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
+ return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+ elif env.config.kerneldoc_verbosity > 0:
+ sys.stderr.write(err)
+
+ lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
+ result = ViewList()
+
+ lineoffset = 0;
+ line_regex = re.compile("^#define LINENO ([0-9]+)$")
+ for line in lines:
+ match = line_regex.search(line)
+ if match:
+ # sphinx counts lines from 0
+ lineoffset = int(match.group(1)) - 1
+ # we must eat our comments since the upset the markup
+ else:
+ result.append(line, filename, lineoffset)
+ lineoffset += 1
+
+ node = nodes.section()
+ buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+ self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
+ self.state.memo.title_styles, self.state.memo.section_level = [], 0
+ try:
+ self.state.nested_parse(result, 0, node, match_titles=1)
+ finally:
+ self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
+ return node.children
+
+ except Exception as e: # pylint: disable=W0703
+ env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
+ (" ".join(cmd), str(e)))
+ return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+
+def setup(app):
+ app.add_config_value('kerneldoc_bin', None, 'env')
+ app.add_config_value('kerneldoc_srctree', None, 'env')
+ app.add_config_value('kerneldoc_verbosity', 1, 'env')
+
+ app.add_directive('kernel-doc', KernelDocDirective)
+
+ return dict(
+ version = __version__,
+ parallel_read_safe = True,
+ parallel_write_safe = True
+ )
diff --git a/Documentation/sphinx/kfigure.py b/Documentation/sphinx/kfigure.py
new file mode 100644
index 0000000000..b97228d2cc
--- /dev/null
+++ b/Documentation/sphinx/kfigure.py
@@ -0,0 +1,551 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=C0103, R0903, R0912, R0915
+u"""
+ scalable figure and image handling
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Sphinx extension which implements scalable image handling.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :license: GPL Version 2, June 1991 see Linux/COPYING for details.
+
+ The build for image formats depend on image's source format and output's
+ destination format. This extension implement methods to simplify image
+ handling from the author's POV. Directives like ``kernel-figure`` implement
+ methods *to* always get the best output-format even if some tools are not
+ installed. For more details take a look at ``convert_image(...)`` which is
+ the core of all conversions.
+
+ * ``.. kernel-image``: for image handling / a ``.. image::`` replacement
+
+ * ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement
+
+ * ``.. kernel-render``: for render markup / a concept to embed *render*
+ markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``)
+
+ - ``DOT``: render embedded Graphviz's **DOC**
+ - ``SVG``: render embedded Scalable Vector Graphics (**SVG**)
+ - ... *developable*
+
+ Used tools:
+
+ * ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not
+ available, the DOT language is inserted as literal-block.
+
+ * SVG to PDF: To generate PDF, you need at least one of this tools:
+
+ - ``convert(1)``: ImageMagick (https://www.imagemagick.org)
+
+ List of customizations:
+
+ * generate PDF from SVG / used by PDF (LaTeX) builder
+
+ * generate SVG (html-builder) and PDF (latex-builder) from DOT files.
+ DOT: see http://www.graphviz.org/content/dot-language
+
+ """
+
+import os
+from os import path
+import subprocess
+from hashlib import sha1
+import sys
+
+from docutils import nodes
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives import images
+import sphinx
+
+from sphinx.util.nodes import clean_astext
+from six import iteritems
+
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+ _unicode = str
+else:
+ _unicode = unicode
+
+# Get Sphinx version
+major, minor, patch = sphinx.version_info[:3]
+if major == 1 and minor > 3:
+ # patches.Figure only landed in Sphinx 1.4
+ from sphinx.directives.patches import Figure # pylint: disable=C0413
+else:
+ Figure = images.Figure
+
+__version__ = '1.0.0'
+
+# simple helper
+# -------------
+
+def which(cmd):
+ """Searches the ``cmd`` in the ``PATH`` environment.
+
+ This *which* searches the PATH for executable ``cmd`` . First match is
+ returned, if nothing is found, ``None` is returned.
+ """
+ envpath = os.environ.get('PATH', None) or os.defpath
+ for folder in envpath.split(os.pathsep):
+ fname = folder + os.sep + cmd
+ if path.isfile(fname):
+ return fname
+
+def mkdir(folder, mode=0o775):
+ if not path.isdir(folder):
+ os.makedirs(folder, mode)
+
+def file2literal(fname):
+ with open(fname, "r") as src:
+ data = src.read()
+ node = nodes.literal_block(data, data)
+ return node
+
+def isNewer(path1, path2):
+ """Returns True if ``path1`` is newer than ``path2``
+
+ If ``path1`` exists and is newer than ``path2`` the function returns
+ ``True`` is returned otherwise ``False``
+ """
+ return (path.exists(path1)
+ and os.stat(path1).st_ctime > os.stat(path2).st_ctime)
+
+def pass_handle(self, node): # pylint: disable=W0613
+ pass
+
+# setup conversion tools and sphinx extension
+# -------------------------------------------
+
+# Graphviz's dot(1) support
+dot_cmd = None
+
+# ImageMagick' convert(1) support
+convert_cmd = None
+
+
+def setup(app):
+ # check toolchain first
+ app.connect('builder-inited', setupTools)
+
+ # image handling
+ app.add_directive("kernel-image", KernelImage)
+ app.add_node(kernel_image,
+ html = (visit_kernel_image, pass_handle),
+ latex = (visit_kernel_image, pass_handle),
+ texinfo = (visit_kernel_image, pass_handle),
+ text = (visit_kernel_image, pass_handle),
+ man = (visit_kernel_image, pass_handle), )
+
+ # figure handling
+ app.add_directive("kernel-figure", KernelFigure)
+ app.add_node(kernel_figure,
+ html = (visit_kernel_figure, pass_handle),
+ latex = (visit_kernel_figure, pass_handle),
+ texinfo = (visit_kernel_figure, pass_handle),
+ text = (visit_kernel_figure, pass_handle),
+ man = (visit_kernel_figure, pass_handle), )
+
+ # render handling
+ app.add_directive('kernel-render', KernelRender)
+ app.add_node(kernel_render,
+ html = (visit_kernel_render, pass_handle),
+ latex = (visit_kernel_render, pass_handle),
+ texinfo = (visit_kernel_render, pass_handle),
+ text = (visit_kernel_render, pass_handle),
+ man = (visit_kernel_render, pass_handle), )
+
+ app.connect('doctree-read', add_kernel_figure_to_std_domain)
+
+ return dict(
+ version = __version__,
+ parallel_read_safe = True,
+ parallel_write_safe = True
+ )
+
+
+def setupTools(app):
+ u"""
+ Check available build tools and log some *verbose* messages.
+
+ This function is called once, when the builder is initiated.
+ """
+ global dot_cmd, convert_cmd # pylint: disable=W0603
+ app.verbose("kfigure: check installed tools ...")
+
+ dot_cmd = which('dot')
+ convert_cmd = which('convert')
+
+ if dot_cmd:
+ app.verbose("use dot(1) from: " + dot_cmd)
+ else:
+ app.warn("dot(1) not found, for better output quality install "
+ "graphviz from http://www.graphviz.org")
+ if convert_cmd:
+ app.verbose("use convert(1) from: " + convert_cmd)
+ else:
+ app.warn(
+ "convert(1) not found, for SVG to PDF conversion install "
+ "ImageMagick (https://www.imagemagick.org)")
+
+
+# integrate conversion tools
+# --------------------------
+
+RENDER_MARKUP_EXT = {
+ # The '.ext' must be handled by convert_image(..) function's *in_ext* input.
+ # <name> : <.ext>
+ 'DOT' : '.dot',
+ 'SVG' : '.svg'
+}
+
+def convert_image(img_node, translator, src_fname=None):
+ """Convert a image node for the builder.
+
+ Different builder prefer different image formats, e.g. *latex* builder
+ prefer PDF while *html* builder prefer SVG format for images.
+
+ This function handles output image formats in dependence of source the
+ format (of the image) and the translator's output format.
+ """
+ app = translator.builder.app
+
+ fname, in_ext = path.splitext(path.basename(img_node['uri']))
+ if src_fname is None:
+ src_fname = path.join(translator.builder.srcdir, img_node['uri'])
+ if not path.exists(src_fname):
+ src_fname = path.join(translator.builder.outdir, img_node['uri'])
+
+ dst_fname = None
+
+ # in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages
+
+ app.verbose('assert best format for: ' + img_node['uri'])
+
+ if in_ext == '.dot':
+
+ if not dot_cmd:
+ app.verbose("dot from graphviz not available / include DOT raw.")
+ img_node.replace_self(file2literal(src_fname))
+
+ elif translator.builder.format == 'latex':
+ dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
+ img_node['uri'] = fname + '.pdf'
+ img_node['candidates'] = {'*': fname + '.pdf'}
+
+
+ elif translator.builder.format == 'html':
+ dst_fname = path.join(
+ translator.builder.outdir,
+ translator.builder.imagedir,
+ fname + '.svg')
+ img_node['uri'] = path.join(
+ translator.builder.imgpath, fname + '.svg')
+ img_node['candidates'] = {
+ '*': path.join(translator.builder.imgpath, fname + '.svg')}
+
+ else:
+ # all other builder formats will include DOT as raw
+ img_node.replace_self(file2literal(src_fname))
+
+ elif in_ext == '.svg':
+
+ if translator.builder.format == 'latex':
+ if convert_cmd is None:
+ app.verbose("no SVG to PDF conversion available / include SVG raw.")
+ img_node.replace_self(file2literal(src_fname))
+ else:
+ dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
+ img_node['uri'] = fname + '.pdf'
+ img_node['candidates'] = {'*': fname + '.pdf'}
+
+ if dst_fname:
+ # the builder needs not to copy one more time, so pop it if exists.
+ translator.builder.images.pop(img_node['uri'], None)
+ _name = dst_fname[len(translator.builder.outdir) + 1:]
+
+ if isNewer(dst_fname, src_fname):
+ app.verbose("convert: {out}/%s already exists and is newer" % _name)
+
+ else:
+ ok = False
+ mkdir(path.dirname(dst_fname))
+
+ if in_ext == '.dot':
+ app.verbose('convert DOT to: {out}/' + _name)
+ ok = dot2format(app, src_fname, dst_fname)
+
+ elif in_ext == '.svg':
+ app.verbose('convert SVG to: {out}/' + _name)
+ ok = svg2pdf(app, src_fname, dst_fname)
+
+ if not ok:
+ img_node.replace_self(file2literal(src_fname))
+
+
+def dot2format(app, dot_fname, out_fname):
+ """Converts DOT file to ``out_fname`` using ``dot(1)``.
+
+ * ``dot_fname`` pathname of the input DOT file, including extension ``.dot``
+ * ``out_fname`` pathname of the output file, including format extension
+
+ The *format extension* depends on the ``dot`` command (see ``man dot``
+ option ``-Txxx``). Normally you will use one of the following extensions:
+
+ - ``.ps`` for PostScript,
+ - ``.svg`` or ``svgz`` for Structured Vector Graphics,
+ - ``.fig`` for XFIG graphics and
+ - ``.png`` or ``gif`` for common bitmap graphics.
+
+ """
+ out_format = path.splitext(out_fname)[1][1:]
+ cmd = [dot_cmd, '-T%s' % out_format, dot_fname]
+ exit_code = 42
+
+ with open(out_fname, "w") as out:
+ exit_code = subprocess.call(cmd, stdout = out)
+ if exit_code != 0:
+ app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
+ return bool(exit_code == 0)
+
+def svg2pdf(app, svg_fname, pdf_fname):
+ """Converts SVG to PDF with ``convert(1)`` command.
+
+ Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for
+ conversion. Returns ``True`` on success and ``False`` if an error occurred.
+
+ * ``svg_fname`` pathname of the input SVG file with extension (``.svg``)
+ * ``pdf_name`` pathname of the output PDF file with extension (``.pdf``)
+
+ """
+ cmd = [convert_cmd, svg_fname, pdf_fname]
+ # use stdout and stderr from parent
+ exit_code = subprocess.call(cmd)
+ if exit_code != 0:
+ app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
+ return bool(exit_code == 0)
+
+
+# image handling
+# ---------------------
+
+def visit_kernel_image(self, node): # pylint: disable=W0613
+ """Visitor of the ``kernel_image`` Node.
+
+ Handles the ``image`` child-node with the ``convert_image(...)``.
+ """
+ img_node = node[0]
+ convert_image(img_node, self)
+
+class kernel_image(nodes.image):
+ """Node for ``kernel-image`` directive."""
+ pass
+
+class KernelImage(images.Image):
+ u"""KernelImage directive
+
+ Earns everything from ``.. image::`` directive, except *remote URI* and
+ *glob* pattern. The KernelImage wraps a image node into a
+ kernel_image node. See ``visit_kernel_image``.
+ """
+
+ def run(self):
+ uri = self.arguments[0]
+ if uri.endswith('.*') or uri.find('://') != -1:
+ raise self.severe(
+ 'Error in "%s: %s": glob pattern and remote images are not allowed'
+ % (self.name, uri))
+ result = images.Image.run(self)
+ if len(result) == 2 or isinstance(result[0], nodes.system_message):
+ return result
+ (image_node,) = result
+ # wrap image node into a kernel_image node / see visitors
+ node = kernel_image('', image_node)
+ return [node]
+
+# figure handling
+# ---------------------
+
+def visit_kernel_figure(self, node): # pylint: disable=W0613
+ """Visitor of the ``kernel_figure`` Node.
+
+ Handles the ``image`` child-node with the ``convert_image(...)``.
+ """
+ img_node = node[0][0]
+ convert_image(img_node, self)
+
+class kernel_figure(nodes.figure):
+ """Node for ``kernel-figure`` directive."""
+
+class KernelFigure(Figure):
+ u"""KernelImage directive
+
+ Earns everything from ``.. figure::`` directive, except *remote URI* and
+ *glob* pattern. The KernelFigure wraps a figure node into a kernel_figure
+ node. See ``visit_kernel_figure``.
+ """
+
+ def run(self):
+ uri = self.arguments[0]
+ if uri.endswith('.*') or uri.find('://') != -1:
+ raise self.severe(
+ 'Error in "%s: %s":'
+ ' glob pattern and remote images are not allowed'
+ % (self.name, uri))
+ result = Figure.run(self)
+ if len(result) == 2 or isinstance(result[0], nodes.system_message):
+ return result
+ (figure_node,) = result
+ # wrap figure node into a kernel_figure node / see visitors
+ node = kernel_figure('', figure_node)
+ return [node]
+
+
+# render handling
+# ---------------------
+
+def visit_kernel_render(self, node):
+ """Visitor of the ``kernel_render`` Node.
+
+ If rendering tools available, save the markup of the ``literal_block`` child
+ node into a file and replace the ``literal_block`` node with a new created
+ ``image`` node, pointing to the saved markup file. Afterwards, handle the
+ image child-node with the ``convert_image(...)``.
+ """
+ app = self.builder.app
+ srclang = node.get('srclang')
+
+ app.verbose('visit kernel-render node lang: "%s"' % (srclang))
+
+ tmp_ext = RENDER_MARKUP_EXT.get(srclang, None)
+ if tmp_ext is None:
+ app.warn('kernel-render: "%s" unknown / include raw.' % (srclang))
+ return
+
+ if not dot_cmd and tmp_ext == '.dot':
+ app.verbose("dot from graphviz not available / include raw.")
+ return
+
+ literal_block = node[0]
+
+ code = literal_block.astext()
+ hashobj = code.encode('utf-8') # str(node.attributes)
+ fname = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest()))
+
+ tmp_fname = path.join(
+ self.builder.outdir, self.builder.imagedir, fname + tmp_ext)
+
+ if not path.isfile(tmp_fname):
+ mkdir(path.dirname(tmp_fname))
+ with open(tmp_fname, "w") as out:
+ out.write(code)
+
+ img_node = nodes.image(node.rawsource, **node.attributes)
+ img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext)
+ img_node['candidates'] = {
+ '*': path.join(self.builder.imgpath, fname + tmp_ext)}
+
+ literal_block.replace_self(img_node)
+ convert_image(img_node, self, tmp_fname)
+
+
+class kernel_render(nodes.General, nodes.Inline, nodes.Element):
+ """Node for ``kernel-render`` directive."""
+ pass
+
+class KernelRender(Figure):
+ u"""KernelRender directive
+
+ Render content by external tool. Has all the options known from the
+ *figure* directive, plus option ``caption``. If ``caption`` has a
+ value, a figure node with the *caption* is inserted. If not, a image node is
+ inserted.
+
+ The KernelRender directive wraps the text of the directive into a
+ literal_block node and wraps it into a kernel_render node. See
+ ``visit_kernel_render``.
+ """
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = False
+
+ # earn options from 'figure'
+ option_spec = Figure.option_spec.copy()
+ option_spec['caption'] = directives.unchanged
+
+ def run(self):
+ return [self.build_node()]
+
+ def build_node(self):
+
+ srclang = self.arguments[0].strip()
+ if srclang not in RENDER_MARKUP_EXT.keys():
+ return [self.state_machine.reporter.warning(
+ 'Unknown source language "%s", use one of: %s.' % (
+ srclang, ",".join(RENDER_MARKUP_EXT.keys())),
+ line=self.lineno)]
+
+ code = '\n'.join(self.content)
+ if not code.strip():
+ return [self.state_machine.reporter.warning(
+ 'Ignoring "%s" directive without content.' % (
+ self.name),
+ line=self.lineno)]
+
+ node = kernel_render()
+ node['alt'] = self.options.get('alt','')
+ node['srclang'] = srclang
+ literal_node = nodes.literal_block(code, code)
+ node += literal_node
+
+ caption = self.options.get('caption')
+ if caption:
+ # parse caption's content
+ parsed = nodes.Element()
+ self.state.nested_parse(
+ ViewList([caption], source=''), self.content_offset, parsed)
+ caption_node = nodes.caption(
+ parsed[0].rawsource, '', *parsed[0].children)
+ caption_node.source = parsed[0].source
+ caption_node.line = parsed[0].line
+
+ figure_node = nodes.figure('', node)
+ for k,v in self.options.items():
+ figure_node[k] = v
+ figure_node += caption_node
+
+ node = figure_node
+
+ return node
+
+def add_kernel_figure_to_std_domain(app, doctree):
+ """Add kernel-figure anchors to 'std' domain.
+
+ The ``StandardDomain.process_doc(..)`` method does not know how to resolve
+ the caption (label) of ``kernel-figure`` directive (it only knows about
+ standard nodes, e.g. table, figure etc.). Without any additional handling
+ this will result in a 'undefined label' for kernel-figures.
+
+ This handle adds labels of kernel-figure to the 'std' domain labels.
+ """
+
+ std = app.env.domains["std"]
+ docname = app.env.docname
+ labels = std.data["labels"]
+
+ for name, explicit in iteritems(doctree.nametypes):
+ if not explicit:
+ continue
+ labelid = doctree.nameids[name]
+ if labelid is None:
+ continue
+ node = doctree.ids[labelid]
+
+ if node.tagname == 'kernel_figure':
+ for n in node.next_node():
+ if n.tagname == 'caption':
+ sectname = clean_astext(n)
+ # add label to std domain
+ labels[name] = docname, labelid, sectname
+ break
diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py
new file mode 100644
index 0000000000..301a21aa4f
--- /dev/null
+++ b/Documentation/sphinx/load_config.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=R0903, C0330, R0914, R0912, E0401
+
+import os
+import sys
+from sphinx.util.pycompat import execfile_
+
+# ------------------------------------------------------------------------------
+def loadConfig(namespace):
+# ------------------------------------------------------------------------------
+
+ u"""Load an additional configuration file into *namespace*.
+
+ The name of the configuration file is taken from the environment
+ ``SPHINX_CONF``. The external configuration file extends (or overwrites) the
+ configuration values from the origin ``conf.py``. With this you are able to
+ maintain *build themes*. """
+
+ config_file = os.environ.get("SPHINX_CONF", None)
+ if (config_file is not None
+ and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
+ config_file = os.path.abspath(config_file)
+
+ if os.path.isfile(config_file):
+ sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
+ config = namespace.copy()
+ config['__file__'] = config_file
+ execfile_(config_file, config)
+ del config['__file__']
+ namespace.update(config)
+ else:
+ sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
diff --git a/Documentation/sphinx/parse-headers.pl b/Documentation/sphinx/parse-headers.pl
new file mode 100755
index 0000000000..d410f47567
--- /dev/null
+++ b/Documentation/sphinx/parse-headers.pl
@@ -0,0 +1,401 @@
+#!/usr/bin/perl
+use strict;
+use Text::Tabs;
+use Getopt::Long;
+use Pod::Usage;
+
+my $debug;
+my $help;
+my $man;
+
+GetOptions(
+ "debug" => \$debug,
+ 'usage|?' => \$help,
+ 'help' => \$man
+) or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
+
+my ($file_in, $file_out, $file_exceptions) = @ARGV;
+
+my $data;
+my %ioctls;
+my %defines;
+my %typedefs;
+my %enums;
+my %enum_symbols;
+my %structs;
+
+require Data::Dumper if ($debug);
+
+#
+# read the file and get identifiers
+#
+
+my $is_enum = 0;
+my $is_comment = 0;
+open IN, $file_in or die "Can't open $file_in";
+while (<IN>) {
+ $data .= $_;
+
+ my $ln = $_;
+ if (!$is_comment) {
+ $ln =~ s,/\*.*(\*/),,g;
+
+ $is_comment = 1 if ($ln =~ s,/\*.*,,);
+ } else {
+ if ($ln =~ s,^(.*\*/),,) {
+ $is_comment = 0;
+ } else {
+ next;
+ }
+ }
+
+ if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) {
+ my $s = $1;
+ my $n = $1;
+ $n =~ tr/A-Z/a-z/;
+ $n =~ tr/_/-/;
+
+ $enum_symbols{$s} = "\\ :ref:`$s <$n>`\\ ";
+
+ $is_enum = 0 if ($is_enum && m/\}/);
+ next;
+ }
+ $is_enum = 0 if ($is_enum && m/\}/);
+
+ if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) {
+ my $s = $1;
+ my $n = $1;
+ $n =~ tr/A-Z/a-z/;
+
+ $ioctls{$s} = "\\ :ref:`$s <$n>`\\ ";
+ next;
+ }
+
+ if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) {
+ my $s = $1;
+ my $n = $1;
+ $n =~ tr/A-Z/a-z/;
+ $n =~ tr/_/-/;
+
+ $defines{$s} = "\\ :ref:`$s <$n>`\\ ";
+ next;
+ }
+
+ if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) {
+ my $s = $2;
+ my $n = $3;
+
+ $typedefs{$n} = "\\ :c:type:`$n <$s>`\\ ";
+ next;
+ }
+ if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/
+ || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/
+ || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/
+ || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) {
+ my $s = $1;
+
+ $enums{$s} = "enum :c:type:`$s`\\ ";
+
+ $is_enum = $1;
+ next;
+ }
+ if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/
+ || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/
+ || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/
+ || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/
+ ) {
+ my $s = $1;
+
+ $structs{$s} = "struct :c:type:`$s`\\ ";
+ next;
+ }
+}
+close IN;
+
+#
+# Handle multi-line typedefs
+#
+
+my @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,
+ $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,);
+foreach my $m (@matches) {
+ my $s = $m;
+
+ $typedefs{$s} = "\\ :c:type:`$s`\\ ";
+ next;
+}
+
+#
+# Handle exceptions, if any
+#
+
+my %def_reftype = (
+ "ioctl" => ":ref",
+ "define" => ":ref",
+ "symbol" => ":ref",
+ "typedef" => ":c:type",
+ "enum" => ":c:type",
+ "struct" => ":c:type",
+);
+
+if ($file_exceptions) {
+ open IN, $file_exceptions or die "Can't read $file_exceptions";
+ while (<IN>) {
+ next if (m/^\s*$/ || m/^\s*#/);
+
+ # Parsers to ignore a symbol
+
+ if (m/^ignore\s+ioctl\s+(\S+)/) {
+ delete $ioctls{$1} if (exists($ioctls{$1}));
+ next;
+ }
+ if (m/^ignore\s+define\s+(\S+)/) {
+ delete $defines{$1} if (exists($defines{$1}));
+ next;
+ }
+ if (m/^ignore\s+typedef\s+(\S+)/) {
+ delete $typedefs{$1} if (exists($typedefs{$1}));
+ next;
+ }
+ if (m/^ignore\s+enum\s+(\S+)/) {
+ delete $enums{$1} if (exists($enums{$1}));
+ next;
+ }
+ if (m/^ignore\s+struct\s+(\S+)/) {
+ delete $structs{$1} if (exists($structs{$1}));
+ next;
+ }
+ if (m/^ignore\s+symbol\s+(\S+)/) {
+ delete $enum_symbols{$1} if (exists($enum_symbols{$1}));
+ next;
+ }
+
+ # Parsers to replace a symbol
+ my ($type, $old, $new, $reftype);
+
+ if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) {
+ $type = $1;
+ $old = $2;
+ $new = $3;
+ } else {
+ die "Can't parse $file_exceptions: $_";
+ }
+
+ if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) {
+ $reftype = ":c:$1";
+ $new = $2;
+ } elsif ($new =~ m/\:ref\:\`(.+)\`/) {
+ $reftype = ":ref";
+ $new = $1;
+ } else {
+ $reftype = $def_reftype{$type};
+ }
+ $new = "$reftype:`$old <$new>`";
+
+ if ($type eq "ioctl") {
+ $ioctls{$old} = $new if (exists($ioctls{$old}));
+ next;
+ }
+ if ($type eq "define") {
+ $defines{$old} = $new if (exists($defines{$old}));
+ next;
+ }
+ if ($type eq "symbol") {
+ $enum_symbols{$old} = $new if (exists($enum_symbols{$old}));
+ next;
+ }
+ if ($type eq "typedef") {
+ $typedefs{$old} = $new if (exists($typedefs{$old}));
+ next;
+ }
+ if ($type eq "enum") {
+ $enums{$old} = $new if (exists($enums{$old}));
+ next;
+ }
+ if ($type eq "struct") {
+ $structs{$old} = $new if (exists($structs{$old}));
+ next;
+ }
+
+ die "Can't parse $file_exceptions: $_";
+ }
+}
+
+if ($debug) {
+ print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
+ print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
+ print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
+ print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
+ print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
+ print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
+}
+
+#
+# Align block
+#
+$data = expand($data);
+$data = " " . $data;
+$data =~ s/\n/\n /g;
+$data =~ s/\n\s+$/\n/g;
+$data =~ s/\n\s+\n/\n\n/g;
+
+#
+# Add escape codes for special characters
+#
+$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g;
+
+$data =~ s,DEPRECATED,**DEPRECATED**,g;
+
+#
+# Add references
+#
+
+my $start_delim = "[ \n\t\(\=\*\@]";
+my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
+
+foreach my $r (keys %ioctls) {
+ my $s = $ioctls{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+
+ $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %defines) {
+ my $s = $defines{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+
+ $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %enum_symbols) {
+ my $s = $enum_symbols{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+
+ $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+foreach my $r (keys %enums) {
+ my $s = $enums{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+
+ $data =~ s/enum\s+($r)$end_delim/$s$2/g;
+}
+
+foreach my $r (keys %structs) {
+ my $s = $structs{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+
+ $data =~ s/struct\s+($r)$end_delim/$s$2/g;
+}
+
+foreach my $r (keys %typedefs) {
+ my $s = $typedefs{$r};
+
+ $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
+
+ print "$r -> $s\n" if ($debug);
+ $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
+}
+
+$data =~ s/\\ ([\n\s])/\1/g;
+
+#
+# Generate output file
+#
+
+my $title = $file_in;
+$title =~ s,.*/,,;
+
+open OUT, "> $file_out" or die "Can't open $file_out";
+print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
+print OUT "$title\n";
+print OUT "=" x length($title);
+print OUT "\n\n.. parsed-literal::\n\n";
+print OUT $data;
+close OUT;
+
+__END__
+
+=head1 NAME
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+=head1 SYNOPSIS
+
+B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging.
+
+=item B<--usage>
+
+Prints a brief help message and exits.
+
+=item B<--help>
+
+Prints a more detailed help message and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
+to replace the default references by a custom one.
+
+Please read Documentation/doc-guide/parse-headers.rst at the Kernel's
+tree for more details.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab at kernel.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung at kernel.org>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt
new file mode 100644
index 0000000000..742be3e126
--- /dev/null
+++ b/Documentation/sphinx/requirements.txt
@@ -0,0 +1,3 @@
+docutils==0.12
+Sphinx==1.4.9
+sphinx_rtd_theme
diff --git a/Documentation/sphinx/rstFlatTable.py b/Documentation/sphinx/rstFlatTable.py
new file mode 100755
index 0000000000..25feb0d35e
--- /dev/null
+++ b/Documentation/sphinx/rstFlatTable.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8; mode: python -*-
+# pylint: disable=C0330, R0903, R0912
+
+u"""
+ flat-table
+ ~~~~~~~~~~
+
+ Implementation of the ``flat-table`` reST-directive.
+
+ :copyright: Copyright (C) 2016 Markus Heiser
+ :license: GPL Version 2, June 1991 see linux/COPYING for details.
+
+ The ``flat-table`` (:py:class:`FlatTable`) is a double-stage list similar to
+ the ``list-table`` with some additional features:
+
+ * *column-span*: with the role ``cspan`` a cell can be extended through
+ additional columns
+
+ * *row-span*: with the role ``rspan`` a cell can be extended through
+ additional rows
+
+ * *auto span* rightmost cell of a table row over the missing cells on the
+ right side of that table-row. With Option ``:fill-cells:`` this behavior
+ can changed from *auto span* to *auto fill*, which automaticly inserts
+ (empty) cells instead of spanning the last cell.
+
+ Options:
+
+ * header-rows: [int] count of header rows
+ * stub-columns: [int] count of stub columns
+ * widths: [[int] [int] ... ] widths of columns
+ * fill-cells: instead of autospann missing cells, insert missing cells
+
+ roles:
+
+ * cspan: [int] additionale columns (*morecols*)
+ * rspan: [int] additionale rows (*morerows*)
+"""
+
+# ==============================================================================
+# imports
+# ==============================================================================
+
+import sys
+
+from docutils import nodes
+from docutils.parsers.rst import directives, roles
+from docutils.parsers.rst.directives.tables import Table
+from docutils.utils import SystemMessagePropagation
+
+# ==============================================================================
+# common globals
+# ==============================================================================
+
+# The version numbering follows numbering of the specification
+# (Documentation/books/kernel-doc-HOWTO).
+__version__ = '1.0'
+
+PY3 = sys.version_info[0] == 3
+PY2 = sys.version_info[0] == 2
+
+if PY3:
+ # pylint: disable=C0103, W0622
+ unicode = str
+ basestring = str
+
+# ==============================================================================
+def setup(app):
+# ==============================================================================
+
+ app.add_directive("flat-table", FlatTable)
+ roles.register_local_role('cspan', c_span)
+ roles.register_local_role('rspan', r_span)
+
+ return dict(
+ version = __version__,
+ parallel_read_safe = True,
+ parallel_write_safe = True
+ )
+
+# ==============================================================================
+def c_span(name, rawtext, text, lineno, inliner, options=None, content=None):
+# ==============================================================================
+ # pylint: disable=W0613
+
+ options = options if options is not None else {}
+ content = content if content is not None else []
+ nodelist = [colSpan(span=int(text))]
+ msglist = []
+ return nodelist, msglist
+
+# ==============================================================================
+def r_span(name, rawtext, text, lineno, inliner, options=None, content=None):
+# ==============================================================================
+ # pylint: disable=W0613
+
+ options = options if options is not None else {}
+ content = content if content is not None else []
+ nodelist = [rowSpan(span=int(text))]
+ msglist = []
+ return nodelist, msglist
+
+
+# ==============================================================================
+class rowSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
+class colSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321
+# ==============================================================================
+
+# ==============================================================================
+class FlatTable(Table):
+# ==============================================================================
+
+ u"""FlatTable (``flat-table``) directive"""
+
+ option_spec = {
+ 'name': directives.unchanged
+ , 'class': directives.class_option
+ , 'header-rows': directives.nonnegative_int
+ , 'stub-columns': directives.nonnegative_int
+ , 'widths': directives.positive_int_list
+ , 'fill-cells' : directives.flag }
+
+ def run(self):
+
+ if not self.content:
+ error = self.state_machine.reporter.error(
+ 'The "%s" directive is empty; content required.' % self.name,
+ nodes.literal_block(self.block_text, self.block_text),
+ line=self.lineno)
+ return [error]
+
+ title, messages = self.make_title()
+ node = nodes.Element() # anonymous container for parsing
+ self.state.nested_parse(self.content, self.content_offset, node)
+
+ tableBuilder = ListTableBuilder(self)
+ tableBuilder.parseFlatTableNode(node)
+ tableNode = tableBuilder.buildTableNode()
+ # SDK.CONSOLE() # print --> tableNode.asdom().toprettyxml()
+ if title:
+ tableNode.insert(0, title)
+ return [tableNode] + messages
+
+
+# ==============================================================================
+class ListTableBuilder(object):
+# ==============================================================================
+
+ u"""Builds a table from a double-stage list"""
+
+ def __init__(self, directive):
+ self.directive = directive
+ self.rows = []
+ self.max_cols = 0
+
+ def buildTableNode(self):
+
+ colwidths = self.directive.get_column_widths(self.max_cols)
+ if isinstance(colwidths, tuple):
+ # Since docutils 0.13, get_column_widths returns a (widths,
+ # colwidths) tuple, where widths is a string (i.e. 'auto').
+ # See https://sourceforge.net/p/docutils/patches/120/.
+ colwidths = colwidths[1]
+ stub_columns = self.directive.options.get('stub-columns', 0)
+ header_rows = self.directive.options.get('header-rows', 0)
+
+ table = nodes.table()
+ tgroup = nodes.tgroup(cols=len(colwidths))
+ table += tgroup
+
+
+ for colwidth in colwidths:
+ colspec = nodes.colspec(colwidth=colwidth)
+ # FIXME: It seems, that the stub method only works well in the
+ # absence of rowspan (observed by the html buidler, the docutils-xml
+ # build seems OK). This is not extraordinary, because there exists
+ # no table directive (except *this* flat-table) which allows to
+ # define coexistent of rowspan and stubs (there was no use-case
+ # before flat-table). This should be reviewed (later).
+ if stub_columns:
+ colspec.attributes['stub'] = 1
+ stub_columns -= 1
+ tgroup += colspec
+ stub_columns = self.directive.options.get('stub-columns', 0)
+
+ if header_rows:
+ thead = nodes.thead()
+ tgroup += thead
+ for row in self.rows[:header_rows]:
+ thead += self.buildTableRowNode(row)
+
+ tbody = nodes.tbody()
+ tgroup += tbody
+
+ for row in self.rows[header_rows:]:
+ tbody += self.buildTableRowNode(row)
+ return table
+
+ def buildTableRowNode(self, row_data, classes=None):
+ classes = [] if classes is None else classes
+ row = nodes.row()
+ for cell in row_data:
+ if cell is None:
+ continue
+ cspan, rspan, cellElements = cell
+
+ attributes = {"classes" : classes}
+ if rspan:
+ attributes['morerows'] = rspan
+ if cspan:
+ attributes['morecols'] = cspan
+ entry = nodes.entry(**attributes)
+ entry.extend(cellElements)
+ row += entry
+ return row
+
+ def raiseError(self, msg):
+ error = self.directive.state_machine.reporter.error(
+ msg
+ , nodes.literal_block(self.directive.block_text
+ , self.directive.block_text)
+ , line = self.directive.lineno )
+ raise SystemMessagePropagation(error)
+
+ def parseFlatTableNode(self, node):
+ u"""parses the node from a :py:class:`FlatTable` directive's body"""
+
+ if len(node) != 1 or not isinstance(node[0], nodes.bullet_list):
+ self.raiseError(
+ 'Error parsing content block for the "%s" directive: '
+ 'exactly one bullet list expected.' % self.directive.name )
+
+ for rowNum, rowItem in enumerate(node[0]):
+ row = self.parseRowItem(rowItem, rowNum)
+ self.rows.append(row)
+ self.roundOffTableDefinition()
+
+ def roundOffTableDefinition(self):
+ u"""Round off the table definition.
+
+ This method rounds off the table definition in :py:member:`rows`.
+
+ * This method inserts the needed ``None`` values for the missing cells
+ arising from spanning cells over rows and/or columns.
+
+ * recount the :py:member:`max_cols`
+
+ * Autospan or fill (option ``fill-cells``) missing cells on the right
+ side of the table-row
+ """
+
+ y = 0
+ while y < len(self.rows):
+ x = 0
+
+ while x < len(self.rows[y]):
+ cell = self.rows[y][x]
+ if cell is None:
+ x += 1
+ continue
+ cspan, rspan = cell[:2]
+ # handle colspan in current row
+ for c in range(cspan):
+ try:
+ self.rows[y].insert(x+c+1, None)
+ except: # pylint: disable=W0702
+ # the user sets ambiguous rowspans
+ pass # SDK.CONSOLE()
+ # handle colspan in spanned rows
+ for r in range(rspan):
+ for c in range(cspan + 1):
+ try:
+ self.rows[y+r+1].insert(x+c, None)
+ except: # pylint: disable=W0702
+ # the user sets ambiguous rowspans
+ pass # SDK.CONSOLE()
+ x += 1
+ y += 1
+
+ # Insert the missing cells on the right side. For this, first
+ # re-calculate the max columns.
+
+ for row in self.rows:
+ if self.max_cols < len(row):
+ self.max_cols = len(row)
+
+ # fill with empty cells or cellspan?
+
+ fill_cells = False
+ if 'fill-cells' in self.directive.options:
+ fill_cells = True
+
+ for row in self.rows:
+ x = self.max_cols - len(row)
+ if x and not fill_cells:
+ if row[-1] is None:
+ row.append( ( x - 1, 0, []) )
+ else:
+ cspan, rspan, content = row[-1]
+ row[-1] = (cspan + x, rspan, content)
+ elif x and fill_cells:
+ for i in range(x):
+ row.append( (0, 0, nodes.comment()) )
+
+ def pprint(self):
+ # for debugging
+ retVal = "[ "
+ for row in self.rows:
+ retVal += "[ "
+ for col in row:
+ if col is None:
+ retVal += ('%r' % col)
+ retVal += "\n , "
+ else:
+ content = col[2][0].astext()
+ if len (content) > 30:
+ content = content[:30] + "..."
+ retVal += ('(cspan=%s, rspan=%s, %r)'
+ % (col[0], col[1], content))
+ retVal += "]\n , "
+ retVal = retVal[:-2]
+ retVal += "]\n , "
+ retVal = retVal[:-2]
+ return retVal + "]"
+
+ def parseRowItem(self, rowItem, rowNum):
+ row = []
+ childNo = 0
+ error = False
+ cell = None
+ target = None
+
+ for child in rowItem:
+ if (isinstance(child , nodes.comment)
+ or isinstance(child, nodes.system_message)):
+ pass
+ elif isinstance(child , nodes.target):
+ target = child
+ elif isinstance(child, nodes.bullet_list):
+ childNo += 1
+ cell = child
+ else:
+ error = True
+ break
+
+ if childNo != 1 or error:
+ self.raiseError(
+ 'Error parsing content block for the "%s" directive: '
+ 'two-level bullet list expected, but row %s does not '
+ 'contain a second-level bullet list.'
+ % (self.directive.name, rowNum + 1))
+
+ for cellItem in cell:
+ cspan, rspan, cellElements = self.parseCellItem(cellItem)
+ if target is not None:
+ cellElements.insert(0, target)
+ row.append( (cspan, rspan, cellElements) )
+ return row
+
+ def parseCellItem(self, cellItem):
+ # search and remove cspan, rspan colspec from the first element in
+ # this listItem (field).
+ cspan = rspan = 0
+ if not len(cellItem):
+ return cspan, rspan, []
+ for elem in cellItem[0]:
+ if isinstance(elem, colSpan):
+ cspan = elem.get("span")
+ elem.parent.remove(elem)
+ continue
+ if isinstance(elem, rowSpan):
+ rspan = elem.get("span")
+ elem.parent.remove(elem)
+ continue
+ return cspan, rspan, cellItem[:]
diff --git a/Makefile b/Makefile
index 7d5f801eea..2727f819a5 100644
--- a/Makefile
+++ b/Makefile
@@ -1713,9 +1713,11 @@ tests:
# Documentation targets
# ---------------------------------------------------------------------------
-%docs: scripts_basic FORCE
- $(Q)$(MAKE) $(build)=scripts build_docproc
- $(Q)$(MAKE) $(build)=doc/DocBook $@
+DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
+ linkcheckdocs dochelp refcheckdocs
+PHONY += $(DOC_TARGETS)
+$(DOC_TARGETS): scripts_basic FORCE
+ $(Q)$(MAKE) $(build)=Documentation $@
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
diff --git a/doc/DocBook/.gitignore b/doc/DocBook/.gitignore
deleted file mode 100644
index 7ebd5465d9..0000000000
--- a/doc/DocBook/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-*.xml
-*.ps
-*.pdf
-*.html
-*.9.gz
-*.9
-*.aux
-*.dvi
-*.log
-*.out
-*.png
-*.gif
-*.svg
-media-indices.tmpl
-media-entities.tmpl
diff --git a/doc/DocBook/Makefile b/doc/DocBook/Makefile
deleted file mode 100644
index 5257613513..0000000000
--- a/doc/DocBook/Makefile
+++ /dev/null
@@ -1,222 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-###
-# This makefile is used to generate the kernel documentation,
-# primarily based on in-line comments in various source files.
-# See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
-# to document the SRC - and how to read it.
-# To add a new book the only step required is to add the book to the
-# list of DOCBOOKS.
-
-DOCBOOKS := efi.xml linker_lists.xml stdio.xml
-
-###
-# The build process is as follows (targets):
-# (xmldocs) [by docproc]
-# file.tmpl --> file.xml +--> file.ps (psdocs) [by db2ps or xmlto]
-# +--> file.pdf (pdfdocs) [by db2pdf or xmlto]
-# +--> DIR=file (htmldocs) [by xmlto]
-# +--> man/ (mandocs) [by xmlto]
-
-
-# for PDF and PS output you can choose between xmlto and docbook-utils tools
-PDF_METHOD = $(prefer-db2x)
-PS_METHOD = $(prefer-db2x)
-
-
-###
-# The targets that may be used.
-PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs
-
-targets += $(DOCBOOKS)
-BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
-xmldocs: $(BOOKS)
-sgmldocs: xmldocs
-
-PS := $(patsubst %.xml, %.ps, $(BOOKS))
-psdocs: $(PS)
-
-PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
-pdfdocs: $(PDF)
-
-HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
-htmldocs: $(HTML)
- $(call build_main_index)
- $(call build_images)
- $(call install_media_images)
-
-MAN := $(patsubst %.xml, %.9, $(BOOKS))
-mandocs: $(MAN)
- $(if $(wildcard $(obj)/man/*.9),gzip -f $(obj)/man/*.9)
-
-installmandocs: mandocs
- mkdir -p /usr/local/man/man9/
- install $(obj)/man/*.9.gz /usr/local/man/man9/
-
-###
-#External programs used
-KERNELDOC = $(srctree)/scripts/kernel-doc
-DOCPROC = $(objtree)/scripts/docproc
-
-XMLTOFLAGS = -m $(srctree)/$(src)/stylesheet.xsl
-XMLTOFLAGS += --skip-validation
-
-###
-# DOCPROC is used for two purposes:
-# 1) To generate a dependency list for a .tmpl file
-# 2) To preprocess a .tmpl file and call kernel-doc with
-# appropriate parameters.
-# The following rules are used to generate the .xml documentation
-# required to generate the final targets. (ps, pdf, html).
-quiet_cmd_docproc = DOCPROC $@
- cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@
-define rule_docproc
- set -e; \
- $(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) \
- $(cmd_$(1)); \
- ( \
- echo 'cmd_$@ := $(cmd_$(1))'; \
- echo $@: `SRCTREE=$(srctree) $(DOCPROC) depend $<`; \
- ) > $(dir $@).$(notdir $@).cmd
-endef
-
-%.xml: %.tmpl $(KERNELDOC) $(DOCPROC) FORCE
- $(call if_changed_rule,docproc)
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
-
-notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \
- exit 1
-db2xtemplate = db2TYPE -o $(dir $@) $<
-xmltotemplate = xmlto TYPE $(XMLTOFLAGS) -o $(dir $@) $<
-
-# determine which methods are available
-ifeq ($(shell which db2ps >/dev/null 2>&1 && echo found),found)
- use-db2x = db2x
- prefer-db2x = db2x
-else
- use-db2x = notfound
- prefer-db2x = $(use-xmlto)
-endif
-ifeq ($(shell which xmlto >/dev/null 2>&1 && echo found),found)
- use-xmlto = xmlto
- prefer-xmlto = xmlto
-else
- use-xmlto = notfound
- prefer-xmlto = $(use-db2x)
-endif
-
-# the commands, generated from the chosen template
-quiet_cmd_db2ps = PS $@
- cmd_db2ps = $(subst TYPE,ps, $($(PS_METHOD)template))
-%.ps : %.xml
- $(call cmd,db2ps)
-
-quiet_cmd_db2pdf = PDF $@
- cmd_db2pdf = $(subst TYPE,pdf, $($(PDF_METHOD)template))
-%.pdf : %.xml
- $(call cmd,db2pdf)
-
-
-index = index.html
-main_idx = $(obj)/$(index)
-build_main_index = rm -rf $(main_idx); \
- echo '<h1>U-Boot Bootloader HTML Documentation</h1>' >> $(main_idx) && \
- echo '<h2>U-Boot Version: $(UBOOTVERSION)</h2>' >> $(main_idx) && \
- cat $(HTML) >> $(main_idx)
-
-quiet_cmd_db2html = HTML $@
- cmd_db2html = xmlto html $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
- echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
- $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
-
-%.html: %.xml
- @(which xmlto > /dev/null 2>&1) || \
- (echo "*** You need to install xmlto ***"; \
- exit 1)
- @rm -rf $@ $(patsubst %.html,%,$@)
- $(call cmd,db2html)
- @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
- cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
-
-quiet_cmd_db2man = MAN $@
- cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; fi
-%.9 : %.xml
- @(which xmlto > /dev/null 2>&1) || \
- (echo "*** You need to install xmlto ***"; \
- exit 1)
- $(Q)mkdir -p $(obj)/man
- $(call cmd,db2man)
- @touch $@
-
-###
-# Rules to generate postscripts and PNG images from .fig format files
-quiet_cmd_fig2eps = FIG2EPS $@
- cmd_fig2eps = fig2dev -Leps $< $@
-
-%.eps: %.fig
- @(which fig2dev > /dev/null 2>&1) || \
- (echo "*** You need to install transfig ***"; \
- exit 1)
- $(call cmd,fig2eps)
-
-quiet_cmd_fig2png = FIG2PNG $@
- cmd_fig2png = fig2dev -Lpng $< $@
-
-%.png: %.fig
- @(which fig2dev > /dev/null 2>&1) || \
- (echo "*** You need to install transfig ***"; \
- exit 1)
- $(call cmd,fig2png)
-
-###
-# Rule to convert a .c file to inline XML documentation
- gen_xml = :
- quiet_gen_xml = echo ' GEN $@'
-silent_gen_xml = :
-%.xml: %.c
- @$($(quiet)gen_xml)
- @( \
- echo "<programlisting>"; \
- expand --tabs=8 < $< | \
- sed -e "s/&/\\&/g" \
- -e "s/</\\</g" \
- -e "s/>/\\>/g"; \
- echo "</programlisting>") > $@
-
-###
-# Help targets as used by the top-level makefile
-dochelp:
- @echo ' U-Boot bootloader internal documentation in different formats:'
- @echo ' htmldocs - HTML'
- @echo ' pdfdocs - PDF'
- @echo ' psdocs - Postscript'
- @echo ' xmldocs - XML DocBook'
- @echo ' mandocs - man pages'
- @echo ' installmandocs - install man pages generated by mandocs'
- @echo ' cleandocs - clean all generated DocBook files'
-
-###
-# Temporary files left by various tools
-clean-files := $(DOCBOOKS) \
- $(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
- $(patsubst %.xml, %.aux, $(DOCBOOKS)) \
- $(patsubst %.xml, %.tex, $(DOCBOOKS)) \
- $(patsubst %.xml, %.log, $(DOCBOOKS)) \
- $(patsubst %.xml, %.out, $(DOCBOOKS)) \
- $(patsubst %.xml, %.ps, $(DOCBOOKS)) \
- $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
- $(patsubst %.xml, %.html, $(DOCBOOKS)) \
- $(patsubst %.xml, %.9, $(DOCBOOKS)) \
- $(index)
-
-clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
-
-cleandocs:
- $(Q)rm -f $(call objectify, $(clean-files))
- $(Q)rm -rf $(call objectify, $(clean-dirs))
-
-# Declare the contents of the .PHONY variable as phony. We keep that
-# information in a variable se we can use it in if_changed and friends.
-
-.PHONY: $(PHONY)
diff --git a/doc/DocBook/docbook.css b/doc/DocBook/docbook.css
deleted file mode 100644
index 7a79ec54bd..0000000000
--- a/doc/DocBook/docbook.css
+++ /dev/null
@@ -1,16 +0,0 @@
-body {
- font-family: sans-serif;
-}
-
-.programlisting {
- font-family: monospace;
- font-size: 1em;
- display: block;
- padding: 10px;
- border: 1px solid #aaa;
- color: #000;
- background-color: #eee;
- overflow: auto;
- margin: 1em 0em;
- border-radius: 6px;
-}
diff --git a/doc/DocBook/efi.tmpl b/doc/DocBook/efi.tmpl
deleted file mode 100644
index 5daaae382b..0000000000
--- a/doc/DocBook/efi.tmpl
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="UBootEFI">
- <bookinfo>
- <title>The U-Boot EFI subsystem</title>
- </bookinfo>
-
-<toc></toc>
-
- <chapter id="BootServices">
- <title>Boot services</title>
-!Ilib/efi_loader/efi_boottime.c
- </chapter>
-
-</book>
diff --git a/doc/DocBook/linker_lists.tmpl b/doc/DocBook/linker_lists.tmpl
deleted file mode 100644
index f1975165d6..0000000000
--- a/doc/DocBook/linker_lists.tmpl
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="UBootLGArrays">
- <bookinfo>
- <title>The U-Boot Linker-Generated Arrays</title>
-
- <legalnotice>
- <para>
- This documentation is free software; you can redistribute
- it and/or modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later
- version.
- </para>
-
- <para>
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of U-Boot Bootloader.
- </para>
- </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
- <chapter id="adt">
- <title>Linker-Generated Arrays</title>
-!Iinclude/linker_lists.h
- </chapter>
-
-</book>
diff --git a/doc/DocBook/stdio.tmpl b/doc/DocBook/stdio.tmpl
deleted file mode 100644
index 4783abb0a0..0000000000
--- a/doc/DocBook/stdio.tmpl
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="UBootSTDIO">
- <bookinfo>
- <title>The U-Boot STDIO subsystem</title>
-
- <legalnotice>
- <para>
- This documentation is free software; you can redistribute
- it and/or modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later
- version.
- </para>
-
- <para>
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of U-Boot Bootloader.
- </para>
- </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
- <chapter id="adt">
- <title>U-Boot Serial subsystem</title>
-!Idrivers/serial/serial.c
- </chapter>
-
-</book>
diff --git a/doc/DocBook/stylesheet.xsl b/doc/DocBook/stylesheet.xsl
deleted file mode 100644
index 85b2527519..0000000000
--- a/doc/DocBook/stylesheet.xsl
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
-<param name="chunk.quietly">1</param>
-<param name="funcsynopsis.style">ansi</param>
-<param name="funcsynopsis.tabular.threshold">80</param>
-<param name="callout.graphics">0</param>
-<!-- <param name="paper.type">A4</param> -->
-<param name="generate.section.toc.level">2</param>
-<param name="use.id.as.filename">1</param>
-</stylesheet>
diff --git a/include/linker_lists.h b/include/linker_lists.h
index e0759d446f..d775d041e0 100644
--- a/include/linker_lists.h
+++ b/include/linker_lists.h
@@ -20,87 +20,6 @@
#if !defined(__ASSEMBLY__)
/**
- * A linker list is constructed by grouping together linker input
- * sections, each containing one entry of the list. Each input section
- * contains a constant initialized variable which holds the entry's
- * content. Linker list input sections are constructed from the list
- * and entry names, plus a prefix which allows grouping all lists
- * together. Assuming _list and _entry are the list and entry names,
- * then the corresponding input section name is
- *
- * .u_boot_list_ + 2_ + @_list + _2_ + @_entry
- *
- * and the C variable name is
- *
- * _u_boot_list + _2_ + @_list + _2_ + @_entry
- *
- * This ensures uniqueness for both input section and C variable name.
- *
- * Note that the names differ only in the first character, "." for the
- * section and "_" for the variable, so that the linker cannot confuse
- * section and symbol names. From now on, both names will be referred
- * to as
- *
- * %u_boot_list_ + 2_ + @_list + _2_ + @_entry
- *
- * Entry variables need never be referred to directly.
- *
- * The naming scheme for input sections allows grouping all linker lists
- * into a single linker output section and grouping all entries for a
- * single list.
- *
- * Note the two '_2_' constant components in the names: their presence
- * allows putting a start and end symbols around a list, by mapping
- * these symbols to sections names with components "1" (before) and
- * "3" (after) instead of "2" (within).
- * Start and end symbols for a list can generally be defined as
- *
- * %u_boot_list_2_ + @_list + _1_...
- * %u_boot_list_2_ + @_list + _3_...
- *
- * Start and end symbols for the whole of the linker lists area can be
- * defined as
- *
- * %u_boot_list_1_...
- * %u_boot_list_3_...
- *
- * Here is an example of the sorted sections which result from a list
- * "array" made up of three entries : "first", "second" and "third",
- * iterated at least once.
- *
- * .u_boot_list_2_array_1
- * .u_boot_list_2_array_2_first
- * .u_boot_list_2_array_2_second
- * .u_boot_list_2_array_2_third
- * .u_boot_list_2_array_3
- *
- * If lists must be divided into sublists (e.g. for iterating only on
- * part of a list), one can simply give the list a name of the form
- * 'outer_2_inner', where 'outer' is the global list name and 'inner'
- * is the sub-list name. Iterators for the whole list should use the
- * global list name ("outer"); iterators for only a sub-list should use
- * the full sub-list name ("outer_2_inner").
- *
- * Here is an example of the sections generated from a global list
- * named "drivers", two sub-lists named "i2c" and "pci", and iterators
- * defined for the whole list and each sub-list:
- *
- * %u_boot_list_2_drivers_1
- * %u_boot_list_2_drivers_2_i2c_1
- * %u_boot_list_2_drivers_2_i2c_2_first
- * %u_boot_list_2_drivers_2_i2c_2_first
- * %u_boot_list_2_drivers_2_i2c_2_second
- * %u_boot_list_2_drivers_2_i2c_2_third
- * %u_boot_list_2_drivers_2_i2c_3
- * %u_boot_list_2_drivers_2_pci_1
- * %u_boot_list_2_drivers_2_pci_2_first
- * %u_boot_list_2_drivers_2_pci_2_second
- * %u_boot_list_2_drivers_2_pci_2_third
- * %u_boot_list_2_drivers_2_pci_3
- * %u_boot_list_2_drivers_3
- */
-
-/**
* llsym() - Access a linker-generated array entry
* @_type: Data type of the entry
* @_name: Name of the entry
@@ -134,16 +53,19 @@
* a subsection of this section is declared and contains some elements,
* it is imperative that the elements are of the same type.
*
- * 4) In case an outer section is declared that contains some array elements
+ * 3) In case an outer section is declared that contains some array elements
* AND an inner subsection of this section is declared and contains some
* elements, then when traversing the outer section, even the elements of
* the inner sections are present in the array.
*
* Example:
- * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
- * .x = 3,
- * .y = 4,
- * };
+ *
+ * ::
+ *
+ * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
+ * .x = 3,
+ * .y = 4,
+ * };
*/
#define ll_entry_declare(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \
@@ -160,18 +82,20 @@
* This is like ll_entry_declare() but creates multiple entries. It should
* be assigned to an array.
*
- * ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
- * { .x = 3, .y = 4 },
- * { .x = 8, .y = 2 },
- * { .x = 1, .y = 7 }
- * };
+ * ::
+ *
+ * ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
+ * { .x = 3, .y = 4 },
+ * { .x = 8, .y = 2 },
+ * { .x = 1, .y = 7 }
+ * };
*/
#define ll_entry_declare_list(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name[] __aligned(4) \
__attribute__((unused, \
section(".u_boot_list_2_"#_list"_2_"#_name)))
-/**
+/*
* We need a 0-byte-size type for iterator symbols, and the compiler
* does not allow defining objects of C type 'void'. Using an empty
* struct is allowed by the compiler, but causes gcc versions 4.4 and
@@ -185,7 +109,7 @@
* @_type: Data type of the entry
* @_list: Name of the list in which this entry is placed
*
- * This function returns (_type *) pointer to the very first entry of a
+ * This function returns ``(_type *)`` pointer to the very first entry of a
* linker-generated array placed into subsection of .u_boot_list section
* specified by _list argument.
*
@@ -193,7 +117,10 @@
* must be 2 and its rightmost index must be 1.
*
* Example:
- * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
+ *
+ * ::
+ *
+ * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
*/
#define ll_entry_start(_type, _list) \
({ \
@@ -208,7 +135,7 @@
* @_list: Name of the list in which this entry is placed
* (with underscores instead of dots)
*
- * This function returns (_type *) pointer after the very last entry of
+ * This function returns ``(_type *)`` pointer after the very last entry of
* a linker-generated array placed into subsection of .u_boot_list
* section specified by _list argument.
*
@@ -216,7 +143,10 @@
* must be 2 and its rightmost index must be 3.
*
* Example:
- * struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub);
+ *
+ * ::
+ *
+ * struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub);
*/
#define ll_entry_end(_type, _list) \
({ \
@@ -234,11 +164,14 @@
* argument. The result is of an unsigned int type.
*
* Example:
- * int i;
- * const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub);
- * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
- * for (i = 0; i < count; i++, msc++)
- * printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y);
+ *
+ * ::
+ *
+ * int i;
+ * const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub);
+ * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);
+ * for (i = 0; i < count; i++, msc++)
+ * printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y);
*/
#define ll_entry_count(_type, _list) \
({ \
@@ -259,12 +192,15 @@
* and it's name.
*
* Example:
- * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
- * .x = 3,
- * .y = 4,
- * };
- * ...
- * struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub);
+ *
+ * ::
+ *
+ * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
+ * .x = 3,
+ * .y = 4,
+ * };
+ * ...
+ * struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub);
*/
#define ll_entry_get(_type, _name, _list) \
({ \
@@ -278,14 +214,17 @@
* ll_start() - Point to first entry of first linker-generated array
* @_type: Data type of the entry
*
- * This function returns (_type *) pointer to the very first entry of
+ * This function returns ``(_type *)`` pointer to the very first entry of
* the very first linker-generated array.
*
* Since this macro defines the start of the linker-generated arrays,
* its leftmost index must be 1.
*
* Example:
- * struct my_sub_cmd *msc = ll_start(struct my_sub_cmd);
+ *
+ * ::
+ *
+ * struct my_sub_cmd *msc = ll_start(struct my_sub_cmd);
*/
#define ll_start(_type) \
({ \
@@ -298,14 +237,17 @@
* ll_end() - Point after last entry of last linker-generated array
* @_type: Data type of the entry
*
- * This function returns (_type *) pointer after the very last entry of
+ * This function returns ``(_type *)`` pointer after the very last entry of
* the very last linker-generated array.
*
* Since this macro defines the end of the linker-generated arrays,
* its leftmost index must be 3.
*
* Example:
- * struct my_sub_cmd *msc = ll_end(struct my_sub_cmd);
+ *
+ * ::
+ *
+ * struct my_sub_cmd *msc = ll_end(struct my_sub_cmd);
*/
#define ll_end(_type) \
({ \
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 261d66d97f..eeefe0bdfe 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -115,9 +115,9 @@ void efi_save_gd(void)
}
/*
- * Special case handler for error/abort that just forces things back
- * to u-boot world so we can dump out an abort msg, without any care
- * about returning back to UEFI world.
+ * Special case handler for error/abort that just forces things back to u-boot
+ * world so we can dump out an abort msg, without any care about returning back
+ * to UEFI world.
*/
void efi_restore_gd(void)
{
@@ -130,14 +130,14 @@ void efi_restore_gd(void)
}
/**
- * indent_string - returns a string for indenting with two spaces per level
+ * indent_string() - returns a string for indenting with two spaces per level
+ * @level: indent level
*
* A maximum of ten indent levels is supported. Higher indent levels will be
* truncated.
*
- * @level: indent level
- * Return Value: A string for indenting with two spaces per level is
- * returned.
+ * Return: A string for indenting with two spaces per level is
+ * returned.
*/
static const char *indent_string(int level)
{
@@ -164,18 +164,18 @@ const char *__efi_nesting_dec(void)
}
/**
- * efi_queue_event - queue an EFI event
+ * efi_queue_event() - queue an EFI event
+ * @event: event to signal
+ * @check_tpl: check the TPL level
*
* This function queues the notification function of the event for future
* execution.
*
- * The notification function is called if the task priority level of the
- * event is higher than the current task priority level.
+ * The notification function is called if the task priority level of the event
+ * is higher than the current task priority level.
*
* For the SignalEvent service see efi_signal_event_ext.
*
- * @event: event to signal
- * @check_tpl: check the TPL level
*/
static void efi_queue_event(struct efi_event *event, bool check_tpl)
{
@@ -191,16 +191,15 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl)
}
/**
- * efi_signal_event - signal an EFI event
+ * efi_signal_event() - signal an EFI event
+ * @event: event to signal
+ * @check_tpl: check the TPL level
*
- * This function signals an event. If the event belongs to an event group
- * all events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
+ * This function signals an event. If the event belongs to an event group all
+ * events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
* their notification function is queued.
*
* For the SignalEvent service see efi_signal_event_ext.
- *
- * @event: event to signal
- * @check_tpl: check the TPL level
*/
void efi_signal_event(struct efi_event *event, bool check_tpl)
{
@@ -235,14 +234,15 @@ void efi_signal_event(struct efi_event *event, bool check_tpl)
}
/**
- * efi_raise_tpl - raise the task priority level
+ * efi_raise_tpl() - raise the task priority level
+ * @new_tpl: new value of the task priority level
*
* This function implements the RaiseTpl service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @new_tpl: new value of the task priority level
- * Return Value: old value of the task priority level
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: old value of the task priority level
*/
static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl)
{
@@ -261,13 +261,13 @@ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl)
}
/**
- * efi_restore_tpl - lower the task priority level
+ * efi_restore_tpl() - lower the task priority level
+ * @old_tpl: value of the task priority level to be restored
*
* This function implements the RestoreTpl service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @old_tpl: value of the task priority level to be restored
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*/
static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl)
{
@@ -288,17 +288,18 @@ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl)
}
/**
- * efi_allocate_pages_ext - allocate memory pages
+ * efi_allocate_pages_ext() - allocate memory pages
+ * @type: type of allocation to be performed
+ * @memory_type: usage type of the allocated memory
+ * @pages: number of pages to be allocated
+ * @memory: allocated memory
*
* This function implements the AllocatePages service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @type: type of allocation to be performed
- * @memory_type: usage type of the allocated memory
- * @pages: number of pages to be allocated
- * @memory: allocated memory
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
efi_uintn_t pages,
@@ -312,15 +313,16 @@ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
}
/**
- * efi_free_pages_ext - Free memory pages.
+ * efi_free_pages_ext() - Free memory pages.
+ * @memory: start of the memory area to be freed
+ * @pages: number of pages to be freed
*
* This function implements the FreePages service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @memory: start of the memory area to be freed
- * @pages: number of pages to be freed
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory,
efi_uintn_t pages)
@@ -333,19 +335,20 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory,
}
/**
- * efi_get_memory_map_ext - get map describing memory usage
+ * efi_get_memory_map_ext() - get map describing memory usage
+ * @memory_map_size: on entry the size, in bytes, of the memory map buffer,
+ * on exit the size of the copied memory map
+ * @memory_map: buffer to which the memory map is written
+ * @map_key: key for the memory map
+ * @descriptor_size: size of an individual memory descriptor
+ * @descriptor_version: version number of the memory descriptor structure
*
* This function implements the GetMemoryMap service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @memory_map_size: on entry the size, in bytes, of the memory map buffer,
- * on exit the size of the copied memory map
- * @memory_map: buffer to which the memory map is written
- * @map_key: key for the memory map
- * @descriptor_size: size of an individual memory descriptor
- * @descriptor_version: version number of the memory descriptor structure
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_get_memory_map_ext(
efi_uintn_t *memory_map_size,
@@ -364,16 +367,17 @@ static efi_status_t EFIAPI efi_get_memory_map_ext(
}
/**
- * efi_allocate_pool_ext - allocate memory from pool
+ * efi_allocate_pool_ext() - allocate memory from pool
+ * @pool_type: type of the pool from which memory is to be allocated
+ * @size: number of bytes to be allocated
+ * @buffer: allocated memory
*
* This function implements the AllocatePool service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @pool_type: type of the pool from which memory is to be allocated
- * @size: number of bytes to be allocated
- * @buffer: allocated memory
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
efi_uintn_t size,
@@ -387,14 +391,15 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
}
/**
- * efi_free_pool_ext - free memory from pool
+ * efi_free_pool_ext() - free memory from pool
+ * @buffer: start of memory to be freed
*
* This function implements the FreePool service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @buffer: start of memory to be freed
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
{
@@ -406,12 +411,10 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
}
/**
- * efi_add_handle - add a new object to the object list
- *
- * The protocols list is initialized.
- * The object handle is set.
+ * efi_add_handle() - add a new object to the object list
+ * @obj: object to be added
*
- * @obj: object to be added
+ * The protocols list is initialized. The object handle is set.
*/
void efi_add_handle(struct efi_object *obj)
{
@@ -423,10 +426,10 @@ void efi_add_handle(struct efi_object *obj)
}
/**
- * efi_create_handle - create handle
+ * efi_create_handle() - create handle
+ * @handle: new handle
*
- * @handle: new handle
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_create_handle(efi_handle_t *handle)
{
@@ -443,12 +446,12 @@ efi_status_t efi_create_handle(efi_handle_t *handle)
}
/**
- * efi_search_protocol - find a protocol on a handle.
+ * efi_search_protocol() - find a protocol on a handle.
+ * @handle: handle
+ * @protocol_guid: GUID of the protocol
+ * @handler: reference to the protocol
*
- * @handle: handle
- * @protocol_guid: GUID of the protocol
- * @handler: reference to the protocol
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_search_protocol(const efi_handle_t handle,
const efi_guid_t *protocol_guid,
@@ -476,12 +479,12 @@ efi_status_t efi_search_protocol(const efi_handle_t handle,
}
/**
- * efi_remove_protocol - delete protocol from a handle
+ * efi_remove_protocol() - delete protocol from a handle
+ * @handle: handle from which the protocol shall be deleted
+ * @protocol: GUID of the protocol to be deleted
+ * @protocol_interface: interface of the protocol implementation
*
- * @handle: handle from which the protocol shall be deleted
- * @protocol: GUID of the protocol to be deleted
- * @protocol_interface: interface of the protocol implementation
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_remove_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
@@ -503,10 +506,10 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle,
}
/**
- * efi_remove_all_protocols - delete all protocols from a handle
+ * efi_remove_all_protocols() - delete all protocols from a handle
+ * @handle: handle from which the protocols shall be deleted
*
- * @handle: handle from which the protocols shall be deleted
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
{
@@ -529,9 +532,9 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
}
/**
- * efi_delete_handle - delete handle
+ * efi_delete_handle() - delete handle
*
- * @obj: handle to delete
+ * @obj: handle to delete
*/
void efi_delete_handle(struct efi_object *obj)
{
@@ -543,10 +546,10 @@ void efi_delete_handle(struct efi_object *obj)
}
/**
- * efi_is_event - check if a pointer is a valid event
+ * efi_is_event() - check if a pointer is a valid event
+ * @event: pointer to check
*
- * @event: pointer to check
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_is_event(const struct efi_event *event)
{
@@ -562,20 +565,20 @@ static efi_status_t efi_is_event(const struct efi_event *event)
}
/**
- * efi_create_event - create an event
+ * efi_create_event() - create an event
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @group: event group
+ * @event: created event
*
* This function is used inside U-Boot code to create an event.
*
* For the API function implementing the CreateEvent service see
* efi_create_event_ext.
*
- * @type: type of the event to create
- * @notify_tpl: task priority level of the event
- * @notify_function: notification function of the event
- * @notify_context: pointer passed to the notification function
- * @group: event group
- * @event: created event
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
void (EFIAPI *notify_function) (
@@ -614,19 +617,20 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
}
/*
- * efi_create_event_ex - create an event in a group
+ * efi_create_event_ex() - create an event in a group
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @event: created event
+ * @event_group: event group
*
* This function implements the CreateEventEx service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @type: type of the event to create
- * @notify_tpl: task priority level of the event
- * @notify_function: notification function of the event
- * @notify_context: pointer passed to the notification function
- * @event: created event
- * @event_group: event group
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
void (EFIAPI *notify_function) (
@@ -643,18 +647,19 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
}
/**
- * efi_create_event_ext - create an event
+ * efi_create_event_ext() - create an event
+ * @type: type of the event to create
+ * @notify_tpl: task priority level of the event
+ * @notify_function: notification function of the event
+ * @notify_context: pointer passed to the notification function
+ * @event: created event
*
* This function implements the CreateEvent service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @type: type of the event to create
- * @notify_tpl: task priority level of the event
- * @notify_function: notification function of the event
- * @notify_context: pointer passed to the notification function
- * @event: created event
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_create_event_ext(
uint32_t type, efi_uintn_t notify_tpl,
@@ -670,7 +675,7 @@ static efi_status_t EFIAPI efi_create_event_ext(
}
/**
- * efi_timer_check - check if a timer event has occurred
+ * efi_timer_check() - check if a timer event has occurred
*
* Check if a timer event has occurred or a queued notification function should
* be called.
@@ -705,15 +710,15 @@ void efi_timer_check(void)
}
/**
- * efi_set_timer - set the trigger time for a timer event or stop the event
+ * efi_set_timer() - set the trigger time for a timer event or stop the event
+ * @event: event for which the timer is set
+ * @type: type of the timer
+ * @trigger_time: trigger period in multiples of 100ns
*
* This is the function for internal usage in U-Boot. For the API function
* implementing the SetTimer service see efi_set_timer_ext.
*
- * @event: event for which the timer is set
- * @type: type of the timer
- * @trigger_time: trigger period in multiples of 100ns
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
uint64_t trigger_time)
@@ -746,16 +751,19 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
}
/**
- * efi_set_timer_ext - Set the trigger time for a timer event or stop the event
+ * efi_set_timer_ext() - Set the trigger time for a timer event or stop the
+ * event
+ * @event: event for which the timer is set
+ * @type: type of the timer
+ * @trigger_time: trigger period in multiples of 100ns
*
* This function implements the SetTimer service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @event: event for which the timer is set
- * @type: type of the timer
- * @trigger_time: trigger period in multiples of 100ns
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event,
enum efi_timer_delay type,
@@ -766,16 +774,17 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event,
}
/**
- * efi_wait_for_event - wait for events to be signaled
+ * efi_wait_for_event() - wait for events to be signaled
+ * @num_events: number of events to be waited for
+ * @event: events to be waited for
+ * @index: index of the event that was signaled
*
* This function implements the WaitForEvent service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @num_events: number of events to be waited for
- * @event: events to be waited for
- * @index: index of the event that was signaled
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
struct efi_event **event,
@@ -823,17 +832,18 @@ out:
}
/**
- * efi_signal_event_ext - signal an EFI event
+ * efi_signal_event_ext() - signal an EFI event
+ * @event: event to signal
*
* This function implements the SignalEvent service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*
* This functions sets the signaled state of the event and queues the
* notification function for execution.
*
- * @event: event to signal
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
{
@@ -845,14 +855,15 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
}
/**
- * efi_close_event - close an EFI event
+ * efi_close_event() - close an EFI event
+ * @event: event to close
*
* This function implements the CloseEvent service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @event: event to close
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
{
@@ -865,17 +876,18 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
}
/**
- * efi_check_event - check if an event is signaled
+ * efi_check_event() - check if an event is signaled
+ * @event: event to check
*
* This function implements the CheckEvent service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * If an event is not signaled yet, the notification function is queued.
- * The signaled state is cleared.
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * If an event is not signaled yet, the notification function is queued. The
+ * signaled state is cleared.
*
- * @event: event to check
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
{
@@ -894,10 +906,10 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
}
/**
- * efi_search_obj - find the internal EFI object for a handle
+ * efi_search_obj() - find the internal EFI object for a handle
+ * @handle: handle to find
*
- * @handle: handle to find
- * Return Value: EFI object
+ * Return: EFI object
*/
struct efi_object *efi_search_obj(const efi_handle_t handle)
{
@@ -912,11 +924,11 @@ struct efi_object *efi_search_obj(const efi_handle_t handle)
}
/**
- * efi_open_protocol_info_entry - create open protocol info entry and add it
- * to a protocol
+ * efi_open_protocol_info_entry() - create open protocol info entry and add it
+ * to a protocol
+ * @handler: handler of a protocol
*
- * @handler: handler of a protocol
- * Return Value: open protocol info entry
+ * Return: open protocol info entry
*/
static struct efi_open_protocol_info_entry *efi_create_open_info(
struct efi_handler *handler)
@@ -933,10 +945,10 @@ static struct efi_open_protocol_info_entry *efi_create_open_info(
}
/**
- * efi_delete_open_info - remove an open protocol info entry from a protocol
+ * efi_delete_open_info() - remove an open protocol info entry from a protocol
+ * @item: open protocol info entry to delete
*
- * @item: open protocol info entry to delete
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_delete_open_info(
struct efi_open_protocol_info_item *item)
@@ -947,12 +959,12 @@ static efi_status_t efi_delete_open_info(
}
/**
- * efi_add_protocol - install new protocol on a handle
+ * efi_add_protocol() - install new protocol on a handle
+ * @handle: handle on which the protocol shall be installed
+ * @protocol: GUID of the protocol to be installed
+ * @protocol_interface: interface of the protocol implementation
*
- * @handle: handle on which the protocol shall be installed
- * @protocol: GUID of the protocol to be installed
- * @protocol_interface: interface of the protocol implementation
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_add_protocol(const efi_handle_t handle,
const efi_guid_t *protocol,
@@ -981,18 +993,19 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
}
/**
- * efi_install_protocol_interface - install protocol interface
+ * efi_install_protocol_interface() - install protocol interface
+ * @handle: handle on which the protocol shall be installed
+ * @protocol: GUID of the protocol to be installed
+ * @protocol_interface_type: type of the interface to be installed,
+ * always EFI_NATIVE_INTERFACE
+ * @protocol_interface: interface of the protocol implementation
*
* This function implements the InstallProtocolInterface service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle on which the protocol shall be installed
- * @protocol: GUID of the protocol to be installed
- * @protocol_interface_type: type of the interface to be installed,
- * always EFI_NATIVE_INTERFACE
- * @protocol_interface: interface of the protocol implementation
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_install_protocol_interface(
void **handle, const efi_guid_t *protocol,
@@ -1027,15 +1040,15 @@ out:
}
/**
- * efi_get_drivers - get all drivers associated to a controller
+ * efi_get_drivers() - get all drivers associated to a controller
+ * @efiobj: handle of the controller
+ * @protocol: protocol guid (optional)
+ * @number_of_drivers: number of child controllers
+ * @driver_handle_buffer: handles of the the drivers
*
* The allocated buffer has to be freed with free().
*
- * @efiobj: handle of the controller
- * @protocol: protocol guid (optional)
- * @number_of_drivers: number of child controllers
- * @driver_handle_buffer: handles of the the drivers
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_get_drivers(struct efi_object *efiobj,
const efi_guid_t *protocol,
@@ -1092,16 +1105,17 @@ static efi_status_t efi_get_drivers(struct efi_object *efiobj,
}
/**
- * efi_disconnect_all_drivers - disconnect all drivers from a controller
+ * efi_disconnect_all_drivers() - disconnect all drivers from a controller
+ * @efiobj: handle of the controller
+ * @protocol: protocol guid (optional)
+ * @child_handle: handle of the child to destroy
*
* This function implements the DisconnectController service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @efiobj: handle of the controller
- * @protocol: protocol guid (optional)
- * @child_handle: handle of the child to destroy
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t efi_disconnect_all_drivers(
struct efi_object *efiobj,
@@ -1131,16 +1145,17 @@ static efi_status_t efi_disconnect_all_drivers(
}
/**
- * efi_uninstall_protocol_interface - uninstall protocol interface
+ * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * @handle: handle from which the protocol shall be removed
+ * @protocol: GUID of the protocol to be removed
+ * @protocol_interface: interface to be removed
*
* This function implements the UninstallProtocolInterface service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle from which the protocol shall be removed
- * @protocol: GUID of the protocol to be removed
- * @protocol_interface: interface to be removed
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_uninstall_protocol_interface(
efi_handle_t handle, const efi_guid_t *protocol,
@@ -1188,18 +1203,17 @@ out:
}
/**
- * efi_register_protocol_notify - register an event for notification when a
- * protocol is installed.
+ * efi_register_protocol_notify() - register an event for notification when a
+ * protocol is installed.
+ * @protocol: GUID of the protocol whose installation shall be notified
+ * @event: event to be signaled upon installation of the protocol
+ * @registration: key for retrieving the registration information
*
* This function implements the RegisterProtocolNotify service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
- * @protocol: GUID of the protocol whose installation shall be
- * notified
- * @event: event to be signaled upon installation of the protocol
- * @registration: key for retrieving the registration information
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_register_protocol_notify(
const efi_guid_t *protocol,
@@ -1211,15 +1225,15 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
}
/**
- * efi_search - determine if an EFI handle implements a protocol
+ * efi_search() - determine if an EFI handle implements a protocol
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @efiobj: handle
*
* See the documentation of the LocateHandle service in the UEFI specification.
*
- * @search_type: selection criterion
- * @protocol: GUID of the protocol
- * @search_key: registration key
- * @efiobj: handle
- * Return Value: 0 if the handle implements the protocol
+ * Return: 0 if the handle implements the protocol
*/
static int efi_search(enum efi_locate_search_type search_type,
const efi_guid_t *protocol, void *search_key,
@@ -1243,17 +1257,17 @@ static int efi_search(enum efi_locate_search_type search_type,
}
/**
- * efi_locate_handle - locate handles implementing a protocol
+ * efi_locate_handle() - locate handles implementing a protocol
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @buffer_size: size of the buffer to receive the handles in bytes
+ * @buffer: buffer to receive the relevant handles
*
* This function is meant for U-Boot internal calls. For the API implementation
* of the LocateHandle service see efi_locate_handle_ext.
*
- * @search_type: selection criterion
- * @protocol: GUID of the protocol
- * @search_key: registration key
- * @buffer_size: size of the buffer to receive the handles in bytes
- * @buffer: buffer to receive the relevant handles
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_locate_handle(
enum efi_locate_search_type search_type,
@@ -1313,18 +1327,19 @@ static efi_status_t efi_locate_handle(
}
/**
- * efi_locate_handle_ext - locate handles implementing a protocol.
+ * efi_locate_handle_ext() - locate handles implementing a protocol.
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @buffer_size: size of the buffer to receive the handles in bytes
+ * @buffer: buffer to receive the relevant handles
*
* This function implements the LocateHandle service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @search_type: selection criterion
- * @protocol: GUID of the protocol
- * @search_key: registration key
- * @buffer_size: size of the buffer to receive the handles in bytes
- * @buffer: buffer to receive the relevant handles
- * Return Value: 0 if the handle implements the protocol
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: 0 if the handle implements the protocol
*/
static efi_status_t EFIAPI efi_locate_handle_ext(
enum efi_locate_search_type search_type,
@@ -1339,10 +1354,10 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
}
/**
- * efi_remove_configuration_table - collapses configuration table entries,
- * removing index i
+ * efi_remove_configuration_table() - collapses configuration table entries,
+ * removing index i
*
- * @i: index of the table entry to be removed
+ * @i: index of the table entry to be removed
*/
static void efi_remove_configuration_table(int i)
{
@@ -1355,15 +1370,15 @@ static void efi_remove_configuration_table(int i)
}
/**
- * efi_install_configuration_table - adds, updates, or removes a configuration
- * table
+ * efi_install_configuration_table() - adds, updates, or removes a
+ * configuration table
+ * @guid: GUID of the installed table
+ * @table: table to be installed
*
* This function is used for internal calls. For the API implementation of the
* InstallConfigurationTable service see efi_install_configuration_table_ext.
*
- * @guid: GUID of the installed table
- * @table: table to be installed
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
void *table)
@@ -1410,16 +1425,17 @@ out:
}
/**
- * efi_install_configuration_table_ex - Adds, updates, or removes a
- * configuration table.
+ * efi_install_configuration_table_ex() - Adds, updates, or removes a
+ * configuration table.
+ * @guid: GUID of the installed table
+ * @table: table to be installed
*
* This function implements the InstallConfigurationTable service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @guid: GUID of the installed table
- * @table: table to be installed
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
void *table)
@@ -1429,17 +1445,16 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
}
/**
- * efi_setup_loaded_image - initialize a loaded image
+ * efi_setup_loaded_image() - initialize a loaded image
+ * @info: loaded image info to be passed to the entry point of the image
+ * @obj: internal object associated with the loaded image
+ * @device_path: device path of the loaded image
+ * @file_path: file path of the loaded image
*
* Initialize a loaded_image_info and loaded_image_info object with correct
* protocols, boot-device, etc.
*
- * @info: loaded image info to be passed to the entry point of the
- * image
- * @obj: internal object associated with the loaded image
- * @device_path: device path of the loaded image
- * @file_path: file path of the loaded image
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_setup_loaded_image(
struct efi_loaded_image *info, struct efi_object *obj,
@@ -1494,11 +1509,11 @@ failure:
}
/**
- * efi_load_image_from_path - load an image using a file path
+ * efi_load_image_from_path() - load an image using a file path
+ * @file_path: the path of the image to load
+ * @buffer: buffer containing the loaded image
*
- * @file_path: the path of the image to load
- * @buffer: buffer containing the loaded image
- * Return Value: status code
+ * Return: status code
*/
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
void **buffer)
@@ -1543,20 +1558,20 @@ error:
}
/**
- * efi_load_image - load an EFI image into memory
+ * efi_load_image() - load an EFI image into memory
+ * @boot_policy: true for request originating from the boot manager
+ * @parent_image: the caller's image handle
+ * @file_path: the path of the image to load
+ * @source_buffer: memory location from which the image is installed
+ * @source_size: size of the memory area from which the image is installed
+ * @image_handle: handle for the newly installed image
*
* This function implements the LoadImage service.
+ *
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
- * @boot_policy: true for request originating from the boot manager
- * @parent_image: the caller's image handle
- * @file_path: the path of the image to load
- * @source_buffer: memory location from which the image is installed
- * @source_size: size of the memory area from which the image is
- * installed
- * @image_handle: handle for the newly installed image
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_handle_t parent_image,
@@ -1633,16 +1648,17 @@ error:
}
/**
- * efi_start_image - dall the entry point of an image
+ * efi_start_image() - dall the entry point of an image
+ * @image_handle: handle of the image
+ * @exit_data_size: size of the buffer
+ * @exit_data: buffer to receive the exit data of the called image
*
* This function implements the StartImage service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @image_handle: handle of the image
- * @exit_data_size: size of the buffer
- * @exit_data: buffer to receive the exit data of the called image
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
unsigned long *exit_data_size,
@@ -1699,17 +1715,18 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
}
/**
- * efi_exit - leave an EFI application or driver
+ * efi_exit() - leave an EFI application or driver
+ * @image_handle: handle of the application or driver that is exiting
+ * @exit_status: status code
+ * @exit_data_size: size of the buffer in bytes
+ * @exit_data: buffer with data describing an error
*
* This function implements the Exit service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @image_handle: handle of the application or driver that is exiting
- * @exit_status: status code
- * @exit_data_size: size of the buffer in bytes
- * @exit_data: buffer with data describing an error
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
efi_status_t exit_status,
@@ -1748,14 +1765,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
}
/**
- * efi_unload_image - unload an EFI image
+ * efi_unload_image() - unload an EFI image
+ * @image_handle: handle of the image to be unloaded
*
* This function implements the UnloadImage service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @image_handle: handle of the image to be unloaded
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
{
@@ -1770,7 +1788,7 @@ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
}
/**
- * efi_exit_caches - fix up caches for EFI payloads if necessary
+ * efi_exit_caches() - fix up caches for EFI payloads if necessary
*/
static void efi_exit_caches(void)
{
@@ -1785,19 +1803,20 @@ static void efi_exit_caches(void)
}
/**
- * efi_exit_boot_services - stop all boot services
+ * efi_exit_boot_services() - stop all boot services
+ * @image_handle: handle of the loaded image
+ * @map_key: key of the memory map
*
* This function implements the ExitBootServices service.
+ *
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
- * All timer events are disabled.
- * For exit boot services events the notification function is called.
- * The boot services are disabled in the system table.
+ * All timer events are disabled. For exit boot services events the
+ * notification function is called. The boot services are disabled in the
+ * system table.
*
- * @image_handle: handle of the loaded image
- * @map_key: key of the memory map
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
unsigned long map_key)
@@ -1860,14 +1879,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
}
/**
- * efi_get_next_monotonic_count - get next value of the counter
+ * efi_get_next_monotonic_count() - get next value of the counter
+ * @count: returned value of the counter
*
* This function implements the NextMonotonicCount service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @count: returned value of the counter
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
{
@@ -1879,14 +1899,15 @@ static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
}
/**
- * efi_stall - sleep
+ * efi_stall() - sleep
+ * @microseconds: period to sleep in microseconds
*
- * This function implements the Stall sercive.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
+ * This function implements the Stall service.
*
- * @microseconds: period to sleep in microseconds
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
{
@@ -1896,17 +1917,18 @@ static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
}
/**
- * efi_set_watchdog_timer - reset the watchdog timer
+ * efi_set_watchdog_timer() - reset the watchdog timer
+ * @timeout: seconds before reset by watchdog
+ * @watchdog_code: code to be logged when resetting
+ * @data_size: size of buffer in bytes
+ * @watchdog_data: buffer with data describing the reset reason
*
* This function implements the SetWatchdogTimer service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @timeout: seconds before reset by watchdog
- * @watchdog_code: code to be logged when resetting
- * @data_size: size of buffer in bytes
- * @watchdog_data: buffer with data describing the reset reason
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
uint64_t watchdog_code,
@@ -1919,17 +1941,18 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
}
/**
- * efi_close_protocol - close a protocol
+ * efi_close_protocol() - close a protocol
+ * @handle: handle on which the protocol shall be closed
+ * @protocol: GUID of the protocol to close
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
*
* This function implements the CloseProtocol service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle on which the protocol shall be closed
- * @protocol: GUID of the protocol to close
- * @agent_handle: handle of the driver
- * @controller_handle: handle of the controller
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
const efi_guid_t *protocol,
@@ -1966,18 +1989,19 @@ out:
}
/**
- * efi_open_protocol_information - provide information about then open status
- * of a protocol on a handle
+ * efi_open_protocol_information() - provide information about then open status
+ * of a protocol on a handle
+ * @handle: handle for which the information shall be retrieved
+ * @protocol: GUID of the protocol
+ * @entry_buffer: buffer to receive the open protocol information
+ * @entry_count: number of entries available in the buffer
*
* This function implements the OpenProtocolInformation service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle for which the information shall be retrieved
- * @protocol: GUID of the protocol
- * @entry_buffer: buffer to receive the open protocol information
- * @entry_count: number of entries available in the buffer
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_open_protocol_information(
efi_handle_t handle, const efi_guid_t *protocol,
@@ -2030,16 +2054,17 @@ out:
}
/**
- * efi_protocols_per_handle - get protocols installed on a handle
+ * efi_protocols_per_handle() - get protocols installed on a handle
+ * @handle: handle for which the information is retrieved
+ * @protocol_buffer: buffer with protocol GUIDs
+ * @protocol_buffer_count: number of entries in the buffer
*
* This function implements the ProtocolsPerHandleService.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle for which the information is retrieved
- * @protocol_buffer: buffer with protocol GUIDs
- * @protocol_buffer_count: number of entries in the buffer
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_protocols_per_handle(
efi_handle_t handle, efi_guid_t ***protocol_buffer,
@@ -2091,18 +2116,19 @@ static efi_status_t EFIAPI efi_protocols_per_handle(
}
/**
- * efi_locate_handle_buffer - locate handles implementing a protocol
+ * efi_locate_handle_buffer() - locate handles implementing a protocol
+ * @search_type: selection criterion
+ * @protocol: GUID of the protocol
+ * @search_key: registration key
+ * @no_handles: number of returned handles
+ * @buffer: buffer with the returned handles
*
* This function implements the LocateHandleBuffer service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @search_type: selection criterion
- * @protocol: GUID of the protocol
- * @search_key: registration key
- * @no_handles: number of returned handles
- * @buffer: buffer with the returned handles
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_locate_handle_buffer(
enum efi_locate_search_type search_type,
@@ -2138,16 +2164,17 @@ out:
}
/**
- * efi_locate_protocol - find an interface implementing a protocol
+ * efi_locate_protocol() - find an interface implementing a protocol
+ * @protocol: GUID of the protocol
+ * @registration: registration key passed to the notification function
+ * @protocol_interface: interface implementing the protocol
*
* This function implements the LocateProtocol service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @protocol: GUID of the protocol
- * @registration: registration key passed to the notification function
- * @protocol_interface: interface implementing the protocol
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
void *registration,
@@ -2179,17 +2206,18 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
}
/**
- * efi_locate_device_path - Get the device path and handle of an device
- * implementing a protocol
+ * efi_locate_device_path() - Get the device path and handle of an device
+ * implementing a protocol
+ * @protocol: GUID of the protocol
+ * @device_path: device path
+ * @device: handle of the device
*
* This function implements the LocateDevicePath service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @protocol: GUID of the protocol
- * @device_path: device path
- * @device: handle of the device
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_locate_device_path(
const efi_guid_t *protocol,
@@ -2256,17 +2284,18 @@ out:
}
/**
- * Install multiple protocol interfaces.
+ * efi_install_multiple_protocol_interfaces() - Install multiple protocol
+ * interfaces
+ * @handle: handle on which the protocol interfaces shall be installed
+ * @...: NULL terminated argument list with pairs of protocol GUIDS and
+ * interfaces
*
* This function implements the MultipleProtocolInterfaces service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle on which the protocol interfaces shall be
- * installed
- * @...: NULL terminated argument list with pairs of protocol
- * GUIDS and interfaces
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
void **handle, ...)
@@ -2314,18 +2343,18 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
}
/**
- * efi_uninstall_multiple_protocol_interfaces - uninstall multiple protocol
- * interfaces
+ * efi_uninstall_multiple_protocol_interfaces() - uninstall multiple protocol
+ * interfaces
+ * @handle: handle from which the protocol interfaces shall be removed
+ * @...: NULL terminated argument list with pairs of protocol GUIDS and
+ * interfaces
*
* This function implements the UninstallMultipleProtocolInterfaces service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle from which the protocol interfaces shall be
- * removed
- * @...: NULL terminated argument list with pairs of protocol
- * GUIDS and interfaces
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
void *handle, ...)
@@ -2373,16 +2402,17 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
}
/**
- * efi_calculate_crc32 - calculate cyclic redundancy code
+ * efi_calculate_crc32() - calculate cyclic redundancy code
+ * @data: buffer with data
+ * @data_size: size of buffer in bytes
+ * @crc32_p: cyclic redundancy code
*
* This function implements the CalculateCrc32 service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @data: buffer with data
- * @data_size: size of buffer in bytes
- * @crc32_p: cyclic redundancy code
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_calculate_crc32(void *data,
unsigned long data_size,
@@ -2394,15 +2424,15 @@ static efi_status_t EFIAPI efi_calculate_crc32(void *data,
}
/**
- * efi_copy_mem - copy memory
+ * efi_copy_mem() - copy memory
+ * @destination: destination of the copy operation
+ * @source: source of the copy operation
+ * @length: number of bytes to copy
*
* This function implements the CopyMem service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @destination: destination of the copy operation
- * @source: source of the copy operation
- * @length: number of bytes to copy
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*/
static void EFIAPI efi_copy_mem(void *destination, const void *source,
size_t length)
@@ -2413,15 +2443,15 @@ static void EFIAPI efi_copy_mem(void *destination, const void *source,
}
/**
- * efi_set_mem - Fill memory with a byte value.
+ * efi_set_mem() - Fill memory with a byte value.
+ * @buffer: buffer to fill
+ * @size: size of buffer in bytes
+ * @value: byte to copy to the buffer
*
* This function implements the SetMem service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @buffer: buffer to fill
- * @size: size of buffer in bytes
- * @value: byte to copy to the buffer
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*/
static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value)
{
@@ -2431,14 +2461,14 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value)
}
/**
- * efi_protocol_open - open protocol interface on a handle
+ * efi_protocol_open() - open protocol interface on a handle
+ * @handler: handler of a protocol
+ * @protocol_interface: interface implementing the protocol
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
+ * @attributes: attributes indicating how to open the protocol
*
- * @handler: handler of a protocol
- * @protocol_interface: interface implementing the protocol
- * @agent_handle: handle of the driver
- * @controller_handle: handle of the controller
- * @attributes: attributes indicating how to open the protocol
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_protocol_open(
struct efi_handler *handler,
@@ -2526,19 +2556,20 @@ out:
}
/**
- * efi_open_protocol - open protocol interface on a handle
+ * efi_open_protocol() - open protocol interface on a handle
+ * @handle: handle on which the protocol shall be opened
+ * @protocol: GUID of the protocol
+ * @protocol_interface: interface implementing the protocol
+ * @agent_handle: handle of the driver
+ * @controller_handle: handle of the controller
+ * @attributes: attributes indicating how to open the protocol
*
* This function implements the OpenProtocol interface.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle on which the protocol shall be opened
- * @protocol: GUID of the protocol
- * @protocol_interface: interface implementing the protocol
- * @agent_handle: handle of the driver
- * @controller_handle: handle of the controller
- * @attributes: attributes indicating how to open the protocol
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_open_protocol(
void *handle, const efi_guid_t *protocol,
@@ -2593,16 +2624,17 @@ out:
}
/**
- * efi_handle_protocol - get interface of a protocol on a handle
+ * efi_handle_protocol() - get interface of a protocol on a handle
+ * @handle: handle on which the protocol shall be opened
+ * @protocol: GUID of the protocol
+ * @protocol_interface: interface implementing the protocol
*
* This function implements the HandleProtocol service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @handle: handle on which the protocol shall be opened
- * @protocol: GUID of the protocol
- * @protocol_interface: interface implementing the protocol
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle,
const efi_guid_t *protocol,
@@ -2613,12 +2645,12 @@ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle,
}
/**
- * efi_bind_controller - bind a single driver to a controller
+ * efi_bind_controller() - bind a single driver to a controller
+ * @controller_handle: controller handle
+ * @driver_image_handle: driver handle
+ * @remain_device_path: remaining path
*
- * @controller_handle: controller handle
- * @driver_image_handle: driver handle
- * @remain_device_path: remaining path
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_bind_controller(
efi_handle_t controller_handle,
@@ -2649,12 +2681,12 @@ static efi_status_t efi_bind_controller(
}
/**
- * efi_connect_single_controller - connect a single driver to a controller
+ * efi_connect_single_controller() - connect a single driver to a controller
+ * @controller_handle: controller
+ * @driver_image_handle: driver
+ * @remain_device_path: remainting path
*
- * @controller_handle: controller
- * @driver_image_handle: driver
- * @remain_device_path: remainting path
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_connect_single_controller(
efi_handle_t controller_handle,
@@ -2721,21 +2753,22 @@ static efi_status_t efi_connect_single_controller(
}
/**
- * efi_connect_controller - connect a controller to a driver
+ * efi_connect_controller() - connect a controller to a driver
+ * @controller_handle: handle of the controller
+ * @driver_image_handle: handle of the driver
+ * @remain_device_path: device path of a child controller
+ * @recursive: true to connect all child controllers
*
* This function implements the ConnectController service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*
* First all driver binding protocol handles are tried for binding drivers.
* Afterwards all handles that have openened a protocol of the controller
* with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER are connected to drivers.
*
- * @controller_handle: handle of the controller
- * @driver_image_handle: handle of the driver
- * @remain_device_path: device path of a child controller
- * @recursive: true to connect all child controllers
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_connect_controller(
efi_handle_t controller_handle,
@@ -2789,21 +2822,21 @@ out:
}
/**
- * efi_reinstall_protocol_interface - reinstall protocol interface
+ * efi_reinstall_protocol_interface() - reinstall protocol interface
+ * @handle: handle on which the protocol shall be reinstalled
+ * @protocol: GUID of the protocol to be installed
+ * @old_interface: interface to be removed
+ * @new_interface: interface to be installed
*
* This function implements the ReinstallProtocolInterface service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
*
* The old interface is uninstalled. The new interface is installed.
* Drivers are connected.
*
- * @handle: handle on which the protocol shall be
- * reinstalled
- * @protocol: GUID of the protocol to be installed
- * @old_interface: interface to be removed
- * @new_interface: interface to be installed
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t EFIAPI efi_reinstall_protocol_interface(
efi_handle_t handle, const efi_guid_t *protocol,
@@ -2832,15 +2865,15 @@ out:
}
/**
- * efi_get_child_controllers - get all child controllers associated to a driver
+ * efi_get_child_controllers() - get all child controllers associated to a driver
+ * @efiobj: handle of the controller
+ * @driver_handle: handle of the driver
+ * @number_of_children: number of child controllers
+ * @child_handle_buffer: handles of the the child controllers
*
* The allocated buffer has to be freed with free().
*
- * @efiobj: handle of the controller
- * @driver_handle: handle of the driver
- * @number_of_children: number of child controllers
- * @child_handle_buffer: handles of the the child controllers
- * Return Value: status code
+ * Return: status code
*/
static efi_status_t efi_get_child_controllers(
struct efi_object *efiobj,
@@ -2896,16 +2929,17 @@ static efi_status_t efi_get_child_controllers(
}
/**
- * efi_disconnect_controller - disconnect a controller from a driver
+ * efi_disconnect_controller() - disconnect a controller from a driver
+ * @controller_handle: handle of the controller
+ * @driver_image_handle: handle of the driver
+ * @child_handle: handle of the child to destroy
*
* This function implements the DisconnectController service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
*
- * @controller_handle: handle of the controller
- * @driver_image_handle: handle of the driver
- * @child_handle: handle of the child to destroy
- * Return Value: status code
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
*/
static efi_status_t EFIAPI efi_disconnect_controller(
efi_handle_t controller_handle,
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 08a6c76845..3cb6259182 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1,5 +1,7 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
+use warnings;
use strict;
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
@@ -39,41 +41,51 @@ use strict;
# 25/07/2012 - Added support for HTML5
# -- Dan Luedtke <mail at danrl.de>
-#
-# This will read a 'c' file and scan for embedded comments in the
-# style of gnome comments (+minor extensions - see below).
-#
-
-# Note: This only supports 'c'.
-
-# usage:
-# kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
-# [ -no-doc-sections ]
-# [ -function funcname [ -function funcname ...] ]
-# c file(s)s > outputfile
-# or
-# [ -nofunction funcname [ -function funcname ...] ]
-# c file(s)s > outputfile
-#
-# Set output format using one of -docbook -html -html5 -text or -man.
-# Default is man.
-# The -list format is for internal use by docproc.
-#
-# -no-doc-sections
-# Do not output DOC: sections
-#
-# -function funcname
-# If set, then only generate documentation for the given function(s) or
-# DOC: section titles. All other functions and DOC: sections are ignored.
-#
-# -nofunction funcname
-# If set, then only generate documentation for the other function(s)/DOC:
-# sections. Cannot be used together with -function (yes, that's a bug --
-# perl hackers can fix it 8))
-#
-# c files - list of 'c' files to process
-#
-# All output goes to stdout, with errors to stderr.
+sub usage {
+ my $message = <<"EOF";
+Usage: $0 [OPTION ...] FILE ...
+
+Read C language source or header FILEs, extract embedded documentation comments,
+and print formatted documentation to standard output.
+
+The documentation comments are identified by "/**" opening comment mark. See
+Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
+
+Output format selection (mutually exclusive):
+ -man Output troff manual page format. This is the default.
+ -rst Output reStructuredText format.
+ -none Do not output documentation, only warnings.
+
+Output selection (mutually exclusive):
+ -export Only output documentation for symbols that have been
+ exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
+ in any input FILE or -export-file FILE.
+ -internal Only output documentation for symbols that have NOT been
+ exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
+ in any input FILE or -export-file FILE.
+ -function NAME Only output documentation for the given function(s)
+ or DOC: section title(s). All other functions and DOC:
+ sections are ignored. May be specified multiple times.
+ -nofunction NAME Do NOT output documentation for the given function(s);
+ only output documentation for the other functions and
+ DOC: sections. May be specified multiple times.
+
+Output selection modifiers:
+ -no-doc-sections Do not output DOC: sections.
+ -enable-lineno Enable output of #define LINENO lines. Only works with
+ reStructuredText format.
+ -export-file FILE Specify an additional FILE in which to look for
+ EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with
+ -export or -internal. May be specified multiple times.
+
+Other parameters:
+ -v Verbose output, more warnings and other information.
+ -h Print this help.
+
+EOF
+ print $message;
+ exit 1;
+}
#
# format of comments.
@@ -133,6 +145,30 @@ use strict;
#
# All descriptions can be multiline, except the short function description.
#
+# For really longs structs, you can also describe arguments inside the
+# body of the struct.
+# eg.
+# /**
+# * struct my_struct - short description
+# * @a: first member
+# * @b: second member
+# *
+# * Longer description
+# */
+# struct my_struct {
+# int a;
+# int b;
+# /**
+# * @c: This is longer description of C
+# *
+# * You can use paragraphs to describe arguments
+# * using this method.
+# */
+# int c;
+# };
+#
+# This should be use only for struct/enum members.
+#
# You can also add additional sections. When documenting kernel functions you
# should document the "Context:" of the function, e.g. whether the functions
# can be called form interrupts. Unlike other sections you can end it with an
@@ -161,8 +197,10 @@ use strict;
# 'funcname()' - function
# '$ENVVAR' - environmental variable
# '&struct_name' - name of a structure (up to two words including 'struct')
+# '&struct_name.member' - name of a structure member
# '@parameter' - name of a parameter
# '%CONST' - name of a constant.
+# '``LITERAL``' - literal string without any spaces on it.
## init lots of data
@@ -171,71 +209,56 @@ my $warnings = 0;
my $anon_struct_union = 0;
# match expressions used to find embedded type information
-my $type_constant = '\%([-_\w]+)';
+my $type_constant = '\b``([^\`]+)``\b';
+my $type_constant2 = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
-my $type_param = '\@(\w+)';
-my $type_struct = '\&((struct\s*)*[_\w]+)';
-my $type_struct_xml = '\\&((struct\s*)*[_\w]+)';
+my $type_param = '\@(\w*(\.\w+)*(\.\.\.)?)';
+my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_env = '(\$\w+)';
+my $type_enum = '\&(enum\s*([_\w]+))';
+my $type_struct = '\&(struct\s*([_\w]+))';
+my $type_typedef = '\&(typedef\s*([_\w]+))';
+my $type_union = '\&(union\s*([_\w]+))';
+my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
+my $type_fallback = '\&([_\w]+)';
+my $type_member_func = $type_member . '\(\)';
# Output conversion substitutions.
# One for each output format
-# these work fairly well
-my %highlights_html = ( $type_constant, "<i>\$1</i>",
- $type_func, "<b>\$1</b>",
- $type_struct_xml, "<i>\$1</i>",
- $type_env, "<b><i>\$1</i></b>",
- $type_param, "<tt><b>\$1</b></tt>" );
-my $local_lt = "\\\\\\\\lt:";
-my $local_gt = "\\\\\\\\gt:";
-my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
-
-# html version 5
-my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
- $type_func, "<span class=\"func\">\$1</span>",
- $type_struct_xml, "<span class=\"struct\">\$1</span>",
- $type_env, "<span class=\"env\">\$1</span>",
- $type_param, "<span class=\"param\">\$1</span>" );
-my $blankline_html5 = $local_lt . "br /" . $local_gt;
-
-# XML, docbook format
-my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
- $type_constant, "<constant>\$1</constant>",
- $type_func, "<function>\$1</function>",
- $type_struct_xml, "<structname>\$1</structname>",
- $type_env, "<envar>\$1</envar>",
- $type_param, "<parameter>\$1</parameter>" );
-my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
-
-# gnome, docbook format
-my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
- $type_func, "<function>\$1</function>",
- $type_struct, "<structname>\$1</structname>",
- $type_env, "<envar>\$1</envar>",
- $type_param, "<parameter>\$1</parameter>" );
-my $blankline_gnome = "</para><para>\n";
-
# these are pretty rough
-my %highlights_man = ( $type_constant, "\$1",
- $type_func, "\\\\fB\$1\\\\fP",
- $type_struct, "\\\\fI\$1\\\\fP",
- $type_param, "\\\\fI\$1\\\\fP" );
+my @highlights_man = (
+ [$type_constant, "\$1"],
+ [$type_constant2, "\$1"],
+ [$type_func, "\\\\fB\$1\\\\fP"],
+ [$type_enum, "\\\\fI\$1\\\\fP"],
+ [$type_struct, "\\\\fI\$1\\\\fP"],
+ [$type_typedef, "\\\\fI\$1\\\\fP"],
+ [$type_union, "\\\\fI\$1\\\\fP"],
+ [$type_param, "\\\\fI\$1\\\\fP"],
+ [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
+ [$type_fallback, "\\\\fI\$1\\\\fP"]
+ );
my $blankline_man = "";
-# text-mode
-my %highlights_text = ( $type_constant, "\$1",
- $type_func, "\$1",
- $type_struct, "\$1",
- $type_param, "\$1" );
-my $blankline_text = "";
-
-# list mode
-my %highlights_list = ( $type_constant, "\$1",
- $type_func, "\$1",
- $type_struct, "\$1",
- $type_param, "\$1" );
-my $blankline_list = "";
+# rst-mode
+my @highlights_rst = (
+ [$type_constant, "``\$1``"],
+ [$type_constant2, "``\$1``"],
+ # Note: need to escape () to avoid func matching later
+ [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
+ [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
+ [$type_fp_param, "**\$1\\\\(\\\\)**"],
+ [$type_func, "\\:c\\:func\\:`\$1()`"],
+ [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
+ [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
+ # in rst this can refer to any type
+ [$type_fallback, "\\:c\\:type\\:`\$1`"],
+ [$type_param, "**\$1**"]
+ );
+my $blankline_rst = "\n";
# read arguments
if ($#ARGV == -1) {
@@ -246,24 +269,45 @@ my $kernelversion;
my $dohighlight = "";
my $verbose = 0;
-my $output_mode = "man";
+my $output_mode = "rst";
my $output_preformatted = 0;
my $no_doc_sections = 0;
-my %highlights = %highlights_man;
-my $blankline = $blankline_man;
-my $modulename = "Bootloader API";
-my $function_only = 0;
+my $enable_lineno = 0;
+my @highlights = @highlights_rst;
+my $blankline = $blankline_rst;
+my $modulename = "Kernel API";
+
+use constant {
+ OUTPUT_ALL => 0, # output all symbols and doc sections
+ OUTPUT_INCLUDE => 1, # output only specified symbols
+ OUTPUT_EXCLUDE => 2, # output everything except specified symbols
+ OUTPUT_EXPORTED => 3, # output exported symbols
+ OUTPUT_INTERNAL => 4, # output non-exported symbols
+};
+my $output_selection = OUTPUT_ALL;
+my $show_not_found = 0;
+
+my @export_file_list;
+
+my @build_time;
+if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
+ (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
+ @build_time = gmtime($seconds);
+} else {
+ @build_time = localtime;
+}
+
my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October',
- 'November', 'December')[(localtime)[4]] .
- " " . ((localtime)[5]+1900);
-my $show_not_found = 0;
+ 'November', 'December')[$build_time[4]] .
+ " " . ($build_time[5]+1900);
# Essentially these are globals.
# They probably want to be tidied up, made more localised or something.
# CAVEAT EMPTOR! Some of the others I localised may not want to be, which
# could cause "use of undefined value" or other bugs.
my ($function, %function_table, %parametertypes, $declaration_purpose);
+my $declaration_start_line;
my ($type, $declaration_name, $return_type);
my ($newsection, $newcontents, $prototype, $brcount, %source_map);
@@ -281,39 +325,65 @@ my $section_counter = 0;
my $lineprefix="";
-# states
-# 0 - normal code
-# 1 - looking for function name
-# 2 - scanning field start.
-# 3 - scanning prototype.
-# 4 - documentation block
+# Parser states
+use constant {
+ STATE_NORMAL => 0, # normal code
+ STATE_NAME => 1, # looking for function name
+ STATE_BODY_MAYBE => 2, # body - or maybe more description
+ STATE_BODY => 3, # the body of the comment
+ STATE_PROTO => 4, # scanning prototype
+ STATE_DOCBLOCK => 5, # documentation block
+ STATE_INLINE => 6, # gathering documentation outside main block
+};
my $state;
my $in_doc_sect;
+my $leading_space;
+
+# Inline documentation state
+use constant {
+ STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE)
+ STATE_INLINE_NAME => 1, # looking for member name (@foo:)
+ STATE_INLINE_TEXT => 2, # looking for member documentation
+ STATE_INLINE_END => 3, # done
+ STATE_INLINE_ERROR => 4, # error - Comment without header was found.
+ # Spit a warning as it's not
+ # proper kernel-doc and ignore the rest.
+};
+my $inline_doc_state;
#declaration types: can be
# 'function', 'struct', 'union', 'enum', 'typedef'
my $decl_type;
-my $doc_special = "\@\%\$\&";
-
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
my $doc_end = '\*/';
my $doc_com = '\s*\*\s*';
my $doc_com_body = '\s*\* ?';
my $doc_decl = $doc_com . '(\w+)';
-my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
+# @params and a strictly limited set of supported section names
+my $doc_sect = $doc_com .
+ '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
my $doc_content = $doc_com_body . '(.*)';
my $doc_block = $doc_com . 'DOC:\s*(.*)?';
+my $doc_inline_start = '^\s*/\*\*\s*$';
+my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
+my $doc_inline_end = '^\s*\*/\s*$';
+my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
+my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
-my %constants;
my %parameterdescs;
+my %parameterdesc_start_lines;
my @parameterlist;
my %sections;
my @sectionlist;
+my %section_start_lines;
my $sectcheck;
my $struct_actual;
my $contents = "";
+my $new_start_line = 0;
+
+# the canonical section names. see also $doc_sect above.
my $section_default = "Description"; # default section
my $section_intro = "Introduction";
my $section = $section_default;
@@ -324,80 +394,73 @@ my $undescribed = "-- undescribed --";
reset_state();
-while ($ARGV[0] =~ m/^-(.*)/) {
- my $cmd = shift @ARGV;
- if ($cmd eq "-html") {
- $output_mode = "html";
- %highlights = %highlights_html;
- $blankline = $blankline_html;
- } elsif ($cmd eq "-html5") {
- $output_mode = "html5";
- %highlights = %highlights_html5;
- $blankline = $blankline_html5;
- } elsif ($cmd eq "-man") {
+while ($ARGV[0] =~ m/^--?(.*)/) {
+ my $cmd = $1;
+ shift @ARGV;
+ if ($cmd eq "man") {
$output_mode = "man";
- %highlights = %highlights_man;
+ @highlights = @highlights_man;
$blankline = $blankline_man;
- } elsif ($cmd eq "-text") {
- $output_mode = "text";
- %highlights = %highlights_text;
- $blankline = $blankline_text;
- } elsif ($cmd eq "-docbook") {
- $output_mode = "xml";
- %highlights = %highlights_xml;
- $blankline = $blankline_xml;
- } elsif ($cmd eq "-list") {
- $output_mode = "list";
- %highlights = %highlights_list;
- $blankline = $blankline_list;
- } elsif ($cmd eq "-gnome") {
- $output_mode = "gnome";
- %highlights = %highlights_gnome;
- $blankline = $blankline_gnome;
- } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
+ } elsif ($cmd eq "rst") {
+ $output_mode = "rst";
+ @highlights = @highlights_rst;
+ $blankline = $blankline_rst;
+ } elsif ($cmd eq "none") {
+ $output_mode = "none";
+ } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
$modulename = shift @ARGV;
- } elsif ($cmd eq "-function") { # to only output specific functions
- $function_only = 1;
+ } elsif ($cmd eq "function") { # to only output specific functions
+ $output_selection = OUTPUT_INCLUDE;
$function = shift @ARGV;
$function_table{$function} = 1;
- } elsif ($cmd eq "-nofunction") { # to only output specific functions
- $function_only = 2;
+ } elsif ($cmd eq "nofunction") { # output all except specific functions
+ $output_selection = OUTPUT_EXCLUDE;
$function = shift @ARGV;
$function_table{$function} = 1;
- } elsif ($cmd eq "-v") {
+ } elsif ($cmd eq "export") { # only exported symbols
+ $output_selection = OUTPUT_EXPORTED;
+ %function_table = ();
+ } elsif ($cmd eq "internal") { # only non-exported symbols
+ $output_selection = OUTPUT_INTERNAL;
+ %function_table = ();
+ } elsif ($cmd eq "export-file") {
+ my $file = shift @ARGV;
+ push(@export_file_list, $file);
+ } elsif ($cmd eq "v") {
$verbose = 1;
- } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
+ } elsif (($cmd eq "h") || ($cmd eq "help")) {
usage();
- } elsif ($cmd eq '-no-doc-sections') {
+ } elsif ($cmd eq 'no-doc-sections') {
$no_doc_sections = 1;
- } elsif ($cmd eq '-show-not-found') {
+ } elsif ($cmd eq 'enable-lineno') {
+ $enable_lineno = 1;
+ } elsif ($cmd eq 'show-not-found') {
$show_not_found = 1;
+ } else {
+ # Unknown argument
+ usage();
}
}
# continue execution near EOF;
-sub usage {
- print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
- print " [ -no-doc-sections ]\n";
- print " [ -function funcname [ -function funcname ...] ]\n";
- print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
- print " [ -v ]\n";
- print " c source file(s) > outputfile\n";
- print " -v : verbose output, more warnings & other info listed\n";
- exit 1;
-}
-
# get kernel version from env
sub get_kernel_version() {
my $version = 'unknown kernel version';
- if (defined($ENV{'UBOOTVERSION'})) {
- $version = $ENV{'UBOOTVERSION'};
+ if (defined($ENV{'KERNELVERSION'})) {
+ $version = $ENV{'KERNELVERSION'};
}
return $version;
}
+#
+sub print_lineno {
+ my $lineno = shift;
+ if ($enable_lineno && defined($lineno)) {
+ print "#define LINENO " . $lineno . "\n";
+ }
+}
##
# dumps section contents to arrays/hashes intended for that purpose.
#
@@ -406,28 +469,32 @@ sub dump_section {
my $name = shift;
my $contents = join "\n", @_;
- if ($name =~ m/$type_constant/) {
- $name = $1;
-# print STDERR "constant section '$1' = '$contents'\n";
- $constants{$name} = $contents;
- } elsif ($name =~ m/$type_param/) {
-# print STDERR "parameter def '$1' = '$contents'\n";
+ if ($name =~ m/$type_param/) {
$name = $1;
$parameterdescs{$name} = $contents;
$sectcheck = $sectcheck . $name . " ";
+ $parameterdesc_start_lines{$name} = $new_start_line;
+ $new_start_line = 0;
} elsif ($name eq "@\.\.\.") {
-# print STDERR "parameter def '...' = '$contents'\n";
$name = "...";
$parameterdescs{$name} = $contents;
$sectcheck = $sectcheck . $name . " ";
+ $parameterdesc_start_lines{$name} = $new_start_line;
+ $new_start_line = 0;
} else {
-# print STDERR "other section '$name' = '$contents'\n";
if (defined($sections{$name}) && ($sections{$name} ne "")) {
- print STDERR "Error(${file}:$.): duplicate section name '$name'\n";
- ++$errors;
+ # Only warn on user specified duplicate section names.
+ if ($name ne $section_default) {
+ print STDERR "${file}:$.: warning: duplicate section name '$name'\n";
+ ++$warnings;
+ }
+ $sections{$name} .= $contents;
+ } else {
+ $sections{$name} = $contents;
+ push @sectionlist, $name;
+ $section_start_lines{$name} = $new_start_line;
+ $new_start_line = 0;
}
- $sections{$name} = $contents;
- push @sectionlist, $name;
}
}
@@ -443,15 +510,17 @@ sub dump_doc_section {
return;
}
- if (($function_only == 0) ||
- ( $function_only == 1 && defined($function_table{$name})) ||
- ( $function_only == 2 && !defined($function_table{$name})))
+ if (($output_selection == OUTPUT_ALL) ||
+ ($output_selection == OUTPUT_INCLUDE &&
+ defined($function_table{$name})) ||
+ ($output_selection == OUTPUT_EXCLUDE &&
+ !defined($function_table{$name})))
{
dump_section($file, $name, $contents);
output_blockhead({'sectionlist' => \@sectionlist,
'sections' => \%sections,
'module' => $modulename,
- 'content-only' => ($function_only != 0), });
+ 'content-only' => ($output_selection != OUTPUT_ALL), });
}
}
@@ -476,32 +545,20 @@ sub output_highlight {
# confess "output_highlight got called with no args?\n";
# }
- if ($output_mode eq "html" || $output_mode eq "html5" ||
- $output_mode eq "xml") {
- $contents = local_unescape($contents);
- # convert data read & converted thru xml_escape() into &xyz; format:
- $contents =~ s/\\\\\\/\&/g;
- }
# print STDERR "contents b4:$contents\n";
eval $dohighlight;
die $@ if $@;
# print STDERR "contents af:$contents\n";
-# strip whitespaces when generating html5
- if ($output_mode eq "html5") {
- $contents =~ s/^\s+//;
- $contents =~ s/\s+$//;
- }
foreach $line (split "\n", $contents) {
if (! $output_preformatted) {
$line =~ s/^\s*//;
}
if ($line eq ""){
if (! $output_preformatted) {
- print $lineprefix, local_unescape($blankline);
+ print $lineprefix, $blankline;
}
} else {
- $line =~ s/\\\\\\/\&/g;
if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
print "\\&$line";
} else {
@@ -512,815 +569,6 @@ sub output_highlight {
}
}
-# output sections in html
-sub output_section_html(%) {
- my %args = %{$_[0]};
- my $section;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<h3>$section</h3>\n";
- print "<blockquote>\n";
- output_highlight($args{'sections'}{$section});
- print "</blockquote>\n";
- }
-}
-
-# output enum in html
-sub output_enum_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "<h2>enum " . $args{'enum'} . "</h2>\n";
-
- print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print " <b>" . $parameter . "</b>";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- }
- print "<br>";
- }
- print "};<br>\n";
-
- print "<h3>Constants</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output typedef in html
-sub output_typedef_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
-
- print "<b>typedef " . $args{'typedef'} . "</b>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output struct in html
-sub output_struct_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
-
- print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
- print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print "$parameter<br>\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
- } else {
- print " <i>$type</i> <b>$parameter</b>;<br>\n";
- }
- }
- print "};<br>\n";
-
- print "<h3>Members</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output function in html
-sub output_function_html(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
- print "<i>" . $args{'functiontype'} . "</i>\n";
- print "<b>" . $args{'function'} . "</b>\n";
- print "(";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
- } else {
- print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
- }
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- }
- }
- print ")\n";
-
- print "<h3>Arguments</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output DOC: block header in html
-sub output_blockhead_html(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<h3>$section</h3>\n";
- print "<ul>\n";
- output_highlight($args{'sections'}{$section});
- print "</ul>\n";
- }
- print "<hr>\n";
-}
-
-# output sections in html5
-sub output_section_html5(%) {
- my %args = %{$_[0]};
- my $section;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<section>\n";
- print "<h1>$section</h1>\n";
- print "<p>\n";
- output_highlight($args{'sections'}{$section});
- print "</p>\n";
- print "</section>\n";
- }
-}
-
-# output enum in html5
-sub output_enum_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- my $html5id;
-
- $html5id = $args{'enum'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
- print "<h1>enum " . $args{'enum'} . "</h1>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"keyword\">enum</span> ";
- print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
- print "</li>\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- print "<span class=\"param\">" . $parameter . "</span>";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "</li>\n";
- }
- print "<li>};</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Constants</h1>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output typedef in html5
-sub output_typedef_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- my $html5id;
-
- $html5id = $args{'typedef'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
- print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
-
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"keyword\">typedef</span> ";
- print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
- print "</li>\n";
- print "</ol>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output struct in html5
-sub output_struct_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $html5id;
-
- $html5id = $args{'struct'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
- print "<hgroup>\n";
- print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
- print "<h2>". $args{'purpose'} . "</h2>\n";
- print "</hgroup>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"type\">" . $args{'type'} . "</span> ";
- print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
- print "</li>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- if ($parameter =~ /^#/) {
- print "<span class=\"param\">" . $parameter ."</span>\n";
- print "</li>\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"type\">)</span> ";
- print "(<span class=\"args\">$2</span>);";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"bits\">$2</span>;";
- } else {
- print "<span class=\"type\">$type</span> ";
- print "<span class=\"param\">$parameter</span>;";
- }
- print "</li>\n";
- }
- print "<li>};</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Members</h1>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output function in html5
-sub output_function_html5(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $html5id;
-
- $html5id = $args{'function'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
- print "<hgroup>\n";
- print "<h1>" . $args{'function'} . "</h1>";
- print "<h2>" . $args{'purpose'} . "</h2>\n";
- print "</hgroup>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
- print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
- print "</li>";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"type\">)</span> ";
- print "(<span class=\"args\">$2</span>)";
- } else {
- print "<span class=\"type\">$type</span> ";
- print "<span class=\"param\">$parameter</span>";
- }
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "</li>\n";
- }
- print "<li>)</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Arguments</h1>\n";
- print "<p>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output DOC: block header in html5
-sub output_blockhead_html5(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $html5id;
-
- foreach $section (@{$args{'sectionlist'}}) {
- $html5id = $section;
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
- print "<h1>$section</h1>\n";
- print "<p>\n";
- output_highlight($args{'sections'}{$section});
- print "</p>\n";
- }
- print "</article>\n";
-}
-
-sub output_section_xml(%) {
- my %args = %{$_[0]};
- my $section;
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- print "<refsect1>\n";
- print "<title>$section</title>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "<informalexample><programlisting>\n";
- $output_preformatted = 1;
- } else {
- print "<para>\n";
- }
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- if ($section =~ m/EXAMPLE/i) {
- print "</programlisting></informalexample>\n";
- } else {
- print "</para>\n";
- }
- print "</refsect1>\n";
- }
-}
-
-# output function in XML DocBook
-sub output_function_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = "API-" . $args{'function'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>U-BOOT</title>\n";
- print " <productname>Bootloader Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>" . $args{'function'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <funcsynopsis><funcprototype>\n";
- print " <funcdef>" . $args{'functiontype'} . " ";
- print "<function>" . $args{'function'} . " </function></funcdef>\n";
-
- $count = 0;
- if ($#{$args{'parameterlist'}} >= 0) {
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <paramdef>$1<parameter>$parameter</parameter>)\n";
- print " <funcparams>$2</funcparams></paramdef>\n";
- } else {
- print " <paramdef>" . $type;
- print " <parameter>$parameter</parameter></paramdef>\n";
- }
- }
- } else {
- print " <void/>\n";
- }
- print " </funcprototype></funcsynopsis>\n";
- print "</refsynopsisdiv>\n";
-
- # print parameters
- print "<refsect1>\n <title>Arguments</title>\n";
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
- print " <listitem>\n <para>\n";
- $lineprefix=" ";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para>\n </listitem>\n </varlistentry>\n";
- }
- print " </variablelist>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
- print "</refsect1>\n";
-
- output_section_xml(@_);
- print "</refentry>\n\n";
-}
-
-# output struct in XML DocBook
-sub output_struct_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $id;
-
- $id = "API-struct-" . $args{'struct'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>U-BOOT</title>\n";
- print " <productname>Bootloader Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <programlisting>\n";
- print $args{'type'} . " " . $args{'struct'} . " {\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- my $prm = $parameter;
- # convert data read & converted thru xml_escape() into &xyz; format:
- # This allows us to have #define macros interspersed in a struct.
- $prm =~ s/\\\\\\/\&/g;
- print "$prm\n";
- next;
- }
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- defined($args{'parameterdescs'}{$parameter_name}) || next;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " $1 $parameter) ($2);\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print " $1 $parameter$2;\n";
- } else {
- print " " . $type . " " . $parameter . ";\n";
- }
- }
- print "};";
- print " </programlisting>\n";
- print "</refsynopsisdiv>\n";
-
- print " <refsect1>\n";
- print " <title>Members</title>\n";
-
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- defined($args{'parameterdescs'}{$parameter_name}) || next;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print " <varlistentry>";
- print " <term>$parameter</term>\n";
- print " <listitem><para>\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para></listitem>\n";
- print " </varlistentry>\n";
- }
- print " </variablelist>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
- print " </refsect1>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output enum in XML DocBook
-sub output_enum_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = "API-enum-" . $args{'enum'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>U-BOOT</title>\n";
- print " <productname>Bootloader Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>enum " . $args{'enum'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <programlisting>\n";
- print "enum " . $args{'enum'} . " {\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print " $parameter";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "\n";
- }
- print "};";
- print " </programlisting>\n";
- print "</refsynopsisdiv>\n";
-
- print "<refsect1>\n";
- print " <title>Constants</title>\n";
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print " <varlistentry>";
- print " <term>$parameter</term>\n";
- print " <listitem><para>\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para></listitem>\n";
- print " </varlistentry>\n";
- }
- print " </variablelist>\n";
- print "</refsect1>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output typedef in XML DocBook
-sub output_typedef_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $id;
-
- $id = "API-typedef-" . $args{'typedef'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>U-BOOT</title>\n";
- print " <productname>Bootloader Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
- print "</refsynopsisdiv>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output in XML DocBook
-sub output_blockhead_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- my $id = $args{'module'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- if (!$args{'content-only'}) {
- print "<refsect1>\n <title>$section</title>\n";
- }
- if ($section =~ m/EXAMPLE/i) {
- print "<example><para>\n";
- $output_preformatted = 1;
- } else {
- print "<para>\n";
- }
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- if ($section =~ m/EXAMPLE/i) {
- print "</para></example>\n";
- } else {
- print "</para>";
- }
- if (!$args{'content-only'}) {
- print "\n</refsect1>\n";
- }
- }
-
- print "\n\n";
-}
-
-# output in XML DocBook
-sub output_function_gnome {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = $args{'module'} . "-" . $args{'function'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<sect2>\n";
- print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
-
- print " <funcsynopsis>\n";
- print " <funcdef>" . $args{'functiontype'} . " ";
- print "<function>" . $args{'function'} . " ";
- print "</function></funcdef>\n";
-
- $count = 0;
- if ($#{$args{'parameterlist'}} >= 0) {
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
- print " <funcparams>$2</funcparams></paramdef>\n";
- } else {
- print " <paramdef>" . $type;
- print " <parameter>$parameter</parameter></paramdef>\n";
- }
- }
- } else {
- print " <void>\n";
- }
- print " </funcsynopsis>\n";
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
- print "<tgroup cols=\"2\">\n";
- print "<colspec colwidth=\"2*\">\n";
- print "<colspec colwidth=\"8*\">\n";
- print "<tbody>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
- print " <entry>\n";
- $lineprefix=" ";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </entry></row>\n";
- }
- print " </tbody></tgroup></informaltable>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
-
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- print "<simplesect>\n <title>$section</title>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "<example><programlisting>\n";
- $output_preformatted = 1;
- } else {
- }
- print "<para>\n";
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- print "</para>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "</programlisting></example>\n";
- } else {
- }
- print " </simplesect>\n";
- }
-
- print "</sect2>\n\n";
-}
-
##
# output function in man
sub output_function_man(%) {
@@ -1328,7 +576,7 @@ sub output_function_man(%) {
my ($parameter, $section);
my $count;
- print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Bootloader Hacker's Manual\" U-BOOT\n";
+ print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
print ".SH NAME\n";
print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
@@ -1379,7 +627,7 @@ sub output_enum_man(%) {
my ($parameter, $section);
my $count;
- print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
+ print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
print ".SH NAME\n";
print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
@@ -1419,37 +667,17 @@ sub output_struct_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
- print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" U-BOOT\n";
+ print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
print ".SH NAME\n";
print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
+ my $declaration = $args{'definition'};
+ $declaration =~ s/\t/ /g;
+ $declaration =~ s/\n/"\n.br\n.BI \"/g;
print ".SH SYNOPSIS\n";
print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
-
- foreach my $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print ".BI \"$parameter\"\n.br\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print ".BI \" " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print ".BI \" " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
- } else {
- $type =~ s/([^\*])$/$1 /;
- print ".BI \" " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
- }
- print "\n.br\n";
- }
- print "};\n.br\n";
+ print ".BI \"$declaration\n};\n.br\n\n";
print ".SH Members\n";
foreach $parameter (@{$args{'parameterlist'}}) {
@@ -1474,7 +702,7 @@ sub output_typedef_man(%) {
my %args = %{$_[0]};
my ($parameter, $section);
- print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
+ print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
print ".SH NAME\n";
print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
@@ -1490,7 +718,7 @@ sub output_blockhead_man(%) {
my ($parameter, $section);
my $count;
- print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
+ print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
foreach $section (@{$args{'sectionlist'}}) {
print ".SH \"$section\"\n";
@@ -1499,135 +727,256 @@ sub output_blockhead_man(%) {
}
##
-# output in text
-sub output_function_text(%) {
+# output in restructured text
+#
+
+#
+# This could use some work; it's used to output the DOC: sections, and
+# starts by putting out the name of the doc section itself, but that tends
+# to duplicate a header already in the template file.
+#
+sub output_blockhead_rst(%) {
my %args = %{$_[0]};
my ($parameter, $section);
- my $start;
- print "Name:\n\n";
- print $args{'function'} . " - " . $args{'purpose'} . "\n";
+ foreach $section (@{$args{'sectionlist'}}) {
+ if ($output_selection != OUTPUT_INCLUDE) {
+ print "**$section**\n\n";
+ }
+ print_lineno($section_start_lines{$section});
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
+ }
+}
+
+#
+# Apply the RST highlights to a sub-block of text.
+#
+sub highlight_block($) {
+ # The dohighlight kludge requires the text be called $contents
+ my $contents = shift;
+ eval $dohighlight;
+ die $@ if $@;
+ return $contents;
+}
+
+#
+# Regexes used only here.
+#
+my $sphinx_literal = '^[^.].*::$';
+my $sphinx_cblock = '^\.\.\ +code-block::';
+
+sub output_highlight_rst {
+ my $input = join "\n", at _;
+ my $output = "";
+ my $line;
+ my $in_literal = 0;
+ my $litprefix;
+ my $block = "";
+
+ foreach $line (split "\n",$input) {
+ #
+ # If we're in a literal block, see if we should drop out
+ # of it. Otherwise pass the line straight through unmunged.
+ #
+ if ($in_literal) {
+ if (! ($line =~ /^\s*$/)) {
+ #
+ # If this is the first non-blank line in a literal
+ # block we need to figure out what the proper indent is.
+ #
+ if ($litprefix eq "") {
+ $line =~ /^(\s*)/;
+ $litprefix = '^' . $1;
+ $output .= $line . "\n";
+ } elsif (! ($line =~ /$litprefix/)) {
+ $in_literal = 0;
+ } else {
+ $output .= $line . "\n";
+ }
+ } else {
+ $output .= $line . "\n";
+ }
+ }
+ #
+ # Not in a literal block (or just dropped out)
+ #
+ if (! $in_literal) {
+ $block .= $line . "\n";
+ if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) {
+ $in_literal = 1;
+ $litprefix = "";
+ $output .= highlight_block($block);
+ $block = ""
+ }
+ }
+ }
+
+ if ($block) {
+ $output .= highlight_block($block);
+ }
+ foreach $line (split "\n", $output) {
+ print $lineprefix . $line . "\n";
+ }
+}
- print "\nSynopsis:\n\n";
+sub output_function_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $oldprefix = $lineprefix;
+ my $start = "";
+
+ if ($args{'typedef'}) {
+ print ".. c:type:: ". $args{'function'} . "\n\n";
+ print_lineno($declaration_start_line);
+ print " **Typedef**: ";
+ $lineprefix = "";
+ output_highlight_rst($args{'purpose'});
+ $start = "\n\n**Syntax**\n\n ``";
+ } else {
+ print ".. c:function:: ";
+ }
if ($args{'functiontype'} ne "") {
- $start = $args{'functiontype'} . " " . $args{'function'} . " (";
+ $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
} else {
- $start = $args{'function'} . " (";
+ $start .= $args{'function'} . " (";
}
print $start;
my $count = 0;
foreach my $parameter (@{$args{'parameterlist'}}) {
+ if ($count ne 0) {
+ print ", ";
+ }
+ $count++;
$type = $args{'parametertypes'}{$parameter};
+
if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
# pointer-to-function
print $1 . $parameter . ") (" . $2;
} else {
print $type . " " . $parameter;
}
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- print " " x length($start);
- } else {
- print ");\n\n";
- }
+ }
+ if ($args{'typedef'}) {
+ print ");``\n\n";
+ } else {
+ print ")\n\n";
+ print_lineno($declaration_start_line);
+ $lineprefix = " ";
+ output_highlight_rst($args{'purpose'});
+ print "\n";
}
- print "Arguments:\n\n";
+ print "**Parameters**\n\n";
+ $lineprefix = " ";
foreach $parameter (@{$args{'parameterlist'}}) {
my $parameter_name = $parameter;
$parameter_name =~ s/\[.*//;
+ $type = $args{'parametertypes'}{$parameter};
+
+ if ($type ne "") {
+ print "``$type $parameter``\n";
+ } else {
+ print "``$parameter``\n";
+ }
+
+ print_lineno($parameterdesc_start_lines{$parameter_name});
- print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
+ if (defined($args{'parameterdescs'}{$parameter_name}) &&
+ $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ } else {
+ print " *undescribed*\n";
+ }
+ print "\n";
}
- output_section_text(@_);
+
+ $lineprefix = $oldprefix;
+ output_section_rst(@_);
}
-#output sections in text
-sub output_section_text(%) {
+sub output_section_rst(%) {
my %args = %{$_[0]};
my $section;
+ my $oldprefix = $lineprefix;
+ $lineprefix = "";
- print "\n";
foreach $section (@{$args{'sectionlist'}}) {
- print "$section:\n\n";
- output_highlight($args{'sections'}{$section});
+ print "**$section**\n\n";
+ print_lineno($section_start_lines{$section});
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
}
- print "\n\n";
+ print "\n";
+ $lineprefix = $oldprefix;
}
-# output enum in text
-sub output_enum_text(%) {
+sub output_enum_rst(%) {
my %args = %{$_[0]};
my ($parameter);
+ my $oldprefix = $lineprefix;
my $count;
- print "Enum:\n\n";
+ my $name = "enum " . $args{'enum'};
- print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
- print "enum " . $args{'enum'} . " {\n";
- $count = 0;
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print_lineno($declaration_start_line);
+ $lineprefix = " ";
+ output_highlight_rst($args{'purpose'});
+ print "\n";
+
+ print "**Constants**\n\n";
+ $lineprefix = " ";
foreach $parameter (@{$args{'parameterlist'}}) {
- print "\t$parameter";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
+ print "``$parameter``\n";
+ if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
+ output_highlight_rst($args{'parameterdescs'}{$parameter});
+ } else {
+ print " *undescribed*\n";
}
print "\n";
}
- print "};\n\n";
-
- print "Constants:\n\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "$parameter\n\t";
- print $args{'parameterdescs'}{$parameter} . "\n";
- }
- output_section_text(@_);
+ $lineprefix = $oldprefix;
+ output_section_rst(@_);
}
-# output typedef in text
-sub output_typedef_text(%) {
+sub output_typedef_rst(%) {
my %args = %{$_[0]};
my ($parameter);
- my $count;
- print "Typedef:\n\n";
+ my $oldprefix = $lineprefix;
+ my $name = "typedef " . $args{'typedef'};
+
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print_lineno($declaration_start_line);
+ $lineprefix = " ";
+ output_highlight_rst($args{'purpose'});
+ print "\n";
- print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
- output_section_text(@_);
+ $lineprefix = $oldprefix;
+ output_section_rst(@_);
}
-# output struct as text
-sub output_struct_text(%) {
+sub output_struct_rst(%) {
my %args = %{$_[0]};
my ($parameter);
+ my $oldprefix = $lineprefix;
+ my $name = $args{'type'} . " " . $args{'struct'};
- print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
- print $args{'type'} . " " . $args{'struct'} . " {\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print "$parameter\n";
- next;
- }
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print_lineno($declaration_start_line);
+ $lineprefix = " ";
+ output_highlight_rst($args{'purpose'});
+ print "\n";
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "\t$1 $parameter) ($2);\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print "\t$1 $parameter$2;\n";
- } else {
- print "\t" . $type . " " . $parameter . ";\n";
- }
- }
- print "};\n\n";
+ print "**Definition**\n\n";
+ print "::\n\n";
+ my $declaration = $args{'definition'};
+ $declaration =~ s/\t/ /g;
+ print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n";
- print "Members:\n\n";
+ print "**Members**\n\n";
+ $lineprefix = " ";
foreach $parameter (@{$args{'parameterlist'}}) {
($parameter =~ /^#/) && next;
@@ -1635,58 +984,33 @@ sub output_struct_text(%) {
$parameter_name =~ s/\[.*//;
($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "$parameter\n\t";
- print $args{'parameterdescs'}{$parameter_name} . "\n";
+ $type = $args{'parametertypes'}{$parameter};
+ print_lineno($parameterdesc_start_lines{$parameter_name});
+ print "``" . $parameter . "``\n";
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ print "\n";
}
print "\n";
- output_section_text(@_);
-}
-sub output_blockhead_text(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
-
- foreach $section (@{$args{'sectionlist'}}) {
- print " $section:\n";
- print " -> ";
- output_highlight($args{'sections'}{$section});
- }
+ $lineprefix = $oldprefix;
+ output_section_rst(@_);
}
-## list mode output functions
-
-sub output_function_list(%) {
- my %args = %{$_[0]};
+## none mode output functions
- print $args{'function'} . "\n";
+sub output_function_none(%) {
}
-# output enum in list
-sub output_enum_list(%) {
- my %args = %{$_[0]};
- print $args{'enum'} . "\n";
+sub output_enum_none(%) {
}
-# output typedef in list
-sub output_typedef_list(%) {
- my %args = %{$_[0]};
- print $args{'typedef'} . "\n";
+sub output_typedef_none(%) {
}
-# output struct as list
-sub output_struct_list(%) {
- my %args = %{$_[0]};
-
- print $args{'struct'} . "\n";
+sub output_struct_none(%) {
}
-sub output_blockhead_list(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "DOC: $section\n";
- }
+sub output_blockhead_none(%) {
}
##
@@ -1698,9 +1022,13 @@ sub output_declaration {
my $name = shift;
my $functype = shift;
my $func = "output_${functype}_$output_mode";
- if (($function_only==0) ||
- ( $function_only == 1 && defined($function_table{$name})) ||
- ( $function_only == 2 && !defined($function_table{$name})))
+ if (($output_selection == OUTPUT_ALL) ||
+ (($output_selection == OUTPUT_INCLUDE ||
+ $output_selection == OUTPUT_EXPORTED) &&
+ defined($function_table{$name})) ||
+ (($output_selection == OUTPUT_EXCLUDE ||
+ $output_selection == OUTPUT_INTERNAL) &&
+ !($functype eq "function" && defined($function_table{$name}))))
{
&$func(@_);
$section_counter++;
@@ -1733,35 +1061,128 @@ sub dump_union($$) {
sub dump_struct($$) {
my $x = shift;
my $file = shift;
- my $nested;
if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
- #my $decl_type = $1;
+ my $decl_type = $1;
$declaration_name = $2;
my $members = $3;
- # ignore embedded structs or unions
- $members =~ s/({.*})//g;
- $nested = $1;
-
# ignore members marked private:
- $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos;
- $members =~ s/\/\*\s*private:.*//gos;
+ $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
+ $members =~ s/\/\*\s*private:.*//gosi;
# strip comments:
$members =~ s/\/\*.*?\*\///gos;
- $nested =~ s/\/\*.*?\*\///gos;
- # strip kmemcheck_bitfield_{begin,end}.*;
- $members =~ s/kmemcheck_bitfield_.*?;//gos;
# strip attributes
- $members =~ s/__aligned\s*\(.+\)//gos;
-
- create_parameterlist($members, ';', $file);
- check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
-
+ $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
+ $members =~ s/__aligned\s*\([^;]*\)//gos;
+ $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
+ # replace DECLARE_BITMAP
+ $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
+ # replace DECLARE_HASHTABLE
+ $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
+ # replace DECLARE_KFIFO
+ $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+ # replace DECLARE_KFIFO_PTR
+ $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+
+ my $declaration = $members;
+
+ # Split nested struct/union elements as newer ones
+ while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) {
+ my $newmember;
+ my $maintype = $1;
+ my $ids = $4;
+ my $content = $3;
+ foreach my $id(split /,/, $ids) {
+ $newmember .= "$maintype $id; ";
+
+ $id =~ s/[:\[].*//;
+ $id =~ s/^\s*\**(\S+)\s*/$1/;
+ foreach my $arg (split /;/, $content) {
+ next if ($arg =~ m/^\s*$/);
+ if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
+ # pointer-to-function
+ my $type = $1;
+ my $name = $2;
+ my $extra = $3;
+ next if (!$name);
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type$name$extra; ";
+ } else {
+ $newmember .= "$type$id.$name$extra; ";
+ }
+ } else {
+ my $type;
+ my $names;
+ $arg =~ s/^\s+//;
+ $arg =~ s/\s+$//;
+ # Handle bitmaps
+ $arg =~ s/:\s*\d+\s*//g;
+ # Handle arrays
+ $arg =~ s/\[.*\]//g;
+ # The type may have multiple words,
+ # and multiple IDs can be defined, like:
+ # const struct foo, *bar, foobar
+ # So, we remove spaces when parsing the
+ # names, in order to match just names
+ # and commas for the names
+ $arg =~ s/\s*,\s*/,/g;
+ if ($arg =~ m/(.*)\s+([\S+,]+)/) {
+ $type = $1;
+ $names = $2;
+ } else {
+ $newmember .= "$arg; ";
+ next;
+ }
+ foreach my $name (split /,/, $names) {
+ $name =~ s/^\s*\**(\S+)\s*/$1/;
+ next if (($name =~ m/^\s*$/));
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type $name; ";
+ } else {
+ $newmember .= "$type $id.$name; ";
+ }
+ }
+ }
+ }
+ }
+ $members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)}([^\{\}\;]*)\;/$newmember/;
+ }
+
+ # Ignore other nested elements, like enums
+ $members =~ s/({[^\{\}]*})//g;
+
+ create_parameterlist($members, ';', $file, $declaration_name);
+ check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
+
+ # Adjust declaration for better display
+ $declaration =~ s/([{;])/$1\n/g;
+ $declaration =~ s/}\s+;/};/g;
+ # Better handle inlined enums
+ do {} while ($declaration =~ s/(enum\s+{[^}]+),([^\n])/$1,\n$2/);
+
+ my @def_args = split /\n/, $declaration;
+ my $level = 1;
+ $declaration = "";
+ foreach my $clause (@def_args) {
+ $clause =~ s/^\s+//;
+ $clause =~ s/\s+$//;
+ $clause =~ s/\s+/ /;
+ next if (!$clause);
+ $level-- if ($clause =~ m/(})/ && $level > 1);
+ if (!($clause =~ m/^\s*#/)) {
+ $declaration .= "\t" x $level;
+ }
+ $declaration .= "\t" . $clause . "\n";
+ $level++ if ($clause =~ m/({)/ && !($clause =~m/}/));
+ }
output_declaration($declaration_name,
'struct',
{'struct' => $declaration_name,
'module' => $modulename,
+ 'definition' => $declaration,
'parameterlist' => \@parameterlist,
'parameterdescs' => \%parameterdescs,
'parametertypes' => \%parametertypes,
@@ -1772,33 +1193,84 @@ sub dump_struct($$) {
});
}
else {
- print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
+ print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
++$errors;
}
}
+
+sub show_warnings($$) {
+ my $functype = shift;
+ my $name = shift;
+
+ return 1 if ($output_selection == OUTPUT_ALL);
+
+ if ($output_selection == OUTPUT_EXPORTED) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INTERNAL) {
+ if (!($functype eq "function" && defined($function_table{$name}))) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INCLUDE) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ 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()");
+}
+
sub dump_enum($$) {
my $x = shift;
my $file = shift;
$x =~ s@/\*.*?\*/@@gos; # strip comments.
- $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums
+ # strip #define macros inside enums
+ $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
$declaration_name = $1;
my $members = $2;
+ my %_members;
+
+ $members =~ s/\s+$//;
foreach my $arg (split ',', $members) {
$arg =~ s/^\s*(\w+).*/$1/;
push @parameterlist, $arg;
if (!$parameterdescs{$arg}) {
$parameterdescs{$arg} = $undescribed;
- print STDERR "Warning(${file}:$.): Enum value '$arg' ".
- "not described in enum '$declaration_name'\n";
+ if (show_warnings("enum", $declaration_name)) {
+ print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n";
+ }
}
-
+ $_members{$arg} = 1;
}
+ while (my ($k, $v) = each %parameterdescs) {
+ if (!exists($_members{$k})) {
+ if (show_warnings("enum", $declaration_name)) {
+ print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n";
+ }
+ }
+ }
+
output_declaration($declaration_name,
'enum',
{'enum' => $declaration_name,
@@ -1811,7 +1283,7 @@ sub dump_enum($$) {
});
}
else {
- print STDERR "Error(${file}:$.): Cannot parse enum!\n";
+ print STDERR "${file}:$.: error: Cannot parse enum!\n";
++$errors;
}
}
@@ -1821,6 +1293,34 @@ sub dump_typedef($$) {
my $file = shift;
$x =~ s@/\*.*?\*/@@gos; # strip comments.
+
+ # Parse function prototypes
+ if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
+ $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
+
+ # Function typedefs
+ $return_type = $1;
+ $declaration_name = $2;
+ my $args = $3;
+
+ create_parameterlist($args, ',', $file, $declaration_name);
+
+ output_declaration($declaration_name,
+ 'function',
+ {'function' => $declaration_name,
+ 'typedef' => 1,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+ return;
+ }
+
while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
$x =~ s/\(*.\)\s*;$/;/;
$x =~ s/\[*.\]\s*;$/;/;
@@ -1839,7 +1339,7 @@ sub dump_typedef($$) {
});
}
else {
- print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
+ print STDERR "${file}:$.: error: Cannot parse typedef!\n";
++$errors;
}
}
@@ -1852,10 +1352,11 @@ sub save_struct_actual($) {
$struct_actual = $struct_actual . $actual . " ";
}
-sub create_parameterlist($$$) {
+sub create_parameterlist($$$$) {
my $args = shift;
my $splitter = shift;
my $file = shift;
+ my $declaration_name = shift;
my $type;
my $param;
@@ -1880,12 +1381,12 @@ sub create_parameterlist($$$) {
} elsif ($arg =~ m/\(.+\)\s*\(/) {
# pointer-to-function
$arg =~ tr/#/,/;
- $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
+ $arg =~ m/[^\(]+\(\*?\s*([\w\.]*)\s*\)/;
$param = $1;
$type = $arg;
$type =~ s/([^\(]+\(\*?)\s*$param/$1/;
save_struct_actual($param);
- push_parameter($param, $type, $file);
+ push_parameter($param, $type, $file, $declaration_name);
} elsif ($arg) {
$arg =~ s/\s*:\s*/:/g;
$arg =~ s/\s*\[/\[/g;
@@ -1910,27 +1411,28 @@ sub create_parameterlist($$$) {
foreach $param (@args) {
if ($param =~ m/^(\*+)\s*(.*)/) {
save_struct_actual($2);
- push_parameter($2, "$type $1", $file);
+ push_parameter($2, "$type $1", $file, $declaration_name);
}
elsif ($param =~ m/(.*?):(\d+)/) {
if ($type ne "") { # skip unnamed bit-fields
save_struct_actual($1);
- push_parameter($1, "$type:$2", $file)
+ push_parameter($1, "$type:$2", $file, $declaration_name)
}
}
else {
save_struct_actual($param);
- push_parameter($param, $type, $file);
+ push_parameter($param, $type, $file, $declaration_name);
}
}
}
}
}
-sub push_parameter($$$) {
+sub push_parameter($$$$) {
my $param = shift;
my $type = shift;
my $file = shift;
+ my $declaration_name = shift;
if (($anon_struct_union == 1) && ($type eq "") &&
($param eq "}")) {
@@ -1938,11 +1440,14 @@ sub push_parameter($$$) {
}
$anon_struct_union = 0;
- my $param_name = $param;
- $param_name =~ s/\[.*//;
+ $param =~ s/[\[\)].*//;
if ($type eq "" && $param =~ /\.\.\.$/)
{
+ if (!$param =~ /\w\.\.\.$/) {
+ # handles unnamed variable parameters
+ $param = "...";
+ }
if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
$parameterdescs{$param} = "variable arguments";
}
@@ -1964,25 +1469,17 @@ sub push_parameter($$$) {
# warn if parameter has no description
# (but ignore ones starting with # as these are not parameters
# but inline preprocessor statements);
- # also ignore unnamed structs/unions;
- if (!$anon_struct_union) {
- if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
-
- $parameterdescs{$param_name} = $undescribed;
+ # Note: It will also ignore void params and unnamed structs/unions
+ if (!defined $parameterdescs{$param} && $param !~ /^#/) {
+ $parameterdescs{$param} = $undescribed;
- if (($type eq 'function') || ($type eq 'enum')) {
- print STDERR "Warning(${file}:$.): Function parameter ".
- "or member '$param' not " .
- "described in '$declaration_name'\n";
- }
- print STDERR "Warning(${file}:$.):" .
- " No description found for parameter '$param'\n";
- ++$warnings;
- }
+ if (show_warnings($type, $declaration_name)) {
+ print STDERR
+ "${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n";
+ ++$warnings;
+ }
}
- $param = xml_escape($param);
-
# strip spaces from $param so that it is one continuous string
# on @parameterlist;
# this fixes a problem where check_sections() cannot find
@@ -1993,11 +1490,12 @@ sub push_parameter($$$) {
# "[blah" in a parameter string;
###$param =~ s/\s*//g;
push @parameterlist, $param;
+ $type =~ s/\s\s+/ /g;
$parametertypes{$param} = $type;
}
-sub check_sections($$$$$$) {
- my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
+sub check_sections($$$$$) {
+ my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
my @sects = split ' ', $sectcheck;
my @prms = split ' ', $prmscheck;
my $err;
@@ -2026,19 +1524,11 @@ sub check_sections($$$$$$) {
}
if ($err) {
if ($decl_type eq "function") {
- print STDERR "Warning(${file}:$.): " .
+ print STDERR "${file}:$.: warning: " .
"Excess function parameter " .
"'$sects[$sx]' " .
"description in '$decl_name'\n";
++$warnings;
- } else {
- if ($nested !~ m/\Q$sects[$sx]\E/) {
- print STDERR "Warning(${file}:$.): " .
- "Excess struct/union/enum/typedef member " .
- "'$sects[$sx]' " .
- "description in '$decl_name'\n";
- ++$warnings;
- }
}
}
}
@@ -2059,7 +1549,7 @@ sub check_return_section {
if (!defined($sections{$section_return}) ||
$sections{$section_return} eq "") {
- print STDERR "Warning(${file}:$.): " .
+ print STDERR "${file}:$.: warning: " .
"No description found for return value of " .
"'$declaration_name'\n";
++$warnings;
@@ -2088,8 +1578,15 @@ sub dump_function($$) {
$prototype =~ s/__meminit +//;
$prototype =~ s/__must_check +//;
$prototype =~ s/__weak +//;
+ $prototype =~ s/__sched +//;
my $define = $prototype =~ s/^#\s*define\s+//; #ak added
- $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
+ $prototype =~ s/__attribute__\s*\(\(
+ (?:
+ [\w\s]++ # attribute name
+ (?:\([^)]*+\))? # attribute arguments
+ \s*+,? # optional comma at the end
+ )+
+ \)\)\s+//x;
# Yes, this truly is vile. We are looking for:
# 1. Return type (may be nothing if we're looking at a macro)
@@ -2117,33 +1614,33 @@ sub dump_function($$) {
$noret = 1;
} elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
- $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
- $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
- $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
- $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
- $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
- $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
- $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
$return_type = $1;
$declaration_name = $2;
my $args = $3;
- create_parameterlist($args, ',', $file);
+ create_parameterlist($args, ',', $file, $declaration_name);
} else {
- print STDERR "Warning(${file}:$.): cannot understand function prototype: '$prototype'\n";
+ print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n";
return;
}
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
# functions don't have a 'Return' doc section. So until the number
@@ -2170,7 +1667,6 @@ sub dump_function($$) {
sub reset_state {
$function = "";
- %constants = ();
%parameterdescs = ();
%parametertypes = ();
@parameterlist = ();
@@ -2180,7 +1676,8 @@ sub reset_state {
$struct_actual = "";
$prototype = "";
- $state = 0;
+ $state = STATE_NORMAL;
+ $inline_doc_state = STATE_INLINE_NA;
}
sub tracepoint_munge($) {
@@ -2202,7 +1699,7 @@ sub tracepoint_munge($) {
$tracepointargs = $1;
}
if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
- print STDERR "Warning(${file}:$.): Unrecognized tracepoint format: \n".
+ print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n".
"$prototype\n";
} else {
$prototype = "static inline void trace_$tracepointname($tracepointargs)";
@@ -2212,7 +1709,7 @@ sub tracepoint_munge($) {
sub syscall_munge() {
my $void = 0;
- $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
if ($prototype =~ m/SYSCALL_DEFINE0/) {
$void = 1;
@@ -2243,7 +1740,7 @@ sub syscall_munge() {
}
}
-sub process_state3_function($$) {
+sub process_proto_function($$) {
my $x = shift;
my $file = shift;
@@ -2273,7 +1770,7 @@ sub process_state3_function($$) {
}
}
-sub process_state3_type($$) {
+sub process_proto_type($$) {
my $x = shift;
my $file = shift;
@@ -2289,6 +1786,9 @@ sub process_state3_type($$) {
while (1) {
if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
+ if( length $prototype ) {
+ $prototype .= " "
+ }
$prototype .= $1 . $2;
($2 eq '{') && $brcount++;
($2 eq '}') && $brcount--;
@@ -2305,279 +1805,369 @@ sub process_state3_type($$) {
}
}
-# xml_escape: replace <, >, and & in the text stream;
-#
-# however, formatting controls that are generated internally/locally in the
-# kernel-doc script are not escaped here; instead, they begin life like
-# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
-# are converted to their mnemonic-expected output, without the 4 * '\' & ':',
-# just before actual output; (this is done by local_unescape())
-sub xml_escape($) {
- my $text = shift;
- if (($output_mode eq "text") || ($output_mode eq "man")) {
- return $text;
- }
- $text =~ s/\&/\\\\\\amp;/g;
- $text =~ s/\</\\\\\\lt;/g;
- $text =~ s/\>/\\\\\\gt;/g;
- return $text;
-}
-
-# convert local escape strings to html
-# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes)
-sub local_unescape($) {
- my $text = shift;
- if (($output_mode eq "text") || ($output_mode eq "man")) {
- return $text;
- }
- $text =~ s/\\\\\\\\lt:/</g;
- $text =~ s/\\\\\\\\gt:/>/g;
- return $text;
-}
-sub process_file($) {
+sub map_filename($) {
my $file;
- my $identifier;
- my $func;
- my $descr;
- my $in_purpose = 0;
- my $initial_section_counter = $section_counter;
+ my ($orig_file) = @_;
if (defined($ENV{'SRCTREE'})) {
- $file = "$ENV{'SRCTREE'}" . "/" . "@_";
- }
- else {
- $file = "@_";
+ $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
+ } else {
+ $file = $orig_file;
}
+
if (defined($source_map{$file})) {
$file = $source_map{$file};
}
+ return $file;
+}
+
+sub process_export_file($) {
+ my ($orig_file) = @_;
+ my $file = map_filename($orig_file);
+
if (!open(IN,"<$file")) {
print STDERR "Error: Cannot open file $file\n";
++$errors;
return;
}
- $. = 1;
-
- $section_counter = 0;
while (<IN>) {
- while (s/\\\s*$//) {
- $_ .= <IN>;
+ if (/$export_symbol/) {
+ $function_table{$2} = 1;
}
- if ($state == 0) {
- if (/$doc_start/o) {
- $state = 1; # next line is always the function name
- $in_doc_sect = 0;
- }
- } elsif ($state == 1) { # this line is the function name (always)
- if (/$doc_block/o) {
- $state = 4;
- $contents = "";
- if ( $1 eq "" ) {
- $section = $section_intro;
- } else {
- $section = $1;
- }
- }
- elsif (/$doc_decl/o) {
- $identifier = $1;
- if (/\s*([\w\s]+?)\s*-/) {
- $identifier = $1;
- }
+ }
- $state = 2;
- if (/-(.*)/) {
- # strip leading/trailing/multiple spaces
- $descr= $1;
- $descr =~ s/^\s*//;
- $descr =~ s/\s*$//;
- $descr =~ s/\s+/ /g;
- $declaration_purpose = xml_escape($descr);
- $in_purpose = 1;
- } else {
- $declaration_purpose = "";
- }
+ close(IN);
+}
- if (($declaration_purpose eq "") && $verbose) {
- print STDERR "Warning(${file}:$.): missing initial short description on line:\n";
- print STDERR $_;
- ++$warnings;
- }
+#
+# Parsers for the various processing states.
+#
+# STATE_NORMAL: looking for the /** to begin everything.
+#
+sub process_normal() {
+ if (/$doc_start/o) {
+ $state = STATE_NAME; # next line is always the function name
+ $in_doc_sect = 0;
+ $declaration_start_line = $. + 1;
+ }
+}
- if ($identifier =~ m/^struct/) {
- $decl_type = 'struct';
- } elsif ($identifier =~ m/^union/) {
- $decl_type = 'union';
- } elsif ($identifier =~ m/^enum/) {
- $decl_type = 'enum';
- } elsif ($identifier =~ m/^typedef/) {
- $decl_type = 'typedef';
- } else {
- $decl_type = 'function';
- }
+#
+# STATE_NAME: Looking for the "name - description" line
+#
+sub process_name($$) {
+ my $file = shift;
+ my $identifier;
+ my $descr;
- if ($verbose) {
- print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
- }
- } else {
- print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
- " - I thought it was a doc line\n";
+ if (/$doc_block/o) {
+ $state = STATE_DOCBLOCK;
+ $contents = "";
+ $new_start_line = $. + 1;
+
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
+ }
+ elsif (/$doc_decl/o) {
+ $identifier = $1;
+ if (/\s*([\w\s]+?)(\(\))?\s*-/) {
+ $identifier = $1;
+ }
+
+ $state = STATE_BODY;
+ # if there's no @param blocks need to set up default section
+ # here
+ $contents = "";
+ $section = $section_default;
+ $new_start_line = $. + 1;
+ if (/-(.*)/) {
+ # strip leading/trailing/multiple spaces
+ $descr= $1;
+ $descr =~ s/^\s*//;
+ $descr =~ s/\s*$//;
+ $descr =~ s/\s+/ /g;
+ $declaration_purpose = $descr;
+ $state = STATE_BODY_MAYBE;
+ } else {
+ $declaration_purpose = "";
+ }
+
+ if (($declaration_purpose eq "") && $verbose) {
+ print STDERR "${file}:$.: warning: missing initial short description on line:\n";
+ print STDERR $_;
+ ++$warnings;
+ }
+
+ if ($identifier =~ m/^struct/) {
+ $decl_type = 'struct';
+ } elsif ($identifier =~ m/^union/) {
+ $decl_type = 'union';
+ } elsif ($identifier =~ m/^enum/) {
+ $decl_type = 'enum';
+ } elsif ($identifier =~ m/^typedef/) {
+ $decl_type = 'typedef';
+ } else {
+ $decl_type = 'function';
+ }
+
+ if ($verbose) {
+ print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
+ }
+ } else {
+ print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
+ " - I thought it was a doc line\n";
+ ++$warnings;
+ $state = STATE_NORMAL;
+ }
+}
+
+
+#
+# STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment.
+#
+sub process_body($$) {
+ my $file = shift;
+
+ if (/$doc_sect/i) { # case insensitive for supported section names
+ $newsection = $1;
+ $newcontents = $2;
+
+ # map the supported section names to the canonical names
+ if ($newsection =~ m/^description$/i) {
+ $newsection = $section_default;
+ } elsif ($newsection =~ m/^context$/i) {
+ $newsection = $section_context;
+ } elsif ($newsection =~ m/^returns?$/i) {
+ $newsection = $section_return;
+ } elsif ($newsection =~ m/^\@return$/) {
+ # special: @return is a section, not a param description
+ $newsection = $section_return;
+ }
+
+ if (($contents ne "") && ($contents ne "\n")) {
+ if (!$in_doc_sect && $verbose) {
+ print STDERR "${file}:$.: warning: contents before sections\n";
++$warnings;
- $state = 0;
}
- } elsif ($state == 2) { # look for head: lines, and include content
- if (/$doc_sect/o) {
- $newsection = $1;
- $newcontents = $2;
-
- if (($contents ne "") && ($contents ne "\n")) {
- if (!$in_doc_sect && $verbose) {
- print STDERR "Warning(${file}:$.): contents before sections\n";
- ++$warnings;
- }
- dump_section($file, $section, xml_escape($contents));
- $section = $section_default;
- }
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ }
+
+ $in_doc_sect = 1;
+ $state = STATE_BODY;
+ $contents = $newcontents;
+ $new_start_line = $.;
+ while (substr($contents, 0, 1) eq " ") {
+ $contents = substr($contents, 1);
+ }
+ if ($contents ne "") {
+ $contents .= "\n";
+ }
+ $section = $newsection;
+ $leading_space = undef;
+ } elsif (/$doc_end/) {
+ if (($contents ne "") && ($contents ne "\n")) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+ # look for doc_com + <text> + doc_end:
+ if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
+ print STDERR "${file}:$.: warning: suspicious ending line: $_";
+ ++$warnings;
+ }
- $in_doc_sect = 1;
- $in_purpose = 0;
- $contents = $newcontents;
- if ($contents ne "") {
- while ((substr($contents, 0, 1) eq " ") ||
- substr($contents, 0, 1) eq "\t") {
- $contents = substr($contents, 1);
+ $prototype = "";
+ $state = STATE_PROTO;
+ $brcount = 0;
+ } elsif (/$doc_content/) {
+ # miguel-style comment kludge, look for blank lines after
+ # @parameter line to signify start of description
+ if ($1 eq "") {
+ if ($section =~ m/^@/ || $section eq $section_context) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ $new_start_line = $.;
+ } else {
+ $contents .= "\n";
+ }
+ $state = STATE_BODY;
+ } elsif ($state == STATE_BODY_MAYBE) {
+ # Continued declaration purpose
+ chomp($declaration_purpose);
+ $declaration_purpose .= " " . $1;
+ $declaration_purpose =~ s/\s+/ /g;
+ } else {
+ my $cont = $1;
+ if ($section =~ m/^@/ || $section eq $section_context) {
+ if (!defined $leading_space) {
+ if ($cont =~ m/^(\s+)/) {
+ $leading_space = $1;
+ } else {
+ $leading_space = "";
}
- $contents .= "\n";
}
- $section = $newsection;
- } elsif (/$doc_end/) {
+ $cont =~ s/^$leading_space//;
+ }
+ $contents .= $cont . "\n";
+ }
+ } else {
+ # i dont know - bad line? ignore.
+ print STDERR "${file}:$.: warning: bad line: $_";
+ ++$warnings;
+ }
+}
- if (($contents ne "") && ($contents ne "\n")) {
- dump_section($file, $section, xml_escape($contents));
- $section = $section_default;
- $contents = "";
- }
- # look for doc_com + <text> + doc_end:
- if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
- print STDERR "Warning(${file}:$.): suspicious ending line: $_";
- ++$warnings;
- }
- $prototype = "";
- $state = 3;
- $brcount = 0;
-# print STDERR "end of doc comment, looking for prototype\n";
- } elsif (/$doc_content/) {
- # miguel-style comment kludge, look for blank lines after
- # @parameter line to signify start of description
- if ($1 eq "") {
- if ($section =~ m/^@/ || $section eq $section_context) {
- dump_section($file, $section, xml_escape($contents));
- $section = $section_default;
- $contents = "";
- } else {
- $contents .= "\n";
- }
- $in_purpose = 0;
- } elsif ($in_purpose == 1) {
- # Continued declaration purpose
- chomp($declaration_purpose);
- $declaration_purpose .= " " . xml_escape($1);
- $declaration_purpose =~ s/\s+/ /g;
- } else {
- $contents .= $1 . "\n";
- }
- } else {
- # i dont know - bad line? ignore.
- print STDERR "Warning(${file}:$.): bad line: $_";
- ++$warnings;
+#
+# STATE_PROTO: reading a function/whatever prototype.
+#
+sub process_proto($$) {
+ my $file = shift;
+
+ if (/$doc_inline_oneline/) {
+ $section = $1;
+ $contents = $2;
+ if ($contents ne "") {
+ $contents .= "\n";
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+ } elsif (/$doc_inline_start/) {
+ $state = STATE_INLINE;
+ $inline_doc_state = STATE_INLINE_NAME;
+ } elsif ($decl_type eq 'function') {
+ process_proto_function($_, $file);
+ } else {
+ process_proto_type($_, $file);
+ }
+}
+
+#
+# STATE_DOCBLOCK: within a DOC: block.
+#
+sub process_docblock($$) {
+ my $file = shift;
+
+ if (/$doc_end/) {
+ dump_doc_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ $function = "";
+ %parameterdescs = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ $state = STATE_NORMAL;
+ } elsif (/$doc_content/) {
+ if ( $1 eq "" ) {
+ $contents .= $blankline;
+ } else {
+ $contents .= $1 . "\n";
+ }
+ }
+}
+
+#
+# STATE_INLINE: docbook comments within a prototype.
+#
+sub process_inline($$) {
+ my $file = shift;
+
+ # First line (state 1) needs to be a @parameter
+ if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
+ $section = $1;
+ $contents = $2;
+ $new_start_line = $.;
+ if ($contents ne "") {
+ while (substr($contents, 0, 1) eq " ") {
+ $contents = substr($contents, 1);
}
- } elsif ($state == 3) { # scanning for function '{' (end of prototype)
- if ($decl_type eq 'function') {
- process_state3_function($_, $file);
- } else {
- process_state3_type($_, $file);
+ $contents .= "\n";
+ }
+ $inline_doc_state = STATE_INLINE_TEXT;
+ # Documentation block end */
+ } elsif (/$doc_inline_end/) {
+ if (($contents ne "") && ($contents ne "\n")) {
+ dump_section($file, $section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+ $state = STATE_PROTO;
+ $inline_doc_state = STATE_INLINE_NA;
+ # Regular text
+ } elsif (/$doc_content/) {
+ if ($inline_doc_state == STATE_INLINE_TEXT) {
+ $contents .= $1 . "\n";
+ # nuke leading blank lines
+ if ($contents =~ /^\s*$/) {
+ $contents = "";
}
- } elsif ($state == 4) {
- # Documentation block
- if (/$doc_block/) {
- dump_doc_section($file, $section, xml_escape($contents));
- $contents = "";
- $function = "";
- %constants = ();
- %parameterdescs = ();
- %parametertypes = ();
- @parameterlist = ();
- %sections = ();
- @sectionlist = ();
- $prototype = "";
- if ( $1 eq "" ) {
- $section = $section_intro;
- } else {
- $section = $1;
- }
- }
- elsif (/$doc_end/)
- {
- dump_doc_section($file, $section, xml_escape($contents));
- $contents = "";
- $function = "";
- %constants = ();
- %parameterdescs = ();
- %parametertypes = ();
- @parameterlist = ();
- %sections = ();
- @sectionlist = ();
- $prototype = "";
- $state = 0;
- }
- elsif (/$doc_content/)
- {
- if ( $1 eq "" )
- {
- $contents .= $blankline;
- }
- else
- {
- $contents .= $1 . "\n";
- }
- }
+ } elsif ($inline_doc_state == STATE_INLINE_NAME) {
+ $inline_doc_state = STATE_INLINE_ERROR;
+ print STDERR "${file}:$.: warning: ";
+ print STDERR "Incorrect use of kernel-doc format: $_";
+ ++$warnings;
}
}
+}
+
+
+sub process_file($) {
+ my $file;
+ my $initial_section_counter = $section_counter;
+ my ($orig_file) = @_;
+
+ $file = map_filename($orig_file);
+
+ if (!open(IN,"<$file")) {
+ print STDERR "Error: Cannot open file $file\n";
+ ++$errors;
+ return;
+ }
+
+ $. = 1;
+
+ $section_counter = 0;
+ while (<IN>) {
+ while (s/\\\s*$//) {
+ $_ .= <IN>;
+ }
+ # Replace tabs by spaces
+ while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
+ # Hand this line to the appropriate state handler
+ if ($state == STATE_NORMAL) {
+ process_normal();
+ } elsif ($state == STATE_NAME) {
+ process_name($file, $_);
+ } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) {
+ process_body($file, $_);
+ } elsif ($state == STATE_INLINE) { # scanning for inline parameters
+ process_inline($file, $_);
+ } elsif ($state == STATE_PROTO) {
+ process_proto($file, $_);
+ } elsif ($state == STATE_DOCBLOCK) {
+ process_docblock($file, $_);
+ }
+ }
+
+ # Make sure we got something interesting.
if ($initial_section_counter == $section_counter) {
- print STDERR "Warning(${file}): no structured comments found\n";
- if (($function_only == 1) && ($show_not_found == 1)) {
- print STDERR " Was looking for '$_'.\n" for keys %function_table;
+ if ($output_mode ne "none") {
+ print STDERR "${file}:1: warning: no structured comments found\n";
}
- if ($output_mode eq "xml") {
- # The template wants at least one RefEntry here; make one.
- print "<refentry>\n";
- print " <refnamediv>\n";
- print " <refname>\n";
- print " ${file}\n";
- print " </refname>\n";
- print " <refpurpose>\n";
- print " Document generation inconsistency\n";
- print " </refpurpose>\n";
- print " </refnamediv>\n";
- print " <refsect1>\n";
- print " <title>\n";
- print " Oops\n";
- print " </title>\n";
- print " <warning>\n";
- print " <para>\n";
- print " The template for this document tried to insert\n";
- print " the structured comment from the file\n";
- print " <filename>${file}</filename> at this point,\n";
- print " but none was found.\n";
- print " This dummy section is inserted to allow\n";
- print " generation to continue.\n";
- print " </para>\n";
- print " </warning>\n";
- print " </refsect1>\n";
- print "</refentry>\n";
+ if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
+ print STDERR " Was looking for '$_'.\n" for keys %function_table;
}
}
}
@@ -2587,9 +2177,11 @@ $kernelversion = get_kernel_version();
# generate a sequence of code that will splice in highlighting information
# using the s// operator.
-foreach my $pattern (keys %highlights) {
-# print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
- $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+for (my $k = 0; $k < @highlights; $k++) {
+ my $pattern = $highlights[$k][0];
+ my $result = $highlights[$k][1];
+# print STDERR "scanning pattern:$pattern, highlight:($result)\n";
+ $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n";
}
# Read the file that maps relative names to absolute names for
@@ -2605,6 +2197,17 @@ if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
close(SOURCE_MAP);
}
+if ($output_selection == OUTPUT_EXPORTED ||
+ $output_selection == OUTPUT_INTERNAL) {
+
+ push(@export_file_list, @ARGV);
+
+ foreach (@export_file_list) {
+ chomp;
+ process_export_file($_);
+ }
+}
+
foreach (@ARGV) {
chomp;
process_file($_);
@@ -2616,4 +2219,4 @@ if ($verbose && $warnings) {
print STDERR "$warnings warnings\n";
}
-exit($errors);
+exit($output_mode eq "none" ? 0 : $errors);
--
2.11.0
More information about the U-Boot
mailing list