Commit 30ff89189ba111268cfcde508ac4cc9f83eb9bcd

Authored by Marek Vasut
Committed by Tom Rini
1 parent c50204a517

kerneldoc: Implant DocBook from Linux kernel

Pull slightly modified version of Documentation/DocBook, the related perl
script scripts/kernel-doc and the scripts/docproc.c from Linux kernel and
implant it into U-Boot. This will allow smooth generation of kerneldoc
style documentation.

It was necessary to modify the DocBook/Makefile to work with U-Boot build
system. The changes were only minor though and involved replacing the kbuild
specific parts.

It was also necessary to replace use of variables like KERNEL_VERSION with
U_BOOT_VERSION, strings like Linux kernel with U-Boot Bootloader etc. so
the generated result actually matches.

Finally, it was necessary to adjust docproc.c, since the documentation in
U-Boot is located in doc/DocBook instead of Documentation/DocBook as is in
case of the Linux kernel.

Some parts of the DocBook Makefile are unused, but to allow easier sync with
Linux kernel, these parts are still left in. The targets enabled now are
"htmldocs" "pdfdocs" "psdocs" "xmldocs" and "cleandocs" to remove the results
of documentation build.

Linux scripts/docproc.c:
commit f0f3ca8d967462dafb815412b14ca3339b9817a6
Date:   Wed Jun 15 11:53:13 2011 +0200

Linux scripts/kernel-doc:
commit 1b40c1944db445c1de1c47ffd8cd426167f488e8
Date:   Sun Aug 12 10:46:15 2012 +0200

Linux Documentation/DocBook:
commit bb8187d35f820671d6dd76700d77a6b55f95e2c5
Date:   Thu May 17 19:06:13 2012 -0400

Signed-off-by: Marek Vasut <marex@denx.de>

Showing 9 changed files with 3430 additions and 2 deletions Side-by-side Diff

... ... @@ -715,6 +715,9 @@
715 715 $(MAKE) -C tools/$@ all MTD_VERSION=${MTD_VERSION}
716 716 gdbtools: gdb
717 717  
  718 +xmldocs pdfdocs psdocs htmldocs mandocs: tools/kernel-doc/docproc
  719 + $(MAKE) U_BOOT_VERSION=$(U_BOOT_VERSION) -C doc/DocBook/ $@
  720 +
718 721 tools-all: easylogo env gdb $(VERSION_FILE) $(TIMESTAMP_FILE)
719 722 $(MAKE) -C tools HOST_TOOLS_ALL=y
720 723  
... ... @@ -799,7 +802,8 @@
799 802 $(obj)tools/mk{env,}image $(obj)tools/mpc86x_clk \
800 803 $(obj)tools/mk{smdk5250,}spl \
801 804 $(obj)tools/mxsboot \
802   - $(obj)tools/ncb $(obj)tools/ubsha1
  805 + $(obj)tools/ncb $(obj)tools/ubsha1 \
  806 + $(obj)tools/kernel-doc/docproc
803 807 @rm -f $(obj)board/cray/L1/{bootscript.c,bootscript.image} \
804 808 $(obj)board/matrix_vision/*/bootscript.img \
805 809 $(obj)board/voiceblue/eeprom \
... ... @@ -812,6 +816,7 @@
812 816 @rm -f $(obj)include/generated/asm-offsets.h
813 817 @rm -f $(obj)$(CPUDIR)/$(SOC)/asm-offsets.s
814 818 @rm -f $(TIMESTAMP_FILE) $(VERSION_FILE)
  819 + @$(MAKE) -C doc/DocBook/ cleandocs
815 820 @find $(OBJTREE) -type f \
816 821 \( -name 'core' -o -name '*.bak' -o -name '*~' -o -name '*.su' \
817 822 -o -name '*.o' -o -name '*.a' -o -name '*.exe' \) -print \
doc/DocBook/.gitignore
  1 +*/
  2 +*.xml
  3 +*.ps
  4 +*.pdf
  5 +*.html
  6 +*.9.gz
  7 +*.9
  8 +*.aux
  9 +*.dvi
  10 +*.log
  11 +*.out
  12 +*.png
  13 +*.gif
  14 +media-indices.tmpl
  15 +media-entities.tmpl
