OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [scripts/] [kernel-doc] - Blame information for rev 3

Details | Compare with Previous | View Log

\n";\n";
Line No. Rev Author Line
1 3 xianfeng
#!/usr/bin/perl -w
2
 
3
use strict;
4
 
5
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
6
## Copyright (C) 2000, 1  Tim Waugh           ##
7
## Copyright (C) 2001  Simon Huggins                             ##
8
## Copyright (C) 2005-2007  Randy Dunlap                         ##
9
##                                                               ##
10
## #define enhancements by Armin Kuster          ##
11
## Copyright (c) 2000 MontaVista Software, Inc.                  ##
12
##                                                               ##
13
## This software falls under the GNU General Public License.     ##
14
## Please read the COPYING file for more information             ##
15
 
16
# w.o. 03-11-2000: added the '-filelist' option.
17
 
18
# 18/01/2001 -  Cleanups
19
#               Functions prototyped as foo(void) same as foo()
20
#               Stop eval'ing where we don't need to.
21
# -- huggie@earth.li
22
 
23
# 27/06/2001 -  Allowed whitespace after initial "/**" and
24
#               allowed comments before function declarations.
25
# -- Christian Kreibich 
26
 
27
# Still to do:
28
#       - add perldoc documentation
29
#       - Look more closely at some of the scarier bits :)
30
 
31
# 26/05/2001 -  Support for separate source and object trees.
32
#               Return error code.
33
#               Keith Owens 
34
 
35
# 23/09/2001 - Added support for typedefs, structs, enums and unions
36
#              Support for Context section; can be terminated using empty line
37
#              Small fixes (like spaces vs. \s in regex)
38
# -- Tim Jansen 
39
 
40
 
41
#
42
# This will read a 'c' file and scan for embedded comments in the
43
# style of gnome comments (+minor extensions - see below).
44
#
45
 
46
# Note: This only supports 'c'.
47
 
48
# usage:
49
# kernel-doc [ -docbook | -html | -text | -man ]
50
#           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
51
# or
52
#           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
53
#
54
#  Set output format using one of -docbook -html -text or -man.  Default is man.
55
#
56
#  -function funcname
57
#       If set, then only generate documentation for the given function(s).  All
58
#       other functions are ignored.
59
#
60
#  -nofunction funcname
61
#       If set, then only generate documentation for the other function(s).
62
#       Cannot be used together with -function
63
#       (yes, that's a bug -- perl hackers can fix it 8))
64
#
65
#  c files - list of 'c' files to process
66
#
67
#  All output goes to stdout, with errors to stderr.
68
 
69
#
70
# format of comments.
71
# In the following table, (...)? signifies optional structure.
72
#                         (...)* signifies 0 or more structure elements
73
# /**
74
#  * function_name(:)? (- short description)?
75
# (* @parameterx: (description of parameter x)?)*
76
# (* a blank line)?
77
#  * (Description:)? (Description of function)?
78
#  * (section header: (section description)? )*
79
#  (*)?*/
80
#
81
# So .. the trivial example would be:
82
#
83
# /**
84
#  * my_function
85
#  **/
86
#
87
# If the Description: header tag is omitted, then there must be a blank line
88
# after the last parameter specification.
89
# e.g.
90
# /**
91
#  * my_function - does my stuff
92
#  * @my_arg: its mine damnit
93
#  *
94
#  * Does my stuff explained.
95
#  */
96
#
97
#  or, could also use:
98
# /**
99
#  * my_function - does my stuff
100
#  * @my_arg: its mine damnit
101
#  * Description: Does my stuff explained.
102
#  */
103
# etc.
104
#
105
# Beside functions you can also write documentation for structs, unions,
106
# enums and typedefs. Instead of the function name you must write the name
107
# of the declaration;  the struct/union/enum/typedef must always precede
108
# the name. Nesting of declarations is not supported.
109
# Use the argument mechanism to document members or constants.
110
# e.g.
111
# /**
112
#  * struct my_struct - short description
113
#  * @a: first member
114
#  * @b: second member
115
#  *
116
#  * Longer description
117
#  */
118
# struct my_struct {
119
#     int a;
120
#     int b;
121
# /* private: */
122
#     int c;
123
# };
124
#
125
# All descriptions can be multiline, except the short function description.
126
#
127
# You can also add additional sections. When documenting kernel functions you
128
# should document the "Context:" of the function, e.g. whether the functions
129
# can be called form interrupts. Unlike other sections you can end it with an
130
# empty line.
131
# Example-sections should contain the string EXAMPLE so that they are marked
132
# appropriately in DocBook.
133
#
134
# Example:
135
# /**
136
#  * user_function - function that can only be called in user context
137
#  * @a: some argument
138
#  * Context: !in_interrupt()
139
#  *
140
#  * Some description
141
#  * Example:
142
#  *    user_function(22);
143
#  */
144
# ...
145
#
146
#
147
# All descriptive text is further processed, scanning for the following special
148
# patterns, which are highlighted appropriately.
149
#
150
# 'funcname()' - function
151
# '$ENVVAR' - environmental variable
152
# '&struct_name' - name of a structure (up to two words including 'struct')
153
# '@parameter' - name of a parameter
154
# '%CONST' - name of a constant.
155
 
156
my $errors = 0;
157
my $warnings = 0;
158
my $anon_struct_union = 0;
159
 
160
# match expressions used to find embedded type information
161
my $type_constant = '\%([-_\w]+)';
162
my $type_func = '(\w+)\(\)';
163
my $type_param = '\@(\w+)';
164
my $type_struct = '\&((struct\s*)*[_\w]+)';
165
my $type_struct_xml = '\\&((struct\s*)*[_\w]+)';
166
my $type_env = '(\$\w+)';
167
 
168
# Output conversion substitutions.
169
#  One for each output format
170
 
171
# these work fairly well
172
my %highlights_html = ( $type_constant, "\$1",
173
                        $type_func, "\$1",
174
                        $type_struct_xml, "\$1",
175
                        $type_env, "\$1",
176
                        $type_param, "\$1" );
177
my $local_lt = "\\\\\\\\lt:";
178
my $local_gt = "\\\\\\\\gt:";
179
my $blankline_html = $local_lt . "p" . $local_gt;       # was "

"

180
 
181
# XML, docbook format
182
my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1\$2",
183
                        $type_constant, "\$1",
184
                        $type_func, "\$1",
185
                        $type_struct, "\$1",
186
                        $type_env, "\$1",
187
                        $type_param, "\$1" );
188
my $blankline_xml = "\n";
189
 
190
# gnome, docbook format
191
my %highlights_gnome = ( $type_constant, "\$1",
192
                         $type_func, "\$1",
193
                         $type_struct, "\$1",
194
                         $type_env, "\$1",
195
                         $type_param, "\$1" );
196
my $blankline_gnome = "\n";
197
 
198
# these are pretty rough
199
my %highlights_man = ( $type_constant, "\$1",
200
                       $type_func, "\\\\fB\$1\\\\fP",
201
                       $type_struct, "\\\\fI\$1\\\\fP",
202
                       $type_param, "\\\\fI\$1\\\\fP" );
203
my $blankline_man = "";
204
 
205
# text-mode
206
my %highlights_text = ( $type_constant, "\$1",
207
                        $type_func, "\$1",
208
                        $type_struct, "\$1",
209
                        $type_param, "\$1" );
210
my $blankline_text = "";
211
 
212
 
213
sub usage {
214
    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
215
    print "         [ -function funcname [ -function funcname ...] ]\n";
216
    print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
217
    print "         c source file(s) > outputfile\n";
218
    exit 1;
219
}
220
 
221
# read arguments
222
if ($#ARGV==-1) {
223
    usage();
224
}
225
 
226
my $verbose = 0;
227
my $output_mode = "man";
228
my %highlights = %highlights_man;
229
my $blankline = $blankline_man;
230
my $modulename = "Kernel API";
231
my $function_only = 0;
232
my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
233
                'July', 'August', 'September', 'October',
234
                'November', 'December')[(localtime)[4]] .
235
  " " . ((localtime)[5]+1900);
236
 
