#!/usr/bin/perl -w # -*- cperl -*- # cdoc - generate man pages for C code # Copyright (C) 2000 Bibliotech Ltd., Unit 2-3, 50 Carnwath Road, # London, SW6 3EG, United Kingdom. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $Id: cdoc,v 1.4 2001/02/16 17:02:15 rich Exp $ use strict; my $arg; my $date = `date +'%B %d, %Y'`; $date =~ s/[\r\n]+$//; my $author; my $version; my $license; while ($arg = shift @ARGV) { my ($type, $header_file); if ($arg eq "--help" || $arg eq "-?" || $arg eq "-h") { print STDERR "cdoc [--options ...] files ...\n", "Options are:\n", " --author \"Author name\" Details for the AUTHOR section\n", " --version package-version Details for the VERSION section\n", " --license \"License data\" Details for the LICENSE section\n"; exit 1; } elsif ($arg eq "--author") { $author = shift @ARGV; next; } elsif ($arg eq "--version") { $version = shift @ARGV; next; } elsif ($arg eq "--license") { $license = shift @ARGV; next; } elsif ($arg =~ /(.*)\.h$/) { header: $type = "header file"; $header_file = $1; open FILE, "<$arg" or die "$arg: cannot open file: $!"; } else { print STDERR "$arg: unknown file type: assuming it's a header file"; goto header; } while () { s/[\n\r]+$//; # Look for intro line. if (m(^\s*/\*\s*(Function|Variable):\s*(.*?)\s+-\s+(.*))o) { my $manpage = $2; my $name_text = $3; my @functions = (); push @functions, { name => $manpage }; my $description = ""; my $bugs = ""; my $history = ""; my $see_also = ""; my $returns = ""; my $section = \$description; # Read the rest of the comment block. while () { s/[\n\r]+$//; s/^\s*\*\s*//; # Remove leading " * ". last if m(^/)o; # End of comment block? if (m(^(Function|Variable):\s*(.*))o) { push @functions, { name => $2 }; } elsif (m(^Bugs:\s*(.*))o) { $section = \$bugs; $$section .= $1 . " "; } elsif (m(^History:\s*(.*))o) { $section = \$history; $$section .= $1 . " "; } elsif (m(^See also:\s*(.*))o) { $section = \$see_also; $$section .= $1 . " "; } elsif (m(^Returns:\s*(.*))o) { $section = \$returns; $$section .= $1 . " "; } elsif (m/^\s*$/) { $$section .= "\n"; } else { $$section .= $_; $$section .= " "; } } # Mark up the sections. $description = mark_up ($description); $bugs = mark_up ($bugs); $history = mark_up ($history); $see_also = mark_up ($see_also); $returns = mark_up ($returns); # Read the functions which should follow, one per line, in order. my $fn; foreach $fn (@functions) { $_ = ; if (!$_ || !m($fn->{name})) { print STDERR "$arg: could not find prototype of variable/function: $fn->{name}\n"; exit 1; } s/[\n\r]+$//; s/^extern\s+//; $fn->{prototype} = $_; } # Now we're in a situation to produce the manual page. print "cdoc: creating $manpage.3\n"; open MANPAGE, ">$manpage.3" or die "$manpage.3: cannot open file: $!"; my $names = join ", ", map { $_->{name} } @functions; print MANPAGE ".TH $manpage 3 \"$date\" \"GNU\" \"Programmer's Manual\"\n", ".SH NAME\n", "$names \\- $name_text\n", ".SH SYNOPSIS\n", ".nf\n", ".B #include <$header_file.h>\n", ".sp\n"; foreach (@functions) { print MANPAGE ".BI \"$_->{prototype}\"\n"; } print MANPAGE ".fi\n", ".SH DESCRIPTION\n", "$description\n"; print MANPAGE ".SH RETURNS\n$returns\n" if $returns; print MANPAGE ".SH BUGS\n$bugs\n" if $bugs; print MANPAGE ".SH AUTHOR\n$author\n" if $author; print MANPAGE ".SH LICENSE\n$license\n" if $license; print MANPAGE ".SH VERSION\n$version\n" if $version; print MANPAGE ".SH HISTORY\n$history\n" if $history; print MANPAGE ".SH SEE ALSO\n$see_also\n" if $see_also; close MANPAGE; # Links for other pages. my @other_pages = @functions; shift @other_pages; foreach $fn (@other_pages) { print "cdoc: creating $fn->{name}.3\n"; open MANPAGE, ">$fn->{name}.3" or die "$fn->{name}.3: cannot open file: $!"; print MANPAGE ".so man3/$manpage.3\n"; close MANPAGE; } } } close FILE; } exit; sub mark_up { local $_ = shift; s/\n/\n.PP\n/ogs; s/\@code{(.*?)}/\\fB$1\\fP/ogs; s/\@ref{(.*?)}/\\fB$1\\fP/ogs; # Should be able to handle this better. XXX return $_; }