doc/DocBook/Makefile
  1 +###
  2 +# This makefile is used to generate the kernel documentation,
  3 +# primarily based on in-line comments in various source files.
  4 +# See doc/kernel-doc-nano-HOWTO.txt for instruction in how
  5 +# to document the SRC - and how to read it.
  6 +# To add a new book the only step required is to add the book to the
  7 +# list of DOCBOOKS.
  8 +
  9 +include $(TOPDIR)/config.mk
  10 +
  11 +DOCBOOKS :=
  12 +
  13 +###
  14 +# The build process is as follows (targets):
  15 +# (xmldocs) [by docproc]
  16 +# file.tmpl --> file.xml +--> file.ps (psdocs) [by db2ps or xmlto]
  17 +# +--> file.pdf (pdfdocs) [by db2pdf or xmlto]
  18 +# +--> DIR=file (htmldocs) [by xmlto]
  19 +# +--> man/ (mandocs) [by xmlto]
  20 +
  21 +
  22 +# for PDF and PS output you can choose between xmlto and docbook-utils tools
  23 +PDF_METHOD = $(prefer-db2x)
  24 +PS_METHOD = $(prefer-db2x)
  25 +
  26 +
  27 +###
  28 +# The targets that may be used.
  29 +PHONY += $(obj).depend xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs
  30 +
  31 +BOOKS := $(addprefix $(OBJTREE)/doc/DocBook/,$(DOCBOOKS))
  32 +xmldocs: $(BOOKS)
  33 +sgmldocs: xmldocs
  34 +
  35 +PS := $(patsubst %.xml, %.ps, $(BOOKS))
  36 +psdocs: $(PS)
  37 +
  38 +PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
  39 +pdfdocs: $(PDF)
  40 +
  41 +HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
  42 +htmldocs: $(HTML)
  43 + $(call build_main_index)
  44 + $(call build_images)
  45 + $(call install_media_images)
  46 +
  47 +MAN := $(patsubst %.xml, %.9, $(BOOKS))
  48 +mandocs: $(MAN)
  49 +
  50 +installmandocs: mandocs
  51 + mkdir -p /usr/local/man/man9/
  52 + install doc/DocBook/man/*.9.gz /usr/local/man/man9/
  53 +
  54 +###
  55 +#External programs used
  56 +KERNELDOC = $(SRCTREE)/tools/kernel-doc/kernel-doc
  57 +DOCPROC = $(OBJTREE)/tools/kernel-doc/docproc
  58 +
  59 +XMLTOFLAGS = -m $(SRCTREE)/doc/DocBook/stylesheet.xsl
  60 +XMLTOFLAGS += --skip-validation
  61 +
  62 +###
  63 +# DOCPROC is used for two purposes:
  64 +# 1) To generate a dependency list for a .tmpl file
  65 +# 2) To preprocess a .tmpl file and call kernel-doc with
  66 +# appropriate parameters.
  67 +# The following rules are used to generate the .xml documentation
  68 +# required to generate the final targets. (ps, pdf, html).
  69 +%.xml: %.tmpl
  70 + $(DOCPROC) doc $< >$@
  71 +
  72 +ifeq ($@, "cleandocs")
  73 +sinclude $(obj).depend
  74 +$(obj).depend: $(patsubst %.xml, %.tmpl, $(DOCBOOKS))
  75 + rm -f $(obj).depend ; \
  76 + touch $(obj).depend ; \
  77 + for file in $^ ; do \
  78 + xmlfile=`echo "$${file}" | \
  79 + sed "s/tmpl$$/xml/"` ; \
  80 + echo -n "$${xmlfile}: ">> $(obj).depend ; \
  81 + $(DOCPROC) depend $$file >> $(obj).depend ; \
  82 + echo -e "\n\t$(DOCPROC) doc $< >$${xmlfile} " >> \
  83 + $(obj).depend ; \
  84 + done
  85 +endif
  86 +
  87 +###
  88 +# Changes in kernel-doc force a rebuild of all documentation
  89 +$(BOOKS): $(KERNELDOC)
  90 +
  91 +notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \
  92 + exit 1
  93 +db2xtemplate = db2TYPE -o $(dir $@) $<
  94 +xmltotemplate = xmlto TYPE $(XMLTOFLAGS) -o $(dir $@) $<
  95 +
  96 +# determine which methods are available
  97 +ifeq ($(shell which db2ps >/dev/null 2>&1 && echo found),found)
  98 + use-db2x = db2x
  99 + prefer-db2x = db2x
  100 +else
  101 + use-db2x = notfound
  102 + prefer-db2x = $(use-xmlto)
  103 +endif
  104 +ifeq ($(shell which xmlto >/dev/null 2>&1 && echo found),found)
  105 + use-xmlto = xmlto
  106 + prefer-xmlto = xmlto
  107 +else
  108 + use-xmlto = notfound
  109 + prefer-xmlto = $(use-db2x)
  110 +endif
  111 +
  112 +# the commands, generated from the chosen template
  113 +quiet_cmd_db2ps = PS $@
  114 + cmd_db2ps = $(subst TYPE,ps, $($(PS_METHOD)template))
  115 +%.ps : %.xml
  116 + $(call cmd_db2ps)
  117 +
  118 +quiet_cmd_db2pdf = PDF $@
  119 + cmd_db2pdf = $(subst TYPE,pdf, $($(PDF_METHOD)template))
  120 +%.pdf : %.xml
  121 + $(call cmd_db2pdf)
  122 +
  123 +
  124 +index = index.html
  125 +main_idx = $(index)
  126 +build_main_index = rm -rf $(main_idx); \
  127 + echo '<h1>U-Boot Bootloader HTML Documentation</h1>' >> $(main_idx) && \
  128 + echo '<h2>U-Boot Version: $(U_BOOT_VERSION)</h2>' >> $(main_idx) && \
  129 + cat $(HTML) >> $(main_idx)
  130 +
  131 +# To work around bug [1] in docbook-xsl-stylesheets 1.76.1 , generate only html
  132 +# docs instead of xhtml with xmlto.
  133 +# [1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=654338
  134 +quiet_cmd_db2html = HTML $@
  135 + cmd_db2html = xmlto html $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
  136 + echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
  137 + $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
  138 +
  139 +%.html: %.xml
  140 + @(which xmlto > /dev/null 2>&1) || \
  141 + (echo "*** You need to install xmlto ***"; \
  142 + exit 1)
  143 + @rm -rf $@ $(patsubst %.html,%,$@)
  144 + $(call cmd_db2html)
  145 + @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
  146 + cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
  147 +
  148 +quiet_cmd_db2man = MAN $@
  149 + cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi
  150 +%.9 : %.xml
  151 + @(which xmlto > /dev/null 2>&1) || \
  152 + (echo "*** You need to install xmlto ***"; \
  153 + exit 1)
  154 + $(Q)mkdir -p $(obj)man
  155 + $(call cmd_db2man)
  156 + @touch $@
  157 +
  158 +###
  159 +# Rules to generate postscripts and PNG images from .fig format files
  160 +quiet_cmd_fig2eps = FIG2EPS $@
  161 + cmd_fig2eps = fig2dev -Leps $< $@
  162 +
  163 +%.eps: %.fig
  164 + @(which fig2dev > /dev/null 2>&1) || \
  165 + (echo "*** You need to install transfig ***"; \
  166 + exit 1)
  167 + $(call cmd_fig2eps)
  168 +
  169 +quiet_cmd_fig2png = FIG2PNG $@
  170 + cmd_fig2png = fig2dev -Lpng $< $@
  171 +
  172 +%.png: %.fig
  173 + @(which fig2dev > /dev/null 2>&1) || \
  174 + (echo "*** You need to install transfig ***"; \
  175 + exit 1)
  176 + $(call cmd_fig2png)
  177 +
  178 +###
  179 +# Rule to convert a .c file to inline XML documentation
  180 + gen_xml = :
  181 + quiet_gen_xml = echo ' GEN $@'
  182 +silent_gen_xml = :
  183 +%.xml: %.c
  184 + @$($(quiet)gen_xml)
  185 + @( \
  186 + echo "<programlisting>"; \
  187 + expand --tabs=8 < $< | \
  188 + sed -e "s/&/\\&amp;/g" \
  189 + -e "s/</\\&lt;/g" \
  190 + -e "s/>/\\&gt;/g"; \
  191 + echo "</programlisting>") > $@
  192 +
  193 +###
  194 +# Help targets as used by the top-level makefile
  195 +dochelp:
  196 + @echo ' U-Boot bootloader internal documentation in different formats:'
  197 + @echo ' htmldocs - HTML'
  198 + @echo ' pdfdocs - PDF'
  199 + @echo ' psdocs - Postscript'
  200 + @echo ' xmldocs - XML DocBook'
  201 + @echo ' mandocs - man pages'
  202 + @echo ' installmandocs - install man pages generated by mandocs'
  203 + @echo ' cleandocs - clean all generated DocBook files'
  204 +
  205 +###
  206 +# Temporary files left by various tools
  207 +clean-files := $(DOCBOOKS) \
  208 + $(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
  209 + $(patsubst %.xml, %.aux, $(DOCBOOKS)) \
  210 + $(patsubst %.xml, %.tex, $(DOCBOOKS)) \
  211 + $(patsubst %.xml, %.log, $(DOCBOOKS)) \
  212 + $(patsubst %.xml, %.out, $(DOCBOOKS)) \
  213 + $(patsubst %.xml, %.ps, $(DOCBOOKS)) \
  214 + $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
  215 + $(patsubst %.xml, %.html, $(DOCBOOKS)) \
  216 + $(patsubst %.xml, %.9, $(DOCBOOKS)) \
  217 + $(index)
  218 +
  219 +clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
  220 +
  221 +cleandocs:
  222 + @rm -f $(obj).depend
  223 + @$(Q)rm -f $(call objectify, $(clean-files))
  224 + @$(Q)rm -rf $(call objectify, $(clean-dirs))
  225 +
  226 +# Declare the contents of the .PHONY variable as phony. We keep that
  227 +# information in a variable se we can use it in if_changed and friends.
  228 +
  229 +.PHONY: $(PHONY)
doc/DocBook/stylesheet.xsl
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
  3 +<param name="chunk.quietly">1</param>
  4 +<param name="funcsynopsis.style">ansi</param>
  5 +<param name="funcsynopsis.tabular.threshold">80</param>
  6 +<param name="callout.graphics">0</param>
  7 +<!-- <param name="paper.type">A4</param> -->
  8 +<param name="generate.section.toc.level">2</param>
  9 +<param name="use.id.as.filename">1</param>
  10 +</stylesheet>
... ... @@ -17,4 +17,5 @@
17 17 /env/fw_printenv
18 18 /gdb/gdbcont
19 19 /gdb/gdbsend
  20 +/kernel-doc/docproc
... ... @@ -21,7 +21,7 @@
21 21 # MA 02111-1307 USA
22 22 #
23 23  
24   -TOOLSUBDIRS =
  24 +TOOLSUBDIRS = kernel-doc
25 25  
26 26 #
27 27 # Include this after HOSTOS HOSTARCH check
tools/kernel-doc/Makefile
  1 +#
  2 +# Copyright (C) 2012 Marek Vasut <marex@denx.de>
  3 +#
  4 +# This program is free software; you can redistribute it and/or
  5 +# modify it under the terms of the GNU General Public License as
  6 +# published by the Free Software Foundation; either version 2 of
  7 +# the License, or (at your option) any later version.
  8 +#
  9 +# This program is distributed in the hope that it will be useful,
  10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 +# GNU General Public License for more details.
  13 +#
  14 +# You should have received a copy of the GNU General Public License
  15 +# along with this program; if not, write to the Free Software
  16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17 +# MA 02111-1307 USA
  18 +#
  19 +
  20 +include $(TOPDIR)/config.mk
  21 +
  22 +all: $(obj)docproc
  23 +
  24 +$(obj)docproc: docproc.c
  25 + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
  26 + $(HOSTSTRIP) $@
  27 +
  28 +clean:
  29 + rm -rf docproc
  30 +
  31 +#########################################################################
  32 +
  33 +# defines $(obj).depend target
  34 +include $(SRCTREE)/rules.mk
  35 +
  36 +sinclude $(obj).depend
  37 +
  38 +#########################################################################
tools/kernel-doc/docproc.c
  1 +/*
  2 + * docproc is a simple preprocessor for the template files
  3 + * used as placeholders for the kernel internal documentation.
  4 + * docproc is used for documentation-frontend and
  5 + * dependency-generator.
  6 + * The two usages have in common that they require
  7 + * some knowledge of the .tmpl syntax, therefore they
  8 + * are kept together.
  9 + *
  10 + * documentation-frontend
  11 + * Scans the template file and call kernel-doc for
  12 + * all occurrences of ![EIF]file
  13 + * Beforehand each referenced file is scanned for
  14 + * any symbols that are exported via these macros:
  15 + * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), &
  16 + * EXPORT_SYMBOL_GPL_FUTURE()
  17 + * This is used to create proper -function and
  18 + * -nofunction arguments in calls to kernel-doc.
  19 + * Usage: docproc doc file.tmpl
  20 + *
  21 + * dependency-generator:
  22 + * Scans the template file and list all files
  23 + * referenced in a format recognized by make.
  24 + * Usage: docproc depend file.tmpl
  25 + * Writes dependency information to stdout
  26 + * in the following format:
  27 + * file.tmpl src.c src2.c
  28 + * The filenames are obtained from the following constructs:
  29 + * !Efilename
  30 + * !Ifilename
  31 + * !Dfilename
  32 + * !Ffilename
  33 + * !Pfilename
  34 + *
  35 + */
  36 +
  37 +#define _GNU_SOURCE
  38 +#include <stdio.h>
  39 +#include <stdlib.h>
  40 +#include <string.h>
  41 +#include <ctype.h>
  42 +#include <unistd.h>
  43 +#include <limits.h>
  44 +#include <errno.h>
  45 +#include <sys/types.h>
  46 +#include <sys/wait.h>
  47 +
  48 +/* exitstatus is used to keep track of any failing calls to kernel-doc,
  49 + * but execution continues. */
  50 +int exitstatus = 0;
  51 +
  52 +typedef void DFL(char *);
  53 +DFL *defaultline;
  54 +
  55 +typedef void FILEONLY(char * file);
  56 +FILEONLY *internalfunctions;
  57 +FILEONLY *externalfunctions;
  58 +FILEONLY *symbolsonly;
  59 +FILEONLY *findall;
  60 +
  61 +typedef void FILELINE(char * file, char * line);
  62 +FILELINE * singlefunctions;
  63 +FILELINE * entity_system;
  64 +FILELINE * docsection;
  65 +
  66 +#define MAXLINESZ 2048
  67 +#define MAXFILES 250
  68 +#define KERNELDOCPATH "tools/kernel-doc/"
  69 +#define KERNELDOC "kernel-doc"
  70 +#define DOCBOOK "-docbook"
  71 +#define LIST "-list"
  72 +#define FUNCTION "-function"
  73 +#define NOFUNCTION "-nofunction"
  74 +#define NODOCSECTIONS "-no-doc-sections"
  75 +
  76 +static char *srctree, *kernsrctree;
  77 +
  78 +static char **all_list = NULL;
  79 +static int all_list_len = 0;
  80 +
  81 +static void consume_symbol(const char *sym)
  82 +{
  83 + int i;
  84 +
  85 + for (i = 0; i < all_list_len; i++) {
  86 + if (!all_list[i])
  87 + continue;
  88 + if (strcmp(sym, all_list[i]))
  89 + continue;
  90 + all_list[i] = NULL;
  91 + break;
  92 + }
  93 +}
  94 +
  95 +static void usage (void)
  96 +{
  97 + fprintf(stderr, "Usage: docproc {doc|depend} file\n");
  98 + fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
  99 + fprintf(stderr, "doc: frontend when generating kernel documentation\n");
  100 + fprintf(stderr, "depend: generate list of files referenced within file\n");
  101 + fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n");
  102 + fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n");
  103 +}
  104 +
  105 +/*
  106 + * Execute kernel-doc with parameters given in svec
  107 + */
  108 +static void exec_kernel_doc(char **svec)
  109 +{
  110 + pid_t pid;
  111 + int ret;
  112 + char real_filename[PATH_MAX + 1];
  113 + /* Make sure output generated so far are flushed */
  114 + fflush(stdout);
  115 + switch (pid=fork()) {
  116 + case -1:
  117 + perror("fork");
  118 + exit(1);
  119 + case 0:
  120 + memset(real_filename, 0, sizeof(real_filename));
  121 + strncat(real_filename, kernsrctree, PATH_MAX);
  122 + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
  123 + PATH_MAX - strlen(real_filename));
  124 + execvp(real_filename, svec);
  125 + fprintf(stderr, "exec ");
  126 + perror(real_filename);
  127 + exit(1);
  128 + default:
  129 + waitpid(pid, &ret ,0);
  130 + }
  131 + if (WIFEXITED(ret))
  132 + exitstatus |= WEXITSTATUS(ret);
  133 + else
  134 + exitstatus = 0xff;
  135 +}
  136 +
  137 +/* Types used to create list of all exported symbols in a number of files */
  138 +struct symbols
  139 +{
  140 + char *name;
  141 +};
  142 +
  143 +struct symfile
  144 +{
  145 + char *filename;
  146 + struct symbols *symbollist;
  147 + int symbolcnt;
  148 +};
  149 +
  150 +struct symfile symfilelist[MAXFILES];
  151 +int symfilecnt = 0;
  152 +
  153 +static void add_new_symbol(struct symfile *sym, char * symname)
  154 +{
  155 + sym->symbollist =
  156 + realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
  157 + sym->symbollist[sym->symbolcnt++].name = strdup(symname);
  158 +}
  159 +
  160 +/* Add a filename to the list */
  161 +static struct symfile * add_new_file(char * filename)
  162 +{
  163 + symfilelist[symfilecnt++].filename = strdup(filename);
  164 + return &symfilelist[symfilecnt - 1];
  165 +}
  166 +
  167 +/* Check if file already are present in the list */
  168 +static struct symfile * filename_exist(char * filename)
  169 +{
  170 + int i;
  171 + for (i=0; i < symfilecnt; i++)
  172 + if (strcmp(symfilelist[i].filename, filename) == 0)
  173 + return &symfilelist[i];
  174 + return NULL;
  175 +}
  176 +
  177 +/*
  178 + * List all files referenced within the template file.
  179 + * Files are separated by tabs.
  180 + */
  181 +static void adddep(char * file) { printf("\t%s", file); }
  182 +static void adddep2(char * file, char * line) { line = line; adddep(file); }
  183 +static void noaction(char * line) { line = line; }
  184 +static void noaction2(char * file, char * line) { file = file; line = line; }
  185 +
  186 +/* Echo the line without further action */
  187 +static void printline(char * line) { printf("%s", line); }
  188 +
  189 +/*
  190 + * Find all symbols in filename that are exported with EXPORT_SYMBOL &
  191 + * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly).
  192 + * All symbols located are stored in symfilelist.
  193 + */
  194 +static void find_export_symbols(char * filename)
  195 +{
  196 + FILE * fp;
  197 + struct symfile *sym;
  198 + char line[MAXLINESZ];
  199 + if (filename_exist(filename) == NULL) {
  200 + char real_filename[PATH_MAX + 1];
  201 + memset(real_filename, 0, sizeof(real_filename));
  202 + strncat(real_filename, srctree, PATH_MAX);
  203 + strncat(real_filename, "/", PATH_MAX - strlen(real_filename));
  204 + strncat(real_filename, filename,
  205 + PATH_MAX - strlen(real_filename));
  206 + sym = add_new_file(filename);
  207 + fp = fopen(real_filename, "r");
  208 + if (fp == NULL) {
  209 + fprintf(stderr, "docproc: ");
  210 + perror(real_filename);
  211 + exit(1);
  212 + }
  213 + while (fgets(line, MAXLINESZ, fp)) {
  214 + char *p;
  215 + char *e;
  216 + if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) ||
  217 + ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) {
  218 + /* Skip EXPORT_SYMBOL{_GPL} */
  219 + while (isalnum(*p) || *p == '_')
  220 + p++;
  221 + /* Remove parentheses & additional whitespace */
  222 + while (isspace(*p))
  223 + p++;
  224 + if (*p != '(')
  225 + continue; /* Syntax error? */
  226 + else
  227 + p++;
  228 + while (isspace(*p))
  229 + p++;
  230 + e = p;
  231 + while (isalnum(*e) || *e == '_')
  232 + e++;
  233 + *e = '\0';
  234 + add_new_symbol(sym, p);
  235 + }
  236 + }
  237 + fclose(fp);
  238 + }
  239 +}
  240 +
  241 +/*
  242 + * Document all external or internal functions in a file.
  243 + * Call kernel-doc with following parameters:
  244 + * kernel-doc -docbook -nofunction function_name1 filename
  245 + * Function names are obtained from all the src files
  246 + * by find_export_symbols.
  247 + * intfunc uses -nofunction
  248 + * extfunc uses -function
  249 + */
  250 +static void docfunctions(char * filename, char * type)
  251 +{
  252 + int i,j;
  253 + int symcnt = 0;
  254 + int idx = 0;
  255 + char **vec;
  256 +
  257 + for (i=0; i <= symfilecnt; i++)
  258 + symcnt += symfilelist[i].symbolcnt;
  259 + vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *));
  260 + if (vec == NULL) {
  261 + perror("docproc: ");
  262 + exit(1);
  263 + }
  264 + vec[idx++] = KERNELDOC;
  265 + vec[idx++] = DOCBOOK;
  266 + vec[idx++] = NODOCSECTIONS;
  267 + for (i=0; i < symfilecnt; i++) {
  268 + struct symfile * sym = &symfilelist[i];
  269 + for (j=0; j < sym->symbolcnt; j++) {
  270 + vec[idx++] = type;
  271 + consume_symbol(sym->symbollist[j].name);
  272 + vec[idx++] = sym->symbollist[j].name;
  273 + }
  274 + }
  275 + vec[idx++] = filename;
  276 + vec[idx] = NULL;
  277 + printf("<!-- %s -->\n", filename);
  278 + exec_kernel_doc(vec);
  279 + fflush(stdout);
  280 + free(vec);
  281 +}
  282 +static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
  283 +static void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
  284 +
  285 +/*
  286 + * Document specific function(s) in a file.
  287 + * Call kernel-doc with the following parameters:
  288 + * kernel-doc -docbook -function function1 [-function function2]
  289 + */
  290 +static void singfunc(char * filename, char * line)
  291 +{
  292 + char *vec[200]; /* Enough for specific functions */
  293 + int i, idx = 0;
  294 + int startofsym = 1;
  295 + vec[idx++] = KERNELDOC;
  296 + vec[idx++] = DOCBOOK;
  297 +
  298 + /* Split line up in individual parameters preceded by FUNCTION */
  299 + for (i=0; line[i]; i++) {
  300 + if (isspace(line[i])) {
  301 + line[i] = '\0';
  302 + startofsym = 1;
  303 + continue;
  304 + }
  305 + if (startofsym) {
  306 + startofsym = 0;
  307 + vec[idx++] = FUNCTION;
  308 + vec[idx++] = &line[i];
  309 + }
  310 + }
  311 + for (i = 0; i < idx; i++) {
  312 + if (strcmp(vec[i], FUNCTION))
  313 + continue;
  314 + consume_symbol(vec[i + 1]);
  315 + }
  316 + vec[idx++] = filename;
  317 + vec[idx] = NULL;
  318 + exec_kernel_doc(vec);
  319 +}
  320 +
  321 +/*
  322 + * Insert specific documentation section from a file.
  323 + * Call kernel-doc with the following parameters:
  324 + * kernel-doc -docbook -function "doc section" filename
  325 + */
  326 +static void docsect(char *filename, char *line)
  327 +{
  328 + char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */
  329 + char *s;
  330 +
  331 + for (s = line; *s; s++)
  332 + if (*s == '\n')
  333 + *s = '\0';
  334 +
  335 + if (asprintf(&s, "DOC: %s", line) < 0) {
  336 + perror("asprintf");
  337 + exit(1);
  338 + }
  339 + consume_symbol(s);
  340 + free(s);
  341 +
  342 + vec[0] = KERNELDOC;
  343 + vec[1] = DOCBOOK;
  344 + vec[2] = FUNCTION;
  345 + vec[3] = line;
  346 + vec[4] = filename;
  347 + vec[5] = NULL;
  348 + exec_kernel_doc(vec);
  349 +}
  350 +
  351 +static void find_all_symbols(char *filename)
  352 +{
  353 + char *vec[4]; /* kerneldoc -list file NULL */
  354 + pid_t pid;
  355 + int ret, i, count, start;
  356 + char real_filename[PATH_MAX + 1];
  357 + int pipefd[2];
  358 + char *data, *str;
  359 + size_t data_len = 0;
  360 +
  361 + vec[0] = KERNELDOC;
  362 + vec[1] = LIST;
  363 + vec[2] = filename;
  364 + vec[3] = NULL;
  365 +
  366 + if (pipe(pipefd)) {
  367 + perror("pipe");
  368 + exit(1);
  369 + }
  370 +
  371 + switch (pid=fork()) {
  372 + case -1:
  373 + perror("fork");
  374 + exit(1);
  375 + case 0:
  376 + close(pipefd[0]);
  377 + dup2(pipefd[1], 1);
  378 + memset(real_filename, 0, sizeof(real_filename));
  379 + strncat(real_filename, kernsrctree, PATH_MAX);
  380 + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
  381 + PATH_MAX - strlen(real_filename));
  382 + execvp(real_filename, vec);
  383 + fprintf(stderr, "exec ");
  384 + perror(real_filename);
  385 + exit(1);
  386 + default:
  387 + close(pipefd[1]);
  388 + data = malloc(4096);
  389 + do {
  390 + while ((ret = read(pipefd[0],
  391 + data + data_len,
  392 + 4096)) > 0) {
  393 + data_len += ret;
  394 + data = realloc(data, data_len + 4096);
  395 + }
  396 + } while (ret == -EAGAIN);
  397 + if (ret != 0) {
  398 + perror("read");
  399 + exit(1);
  400 + }
  401 + waitpid(pid, &ret ,0);
  402 + }
  403 + if (WIFEXITED(ret))
  404 + exitstatus |= WEXITSTATUS(ret);
  405 + else
  406 + exitstatus = 0xff;
  407 +
  408 + count = 0;
  409 + /* poor man's strtok, but with counting */
  410 + for (i = 0; i < data_len; i++) {
  411 + if (data[i] == '\n') {
  412 + count++;
  413 + data[i] = '\0';
  414 + }
  415 + }
  416 + start = all_list_len;
  417 + all_list_len += count;
  418 + all_list = realloc(all_list, sizeof(char *) * all_list_len);
  419 + str = data;
  420 + for (i = 0; i < data_len && start != all_list_len; i++) {
  421 + if (data[i] == '\0') {
  422 + all_list[start] = str;
  423 + str = data + i + 1;
  424 + start++;
  425 + }
  426 + }
  427 +}
  428 +
  429 +/*
  430 + * Parse file, calling action specific functions for:
  431 + * 1) Lines containing !E
  432 + * 2) Lines containing !I
  433 + * 3) Lines containing !D
  434 + * 4) Lines containing !F
  435 + * 5) Lines containing !P
  436 + * 6) Lines containing !C
  437 + * 7) Default lines - lines not matching the above
  438 + */
  439 +static void parse_file(FILE *infile)
  440 +{
  441 + char line[MAXLINESZ];
  442 + char * s;
  443 + while (fgets(line, MAXLINESZ, infile)) {
  444 + if (line[0] == '!') {
  445 + s = line + 2;
  446 + switch (line[1]) {
  447 + case 'E':
  448 + while (*s && !isspace(*s)) s++;
  449 + *s = '\0';
  450 + externalfunctions(line+2);
  451 + break;
  452 + case 'I':
  453 + while (*s && !isspace(*s)) s++;
  454 + *s = '\0';
  455 + internalfunctions(line+2);
  456 + break;
  457 + case 'D':
  458 + while (*s && !isspace(*s)) s++;
  459 + *s = '\0';
  460 + symbolsonly(line+2);
  461 + break;
  462 + case 'F':
  463 + /* filename */
  464 + while (*s && !isspace(*s)) s++;
  465 + *s++ = '\0';
  466 + /* function names */
  467 + while (isspace(*s))
  468 + s++;
  469 + singlefunctions(line +2, s);
  470 + break;
  471 + case 'P':
  472 + /* filename */
  473 + while (*s && !isspace(*s)) s++;
  474 + *s++ = '\0';
  475 + /* DOC: section name */
  476 + while (isspace(*s))
  477 + s++;
  478 + docsection(line + 2, s);
  479 + break;
  480 + case 'C':
  481 + while (*s && !isspace(*s)) s++;
  482 + *s = '\0';
  483 + if (findall)
  484 + findall(line+2);
  485 + break;
  486 + default:
  487 + defaultline(line);
  488 + }
  489 + } else {
  490 + defaultline(line);
  491 + }
  492 + }
  493 + fflush(stdout);
  494 +}
  495 +
  496 +
  497 +int main(int argc, char *argv[])
  498 +{
  499 + FILE * infile;
  500 + int i;
  501 +
  502 + srctree = getenv("SRCTREE");
  503 + if (!srctree)
  504 + srctree = getcwd(NULL, 0);
  505 + kernsrctree = getenv("KBUILD_SRC");
  506 + if (!kernsrctree || !*kernsrctree)
  507 + kernsrctree = srctree;
  508 + if (argc != 3) {
  509 + usage();
  510 + exit(1);
  511 + }
  512 + /* Open file, exit on error */
  513 + infile = fopen(argv[2], "r");
  514 + if (infile == NULL) {
  515 + fprintf(stderr, "docproc: ");
  516 + perror(argv[2]);
  517 + exit(2);
  518 + }
  519 +
  520 + if (strcmp("doc", argv[1]) == 0) {
  521 + /* Need to do this in two passes.
  522 + * First pass is used to collect all symbols exported
  523 + * in the various files;
  524 + * Second pass generate the documentation.
  525 + * This is required because some functions are declared
  526 + * and exported in different files :-((
  527 + */
  528 + /* Collect symbols */
  529 + defaultline = noaction;
  530 + internalfunctions = find_export_symbols;
  531 + externalfunctions = find_export_symbols;
  532 + symbolsonly = find_export_symbols;
  533 + singlefunctions = noaction2;
  534 + docsection = noaction2;
  535 + findall = find_all_symbols;
  536 + parse_file(infile);
  537 +
  538 + /* Rewind to start from beginning of file again */
  539 + fseek(infile, 0, SEEK_SET);
  540 + defaultline = printline;
  541 + internalfunctions = intfunc;
  542 + externalfunctions = extfunc;
  543 + symbolsonly = printline;
  544 + singlefunctions = singfunc;
  545 + docsection = docsect;
  546 + findall = NULL;
  547 +
  548 + parse_file(infile);
  549 +
  550 + for (i = 0; i < all_list_len; i++) {
  551 + if (!all_list[i])
  552 + continue;
  553 + fprintf(stderr, "Warning: didn't use docs for %s\n",
  554 + all_list[i]);
  555 + }
  556 + } else if (strcmp("depend", argv[1]) == 0) {
  557 + /* Create first part of dependency chain
  558 + * file.tmpl */
  559 + printf("%s\t", argv[2]);
  560 + defaultline = noaction;
  561 + internalfunctions = adddep;
  562 + externalfunctions = adddep;
  563 + symbolsonly = adddep;
  564 + singlefunctions = adddep2;
  565 + docsection = adddep2;
  566 + findall = adddep;
  567 + parse_file(infile);
  568 + printf("\n");
  569 + } else {
  570 + fprintf(stderr, "Unknown option: %s\n", argv[1]);
  571 + exit(1);
  572 + }
  573 + fclose(infile);
  574 + fflush(stdout);
  575 + return exitstatus;
  576 +}