237
# Essentially these are globals
238
# They probably want to be tidied up made more localised or summat.
239
# CAVEAT EMPTOR!  Some of the others I localised may not want to be which
240
# could cause "use of undefined value" or other bugs.
241
my ($function, %function_table,%parametertypes,$declaration_purpose);
242
my ($type,$declaration_name,$return_type);
243
my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
244
 
245
# Generated docbook code is inserted in a template at a point where
246
# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
247
# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
248
# We keep track of number of generated entries and generate a dummy
249
# if needs be to ensure the expanded template can be postprocessed
250
# into html.
251
my $section_counter = 0;
252
 
253
my $lineprefix="";
254
 
255
# states
256
# 0 - normal code
257
# 1 - looking for function name
258
# 2 - scanning field start.
259
# 3 - scanning prototype.
260
# 4 - documentation block
261
my $state;
262
my $in_doc_sect;
263
 
264
#declaration types: can be
265
# 'function', 'struct', 'union', 'enum', 'typedef'
266
my $decl_type;
267
 
268
my $doc_special = "\@\%\$\&";
269
 
270
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
271
my $doc_end = '\*/';
272
my $doc_com = '\s*\*\s*';
273
my $doc_decl = $doc_com.'(\w+)';
274
my $doc_sect = $doc_com.'(['.$doc_special.']?[\w\s]+):(.*)';
275
my $doc_content = $doc_com.'(.*)';
276
my $doc_block = $doc_com.'DOC:\s*(.*)?';
277
 
278
my %constants;
279
my %parameterdescs;
280
my @parameterlist;
281
my %sections;
282
my @sectionlist;
283
 
284
my $contents = "";
285
my $section_default = "Description";    # default section
286
my $section_intro = "Introduction";
287
my $section = $section_default;
288
my $section_context = "Context";
289
 
290
my $undescribed = "-- undescribed --";
291
 
292
reset_state();
293
 
294
while ($ARGV[0] =~ m/^-(.*)/) {
295
    my $cmd = shift @ARGV;
296
    if ($cmd eq "-html") {
297
        $output_mode = "html";
298
        %highlights = %highlights_html;
299
        $blankline = $blankline_html;
300
    } elsif ($cmd eq "-man") {
301
        $output_mode = "man";
302
        %highlights = %highlights_man;
303
        $blankline = $blankline_man;
304
    } elsif ($cmd eq "-text") {
305
        $output_mode = "text";
306
        %highlights = %highlights_text;
307
        $blankline = $blankline_text;
308
    } elsif ($cmd eq "-docbook") {
309
        $output_mode = "xml";
310
        %highlights = %highlights_xml;
311
        $blankline = $blankline_xml;
312
    } elsif ($cmd eq "-gnome") {
313
        $output_mode = "gnome";
314
        %highlights = %highlights_gnome;
315
        $blankline = $blankline_gnome;
316
    } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
317
        $modulename = shift @ARGV;
318
    } elsif ($cmd eq "-function") { # to only output specific functions
319
        $function_only = 1;
320
        $function = shift @ARGV;
321
        $function_table{$function} = 1;
322
    } elsif ($cmd eq "-nofunction") { # to only output specific functions
323
        $function_only = 2;
324
        $function = shift @ARGV;
325
        $function_table{$function} = 1;
326
    } elsif ($cmd eq "-v") {
327
        $verbose = 1;
328
    } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
329
        usage();
330
    } elsif ($cmd eq '-filelist') {
331
            $filelist = shift @ARGV;
332
    }
333
}
334
 
335
# get kernel version from env
336
sub get_kernel_version() {
337
    my $version;
338
 
339
    if (defined($ENV{'KERNELVERSION'})) {
340
        $version = $ENV{'KERNELVERSION'};
341
    }
342
    return $version;
343
}
344
my $kernelversion = get_kernel_version();
345
 
346
# generate a sequence of code that will splice in highlighting information
347
# using the s// operator.
348
my $dohighlight = "";
349
foreach my $pattern (keys %highlights) {
350
#   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
351
    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
352
}
353
 
354
##
355
# dumps section contents to arrays/hashes intended for that purpose.
356
#
357
sub dump_section {
358
    my $name = shift;
359
    my $contents = join "\n", @_;
360
 
361
    if ($name =~ m/$type_constant/) {
362
        $name = $1;
363
#       print STDERR "constant section '$1' = '$contents'\n";
364
        $constants{$name} = $contents;
365
    } elsif ($name =~ m/$type_param/) {
366
#       print STDERR "parameter def '$1' = '$contents'\n";
367
        $name = $1;
368
        $parameterdescs{$name} = $contents;
369
    } else {
370
#       print STDERR "other section '$name' = '$contents'\n";
371
        $sections{$name} = $contents;
372
        push @sectionlist, $name;
373
    }
374
}
375
 
376
##
377
# output function
378
#
379
# parameterdescs, a hash.
380
#  function => "function name"
381
#  parameterlist => @list of parameters
382
#  parameterdescs => %parameter descriptions
383
#  sectionlist => @list of sections
384
#  sections => %section descriptions
385
#
386
 
387
sub output_highlight {
388
    my $contents = join "\n",@_;
389
    my $line;
390
 
391
#   DEBUG
392
#   if (!defined $contents) {
393
#       use Carp;
394
#       confess "output_highlight got called with no args?\n";
395
#   }
396
 
397
    if ($output_mode eq "html") {
398
        $contents = local_unescape($contents);
399
        # convert data read & converted thru xml_escape() into &xyz; format:
400
        $contents =~ s/\\\\\\/&/g;
401
    }
402
#   print STDERR "contents b4:$contents\n";
403
    eval $dohighlight;
404
    die $@ if $@;
405
#   print STDERR "contents af:$contents\n";
406
 
407
    foreach $line (split "\n", $contents) {
408
        if ($line eq ""){
409
            print $lineprefix, local_unescape($blankline);
410
        } else {
411
            $line =~ s/\\\\\\/\&/g;
412
            if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
413
                print "\\&$line";
414
            } else {
415
                print $lineprefix, $line;
416
            }
417
        }
418
        print "\n";
419
    }
420
}
421
 
422
#output sections in html
423
sub output_section_html(%) {
424
    my %args = %{$_[0]};
425
    my $section;
426
 
427
    foreach $section (@{$args{'sectionlist'}}) {
428
        print "

$section

\n";
429
        print "
\n";
430
        output_highlight($args{'sections'}{$section});
431
        print "\n";
432
    }
433
}
434
 
435
# output enum in html
436
sub output_enum_html(%) {
437
    my %args = %{$_[0]};
438
    my ($parameter);
439
    my $count;
440
    print "

enum ".$args{'enum'}."

\n";
441
 
442
    print "enum ".$args{'enum'}." {
\n";
443
    $count = 0;
444
    foreach $parameter (@{$args{'parameterlist'}}) {
445
        print " ".$parameter."";
446
        if ($count != $#{$args{'parameterlist'}}) {
447
            $count++;
448
            print ",\n";
449
        }
450
        print "
";
451
    }
452
    print "};
\n";
453
 
454
    print "

Constants

\n";
455
    print "
\n";
456
    foreach $parameter (@{$args{'parameterlist'}}) {
457
        print "
".$parameter."\n";
458
        print "
";
459
        output_highlight($args{'parameterdescs'}{$parameter});
460
    }
461
    print "\n";
462
    output_section_html(@_);
463
    print "
\n";
464
}
465
 
466
# output typedef in html
467
sub output_typedef_html(%) {
468
    my %args = %{$_[0]};
469
    my ($parameter);
470
    my $count;
471
    print "

typedef ".$args{'typedef'}."

\n";
472
 
473
    print "typedef ".$args{'typedef'}."\n";
474
    output_section_html(@_);
475
    print "
\n";
476
}
477
 
