1 #!/usr/bin/perl
2
3 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
4 ## Copyright (C) 2000 Tim Waugh <twaugh@redhat.com> ##
5 ## ##
6 ## #define enhancements by Armin Kuster <akuster@mvista.com> ##
7 ## Copyright (c) 2000 MontaVista Software, Inc. ##
8 ## ##
9 ## This software falls under the GNU General Public License. ##
10 ## Please read the COPYING file for more information ##
11
12 # w.o. 03-11-2000: added the '-filelist' option.
13
14 #
15 # This will read a 'c' file and scan for embedded comments in the
16 # style of gnome comments (+minor extensions - see below).
17 #
18
19 # Note: This only supports 'c'.
20
21 # usage:
22 # kerneldoc [ -docbook | -html | -text | -man ]
23 # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
24 # or
25 # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
26 #
27 # Set output format using one of -docbook -html -text or -man. Default is man.
28 #
29 # -function funcname
30 # If set, then only generate documentation for the given function(s). All
31 # other functions are ignored.
32 #
33 # -nofunction funcname
34 # If set, then only generate documentation for the other function(s). All
35 # other functions are ignored. Cannot be used with -function together
36 # (yes thats a bug - perl hackers can fix it 8))
37 #
38 # c files - list of 'c' files to process
39 #
40 # All output goes to stdout, with errors to stderr.
41
42 #
43 # format of comments.
44 # In the following table, (...)? signifies optional structure.
45 # (...)* signifies 0 or more structure elements
46 # /**
47 # * function_name(:)? (- short description)?
48 # (* @parameterx: (description of parameter x)?)*
49 # (* a blank line)?
50 # * (Description:)? (Description of function)?
51 # * (section header: (section description)? )*
52 # (*)?*/
53 #
54 # So .. the trivial example would be:
55 #
56 # /**
57 # * my_function
58 # **/
59 #
60 # If the Description: header tag is ommitted, then there must be a blank line
61 # after the last parameter specification.
62 # e.g.
63 # /**
64 # * my_function - does my stuff
65 # * @my_arg: its mine damnit
66 # *
67 # * Does my stuff explained.
68 # */
69 #
70 # or, could also use:
71 # /**
72 # * my_function - does my stuff
73 # * @my_arg: its mine damnit
74 # * Description: Does my stuff explained.
75 # */
76 # etc.
77 #
78 # All descriptions can be multiline, apart from the short function description.
79 #
80 # All descriptive text is further processed, scanning for the following special
81 # patterns, which are highlighted appropriately.
82 #
83 # 'funcname()' - function
84 # '$ENVVAR' - environmental variable
85 # '&struct_name' - name of a structure (up to two words including 'struct')
86 # '@parameter' - name of a parameter
87 # '%CONST' - name of a constant.
88
89 # match expressions used to find embedded type information
90 $type_constant = "\\\%([-_\\w]+)";
91 $type_func = "(\\w+)\\(\\)";
92 $type_param = "\\\@(\\w+)";
93 $type_struct = "\\\&((struct\\s*)?[_\\w]+)";
94 $type_env = "(\\\$\\w+)";
95
96
97 # Output conversion substitutions.
98 # One for each output format
99
100 # these work fairly well
101 %highlights_html = ( $type_constant, "<i>\$1</i>",
102 $type_func, "<b>\$1</b>",
103 $type_struct, "<i>\$1</i>",
104 $type_param, "<tt><b>\$1</b></tt>" );
105 $blankline_html = "<p>";
106
107 # sgml, docbook format
108 %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
109 $type_constant, "<constant>\$1</constant>",
110 $type_func, "<function>\$1</function>",
111 $type_struct, "<structname>\$1</structname>",
112 $type_env, "<envar>\$1</envar>",
113 $type_param, "<parameter>\$1</parameter>" );
114 $blankline_sgml = "</para><para>\n";
115
116 # gnome, docbook format
117 %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
118 $type_func, "<function>\$1</function>",
119 $type_struct, "<structname>\$1</structname>",
120 $type_env, "<envar>\$1</envar>",
121 $type_param, "<parameter>\$1</parameter>" );
122 $blankline_gnome = "</para><para>\n";
123
124 # these are pretty rough
125 %highlights_man = ( $type_constant, "\$1",
126 $type_func, "\\\\fB\$1\\\\fP",
127 $type_struct, "\\\\fI\$1\\\\fP",
128 $type_param, "\\\\fI\$1\\\\fP" );
129 $blankline_man = "";
130
131 # text-mode
132 %highlights_text = ( $type_constant, "\$1",
133 $type_func, "\$1",
134 $type_struct, "\$1",
135 $type_param, "\$1" );
136 $blankline_text = "";
137
138
139 sub usage {
140 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
141 print " [ -function funcname [ -function funcname ...] ]\n";
142 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
143 print " c source file(s) > outputfile\n";
144 exit 1;
145 }
146
147 # read arguments
148 if ($#ARGV==-1) {
149 usage();
150 }
151
152 $verbose = 0;
153 $output_mode = "man";
154 %highlights = %highlights_man;
155 $blankline = $blankline_man;
156 $modulename = "API Documentation";
157 $function_only = 0;
158 $filelist = '';
159
160 while ($ARGV[0] =~ m/^-(.*)/) {
161 $cmd = shift @ARGV;
162 if ($cmd eq "-html") {
163 $output_mode = "html";
164 %highlights = %highlights_html;
165 $blankline = $blankline_html;
166 } elsif ($cmd eq "-man") {
167 $output_mode = "man";
168 %highlights = %highlights_man;
169 $blankline = $blankline_man;
170 } elsif ($cmd eq "-text") {
171 $output_mode = "text";
172 %highlights = %highlights_text;
173 $blankline = $blankline_text;
174 } elsif ($cmd eq "-docbook") {
175 $output_mode = "sgml";
176 %highlights = %highlights_sgml;
177 $blankline = $blankline_sgml;
178 } elsif ($cmd eq "-gnome") {
179 $output_mode = "gnome";
180 %highlights = %highlights_gnome;
181 $blankline = $blankline_gnome;
182 } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
183 $modulename = shift @ARGV;
184 } elsif ($cmd eq "-function") { # to only output specific functions
185 $function_only = 1;
186 $function = shift @ARGV;
187 $function_table{$function} = 1;
188 } elsif ($cmd eq "-nofunction") { # to only output specific functions
189 $function_only = 2;
190 $function = shift @ARGV;
191 $function_table{$function} = 1;
192 } elsif ($cmd eq "-v") {
193 $verbose = 1;
194 } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
195 usage();
196 } elsif ($cmd eq '-filelist') {
197 $filelist = shift @ARGV;
198 }
199 }
200
201
202 # generate a sequence of code that will splice in highlighting information
203 # using the s// operator.
204 $dohighlight = "";
205 foreach $pattern (keys %highlights) {
206 # print "scanning pattern $pattern ($highlights{$pattern})\n";
207 $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
208 }
209
210 ##
211 # dumps section contents to arrays/hashes intended for that purpose.
212 #
213 sub dump_section {
214 my $name = shift @_;
215 my $contents = join "\n", @_;
216
217 if ($name =~ m/$type_constant/) {
218 $name = $1;
219 # print STDERR "constant section '$1' = '$contents'\n";
220 $constants{$name} = $contents;
221 } elsif ($name =~ m/$type_param/) {
222 # print STDERR "parameter def '$1' = '$contents'\n";
223 $name = $1;
224 $parameters{$name} = $contents;
225 } else {
226 # print STDERR "other section '$name' = '$contents'\n";
227 $sections{$name} = $contents;
228 push @sectionlist, $name;
229 }
230 }
231
232 ##
233 # output function
234 #
235 # parameters, a hash.
236 # function => "function name"
237 # parameterlist => @list of parameters
238 # parameters => %parameter descriptions
239 # sectionlist => @list of sections
240 # sections => %descriont descriptions
241 #
242
243 sub output_highlight {
244 my $contents = join "\n", @_;
245 my $line;
246
247 eval $dohighlight;
248 foreach $line (split "\n", $contents) {
249 if ($line eq ""){
250 print $lineprefix, $blankline;
251 } else {
252 $line =~ s/\\\\\\/\&/g;
253 print $lineprefix, $line;
254 }
255 print "\n";
256 }
257 }
258
259
260 # output in html
261 sub output_html {
262 my %args = %{$_[0]};
263 my ($parameter, $section);
264 my $count;
265 print "<h2>Function</h2>\n";
266
267 print "<i>".$args{'functiontype'}."</i>\n";
268 print "<b>".$args{'function'}."</b>\n";
269 print "(";
270 $count = 0;
271 foreach $parameter (@{$args{'parameterlist'}}) {
272 $type = $args{'parametertypes'}{$parameter};
273 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
274 # pointer-to-function
275 print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
276 } else {
277 print "<i>".$type."</i> <b>".$parameter."</b>";
278 }
279 if ($count != $#{$args{'parameterlist'}}) {
280 $count++;
281 print ",\n";
282 }
283 }
284 print ")\n";
285
286 print "<h3>Arguments</h3>\n";
287 print "<dl>\n";
288 foreach $parameter (@{$args{'parameterlist'}}) {
289 print "<dt><b>".$parameter."</b>\n";
290 print "<dd>";
291 output_highlight($args{'parameters'}{$parameter});
292 }
293 print "</dl>\n";
294 foreach $section (@{$args{'sectionlist'}}) {
295 print "<h3>$section</h3>\n";
296 print "<blockquote>\n";
297 output_highlight($args{'sections'}{$section});
298 print "</blockquote>\n";
299 }
300 print "<hr>\n";
301 }
302
303
304 # output in html
305 sub output_intro_html {
306 my %args = %{$_[0]};
307 my ($parameter, $section);
308 my $count;
309
310 foreach $section (@{$args{'sectionlist'}}) {
311 print "<h3>$section</h3>\n";
312 print "<ul>\n";
313 output_highlight($args{'sections'}{$section});
314 print "</ul>\n";
315 }
316 print "<hr>\n";
317 }
318
319
320
321 # output in sgml DocBook
322 sub output_sgml {
323 my %args = %{$_[0]};
324 my ($parameter, $section);
325 my $count;
326 my $id;
327
328 $id = "API-".$args{'function'};
329 $id =~ s/[^A-Za-z0-9]/-/g;
330
331 print "<refentry>\n";
332 print "<refmeta>\n";
333 print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
334 print "</refmeta>\n";
335 print "<refnamediv>\n";
336 print " <refname>".$args{'function'}."</refname>\n";
337 print " <refpurpose>\n";
338 print " ";
339 output_highlight ($args{'purpose'});
340 print " </refpurpose>\n";
341 print "</refnamediv>\n";
342
343 print "<refsynopsisdiv>\n";
344 print " <title>Synopsis</title>\n";
345 print " <funcsynopsis>\n";
346 print " <funcdef>".$args{'functiontype'}." ";
347 print "<function>".$args{'function'}." ";
348 print "</function></funcdef>\n";
349
350 # print "<refsect1>\n";
351 # print " <title>Synopsis</title>\n";
352 # print " <funcsynopsis>\n";
353 # print " <funcdef>".$args{'functiontype'}." ";
354 # print "<function>".$args{'function'}." ";
355 # print "</function></funcdef>\n";
356
357 $count = 0;
358 if ($#{$args{'parameterlist'}} >= 0) {
359 foreach $parameter (@{$args{'parameterlist'}}) {
360 $type = $args{'parametertypes'}{$parameter};
361 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
362 # pointer-to-function
363 print " <paramdef>$1<parameter>$parameter</parameter>)\n";
364 print " <funcparams>$2</funcparams></paramdef>\n";
365 } else {
366 print " <paramdef>".$type;
367 print " <parameter>$parameter</parameter></paramdef>\n";
368 }
369 }
370 } else {
371 print " <void>\n";
372 }
373 print " </funcsynopsis>\n";
374 print "</refsynopsisdiv>\n";
375 # print "</refsect1>\n";
376
377 # print parameters
378 print "<refsect1>\n <title>Arguments</title>\n";
379 # print "<para>\nArguments\n";
380 if ($#{$args{'parameterlist'}} >= 0) {
381 print " <variablelist>\n";
382 foreach $parameter (@{$args{'parameterlist'}}) {
383 print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
384 print " <listitem>\n <para>\n";
385 $lineprefix=" ";
386 output_highlight($args{'parameters'}{$parameter});
387 print " </para>\n </listitem>\n </varlistentry>\n";
388 }
389 print " </variablelist>\n";
390 } else {
391 print " <para>\n None\n </para>\n";
392 }
393 print "</refsect1>\n";
394
395 # print out each section
396 $lineprefix=" ";
397 foreach $section (@{$args{'sectionlist'}}) {
398 print "<refsect1>\n <title>$section</title>\n <para>\n";
399 # print "<para>\n$section\n";
400 if ($section =~ m/EXAMPLE/i) {
401 print "<example><para>\n";
402 }
403 output_highlight($args{'sections'}{$section});
404 # print "</para>";
405 if ($section =~ m/EXAMPLE/i) {
406 print "</para></example>\n";
407 }
408 print " </para>\n</refsect1>\n";
409 }
410
411 print "</refentry>\n\n";
412 }
413
414 # output in sgml DocBook
415 sub output_intro_sgml {
416 my %args = %{$_[0]};
417 my ($parameter, $section);
418 my $count;
419 my $id;
420
421 $id = $args{'module'};
422 $id =~ s/[^A-Za-z0-9]/-/g;
423
424 # print out each section
425 $lineprefix=" ";
426 foreach $section (@{$args{'sectionlist'}}) {
427 print "<refsect1>\n <title>$section</title>\n <para>\n";
428 # print "<para>\n$section\n";
429 if ($section =~ m/EXAMPLE/i) {
430 print "<example><para>\n";
431 }
432 output_highlight($args{'sections'}{$section});
433 # print "</para>";
434 if ($section =~ m/EXAMPLE/i) {
435 print "</para></example>\n";
436 }
437 print " </para>\n</refsect1>\n";
438 }
439
440 print "\n\n";
441 }
442
443 # output in sgml DocBook
444 sub output_gnome {
445 my %args = %{$_[0]};
446 my ($parameter, $section);
447 my $count;
448 my $id;
449
450 $id = $args{'module'}."-".$args{'function'};
451 $id =~ s/[^A-Za-z0-9]/-/g;
452
453 print "<sect2>\n";
454 print " <title id=\"$id\">".$args{'function'}."</title>\n";
455
456 # print "<simplesect>\n";
457 # print " <title>Synopsis</title>\n";
458 print " <funcsynopsis>\n";
459 print " <funcdef>".$args{'functiontype'}." ";
460 print "<function>".$args{'function'}." ";
461 print "</function></funcdef>\n";
462
463 $count = 0;
464 if ($#{$args{'parameterlist'}} >= 0) {
465 foreach $parameter (@{$args{'parameterlist'}}) {
466 $type = $args{'parametertypes'}{$parameter};
467 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
468 # pointer-to-function
469 print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
470 print " <funcparams>$2</funcparams></paramdef>\n";
471 } else {
472 print " <paramdef>".$type;
473 print " <parameter>$parameter</parameter></paramdef>\n";
474 }
475 }
476 } else {
477 print " <void>\n";
478 }
479 print " </funcsynopsis>\n";
480 # print "</simplesect>\n";
481 # print "</refsect1>\n";
482
483 # print parameters
484 # print "<simplesect>\n <title>Arguments</title>\n";
485 # if ($#{$args{'parameterlist'}} >= 0) {
486 # print " <variablelist>\n";
487 # foreach $parameter (@{$args{'parameterlist'}}) {
488 # print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
489 # print " <listitem>\n <para>\n";
490 # $lineprefix=" ";
491 # output_highlight($args{'parameters'}{$parameter});
492 # print " </para>\n </listitem>\n </varlistentry>\n";
493 # }
494 # print " </variablelist>\n";
495 # } else {
496 # print " <para>\n None\n </para>\n";
497 # }
498 # print "</simplesect>\n";
499
500 # print "<simplesect>\n <title>Arguments</title>\n";
501 if ($#{$args{'parameterlist'}} >= 0) {
502 print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
503 print "<tgroup cols=\"2\">\n";
504 print "<colspec colwidth=\"2*\">\n";
505 print "<colspec colwidth=\"8*\">\n";
506 print "<tbody>\n";
507 foreach $parameter (@{$args{'parameterlist'}}) {
508 print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
509 print " <entry>\n";
510 $lineprefix=" ";
511 output_highlight($args{'parameters'}{$parameter});
512 print " </entry></row>\n";
513 }
514 print " </tbody></tgroup></informaltable>\n";
515 } else {
516 print " <para>\n None\n </para>\n";
517 }
518 # print "</simplesect>\n";
519
520 # print out each section
521 $lineprefix=" ";
522 foreach $section (@{$args{'sectionlist'}}) {
523 print "<simplesect>\n <title>$section</title>\n";
524 # print "<para>\n$section\n";
525 if ($section =~ m/EXAMPLE/i) {
526 print "<example><programlisting>\n";
527 } else {
528 }
529 print "<para>\n";
530 output_highlight($args{'sections'}{$section});
531 # print "</para>";
532 print "</para>\n";
533 if ($section =~ m/EXAMPLE/i) {
534 print "</programlisting></example>\n";
535 } else {
536 }
537 print " </simplesect>\n";
538 }
539
540 print "</sect2>\n\n";
541 }
542
543 ##
544 # output in man
545 sub output_man {
546 my %args = %{$_[0]};
547 my ($parameter, $section);
548 my $count;
549
550 print ".TH \"$args{'module'}\" 4 \"$args{'function'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
551
552 print ".SH NAME\n";
553 print $args{'function'}." \\- ".$args{'purpose'}."\n";
554
555 print ".SH SYNOPSIS\n";
556 print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
557 $count = 0;
558 $parenth = "(";
559 $post = ",";
560 foreach $parameter (@{$args{'parameterlist'}}) {
561 if ($count == $#{$args{'parameterlist'}}) {
562 $post = ");";
563 }
564 $type = $args{'parametertypes'}{$parameter};
565 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
566 # pointer-to-function
567 print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
568 } else {
569 $type =~ s/([^\*])$/\1 /;
570 print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
571 }
572 $count++;
573 $parenth = "";
574 }
575
576 print ".SH Arguments\n";
577 foreach $parameter (@{$args{'parameterlist'}}) {
578 print ".IP \"".$parameter."\" 12\n";
579 output_highlight($args{'parameters'}{$parameter});
580 }
581 foreach $section (@{$args{'sectionlist'}}) {
582 print ".SH \"$section\"\n";
583 output_highlight($args{'sections'}{$section});
584 }
585 }
586
587 sub output_intro_man {
588 my %args = %{$_[0]};
589 my ($parameter, $section);
590 my $count;
591
592 print ".TH \"$args{'module'}\" 4 \"$args{'module'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
593
594 foreach $section (@{$args{'sectionlist'}}) {
595 print ".SH \"$section\"\n";
596 output_highlight($args{'sections'}{$section});
597 }
598 }
599
600 ##
601 # output in text
602 sub output_text {
603 my %args = %{$_[0]};
604 my ($parameter, $section);
605
606 print "Function:\n\n";
607 $start=$args{'functiontype'}." ".$args{'function'}." (";
608 print $start;
609 $count = 0;
610 foreach $parameter (@{$args{'parameterlist'}}) {
611 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
612 # pointer-to-function
613 print $1.$parameter.") (".$2;
614 } else {
615 print $type." ".$parameter;
616 }
617 if ($count != $#{$args{'parameterlist'}}) {
618 $count++;
619 print ",\n";
620 print " " x length($start);
621 } else {
622 print ");\n\n";
623 }
624 }
625
626 print "Arguments:\n\n";
627 foreach $parameter (@{$args{'parameterlist'}}) {
628 print $parameter."\n\t".$args{'parameters'}{$parameter}."\n";
629 }
630 foreach $section (@{$args{'sectionlist'}}) {
631 print "$section:\n\n";
632 output_highlight($args{'sections'}{$section});
633 }
634 print "\n\n";
635 }
636
637 sub output_intro_text {
638 my %args = %{$_[0]};
639 my ($parameter, $section);
640
641 foreach $section (@{$args{'sectionlist'}}) {
642 print " $section:\n";
643 print " -> ";
644 output_highlight($args{'sections'}{$section});
645 }
646 }
647
648 ##
649 # generic output function - calls the right one based
650 # on current output mode.
651 sub output_function {
652 # output_html(@_);
653 eval "output_".$output_mode."(\@_);";
654 }
655
656 ##
657 # generic output function - calls the right one based
658 # on current output mode.
659 sub output_intro {
660 # output_html(@_);
661 eval "output_intro_".$output_mode."(\@_);";
662 }
663
664
665 ##
666 # takes a function prototype and spits out all the details
667 # stored in the global arrays/hashes.
668 sub dump_function {
669 my $prototype = shift @_;
670
671 $prototype =~ s/^static +//;
672 $prototype =~ s/^extern +//;
673 $prototype =~ s/^inline +//;
674 $prototype =~ s/^__inline__ +//;
675 $prototype =~ s/^#define +//; #ak added
676
677 # Yes, this truly is vile. We are looking for:
678 # 1. Return type (may be nothing if we're looking at a macro)
679 # 2. Function name
680 # 3. Function parameters.
681 #
682 # All the while we have to watch out for function pointer parameters
683 # (which IIRC is what the two sections are for), C types (these
684 # regexps don't even start to express all the possibilities), and
685 # so on.
686 #
687 # If you mess with these regexps, it's a good idea to check that
688 # the following functions' documentation still comes out right:
689 # - parport_register_device (function pointer parameters)
690 # - atomic_set (macro)
691 # - pci_match_device (long return type)
692
693 if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
694 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
695 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
696 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
697 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
698 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
699 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
700 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
701 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
702 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
703 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
704 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
705 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
706 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
707 $return_type = $1;
708 $function_name = $2;
709 $args = $3;
710
711 # allow for up to fours args to function pointers
712 $args =~ s/(\([^\),]+),/\1#/g;
713 $args =~ s/(\([^\),]+),/\1#/g;
714 $args =~ s/(\([^\),]+),/\1#/g;
715 # print STDERR "ARGS = '$args'\n";
716
717 foreach $arg (split ',', $args) {
718 # strip leading/trailing spaces
719 $arg =~ s/^\s*//;
720 $arg =~ s/\s*$//;
721
722 if ($arg =~ m/\(/) {
723 # pointer-to-function
724 $arg =~ tr/#/,/;
725 $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
726 $param = $1;
727 $type = $arg;
728 $type =~ s/([^\(]+\(\*)$param/\1/;
729 } else {
730 # evil magic to get fixed array parameters to work
731 $arg =~ s/(.+\s+)(.+)\[.*/\1* \2/;
732 # print STDERR "SCAN ARG: '$arg'\n";
733 @args = split('\s', $arg);
734
735 # print STDERR " -> @args\n";
736 $param = pop @args;
737 # print STDERR " -> @args\n";
738 if ($param =~ m/^(\*+)(.*)/) {
739 $param = $2;
740 push @args, $1;
741 }
742 $type = join " ", @args;
743 }
744
745 if ($type eq "" && $param eq "...")
746 {
747 $type="...";
748 $param="...";
749 $parameters{"..."} = "variable arguments";
750 }
751 elsif ($type eq "" && $param eq "")
752 {
753 $type="";
754 $param="void";
755 $parameters{void} = "no arguments";
756 }
757 if ($type ne "" && $parameters{$param} eq "") {
758 $parameters{$param} = "-- undescribed --";
759 print STDERR "Warning($file:$lineno): Function parameter '$param' not described in '$function_name'\n";
760 }
761
762 push @parameterlist, $param;
763 $parametertypes{$param} = $type;
764 # print STDERR "param = '$param', type = '$type'\n";
765 }
766 } else {
767 print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n";
768 return;
769 }
770
771 if ($function_only==0 ||
772 ( $function_only == 1 && defined($function_table{$function_name})) ||
773 ( $function_only == 2 && !defined($function_table{$function_name})))
774 {
775 output_function({'function' => $function_name,
776 'module' => $modulename,
777 'functiontype' => $return_type,
778 'parameterlist' => \@parameterlist,
779 'parameters' => \%parameters,
780 'parametertypes' => \%parametertypes,
781 'sectionlist' => \@sectionlist,
782 'sections' => \%sections,
783 'purpose' => $function_purpose
784 });
785 }
786 }
787
788 ######################################################################
789 # main
790 # states
791 # 0 - normal code
792 # 1 - looking for function name
793 # 2 - scanning field start.
794 # 3 - scanning prototype.
795 $state = 0;
796 $section = "";
797
798 $doc_special = "\@\%\$\&";
799
800 $doc_start = "^/\\*\\*\$";
801 $doc_end = "\\*/";
802 $doc_com = "\\s*\\*\\s*";
803 $doc_func = $doc_com."(\\w+):?";
804 $doc_sect = $doc_com."([".$doc_special."]?[\\w ]+):(.*)";
805 $doc_content = $doc_com."(.*)";
806 $doc_block = $doc_com."DOC:\\s*(.*)?";
807
808 %constants = ();
809 %parameters = ();
810 @parameterlist = ();
811 %sections = ();
812 @sectionlist = ();
813
814 $contents = "";
815 $section_default = "Description"; # default section
816 $section_intro = "Introduction";
817 $section = $section_default;
818
819 if( $filelist ne '' ) {
820 open(FLIST,"<$filelist") or die "Can't open file list $filelist";
821 while(<FLIST>) {
822 chop;
823 process_file($_);
824 }
825 }
826
827 foreach $file (@ARGV) {
828 chomp($file);
829 process_file($file);
830 }
831
832 sub process_file($) {
833 my ($file) = @_;
834
835 if (!open(IN,"<$file")) {
836 print STDERR "Error: Cannot open file $file\n";
837 return;
838 }
839
840 $lineno = 0;
841 while (<IN>) {
842 $lineno++;
843
844 if ($state == 0) {
845 if (/$doc_start/o) {
846 $state = 1; # next line is always the function name
847 }
848 } elsif ($state == 1) { # this line is the function name (always)
849 if (/$doc_block/o) {
850 $state = 4;
851 $contents = "";
852 if ( $1 eq "" ) {
853 $section = $section_intro;
854 } else {
855 $section = $1;
856 }
857 }
858 elsif (/$doc_func/o) {
859 $function = $1;
860 $state = 2;
861 if (/-(.*)/) {
862 $function_purpose = $1;
863 } else {
864 $function_purpose = "";
865 }
866 if ($verbose) {
867 print STDERR "Info($lineno): Scanning doc for $function\n";
868 }
869 } else {
870 print STDERR "WARN($lineno): Cannot understand $_ on line $lineno",
871 " - I thought it was a doc line\n";
872 $state = 0;
873 }
874 } elsif ($state == 2) { # look for head: lines, and include content
875 if (/$doc_sect/o) {
876 $newsection = $1;
877 $newcontents = $2;
878
879 if ($contents ne "") {
880 $contents =~ s/\&/\\\\\\amp;/g;
881 $contents =~ s/\</\\\\\\lt;/g;
882 $contents =~ s/\>/\\\\\\gt;/g;
883 dump_section($section, $contents);
884 $section = $section_default;
885 }
886
887 $contents = $newcontents;
888 if ($contents ne "") {
889 $contents .= "\n";
890 }
891 $section = $newsection;
892 } elsif (/$doc_end/) {
893
894 if ($contents ne "") {
895 $contents =~ s/\&/\\\\\\amp;/g;
896 $contents =~ s/\</\\\\\\lt;/g;
897 $contents =~ s/\>/\\\\\\gt;/g;
898 dump_section($section, $contents);
899 $section = $section_default;
900 $contents = "";
901 }
902
903 # print STDERR "end of doc comment, looking for prototype\n";
904 $prototype = "";
905 $state = 3;
906 } elsif (/$doc_content/) {
907 # miguel-style comment kludge, look for blank lines after
908 # @parameter line to signify start of description
909 if ($1 eq "" && $section =~ m/^@/) {
910 $contents =~ s/\&/\\\\\\amp;/g;
911 $contents =~ s/\</\\\\\\lt;/g;
912 $contents =~ s/\>/\\\\\\gt;/g;
913 dump_section($section, $contents);
914 $section = $section_default;
915 $contents = "";
916 } else {
917 $contents .= $1."\n";
918 }
919 } else {
920 # i dont know - bad line? ignore.
921 print STDERR "WARNING($lineno): bad line: $_";
922 }
923 } elsif ($state == 3) { # scanning for function { (end of prototype)
924 if (m#\s*/\*\s+MACDOC\s*#io) {
925 # do nothing
926 }
927 elsif (/([^\{]*)/) {
928 $prototype .= $1;
929 }
930 if (/\{/ || /\#/) { # added for #define AK
931 $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
932 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
933 $prototype =~ s@^ +@@gos; # strip leading spaces
934 dump_function($prototype);
935
936 $function = "";
937 %constants = ();
938 %parameters = ();
939 %parametertypes = ();
940 @parameterlist = ();
941 %sections = ();
942 @sectionlist = ();
943 $prototype = "";
944
945 $state = 0;
946 }
947 } elsif ($state == 4) {
948 # Documentation block
949 if (/$doc_block/) {
950 dump_section($section, $contents);
951 output_intro({'sectionlist' => \@sectionlist,
952 'sections' => \%sections });
953 $contents = "";
954 $function = "";
955 %constants = ();
956 %parameters = ();
957 %parametertypes = ();
958 @parameterlist = ();
959 %sections = ();
960 @sectionlist = ();
961 $prototype = "";
962 if ( $1 eq "" ) {
963 $section = $section_intro;
964 } else {
965 $section = $1;
966 }
967 }
968 elsif (/$doc_end/)
969 {
970 dump_section($section, $contents);
971 output_intro({'sectionlist' => \@sectionlist,
972 'sections' => \%sections });
973 $contents = "";
974 $function = "";
975 %constants = ();
976 %parameters = ();
977 %parametertypes = ();
978 @parameterlist = ();
979 %sections = ();
980 @sectionlist = ();
981 $prototype = "";
982 $state = 0;
983 }
984 elsif (/$doc_content/)
985 {
986 if ( $1 eq "" )
987 {
988 $contents .= $blankline;
989 }
990 else
991 {
992 $contents .= $1 . "\n";
993 }
994 }
995 }
996 }
997 }
998
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.