Commit eda603f6cdba4b14dbf80531fab2fe545232e7a0
Committed by
Linus Torvalds
1 parent
1f3a66889c
Exists in
master
and in
39 other branches
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 |
scripts/kernel-doc
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 = '\\&((struct\s*)*[_\w]+)'; | 167 | my $type_struct_xml = '\\&((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 " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n"; | 553 | print " <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 " <i>$1</i> <b>$parameter</b>$2;<br>\n"; | 556 | print " <i>$1</i> <b>$parameter</b>$2;<br>\n"; |
545 | } else { | 557 | } else { |
546 | print " <i>$type</i> <b>$parameter</b>;<br>\n"; | 558 | print " <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 |