478
# output struct in html
479
sub output_struct_html(%) {
480
    my %args = %{$_[0]};
481
    my ($parameter);
482
 
483
    print "

".$args{'type'}." ".$args{'struct'}. " - " .$args{'purpose'}."

\n";
484
    print "".$args{'type'}." ".$args{'struct'}." {
\n";
485
    foreach $parameter (@{$args{'parameterlist'}}) {
486
        if ($parameter =~ /^#/) {
487
                print "$parameter
\n";
488
                next;
489
        }
490
        my $parameter_name = $parameter;
491
        $parameter_name =~ s/\[.*//;
492
 
493
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
494
        $type = $args{'parametertypes'}{$parameter};
495
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
496
            # pointer-to-function
497
            print "    $1$parameter) ($2);
\n";
498
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
499
            # bitfield
500
            print "    $1 $parameter$2;
\n";
501
        } else {
502
            print "    $type $parameter;
\n";
503
        }
504
    }
505
    print "};
\n";
506
 
507
    print "

Members

\n";
508
    print "
\n";
509
    foreach $parameter (@{$args{'parameterlist'}}) {
510
        ($parameter =~ /^#/) && next;
511
 
512
        my $parameter_name = $parameter;
513
        $parameter_name =~ s/\[.*//;
514
 
515
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
516
        print "
".$parameter."\n";
517
        print "
";
518
        output_highlight($args{'parameterdescs'}{$parameter_name});
519
    }
520
    print "\n";
521
    output_section_html(@_);
522
    print "
\n";
523
}
524
 
525
# output function in html
526
sub output_function_html(%) {
527
    my %args = %{$_[0]};
528
    my ($parameter, $section);
529
    my $count;
530
 
531
    print "

" .$args{'function'}." - ".$args{'purpose'}."

\n";
532
    print "".$args{'functiontype'}."\n";
533
    print "".$args{'function'}."\n";
534
    print "(";
535
    $count = 0;
536
    foreach $parameter (@{$args{'parameterlist'}}) {
537
        $type = $args{'parametertypes'}{$parameter};
538
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
539
            # pointer-to-function
540
            print "$1$parameter) ($2)";
541
        } else {
542
            print "".$type." ".$parameter."";
543
        }
544
        if ($count != $#{$args{'parameterlist'}}) {
545
            $count++;
546
            print ",\n";
547
        }
548
    }
549
    print ")\n";
550
 
551
    print "

Arguments

\n";
552
    print "
\n";
553
    foreach $parameter (@{$args{'parameterlist'}}) {
554
        my $parameter_name = $parameter;
555
        $parameter_name =~ s/\[.*//;
556
 
557
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
558
        print "
".$parameter."\n";
559
        print "
";
560
        output_highlight($args{'parameterdescs'}{$parameter_name});
561
    }
562
    print "\n";
563
    output_section_html(@_);
564
    print "
\n";
565
}
566
 
567
# output intro in html
568
sub output_intro_html(%) {
569
    my %args = %{$_[0]};
570
    my ($parameter, $section);
571
    my $count;
572
 
573
    foreach $section (@{$args{'sectionlist'}}) {
574
        print "

$section

\n";
575
        print "
    \n";
576
        output_highlight($args{'sections'}{$section});
577
        print "\n";
578
    }
579
    print "
\n";
580
}
581
 
582
sub output_section_xml(%) {
583
    my %args = %{$_[0]};
584
    my $section;
585
    # print out each section
586
    $lineprefix="   ";
587
    foreach $section (@{$args{'sectionlist'}}) {
588
        print "\n";
589
        print "$section\n";
590
        if ($section =~ m/EXAMPLE/i) {
591
            print "\n";
592
        } else {
593
            print "\n";
594
        }
595
        output_highlight($args{'sections'}{$section});
596
        if ($section =~ m/EXAMPLE/i) {
597
            print "\n";
598
        } else {
599
            print "\n";
600
        }
601
        print "\n";
602
    }
603
}
604
 
605
# output function in XML DocBook
606
sub output_function_xml(%) {
607
    my %args = %{$_[0]};
608
    my ($parameter, $section);
609
    my $count;
610
    my $id;
611
 
612
    $id = "API-".$args{'function'};
613
    $id =~ s/[^A-Za-z0-9]/-/g;
614
 
615
    print "\n";
616
    print "\n";
617
    print " LINUX\n";
618
    print " Kernel Hackers Manual\n";
619
    print " $man_date\n";
620
    print "\n";
621
    print "\n";
622
    print " ".$args{'function'}."\n";
623
    print " 9\n";
624
    print " " . $kernelversion . "\n";
625
    print "\n";
626
    print "\n";
627
    print " ".$args{'function'}."\n";
628
    print " \n";
629
    print "  ";
630
    output_highlight ($args{'purpose'});
631
    print " \n";
632
    print "\n";
633
 
634
    print "\n";
635
    print " Synopsis\n";
636
    print "  \n";
637
    print "   ".$args{'functiontype'}." ";
638
    print "".$args{'function'}." \n";
639
 
640
    $count = 0;
641
    if ($#{$args{'parameterlist'}} >= 0) {
642
        foreach $parameter (@{$args{'parameterlist'}}) {
643
            $type = $args{'parametertypes'}{$parameter};
644
            if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
645
                # pointer-to-function
646
                print "   $1$parameter)\n";
647
                print "     $2\n";
648
            } else {
649
                print "   ".$type;
650
                print " $parameter\n";
651
            }
652
        }
653
    } else {
654
        print "  \n";
655
    }
656
    print "  \n";
657
    print "\n";
658
 
659
    # print parameters
660
    print "\n Arguments\n";
661
    if ($#{$args{'parameterlist'}} >= 0) {
662
        print " \n";
663
        foreach $parameter (@{$args{'parameterlist'}}) {
664
            my $parameter_name = $parameter;
665
            $parameter_name =~ s/\[.*//;
666
 
667
            print "  \n   $parameter\n";
668
            print "   \n    \n";
669
            $lineprefix="     ";
670
            output_highlight($args{'parameterdescs'}{$parameter_name});
671
            print "    \n   \n  \n";
672
        }
673
        print " \n";
674
    } else {
675
        print " \n  None\n \n";
676
    }
677
    print "\n";
678
 
679
    output_section_xml(@_);
680
    print "\n\n";
681
}
682
 
683
# output struct in XML DocBook
684
sub output_struct_xml(%) {
685
    my %args = %{$_[0]};
686
    my ($parameter, $section);
687
    my $id;
688
 
689
    $id = "API-struct-".$args{'struct'};
690
    $id =~ s/[^A-Za-z0-9]/-/g;
691
 
692
    print "\n";
693
    print "\n";
694
    print " LINUX\n";
695
    print " Kernel Hackers Manual\n";
696
    print " $man_date\n";
697
    print "\n";
698
    print "\n";
699
    print " ".$args{'type'}." ".$args{'struct'}."\n";
700
    print " 9\n";
701
    print " " . $kernelversion . "\n";
702
    print "\n";
703
    print "\n";
704
    print " ".$args{'type'}." ".$args{'struct'}."\n";
705
    print " \n";
706
    print "  ";
707
    output_highlight ($args{'purpose'});
708
    print " \n";
709
    print "\n";
710
 
711
    print "\n";
712
    print " Synopsis\n";
713
    print "  \n";
714
    print $args{'type'}." ".$args{'struct'}." {\n";
715
    foreach $parameter (@{$args{'parameterlist'}}) {
716
        if ($parameter =~ /^#/) {
717
            print "$parameter\n";
718
            next;
719
        }
720
 
721
        my $parameter_name = $parameter;
722
        $parameter_name =~ s/\[.*//;
723
 
724
        defined($args{'parameterdescs'}{$parameter_name}) || next;
725
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
726
        $type = $args{'parametertypes'}{$parameter};
727
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
728
            # pointer-to-function
729
            print "  $1 $parameter) ($2);\n";
730
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
731
            # bitfield
732
            print "  $1 $parameter$2;\n";
733
        } else {
734
            print "  ".$type." ".$parameter.";\n";
735
        }
736
    }
737
    print "};";
738
    print "  \n";
739
    print "\n";
740
 
741
    print " \n";
742
    print "  Members\n";
743
 
744
    print "  \n";
745
    foreach $parameter (@{$args{'parameterlist'}}) {
746
      ($parameter =~ /^#/) && next;
747
 
748
      my $parameter_name = $parameter;
749
      $parameter_name =~ s/\[.*//;
750
 
751
      defined($args{'parameterdescs'}{$parameter_name}) || next;
752
      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
753
      print "    ";
754
      print "      $parameter\n";
755
      print "      \n";
756
      output_highlight($args{'parameterdescs'}{$parameter_name});
757
      print "      \n";
758
      print "    \n";
759
    }
760
    print "  \n";
761
    print " \n";
762
 
763
    output_section_xml(@_);
764
 
765
    print "\n\n";
766
}
767
 
768
# output enum in XML DocBook
769
sub output_enum_xml(%) {
770
    my %args = %{$_[0]};
771
    my ($parameter, $section);
772
    my $count;
773
    my $id;
774
 
775
    $id = "API-enum-".$args{'enum'};
776
    $id =~ s/[^A-Za-z0-9]/-/g;
777
 
778
    print "\n";
779
    print "\n";
780
    print " LINUX\n";
781
    print " Kernel Hackers Manual\n";
782
    print " $man_date\n";
783
    print "\n";
784
    print "\n";
785
    print " enum ".$args{'enum'}."\n";
786
    print " 9\n";
787
    print " " . $kernelversion . "\n";
788
    print "\n";
789
    print "\n";
790
    print " enum ".$args{'enum'}."\n";
791
    print " \n";
792
    print "  ";
793
    output_highlight ($args{'purpose'});
794
    print " \n";
795
    print "\n";
796
 
797
    print "\n";
798
    print " Synopsis\n";
799
    print "  \n";
800
    print "enum ".$args{'enum'}." {\n";
801
    $count = 0;
802
    foreach $parameter (@{$args{'parameterlist'}}) {
803
        print "  $parameter";
804
        if ($count != $#{$args{'parameterlist'}}) {
805
            $count++;
806
            print ",";
807
        }
808
        print "\n";
809
    }
810
    print "};";
811
    print "  \n";
812
    print "\n";
813
 
814
    print "\n";
815
    print " Constants\n";
816
    print "  \n";
817
    foreach $parameter (@{$args{'parameterlist'}}) {
818
      my $parameter_name = $parameter;
819
      $parameter_name =~ s/\[.*//;
820
 
821
      print "    ";
822
      print "      $parameter\n";
823
      print "      \n";
824
      output_highlight($args{'parameterdescs'}{$parameter_name});
825
      print "      \n";
826
      print "    \n";
827
    }
828
    print "  \n";
829
    print "\n";
830
 
831
    output_section_xml(@_);
832
 
833
    print "\n\n";
834
}
835
 
836
# output typedef in XML DocBook
837
sub output_typedef_xml(%) {
838
    my %args = %{$_[0]};
839
    my ($parameter, $section);
840
    my $id;
841
 
842
    $id = "API-typedef-".$args{'typedef'};
843
    $id =~ s/[^A-Za-z0-9]/-/g;
844
 
845
    print "\n";
846
    print "\n";
847
    print " LINUX\n";
848
    print " Kernel Hackers Manual\n";
849
    print " $man_date\n";
850
    print "\n";
851
    print "\n";
852
    print " typedef ".$args{'typedef'}."\n";
853
    print " 9\n";
854
    print "\n";
855
    print "\n";
856
    print " typedef ".$args{'typedef'}."\n";
857
    print " \n";
858
    print "  ";
859
    output_highlight ($args{'purpose'});
860
    print " \n";
861
    print "\n";
862
 
863
    print "\n";
864
    print " Synopsis\n";
865
    print "  typedef ".$args{'typedef'}.";\n";
866
    print "\n";
867
 
868
    output_section_xml(@_);
869
 
870
    print "\n\n";
871
}
872
 
873
# output in XML DocBook
874
sub output_intro_xml(%) {
875
    my %args = %{$_[0]};
876
    my ($parameter, $section);
877
    my $count;
878
 
879
    my $id = $args{'module'};
880
    $id =~ s/[^A-Za-z0-9]/-/g;
881
 
882
    # print out each section
883
    $lineprefix="   ";
884
    foreach $section (@{$args{'sectionlist'}}) {
885
        print "\n $section\n \n";
886
        if ($section =~ m/EXAMPLE/i) {
887
            print "\n";
888
        }
889
        output_highlight($args{'sections'}{$section});
890
        if ($section =~ m/EXAMPLE/i) {
891
            print "\n";
892
        }
893
        print " \n\n";
894
    }
895
 
896
    print "\n\n";
897
}
898
 
899
# output in XML DocBook
900
sub output_function_gnome {
901
    my %args = %{$_[0]};
902
    my ($parameter, $section);
903
    my $count;
904
    my $id;
905
 
906
    $id = $args{'module'}."-".$args{'function'};
907
    $id =~ s/[^A-Za-z0-9]/-/g;
908
 
909
    print "\n";
910
    print " ".$args{'function'}."\n";
911
 
912
    print "  \n";
913
    print "   ".$args{'functiontype'}." ";
914
    print "".$args{'function'}." ";
915
    print "\n";
916
 
917
    $count = 0;
918
    if ($#{$args{'parameterlist'}} >= 0) {
919
        foreach $parameter (@{$args{'parameterlist'}}) {
920
            $type = $args{'parametertypes'}{$parameter};
921
            if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
922
                # pointer-to-function
923
                print "   $1 $parameter)\n";
924
                print "     $2\n";
925
            } else {
926
                print "   ".$type;
927
                print " $parameter\n";
928
            }
929
        }
930
    } else {
931
        print "  \n";
932
    }
933
    print "  \n";
934
    if ($#{$args{'parameterlist'}} >= 0) {
935
        print " \n";
936
        print "\n";
937
        print "\n";
938
        print "\n";
939
        print "
940
        foreach $parameter (@{$args{'parameterlist'}}) {
941
            my $parameter_name = $parameter;
942
            $parameter_name =~ s/\[.*//;
943
 
944
            print "  $parameter\n";
945
            print "   \n";
946
            $lineprefix="     ";
947
            output_highlight($args{'parameterdescs'}{$parameter_name});
948
            print "    \n";
949
        }
950
        print " 
951
    } else {
952
        print " \n  None\n \n";
953
    }
954
 
955
    # print out each section
956
    $lineprefix="   ";
957
    foreach $section (@{$args{'sectionlist'}}) {
958
        print "\n $section\n";
959
        if ($section =~ m/EXAMPLE/i) {
960
            print "\n";
961
        } else {
962
        }
963
        print "\n";
964
        output_highlight($args{'sections'}{$section});
965
        print "\n";
966
        if ($section =~ m/EXAMPLE/i) {
967
            print "\n";
968
        } else {
969
        }
970
        print " \n";
971
    }
972
 
973
    print "\n\n";
974
}
975
 
976
##
977
# output function in man
978
sub output_function_man(%) {
979
    my %args = %{$_[0]};
980
    my ($parameter, $section);
981
    my $count;
982
 
983
    print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
984
 
985
    print ".SH NAME\n";
986
    print $args{'function'}." \\- ".$args{'purpose'}."\n";
987
 
988
    print ".SH SYNOPSIS\n";
989
    if ($args{'functiontype'} ne "") {
990
        print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
991
    } else {
992
        print ".B \"".$args{'function'}."\n";
993
    }
994
    $count = 0;
995
    my $parenth = "(";
996
    my $post = ",";
997
    foreach my $parameter (@{$args{'parameterlist'}}) {
998
        if ($count == $#{$args{'parameterlist'}}) {
999
            $post = ");";
1000
        }
1001
        $type = $args{'parametertypes'}{$parameter};
1002
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1003
            # pointer-to-function
1004
            print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
1005
        } else {
1006
            $type =~ s/([^\*])$/$1 /;
1007
            print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
1008
        }
1009
        $count++;
1010
        $parenth = "";
1011
    }
1012
 
1013
    print ".SH ARGUMENTS\n";
1014
    foreach $parameter (@{$args{'parameterlist'}}) {
1015
        my $parameter_name = $parameter;
1016
        $parameter_name =~ s/\[.*//;
1017
 
1018
        print ".IP \"".$parameter."\" 12\n";
1019
        output_highlight($args{'parameterdescs'}{$parameter_name});
1020
    }
1021
    foreach $section (@{$args{'sectionlist'}}) {
1022
        print ".SH \"", uc $section, "\"\n";
1023
        output_highlight($args{'sections'}{$section});
1024
    }
1025
}
1026
 
1027
##
1028
# output enum in man
1029
sub output_enum_man(%) {
1030
    my %args = %{$_[0]};
1031
    my ($parameter, $section);
1032
    my $count;
1033
 
1034
    print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
1035
 
1036
    print ".SH NAME\n";
1037
    print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n";
1038
 
1039
    print ".SH SYNOPSIS\n";
1040
    print "enum ".$args{'enum'}." {\n";
1041
    $count = 0;
1042
    foreach my $parameter (@{$args{'parameterlist'}}) {
1043
        print ".br\n.BI \"    $parameter\"\n";
1044
        if ($count == $#{$args{'parameterlist'}}) {
1045
            print "\n};\n";
1046
            last;
1047
        }
1048
        else {
1049
            print ", \n.br\n";
1050
        }
1051
        $count++;
1052
    }
1053
 
1054
    print ".SH Constants\n";
1055
    foreach $parameter (@{$args{'parameterlist'}}) {
1056
        my $parameter_name = $parameter;
1057
        $parameter_name =~ s/\[.*//;
1058
 
1059
        print ".IP \"".$parameter."\" 12\n";
1060
        output_highlight($args{'parameterdescs'}{$parameter_name});
1061
    }
1062
    foreach $section (@{$args{'sectionlist'}}) {
1063
        print ".SH \"$section\"\n";
1064
        output_highlight($args{'sections'}{$section});
1065
    }
1066
}
1067
 
1068
##
1069
# output struct in man
1070
sub output_struct_man(%) {
1071
    my %args = %{$_[0]};
1072
    my ($parameter, $section);
1073
 
1074
    print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n";
1075
 
1076
    print ".SH NAME\n";
1077
    print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
1078
 
1079
    print ".SH SYNOPSIS\n";
1080
    print $args{'type'}." ".$args{'struct'}." {\n.br\n";
1081
 
1082
    foreach my $parameter (@{$args{'parameterlist'}}) {
1083
        if ($parameter =~ /^#/) {
1084
            print ".BI \"$parameter\"\n.br\n";
1085
            next;
1086
        }
1087
        my $parameter_name = $parameter;
1088
        $parameter_name =~ s/\[.*//;
1089
 
1090
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1091
        $type = $args{'parametertypes'}{$parameter};
1092
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1093
            # pointer-to-function
1094
            print ".BI \"    ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
1095
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1096
            # bitfield
1097
            print ".BI \"    ".$1."\ \" ".$parameter.$2." \""."\"\n;\n";
1098
        } else {
1099
            $type =~ s/([^\*])$/$1 /;
1100
            print ".BI \"    ".$type."\" ".$parameter." \""."\"\n;\n";
1101
        }
1102
        print "\n.br\n";
1103
    }
1104
    print "};\n.br\n";
1105
 
1106
    print ".SH Members\n";
1107
    foreach $parameter (@{$args{'parameterlist'}}) {
1108
        ($parameter =~ /^#/) && next;
1109
 
1110
        my $parameter_name = $parameter;
1111
        $parameter_name =~ s/\[.*//;
1112
 
1113
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1114
        print ".IP \"".$parameter."\" 12\n";
1115
        output_highlight($args{'parameterdescs'}{$parameter_name});
1116
    }
1117
    foreach $section (@{$args{'sectionlist'}}) {
1118
        print ".SH \"$section\"\n";
1119
        output_highlight($args{'sections'}{$section});
1120
    }
1121
}
1122
 
1123
##
1124
# output typedef in man
1125
sub output_typedef_man(%) {
1126
    my %args = %{$_[0]};
1127
    my ($parameter, $section);
1128
 
1129
    print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
1130
 
1131
    print ".SH NAME\n";
1132
    print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n";
1133
 
1134
    foreach $section (@{$args{'sectionlist'}}) {
1135
        print ".SH \"$section\"\n";
1136
        output_highlight($args{'sections'}{$section});
1137
    }
1138
}
1139
 
1140
sub output_intro_man(%) {
1141
    my %args = %{$_[0]};
1142
    my ($parameter, $section);
1143
    my $count;
1144
 
1145
    print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
1146
 
1147
    foreach $section (@{$args{'sectionlist'}}) {
1148
        print ".SH \"$section\"\n";
1149
        output_highlight($args{'sections'}{$section});
1150
    }
1151
}
1152
 
1153
##
1154
# output in text
1155
sub output_function_text(%) {
1156
    my %args = %{$_[0]};
1157
    my ($parameter, $section);
1158
    my $start;
1159
 
1160
    print "Name:\n\n";
1161
    print $args{'function'}." - ".$args{'purpose'}."\n";
1162
 
1163
    print "\nSynopsis:\n\n";
1164
    if ($args{'functiontype'} ne "") {
1165
        $start = $args{'functiontype'}." ".$args{'function'}." (";
1166
    } else {
1167
        $start = $args{'function'}." (";
1168
    }
1169
    print $start;
1170
 
1171
    my $count = 0;
1172
    foreach my $parameter (@{$args{'parameterlist'}}) {
1173
        $type = $args{'parametertypes'}{$parameter};
1174
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1175
            # pointer-to-function
1176
            print $1.$parameter.") (".$2;
1177
        } else {
1178
            print $type." ".$parameter;
1179
        }
1180
        if ($count != $#{$args{'parameterlist'}}) {
1181
            $count++;
1182
            print ",\n";
1183
            print " " x length($start);
1184
        } else {
1185
            print ");\n\n";
1186
        }
1187
    }
1188
 
1189
    print "Arguments:\n\n";
1190
    foreach $parameter (@{$args{'parameterlist'}}) {
1191
        my $parameter_name = $parameter;
1192
        $parameter_name =~ s/\[.*//;
1193
 
1194
        print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n";
1195
    }
1196
    output_section_text(@_);
1197
}
1198
 
1199
#output sections in text
1200
sub output_section_text(%) {
1201
    my %args = %{$_[0]};
1202
    my $section;
1203
 
1204
    print "\n";
1205
    foreach $section (@{$args{'sectionlist'}}) {
1206
        print "$section:\n\n";
1207
        output_highlight($args{'sections'}{$section});
1208
    }
1209
    print "\n\n";
1210
}
1211
 
1212
# output enum in text
1213
sub output_enum_text(%) {
1214
    my %args = %{$_[0]};
1215
    my ($parameter);
1216
    my $count;
1217
    print "Enum:\n\n";
1218
 
1219
    print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n";
1220
    print "enum ".$args{'enum'}." {\n";
1221
    $count = 0;
1222
    foreach $parameter (@{$args{'parameterlist'}}) {
1223
        print "\t$parameter";
1224
        if ($count != $#{$args{'parameterlist'}}) {
1225
            $count++;
1226
            print ",";
1227
        }
1228
        print "\n";
1229
    }
1230
    print "};\n\n";
1231
 
1232
    print "Constants:\n\n";
1233
    foreach $parameter (@{$args{'parameterlist'}}) {
1234
        print "$parameter\n\t";
1235
        print $args{'parameterdescs'}{$parameter}."\n";
1236
    }
1237
 
1238
    output_section_text(@_);
1239
}
1240
 
1241
# output typedef in text
1242
sub output_typedef_text(%) {
1243
    my %args = %{$_[0]};
1244
    my ($parameter);
1245
    my $count;
1246
    print "Typedef:\n\n";
1247
 
1248
    print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n";
1249
    output_section_text(@_);
1250
}
1251
 
1252
# output struct as text
1253
sub output_struct_text(%) {
1254
    my %args = %{$_[0]};
1255
    my ($parameter);
1256
 
1257
    print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n";
1258
    print $args{'type'}." ".$args{'struct'}." {\n";
1259
    foreach $parameter (@{$args{'parameterlist'}}) {
1260
        if ($parameter =~ /^#/) {
1261
            print "$parameter\n";
1262
            next;
1263
        }
1264
 
1265
        my $parameter_name = $parameter;
1266
        $parameter_name =~ s/\[.*//;
1267
 
1268
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1269
        $type = $args{'parametertypes'}{$parameter};
1270
        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1271
            # pointer-to-function
1272
            print "\t$1 $parameter) ($2);\n";
1273
        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1274
            # bitfield
1275
            print "\t$1 $parameter$2;\n";
1276
        } else {
1277
            print "\t".$type." ".$parameter.";\n";
1278
        }
1279
    }
1280
    print "};\n\n";
1281
 
1282
    print "Members:\n\n";
1283
    foreach $parameter (@{$args{'parameterlist'}}) {
1284
        ($parameter =~ /^#/) && next;
1285
 
1286
        my $parameter_name = $parameter;
1287
        $parameter_name =~ s/\[.*//;
1288
 
1289
        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1290
        print "$parameter\n\t";
1291
        print $args{'parameterdescs'}{$parameter_name}."\n";
1292
    }
1293
    print "\n";
1294
    output_section_text(@_);
1295
}
1296
 
1297
sub output_intro_text(%) {
1298
    my %args = %{$_[0]};
1299
    my ($parameter, $section);
1300
 
1301
    foreach $section (@{$args{'sectionlist'}}) {
1302
        print " $section:\n";
1303
        print "    -> ";
1304
        output_highlight($args{'sections'}{$section});
1305
    }
1306
}
1307
 
1308
##
1309
# generic output function for all types (function, struct/union, typedef, enum);
1310
# calls the generated, variable output_ function name based on
1311
# functype and output_mode
1312
sub output_declaration {
1313
    no strict 'refs';
1314
    my $name = shift;
1315
    my $functype = shift;
1316
    my $func = "output_${functype}_$output_mode";
1317
    if (($function_only==0) ||
1318
        ( $function_only == 1 && defined($function_table{$name})) ||
1319
        ( $function_only == 2 && !defined($function_table{$name})))
1320
    {
1321
        &$func(@_);
1322
        $section_counter++;
1323
    }
1324
}
1325
 
1326
##
1327
# generic output function - calls the right one based on current output mode.
1328
sub output_intro {
1329
    no strict 'refs';
1330
    my $func = "output_intro_".$output_mode;
1331
    &$func(@_);
1332
    $section_counter++;
1333
}
1334
 
1335
##
1336
# takes a declaration (struct, union, enum, typedef) and
1337
# invokes the right handler. NOT called for functions.
1338
sub dump_declaration($$) {
1339
    no strict 'refs';
1340
    my ($prototype, $file) = @_;
1341
    my $func = "dump_".$decl_type;
1342
    &$func(@_);
1343
}
1344
 
1345
sub dump_union($$) {
1346
    dump_struct(@_);
1347
}
1348
 
1349
sub dump_struct($$) {
1350
    my $x = shift;
1351
    my $file = shift;
1352
 
1353
    if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
1354
        $declaration_name = $2;
1355
        my $members = $3;
1356
 
1357
        # ignore embedded structs or unions
1358
        $members =~ s/{.*?}//g;
1359
 
1360
        # ignore members marked private:
1361
        $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
1362
        $members =~ s/\/\*.*?private:.*//gos;
1363
        # strip comments:
1364
        $members =~ s/\/\*.*?\*\///gos;
1365
 
1366
        create_parameterlist($members, ';', $file);
1367
 
1368
        output_declaration($declaration_name,
1369
                           'struct',
1370
                           {'struct' => $declaration_name,
1371
                            'module' => $modulename,
1372
                            'parameterlist' => \@parameterlist,
1373
                            'parameterdescs' => \%parameterdescs,
1374
                            'parametertypes' => \%parametertypes,
1375
                            'sectionlist' => \@sectionlist,
1376
                            'sections' => \%sections,
1377
                            'purpose' => $declaration_purpose,
1378
                            'type' => $decl_type
1379
                           });
1380
    }
1381
    else {
1382
        print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
1383
        ++$errors;
1384
    }
1385
}
1386
 
1387
sub dump_enum($$) {
1388
    my $x = shift;
1389
    my $file = shift;
1390
 
1391
    $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1392
    if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
1393
        $declaration_name = $1;
1394
        my $members = $2;
1395
 
1396
        foreach my $arg (split ',', $members) {
1397
            $arg =~ s/^\s*(\w+).*/$1/;
1398
            push @parameterlist, $arg;
1399
            if (!$parameterdescs{$arg}) {
1400
                $parameterdescs{$arg} = $undescribed;
1401
                print STDERR "Warning(${file}:$.): Enum value '$arg' ".
1402
                    "not described in enum '$declaration_name'\n";
1403
            }
1404
 
1405
        }
1406
 
1407
        output_declaration($declaration_name,
1408
                           'enum',
1409
                           {'enum' => $declaration_name,
1410
                            'module' => $modulename,
1411
                            'parameterlist' => \@parameterlist,
1412
                            'parameterdescs' => \%parameterdescs,
1413
                            'sectionlist' => \@sectionlist,
1414
                            'sections' => \%sections,
1415
                            'purpose' => $declaration_purpose
1416
                           });
1417
    }
1418
    else {
1419
        print STDERR "Error(${file}:$.): Cannot parse enum!\n";
1420
        ++$errors;
1421
    }
1422
}
1423
 
1424
sub dump_typedef($$) {
1425
    my $x = shift;
1426
    my $file = shift;
1427
 
1428
    $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1429
    while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
1430
        $x =~ s/\(*.\)\s*;$/;/;
1431
        $x =~ s/\[*.\]\s*;$/;/;
1432
    }
1433
 
1434
    if ($x =~ /typedef.*\s+(\w+)\s*;/) {
1435
        $declaration_name = $1;
1436
 
1437
        output_declaration($declaration_name,
1438
                           'typedef',
1439
                           {'typedef' => $declaration_name,
1440
                            'module' => $modulename,
1441
                            'sectionlist' => \@sectionlist,
1442
                            'sections' => \%sections,
1443
                            'purpose' => $declaration_purpose
1444
                           });
1445
    }
1446
    else {
1447
        print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
1448
        ++$errors;
1449
    }
1450
}
1451
 
1452
sub create_parameterlist($$$) {
1453
    my $args = shift;
1454
    my $splitter = shift;
1455
    my $file = shift;
1456
    my $type;
1457
    my $param;
1458
 
1459
    # temporarily replace commas inside function pointer definition
1460
    while ($args =~ /(\([^\),]+),/) {
1461
        $args =~ s/(\([^\),]+),/$1#/g;
1462
    }
1463
 
1464
    foreach my $arg (split($splitter, $args)) {
1465
        # strip comments
1466
        $arg =~ s/\/\*.*\*\///;
1467
        # strip leading/trailing spaces
1468
        $arg =~ s/^\s*//;
1469
        $arg =~ s/\s*$//;
1470
        $arg =~ s/\s+/ /;
1471
 
1472
        if ($arg =~ /^#/) {
1473
            # Treat preprocessor directive as a typeless variable just to fill
1474
            # corresponding data structures "correctly". Catch it later in
1475
            # output_* subs.
1476
            push_parameter($arg, "", $file);
1477
        } elsif ($arg =~ m/\(.*\*/) {
1478
            # pointer-to-function
1479
            $arg =~ tr/#/,/;
1480
            $arg =~ m/[^\(]+\(\*\s*([^\)]+)\)/;
1481
            $param = $1;
1482
            $type = $arg;
1483
            $type =~ s/([^\(]+\(\*)$param/$1/;
1484
            push_parameter($param, $type, $file);
1485
        } elsif ($arg) {
1486
            $arg =~ s/\s*:\s*/:/g;
1487
            $arg =~ s/\s*\[/\[/g;
1488
 
1489
            my @args = split('\s*,\s*', $arg);
1490
            if ($args[0] =~ m/\*/) {
1491
                $args[0] =~ s/(\*+)\s*/ $1/;
1492
            }
1493
 
1494
            my @first_arg;
1495
            if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
1496
                    shift @args;
1497
                    push(@first_arg, split('\s+', $1));
1498
                    push(@first_arg, $2);
1499
            } else {
1500
                    @first_arg = split('\s+', shift @args);
1501
            }
1502
 
1503
            unshift(@args, pop @first_arg);
1504
            $type = join " ", @first_arg;
1505
 
1506
            foreach $param (@args) {
1507
                if ($param =~ m/^(\*+)\s*(.*)/) {
1508
                    push_parameter($2, "$type $1", $file);
1509
                }
1510
                elsif ($param =~ m/(.*?):(\d+)/) {
1511
                    push_parameter($1, "$type:$2", $file)
1512
                }
1513
                else {
1514
                    push_parameter($param, $type, $file);
1515
                }
1516
            }
1517
        }
1518
    }
1519
}
1520
 
1521
sub push_parameter($$$) {
1522
        my $param = shift;
1523
        my $type = shift;
1524
        my $file = shift;
1525
 
1526
        if (($anon_struct_union == 1) && ($type eq "") &&
1527
            ($param eq "}")) {
1528
                return;         # ignore the ending }; from anon. struct/union
1529
        }
1530
 
1531
        $anon_struct_union = 0;
1532
        my $param_name = $param;
1533
        $param_name =~ s/\[.*//;
1534
 
1535
        if ($type eq "" && $param =~ /\.\.\.$/)
1536
        {
1537
            $type="";
1538
            $parameterdescs{$param} = "variable arguments";
1539
        }
1540
        elsif ($type eq "" && ($param eq "" or $param eq "void"))
1541
        {
1542
            $type="";
1543
            $param="void";
1544
            $parameterdescs{void} = "no arguments";
1545
        }
1546
        elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
1547
        # handle unnamed (anonymous) union or struct:
1548
        {
1549
                $type = $param;
1550
                $param = "{unnamed_" . $param . "}";
1551
                $parameterdescs{$param} = "anonymous\n";
1552
                $anon_struct_union = 1;
1553
        }
1554
 
1555
        # warn if parameter has no description
1556
        # (but ignore ones starting with # as these are not parameters
1557
        # but inline preprocessor statements);
1558
        # also ignore unnamed structs/unions;
1559
        if (!$anon_struct_union) {
1560
        if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
1561
 
1562
            $parameterdescs{$param_name} = $undescribed;
1563
 
1564
            if (($type eq 'function') || ($type eq 'enum')) {
1565
                print STDERR "Warning(${file}:$.): Function parameter ".
1566
                    "or member '$param' not " .
1567
                    "described in '$declaration_name'\n";
1568
            }
1569
            print STDERR "Warning(${file}:$.):".
1570
                         " No description found for parameter '$param'\n";
1571
            ++$warnings;
1572
        }
1573
        }
1574
 
1575
        push @parameterlist, $param;
1576
        $parametertypes{$param} = $type;
1577
}
1578
 
1579
##
1580
# takes a function prototype and the name of the current file being
1581
# processed and spits out all the details stored in the global
1582
# arrays/hashes.
1583
sub dump_function($$) {
1584
    my $prototype = shift;
1585
    my $file = shift;
1586
 
1587
    $prototype =~ s/^static +//;
1588
    $prototype =~ s/^extern +//;
1589
    $prototype =~ s/^fastcall +//;
1590
    $prototype =~ s/^asmlinkage +//;
1591
    $prototype =~ s/^inline +//;
1592
    $prototype =~ s/^__inline__ +//;
1593
    $prototype =~ s/^__inline +//;
1594
    $prototype =~ s/^__always_inline +//;
1595
    $prototype =~ s/^noinline +//;
1596
    $prototype =~ s/__devinit +//;
1597
    $prototype =~ s/^#define\s+//; #ak added
1598
    $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
1599
 
1600
    # Yes, this truly is vile.  We are looking for:
1601
    # 1. Return type (may be nothing if we're looking at a macro)
1602
    # 2. Function name
1603
    # 3. Function parameters.
1604
    #
1605
    # All the while we have to watch out for function pointer parameters
1606
    # (which IIRC is what the two sections are for), C types (these
1607
    # regexps don't even start to express all the possibilities), and
1608
    # so on.
1609
    #
1610
    # If you mess with these regexps, it's a good idea to check that
1611
    # the following functions' documentation still comes out right:
1612
    # - parport_register_device (function pointer parameters)
1613
    # - atomic_set (macro)
1614
    # - pci_match_device, __copy_to_user (long return type)
1615
 
1616
    if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1617
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1618
        $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1619
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1620
        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1621
        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1622
        $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
1623
        $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1624
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1625
        $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1626
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1627
        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1628
        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1629
        $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1630
        $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1631
        $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
1632
        $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
1633
        $return_type = $1;
1634
        $declaration_name = $2;
1635
        my $args = $3;
1636
 
1637
        create_parameterlist($args, ',', $file);
1638
    } else {
1639
        print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
1640
        ++$errors;
1641
        return;
1642
    }
1643
 
1644
    output_declaration($declaration_name,
1645
                       'function',
1646
                       {'function' => $declaration_name,
1647
                        'module' => $modulename,
1648
                        'functiontype' => $return_type,
1649
                        'parameterlist' => \@parameterlist,
1650
                        'parameterdescs' => \%parameterdescs,
1651
                        'parametertypes' => \%parametertypes,
1652
                        'sectionlist' => \@sectionlist,
1653
                        'sections' => \%sections,
1654
                        'purpose' => $declaration_purpose
1655
                       });
1656
}
1657
 
1658
sub process_file($);
1659
 
1660
# Read the file that maps relative names to absolute names for
1661
# separate source and object directories and for shadow trees.
1662
if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
1663
        my ($relname, $absname);
1664
        while() {
1665
                chop();
1666
                ($relname, $absname) = (split())[0..1];
1667
                $relname =~ s:^/+::;
1668
                $source_map{$relname} = $absname;
1669
        }
1670
        close(SOURCE_MAP);
1671
}
1672
 
1673
if ($filelist) {
1674
        open(FLIST,"<$filelist") or die "Can't open file list $filelist";
1675
        while() {
1676
                chop;
1677
                process_file($_);
1678
        }
1679
}
1680
 
1681
foreach (@ARGV) {
1682
    chomp;
1683
    process_file($_);
1684
}
1685
if ($verbose && $errors) {
1686
  print STDERR "$errors errors\n";
1687
}
1688
if ($verbose && $warnings) {
1689
  print STDERR "$warnings warnings\n";
1690
}
1691
 
1692
exit($errors);
1693
 
1694
sub reset_state {
1695
    $function = "";
1696
    %constants = ();
1697
    %parameterdescs = ();
1698
    %parametertypes = ();
1699
    @parameterlist = ();
1700
    %sections = ();
1701
    @sectionlist = ();
1702
    $prototype = "";
1703
 
1704
    $state = 0;
1705
}
1706
 
1707
sub process_state3_function($$) {
1708
    my $x = shift;
1709
    my $file = shift;
1710
 
1711
    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1712
 
1713
    if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) {
1714
        # do nothing
1715
    }
1716
    elsif ($x =~ /([^\{]*)/) {
1717
        $prototype .= $1;
1718
    }
1719
    if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {
1720
        $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
1721
        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1722
        $prototype =~ s@^\s+@@gos; # strip leading spaces
1723
        dump_function($prototype,$file);
1724
        reset_state();
1725
    }
1726
}
1727
 
1728
sub process_state3_type($$) {
1729
    my $x = shift;
1730
    my $file = shift;
1731
 
1732
    $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
1733
    $x =~ s@^\s+@@gos; # strip leading spaces
1734
    $x =~ s@\s+$@@gos; # strip trailing spaces
1735
    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
1736
 
1737
    if ($x =~ /^#/) {
1738
        # To distinguish preprocessor directive from regular declaration later.
1739
        $x .= ";";
1740
    }
1741
 
1742
    while (1) {
1743
        if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
1744
            $prototype .= $1 . $2;
1745
            ($2 eq '{') && $brcount++;
1746
            ($2 eq '}') && $brcount--;
1747
            if (($2 eq ';') && ($brcount == 0)) {
1748
                dump_declaration($prototype,$file);
1749
                reset_state();
1750
                last;
1751
            }
1752
            $x = $3;
1753
        } else {
1754
            $prototype .= $x;
1755
            last;
1756
        }
1757
    }
1758
}
1759
 
1760
# xml_escape: replace <, >, and & in the text stream;
1761
#
1762
# however, formatting controls that are generated internally/locally in the
1763
# kernel-doc script are not escaped here; instead, they begin life like
1764
# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
1765
# are converted to their mnemonic-expected output, without the 4 * '\' & ':',
1766
# just before actual output; (this is done by local_unescape())
1767
sub xml_escape($) {
1768
        my $text = shift;
1769
        if (($output_mode eq "text") || ($output_mode eq "man")) {
1770
                return $text;
1771
        }
1772
        $text =~ s/\&/\\\\\\amp;/g;
1773
        $text =~ s/\
1774
        $text =~ s/\>/\\\\\\gt;/g;
1775
        return $text;
1776
}
1777
 
1778
# convert local escape strings to html
1779
# local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
1780
sub local_unescape($) {
1781
        my $text = shift;
1782
        if (($output_mode eq "text") || ($output_mode eq "man")) {
1783
                return $text;
1784
        }
1785
        $text =~ s/\\\\\\\\lt:/
1786
        $text =~ s/\\\\\\\\gt:/>/g;
1787
        return $text;
1788
}
1789
 
1790
sub process_file($) {
1791
    my $file;
1792
    my $identifier;
1793
    my $func;
1794
    my $descr;
1795
    my $initial_section_counter = $section_counter;
1796
 
1797
    if (defined($ENV{'SRCTREE'})) {
1798
        $file = "$ENV{'SRCTREE'}" . "/" . "@_";
1799
    }
1800
    else {
1801
        $file = "@_";
1802
    }
1803
    if (defined($source_map{$file})) {
1804
        $file = $source_map{$file};
1805
    }
1806
 
1807
    if (!open(IN,"<$file")) {
1808
        print STDERR "Error: Cannot open file $file\n";
1809
        ++$errors;
1810
        return;
1811
    }
1812
 
1813
    $section_counter = 0;
1814
    while () {
1815
        if ($state == 0) {
1816
            if (/$doc_start/o) {
1817
                $state = 1;             # next line is always the function name
1818
                $in_doc_sect = 0;
1819
            }
1820
        } elsif ($state == 1) { # this line is the function name (always)
1821
            if (/$doc_block/o) {
1822
                $state = 4;
1823
                $contents = "";
1824
                if ( $1 eq "" ) {
1825
                        $section = $section_intro;
1826
                } else {
1827
                        $section = $1;
1828
                }
1829
            }
1830
            elsif (/$doc_decl/o) {
1831
                $identifier = $1;
1832
                if (/\s*([\w\s]+?)\s*-/) {
1833
                    $identifier = $1;
1834
                }
1835
 
1836
                $state = 2;
1837
                if (/-(.*)/) {
1838
                    # strip leading/trailing/multiple spaces
1839
                    $descr= $1;
1840
                    $descr =~ s/^\s*//;
1841
                    $descr =~ s/\s*$//;
1842
                    $descr =~ s/\s+/ /;
1843
                    $declaration_purpose = xml_escape($descr);
1844
                } else {
1845
                    $declaration_purpose = "";
1846
                }
1847
                if ($identifier =~ m/^struct/) {
1848
                    $decl_type = 'struct';
1849
                } elsif ($identifier =~ m/^union/) {
1850
                    $decl_type = 'union';
1851
                } elsif ($identifier =~ m/^enum/) {
1852
                    $decl_type = 'enum';
1853
                } elsif ($identifier =~ m/^typedef/) {
1854
                    $decl_type = 'typedef';
1855
                } else {
1856
                    $decl_type = 'function';
1857
                }
1858
 
1859
                if ($verbose) {
1860
                    print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
1861
                }
1862
            } else {
1863
                print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
1864
                " - I thought it was a doc line\n";
1865
                ++$warnings;
1866
                $state = 0;
1867
            }
1868
        } elsif ($state == 2) { # look for head: lines, and include content
1869
            if (/$doc_sect/o) {
1870
                $newsection = $1;
1871
                $newcontents = $2;
1872
 
1873
                if ($contents ne "") {
1874
                    if (!$in_doc_sect && $verbose) {
1875
                        print STDERR "Warning(${file}:$.): contents before sections\n";
1876
                        ++$warnings;
1877
                    }
1878
                    dump_section($section, xml_escape($contents));
1879
                    $section = $section_default;
1880
                }
1881
 
1882
                $in_doc_sect = 1;
1883
                $contents = $newcontents;
1884
                if ($contents ne "") {
1885
                    while ((substr($contents, 0, 1) eq " ") ||
1886
                        substr($contents, 0, 1) eq "\t") {
1887
                            $contents = substr($contents, 1);
1888
                    }
1889
                    $contents .= "\n";
1890
                }
1891
                $section = $newsection;
1892
            } elsif (/$doc_end/) {
1893
 
1894
                if ($contents ne "") {
1895
                    dump_section($section, xml_escape($contents));
1896
                    $section = $section_default;
1897
                    $contents = "";
1898
                }
1899
 
1900
                $prototype = "";
1901
                $state = 3;
1902
                $brcount = 0;
1903
#               print STDERR "end of doc comment, looking for prototype\n";
1904
            } elsif (/$doc_content/) {
1905
                # miguel-style comment kludge, look for blank lines after
1906
                # @parameter line to signify start of description
1907
                if ($1 eq "" &&
1908
                        ($section =~ m/^@/ || $section eq $section_context)) {
1909
                    dump_section($section, xml_escape($contents));
1910
                    $section = $section_default;
1911
                    $contents = "";
1912
                } else {
1913
                    $contents .= $1."\n";
1914
                }
1915
            } else {
1916
                # i dont know - bad line?  ignore.
1917
                print STDERR "Warning(${file}:$.): bad line: $_";
1918
                ++$warnings;
1919
            }
1920
        } elsif ($state == 3) { # scanning for function '{' (end of prototype)
1921
            if ($decl_type eq 'function') {
1922
                process_state3_function($_, $file);
1923
            } else {
1924
                process_state3_type($_, $file);
1925
            }
1926
        } elsif ($state == 4) {
1927
                # Documentation block
1928
                if (/$doc_block/) {
1929
                        dump_section($section, xml_escape($contents));
1930
                        output_intro({'sectionlist' => \@sectionlist,
1931
                                      'sections' => \%sections });
1932
                        $contents = "";
1933
                        $function = "";
1934
                        %constants = ();
1935
                        %parameterdescs = ();
1936
                        %parametertypes = ();
1937
                        @parameterlist = ();
1938
                        %sections = ();
1939
                        @sectionlist = ();
1940
                        $prototype = "";
1941
                        if ( $1 eq "" ) {
1942
                                $section = $section_intro;
1943
                        } else {
1944
                                $section = $1;
1945
                        }
1946
                }
1947
                elsif (/$doc_end/)
1948
                {
1949
                        dump_section($section, xml_escape($contents));
1950
                        output_intro({'sectionlist' => \@sectionlist,
1951
                                      'sections' => \%sections });
1952
                        $contents = "";
1953
                        $function = "";
1954
                        %constants = ();
1955
                        %parameterdescs = ();
1956
                        %parametertypes = ();
1957
                        @parameterlist = ();
1958
                        %sections = ();
1959
                        @sectionlist = ();
1960
                        $prototype = "";
1961
                        $state = 0;
1962
                }
1963
                elsif (/$doc_content/)
1964
                {
1965
                        if ( $1 eq "" )
1966
                        {
1967
                                $contents .= $blankline;
1968
                        }
1969
                        else
1970
                        {
1971
                                $contents .= $1 . "\n";
1972
                        }
1973
                }
1974
        }
1975
    }
1976
    if ($initial_section_counter == $section_counter) {
1977
        print STDERR "Warning(${file}): no structured comments found\n";
1978
        if ($output_mode eq "xml") {
1979
            # The template wants at least one RefEntry here; make one.
1980
            print "\n";
1981
            print " \n";
1982
            print "  \n";
1983
            print "   ${file}\n";
1984
            print "  \n";
1985
            print "  \n";
1986
            print "   Document generation inconsistency\n";
1987
            print "  \n";
1988
            print " \n";
1989
            print " \n";
1990
            print "  \n";</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>1991</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>            print "   Oops\n";</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>1992</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>            print "  \n";
1993
            print "  \n";
1994
            print "   \n";
1995
            print "    The template for this document tried to insert\n";
1996
            print "    the structured comment from the file\n";
1997
            print "    ${file} at this point,\n";
1998
            print "    but none was found.\n";
1999
            print "    This dummy section is inserted to allow\n";
2000
            print "    generation to continue.\n";
2001
            print "   \n";
2002
            print "  \n";
2003
            print " \n";
2004
            print "\n";
2005
        }
2006
    }
2007
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.