3 #####################################################################################
5 # c2man.pl v0.1 Copyright (C) 2000 Mike McCormack
7 # Generates Documents from C source code.
9 # Input is source code with specially formatted comments, output
10 # is man pages. The functionality is meant to be similar to c2man.
11 # The following is an example provided in the Wine documentation.
13 # This library is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU Lesser General Public
15 # License as published by the Free Software Foundation; either
16 # version 2.1 of the License, or (at your option) any later version.
18 # This library is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # Lesser General Public License for more details.
23 # You should have received a copy of the GNU Lesser General Public
24 # License along with this library; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 # Write code to generate HTML output with the -Th option.
29 # Need somebody who knows about TROFF to help touch up the man page generation.
30 # Parse spec files passed with -w option and generate pages for the functions
31 # in the spec files only.
32 # Modify Makefiles to pass multiple C files to speed up man page generation.
33 # Use nm on the shared libraries specified in the spec files to determine which
34 # source files should be parsed, and only parse them.(requires wine to be compiled)
36 #####################################################################################
37 # Input from C source file:
39 # /******************************************************************
40 # * CopyMetaFile32A (GDI32.23)
42 # * Copies the metafile corresponding to hSrcMetaFile to either
43 # * a disk file, if a filename is given, or to a new memory based
44 # * metafile, if lpFileName is NULL.
48 # * Handle to metafile copy on success, NULL on failure.
52 # * Copying to disk returns NULL even if successful.
54 # HMETAFILE32 WINAPI CopyMetaFile32A(
55 # HMETAFILE32 hSrcMetaFile, /* handle of metafile to copy */
56 # LPCSTR lpFilename /* filename if copying to a file */
59 #####################################################################################
60 # Output after processing with nroff -man
62 # CopyMetaFileA(3w) CopyMetaFileA(3w)
66 # CopyMetaFileA - CopyMetaFile32A (GDI32.23)
69 # HMETAFILE32 CopyMetaFileA
71 # HMETAFILE32 hSrcMetaFile,
76 # HMETAFILE32 hSrcMetaFile
77 # Handle of metafile to copy.
80 # Filename if copying to a file.
83 # Copies the metafile corresponding to hSrcMetaFile to
84 # either a disk file, if a filename is given, or to a new
85 # memory based metafile, if lpFileName is NULL.
88 # Handle to metafile copy on success, NULL on failure.
91 # Copying to disk returns NULL even if successful.
94 # GetMetaFileA(3w), GetMetaFileW(3w), CopyMetaFileW(3w),
95 # PlayMetaFile(3w), SetMetaFileBitsEx(3w), GetMetaFileBit-
98 #####################################################################################
102 my ($buffer,$apiref) = @_;
106 # join all the lines of the description together and highlight the headings
111 if ( /^([A-Z]+)$/ ) {
112 $desc = $desc.".SH $1\n.PP\n";
122 #seperate out all the parameters
124 $plist = join ( ' ', @$apiref );
127 $name_type =~ s/\n//g; # remove newlines
128 $name_type =~ s/\(.*$//;
129 $name_type =~ s/WINAPI//;
131 #check that this is a function that we want
132 if ( $funcdb{$apiname."ORD"} eq "" ) { return; }
133 print "Generating $apiname.$section\n";
135 $plist =~ s/\n//g; # remove newlines
136 $plist =~ s/^.*\(\s*//; # remove leading bracket and before
137 $plist =~ s/\s*\).*$//; # remove trailing bracket and leftovers
138 $plist =~ s/\s*,?\s*\/\*([^*]*)\*\// - $1,/g; # move the comma to the back
139 @params = split ( /,/ , $plist); # split parameters
145 # figure the month and the year
146 @datetime = localtime;
147 @months = ( "January", "Febuary", "March", "April", "May", "June",
148 "July", "August", "September", "October", "November", "December" );
149 $date = "$months[$datetime[4]] $datetime[5]";
151 # create the manual page
152 $manfile = "$mandir/$apiname.$section";
153 open(MAN,">$manfile") || die "Couldn't create the man page file $manfile\n";
154 print MAN ".\\\" DO NOT MODIFY THIS FILE! It was generated by gendoc 1.0.\n";
155 print MAN ".TH $apiname \"$section\" \"$date\" \"Wine API\" \"The Wine Project\"\n";
156 print MAN ".SH NAME\n";
157 print MAN "$apiname ($apientry)\n";
158 print MAN ".SH SYNOPSIS\n";
160 print MAN "$name_type\n";
162 for($i=0; $i<@params; $i++) {
163 $x = ($i == (@params-1)) ? "" : ",";
169 print MAN ".SH PARAMETERS\n";
171 for($i=0; $i<@params; $i++) {
172 print MAN " $params[$i]\n";
174 print MAN ".SH DESCRIPTION\n";
181 # extract the comments from source file
186 print "Processing $file\n";
188 open(SOURCE,"<$file") || die "Couldn't open the source file $file\n";
193 # find the start of the comment /**************
198 elsif ($state == 3) {
199 #extract the wine API name and DLLNAME.XXX string
200 if ( / *([A-Za-z_0-9]+) *\(([A-Za-z0-9_]+\.(([0-9]+)|@))\) *$/ ) {
209 elsif ($state == 1) {
210 #save the comment text into buffer, removing leading astericks
215 # find the end of the comment
217 @buffer = ( @buffer , $_ );
224 elsif ($state == 2) {
225 # check that the comment is followed by the declaration of
229 #check if the function's parameters end on this line
231 output_manpage(\@buffer, \@apidef);
242 elsif ($state == 4) {
243 @apidef = ( @apidef , $_ );
244 #find the end of the parameters list
246 output_manpage(\@buffer, \@apidef);
254 # generate a database of functions to have man pages created from the source
255 # creates funclist and funcdb
259 my $name,$type,$ord,$func;
261 open(SPEC,"<$spec") || die "Couldn't open the spec file $spec\n";
265 if( /^name/ ) { next; }
266 if( /^type/ ) { next; }
267 if( /^init/ ) { next; }
268 if( /^rsrc/ ) { next; }
269 if( /^import/ ) { next; }
270 if( /^\s*$/ ) { next; }
271 if( /^\s*(([0-9]+)|@)/ ) {
272 s/\(.*\)//; #remove all the args
273 ($ord,$type,$name,$func) = split( /\s+/ );
274 if(( $type eq "stub" ) || ($type eq "forward")) {next;}
275 if( $func eq "" ) { next; }
276 @funclist = ( @funclist , $func );
277 $funcdb{$func."ORD"} = $ord;
278 $funcdb{$func."TYPE"} = $type;
279 $funcdb{$func."NAME"} = $name;
280 $funcdb{$func."SPEC"} = $spec;
286 ######################################################################
295 if($ARGV[0] eq "-o") { # extract output directory
301 if($ARGV[0] =~ s/^-S// ) { # extract man section
306 if($ARGV[0] =~ s/^-w// ) { # extract man section
308 @specfiles = ( @specfiles , $ARGV[0] );
312 if($ARGV[0] =~ s/^-T// ) {
313 die "FIXME: Only NROFF supported\n";
315 if($ARGV[0] =~ s/^-[LDiI]// ) { #compatible with C2MAN flags
319 last; # stop after there's no more flags
322 #print "manual section: $section\n";
323 #print "man directory : $mandir\n";
324 #print "input files : @ARGV\n";
325 #print "spec files : @specfiles\n";
328 parse_spec($specfiles[0]);
332 #print "Functions: @funclist\n";
335 parse_source($ARGV[0]);