tools/kernel-doc/kernel-doc
Changes suppressed. Click to show
  1 +#!/usr/bin/perl -w
  2 +
  3 +use strict;
  4 +
  5 +## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
  6 +## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
  7 +## Copyright (C) 2001 Simon Huggins ##
  8 +## Copyright (C) 2005-2012 Randy Dunlap ##
  9 +## Copyright (C) 2012 Dan Luedtke ##
  10 +## ##
  11 +## #define enhancements by Armin Kuster <akuster@mvista.com> ##
  12 +## Copyright (c) 2000 MontaVista Software, Inc. ##
  13 +## ##
  14 +## This software falls under the GNU General Public License. ##
  15 +## Please read the COPYING file for more information ##
  16 +
  17 +# 18/01/2001 - Cleanups
  18 +# Functions prototyped as foo(void) same as foo()
  19 +# Stop eval'ing where we don't need to.
  20 +# -- huggie@earth.li
  21 +
  22 +# 27/06/2001 - Allowed whitespace after initial "/**" and
  23 +# allowed comments before function declarations.
  24 +# -- Christian Kreibich <ck@whoop.org>
  25 +
  26 +# Still to do:
  27 +# - add perldoc documentation
  28 +# - Look more closely at some of the scarier bits :)
  29 +
  30 +# 26/05/2001 - Support for separate source and object trees.
  31 +# Return error code.
  32 +# Keith Owens <kaos@ocs.com.au>
  33 +
  34 +# 23/09/2001 - Added support for typedefs, structs, enums and unions
  35 +# Support for Context section; can be terminated using empty line
  36 +# Small fixes (like spaces vs. \s in regex)
  37 +# -- Tim Jansen <tim@tjansen.de>
  38 +
  39 +# 25/07/2012 - Added support for HTML5
  40 +# -- Dan Luedtke <mail@danrl.de>
  41 +
  42 +#
  43 +# This will read a 'c' file and scan for embedded comments in the
  44 +# style of gnome comments (+minor extensions - see below).
  45 +#
  46 +
  47 +# Note: This only supports 'c'.
  48 +
  49 +# usage:
  50 +# kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
  51 +# [ -no-doc-sections ]
  52 +# [ -function funcname [ -function funcname ...] ]
  53 +# c file(s)s > outputfile
  54 +# or
  55 +# [ -nofunction funcname [ -function funcname ...] ]
  56 +# c file(s)s > outputfile
  57 +#
  58 +# Set output format using one of -docbook -html -html5 -text or -man.
  59 +# Default is man.
  60 +# The -list format is for internal use by docproc.
  61 +#
  62 +# -no-doc-sections
  63 +# Do not output DOC: sections
  64 +#
  65 +# -function funcname
  66 +# If set, then only generate documentation for the given function(s) or
  67 +# DOC: section titles. All other functions and DOC: sections are ignored.
  68 +#
  69 +# -nofunction funcname
  70 +# If set, then only generate documentation for the other function(s)/DOC:
  71 +# sections. Cannot be used together with -function (yes, that's a bug --
  72 +# perl hackers can fix it 8))
  73 +#
  74 +# c files - list of 'c' files to process
  75 +#
  76 +# All output goes to stdout, with errors to stderr.
  77 +
  78 +#
  79 +# format of comments.
  80 +# In the following table, (...)? signifies optional structure.
  81 +# (...)* signifies 0 or more structure elements
  82 +# /**
  83 +# * function_name(:)? (- short description)?
  84 +# (* @parameterx: (description of parameter x)?)*
  85 +# (* a blank line)?
  86 +# * (Description:)? (Description of function)?
  87 +# * (section header: (section description)? )*
  88 +# (*)?*/
  89 +#
  90 +# So .. the trivial example would be:
  91 +#
  92 +# /**
  93 +# * my_function
  94 +# */
  95 +#
  96 +# If the Description: header tag is omitted, then there must be a blank line
  97 +# after the last parameter specification.
  98 +# e.g.
  99 +# /**
  100 +# * my_function - does my stuff
  101 +# * @my_arg: its mine damnit
  102 +# *
  103 +# * Does my stuff explained.
  104 +# */
  105 +#
  106 +# or, could also use:
  107 +# /**
  108 +# * my_function - does my stuff
  109 +# * @my_arg: its mine damnit
  110 +# * Description: Does my stuff explained.
  111 +# */
  112 +# etc.
  113 +#
  114 +# Besides functions you can also write documentation for structs, unions,
  115 +# enums and typedefs. Instead of the function name you must write the name
  116 +# of the declaration; the struct/union/enum/typedef must always precede
  117 +# the name. Nesting of declarations is not supported.
  118 +# Use the argument mechanism to document members or constants.
  119 +# e.g.
  120 +# /**
  121 +# * struct my_struct - short description
  122 +# * @a: first member
  123 +# * @b: second member
  124 +# *
  125 +# * Longer description
  126 +# */
  127 +# struct my_struct {
  128 +# int a;
  129 +# int b;
  130 +# /* private: */
  131 +# int c;
  132 +# };
  133 +#
  134 +# All descriptions can be multiline, except the short function description.
  135 +#
  136 +# You can also add additional sections. When documenting kernel functions you
  137 +# should document the "Context:" of the function, e.g. whether the functions
  138 +# can be called form interrupts. Unlike other sections you can end it with an
  139 +# empty line.
  140 +# Example-sections should contain the string EXAMPLE so that they are marked
  141 +# appropriately in DocBook.
  142 +#
  143 +# Example:
  144 +# /**
  145 +# * user_function - function that can only be called in user context
  146 +# * @a: some argument
  147 +# * Context: !in_interrupt()
  148 +# *
  149 +# * Some description
  150 +# * Example:
  151 +# * user_function(22);
  152 +# */
  153 +# ...
  154 +#
  155 +#
  156 +# All descriptive text is further processed, scanning for the following special
  157 +# patterns, which are highlighted appropriately.
  158 +#
  159 +# 'funcname()' - function
  160 +# '$ENVVAR' - environmental variable
  161 +# '&struct_name' - name of a structure (up to two words including 'struct')
  162 +# '@parameter' - name of a parameter
  163 +# '%CONST' - name of a constant.
  164 +
  165 +## init lots of data
  166 +
  167 +my $errors = 0;
  168 +my $warnings = 0;
  169 +my $anon_struct_union = 0;
  170 +
  171 +# match expressions used to find embedded type information
  172 +my $type_constant = '\%([-_\w]+)';
  173 +my $type_func = '(\w+)\(\)';
  174 +my $type_param = '\@(\w+)';
  175 +my $type_struct = '\&((struct\s*)*[_\w]+)';
  176 +my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
  177 +my $type_env = '(\$\w+)';
  178 +
  179 +# Output conversion substitutions.
  180 +# One for each output format
  181 +
  182 +# these work fairly well
  183 +my %highlights_html = ( $type_constant, "<i>\$1</i>",
  184 + $type_func, "<b>\$1</b>",
  185 + $type_struct_xml, "<i>\$1</i>",
  186 + $type_env, "<b><i>\$1</i></b>",
  187 + $type_param, "<tt><b>\$1</b></tt>" );
  188 +my $local_lt = "\\\\\\\\lt:";
  189 +my $local_gt = "\\\\\\\\gt:";
  190 +my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
  191 +
  192 +# html version 5
  193 +my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
  194 + $type_func, "<span class=\"func\">\$1</span>",
  195 + $type_struct_xml, "<span class=\"struct\">\$1</span>",
  196 + $type_env, "<span class=\"env\">\$1</span>",
  197 + $type_param, "<span class=\"param\">\$1</span>" );
  198 +my $blankline_html5 = $local_lt . "br /" . $local_gt;
  199 +
  200 +# XML, docbook format
  201 +my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
  202 + $type_constant, "<constant>\$1</constant>",
  203 + $type_func, "<function>\$1</function>",
  204 + $type_struct_xml, "<structname>\$1</structname>",
  205 + $type_env, "<envar>\$1</envar>",
  206 + $type_param, "<parameter>\$1</parameter>" );
  207 +my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
  208 +
  209 +# gnome, docbook format
  210 +my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
  211 + $type_func, "<function>\$1</function>",
  212 + $type_struct, "<structname>\$1</structname>",
  213 + $type_env, "<envar>\$1</envar>",
  214 + $type_param, "<parameter>\$1</parameter>" );
  215 +my $blankline_gnome = "</para><para>\n";
  216 +
  217 +# these are pretty rough
  218 +my %highlights_man = ( $type_constant, "\$1",
  219 + $type_func, "\\\\fB\$1\\\\fP",
  220 + $type_struct, "\\\\fI\$1\\\\fP",
  221 + $type_param, "\\\\fI\$1\\\\fP" );
  222 +my $blankline_man = "";
  223 +
  224 +# text-mode
  225 +my %highlights_text = ( $type_constant, "\$1",
  226 + $type_func, "\$1",
  227 + $type_struct, "\$1",
  228 + $type_param, "\$1" );
  229 +my $blankline_text = "";
  230 +
  231 +# list mode
  232 +my %highlights_list = ( $type_constant, "\$1",
  233 + $type_func, "\$1",
  234 + $type_struct, "\$1",
  235 + $type_param, "\$1" );
  236 +my $blankline_list = "";
  237 +
  238 +# read arguments
  239 +if ($#ARGV == -1) {
  240 + usage();
  241 +}
  242 +
  243 +my $kernelversion;
  244 +my $dohighlight = "";
  245 +
  246 +my $verbose = 0;
  247 +my $output_mode = "man";
  248 +my $no_doc_sections = 0;
  249 +my %highlights = %highlights_man;
  250 +my $blankline = $blankline_man;
  251 +my $modulename = "Bootloader API";
  252 +my $function_only = 0;
  253 +my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
  254 + 'July', 'August', 'September', 'October',
  255 + 'November', 'December')[(localtime)[4]] .
  256 + " " . ((localtime)[5]+1900);
  257 +
  258 +# Essentially these are globals.
  259 +# They probably want to be tidied up, made more localised or something.
  260 +# CAVEAT EMPTOR! Some of the others I localised may not want to be, which
  261 +# could cause "use of undefined value" or other bugs.
  262 +my ($function, %function_table, %parametertypes, $declaration_purpose);
  263 +my ($type, $declaration_name, $return_type);
  264 +my ($newsection, $newcontents, $prototype, $brcount, %source_map);
  265 +
  266 +if (defined($ENV{'KBUILD_VERBOSE'})) {
  267 + $verbose = "$ENV{'KBUILD_VERBOSE'}";
  268 +}
  269 +
  270 +# Generated docbook code is inserted in a template at a point where
  271 +# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
  272 +# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
  273 +# We keep track of number of generated entries and generate a dummy
  274 +# if needs be to ensure the expanded template can be postprocessed
  275 +# into html.
  276 +my $section_counter = 0;
  277 +
  278 +my $lineprefix="";
  279 +
  280 +# states
  281 +# 0 - normal code
  282 +# 1 - looking for function name
  283 +# 2 - scanning field start.
  284 +# 3 - scanning prototype.
  285 +# 4 - documentation block
  286 +my $state;
  287 +my $in_doc_sect;
  288 +
  289 +#declaration types: can be
  290 +# 'function', 'struct', 'union', 'enum', 'typedef'
  291 +my $decl_type;
  292 +
  293 +my $doc_special = "\@\%\$\&";
  294 +
  295 +my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
  296 +my $doc_end = '\*/';
  297 +my $doc_com = '\s*\*\s*';
  298 +my $doc_decl = $doc_com . '(\w+)';
  299 +my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
  300 +my $doc_content = $doc_com . '(.*)';
  301 +my $doc_block = $doc_com . 'DOC:\s*(.*)?';
  302 +
  303 +my %constants;
  304 +my %parameterdescs;
  305 +my @parameterlist;
  306 +my %sections;
  307 +my @sectionlist;
  308 +my $sectcheck;
  309 +my $struct_actual;
  310 +
  311 +my $contents = "";
  312 +my $section_default = "Description"; # default section
  313 +my $section_intro = "Introduction";
  314 +my $section = $section_default;
  315 +my $section_context = "Context";
  316 +
  317 +my $undescribed = "-- undescribed --";
  318 +
  319 +reset_state();
  320 +
  321 +while ($ARGV[0] =~ m/^-(.*)/) {
  322 + my $cmd = shift @ARGV;
  323 + if ($cmd eq "-html") {
  324 + $output_mode = "html";
  325 + %highlights = %highlights_html;
  326 + $blankline = $blankline_html;
  327 + } elsif ($cmd eq "-html5") {
  328 + $output_mode = "html5";
  329 + %highlights = %highlights_html5;
  330 + $blankline = $blankline_html5;
  331 + } elsif ($cmd eq "-man") {
  332 + $output_mode = "man";
  333 + %highlights = %highlights_man;
  334 + $blankline = $blankline_man;
  335 + } elsif ($cmd eq "-text") {
  336 + $output_mode = "text";
  337 + %highlights = %highlights_text;
  338 + $blankline = $blankline_text;
  339 + } elsif ($cmd eq "-docbook") {
  340 + $output_mode = "xml";
  341 + %highlights = %highlights_xml;
  342 + $blankline = $blankline_xml;
  343 + } elsif ($cmd eq "-list") {
  344 + $output_mode = "list";
  345 + %highlights = %highlights_list;
  346 + $blankline = $blankline_list;
  347 + } elsif ($cmd eq "-gnome") {
  348 + $output_mode = "gnome";
  349 + %highlights = %highlights_gnome;
  350 + $blankline = $blankline_gnome;
  351 + } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
  352 + $modulename = shift @ARGV;
  353 + } elsif ($cmd eq "-function") { # to only output specific functions
  354 + $function_only = 1;
  355 + $function = shift @ARGV;
  356 + $function_table{$function} = 1;
  357 + } elsif ($cmd eq "-nofunction") { # to only output specific functions
  358 + $function_only = 2;
  359 + $function = shift @ARGV;
  360 + $function_table{$function} = 1;
  361 + } elsif ($cmd eq "-v") {
  362 + $verbose = 1;
  363 + } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
  364 + usage();
  365 + } elsif ($cmd eq '-no-doc-sections') {
  366 + $no_doc_sections = 1;
  367 + }
  368 +}
  369 +
  370 +# continue execution near EOF;
  371 +
  372 +sub usage {
  373 + print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
  374 + print " [ -no-doc-sections ]\n";
  375 + print " [ -function funcname [ -function funcname ...] ]\n";
  376 + print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
  377 + print " [ -v ]\n";
  378 + print " c source file(s) > outputfile\n";
  379 + print " -v : verbose output, more warnings & other info listed\n";
  380 + exit 1;
  381 +}
  382 +
  383 +# get kernel version from env
  384 +sub get_kernel_version() {
  385 + my $version = 'unknown kernel version';
  386 +
  387 + if (defined($ENV{'U_BOOT_VERSION'})) {
  388 + $version = $ENV{'U_BOOT_VERSION'};
  389 + }
  390 + return $version;
  391 +}
  392 +
  393 +##
  394 +# dumps section contents to arrays/hashes intended for that purpose.
  395 +#
  396 +sub dump_section {
  397 + my $file = shift;
  398 + my $name = shift;
  399 + my $contents = join "\n", @_;
  400 +
  401 + if ($name =~ m/$type_constant/) {
  402 + $name = $1;
  403 +# print STDERR "constant section '$1' = '$contents'\n";
  404 + $constants{$name} = $contents;
  405 + } elsif ($name =~ m/$type_param/) {
  406 +# print STDERR "parameter def '$1' = '$contents'\n";
  407 + $name = $1;
  408 + $parameterdescs{$name} = $contents;
  409 + $sectcheck = $sectcheck . $name . " ";
  410 + } elsif ($name eq "@\.\.\.") {
  411 +# print STDERR "parameter def '...' = '$contents'\n";
  412 + $name = "...";
  413 + $parameterdescs{$name} = $contents;
  414 + $sectcheck = $sectcheck . $name . " ";
  415 + } else {
  416 +# print STDERR "other section '$name' = '$contents'\n";
  417 + if (defined($sections{$name}) && ($sections{$name} ne "")) {
  418 + print STDERR "Error(${file}:$.): duplicate section name '$name'\n";
  419 + ++$errors;
  420 + }
  421 + $sections{$name} = $contents;
  422 + push @sectionlist, $name;
  423 + }
  424 +}
  425 +
  426 +##
  427 +# dump DOC: section after checking that it should go out
  428 +#
  429 +sub dump_doc_section {
  430 + my $file = shift;
  431 + my $name = shift;
  432 + my $contents = join "\n", @_;
  433 +
  434 + if ($no_doc_sections) {
  435 + return;
  436 + }
  437 +
  438 + if (($function_only == 0) ||
  439 + ( $function_only == 1 && defined($function_table{$name})) ||
  440 + ( $function_only == 2 && !defined($function_table{$name})))
  441 + {
  442 + dump_section($file, $name, $contents);
  443 + output_blockhead({'sectionlist' => \@sectionlist,
  444 + 'sections' => \%sections,
  445 + 'module' => $modulename,
  446 + 'content-only' => ($function_only != 0), });
  447 + }
  448 +}
  449 +
  450 +##
  451 +# output function
  452 +#
  453 +# parameterdescs, a hash.
  454 +# function => "function name"
  455 +# parameterlist => @list of parameters
  456 +# parameterdescs => %parameter descriptions
  457 +# sectionlist => @list of sections
  458 +# sections => %section descriptions
  459 +#
  460 +
  461 +sub output_highlight {
  462 + my $contents = join "\n",@_;
  463 + my $line;
  464 +
  465 +# DEBUG
  466 +# if (!defined $contents) {
  467 +# use Carp;
  468 +# confess "output_highlight got called with no args?\n";
  469 +# }
  470 +
  471 + if ($output_mode eq "html" || $output_mode eq "html5" ||
  472 + $output_mode eq "xml") {
  473 + $contents = local_unescape($contents);
  474 + # convert data read & converted thru xml_escape() into &xyz; format:
  475 + $contents =~ s/\\\\\\/\&/g;
  476 + }
  477 +# print STDERR "contents b4:$contents\n";
  478 + eval $dohighlight;
  479 + die $@ if $@;
  480 +# print STDERR "contents af:$contents\n";
  481 +
  482 +# strip whitespaces when generating html5
  483 + if ($output_mode eq "html5") {
  484 + $contents =~ s/^\s+//;
  485 + $contents =~ s/\s+$//;
  486 + }
  487 + foreach $line (split "\n", $contents) {
  488 + if ($line eq ""){
  489 + print $lineprefix, local_unescape($blankline);
  490 + } else {
  491 + $line =~ s/\\\\\\/\&/g;
  492 + if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
  493 + print "\\&$line";
  494 + } else {
  495 + print $lineprefix, $line;
  496 + }
  497 + }
  498 + print "\n";
  499 + }
  500 +}
  501 +
  502 +# output sections in html
  503 +sub output_section_html(%) {
  504 + my %args = %{$_[0]};
  505 + my $section;
  506 +
  507 + foreach $section (@{$args{'sectionlist'}}) {
  508 + print "<h3>$section</h3>\n";
  509 + print "<blockquote>\n";
  510 + output_highlight($args{'sections'}{$section});
  511 + print "</blockquote>\n";
  512 + }
  513 +}
  514 +
  515 +# output enum in html
  516 +sub output_enum_html(%) {
  517 + my %args = %{$_[0]};
  518 + my ($parameter);
  519 + my $count;
  520 + print "<h2>enum " . $args{'enum'} . "</h2>\n";
  521 +
  522 + print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
  523 + $count = 0;
  524 + foreach $parameter (@{$args{'parameterlist'}}) {
  525 + print " <b>" . $parameter . "</b>";
  526 + if ($count != $#{$args{'parameterlist'}}) {
  527 + $count++;
  528 + print ",\n";
  529 + }
  530 + print "<br>";
  531 + }
  532 + print "};<br>\n";
  533 +
  534 + print "<h3>Constants</h3>\n";
  535 + print "<dl>\n";
  536 + foreach $parameter (@{$args{'parameterlist'}}) {
  537 + print "<dt><b>" . $parameter . "</b>\n";
  538 + print "<dd>";
  539 + output_highlight($args{'parameterdescs'}{$parameter});
  540 + }
  541 + print "</dl>\n";
  542 + output_section_html(@_);
  543 + print "<hr>\n";
  544 +}
  545 +
  546 +# output typedef in html
  547 +sub output_typedef_html(%) {
  548 + my %args = %{$_[0]};
  549 + my ($parameter);
  550 + my $count;
  551 + print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
  552 +
  553 + print "<b>typedef " . $args{'typedef'} . "</b>\n";
  554 + output_section_html(@_);
  555 + print "<hr>\n";
  556 +}
  557 +
  558 +# output struct in html
  559 +sub output_struct_html(%) {
  560 + my %args = %{$_[0]};
  561 + my ($parameter);
  562 +
  563 + print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
  564 + print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
  565 + foreach $parameter (@{$args{'parameterlist'}}) {
  566 + if ($parameter =~ /^#/) {
  567 + print "$parameter<br>\n";
  568 + next;
  569 + }
  570 + my $parameter_name = $parameter;
  571 + $parameter_name =~ s/\[.*//;
  572 +
  573 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  574 + $type = $args{'parametertypes'}{$parameter};
  575 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  576 + # pointer-to-function
  577 + print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
  578 + } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  579 + # bitfield
  580 + print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
  581 + } else {
  582 + print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
  583 + }
  584 + }
  585 + print "};<br>\n";
  586 +
  587 + print "<h3>Members</h3>\n";
  588 + print "<dl>\n";
  589 + foreach $parameter (@{$args{'parameterlist'}}) {
  590 + ($parameter =~ /^#/) && next;
  591 +
  592 + my $parameter_name = $parameter;
  593 + $parameter_name =~ s/\[.*//;
  594 +
  595 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  596 + print "<dt><b>" . $parameter . "</b>\n";
  597 + print "<dd>";
  598 + output_highlight($args{'parameterdescs'}{$parameter_name});
  599 + }
  600 + print "</dl>\n";
  601 + output_section_html(@_);
  602 + print "<hr>\n";
  603 +}
  604 +
  605 +# output function in html
  606 +sub output_function_html(%) {
  607 + my %args = %{$_[0]};
  608 + my ($parameter, $section);
  609 + my $count;
  610 +
  611 + print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
  612 + print "<i>" . $args{'functiontype'} . "</i>\n";
  613 + print "<b>" . $args{'function'} . "</b>\n";
  614 + print "(";
  615 + $count = 0;
  616 + foreach $parameter (@{$args{'parameterlist'}}) {
  617 + $type = $args{'parametertypes'}{$parameter};
  618 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  619 + # pointer-to-function
  620 + print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
  621 + } else {
  622 + print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
  623 + }
  624 + if ($count != $#{$args{'parameterlist'}}) {
  625 + $count++;
  626 + print ",\n";
  627 + }
  628 + }
  629 + print ")\n";
  630 +
  631 + print "<h3>Arguments</h3>\n";
  632 + print "<dl>\n";
  633 + foreach $parameter (@{$args{'parameterlist'}}) {
  634 + my $parameter_name = $parameter;
  635 + $parameter_name =~ s/\[.*//;
  636 +
  637 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  638 + print "<dt><b>" . $parameter . "</b>\n";
  639 + print "<dd>";
  640 + output_highlight($args{'parameterdescs'}{$parameter_name});
  641 + }
  642 + print "</dl>\n";
  643 + output_section_html(@_);
  644 + print "<hr>\n";
  645 +}
  646 +
  647 +# output DOC: block header in html
  648 +sub output_blockhead_html(%) {
  649 + my %args = %{$_[0]};
  650 + my ($parameter, $section);
  651 + my $count;
  652 +
  653 + foreach $section (@{$args{'sectionlist'}}) {
  654 + print "<h3>$section</h3>\n";
  655 + print "<ul>\n";
  656 + output_highlight($args{'sections'}{$section});
  657 + print "</ul>\n";
  658 + }
  659 + print "<hr>\n";
  660 +}
  661 +
  662 +# output sections in html5
  663 +sub output_section_html5(%) {
  664 + my %args = %{$_[0]};
  665 + my $section;
  666 +
  667 + foreach $section (@{$args{'sectionlist'}}) {
  668 + print "<section>\n";
  669 + print "<h1>$section</h1>\n";
  670 + print "<p>\n";
  671 + output_highlight($args{'sections'}{$section});
  672 + print "</p>\n";
  673 + print "</section>\n";
  674 + }
  675 +}
  676 +
  677 +# output enum in html5
  678 +sub output_enum_html5(%) {
  679 + my %args = %{$_[0]};
  680 + my ($parameter);
  681 + my $count;
  682 + my $html5id;
  683 +
  684 + $html5id = $args{'enum'};
  685 + $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
  686 + print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
  687 + print "<h1>enum " . $args{'enum'} . "</h1>\n";
  688 + print "<ol class=\"code\">\n";
  689 + print "<li>";
  690 + print "<span class=\"keyword\">enum</span> ";
  691 + print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
  692 + print "</li>\n";
  693 + $count = 0;
  694 + foreach $parameter (@{$args{'parameterlist'}}) {
  695 + print "<li class=\"indent\">";
  696 + print "<span class=\"param\">" . $parameter . "</span>";
  697 + if ($count != $#{$args{'parameterlist'}}) {
  698 + $count++;
  699 + print ",";
  700 + }
  701 + print "</li>\n";
  702 + }
  703 + print "<li>};</li>\n";
  704 + print "</ol>\n";
  705 +
  706 + print "<section>\n";
  707 + print "<h1>Constants</h1>\n";
  708 + print "<dl>\n";
  709 + foreach $parameter (@{$args{'parameterlist'}}) {
  710 + print "<dt>" . $parameter . "</dt>\n";
  711 + print "<dd>";
  712 + output_highlight($args{'parameterdescs'}{$parameter});
  713 + print "</dd>\n";
  714 + }
  715 + print "</dl>\n";
  716 + print "</section>\n";
  717 + output_section_html5(@_);
  718 + print "</article>\n";
  719 +}
  720 +
  721 +# output typedef in html5
  722 +sub output_typedef_html5(%) {
  723 + my %args = %{$_[0]};
  724 + my ($parameter);
  725 + my $count;
  726 + my $html5id;
  727 +
  728 + $html5id = $args{'typedef'};
  729 + $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
  730 + print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
  731 + print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
  732 +
  733 + print "<ol class=\"code\">\n";
  734 + print "<li>";
  735 + print "<span class=\"keyword\">typedef</span> ";
  736 + print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
  737 + print "</li>\n";
  738 + print "</ol>\n";
  739 + output_section_html5(@_);
  740 + print "</article>\n";
  741 +}
  742 +
  743 +# output struct in html5
  744 +sub output_struct_html5(%) {
  745 + my %args = %{$_[0]};
  746 + my ($parameter);
  747 + my $html5id;
  748 +
  749 + $html5id = $args{'struct'};
  750 + $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
  751 + print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
  752 + print "<hgroup>\n";
  753 + print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
  754 + print "<h2>". $args{'purpose'} . "</h2>\n";
  755 + print "</hgroup>\n";
  756 + print "<ol class=\"code\">\n";
  757 + print "<li>";
  758 + print "<span class=\"type\">" . $args{'type'} . "</span> ";
  759 + print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
  760 + print "</li>\n";
  761 + foreach $parameter (@{$args{'parameterlist'}}) {
  762 + print "<li class=\"indent\">";
  763 + if ($parameter =~ /^#/) {
  764 + print "<span class=\"param\">" . $parameter ."</span>\n";
  765 + print "</li>\n";
  766 + next;
  767 + }
  768 + my $parameter_name = $parameter;
  769 + $parameter_name =~ s/\[.*//;
  770 +
  771 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  772 + $type = $args{'parametertypes'}{$parameter};
  773 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  774 + # pointer-to-function
  775 + print "<span class=\"type\">$1</span> ";
  776 + print "<span class=\"param\">$parameter</span>";
  777 + print "<span class=\"type\">)</span> ";
  778 + print "(<span class=\"args\">$2</span>);";
  779 + } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  780 + # bitfield
  781 + print "<span class=\"type\">$1</span> ";
  782 + print "<span class=\"param\">$parameter</span>";
  783 + print "<span class=\"bits\">$2</span>;";
  784 + } else {
  785 + print "<span class=\"type\">$type</span> ";
  786 + print "<span class=\"param\">$parameter</span>;";
  787 + }
  788 + print "</li>\n";
  789 + }
  790 + print "<li>};</li>\n";
  791 + print "</ol>\n";
  792 +
  793 + print "<section>\n";
  794 + print "<h1>Members</h1>\n";
  795 + print "<dl>\n";
  796 + foreach $parameter (@{$args{'parameterlist'}}) {
  797 + ($parameter =~ /^#/) && next;
  798 +
  799 + my $parameter_name = $parameter;
  800 + $parameter_name =~ s/\[.*//;
  801 +
  802 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  803 + print "<dt>" . $parameter . "</dt>\n";
  804 + print "<dd>";
  805 + output_highlight($args{'parameterdescs'}{$parameter_name});
  806 + print "</dd>\n";
  807 + }
  808 + print "</dl>\n";
  809 + print "</section>\n";
  810 + output_section_html5(@_);
  811 + print "</article>\n";
  812 +}
  813 +
  814 +# output function in html5
  815 +sub output_function_html5(%) {
  816 + my %args = %{$_[0]};
  817 + my ($parameter, $section);
  818 + my $count;
  819 + my $html5id;
  820 +
  821 + $html5id = $args{'function'};
  822 + $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
  823 + print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
  824 + print "<hgroup>\n";
  825 + print "<h1>" . $args{'function'} . "</h1>";
  826 + print "<h2>" . $args{'purpose'} . "</h2>\n";
  827 + print "</hgroup>\n";
  828 + print "<ol class=\"code\">\n";
  829 + print "<li>";
  830 + print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
  831 + print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
  832 + print "</li>";
  833 + $count = 0;
  834 + foreach $parameter (@{$args{'parameterlist'}}) {
  835 + print "<li class=\"indent\">";
  836 + $type = $args{'parametertypes'}{$parameter};
  837 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  838 + # pointer-to-function
  839 + print "<span class=\"type\">$1</span> ";
  840 + print "<span class=\"param\">$parameter</span>";
  841 + print "<span class=\"type\">)</span> ";
  842 + print "(<span class=\"args\">$2</span>)";
  843 + } else {
  844 + print "<span class=\"type\">$type</span> ";
  845 + print "<span class=\"param\">$parameter</span>";
  846 + }
  847 + if ($count != $#{$args{'parameterlist'}}) {
  848 + $count++;
  849 + print ",";
  850 + }
  851 + print "</li>\n";
  852 + }
  853 + print "<li>)</li>\n";
  854 + print "</ol>\n";
  855 +
  856 + print "<section>\n";
  857 + print "<h1>Arguments</h1>\n";
  858 + print "<p>\n";
  859 + print "<dl>\n";
  860 + foreach $parameter (@{$args{'parameterlist'}}) {
  861 + my $parameter_name = $parameter;
  862 + $parameter_name =~ s/\[.*//;
  863 +
  864 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  865 + print "<dt>" . $parameter . "</dt>\n";
  866 + print "<dd>";
  867 + output_highlight($args{'parameterdescs'}{$parameter_name});
  868 + print "</dd>\n";
  869 + }
  870 + print "</dl>\n";
  871 + print "</section>\n";
  872 + output_section_html5(@_);
  873 + print "</article>\n";
  874 +}
  875 +
  876 +# output DOC: block header in html5
  877 +sub output_blockhead_html5(%) {
  878 + my %args = %{$_[0]};
  879 + my ($parameter, $section);
  880 + my $count;
  881 + my $html5id;
  882 +
  883 + foreach $section (@{$args{'sectionlist'}}) {
  884 + $html5id = $section;
  885 + $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
  886 + print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
  887 + print "<h1>$section</h1>\n";
  888 + print "<p>\n";
  889 + output_highlight($args{'sections'}{$section});
  890 + print "</p>\n";
  891 + }
  892 + print "</article>\n";
  893 +}
  894 +
  895 +sub output_section_xml(%) {
  896 + my %args = %{$_[0]};
  897 + my $section;
  898 + # print out each section
  899 + $lineprefix=" ";
  900 + foreach $section (@{$args{'sectionlist'}}) {
  901 + print "<refsect1>\n";
  902 + print "<title>$section</title>\n";
  903 + if ($section =~ m/EXAMPLE/i) {
  904 + print "<informalexample><programlisting>\n";
  905 + } else {
  906 + print "<para>\n";
  907 + }
  908 + output_highlight($args{'sections'}{$section});
  909 + if ($section =~ m/EXAMPLE/i) {
  910 + print "</programlisting></informalexample>\n";
  911 + } else {
  912 + print "</para>\n";
  913 + }
  914 + print "</refsect1>\n";
  915 + }
  916 +}
  917 +
  918 +# output function in XML DocBook
  919 +sub output_function_xml(%) {
  920 + my %args = %{$_[0]};
  921 + my ($parameter, $section);
  922 + my $count;
  923 + my $id;
  924 +
  925 + $id = "API-" . $args{'function'};
  926 + $id =~ s/[^A-Za-z0-9]/-/g;
  927 +
  928 + print "<refentry id=\"$id\">\n";
  929 + print "<refentryinfo>\n";
  930 + print " <title>U-BOOT</title>\n";
  931 + print " <productname>Bootloader Hackers Manual</productname>\n";
  932 + print " <date>$man_date</date>\n";
  933 + print "</refentryinfo>\n";
  934 + print "<refmeta>\n";
  935 + print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
  936 + print " <manvolnum>9</manvolnum>\n";
  937 + print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
  938 + print "</refmeta>\n";
  939 + print "<refnamediv>\n";
  940 + print " <refname>" . $args{'function'} . "</refname>\n";
  941 + print " <refpurpose>\n";
  942 + print " ";
  943 + output_highlight ($args{'purpose'});
  944 + print " </refpurpose>\n";
  945 + print "</refnamediv>\n";
  946 +
  947 + print "<refsynopsisdiv>\n";
  948 + print " <title>Synopsis</title>\n";
  949 + print " <funcsynopsis><funcprototype>\n";
  950 + print " <funcdef>" . $args{'functiontype'} . " ";
  951 + print "<function>" . $args{'function'} . " </function></funcdef>\n";
  952 +
  953 + $count = 0;
  954 + if ($#{$args{'parameterlist'}} >= 0) {
  955 + foreach $parameter (@{$args{'parameterlist'}}) {
  956 + $type = $args{'parametertypes'}{$parameter};
  957 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  958 + # pointer-to-function
  959 + print " <paramdef>$1<parameter>$parameter</parameter>)\n";
  960 + print " <funcparams>$2</funcparams></paramdef>\n";
  961 + } else {
  962 + print " <paramdef>" . $type;
  963 + print " <parameter>$parameter</parameter></paramdef>\n";
  964 + }
  965 + }
  966 + } else {
  967 + print " <void/>\n";
  968 + }
  969 + print " </funcprototype></funcsynopsis>\n";
  970 + print "</refsynopsisdiv>\n";
  971 +
  972 + # print parameters
  973 + print "<refsect1>\n <title>Arguments</title>\n";
  974 + if ($#{$args{'parameterlist'}} >= 0) {
  975 + print " <variablelist>\n";
  976 + foreach $parameter (@{$args{'parameterlist'}}) {
  977 + my $parameter_name = $parameter;
  978 + $parameter_name =~ s/\[.*//;
  979 +
  980 + print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
  981 + print " <listitem>\n <para>\n";
  982 + $lineprefix=" ";
  983 + output_highlight($args{'parameterdescs'}{$parameter_name});
  984 + print " </para>\n </listitem>\n </varlistentry>\n";
  985 + }
  986 + print " </variablelist>\n";
  987 + } else {
  988 + print " <para>\n None\n </para>\n";
  989 + }
  990 + print "</refsect1>\n";
  991 +
  992 + output_section_xml(@_);
  993 + print "</refentry>\n\n";
  994 +}
  995 +
  996 +# output struct in XML DocBook
  997 +sub output_struct_xml(%) {
  998 + my %args = %{$_[0]};
  999 + my ($parameter, $section);
  1000 + my $id;
  1001 +
  1002 + $id = "API-struct-" . $args{'struct'};
  1003 + $id =~ s/[^A-Za-z0-9]/-/g;
  1004 +
  1005 + print "<refentry id=\"$id\">\n";
  1006 + print "<refentryinfo>\n";
  1007 + print " <title>U-BOOT</title>\n";
  1008 + print " <productname>Bootloader Hackers Manual</productname>\n";
  1009 + print " <date>$man_date</date>\n";
  1010 + print "</refentryinfo>\n";
  1011 + print "<refmeta>\n";
  1012 + print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
  1013 + print " <manvolnum>9</manvolnum>\n";
  1014 + print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
  1015 + print "</refmeta>\n";
  1016 + print "<refnamediv>\n";
  1017 + print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
  1018 + print " <refpurpose>\n";
  1019 + print " ";
  1020 + output_highlight ($args{'purpose'});
  1021 + print " </refpurpose>\n";
  1022 + print "</refnamediv>\n";
  1023 +
  1024 + print "<refsynopsisdiv>\n";
  1025 + print " <title>Synopsis</title>\n";
  1026 + print " <programlisting>\n";
  1027 + print $args{'type'} . " " . $args{'struct'} . " {\n";
  1028 + foreach $parameter (@{$args{'parameterlist'}}) {
  1029 + if ($parameter =~ /^#/) {
  1030 + my $prm = $parameter;
  1031 + # convert data read & converted thru xml_escape() into &xyz; format:
  1032 + # This allows us to have #define macros interspersed in a struct.
  1033 + $prm =~ s/\\\\\\/\&/g;
  1034 + print "$prm\n";
  1035 + next;
  1036 + }
  1037 +
  1038 + my $parameter_name = $parameter;
  1039 + $parameter_name =~ s/\[.*//;
  1040 +
  1041 + defined($args{'parameterdescs'}{$parameter_name}) || next;
  1042 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1043 + $type = $args{'parametertypes'}{$parameter};
  1044 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1045 + # pointer-to-function
  1046 + print " $1 $parameter) ($2);\n";
  1047 + } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  1048 + # bitfield
  1049 + print " $1 $parameter$2;\n";
  1050 + } else {
  1051 + print " " . $type . " " . $parameter . ";\n";
  1052 + }
  1053 + }
  1054 + print "};";
  1055 + print " </programlisting>\n";
  1056 + print "</refsynopsisdiv>\n";
  1057 +
  1058 + print " <refsect1>\n";
  1059 + print " <title>Members</title>\n";
  1060 +
  1061 + if ($#{$args{'parameterlist'}} >= 0) {
  1062 + print " <variablelist>\n";
  1063 + foreach $parameter (@{$args{'parameterlist'}}) {
  1064 + ($parameter =~ /^#/) && next;
  1065 +
  1066 + my $parameter_name = $parameter;
  1067 + $parameter_name =~ s/\[.*//;
  1068 +
  1069 + defined($args{'parameterdescs'}{$parameter_name}) || next;
  1070 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1071 + print " <varlistentry>";
  1072 + print " <term>$parameter</term>\n";
  1073 + print " <listitem><para>\n";
  1074 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1075 + print " </para></listitem>\n";
  1076 + print " </varlistentry>\n";
  1077 + }
  1078 + print " </variablelist>\n";
  1079 + } else {
  1080 + print " <para>\n None\n </para>\n";
  1081 + }
  1082 + print " </refsect1>\n";
  1083 +
  1084 + output_section_xml(@_);
  1085 +
  1086 + print "</refentry>\n\n";
  1087 +}
  1088 +
  1089 +# output enum in XML DocBook
  1090 +sub output_enum_xml(%) {
  1091 + my %args = %{$_[0]};
  1092 + my ($parameter, $section);
  1093 + my $count;
  1094 + my $id;
  1095 +
  1096 + $id = "API-enum-" . $args{'enum'};
  1097 + $id =~ s/[^A-Za-z0-9]/-/g;
  1098 +
  1099 + print "<refentry id=\"$id\">\n";
  1100 + print "<refentryinfo>\n";
  1101 + print " <title>U-BOOT</title>\n";
  1102 + print " <productname>Bootloader Hackers Manual</productname>\n";
  1103 + print " <date>$man_date</date>\n";
  1104 + print "</refentryinfo>\n";
  1105 + print "<refmeta>\n";
  1106 + print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
  1107 + print " <manvolnum>9</manvolnum>\n";
  1108 + print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
  1109 + print "</refmeta>\n";
  1110 + print "<refnamediv>\n";
  1111 + print " <refname>enum " . $args{'enum'} . "</refname>\n";
  1112 + print " <refpurpose>\n";
  1113 + print " ";
  1114 + output_highlight ($args{'purpose'});
  1115 + print " </refpurpose>\n";
  1116 + print "</refnamediv>\n";
  1117 +
  1118 + print "<refsynopsisdiv>\n";
  1119 + print " <title>Synopsis</title>\n";
  1120 + print " <programlisting>\n";
  1121 + print "enum " . $args{'enum'} . " {\n";
  1122 + $count = 0;
  1123 + foreach $parameter (@{$args{'parameterlist'}}) {
  1124 + print " $parameter";
  1125 + if ($count != $#{$args{'parameterlist'}}) {
  1126 + $count++;
  1127 + print ",";
  1128 + }
  1129 + print "\n";
  1130 + }
  1131 + print "};";
  1132 + print " </programlisting>\n";
  1133 + print "</refsynopsisdiv>\n";
  1134 +
  1135 + print "<refsect1>\n";
  1136 + print " <title>Constants</title>\n";
  1137 + print " <variablelist>\n";
  1138 + foreach $parameter (@{$args{'parameterlist'}}) {
  1139 + my $parameter_name = $parameter;
  1140 + $parameter_name =~ s/\[.*//;
  1141 +
  1142 + print " <varlistentry>";
  1143 + print " <term>$parameter</term>\n";
  1144 + print " <listitem><para>\n";
  1145 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1146 + print " </para></listitem>\n";
  1147 + print " </varlistentry>\n";
  1148 + }
  1149 + print " </variablelist>\n";
  1150 + print "</refsect1>\n";
  1151 +
  1152 + output_section_xml(@_);
  1153 +
  1154 + print "</refentry>\n\n";
  1155 +}
  1156 +
  1157 +# output typedef in XML DocBook
  1158 +sub output_typedef_xml(%) {
  1159 + my %args = %{$_[0]};
  1160 + my ($parameter, $section);
  1161 + my $id;
  1162 +
  1163 + $id = "API-typedef-" . $args{'typedef'};
  1164 + $id =~ s/[^A-Za-z0-9]/-/g;
  1165 +
  1166 + print "<refentry id=\"$id\">\n";
  1167 + print "<refentryinfo>\n";
  1168 + print " <title>U-BOOT</title>\n";
  1169 + print " <productname>Bootloader Hackers Manual</productname>\n";
  1170 + print " <date>$man_date</date>\n";
  1171 + print "</refentryinfo>\n";
  1172 + print "<refmeta>\n";
  1173 + print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
  1174 + print " <manvolnum>9</manvolnum>\n";
  1175 + print "</refmeta>\n";
  1176 + print "<refnamediv>\n";
  1177 + print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
  1178 + print " <refpurpose>\n";
  1179 + print " ";
  1180 + output_highlight ($args{'purpose'});
  1181 + print " </refpurpose>\n";
  1182 + print "</refnamediv>\n";
  1183 +
  1184 + print "<refsynopsisdiv>\n";
  1185 + print " <title>Synopsis</title>\n";
  1186 + print " <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
  1187 + print "</refsynopsisdiv>\n";
  1188 +
  1189 + output_section_xml(@_);
  1190 +
  1191 + print "</refentry>\n\n";
  1192 +}
  1193 +
  1194 +# output in XML DocBook
  1195 +sub output_blockhead_xml(%) {
  1196 + my %args = %{$_[0]};
  1197 + my ($parameter, $section);
  1198 + my $count;
  1199 +
  1200 + my $id = $args{'module'};
  1201 + $id =~ s/[^A-Za-z0-9]/-/g;
  1202 +
  1203 + # print out each section
  1204 + $lineprefix=" ";
  1205 + foreach $section (@{$args{'sectionlist'}}) {
  1206 + if (!$args{'content-only'}) {
  1207 + print "<refsect1>\n <title>$section</title>\n";
  1208 + }
  1209 + if ($section =~ m/EXAMPLE/i) {
  1210 + print "<example><para>\n";
  1211 + } else {
  1212 + print "<para>\n";
  1213 + }
  1214 + output_highlight($args{'sections'}{$section});
  1215 + if ($section =~ m/EXAMPLE/i) {
  1216 + print "</para></example>\n";
  1217 + } else {
  1218 + print "</para>";
  1219 + }
  1220 + if (!$args{'content-only'}) {
  1221 + print "\n</refsect1>\n";
  1222 + }
  1223 + }
  1224 +
  1225 + print "\n\n";
  1226 +}
  1227 +
  1228 +# output in XML DocBook
  1229 +sub output_function_gnome {
  1230 + my %args = %{$_[0]};
  1231 + my ($parameter, $section);
  1232 + my $count;
  1233 + my $id;
  1234 +
  1235 + $id = $args{'module'} . "-" . $args{'function'};
  1236 + $id =~ s/[^A-Za-z0-9]/-/g;
  1237 +
  1238 + print "<sect2>\n";
  1239 + print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
  1240 +
  1241 + print " <funcsynopsis>\n";
  1242 + print " <funcdef>" . $args{'functiontype'} . " ";
  1243 + print "<function>" . $args{'function'} . " ";
  1244 + print "</function></funcdef>\n";
  1245 +
  1246 + $count = 0;
  1247 + if ($#{$args{'parameterlist'}} >= 0) {
  1248 + foreach $parameter (@{$args{'parameterlist'}}) {
  1249 + $type = $args{'parametertypes'}{$parameter};
  1250 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1251 + # pointer-to-function
  1252 + print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
  1253 + print " <funcparams>$2</funcparams></paramdef>\n";
  1254 + } else {
  1255 + print " <paramdef>" . $type;
  1256 + print " <parameter>$parameter</parameter></paramdef>\n";
  1257 + }
  1258 + }
  1259 + } else {
  1260 + print " <void>\n";
  1261 + }
  1262 + print " </funcsynopsis>\n";
  1263 + if ($#{$args{'parameterlist'}} >= 0) {
  1264 + print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
  1265 + print "<tgroup cols=\"2\">\n";
  1266 + print "<colspec colwidth=\"2*\">\n";
  1267 + print "<colspec colwidth=\"8*\">\n";
  1268 + print "<tbody>\n";
  1269 + foreach $parameter (@{$args{'parameterlist'}}) {
  1270 + my $parameter_name = $parameter;
  1271 + $parameter_name =~ s/\[.*//;
  1272 +
  1273 + print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
  1274 + print " <entry>\n";
  1275 + $lineprefix=" ";
  1276 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1277 + print " </entry></row>\n";
  1278 + }
  1279 + print " </tbody></tgroup></informaltable>\n";
  1280 + } else {
  1281 + print " <para>\n None\n </para>\n";
  1282 + }
  1283 +
  1284 + # print out each section
  1285 + $lineprefix=" ";
  1286 + foreach $section (@{$args{'sectionlist'}}) {
  1287 + print "<simplesect>\n <title>$section</title>\n";
  1288 + if ($section =~ m/EXAMPLE/i) {
  1289 + print "<example><programlisting>\n";
  1290 + } else {
  1291 + }
  1292 + print "<para>\n";
  1293 + output_highlight($args{'sections'}{$section});
  1294 + print "</para>\n";
  1295 + if ($section =~ m/EXAMPLE/i) {
  1296 + print "</programlisting></example>\n";
  1297 + } else {
  1298 + }
  1299 + print " </simplesect>\n";
  1300 + }
  1301 +
  1302 + print "</sect2>\n\n";
  1303 +}
  1304 +
  1305 +##
  1306 +# output function in man
  1307 +sub output_function_man(%) {
  1308 + my %args = %{$_[0]};
  1309 + my ($parameter, $section);
  1310 + my $count;
  1311 +
  1312 + print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Bootloader Hacker's Manual\" U-BOOT\n";
  1313 +
  1314 + print ".SH NAME\n";
  1315 + print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
  1316 +
  1317 + print ".SH SYNOPSIS\n";
  1318 + if ($args{'functiontype'} ne "") {
  1319 + print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
  1320 + } else {
  1321 + print ".B \"" . $args{'function'} . "\n";
  1322 + }
  1323 + $count = 0;
  1324 + my $parenth = "(";
  1325 + my $post = ",";
  1326 + foreach my $parameter (@{$args{'parameterlist'}}) {
  1327 + if ($count == $#{$args{'parameterlist'}}) {
  1328 + $post = ");";
  1329 + }
  1330 + $type = $args{'parametertypes'}{$parameter};
  1331 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1332 + # pointer-to-function
  1333 + print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
  1334 + } else {
  1335 + $type =~ s/([^\*])$/$1 /;
  1336 + print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
  1337 + }
  1338 + $count++;
  1339 + $parenth = "";
  1340 + }
  1341 +
  1342 + print ".SH ARGUMENTS\n";
  1343 + foreach $parameter (@{$args{'parameterlist'}}) {
  1344 + my $parameter_name = $parameter;
  1345 + $parameter_name =~ s/\[.*//;
  1346 +
  1347 + print ".IP \"" . $parameter . "\" 12\n";
  1348 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1349 + }
  1350 + foreach $section (@{$args{'sectionlist'}}) {
  1351 + print ".SH \"", uc $section, "\"\n";
  1352 + output_highlight($args{'sections'}{$section});
  1353 + }
  1354 +}
  1355 +
  1356 +##
  1357 +# output enum in man
  1358 +sub output_enum_man(%) {
  1359 + my %args = %{$_[0]};
  1360 + my ($parameter, $section);
  1361 + my $count;
  1362 +
  1363 + print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
  1364 +
  1365 + print ".SH NAME\n";
  1366 + print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
  1367 +
  1368 + print ".SH SYNOPSIS\n";
  1369 + print "enum " . $args{'enum'} . " {\n";
  1370 + $count = 0;
  1371 + foreach my $parameter (@{$args{'parameterlist'}}) {
  1372 + print ".br\n.BI \" $parameter\"\n";
  1373 + if ($count == $#{$args{'parameterlist'}}) {
  1374 + print "\n};\n";
  1375 + last;
  1376 + }
  1377 + else {
  1378 + print ", \n.br\n";
  1379 + }
  1380 + $count++;
  1381 + }
  1382 +
  1383 + print ".SH Constants\n";
  1384 + foreach $parameter (@{$args{'parameterlist'}}) {
  1385 + my $parameter_name = $parameter;
  1386 + $parameter_name =~ s/\[.*//;
  1387 +
  1388 + print ".IP \"" . $parameter . "\" 12\n";
  1389 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1390 + }
  1391 + foreach $section (@{$args{'sectionlist'}}) {
  1392 + print ".SH \"$section\"\n";
  1393 + output_highlight($args{'sections'}{$section});
  1394 + }
  1395 +}
  1396 +
  1397 +##
  1398 +# output struct in man
  1399 +sub output_struct_man(%) {
  1400 + my %args = %{$_[0]};
  1401 + my ($parameter, $section);
  1402 +
  1403 + print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" U-BOOT\n";
  1404 +
  1405 + print ".SH NAME\n";
  1406 + print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
  1407 +
  1408 + print ".SH SYNOPSIS\n";
  1409 + print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
  1410 +
  1411 + foreach my $parameter (@{$args{'parameterlist'}}) {
  1412 + if ($parameter =~ /^#/) {
  1413 + print ".BI \"$parameter\"\n.br\n";
  1414 + next;
  1415 + }
  1416 + my $parameter_name = $parameter;
  1417 + $parameter_name =~ s/\[.*//;
  1418 +
  1419 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1420 + $type = $args{'parametertypes'}{$parameter};
  1421 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1422 + # pointer-to-function
  1423 + print ".BI \" " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
  1424 + } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  1425 + # bitfield
  1426 + print ".BI \" " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
  1427 + } else {
  1428 + $type =~ s/([^\*])$/$1 /;
  1429 + print ".BI \" " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
  1430 + }
  1431 + print "\n.br\n";
  1432 + }
  1433 + print "};\n.br\n";
  1434 +
  1435 + print ".SH Members\n";
  1436 + foreach $parameter (@{$args{'parameterlist'}}) {
  1437 + ($parameter =~ /^#/) && next;
  1438 +
  1439 + my $parameter_name = $parameter;
  1440 + $parameter_name =~ s/\[.*//;
  1441 +
  1442 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1443 + print ".IP \"" . $parameter . "\" 12\n";
  1444 + output_highlight($args{'parameterdescs'}{$parameter_name});
  1445 + }
  1446 + foreach $section (@{$args{'sectionlist'}}) {
  1447 + print ".SH \"$section\"\n";
  1448 + output_highlight($args{'sections'}{$section});
  1449 + }
  1450 +}
  1451 +
  1452 +##
  1453 +# output typedef in man
  1454 +sub output_typedef_man(%) {
  1455 + my %args = %{$_[0]};
  1456 + my ($parameter, $section);
  1457 +
  1458 + print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
  1459 +
  1460 + print ".SH NAME\n";
  1461 + print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
  1462 +
  1463 + foreach $section (@{$args{'sectionlist'}}) {
  1464 + print ".SH \"$section\"\n";
  1465 + output_highlight($args{'sections'}{$section});
  1466 + }
  1467 +}
  1468 +
  1469 +sub output_blockhead_man(%) {
  1470 + my %args = %{$_[0]};
  1471 + my ($parameter, $section);
  1472 + my $count;
  1473 +
  1474 + print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
  1475 +
  1476 + foreach $section (@{$args{'sectionlist'}}) {
  1477 + print ".SH \"$section\"\n";
  1478 + output_highlight($args{'sections'}{$section});
  1479 + }
  1480 +}
  1481 +
  1482 +##
  1483 +# output in text
  1484 +sub output_function_text(%) {
  1485 + my %args = %{$_[0]};
  1486 + my ($parameter, $section);
  1487 + my $start;
  1488 +
  1489 + print "Name:\n\n";
  1490 + print $args{'function'} . " - " . $args{'purpose'} . "\n";
  1491 +
  1492 + print "\nSynopsis:\n\n";
  1493 + if ($args{'functiontype'} ne "") {
  1494 + $start = $args{'functiontype'} . " " . $args{'function'} . " (";
  1495 + } else {
  1496 + $start = $args{'function'} . " (";
  1497 + }
  1498 + print $start;
  1499 +
  1500 + my $count = 0;
  1501 + foreach my $parameter (@{$args{'parameterlist'}}) {
  1502 + $type = $args{'parametertypes'}{$parameter};
  1503 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1504 + # pointer-to-function
  1505 + print $1 . $parameter . ") (" . $2;
  1506 + } else {
  1507 + print $type . " " . $parameter;
  1508 + }
  1509 + if ($count != $#{$args{'parameterlist'}}) {
  1510 + $count++;
  1511 + print ",\n";
  1512 + print " " x length($start);
  1513 + } else {
  1514 + print ");\n\n";
  1515 + }
  1516 + }
  1517 +
  1518 + print "Arguments:\n\n";
  1519 + foreach $parameter (@{$args{'parameterlist'}}) {
  1520 + my $parameter_name = $parameter;
  1521 + $parameter_name =~ s/\[.*//;
  1522 +
  1523 + print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
  1524 + }
  1525 + output_section_text(@_);
  1526 +}
  1527 +
  1528 +#output sections in text
  1529 +sub output_section_text(%) {
  1530 + my %args = %{$_[0]};
  1531 + my $section;
  1532 +
  1533 + print "\n";
  1534 + foreach $section (@{$args{'sectionlist'}}) {
  1535 + print "$section:\n\n";
  1536 + output_highlight($args{'sections'}{$section});
  1537 + }
  1538 + print "\n\n";
  1539 +}
  1540 +
  1541 +# output enum in text
  1542 +sub output_enum_text(%) {
  1543 + my %args = %{$_[0]};
  1544 + my ($parameter);
  1545 + my $count;
  1546 + print "Enum:\n\n";
  1547 +
  1548 + print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
  1549 + print "enum " . $args{'enum'} . " {\n";
  1550 + $count = 0;
  1551 + foreach $parameter (@{$args{'parameterlist'}}) {
  1552 + print "\t$parameter";
  1553 + if ($count != $#{$args{'parameterlist'}}) {
  1554 + $count++;
  1555 + print ",";
  1556 + }
  1557 + print "\n";
  1558 + }
  1559 + print "};\n\n";
  1560 +
  1561 + print "Constants:\n\n";
  1562 + foreach $parameter (@{$args{'parameterlist'}}) {
  1563 + print "$parameter\n\t";
  1564 + print $args{'parameterdescs'}{$parameter} . "\n";
  1565 + }
  1566 +
  1567 + output_section_text(@_);
  1568 +}
  1569 +
  1570 +# output typedef in text
  1571 +sub output_typedef_text(%) {
  1572 + my %args = %{$_[0]};
  1573 + my ($parameter);
  1574 + my $count;
  1575 + print "Typedef:\n\n";
  1576 +
  1577 + print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
  1578 + output_section_text(@_);
  1579 +}
  1580 +
  1581 +# output struct as text
  1582 +sub output_struct_text(%) {
  1583 + my %args = %{$_[0]};
  1584 + my ($parameter);
  1585 +
  1586 + print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
  1587 + print $args{'type'} . " " . $args{'struct'} . " {\n";
  1588 + foreach $parameter (@{$args{'parameterlist'}}) {
  1589 + if ($parameter =~ /^#/) {
  1590 + print "$parameter\n";
  1591 + next;
  1592 + }
  1593 +
  1594 + my $parameter_name = $parameter;
  1595 + $parameter_name =~ s/\[.*//;
  1596 +
  1597 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1598 + $type = $args{'parametertypes'}{$parameter};
  1599 + if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  1600 + # pointer-to-function
  1601 + print "\t$1 $parameter) ($2);\n";
  1602 + } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  1603 + # bitfield
  1604 + print "\t$1 $parameter$2;\n";
  1605 + } else {
  1606 + print "\t" . $type . " " . $parameter . ";\n";
  1607 + }
  1608 + }
  1609 + print "};\n\n";
  1610 +
  1611 + print "Members:\n\n";
  1612 + foreach $parameter (@{$args{'parameterlist'}}) {
  1613 + ($parameter =~ /^#/) && next;
  1614 +
  1615 + my $parameter_name = $parameter;
  1616 + $parameter_name =~ s/\[.*//;
  1617 +
  1618 + ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
  1619 + print "$parameter\n\t";
  1620 + print $args{'parameterdescs'}{$parameter_name} . "\n";
  1621 + }
  1622 + print "\n";
  1623 + output_section_text(@_);
  1624 +}
  1625 +
  1626 +sub output_blockhead_text(%) {
  1627 + my %args = %{$_[0]};
  1628 + my ($parameter, $section);
  1629 +
  1630 + foreach $section (@{$args{'sectionlist'}}) {
  1631 + print " $section:\n";
  1632 + print " -> ";
  1633 + output_highlight($args{'sections'}{$section});
  1634 + }
  1635 +}
  1636 +
  1637 +## list mode output functions
  1638 +
  1639 +sub output_function_list(%) {
  1640 + my %args = %{$_[0]};
  1641 +
  1642 + print $args{'function'} . "\n";
  1643 +}
  1644 +
  1645 +# output enum in list
  1646 +sub output_enum_list(%) {
  1647 + my %args = %{$_[0]};
  1648 + print $args{'enum'} . "\n";
  1649 +}
  1650 +
  1651 +# output typedef in list
  1652 +sub output_typedef_list(%) {
  1653 + my %args = %{$_[0]};
  1654 + print $args{'typedef'} . "\n";
  1655 +}
  1656 +
  1657 +# output struct as list
  1658 +sub output_struct_list(%) {
  1659 + my %args = %{$_[0]};
  1660 +
  1661 + print $args{'struct'} . "\n";
  1662 +}
  1663 +
  1664 +sub output_blockhead_list(%) {
  1665 + my %args = %{$_[0]};
  1666 + my ($parameter, $section);
  1667 +
  1668 + foreach $section (@{$args{'sectionlist'}}) {
  1669 + print "DOC: $section\n";
  1670 + }
  1671 +}
  1672 +
  1673 +##
  1674 +# generic output function for all types (function, struct/union, typedef, enum);
  1675 +# calls the generated, variable output_ function name based on
  1676 +# functype and output_mode
  1677 +sub output_declaration {
  1678 + no strict 'refs';
  1679 + my $name = shift;
  1680 + my $functype = shift;
  1681 + my $func = "output_${functype}_$output_mode";
  1682 + if (($function_only==0) ||
  1683 + ( $function_only == 1 && defined($function_table{$name})) ||
  1684 + ( $function_only == 2 && !defined($function_table{$name})))
  1685 + {
  1686 + &$func(@_);
  1687 + $section_counter++;
  1688 + }
  1689 +}
  1690 +
  1691 +##
  1692 +# generic output function - calls the right one based on current output mode.
  1693 +sub output_blockhead {
  1694 + no strict 'refs';
  1695 + my $func = "output_blockhead_" . $output_mode;
  1696 + &$func(@_);
  1697 + $section_counter++;
  1698 +}
  1699 +
  1700 +##
  1701 +# takes a declaration (struct, union, enum, typedef) and
  1702 +# invokes the right handler. NOT called for functions.
  1703 +sub dump_declaration($$) {
  1704 + no strict 'refs';
  1705 + my ($prototype, $file) = @_;
  1706 + my $func = "dump_" . $decl_type;
  1707 + &$func(@_);
  1708 +}
  1709 +
  1710 +sub dump_union($$) {
  1711 + dump_struct(@_);
  1712 +}
  1713 +
  1714 +sub dump_struct($$) {
  1715 + my $x = shift;
  1716 + my $file = shift;
  1717 + my $nested;
  1718 +
  1719 + if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
  1720 + #my $decl_type = $1;
  1721 + $declaration_name = $2;
  1722 + my $members = $3;
  1723 +
  1724 + # ignore embedded structs or unions
  1725 + $members =~ s/({.*})//g;
  1726 + $nested = $1;
  1727 +
  1728 + # ignore members marked private:
  1729 + $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos;
  1730 + $members =~ s/\/\*\s*private:.*//gos;
  1731 + # strip comments:
  1732 + $members =~ s/\/\*.*?\*\///gos;
  1733 + $nested =~ s/\/\*.*?\*\///gos;
  1734 + # strip kmemcheck_bitfield_{begin,end}.*;
  1735 + $members =~ s/kmemcheck_bitfield_.*?;//gos;
  1736 + # strip attributes
  1737 + $members =~ s/__aligned\s*\(\d+\)//gos;
  1738 +
  1739 + create_parameterlist($members, ';', $file);
  1740 + check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
  1741 +
  1742 + output_declaration($declaration_name,
  1743 + 'struct',
  1744 + {'struct' => $declaration_name,
  1745 + 'module' => $modulename,
  1746 + 'parameterlist' => \@parameterlist,
  1747 + 'parameterdescs' => \%parameterdescs,
  1748 + 'parametertypes' => \%parametertypes,
  1749 + 'sectionlist' => \@sectionlist,
  1750 + 'sections' => \%sections,
  1751 + 'purpose' => $declaration_purpose,
  1752 + 'type' => $decl_type
  1753 + });
  1754 + }
  1755 + else {
  1756 + print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
  1757 + ++$errors;
  1758 + }
  1759 +}
  1760 +
  1761 +sub dump_enum($$) {
  1762 + my $x = shift;
  1763 + my $file = shift;
  1764 +
  1765 + $x =~ s@/\*.*?\*/@@gos; # strip comments.
  1766 + $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums
  1767 +
  1768 + if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
  1769 + $declaration_name = $1;
  1770 + my $members = $2;
  1771 +
  1772 + foreach my $arg (split ',', $members) {
  1773 + $arg =~ s/^\s*(\w+).*/$1/;
  1774 + push @parameterlist, $arg;
  1775 + if (!$parameterdescs{$arg}) {
  1776 + $parameterdescs{$arg} = $undescribed;
  1777 + print STDERR "Warning(${file}:$.): Enum value '$arg' ".
  1778 + "not described in enum '$declaration_name'\n";
  1779 + }
  1780 +
  1781 + }
  1782 +
  1783 + output_declaration($declaration_name,
  1784 + 'enum',
  1785 + {'enum' => $declaration_name,
  1786 + 'module' => $modulename,
  1787 + 'parameterlist' => \@parameterlist,
  1788 + 'parameterdescs' => \%parameterdescs,
  1789 + 'sectionlist' => \@sectionlist,
  1790 + 'sections' => \%sections,
  1791 + 'purpose' => $declaration_purpose
  1792 + });
  1793 + }
  1794 + else {
  1795 + print STDERR "Error(${file}:$.): Cannot parse enum!\n";
  1796 + ++$errors;
  1797 + }
  1798 +}
  1799 +
  1800 +sub dump_typedef($$) {
  1801 + my $x = shift;
  1802 + my $file = shift;
  1803 +
  1804 + $x =~ s@/\*.*?\*/@@gos; # strip comments.
  1805 + while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
  1806 + $x =~ s/\(*.\)\s*;$/;/;
  1807 + $x =~ s/\[*.\]\s*;$/;/;
  1808 + }
  1809 +
  1810 + if ($x =~ /typedef.*\s+(\w+)\s*;/) {
  1811 + $declaration_name = $1;
  1812 +
  1813 + output_declaration($declaration_name,
  1814 + 'typedef',
  1815 + {'typedef' => $declaration_name,
  1816 + 'module' => $modulename,
  1817 + 'sectionlist' => \@sectionlist,
  1818 + 'sections' => \%sections,
  1819 + 'purpose' => $declaration_purpose
  1820 + });
  1821 + }
  1822 + else {
  1823 + print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
  1824 + ++$errors;
  1825 + }
  1826 +}
  1827 +
  1828 +sub save_struct_actual($) {
  1829 + my $actual = shift;
  1830 +
  1831 + # strip all spaces from the actual param so that it looks like one string item
  1832 + $actual =~ s/\s*//g;
  1833 + $struct_actual = $struct_actual . $actual . " ";
  1834 +}
  1835 +
  1836 +sub create_parameterlist($$$) {
  1837 + my $args = shift;
  1838 + my $splitter = shift;
  1839 + my $file = shift;
  1840 + my $type;
  1841 + my $param;
  1842 +
  1843 + # temporarily replace commas inside function pointer definition
  1844 + while ($args =~ /(\([^\),]+),/) {
  1845 + $args =~ s/(\([^\),]+),/$1#/g;
  1846 + }
  1847 +
  1848 + foreach my $arg (split($splitter, $args)) {
  1849 + # strip comments
  1850 + $arg =~ s/\/\*.*\*\///;
  1851 + # strip leading/trailing spaces
  1852 + $arg =~ s/^\s*//;
  1853 + $arg =~ s/\s*$//;
  1854 + $arg =~ s/\s+/ /;
  1855 +
  1856 + if ($arg =~ /^#/) {
  1857 + # Treat preprocessor directive as a typeless variable just to fill
  1858 + # corresponding data structures "correctly". Catch it later in
  1859 + # output_* subs.
  1860 + push_parameter($arg, "", $file);
  1861 + } elsif ($arg =~ m/\(.+\)\s*\(/) {
  1862 + # pointer-to-function
  1863 + $arg =~ tr/#/,/;
  1864 + $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
  1865 + $param = $1;
  1866 + $type = $arg;
  1867 + $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
  1868 + save_struct_actual($param);
  1869 + push_parameter($param, $type, $file);
  1870 + } elsif ($arg) {
  1871 + $arg =~ s/\s*:\s*/:/g;
  1872 + $arg =~ s/\s*\[/\[/g;
  1873 +
  1874 + my @args = split('\s*,\s*', $arg);
  1875 + if ($args[0] =~ m/\*/) {
  1876 + $args[0] =~ s/(\*+)\s*/ $1/;
  1877 + }
  1878 +
  1879 + my @first_arg;
  1880 + if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
  1881 + shift @args;
  1882 + push(@first_arg, split('\s+', $1));
  1883 + push(@first_arg, $2);
  1884 + } else {
  1885 + @first_arg = split('\s+', shift @args);
  1886 + }
  1887 +
  1888 + unshift(@args, pop @first_arg);
  1889 + $type = join " ", @first_arg;
  1890 +
  1891 + foreach $param (@args) {
  1892 + if ($param =~ m/^(\*+)\s*(.*)/) {
  1893 + save_struct_actual($2);
  1894 + push_parameter($2, "$type $1", $file);
  1895 + }
  1896 + elsif ($param =~ m/(.*?):(\d+)/) {
  1897 + if ($type ne "") { # skip unnamed bit-fields
  1898 + save_struct_actual($1);
  1899 + push_parameter($1, "$type:$2", $file)
  1900 + }
  1901 + }
  1902 + else {
  1903 + save_struct_actual($param);
  1904 + push_parameter($param, $type, $file);
  1905 + }
  1906 + }
  1907 + }
  1908 + }
  1909 +}
  1910 +
  1911 +sub push_parameter($$$) {
  1912 + my $param = shift;
  1913 + my $type = shift;
  1914 + my $file = shift;
  1915 +
  1916 + if (($anon_struct_union == 1) && ($type eq "") &&
  1917 + ($param eq "}")) {
  1918 + return; # ignore the ending }; from anon. struct/union
  1919 + }
  1920 +
  1921 + $anon_struct_union = 0;
  1922 + my $param_name = $param;
  1923 + $param_name =~ s/\[.*//;
  1924 +
  1925 + if ($type eq "" && $param =~ /\.\.\.$/)
  1926 + {
  1927 + if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
  1928 + $parameterdescs{$param} = "variable arguments";
  1929 + }
  1930 + }
  1931 + elsif ($type eq "" && ($param eq "" or $param eq "void"))
  1932 + {
  1933 + $param="void";
  1934 + $parameterdescs{void} = "no arguments";
  1935 + }
  1936 + elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
  1937 + # handle unnamed (anonymous) union or struct:
  1938 + {
  1939 + $type = $param;
  1940 + $param = "{unnamed_" . $param . "}";
  1941 + $parameterdescs{$param} = "anonymous\n";
  1942 + $anon_struct_union = 1;
  1943 + }
  1944 +
  1945 + # warn if parameter has no description
  1946 + # (but ignore ones starting with # as these are not parameters
  1947 + # but inline preprocessor statements);
  1948 + # also ignore unnamed structs/unions;
  1949 + if (!$anon_struct_union) {
  1950 + if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
  1951 +
  1952 + $parameterdescs{$param_name} = $undescribed;
  1953 +
  1954 + if (($type eq 'function') || ($type eq 'enum')) {
  1955 + print STDERR "Warning(${file}:$.): Function parameter ".
  1956 + "or member '$param' not " .
  1957 + "described in '$declaration_name'\n";
  1958 + }
  1959 + print STDERR "Warning(${file}:$.):" .
  1960 + " No description found for parameter '$param'\n";
  1961 + ++$warnings;
  1962 + }
  1963 + }
  1964 +
  1965 + $param = xml_escape($param);
  1966 +
  1967 + # strip spaces from $param so that it is one continuous string
  1968 + # on @parameterlist;
  1969 + # this fixes a problem where check_sections() cannot find
  1970 + # a parameter like "addr[6 + 2]" because it actually appears
  1971 + # as "addr[6", "+", "2]" on the parameter list;
  1972 + # but it's better to maintain the param string unchanged for output,
  1973 + # so just weaken the string compare in check_sections() to ignore
  1974 + # "[blah" in a parameter string;
  1975 + ###$param =~ s/\s*//g;
  1976 + push @parameterlist, $param;
  1977 + $parametertypes{$param} = $type;
  1978 +}
  1979 +
  1980 +sub check_sections($$$$$$) {
  1981 + my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
  1982 + my @sects = split ' ', $sectcheck;
  1983 + my @prms = split ' ', $prmscheck;
  1984 + my $err;
  1985 + my ($px, $sx);
  1986 + my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
  1987 +
  1988 + foreach $sx (0 .. $#sects) {
  1989 + $err = 1;
  1990 + foreach $px (0 .. $#prms) {
  1991 + $prm_clean = $prms[$px];
  1992 + $prm_clean =~ s/\[.*\]//;
  1993 + $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
  1994 + # ignore array size in a parameter string;
  1995 + # however, the original param string may contain
  1996 + # spaces, e.g.: addr[6 + 2]
  1997 + # and this appears in @prms as "addr[6" since the
  1998 + # parameter list is split at spaces;
  1999 + # hence just ignore "[..." for the sections check;
  2000 + $prm_clean =~ s/\[.*//;
  2001 +
  2002 + ##$prm_clean =~ s/^\**//;
  2003 + if ($prm_clean eq $sects[$sx]) {
  2004 + $err = 0;
  2005 + last;
  2006 + }
  2007 + }
  2008 + if ($err) {
  2009 + if ($decl_type eq "function") {
  2010 + print STDERR "Warning(${file}:$.): " .
  2011 + "Excess function parameter " .
  2012 + "'$sects[$sx]' " .
  2013 + "description in '$decl_name'\n";
  2014 + ++$warnings;
  2015 + } else {
  2016 + if ($nested !~ m/\Q$sects[$sx]\E/) {
  2017 + print STDERR "Warning(${file}:$.): " .
  2018 + "Excess struct/union/enum/typedef member " .
  2019 + "'$sects[$sx]' " .
  2020 + "description in '$decl_name'\n";
  2021 + ++$warnings;
  2022 + }
  2023 + }
  2024 + }
  2025 + }
  2026 +}
  2027 +
  2028 +##
  2029 +# takes a function prototype and the name of the current file being
  2030 +# processed and spits out all the details stored in the global
  2031 +# arrays/hashes.
  2032 +sub dump_function($$) {
  2033 + my $prototype = shift;
  2034 + my $file = shift;
  2035 +
  2036 + $prototype =~ s/^static +//;
  2037 + $prototype =~ s/^extern +//;
  2038 + $prototype =~ s/^asmlinkage +//;
  2039 + $prototype =~ s/^inline +//;
  2040 + $prototype =~ s/^__inline__ +//;
  2041 + $prototype =~ s/^__inline +//;
  2042 + $prototype =~ s/^__always_inline +//;
  2043 + $prototype =~ s/^noinline +//;
  2044 + $prototype =~ s/__devinit +//;
  2045 + $prototype =~ s/__init +//;
  2046 + $prototype =~ s/__init_or_module +//;
  2047 + $prototype =~ s/__must_check +//;
  2048 + $prototype =~ s/__weak +//;
  2049 + $prototype =~ s/^#\s*define\s+//; #ak added
  2050 + $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
  2051 +
  2052 + # Yes, this truly is vile. We are looking for:
  2053 + # 1. Return type (may be nothing if we're looking at a macro)
  2054 + # 2. Function name
  2055 + # 3. Function parameters.
  2056 + #
  2057 + # All the while we have to watch out for function pointer parameters
  2058 + # (which IIRC is what the two sections are for), C types (these
  2059 + # regexps don't even start to express all the possibilities), and
  2060 + # so on.
  2061 + #
  2062 + # If you mess with these regexps, it's a good idea to check that
  2063 + # the following functions' documentation still comes out right:
  2064 + # - parport_register_device (function pointer parameters)
  2065 + # - atomic_set (macro)
  2066 + # - pci_match_device, __copy_to_user (long return type)
  2067 +
  2068 + if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2069 + $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2070 + $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2071 + $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2072 + $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2073 + $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2074 + $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
  2075 + $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2076 + $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2077 + $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2078 + $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2079 + $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2080 + $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2081 + $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2082 + $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2083 + $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
  2084 + $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
  2085 + $return_type = $1;
  2086 + $declaration_name = $2;
  2087 + my $args = $3;
  2088 +
  2089 + create_parameterlist($args, ',', $file);
  2090 + } else {
  2091 + print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
  2092 + ++$errors;
  2093 + return;
  2094 + }
  2095 +
  2096 + my $prms = join " ", @parameterlist;
  2097 + check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
  2098 +
  2099 + output_declaration($declaration_name,
  2100 + 'function',
  2101 + {'function' => $declaration_name,
  2102 + 'module' => $modulename,
  2103 + 'functiontype' => $return_type,
  2104 + 'parameterlist' => \@parameterlist,
  2105 + 'parameterdescs' => \%parameterdescs,
  2106 + 'parametertypes' => \%parametertypes,
  2107 + 'sectionlist' => \@sectionlist,
  2108 + 'sections' => \%sections,
  2109 + 'purpose' => $declaration_purpose
  2110 + });
  2111 +}
  2112 +
  2113 +sub reset_state {
  2114 + $function = "";
  2115 + %constants = ();
  2116 + %parameterdescs = ();
  2117 + %parametertypes = ();
  2118 + @parameterlist = ();
  2119 + %sections = ();
  2120 + @sectionlist = ();
  2121 + $sectcheck = "";
  2122 + $struct_actual = "";
  2123 + $prototype = "";
  2124 +
  2125 + $state = 0;
  2126 +}
  2127 +
  2128 +sub tracepoint_munge($) {
  2129 + my $file = shift;
  2130 + my $tracepointname = 0;
  2131 + my $tracepointargs = 0;
  2132 +
  2133 + if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
  2134 + $tracepointname = $1;
  2135 + }
  2136 + if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
  2137 + $tracepointname = $1;
  2138 + }
  2139 + if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
  2140 + $tracepointname = $2;
  2141 + }
  2142 + $tracepointname =~ s/^\s+//; #strip leading whitespace
  2143 + if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
  2144 + $tracepointargs = $1;
  2145 + }
  2146 + if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
  2147 + print STDERR "Warning(${file}:$.): Unrecognized tracepoint format: \n".
  2148 + "$prototype\n";
  2149 + } else {
  2150 + $prototype = "static inline void trace_$tracepointname($tracepointargs)";
  2151 + }
  2152 +}
  2153 +
  2154 +sub syscall_munge() {
  2155 + my $void = 0;
  2156 +
  2157 + $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
  2158 +## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
  2159 + if ($prototype =~ m/SYSCALL_DEFINE0/) {
  2160 + $void = 1;
  2161 +## $prototype = "long sys_$1(void)";
  2162 + }
  2163 +
  2164 + $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
  2165 + if ($prototype =~ m/long (sys_.*?),/) {
  2166 + $prototype =~ s/,/\(/;
  2167 + } elsif ($void) {
  2168 + $prototype =~ s/\)/\(void\)/;
  2169 + }
  2170 +
  2171 + # now delete all of the odd-number commas in $prototype
  2172 + # so that arg types & arg names don't have a comma between them
  2173 + my $count = 0;
  2174 + my $len = length($prototype);
  2175 + if ($void) {
  2176 + $len = 0; # skip the for-loop
  2177 + }
  2178 + for (my $ix = 0; $ix < $len; $ix++) {
  2179 + if (substr($prototype, $ix, 1) eq ',') {
  2180 + $count++;
  2181 + if ($count % 2 == 1) {
  2182 + substr($prototype, $ix, 1) = ' ';
  2183 + }
  2184 + }
  2185 + }
  2186 +}
  2187 +
  2188 +sub process_state3_function($$) {
  2189 + my $x = shift;
  2190 + my $file = shift;
  2191 +
  2192 + $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
  2193 +
  2194 + if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
  2195 + # do nothing
  2196 + }
  2197 + elsif ($x =~ /([^\{]*)/) {
  2198 + $prototype .= $1;
  2199 + }
  2200 +
  2201 + if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
  2202 + $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
  2203 + $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
  2204 + $prototype =~ s@^\s+@@gos; # strip leading spaces
  2205 + if ($prototype =~ /SYSCALL_DEFINE/) {
  2206 + syscall_munge();
  2207 + }
  2208 + if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
  2209 + $prototype =~ /DEFINE_SINGLE_EVENT/)
  2210 + {
  2211 + tracepoint_munge($file);
  2212 + }
  2213 + dump_function($prototype, $file);
  2214 + reset_state();
  2215 + }
  2216 +}
  2217 +
  2218 +sub process_state3_type($$) {
  2219 + my $x = shift;
  2220 + my $file = shift;
  2221 +
  2222 + $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
  2223 + $x =~ s@^\s+@@gos; # strip leading spaces
  2224 + $x =~ s@\s+$@@gos; # strip trailing spaces
  2225 + $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
  2226 +
  2227 + if ($x =~ /^#/) {
  2228 + # To distinguish preprocessor directive from regular declaration later.
  2229 + $x .= ";";
  2230 + }
  2231 +
  2232 + while (1) {
  2233 + if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
  2234 + $prototype .= $1 . $2;
  2235 + ($2 eq '{') && $brcount++;
  2236 + ($2 eq '}') && $brcount--;
  2237 + if (($2 eq ';') && ($brcount == 0)) {
  2238 + dump_declaration($prototype, $file);
  2239 + reset_state();
  2240 + last;
  2241 + }
  2242 + $x = $3;
  2243 + } else {
  2244 + $prototype .= $x;
  2245 + last;
  2246 + }
  2247 + }
  2248 +}
  2249 +
  2250 +# xml_escape: replace <, >, and & in the text stream;
  2251 +#
  2252 +# however, formatting controls that are generated internally/locally in the
  2253 +# kernel-doc script are not escaped here; instead, they begin life like
  2254 +# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
  2255 +# are converted to their mnemonic-expected output, without the 4 * '\' & ':',
  2256 +# just before actual output; (this is done by local_unescape())
  2257 +sub xml_escape($) {
  2258 + my $text = shift;
  2259 + if (($output_mode eq "text") || ($output_mode eq "man")) {
  2260 + return $text;
  2261 + }
  2262 + $text =~ s/\&/\\\\\\amp;/g;
  2263 + $text =~ s/\</\\\\\\lt;/g;
  2264 + $text =~ s/\>/\\\\\\gt;/g;
  2265 + return $text;
  2266 +}
  2267 +
  2268 +# convert local escape strings to html
  2269 +# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes)
  2270 +sub local_unescape($) {
  2271 + my $text = shift;
  2272 + if (($output_mode eq "text") || ($output_mode eq "man")) {
  2273 + return $text;
  2274 + }
  2275 + $text =~ s/\\\\\\\\lt:/</g;
  2276 + $text =~ s/\\\\\\\\gt:/>/g;
  2277 + return $text;
  2278 +}
  2279 +
  2280 +sub process_file($) {
  2281 + my $file;
  2282 + my $identifier;
  2283 + my $func;
  2284 + my $descr;
  2285 + my $in_purpose = 0;
  2286 + my $initial_section_counter = $section_counter;
  2287 +
  2288 + if (defined($ENV{'SRCTREE'})) {
  2289 + $file = "$ENV{'SRCTREE'}" . "/" . "@_";
  2290 + }
  2291 + else {
  2292 + $file = "@_";
  2293 + }
  2294 + if (defined($source_map{$file})) {
  2295 + $file = $source_map{$file};
  2296 + }
  2297 +
  2298 + if (!open(IN,"<$file")) {
  2299 + print STDERR "Error: Cannot open file $file\n";
  2300 + ++$errors;
  2301 + return;
  2302 + }
  2303 +
  2304 + $. = 1;
  2305 +
  2306 + $section_counter = 0;
  2307 + while (<IN>) {
  2308 + if ($state == 0) {
  2309 + if (/$doc_start/o) {
  2310 + $state = 1; # next line is always the function name
  2311 + $in_doc_sect = 0;
  2312 + }
  2313 + } elsif ($state == 1) { # this line is the function name (always)
  2314 + if (/$doc_block/o) {
  2315 + $state = 4;
  2316 + $contents = "";
  2317 + if ( $1 eq "" ) {
  2318 + $section = $section_intro;
  2319 + } else {
  2320 + $section = $1;
  2321 + }
  2322 + }
  2323 + elsif (/$doc_decl/o) {
  2324 + $identifier = $1;
  2325 + if (/\s*([\w\s]+?)\s*-/) {
  2326 + $identifier = $1;
  2327 + }
  2328 +
  2329 + $state = 2;
  2330 + if (/-(.*)/) {
  2331 + # strip leading/trailing/multiple spaces
  2332 + $descr= $1;
  2333 + $descr =~ s/^\s*//;
  2334 + $descr =~ s/\s*$//;
  2335 + $descr =~ s/\s+/ /;
  2336 + $declaration_purpose = xml_escape($descr);
  2337 + $in_purpose = 1;
  2338 + } else {
  2339 + $declaration_purpose = "";
  2340 + }
  2341 +
  2342 + if (($declaration_purpose eq "") && $verbose) {
  2343 + print STDERR "Warning(${file}:$.): missing initial short description on line:\n";
  2344 + print STDERR $_;
  2345 + ++$warnings;
  2346 + }
  2347 +
  2348 + if ($identifier =~ m/^struct/) {
  2349 + $decl_type = 'struct';
  2350 + } elsif ($identifier =~ m/^union/) {
  2351 + $decl_type = 'union';
  2352 + } elsif ($identifier =~ m/^enum/) {
  2353 + $decl_type = 'enum';
  2354 + } elsif ($identifier =~ m/^typedef/) {
  2355 + $decl_type = 'typedef';
  2356 + } else {
  2357 + $decl_type = 'function';
  2358 + }
  2359 +
  2360 + if ($verbose) {
  2361 + print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
  2362 + }
  2363 + } else {
  2364 + print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
  2365 + " - I thought it was a doc line\n";
  2366 + ++$warnings;
  2367 + $state = 0;
  2368 + }
  2369 + } elsif ($state == 2) { # look for head: lines, and include content
  2370 + if (/$doc_sect/o) {
  2371 + $newsection = $1;
  2372 + $newcontents = $2;
  2373 +
  2374 + if (($contents ne "") && ($contents ne "\n")) {
  2375 + if (!$in_doc_sect && $verbose) {
  2376 + print STDERR "Warning(${file}:$.): contents before sections\n";
  2377 + ++$warnings;
  2378 + }
  2379 + dump_section($file, $section, xml_escape($contents));
  2380 + $section = $section_default;
  2381 + }
  2382 +
  2383 + $in_doc_sect = 1;
  2384 + $in_purpose = 0;
  2385 + $contents = $newcontents;
  2386 + if ($contents ne "") {
  2387 + while ((substr($contents, 0, 1) eq " ") ||
  2388 + substr($contents, 0, 1) eq "\t") {
  2389 + $contents = substr($contents, 1);
  2390 + }
  2391 + $contents .= "\n";
  2392 + }
  2393 + $section = $newsection;
  2394 + } elsif (/$doc_end/) {
  2395 +
  2396 + if (($contents ne "") && ($contents ne "\n")) {
  2397 + dump_section($file, $section, xml_escape($contents));
  2398 + $section = $section_default;
  2399 + $contents = "";
  2400 + }
  2401 + # look for doc_com + <text> + doc_end:
  2402 + if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
  2403 + print STDERR "Warning(${file}:$.): suspicious ending line: $_";
  2404 + ++$warnings;
  2405 + }
  2406 +
  2407 + $prototype = "";
  2408 + $state = 3;
  2409 + $brcount = 0;
  2410 +# print STDERR "end of doc comment, looking for prototype\n";
  2411 + } elsif (/$doc_content/) {
  2412 + # miguel-style comment kludge, look for blank lines after
  2413 + # @parameter line to signify start of description
  2414 + if ($1 eq "") {
  2415 + if ($section =~ m/^@/ || $section eq $section_context) {
  2416 + dump_section($file, $section, xml_escape($contents));
  2417 + $section = $section_default;
  2418 + $contents = "";
  2419 + } else {
  2420 + $contents .= "\n";
  2421 + }
  2422 + $in_purpose = 0;
  2423 + } elsif ($in_purpose == 1) {
  2424 + # Continued declaration purpose
  2425 + chomp($declaration_purpose);
  2426 + $declaration_purpose .= " " . xml_escape($1);
  2427 + } else {
  2428 + $contents .= $1 . "\n";
  2429 + }
  2430 + } else {
  2431 + # i dont know - bad line? ignore.
  2432 + print STDERR "Warning(${file}:$.): bad line: $_";
  2433 + ++$warnings;
  2434 + }
  2435 + } elsif ($state == 3) { # scanning for function '{' (end of prototype)
  2436 + if ($decl_type eq 'function') {
  2437 + process_state3_function($_, $file);
  2438 + } else {
  2439 + process_state3_type($_, $file);
  2440 + }
  2441 + } elsif ($state == 4) {
  2442 + # Documentation block
  2443 + if (/$doc_block/) {
  2444 + dump_doc_section($file, $section, xml_escape($contents));
  2445 + $contents = "";
  2446 + $function = "";
  2447 + %constants = ();
  2448 + %parameterdescs = ();
  2449 + %parametertypes = ();
  2450 + @parameterlist = ();
  2451 + %sections = ();
  2452 + @sectionlist = ();
  2453 + $prototype = "";
  2454 + if ( $1 eq "" ) {
  2455 + $section = $section_intro;
  2456 + } else {
  2457 + $section = $1;
  2458 + }
  2459 + }
  2460 + elsif (/$doc_end/)
  2461 + {
  2462 + dump_doc_section($file, $section, xml_escape($contents));
  2463 + $contents = "";
  2464 + $function = "";
  2465 + %constants = ();
  2466 + %parameterdescs = ();
  2467 + %parametertypes = ();
  2468 + @parameterlist = ();
  2469 + %sections = ();
  2470 + @sectionlist = ();
  2471 + $prototype = "";
  2472 + $state = 0;
  2473 + }
  2474 + elsif (/$doc_content/)
  2475 + {
  2476 + if ( $1 eq "" )
  2477 + {
  2478 + $contents .= $blankline;
  2479 + }
  2480 + else
  2481 + {
  2482 + $contents .= $1 . "\n";
  2483 + }
  2484 + }
  2485 + }
  2486 + }
  2487 + if ($initial_section_counter == $section_counter) {
  2488 + print STDERR "Warning(${file}): no structured comments found\n";
  2489 + if ($output_mode eq "xml") {
  2490 + # The template wants at least one RefEntry here; make one.
  2491 + print "<refentry>\n";
  2492 + print " <refnamediv>\n";
  2493 + print " <refname>\n";
  2494 + print " ${file}\n";
  2495 + print " </refname>\n";
  2496 + print " <refpurpose>\n";
  2497 + print " Document generation inconsistency\n";
  2498 + print " </refpurpose>\n";
  2499 + print " </refnamediv>\n";
  2500 + print " <refsect1>\n";
  2501 + print " <title>\n";
  2502 + print " Oops\n";
  2503 + print " </title>\n";
  2504 + print " <warning>\n";
  2505 + print " <para>\n";
  2506 + print " The template for this document tried to insert\n";
  2507 + print " the structured comment from the file\n";
  2508 + print " <filename>${file}</filename> at this point,\n";
  2509 + print " but none was found.\n";
  2510 + print " This dummy section is inserted to allow\n";
  2511 + print " generation to continue.\n";
  2512 + print " </para>\n";
  2513 + print " </warning>\n";
  2514 + print " </refsect1>\n";
  2515 + print "</refentry>\n";
  2516 + }
  2517 + }
  2518 +}
  2519 +
  2520 +
  2521 +$kernelversion = get_kernel_version();
  2522 +
  2523 +# generate a sequence of code that will splice in highlighting information
  2524 +# using the s// operator.
  2525 +foreach my $pattern (keys %highlights) {
  2526 +# print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
  2527 + $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
  2528 +}
  2529 +
  2530 +# Read the file that maps relative names to absolute names for
  2531 +# separate source and object directories and for shadow trees.
  2532 +if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
  2533 + my ($relname, $absname);
  2534 + while(<SOURCE_MAP>) {
  2535 + chop();
  2536 + ($relname, $absname) = (split())[0..1];
  2537 + $relname =~ s:^/+::;
  2538 + $source_map{$relname} = $absname;
  2539 + }
  2540 + close(SOURCE_MAP);
  2541 +}
  2542 +
  2543 +foreach (@ARGV) {
  2544 + chomp;
  2545 + process_file($_);
  2546 +}
  2547 +if ($verbose && $errors) {
  2548 + print STDERR "$errors errors\n";
  2549 +}
  2550 +if ($verbose && $warnings) {
  2551 + print STDERR "$warnings warnings\n";
  2552 +}
  2553 +
  2554 +exit($errors);