Add to git.
[cdoc.git] / cdoc
1 #!/usr/bin/perl -w
2 # -*- cperl -*-
3
4 # cdoc - generate man pages for C code
5 # Copyright (C) 2000 Bibliotech Ltd., Unit 2-3, 50 Carnwath Road,
6 # London, SW6 3EG, United Kingdom.
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22 # $Id: cdoc,v 1.4 2001/02/16 17:02:15 rich Exp $
23
24 use strict;
25
26 my $arg;
27
28 my $date = `date +'%B %d, %Y'`;
29 $date =~ s/[\r\n]+$//;
30
31 my $author;
32 my $version;
33 my $license;
34
35 while ($arg = shift @ARGV)
36   {
37     my ($type, $header_file);
38
39     if ($arg eq "--help" || $arg eq "-?" || $arg eq "-h")
40       {
41         print STDERR
42           "cdoc [--options ...] files ...\n",
43           "Options are:\n",
44           "  --author \"Author name\"      Details for the AUTHOR section\n",
45           "  --version package-version   Details for the VERSION section\n",
46           "  --license \"License data\"    Details for the LICENSE section\n";
47         exit 1;
48       }
49     elsif ($arg eq "--author")
50       {
51         $author = shift @ARGV;
52         next;
53       }
54     elsif ($arg eq "--version")
55       {
56         $version = shift @ARGV;
57         next;
58       }
59     elsif ($arg eq "--license")
60       {
61         $license = shift @ARGV;
62         next;
63       }
64     elsif ($arg =~ /(.*)\.h$/)
65       {
66       header:
67         $type = "header file";
68         $header_file = $1;
69         open FILE, "<$arg"
70           or die "$arg: cannot open file: $!";
71       }
72     else
73       {
74         print STDERR "$arg: unknown file type: assuming it's a header file";
75         goto header;
76       }
77
78     while (<FILE>)
79       {
80         s/[\n\r]+$//;
81
82         # Look for intro line.
83         if (m(^\s*/\*\s*(Function|Variable):\s*(.*?)\s+-\s+(.*))o)
84           {
85             my $manpage = $2;
86             my $name_text = $3;
87
88             my @functions = ();
89             push @functions, { name => $manpage };
90
91             my $description = "";
92             my $bugs = "";
93             my $history = "";
94             my $see_also = "";
95             my $returns = "";
96             my $section = \$description;
97
98             # Read the rest of the comment block.
99             while (<FILE>)
100               {
101                 s/[\n\r]+$//;
102                 s/^\s*\*\s*//;  # Remove leading " * ".
103
104                 last if m(^/)o; # End of comment block?
105
106                 if (m(^(Function|Variable):\s*(.*))o)
107                   {
108                     push @functions, { name => $2 };
109                   }
110                 elsif (m(^Bugs:\s*(.*))o)
111                   {
112                     $section = \$bugs;
113                     $$section .= $1 . " ";
114                   }
115                 elsif (m(^History:\s*(.*))o)
116                   {
117                     $section = \$history;
118                     $$section .= $1 . " ";
119                   }
120                 elsif (m(^See also:\s*(.*))o)
121                   {
122                     $section = \$see_also;
123                     $$section .= $1 . " ";
124                   }
125                 elsif (m(^Returns:\s*(.*))o)
126                   {
127                     $section = \$returns;
128                     $$section .= $1 . " ";
129                   }
130                 elsif (m/^\s*$/)
131                   {
132                     $$section .= "\n";
133                   }
134                 else
135                   {
136                     $$section .= $_;
137                     $$section .= " ";
138                   }
139               }
140
141             # Mark up the sections.
142             $description = mark_up ($description);
143             $bugs = mark_up ($bugs);
144             $history = mark_up ($history);
145             $see_also = mark_up ($see_also);
146             $returns = mark_up ($returns);
147
148             # Read the functions which should follow, one per line, in order.
149             my $fn;
150             foreach $fn (@functions)
151               {
152                 $_ = <FILE>;
153
154                 if (!$_ || !m($fn->{name}))
155                   {
156                     print STDERR "$arg: could not find prototype of variable/function: $fn->{name}\n";
157                     exit 1;
158                   }
159
160                 s/[\n\r]+$//;
161                 s/^extern\s+//;
162                 $fn->{prototype} = $_;
163               }
164
165             # Now we're in a situation to produce the manual page.
166             print "cdoc: creating $manpage.3\n";
167
168             open MANPAGE, ">$manpage.3"
169               or die "$manpage.3: cannot open file: $!";
170
171             my $names = join ", ", map { $_->{name} } @functions;
172
173             print MANPAGE
174               ".TH $manpage 3 \"$date\" \"GNU\" \"Programmer's Manual\"\n",
175               ".SH NAME\n",
176               "$names \\- $name_text\n",
177               ".SH SYNOPSIS\n",
178               ".nf\n",
179               ".B #include <$header_file.h>\n",
180               ".sp\n";
181
182             foreach (@functions)
183               {
184                 print MANPAGE ".BI \"$_->{prototype}\"\n";
185               }
186
187             print MANPAGE
188               ".fi\n",
189               ".SH DESCRIPTION\n",
190               "$description\n";
191
192             print MANPAGE ".SH RETURNS\n$returns\n" if $returns;
193             print MANPAGE ".SH BUGS\n$bugs\n" if $bugs;
194             print MANPAGE ".SH AUTHOR\n$author\n" if $author;
195             print MANPAGE ".SH LICENSE\n$license\n" if $license;
196             print MANPAGE ".SH VERSION\n$version\n" if $version;
197             print MANPAGE ".SH HISTORY\n$history\n" if $history;
198             print MANPAGE ".SH SEE ALSO\n$see_also\n" if $see_also;
199
200             close MANPAGE;
201
202             # Links for other pages.
203             my @other_pages = @functions;
204             shift @other_pages;
205
206             foreach $fn (@other_pages)
207               {
208                 print "cdoc: creating $fn->{name}.3\n";
209
210                 open MANPAGE, ">$fn->{name}.3"
211                   or die "$fn->{name}.3: cannot open file: $!";
212
213                 print MANPAGE
214                   ".so man3/$manpage.3\n";
215
216                 close MANPAGE;
217               }
218           }
219       }
220
221     close FILE;
222   }
223
224 exit;
225
226 sub mark_up
227   {
228     local $_ = shift;
229
230     s/\n/\n.PP\n/ogs;
231     s/\@code{(.*?)}/\\fB$1\\fP/ogs;
232     s/\@ref{(.*?)}/\\fB$1\\fP/ogs; # Should be able to handle this better. XXX
233
234     return $_;
235   }