]> git.ipfire.org Git - thirdparty/bird.git/blob - doc/kernel-doc
Doc: BFD update
[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 or a type
80 # '@parameter' - name of a parameter
81 # '%CONST' - name of a constant.
82 # '|code|' - literal string
83
84 # match expressions used to find embedded type information
85 $type_constant = "\\\%(\\w+)";
86 $type_func = "(\\w+\\(\\))";
87 $type_param = "\\\@(\\w+)";
88 $type_struct = "\\\&(\\w+)";
89 $type_env = "(\\\$\\w+)";
90 $type_code = "\\|([^|]*)\\|";
91
92
93 # Output conversion substitutions.
94 # One for each output format
95
96 # these work fairly well
97 %highlights_html = ( $type_constant, "<i>\$1</i>",
98 $type_func, "<b>\$1</b>",
99 $type_struct, "<i>\$1</i>",
100 $type_param, "<tt><b>\$1</b></tt>" );
101 $blankline_html = "<p>";
102
103 # sgml, docbook format
104 %highlights_sgml = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
105 $type_func, "<function>\$1</function>",
106 $type_struct, "<structname>\$1</structname>",
107 $type_env, "<envar>\$1</envar>",
108 $type_param, "<parameter>\$1</parameter>" );
109 $blankline_sgml = "</para><para>\n";
110
111 # gnome, docbook format
112 %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
113 $type_func, "<function>\$1</function>",
114 $type_struct, "<structname>\$1</structname>",
115 $type_env, "<envar>\$1</envar>",
116 $type_param, "<parameter>\$1</parameter>" );
117 $blankline_gnome = "</para><para>\n";
118
119 # bird documentation
120 %highlights_bird = ( $type_constant, "<const/\$1/",
121 $type_func, "<func/\$1/",
122 $type_struct, "<struct/\$1/",
123 $type_param, "<param/\$1/",
124 $type_code, "<tt>\$1</tt>");
125 $blankline_bird = "<p>";
126
127 # these are pretty rough
128 %highlights_man = ( $type_constant, "\\n.I \\\"\$1\\\"\\n",
129 $type_func, "\\n.B \\\"\$1\\\"\\n",
130 $type_struct, "\\n.I \\\"\$1\\\"\\n",
131 $type_param."([\.\, ]*)\n?", "\\n.I \\\"\$1\$2\\\"\\n" );
132 $blankline_man = "";
133
134 # text-mode
135 %highlights_text = ( $type_constant, "\$1",
136 $type_func, "\$1",
137 $type_struct, "\$1",
138 $type_param, "\$1" );
139 $blankline_text = "";
140
141
142 sub usage {
143 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
144 print " [ -function funcname [ -function funcname ...] ]\n";
145 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
146 print " c source file(s) > outputfile\n";
147 exit 1;
148 }
149
150 # read arguments
151 if ($#ARGV==-1) {
152 usage();
153 }
154
155 $verbose = 0;
156 $output_mode = "man";
157 %highlights = %highlights_man;
158 $blankline = $blankline_man;
159 $modulename = "API Documentation";
160 $function_only = 0;
161 while ($ARGV[0] =~ m/^-(.*)/) {
162 $cmd = shift @ARGV;
163 if ($cmd eq "-html") {
164 $output_mode = "html";
165 %highlights = %highlights_html;
166 $blankline = $blankline_html;
167 } elsif ($cmd eq "-man") {
168 $output_mode = "man";
169 %highlights = %highlights_man;
170 $blankline = $blankline_man;
171 } elsif ($cmd eq "-text") {
172 $output_mode = "text";
173 %highlights = %highlights_text;
174 $blankline = $blankline_text;
175 } elsif ($cmd eq "-docbook") {
176 $output_mode = "sgml";
177 %highlights = %highlights_sgml;
178 $blankline = $blankline_sgml;
179 } elsif ($cmd eq "-gnome") {
180 $output_mode = "gnome";
181 %highlights = %highlights_gnome;
182 $blankline = $blankline_gnome;
183 } elsif ($cmd eq "-bird") {
184 $output_mode = "bird";
185 %highlights = %highlights_bird;
186 $blankline = $blankline_bird;
187 } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
188 $modulename = shift @ARGV;
189 } elsif ($cmd eq "-function") { # to only output specific functions
190 $function_only = 1;
191 $function = shift @ARGV;
192 $function_table{$function} = 1;
193 } elsif ($cmd eq "-nofunction") { # to only output specific functions
194 $function_only = 2;
195 $function = shift @ARGV;
196 $function_table{$function} = 1;
197 } elsif ($cmd eq "-v") {
198 $verbose = 1;
199 } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
200 usage();
201 }
202 }
203
204
205 # generate a sequence of code that will splice in highlighting information
206 # using the s// operator.
207 $dohighlight = "";
208 foreach $pattern (keys %highlights) {
209 # print "scanning pattern $pattern ($highlights{$pattern})\n";
210 $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
211 }
212
213 ##
214 # dumps section contents to arrays/hashes intended for that purpose.
215 #
216 sub dump_section {
217 my $name = shift @_;
218 my $contents = join "\n", @_;
219
220 if ($name =~ m/$type_constant/) {
221 $name = $1;
222 # print STDERR "constant section '$1' = '$contents'\n";
223 $constants{$name} = $contents;
224 } elsif ($name =~ m/$type_param/) {
225 # print STDERR "parameter def '$1' = '$contents'\n";
226 $name = $1;
227 $parameters{$name} = $contents;
228 } else {
229 # print STDERR "other section '$name' = '$contents'\n";
230 $sections{$name} = $contents;
231 push @sectionlist, $name;
232 }
233 }
234
235 ##
236 # output function
237 #
238 # parameters, a hash.
239 # function => "function name"
240 # parameterlist => @list of parameters
241 # parameters => %parameter descriptions
242 # sectionlist => @list of sections
243 # sections => %descriont descriptions
244 #
245
246 sub output_highlight {
247 my $contents = join "\n", @_;
248 my $line;
249
250 eval $dohighlight;
251 foreach $line (split "\n", $contents) {
252 if ($line eq ""){
253 print $lineprefix, $blankline;
254 } else {
255 $line =~ s/\\\\\\/\&/g;
256 print $lineprefix, $line;
257 }
258 print "\n";
259 }
260 }
261
262
263 # output in html
264 sub output_html {
265 my %args = %{$_[0]};
266 my ($parameter, $section);
267 my $count;
268 print "<h2>Function</h2>\n";
269
270 print "<i>".$args{'functiontype'}."</i>\n";
271 print "<b>".$args{'function'}."</b>\n";
272 print "(";
273 $count = 0;
274 foreach $parameter (@{$args{'parameterlist'}}) {
275 print "<i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
276 if ($count != $#{$args{'parameterlist'}}) {
277 $count++;
278 print ", ";
279 }
280 }
281 print ")\n";
282
283 print "<h3>Arguments</h3>\n";
284 print "<dl>\n";
285 foreach $parameter (@{$args{'parameterlist'}}) {
286 print "<dt><i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
287 print "<dd>";
288 output_highlight($args{'parameters'}{$parameter});
289 }
290 print "</dl>\n";
291 foreach $section (@{$args{'sectionlist'}}) {
292 print "<h1>$section</h1>\n";
293 print "<ul>\n";
294 output_highlight($args{'sections'}{$section});
295 print "</ul>\n";
296 }
297 print "<hr>\n";
298 }
299
300
301 # output in html
302 sub output_intro_html {
303 my %args = %{$_[0]};
304 my ($parameter, $section);
305 my $count;
306
307 foreach $section (@{$args{'sectionlist'}}) {
308 print "<h1>$section</h1>\n";
309 print "<ul>\n";
310 output_highlight($args{'sections'}{$section});
311 print "</ul>\n";
312 }
313 print "<hr>\n";
314 }
315
316
317
318 # output in sgml DocBook
319 sub output_sgml {
320 my %args = %{$_[0]};
321 my ($parameter, $section);
322 my $count;
323 my $id;
324
325 $id = $args{'module'}."-".$args{'function'};
326 $id =~ s/[^A-Za-z0-9]/-/g;
327
328 print "<refentry>\n";
329 print "<refmeta>\n";
330 print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
331 print "</refmeta>\n";
332 print "<refnamediv>\n";
333 print " <refname>".$args{'function'}."</refname>\n";
334 print " <refpurpose>\n";
335 print " ".$args{'purpose'}."\n";
336 print " </refpurpose>\n";
337 print "</refnamediv>\n";
338
339 print "<refsynopsisdiv>\n";
340 print " <title>Synopsis</title>\n";
341 print " <funcsynopsis>\n";
342 print " <funcdef>".$args{'functiontype'}." ";
343 print "<function>".$args{'function'}." ";
344 print "</function></funcdef>\n";
345
346 # print "<refsect1>\n";
347 # print " <title>Synopsis</title>\n";
348 # print " <funcsynopsis>\n";
349 # print " <funcdef>".$args{'functiontype'}." ";
350 # print "<function>".$args{'function'}." ";
351 # print "</function></funcdef>\n";
352
353 $count = 0;
354 if ($#{$args{'parameterlist'}} >= 0) {
355 foreach $parameter (@{$args{'parameterlist'}}) {
356 print " <paramdef>".$args{'parametertypes'}{$parameter};
357 print " <parameter>$parameter</parameter></paramdef>\n";
358 }
359 } else {
360 print " <void>\n";
361 }
362 print " </funcsynopsis>\n";
363 print "</refsynopsisdiv>\n";
364 # print "</refsect1>\n";
365
366 # print parameters
367 print "<refsect1>\n <title>Arguments</title>\n";
368 # print "<para>\nArguments\n";
369 if ($#{$args{'parameterlist'}} >= 0) {
370 print " <variablelist>\n";
371 foreach $parameter (@{$args{'parameterlist'}}) {
372 print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
373 print " <listitem>\n <para>\n";
374 $lineprefix=" ";
375 output_highlight($args{'parameters'}{$parameter});
376 print " </para>\n </listitem>\n </varlistentry>\n";
377 }
378 print " </variablelist>\n";
379 } else {
380 print " <para>\n None\n </para>\n";
381 }
382 print "</refsect1>\n";
383
384 # print out each section
385 $lineprefix=" ";
386 foreach $section (@{$args{'sectionlist'}}) {
387 print "<refsect1>\n <title>$section</title>\n <para>\n";
388 # print "<para>\n$section\n";
389 if ($section =~ m/EXAMPLE/i) {
390 print "<example><para>\n";
391 }
392 output_highlight($args{'sections'}{$section});
393 # print "</para>";
394 if ($section =~ m/EXAMPLE/i) {
395 print "</para></example>\n";
396 }
397 print " </para>\n</refsect1>\n";
398 }
399
400 print "</refentry>\n\n";
401 }
402
403 # output in sgml DocBook
404 sub output_intro_sgml {
405 my %args = %{$_[0]};
406 my ($parameter, $section);
407 my $count;
408 my $id;
409
410 $id = $args{'module'};
411 $id =~ s/[^A-Za-z0-9]/-/g;
412
413 # print out each section
414 $lineprefix=" ";
415 foreach $section (@{$args{'sectionlist'}}) {
416 print "<refsect1>\n <title>$section</title>\n <para>\n";
417 # print "<para>\n$section\n";
418 if ($section =~ m/EXAMPLE/i) {
419 print "<example><para>\n";
420 }
421 output_highlight($args{'sections'}{$section});
422 # print "</para>";
423 if ($section =~ m/EXAMPLE/i) {
424 print "</para></example>\n";
425 }
426 print " </para>\n</refsect1>\n";
427 }
428
429 print "\n\n";
430 }
431
432 # output in sgml DocBook
433 sub output_gnome {
434 my %args = %{$_[0]};
435 my ($parameter, $section);
436 my $count;
437 my $id;
438
439 $id = $args{'module'}."-".$args{'function'};
440 $id =~ s/[^A-Za-z0-9]/-/g;
441
442 print "<sect2>\n";
443 print " <title id=\"$id\">".$args{'function'}."</title>\n";
444
445 # print "<simplesect>\n";
446 # print " <title>Synopsis</title>\n";
447 print " <funcsynopsis>\n";
448 print " <funcdef>".$args{'functiontype'}." ";
449 print "<function>".$args{'function'}." ";
450 print "</function></funcdef>\n";
451
452 $count = 0;
453 if ($#{$args{'parameterlist'}} >= 0) {
454 foreach $parameter (@{$args{'parameterlist'}}) {
455 print " <paramdef>".$args{'parametertypes'}{$parameter};
456 print " <parameter>$parameter</parameter></paramdef>\n";
457 }
458 } else {
459 print " <void>\n";
460 }
461 print " </funcsynopsis>\n";
462 # print "</simplesect>\n";
463 # print "</refsect1>\n";
464
465 # print parameters
466 # print "<simplesect>\n <title>Arguments</title>\n";
467 # if ($#{$args{'parameterlist'}} >= 0) {
468 # print " <variablelist>\n";
469 # foreach $parameter (@{$args{'parameterlist'}}) {
470 # print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
471 # print " <listitem>\n <para>\n";
472 # $lineprefix=" ";
473 # output_highlight($args{'parameters'}{$parameter});
474 # print " </para>\n </listitem>\n </varlistentry>\n";
475 # }
476 # print " </variablelist>\n";
477 # } else {
478 # print " <para>\n None\n </para>\n";
479 # }
480 # print "</simplesect>\n";
481
482 # print "<simplesect>\n <title>Arguments</title>\n";
483 if ($#{$args{'parameterlist'}} >= 0) {
484 print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
485 print "<tgroup cols=\"2\">\n";
486 print "<colspec colwidth=\"2*\">\n";
487 print "<colspec colwidth=\"8*\">\n";
488 print "<tbody>\n";
489 foreach $parameter (@{$args{'parameterlist'}}) {
490 print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
491 print " <entry>\n";
492 $lineprefix=" ";
493 output_highlight($args{'parameters'}{$parameter});
494 print " </entry></row>\n";
495 }
496 print " </tbody></tgroup></informaltable>\n";
497 } else {
498 print " <para>\n None\n </para>\n";
499 }
500 # print "</simplesect>\n";
501
502 # print out each section
503 $lineprefix=" ";
504 foreach $section (@{$args{'sectionlist'}}) {
505 print "<simplesect>\n <title>$section</title>\n";
506 # print "<para>\n$section\n";
507 if ($section =~ m/EXAMPLE/i) {
508 print "<example><programlisting>\n";
509 } else {
510 }
511 print "<para>\n";
512 output_highlight($args{'sections'}{$section});
513 # print "</para>";
514 print "</para>\n";
515 if ($section =~ m/EXAMPLE/i) {
516 print "</programlisting></example>\n";
517 } else {
518 }
519 print " </simplesect>\n";
520 }
521
522 print "</sect2>\n\n";
523 }
524
525 # output in birddoc
526 sub output_bird {
527 my %args = %{$_[0]};
528 my ($parameter, $section);
529 my $count;
530 print "<function><p><type>".$args{'functiontype'}."</type>\n";
531 print "<funcdef>".$args{'function'}."</funcdef>\n";
532 print "(";
533 $count = 0;
534 my $ntyped = 0;
535 foreach $parameter (@{$args{'parameterlist'}}) {
536 if ($args{'parametertypes'}{$parameter} ne "") {
537 print "<type>".$args{'parametertypes'}{$parameter}."</type> ";
538 $ntyped++;
539 }
540 print "<param>".$parameter."</param>";
541 if ($count != $#{$args{'parameterlist'}}) {
542 $count++;
543 print ", ";
544 }
545 }
546 print ")";
547 if ($args{'purpose'} ne "") {
548 print " -- ";
549 output_highlight($args{'purpose'});
550 }
551 print "\n";
552
553 if ($ntyped) {
554 print "<funcsect>Arguments\n";
555 print "<p><descrip>\n";
556 foreach $parameter (@{$args{'parameterlist'}}) {
557 print "<tagp><type>".$args{'parametertypes'}{$parameter}."</type> <param>".$parameter."</param></tagp>\n";
558 output_highlight($args{'parameters'}{$parameter});
559 }
560 print "</descrip>\n";
561 }
562 foreach $section (@{$args{'sectionlist'}}) {
563 print "<funcsect>$section\n";
564 print "<p>\n";
565 output_highlight($args{'sections'}{$section});
566 }
567 print "</function>\n";
568 }
569
570 # output in birddoc
571 sub output_intro_bird {
572 my %args = %{$_[0]};
573 my ($parameter, $section);
574 my $count;
575 my $id;
576
577 $id = $args{'module'};
578 $id =~ s/[^A-Za-z0-9]/-/g;
579
580 # print out each section
581 $lineprefix=" ";
582 foreach $section (@{$args{'sectionlist'}}) {
583 print "<sect>$section\n<p>\n";
584 output_highlight($args{'sections'}{$section});
585 }
586
587 print "\n\n";
588 }
589
590 ##
591 # output in man
592 sub output_man {
593 my %args = %{$_[0]};
594 my ($parameter, $section);
595 my $count;
596
597 print ".TH \"$args{'module'}\" \"$args{'function'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
598
599 print ".SH Function\n";
600
601 print ".I \"".$args{'functiontype'}."\"\n";
602 print ".B \"".$args{'function'}."\"\n";
603 print "(\n";
604 $count = 0;
605 foreach $parameter (@{$args{'parameterlist'}}) {
606 print ".I \"".$args{'parametertypes'}{$parameter}."\"\n.B \"".$parameter."\"\n";
607 if ($count != $#{$args{'parameterlist'}}) {
608 $count++;
609 print ",\n";
610 }
611 }
612 print ")\n";
613
614 print ".SH Arguments\n";
615 foreach $parameter (@{$args{'parameterlist'}}) {
616 print ".IP \"".$args{'parametertypes'}{$parameter}." ".$parameter."\" 12\n";
617 output_highlight($args{'parameters'}{$parameter});
618 }
619 foreach $section (@{$args{'sectionlist'}}) {
620 print ".SH \"$section\"\n";
621 output_highlight($args{'sections'}{$section});
622 }
623 }
624
625 sub output_intro_man {
626 my %args = %{$_[0]};
627 my ($parameter, $section);
628 my $count;
629
630 print ".TH \"$args{'module'}\" \"$args{'module'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
631
632 foreach $section (@{$args{'sectionlist'}}) {
633 print ".SH \"$section\"\n";
634 output_highlight($args{'sections'}{$section});
635 }
636 }
637
638 ##
639 # output in text
640 sub output_text {
641 my %args = %{$_[0]};
642 my ($parameter, $section);
643
644 print "Function = ".$args{'function'}."\n";
645 print " return type: ".$args{'functiontype'}."\n\n";
646 foreach $parameter (@{$args{'parameterlist'}}) {
647 print " ".$args{'parametertypes'}{$parameter}." ".$parameter."\n";
648 print " -> ".$args{'parameters'}{$parameter}."\n";
649 }
650 foreach $section (@{$args{'sectionlist'}}) {
651 print " $section:\n";
652 print " -> ";
653 output_highlight($args{'sections'}{$section});
654 }
655 }
656
657 sub output_intro_text {
658 my %args = %{$_[0]};
659 my ($parameter, $section);
660
661 foreach $section (@{$args{'sectionlist'}}) {
662 print " $section:\n";
663 print " -> ";
664 output_highlight($args{'sections'}{$section});
665 }
666 }
667
668 ##
669 # generic output function - calls the right one based
670 # on current output mode.
671 sub output_function {
672 # output_html(@_);
673 eval "output_".$output_mode."(\@_);";
674 }
675
676 ##
677 # generic output function - calls the right one based
678 # on current output mode.
679 sub output_intro {
680 # output_html(@_);
681 eval "output_intro_".$output_mode."(\@_);";
682 }
683
684
685 ##
686 # takes a function prototype and spits out all the details
687 # stored in the global arrays/hsahes.
688 sub dump_function {
689 my $prototype = shift @_;
690
691 $prototype =~ s/^static+ //;
692 $prototype =~ s/^extern+ //;
693 $prototype =~ s/^inline+ //;
694 $prototype =~ s/^__inline__+ //;
695
696 if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
697 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
698 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
699 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
700 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/) {
701 $return_type = $1;
702 $function_name = $2;
703 $args = $3;
704
705 # print STDERR "ARGS = '$args'\n";
706
707 foreach $arg (split ',', $args) {
708 # strip leading/trailing spaces
709 $arg =~ s/^\s*//;
710 $arg =~ s/\s*$//;
711 # print STDERR "SCAN ARG: '$arg'\n";
712 @args = split('\s', $arg);
713
714 # print STDERR " -> @args\n";
715 $param = pop @args;
716 # print STDERR " -> @args\n";
717 if ($param =~ m/^(\*+)(.*)/) {
718 $param = $2;
719 push @args, $1;
720 }
721 $type = join " ", @args;
722
723 if ($type eq "" && $param eq "...")
724 {
725 $type="...";
726 $param="...";
727 $parameters{"..."} = "variable arguments";
728 }
729 if ($type eq "")
730 {
731 $type="";
732 $param="void";
733 $parameters{void} = "no arguments";
734 }
735 if ($parameters{$param} eq "") {
736 $parameters{$param} = "-- undescribed --";
737 print STDERR "Warning($lineno): Function parameter '$param' not described in '$function_name'\n";
738 }
739
740 push @parameterlist, $param;
741 $parametertypes{$param} = $type;
742 # print STDERR "param = '$param', type = '$type'\n";
743 }
744 } else {
745 print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n";
746 return;
747 }
748
749 if ($function_only==0 ||
750 ( $function_only == 1 && defined($function_table{$function_name})) ||
751 ( $function_only == 2 && !defined($function_table{$function_name})))
752 {
753 output_function({'function' => $function_name,
754 'module' => $modulename,
755 'functiontype' => $return_type,
756 'parameterlist' => \@parameterlist,
757 'parameters' => \%parameters,
758 'parametertypes' => \%parametertypes,
759 'sectionlist' => \@sectionlist,
760 'sections' => \%sections,
761 'purpose' => $function_purpose
762 });
763 }
764 }
765
766 ######################################################################
767 # main
768 # states
769 # 0 - normal code
770 # 1 - looking for function name
771 # 2 - scanning field start.
772 # 3 - scanning prototype.
773 $state = 0;
774 $section = "";
775
776 $doc_special = "\@\%\$\&";
777
778 $doc_start = "^/\\*\\*\$";
779 $doc_end = "\\*/";
780 $doc_com = "\\s*\\*\\s*";
781 $doc_func = $doc_com."(\\w+):?";
782 $doc_sect = $doc_com."([".$doc_special."]?[\\w ]+):(.*)";
783 $doc_content = $doc_com."(.*)";
784 $doc_block = $doc_com."DOC:\\s*(.*)?";
785
786 %constants = ();
787 %parameters = ();
788 @parameterlist = ();
789 %sections = ();
790 @sectionlist = ();
791
792 $contents = "";
793 $section_default = "Description"; # default section
794 $section_intro = "Introduction";
795 $section = $section_default;
796
797 $lineno = 0;
798 foreach $file (@ARGV) {
799 if (!open(IN,"<$file")) {
800 print STDERR "Error: Cannot open file $file\n";
801 next;
802 }
803 while (<IN>) {
804 $lineno++;
805
806 if ($state == 0) {
807 if (/$doc_start/o) {
808 $state = 1; # next line is always the function name
809 }
810 } elsif ($state == 1) { # this line is the function name (always)
811 if (/$doc_block/o) {
812 $state = 4;
813 $contents = "";
814 if ( $1 eq "" ) {
815 $section = $section_intro;
816 } else {
817 $section = $1;
818 }
819 }
820 elsif (/$doc_func/o) {
821 $function = $1;
822 $state = 2;
823 if (/-(.*)/) {
824 $function_purpose = $1;
825 } else {
826 $function_purpose = "";
827 }
828 if ($verbose) {
829 print STDERR "Info($lineno): Scanning doc for $function\n";
830 }
831 } else {
832 print STDERR "WARN($lineno): Cannot understand $_ on line $lineno",
833 " - I thought it was a doc line\n";
834 $state = 0;
835 }
836 } elsif ($state == 2) { # look for head: lines, and include content
837 if (/$doc_sect/o) {
838 $newsection = $1;
839 $newcontents = $2;
840
841 if ($contents ne "") {
842 # $contents =~ s/\&/\\\\\\amp;/g;
843 $contents =~ s/\</\\\\\\lt;/g;
844 $contents =~ s/\>/\\\\\\gt;/g;
845 dump_section($section, $contents);
846 $section = $section_default;
847 }
848
849 $contents = $newcontents;
850 if ($contents ne "") {
851 $contents .= "\n";
852 }
853 $section = $newsection;
854 } elsif (/$doc_end/) {
855
856 if ($contents ne "") {
857 # $contents =~ s/\&/\\\\\\amp;/g;
858 $contents =~ s/\</\\\\\\lt;/g;
859 $contents =~ s/\>/\\\\\\gt;/g;
860 dump_section($section, $contents);
861 $section = $section_default;
862 $contents = "";
863 }
864
865 # print STDERR "end of doc comment, looking for prototype\n";
866 $prototype = "";
867 $state = 3;
868 } elsif (/$doc_content/) {
869 # miguel-style comment kludge, look for blank lines after
870 # @parameter line to signify start of description
871 if ($1 eq "" && $section =~ m/^@/) {
872 # $contents =~ s/\&/\\\\\\amp;/g;
873 $contents =~ s/\</\\\\\\lt;/g;
874 $contents =~ s/\>/\\\\\\gt;/g;
875 dump_section($section, $contents);
876 $section = $section_default;
877 $contents = "";
878 } else {
879 $contents .= $1."\n";
880 }
881 } else {
882 # i dont know - bad line? ignore.
883 print STDERR "WARNING($lineno): bad line: $_";
884 }
885 } elsif ($state == 3) { # scanning for function { (end of prototype)
886 if (m#\s*/\*\s+MACDOC\s*#io) {
887 # do nothing
888 }
889 elsif (/([^\{]*)/) {
890 $prototype .= $1;
891 }
892 if (/\{/) {
893 $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
894 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
895 $prototype =~ s@^ +@@gos; # strip leading spaces
896 dump_function($prototype);
897
898 $function = "";
899 %constants = ();
900 %parameters = ();
901 %parametertypes = ();
902 @parameterlist = ();
903 %sections = ();
904 @sectionlist = ();
905 $prototype = "";
906
907 $state = 0;
908 }
909 } elsif ($state == 4) {
910 # Documentation block
911 if (/$doc_block/) {
912 # $contents =~ s/\&/\\\\\\amp;/g;
913 $contents =~ s/\</\\\\\\lt;/g;
914 $contents =~ s/\>/\\\\\\gt;/g;
915 dump_section($section, $contents);
916 output_intro({'sectionlist' => \@sectionlist,
917 'sections' => \%sections });
918 $contents = "";
919 $function = "";
920 %constants = ();
921 %parameters = ();
922 %parametertypes = ();
923 @parameterlist = ();
924 %sections = ();
925 @sectionlist = ();
926 $prototype = "";
927 if ( $1 eq "" ) {
928 $section = $section_intro;
929 } else {
930 $section = $1;
931 }
932 }
933 elsif (/$doc_end/)
934 {
935 # $contents =~ s/\&/\\\\\\amp;/g;
936 $contents =~ s/\</\\\\\\lt;/g;
937 $contents =~ s/\>/\\\\\\gt;/g;
938 dump_section($section, $contents);
939 output_intro({'sectionlist' => \@sectionlist,
940 'sections' => \%sections });
941 $contents = "";
942 $function = "";
943 %constants = ();
944 %parameters = ();
945 %parametertypes = ();
946 @parameterlist = ();
947 %sections = ();
948 @sectionlist = ();
949 $prototype = "";
950 $state = 0;
951 }
952 elsif (/$doc_content/)
953 {
954 if ( $1 eq "" )
955 {
956 $contents .= "\n";
957 }
958 else
959 {
960 $contents .= $1 . "\n";
961 }
962 }
963 }
964 }
965 }
966