Commit eda603f6cdba4b14dbf80531fab2fe545232e7a0

Authored by Johannes Berg
Committed by Linus Torvalds
1 parent 1f3a66889c

docbook: warn on unused doc entries

When you don't use !E or !I but only !F, then it's very easy to miss
including some functions, structs etc.  in documentation.  To help
finding which ones were missed, allow printing out the unused ones as
warnings.

For example, using this on mac80211 yields a lot of warnings like this:

  Warning: didn't use docs for DOC: mac80211 workqueue
  Warning: didn't use docs for ieee80211_max_queues
  Warning: didn't use docs for ieee80211_bss_change
  Warning: didn't use docs for ieee80211_bss_conf

when generating the documentation for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 183 additions and 3 deletions Inline Diff

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