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