Lines 1-863
Link Here
|
1 |
#!/usr/bin/perl |
|
|
2 |
|
3 |
## Copyright (c) 2002, 2003 Simon Josefsson ## |
4 |
## added -texinfo, -listfunc ## |
5 |
## man page revamp ## |
6 |
## various improvements ## |
7 |
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ## |
8 |
## hacked to allow -tex option --nmav ## |
9 |
## ## |
10 |
## This software falls under the GNU Public License. Please read ## |
11 |
## the COPYING file for more information ## |
12 |
|
13 |
# |
14 |
# This will read a 'c' file and scan for embedded comments in the |
15 |
# style of gnome comments (+minor extensions - see below). |
16 |
# |
17 |
# This program is modified by Nikos Mavroyanopoulos, for the gnutls |
18 |
# project. |
19 |
|
20 |
# Note: This only supports 'c'. |
21 |
|
22 |
# usage: |
23 |
# gdoc [ -docbook | -html | -text | -man | -tex | -texinfo | -listfunc ] |
24 |
# [ -sourceversion verno ] [ -includefuncprefix ] [ -bugsto address ] |
25 |
# [ -seeinfo infonode ] [ -copyright notice ] [ -verbatimcopying ] |
26 |
# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile |
27 |
# |
28 |
# Set output format using one of -docbook, -html, -text, -man, -tex, |
29 |
# -texinfo, or -listfunc. Default is man. |
30 |
# |
31 |
# -sourceversion |
32 |
# Version number for source code, e.g. '1.0.4'. Used in 'man' headers. |
33 |
# Defaults to using current date. |
34 |
# |
35 |
# -includefuncprefix |
36 |
# For man pages, generate a #include <FILE.h> based on the function |
37 |
# prefix. For example, a function gss_init_sec_context will generate |
38 |
# an include statement of #include <gss.h>. |
39 |
# |
40 |
# -bugsto address |
41 |
# For man pages, include a section about reporting bugs and mention |
42 |
# the given e-mail address, e.g 'bug-libidn@gnu.org'. |
43 |
# |
44 |
# -seeinfo infonode |
45 |
# For man pages, include a section that point to an info manual |
46 |
# for more information. |
47 |
# |
48 |
# -copyright notice |
49 |
# For man pages, include a copyright section with the given |
50 |
# notice after a preamble. Use, e.g., '2002, 2003 Simon Josefsson'. |
51 |
# |
52 |
# -verbatimcopying |
53 |
# For man pages, and when the -copyright parameter is used, |
54 |
# add a licensing statement that say verbatim copying is permitted. |
55 |
# |
56 |
# -function funcname |
57 |
# If set, then only generate documentation for the given function(s). All |
58 |
# other functions are ignored. |
59 |
# |
60 |
# c files - list of 'c' files to process |
61 |
# |
62 |
# All output goes to stdout, with errors to stderr. |
63 |
|
64 |
# |
65 |
# format of comments. |
66 |
# In the following table, (...)? signifies optional structure. |
67 |
# (...)* signifies 0 or more structure elements |
68 |
# /** |
69 |
# * function_name(:)? (- short description)? |
70 |
# (* @parameterx: (description of parameter x)?)* |
71 |
# (* a blank line)? |
72 |
# * (Description:)? (Description of function)? |
73 |
# * (Section header: (section description)? )* |
74 |
# (*)?*/ |
75 |
# |
76 |
# So .. the trivial example would be: |
77 |
# |
78 |
# /** |
79 |
# * my_function |
80 |
# **/ |
81 |
# |
82 |
# If the Description: header tag is ommitted, then there must be a blank line |
83 |
# after the last parameter specification. |
84 |
# e.g. |
85 |
# /** |
86 |
# * my_function - does my stuff |
87 |
# * @my_arg: its mine damnit |
88 |
# * |
89 |
# * Does my stuff explained. |
90 |
# */ |
91 |
# |
92 |
# or, could also use: |
93 |
# /** |
94 |
# * my_function - does my stuff |
95 |
# * @my_arg: its mine damnit |
96 |
# * Description: Does my stuff explained. |
97 |
# */ |
98 |
# etc. |
99 |
# |
100 |
# All descriptions can be multiline, apart from the short function description. |
101 |
# |
102 |
# All descriptive text is further processed, scanning for the following special |
103 |
# patterns, which are highlighted appropriately. |
104 |
# |
105 |
# 'funcname()' - function |
106 |
# '$ENVVAR' - environmental variable |
107 |
# '&struct_name' - name of a structure |
108 |
# '@parameter' - name of a parameter |
109 |
# '%CONST' - name of a constant. |
110 |
|
111 |
# |
112 |
# Extensions for LaTeX: |
113 |
# |
114 |
# 1. the symbol '->' will be replaced with a rightarrow |
115 |
# 2. x^y with ${x}^{y}$. |
116 |
# 3. xxx\: with xxx: |
117 |
|
118 |
use POSIX qw(strftime); |
119 |
|
120 |
# match expressions used to find embedded type information |
121 |
$type_constant = "\\\%(\\w+)"; |
122 |
$type_func = "(\\w+\\(\\))"; |
123 |
#$type_func = "((\\w|\\\\)+\\(\\))"; |
124 |
#$type_func = "(\\(w||\\\\)+\\(\\))"; |
125 |
$type_param = "\\\@(\\w+)"; |
126 |
$type_struct = "\\\&(\\w+)"; |
127 |
$type_env = "(\\\$\\w+)"; |
128 |
|
129 |
|
130 |
# Output conversion substitutions. |
131 |
# One for each output format |
132 |
|
133 |
# these work fairly well |
134 |
%highlights_html = ( $type_constant, "<i>\$1</i>", |
135 |
$type_func, "<b>\$1</b>", |
136 |
$type_struct, "<i>\$1</i>", |
137 |
$type_param, "<tt><b>\$1</b></tt>" ); |
138 |
$blankline_html = "<p>"; |
139 |
|
140 |
%highlights_texinfo = ( $type_constant, "\\\@var{\$1}", |
141 |
$type_func, "\\\@code{\$1}", |
142 |
$type_struct, "\\\@code{\$1}", |
143 |
$type_param, "\\\@code{\$1}" ); |
144 |
$blankline_texinfo = ""; |
145 |
|
146 |
%highlights_tex = ( $type_constant, "{\\\\it \$1}", |
147 |
$type_func, "{\\\\bf \$1}", |
148 |
$type_struct, "{\\\\it \$1}", |
149 |
$type_param, "{\\\\bf \$1}" ); |
150 |
$blankline_tex = "\\"; |
151 |
|
152 |
# sgml, docbook format |
153 |
%highlights_sgml = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>", |
154 |
$type_func, "<function>\$1</function>", |
155 |
$type_struct, "<structname>\$1</structname>", |
156 |
$type_env, "<envar>\$1</envar>", |
157 |
$type_param, "<parameter>\$1</parameter>" ); |
158 |
$blankline_sgml = "</para><para>\n"; |
159 |
|
160 |
# these are pretty rough |
161 |
%highlights_man = ( $type_constant, "\\n.I \\\"\$1\\\"\\n", |
162 |
$type_func, "\\n.B \\\"\$1\\\"\\n", |
163 |
$type_struct, "\\n.I \\\"\$1\\\"\\n", |
164 |
$type_param."([\.\, ]*)\n?", "\\n.I \\\"\$1\$2\\\"\\n" ); |
165 |
$blankline_man = ""; |
166 |
|
167 |
# text-mode |
168 |
%highlights_text = ( $type_constant, "\$1", |
169 |
$type_func, "\$1", |
170 |
$type_struct, "\$1", |
171 |
$type_param, "\$1" ); |
172 |
$blankline_text = ""; |
173 |
|
174 |
|
175 |
sub usage { |
176 |
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -tex | -texinfo -listfunc ]\n"; |
177 |
print " [ -sourceversion verno ] [ -includefuncprefix ]\n"; |
178 |
print " [ -bugsto address ] [ -seeinfo infonode ] [ -copyright notice]\n"; |
179 |
print " [ -verbatimcopying ]\n"; |
180 |
print " [ -function funcname [ -function funcname ...] ]\n"; |
181 |
print " c source file(s) > outputfile\n"; |
182 |
exit 1; |
183 |
} |
184 |
|
185 |
# read arguments |
186 |
if ($#ARGV==-1) { |
187 |
usage(); |
188 |
} |
189 |
|
190 |
$verbose = 0; |
191 |
$output_mode = "man"; |
192 |
%highlights = %highlights_man; |
193 |
$blankline = $blankline_man; |
194 |
$modulename = "API Documentation"; |
195 |
$sourceversion = strftime "%Y-%m-%d", localtime; |
196 |
$function_only = 0; |
197 |
while ($ARGV[0] =~ m/^-(.*)/) { |
198 |
$cmd = shift @ARGV; |
199 |
if ($cmd eq "-html") { |
200 |
$output_mode = "html"; |
201 |
%highlights = %highlights_html; |
202 |
$blankline = $blankline_html; |
203 |
} elsif ($cmd eq "-man") { |
204 |
$output_mode = "man"; |
205 |
%highlights = %highlights_man; |
206 |
$blankline = $blankline_man; |
207 |
} elsif ($cmd eq "-tex") { |
208 |
$output_mode = "tex"; |
209 |
%highlights = %highlights_tex; |
210 |
$blankline = $blankline_tex; |
211 |
} elsif ($cmd eq "-texinfo") { |
212 |
$output_mode = "texinfo"; |
213 |
%highlights = %highlights_texinfo; |
214 |
$blankline = $blankline_texinfo; |
215 |
} elsif ($cmd eq "-text") { |
216 |
$output_mode = "text"; |
217 |
%highlights = %highlights_text; |
218 |
$blankline = $blankline_text; |
219 |
} elsif ($cmd eq "-docbook") { |
220 |
$output_mode = "sgml"; |
221 |
%highlights = %highlights_sgml; |
222 |
$blankline = $blankline_sgml; |
223 |
} elsif ($cmd eq "-listfunc") { |
224 |
$output_mode = "listfunc"; |
225 |
} elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document |
226 |
$modulename = shift @ARGV; |
227 |
} elsif ($cmd eq "-sourceversion") { |
228 |
$sourceversion = shift @ARGV; |
229 |
} elsif ($cmd eq "-includefuncprefix") { |
230 |
$includefuncprefix = 1; |
231 |
} elsif ($cmd eq "-bugsto") { |
232 |
$bugsto = shift @ARGV; |
233 |
} elsif ($cmd eq "-copyright") { |
234 |
$copyright = shift @ARGV; |
235 |
} elsif ($cmd eq "-verbatimcopying") { |
236 |
$verbatimcopying = 1; |
237 |
} elsif ($cmd eq "-seeinfo") { |
238 |
$seeinfo = shift @ARGV; |
239 |
} elsif ($cmd eq "-function") { # to only output specific functions |
240 |
$function_only = 1; |
241 |
$function = shift @ARGV; |
242 |
$function_table{$function} = 1; |
243 |
} elsif ($cmd eq "-v") { |
244 |
$verbose = 1; |
245 |
} elsif (($cmd eq "-h") || ($cmd eq "--help")) { |
246 |
usage(); |
247 |
} |
248 |
} |
249 |
|
250 |
## |
251 |
# dumps section contents to arrays/hashes intended for that purpose. |
252 |
# |
253 |
sub dump_section { |
254 |
my $name = shift @_; |
255 |
my $contents = join "\n", @_; |
256 |
|
257 |
if ($name =~ m/$type_constant/) { |
258 |
$name = $1; |
259 |
# print STDERR "constant section '$1' = '$contents'\n"; |
260 |
$constants{$name} = $contents; |
261 |
} elsif ($name =~ m/$type_param/) { |
262 |
# print STDERR "parameter def '$1' = '$contents'\n"; |
263 |
$name = $1; |
264 |
$parameters{$name} = $contents; |
265 |
} else { |
266 |
# print STDERR "other section '$name' = '$contents'\n"; |
267 |
$sections{$name} = $contents; |
268 |
push @sectionlist, $name; |
269 |
} |
270 |
} |
271 |
|
272 |
## |
273 |
# output function |
274 |
# |
275 |
# parameters, a hash. |
276 |
# function => "function name" |
277 |
# parameterlist => @list of parameters |
278 |
# parameters => %parameter descriptions |
279 |
# sectionlist => @list of sections |
280 |
# sections => %descriont descriptions |
281 |
# |
282 |
|
283 |
sub repstr { |
284 |
$pattern = shift; |
285 |
$repl = shift; |
286 |
$match1 = shift; |
287 |
$match2 = shift; |
288 |
$match3 = shift; |
289 |
$match4 = shift; |
290 |
|
291 |
$output = $repl; |
292 |
$output =~ s,\$1,$match1,g; |
293 |
$output =~ s,\$2,$match2,g; |
294 |
$output =~ s,\$3,$match3,g; |
295 |
$output =~ s,\$4,$match4,g; |
296 |
|
297 |
eval "\$return = qq/$output/"; |
298 |
|
299 |
# print "pattern $pattern matched 1=$match1 2=$match2 3=$match3 4=$match4 replace $repl yielded $output interpolated $return\n"; |
300 |
|
301 |
$return; |
302 |
} |
303 |
|
304 |
sub output_highlight { |
305 |
my $contents = join "\n", @_; |
306 |
my $line; |
307 |
|
308 |
foreach $pattern (keys %highlights) { |
309 |
# print "scanning pattern $pattern ($highlights{$pattern})\n"; |
310 |
$contents =~ s:$pattern:repstr($pattern, $highlights{$pattern}, $1, $2, $3, $4):gse; |
311 |
} |
312 |
foreach $line (split "\n", $contents) { |
313 |
if ($line eq ""){ |
314 |
print $lineprefix, $blankline; |
315 |
} else { |
316 |
print $lineprefix, $line; |
317 |
} |
318 |
print "\n"; |
319 |
} |
320 |
} |
321 |
|
322 |
# output in texinfo |
323 |
sub output_texinfo { |
324 |
my %args = %{$_[0]}; |
325 |
my ($parameter, $section); |
326 |
my $count; |
327 |
|
328 |
print "\@deftypefun {" . $args{'functiontype'} . "} "; |
329 |
print "{".$args{'function'}."} "; |
330 |
print "("; |
331 |
$count = 0; |
332 |
foreach $parameter (@{$args{'parameterlist'}}) { |
333 |
print $args{'parametertypes'}{$parameter}." \@var{".$parameter."}"; |
334 |
if ($count != $#{$args{'parameterlist'}}) { |
335 |
$count++; |
336 |
print ", "; |
337 |
} |
338 |
} |
339 |
print ")\n"; |
340 |
foreach $parameter (@{$args{'parameterlist'}}) { |
341 |
if ($args{'parameters'}{$parameter}) { |
342 |
print "\@var{".$parameter."}: "; |
343 |
output_highlight($args{'parameters'}{$parameter}); |
344 |
print "\n"; |
345 |
} |
346 |
} |
347 |
foreach $section (@{$args{'sectionlist'}}) { |
348 |
print "\n\@strong{$section:} " if $section ne $section_default; |
349 |
$args{'sections'}{$section} =~ s:([{}]):\@\1:gs; |
350 |
output_highlight($args{'sections'}{$section}); |
351 |
} |
352 |
print "\@end deftypefun\n\n"; |
353 |
} |
354 |
|
355 |
# output in html |
356 |
sub output_html { |
357 |
my %args = %{$_[0]}; |
358 |
my ($parameter, $section); |
359 |
my $count; |
360 |
print "\n\n<a name=\"". $args{'function'} . "\"> </a><h2>Function</h2>\n"; |
361 |
|
362 |
print "<i>".$args{'functiontype'}."</i>\n"; |
363 |
print "<b>".$args{'function'}."</b>\n"; |
364 |
print "("; |
365 |
$count = 0; |
366 |
foreach $parameter (@{$args{'parameterlist'}}) { |
367 |
print "<i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n"; |
368 |
if ($count != $#{$args{'parameterlist'}}) { |
369 |
$count++; |
370 |
print ", "; |
371 |
} |
372 |
} |
373 |
print ")\n"; |
374 |
|
375 |
print "<h3>Arguments</h3>\n"; |
376 |
print "<dl>\n"; |
377 |
foreach $parameter (@{$args{'parameterlist'}}) { |
378 |
print "<dt><i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n"; |
379 |
print "<dd>"; |
380 |
output_highlight($args{'parameters'}{$parameter}); |
381 |
} |
382 |
print "</dl>\n"; |
383 |
foreach $section (@{$args{'sectionlist'}}) { |
384 |
print "<h3>$section</h3>\n"; |
385 |
print "<ul>\n"; |
386 |
output_highlight($args{'sections'}{$section}); |
387 |
print "</ul>\n"; |
388 |
} |
389 |
print "<hr>\n"; |
390 |
} |
391 |
|
392 |
# output in tex |
393 |
sub output_tex { |
394 |
my %args = %{$_[0]}; |
395 |
my ($parameter, $section); |
396 |
my $count; |
397 |
my $func = $args{'function'}; |
398 |
my $param; |
399 |
my $param2; |
400 |
my $sec; |
401 |
my $check; |
402 |
my $type; |
403 |
|
404 |
$func =~ s/_/\\_/g; |
405 |
|
406 |
print "\n\n\\subsection{". $func . "}\n\\label{" . $args{'function'} . "}\n"; |
407 |
|
408 |
$type = $args{'functiontype'}; |
409 |
$type =~ s/_/\\_/g; |
410 |
|
411 |
print "{\\it ".$type."}\n"; |
412 |
print "{\\bf ".$func."}\n"; |
413 |
print "(\n"; |
414 |
$count = 0; |
415 |
foreach $parameter (@{$args{'parameterlist'}}) { |
416 |
$param = $args{'parametertypes'}{$parameter}; |
417 |
$param2 = $parameter; |
418 |
$param =~ s/_/\\_/g; |
419 |
$param2 =~ s/_/\\_/g; |
420 |
|
421 |
print "{\\it ".$param."} {\\bf ".$param2."}\n"; |
422 |
if ($count != $#{$args{'parameterlist'}}) { |
423 |
$count++; |
424 |
print ", "; |
425 |
} |
426 |
} |
427 |
print ")\n"; |
428 |
|
429 |
print "\n{\\large{Arguments}}\n"; |
430 |
|
431 |
print "\\begin{itemize}\n"; |
432 |
$check=0; |
433 |
foreach $parameter (@{$args{'parameterlist'}}) { |
434 |
$param1 = $args{'parametertypes'}{$parameter}; |
435 |
$param1 =~ s/_/\\_/g; |
436 |
$param2 = $parameter; |
437 |
$param2 =~ s/_/\\_/g; |
438 |
|
439 |
$check = 1; |
440 |
print "\\item {\\it ".$param1."} {\\bf ".$param2."}: \n"; |
441 |
# print "\n"; |
442 |
|
443 |
$param3 = $args{'parameters'}{$parameter}; |
444 |
$param3 =~ s/_/\\_/g; |
445 |
$param3 =~ s/&([a-zA-Z\_]+)/{\\it \1}/g; |
446 |
|
447 |
output_highlight($param3); |
448 |
} |
449 |
if ($check==0) { |
450 |
print "\\item void\n"; |
451 |
} |
452 |
print "\\end{itemize}\n"; |
453 |
|
454 |
foreach $section (@{$args{'sectionlist'}}) { |
455 |
$sec = $section; |
456 |
$sec =~ s/_/\\_/g; |
457 |
$sec =~ s/&([a-zA-Z\_]+)/{\\it \1}/g; |
458 |
|
459 |
print "\n\\par{\\large{$sec}}\\par\n"; |
460 |
print "\\begin{rmfamily}\n"; |
461 |
|
462 |
$sec = $args{'sections'}{$section}; |
463 |
$sec =~ s/_/\\_/g; |
464 |
$sec =~ s/\\:/:/g; |
465 |
$sec =~ s/&([a-zA-Z\_]+)/{\\it \1}/g; |
466 |
$sec =~ s/->/\$\\rightarrow\$/g; |
467 |
$sec =~ s/([0-9]+)\^([0-9]+)/\$\{\1\}\^\{\2\}\$/g; |
468 |
|
469 |
output_highlight($sec); |
470 |
print "\\end{rmfamily}\n"; |
471 |
} |
472 |
print "\n"; |
473 |
} |
474 |
|
475 |
|
476 |
# output in sgml DocBook |
477 |
sub output_sgml { |
478 |
my %args = %{$_[0]}; |
479 |
my ($parameter, $section); |
480 |
my $count; |
481 |
my $id; |
482 |
|
483 |
$id = $args{'module'}."-".$args{'function'}; |
484 |
$id =~ s/[^A-Za-z0-9]/-/g; |
485 |
|
486 |
print "<refentry>\n"; |
487 |
print "<refmeta>\n"; |
488 |
print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n"; |
489 |
print "</refmeta>\n"; |
490 |
print "<refnamediv>\n"; |
491 |
print " <refname>".$args{'function'}."</refname>\n"; |
492 |
print " <refpurpose>\n"; |
493 |
print " ".$args{'purpose'}."\n"; |
494 |
print " </refpurpose>\n"; |
495 |
print "</refnamediv>\n"; |
496 |
|
497 |
print "<refsynopsisdiv>\n"; |
498 |
print " <title>Synopsis</title>\n"; |
499 |
print " <funcsynopsis>\n"; |
500 |
print " <funcdef>".$args{'functiontype'}." "; |
501 |
print "<function>".$args{'function'}." "; |
502 |
print "</function></funcdef>\n"; |
503 |
|
504 |
# print "<refsect1>\n"; |
505 |
# print " <title>Synopsis</title>\n"; |
506 |
# print " <funcsynopsis>\n"; |
507 |
# print " <funcdef>".$args{'functiontype'}." "; |
508 |
# print "<function>".$args{'function'}." "; |
509 |
# print "</function></funcdef>\n"; |
510 |
|
511 |
$count = 0; |
512 |
if ($#{$args{'parameterlist'}} >= 0) { |
513 |
foreach $parameter (@{$args{'parameterlist'}}) { |
514 |
print " <paramdef>".$args{'parametertypes'}{$parameter}; |
515 |
print " <parameter>$parameter</parameter></paramdef>\n"; |
516 |
} |
517 |
} else { |
518 |
print " <void>\n"; |
519 |
} |
520 |
print " </funcsynopsis>\n"; |
521 |
print "</refsynopsisdiv>\n"; |
522 |
# print "</refsect1>\n"; |
523 |
|
524 |
# print parameters |
525 |
print "<refsect1>\n <title>Arguments</title>\n"; |
526 |
# print "<para>\nArguments\n"; |
527 |
if ($#{$args{'parameterlist'}} >= 0) { |
528 |
print " <variablelist>\n"; |
529 |
foreach $parameter (@{$args{'parameterlist'}}) { |
530 |
print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n"; |
531 |
print " <listitem>\n <para>\n"; |
532 |
$lineprefix=" "; |
533 |
output_highlight($args{'parameters'}{$parameter}); |
534 |
print " </para>\n </listitem>\n </varlistentry>\n"; |
535 |
} |
536 |
print " </variablelist>\n"; |
537 |
} else { |
538 |
print " <para>\n None\n </para>\n"; |
539 |
} |
540 |
print "</refsect1>\n"; |
541 |
|
542 |
# print out each section |
543 |
$lineprefix=" "; |
544 |
foreach $section (@{$args{'sectionlist'}}) { |
545 |
print "<refsect1>\n <title>$section</title>\n <para>\n"; |
546 |
# print "<para>\n$section\n"; |
547 |
if ($section =~ m/EXAMPLE/i) { |
548 |
print "<example><para>\n"; |
549 |
} |
550 |
output_highlight($args{'sections'}{$section}); |
551 |
# print "</para>"; |
552 |
if ($section =~ m/EXAMPLE/i) { |
553 |
print "</para></example>\n"; |
554 |
} |
555 |
print " </para>\n</refsect1>\n"; |
556 |
} |
557 |
|
558 |
print "\n\n"; |
559 |
} |
560 |
|
561 |
## |
562 |
# output in man |
563 |
sub output_man { |
564 |
my %args = %{$_[0]}; |
565 |
my ($parameter, $section); |
566 |
my $count; |
567 |
|
568 |
print ".TH \"$args{'function'}\" 3 \"$args{'sourceversion'}\" \"". $args{'module'} . "\" \"". $args{'module'} . "\"\n"; |
569 |
|
570 |
print ".SH NAME\n"; |
571 |
|
572 |
print $args{'function'}."\n"; |
573 |
|
574 |
print ".SH SYNOPSIS\n"; |
575 |
print ".B #include <". lc((split /_/, $args{'function'})[0]) . ".h>\n" |
576 |
if $args{'includefuncprefix'}; |
577 |
print ".sp\n"; |
578 |
print ".BI \"".$args{'functiontype'}." ".$args{'function'}."("; |
579 |
$count = 0; |
580 |
foreach $parameter (@{$args{'parameterlist'}}) { |
581 |
print $args{'parametertypes'}{$parameter}." \" ".$parameter." \""; |
582 |
if ($count != $#{$args{'parameterlist'}}) { |
583 |
$count++; |
584 |
print ", "; |
585 |
} |
586 |
} |
587 |
print ");\"\n"; |
588 |
|
589 |
print ".SH ARGUMENTS\n"; |
590 |
foreach $parameter (@{$args{'parameterlist'}}) { |
591 |
print ".IP \"".$args{'parametertypes'}{$parameter}." ".$parameter."\" 12\n"; |
592 |
output_highlight($args{'parameters'}{$parameter}); |
593 |
} |
594 |
foreach $section (@{$args{'sectionlist'}}) { |
595 |
print ".SH \"" . uc($section) . "\"\n"; |
596 |
output_highlight($args{'sections'}{$section}); |
597 |
} |
598 |
|
599 |
if ($args{'bugsto'}) { |
600 |
print ".SH \"REPORTING BUGS\"\n"; |
601 |
print "Report bugs to <". $args{'bugsto'} . ">.\n"; |
602 |
} |
603 |
|
604 |
if ($args{'copyright'}) { |
605 |
print ".SH COPYRIGHT\n"; |
606 |
print "Copyright \\(co ". $args{'copyright'} . ".\n"; |
607 |
if ($args{'verbatimcopying'}) { |
608 |
print ".br\n"; |
609 |
print "Permission is granted to make and distribute verbatim copies of this\n"; |
610 |
print "manual provided the copyright notice and this permission notice are\n"; |
611 |
print "preserved on all copies.\n"; |
612 |
} |
613 |
} |
614 |
|
615 |
if ($args{'seeinfo'}) { |
616 |
print ".SH \"SEE ALSO\"\n"; |
617 |
print "The full documentation for\n"; |
618 |
print ".B " . $args{'module'} . "\n"; |
619 |
print "is maintained as a Texinfo manual. If the\n"; |
620 |
print ".B info\n"; |
621 |
print "and\n"; |
622 |
print ".B " . $args{'module'} . "\n"; |
623 |
print "programs are properly installed at your site, the command\n"; |
624 |
print ".IP\n"; |
625 |
print ".B info " . $args{'seeinfo'} . "\n"; |
626 |
print ".PP\n"; |
627 |
print "should give you access to the complete manual.\n"; |
628 |
} |
629 |
} |
630 |
|
631 |
sub output_listfunc { |
632 |
my %args = %{$_[0]}; |
633 |
print $args{'function'} . "\n"; |
634 |
} |
635 |
|
636 |
## |
637 |
# output in text |
638 |
sub output_text { |
639 |
my %args = %{$_[0]}; |
640 |
my ($parameter, $section); |
641 |
|
642 |
print "Function = ".$args{'function'}."\n"; |
643 |
print " return type: ".$args{'functiontype'}."\n\n"; |
644 |
foreach $parameter (@{$args{'parameterlist'}}) { |
645 |
print " ".$args{'parametertypes'}{$parameter}." ".$parameter."\n"; |
646 |
print " -> ".$args{'parameters'}{$parameter}."\n"; |
647 |
} |
648 |
foreach $section (@{$args{'sectionlist'}}) { |
649 |
print " $section:\n"; |
650 |
print " -> "; |
651 |
output_highlight($args{'sections'}{$section}); |
652 |
} |
653 |
} |
654 |
|
655 |
## |
656 |
# generic output function - calls the right one based |
657 |
# on current output mode. |
658 |
sub output_function { |
659 |
# output_html(@_); |
660 |
eval "output_".$output_mode."(\@_);"; |
661 |
} |
662 |
|
663 |
|
664 |
## |
665 |
# takes a function prototype and spits out all the details |
666 |
# stored in the global arrays/hsahes. |
667 |
sub dump_function { |
668 |
my $prototype = shift @_; |
669 |
|
670 |
if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ || |
671 |
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ || |
672 |
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ || |
673 |
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ || |
674 |
$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/) { |
675 |
$return_type = $1; |
676 |
$function_name = $2; |
677 |
$args = $3; |
678 |
|
679 |
# print STDERR "ARGS = '$args'\n"; |
680 |
|
681 |
foreach $arg (split ',', $args) { |
682 |
# strip leading/trailing spaces |
683 |
$arg =~ s/^\s*//; |
684 |
$arg =~ s/\s*$//; |
685 |
# print STDERR "SCAN ARG: '$arg'\n"; |
686 |
@args = split('\s', $arg); |
687 |
|
688 |
# print STDERR " -> @args\n"; |
689 |
$param = pop @args; |
690 |
# print STDERR " -> @args\n"; |
691 |
if ($param =~ m/^(\*+)(.*)/) { |
692 |
$param = $2; |
693 |
push @args, $1; |
694 |
} |
695 |
if ($param =~ m/^(.*)(\[\])$/) { |
696 |
$param = $1; |
697 |
push @args, $2; |
698 |
} |
699 |
# print STDERR " :> @args\n"; |
700 |
$type = join " ", @args; |
701 |
|
702 |
if ($parameters{$param} eq "" && $param != "void") { |
703 |
$parameters{$param} = "-- undescribed --"; |
704 |
print STDERR "Warning($lineno): Function parameter '$param' not described in '$function_name'\n"; |
705 |
} |
706 |
|
707 |
push @parameterlist, $param; |
708 |
$parametertypes{$param} = $type; |
709 |
|
710 |
# print STDERR "param = '$param', type = '$type'\n"; |
711 |
} |
712 |
} else { |
713 |
print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n"; |
714 |
return; |
715 |
} |
716 |
|
717 |
if ($function_only==0 || defined($function_table{$function_name})) { |
718 |
output_function({'function' => $function_name, |
719 |
'module' => $modulename, |
720 |
'sourceversion' => $sourceversion, |
721 |
'includefuncprefix' => $includefuncprefix, |
722 |
'bugsto' => $bugsto, |
723 |
'copyright' => $copyright, |
724 |
'verbatimcopying' => $verbatimcopying, |
725 |
'seeinfo' => $seeinfo, |
726 |
'functiontype' => $return_type, |
727 |
'parameterlist' => \@parameterlist, |
728 |
'parameters' => \%parameters, |
729 |
'parametertypes' => \%parametertypes, |
730 |
'sectionlist' => \@sectionlist, |
731 |
'sections' => \%sections, |
732 |
'purpose' => $function_purpose |
733 |
}); |
734 |
} |
735 |
} |
736 |
|
737 |
###################################################################### |
738 |
# main |
739 |
# states |
740 |
# 0 - normal code |
741 |
# 1 - looking for function name |
742 |
# 2 - scanning field start. |
743 |
# 3 - scanning prototype. |
744 |
$state = 0; |
745 |
$section = ""; |
746 |
|
747 |
$doc_special = "\@\%\$\&"; |
748 |
|
749 |
$doc_start = "^/\\*\\*\$"; |
750 |
$doc_end = "\\*/"; |
751 |
$doc_com = "\\s*\\*\\s*"; |
752 |
$doc_func = $doc_com."(\\w+):?"; |
753 |
$doc_sect = $doc_com."([".$doc_special."[:upper:]][\\w ]+):(.*)"; |
754 |
$doc_content = $doc_com."(.*)"; |
755 |
|
756 |
%constants = (); |
757 |
%parameters = (); |
758 |
@parameterlist = (); |
759 |
%sections = (); |
760 |
@sectionlist = (); |
761 |
|
762 |
$contents = ""; |
763 |
$section_default = "Description"; # default section |
764 |
$section = $section_default; |
765 |
|
766 |
$lineno = 0; |
767 |
foreach $file (@ARGV) { |
768 |
if (!open(IN,"<$file")) { |
769 |
print STDERR "Error: Cannot open file $file\n"; |
770 |
next; |
771 |
} |
772 |
while (<IN>) { |
773 |
$lineno++; |
774 |
|
775 |
if ($state == 0) { |
776 |
if (/$doc_start/o) { |
777 |
$state = 1; # next line is always the function name |
778 |
} |
779 |
} elsif ($state == 1) { # this line is the function name (always) |
780 |
if (/$doc_func/o) { |
781 |
$function = $1; |
782 |
$state = 2; |
783 |
if (/-(.*)/) { |
784 |
$function_purpose = $1; |
785 |
} else { |
786 |
$function_purpose = ""; |
787 |
} |
788 |
if ($verbose) { |
789 |
print STDERR "Info($lineno): Scanning doc for $function\n"; |
790 |
} |
791 |
} else { |
792 |
print STDERR "WARN($lineno): Cannot understand $_ on line $lineno", |
793 |
" - I thought it was a doc line\n"; |
794 |
$state = 0; |
795 |
} |
796 |
} elsif ($state == 2) { # look for head: lines, and include content |
797 |
if (/$doc_sect/o) { |
798 |
$newsection = $1; |
799 |
$newcontents = $2; |
800 |
|
801 |
if ($contents ne "") { |
802 |
dump_section($section, $contents); |
803 |
$section = $section_default; |
804 |
} |
805 |
|
806 |
$contents = $newcontents; |
807 |
if ($contents ne "") { |
808 |
$contents .= "\n"; |
809 |
} |
810 |
$section = $newsection; |
811 |
} elsif (/$doc_end/) { |
812 |
|
813 |
if ($contents ne "") { |
814 |
dump_section($section, $contents); |
815 |
$section = $section_default; |
816 |
$contents = ""; |
817 |
} |
818 |
|
819 |
# print STDERR "end of doc comment, looking for prototype\n"; |
820 |
$prototype = ""; |
821 |
$state = 3; |
822 |
} elsif (/$doc_content/) { |
823 |
# miguel-style comment kludge, look for blank lines after |
824 |
# @parameter line to signify start of description |
825 |
if ($1 eq "" && $section =~ m/^@/) { |
826 |
dump_section($section, $contents); |
827 |
$section = $section_default; |
828 |
$contents = ""; |
829 |
} else { |
830 |
$contents .= $1."\n"; |
831 |
} |
832 |
} else { |
833 |
# i dont know - bad line? ignore. |
834 |
print STDERR "WARNING($lineno): bad line: $_"; |
835 |
} |
836 |
} elsif ($state == 3) { # scanning for function { (end of prototype) |
837 |
if (m#\s*/\*\s+MACDOC\s*#io) { |
838 |
# do nothing |
839 |
} |
840 |
elsif (/([^\{]*)/) { |
841 |
$prototype .= $1; |
842 |
} |
843 |
if (/\{/) { |
844 |
$prototype =~ s@/\*.*?\*/@@gos; # strip comments. |
845 |
$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. |
846 |
$prototype =~ s@^ +@@gos; # strip leading spaces |
847 |
dump_function($prototype); |
848 |
|
849 |
$function = ""; |
850 |
%constants = (); |
851 |
%parameters = (); |
852 |
%parametertypes = (); |
853 |
@parameterlist = (); |
854 |
%sections = (); |
855 |
@sectionlist = (); |
856 |
$prototype = ""; |
857 |
|
858 |
$state = 0; |
859 |
} |
860 |
} |
861 |
} |
862 |
} |
863 |
|