Fixed test to run fine (0 errors) on Win NT.
[wine.git] / tools / c2man.pl
blob9f5315cdb11c328d2c59dd5dcf59e2cfeeef2e6b
1 #!/usr/bin/perl
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
27 # TODO:
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)
41 # *
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.
45 # *
46 # * RETURNS
47 # *
48 # * Handle to metafile copy on success, NULL on failure.
49 # *
50 # * BUGS
51 # *
52 # * Copying to disk returns NULL even if successful.
53 # */
54 # HMETAFILE32 WINAPI CopyMetaFile32A(
55 # HMETAFILE32 hSrcMetaFile, /* handle of metafile to copy */
56 # LPCSTR lpFilename /* filename if copying to a file */
57 # ) { ... }
59 #####################################################################################
60 # Output after processing with nroff -man
62 # CopyMetaFileA(3w) CopyMetaFileA(3w)
65 # NAME
66 # CopyMetaFileA - CopyMetaFile32A (GDI32.23)
68 # SYNOPSIS
69 # HMETAFILE32 CopyMetaFileA
70 # (
71 # HMETAFILE32 hSrcMetaFile,
72 # LPCSTR lpFilename
73 # );
75 # PARAMETERS
76 # HMETAFILE32 hSrcMetaFile
77 # Handle of metafile to copy.
79 # LPCSTR lpFilename
80 # Filename if copying to a file.
82 # DESCRIPTION
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.
87 # RETURNS
88 # Handle to metafile copy on success, NULL on failure.
90 # BUGS
91 # Copying to disk returns NULL even if successful.
93 # SEE ALSO
94 # GetMetaFileA(3w), GetMetaFileW(3w), CopyMetaFileW(3w),
95 # PlayMetaFile(3w), SetMetaFileBitsEx(3w), GetMetaFileBit-
96 # sEx(3w)
98 #####################################################################################
100 sub output_manpage
102 my ($buffer,$apiref) = @_;
103 my $parameters;
104 my $desc;
106 # join all the lines of the description together and highlight the headings
107 for (@$buffer) {
108 s/\n//g;
109 s/^\s*//g;
110 s/\s*$//g;
111 if ( /^([A-Z]+)$/ ) {
112 $desc = $desc.".SH $1\n.PP\n";
114 elsif ( /^$/ ) {
115 $desc = "$desc\n";
117 else {
118 $desc = "$desc $_";
122 #seperate out all the parameters
124 $plist = join ( ' ', @$apiref );
126 $name_type = $plist;
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
140 for(@params) {
141 s/^\s*//;
142 s/\s*$//;
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";
159 print MAN ".PP\n";
160 print MAN "$name_type\n";
161 print MAN " (\n";
162 for($i=0; $i<@params; $i++) {
163 $x = ($i == (@params-1)) ? "" : ",";
164 $c = $params[$i];
165 $c =~ s/-.*//;
166 print MAN " $c$x\n";
168 print MAN " );\n";
169 print MAN ".SH PARAMETERS\n";
170 print MAN ".PP\n";
171 for($i=0; $i<@params; $i++) {
172 print MAN " $params[$i]\n";
174 print MAN ".SH DESCRIPTION\n";
175 print MAN ".PP\n";
176 print MAN $desc;
177 close(MAN);
181 # extract the comments from source file
183 sub parse_source
185 my $file = $_[0];
186 print "Processing $file\n";
188 open(SOURCE,"<$file") || die "Couldn't open the source file $file\n";
189 $state = 0;
190 while(<SOURCE>) {
191 if($state == 0 ) {
192 if ( /^\/\**$/ ) {
193 # find the start of the comment /**************
194 $state = 3;
195 @buffer = ();
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]+)|@))\) *$/ ) {
201 $apiname = $1;
202 $apientry = $2;
203 $state = 1;
205 else {
206 $state = 0;
209 elsif ($state == 1) {
210 #save the comment text into buffer, removing leading astericks
211 if ( /^ \*\// ) {
212 $state = 2;
214 else {
215 # find the end of the comment
216 if ( s/^ \*// ) {
217 @buffer = ( @buffer , $_ );
219 else {
220 $state = 0;
224 elsif ($state == 2) {
225 # check that the comment is followed by the declaration of
226 # a WINAPI function.
227 if ( /WINAPI/ ) {
228 @apidef = ( $_ );
229 #check if the function's parameters end on this line
230 if( /\)/ ) {
231 output_manpage(\@buffer, \@apidef);
232 $state = 0;
234 else {
235 $state = 4;
238 else {
239 $state = 0;
242 elsif ($state == 4) {
243 @apidef = ( @apidef , $_ );
244 #find the end of the parameters list
245 if( /\)/ ) {
246 output_manpage(\@buffer, \@apidef);
247 $state = 0;
251 close(SOURCE);
254 # generate a database of functions to have man pages created from the source
255 # creates funclist and funcdb
256 sub parse_spec
258 my $spec = $_[0];
259 my $name,$type,$ord,$func;
261 open(SPEC,"<$spec") || die "Couldn't open the spec file $spec\n";
262 while(<SPEC>)
264 if( /^#/ ) { next; }
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;
283 close(SPEC);
286 ######################################################################
288 #main starts here
290 $mandir = "man3w";
291 $section = "3";
293 #process args
294 while(@ARGV) {
295 if($ARGV[0] eq "-o") { # extract output directory
296 shift @ARGV;
297 $mandir = $ARGV[0];
298 shift @ARGV;
299 next;
301 if($ARGV[0] =~ s/^-S// ) { # extract man section
302 $section = $ARGV[0];
303 shift @ARGV;
304 next;
306 if($ARGV[0] =~ s/^-w// ) { # extract man section
307 shift @ARGV;
308 @specfiles = ( @specfiles , $ARGV[0] );
309 shift @ARGV;
310 next;
312 if($ARGV[0] =~ s/^-T// ) {
313 die "FIXME: Only NROFF supported\n";
315 if($ARGV[0] =~ s/^-[LDiI]// ) { #compatible with C2MAN flags
316 shift @ARGV;
317 next;
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";
327 while(@specfiles) {
328 parse_spec($specfiles[0]);
329 shift @specfiles;
332 #print "Functions: @funclist\n";
334 while(@ARGV) {
335 parse_source($ARGV[0]);
336 shift @ARGV;