162306a36Sopenharmony_ci#!/usr/bin/env perl 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ciuse warnings; 562306a36Sopenharmony_ciuse strict; 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ## 862306a36Sopenharmony_ci## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## 962306a36Sopenharmony_ci## Copyright (C) 2001 Simon Huggins ## 1062306a36Sopenharmony_ci## Copyright (C) 2005-2012 Randy Dunlap ## 1162306a36Sopenharmony_ci## Copyright (C) 2012 Dan Luedtke ## 1262306a36Sopenharmony_ci## ## 1362306a36Sopenharmony_ci## #define enhancements by Armin Kuster <akuster@mvista.com> ## 1462306a36Sopenharmony_ci## Copyright (c) 2000 MontaVista Software, Inc. ## 1562306a36Sopenharmony_ci# 1662306a36Sopenharmony_ci# Copyright (C) 2022 Tomasz Warniełło (POD) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciuse Pod::Usage qw/pod2usage/; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci=head1 NAME 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cikernel-doc - Print formatted kernel documentation to stdout 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci=head1 SYNOPSIS 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-description] [-Wcontents-before-sections] 2762306a36Sopenharmony_ci [ -man | 2862306a36Sopenharmony_ci -rst [-sphinx-version VERSION] [-enable-lineno] | 2962306a36Sopenharmony_ci -none 3062306a36Sopenharmony_ci ] 3162306a36Sopenharmony_ci [ 3262306a36Sopenharmony_ci -export | 3362306a36Sopenharmony_ci -internal | 3462306a36Sopenharmony_ci [-function NAME] ... | 3562306a36Sopenharmony_ci [-nosymbol NAME] ... 3662306a36Sopenharmony_ci ] 3762306a36Sopenharmony_ci [-no-doc-sections] 3862306a36Sopenharmony_ci [-export-file FILE] ... 3962306a36Sopenharmony_ci FILE ... 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciRun `kernel-doc -h` for details. 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci=head1 DESCRIPTION 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciRead C language source or header FILEs, extract embedded documentation comments, 4662306a36Sopenharmony_ciand print formatted documentation to standard output. 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciThe documentation comments are identified by the "/**" opening comment mark. 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciSee Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax. 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci=cut 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci# more perldoc at the end of the file 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci## init lots of data 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cimy $errors = 0; 5962306a36Sopenharmony_cimy $warnings = 0; 6062306a36Sopenharmony_cimy $anon_struct_union = 0; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci# match expressions used to find embedded type information 6362306a36Sopenharmony_cimy $type_constant = '\b``([^\`]+)``\b'; 6462306a36Sopenharmony_cimy $type_constant2 = '\%([-_\w]+)'; 6562306a36Sopenharmony_cimy $type_func = '(\w+)\(\)'; 6662306a36Sopenharmony_cimy $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; 6762306a36Sopenharmony_cimy $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; 6862306a36Sopenharmony_cimy $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params 6962306a36Sopenharmony_cimy $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params 7062306a36Sopenharmony_cimy $type_env = '(\$\w+)'; 7162306a36Sopenharmony_cimy $type_enum = '\&(enum\s*([_\w]+))'; 7262306a36Sopenharmony_cimy $type_struct = '\&(struct\s*([_\w]+))'; 7362306a36Sopenharmony_cimy $type_typedef = '\&(typedef\s*([_\w]+))'; 7462306a36Sopenharmony_cimy $type_union = '\&(union\s*([_\w]+))'; 7562306a36Sopenharmony_cimy $type_member = '\&([_\w]+)(\.|->)([_\w]+)'; 7662306a36Sopenharmony_cimy $type_fallback = '\&([_\w]+)'; 7762306a36Sopenharmony_cimy $type_member_func = $type_member . '\(\)'; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci# Output conversion substitutions. 8062306a36Sopenharmony_ci# One for each output format 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci# these are pretty rough 8362306a36Sopenharmony_cimy @highlights_man = ( 8462306a36Sopenharmony_ci [$type_constant, "\$1"], 8562306a36Sopenharmony_ci [$type_constant2, "\$1"], 8662306a36Sopenharmony_ci [$type_func, "\\\\fB\$1\\\\fP"], 8762306a36Sopenharmony_ci [$type_enum, "\\\\fI\$1\\\\fP"], 8862306a36Sopenharmony_ci [$type_struct, "\\\\fI\$1\\\\fP"], 8962306a36Sopenharmony_ci [$type_typedef, "\\\\fI\$1\\\\fP"], 9062306a36Sopenharmony_ci [$type_union, "\\\\fI\$1\\\\fP"], 9162306a36Sopenharmony_ci [$type_param, "\\\\fI\$1\\\\fP"], 9262306a36Sopenharmony_ci [$type_param_ref, "\\\\fI\$1\$2\\\\fP"], 9362306a36Sopenharmony_ci [$type_member, "\\\\fI\$1\$2\$3\\\\fP"], 9462306a36Sopenharmony_ci [$type_fallback, "\\\\fI\$1\\\\fP"] 9562306a36Sopenharmony_ci ); 9662306a36Sopenharmony_cimy $blankline_man = ""; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci# rst-mode 9962306a36Sopenharmony_cimy @highlights_rst = ( 10062306a36Sopenharmony_ci [$type_constant, "``\$1``"], 10162306a36Sopenharmony_ci [$type_constant2, "``\$1``"], 10262306a36Sopenharmony_ci # Note: need to escape () to avoid func matching later 10362306a36Sopenharmony_ci [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"], 10462306a36Sopenharmony_ci [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"], 10562306a36Sopenharmony_ci [$type_fp_param, "**\$1\\\\(\\\\)**"], 10662306a36Sopenharmony_ci [$type_fp_param2, "**\$1\\\\(\\\\)**"], 10762306a36Sopenharmony_ci [$type_func, "\$1()"], 10862306a36Sopenharmony_ci [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"], 10962306a36Sopenharmony_ci [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"], 11062306a36Sopenharmony_ci [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"], 11162306a36Sopenharmony_ci [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"], 11262306a36Sopenharmony_ci # in rst this can refer to any type 11362306a36Sopenharmony_ci [$type_fallback, "\\:c\\:type\\:`\$1`"], 11462306a36Sopenharmony_ci [$type_param_ref, "**\$1\$2**"] 11562306a36Sopenharmony_ci ); 11662306a36Sopenharmony_cimy $blankline_rst = "\n"; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci# read arguments 11962306a36Sopenharmony_ciif ($#ARGV == -1) { 12062306a36Sopenharmony_ci pod2usage( 12162306a36Sopenharmony_ci -message => "No arguments!\n", 12262306a36Sopenharmony_ci -exitval => 1, 12362306a36Sopenharmony_ci -verbose => 99, 12462306a36Sopenharmony_ci -sections => 'SYNOPSIS', 12562306a36Sopenharmony_ci -output => \*STDERR, 12662306a36Sopenharmony_ci ); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cimy $kernelversion; 13062306a36Sopenharmony_cimy ($sphinx_major, $sphinx_minor, $sphinx_patch); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cimy $dohighlight = ""; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cimy $verbose = 0; 13562306a36Sopenharmony_cimy $Werror = 0; 13662306a36Sopenharmony_cimy $Wreturn = 0; 13762306a36Sopenharmony_cimy $Wshort_desc = 0; 13862306a36Sopenharmony_cimy $Wcontents_before_sections = 0; 13962306a36Sopenharmony_cimy $output_mode = "rst"; 14062306a36Sopenharmony_cimy $output_preformatted = 0; 14162306a36Sopenharmony_cimy $no_doc_sections = 0; 14262306a36Sopenharmony_cimy $enable_lineno = 0; 14362306a36Sopenharmony_cimy @highlights = @highlights_rst; 14462306a36Sopenharmony_cimy $blankline = $blankline_rst; 14562306a36Sopenharmony_cimy $modulename = "Kernel API"; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ciuse constant { 14862306a36Sopenharmony_ci OUTPUT_ALL => 0, # output all symbols and doc sections 14962306a36Sopenharmony_ci OUTPUT_INCLUDE => 1, # output only specified symbols 15062306a36Sopenharmony_ci OUTPUT_EXPORTED => 2, # output exported symbols 15162306a36Sopenharmony_ci OUTPUT_INTERNAL => 3, # output non-exported symbols 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_cimy $output_selection = OUTPUT_ALL; 15462306a36Sopenharmony_cimy $show_not_found = 0; # No longer used 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cimy @export_file_list; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cimy @build_time; 15962306a36Sopenharmony_ciif (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && 16062306a36Sopenharmony_ci (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') { 16162306a36Sopenharmony_ci @build_time = gmtime($seconds); 16262306a36Sopenharmony_ci} else { 16362306a36Sopenharmony_ci @build_time = localtime; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cimy $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 16762306a36Sopenharmony_ci 'July', 'August', 'September', 'October', 16862306a36Sopenharmony_ci 'November', 'December')[$build_time[4]] . 16962306a36Sopenharmony_ci " " . ($build_time[5]+1900); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci# Essentially these are globals. 17262306a36Sopenharmony_ci# They probably want to be tidied up, made more localised or something. 17362306a36Sopenharmony_ci# CAVEAT EMPTOR! Some of the others I localised may not want to be, which 17462306a36Sopenharmony_ci# could cause "use of undefined value" or other bugs. 17562306a36Sopenharmony_cimy ($function, %function_table, %parametertypes, $declaration_purpose); 17662306a36Sopenharmony_cimy %nosymbol_table = (); 17762306a36Sopenharmony_cimy $declaration_start_line; 17862306a36Sopenharmony_cimy ($type, $declaration_name, $return_type); 17962306a36Sopenharmony_cimy ($newsection, $newcontents, $prototype, $brcount, %source_map); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciif (defined($ENV{'KBUILD_VERBOSE'}) && $ENV{'KBUILD_VERBOSE'} =~ '1') { 18262306a36Sopenharmony_ci $verbose = 1; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciif (defined($ENV{'KCFLAGS'})) { 18662306a36Sopenharmony_ci my $kcflags = "$ENV{'KCFLAGS'}"; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if ($kcflags =~ /Werror/) { 18962306a36Sopenharmony_ci $Werror = 1; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci# reading this variable is for backwards compat just in case 19462306a36Sopenharmony_ci# someone was calling it with the variable from outside the 19562306a36Sopenharmony_ci# kernel's build system 19662306a36Sopenharmony_ciif (defined($ENV{'KDOC_WERROR'})) { 19762306a36Sopenharmony_ci $Werror = "$ENV{'KDOC_WERROR'}"; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci# other environment variables are converted to command-line 20062306a36Sopenharmony_ci# arguments in cmd_checkdoc in the build system 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci# Generated docbook code is inserted in a template at a point where 20362306a36Sopenharmony_ci# docbook v3.1 requires a non-zero sequence of RefEntry's; see: 20462306a36Sopenharmony_ci# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html 20562306a36Sopenharmony_ci# We keep track of number of generated entries and generate a dummy 20662306a36Sopenharmony_ci# if needs be to ensure the expanded template can be postprocessed 20762306a36Sopenharmony_ci# into html. 20862306a36Sopenharmony_cimy $section_counter = 0; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cimy $lineprefix=""; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci# Parser states 21362306a36Sopenharmony_ciuse constant { 21462306a36Sopenharmony_ci STATE_NORMAL => 0, # normal code 21562306a36Sopenharmony_ci STATE_NAME => 1, # looking for function name 21662306a36Sopenharmony_ci STATE_BODY_MAYBE => 2, # body - or maybe more description 21762306a36Sopenharmony_ci STATE_BODY => 3, # the body of the comment 21862306a36Sopenharmony_ci STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line 21962306a36Sopenharmony_ci STATE_PROTO => 5, # scanning prototype 22062306a36Sopenharmony_ci STATE_DOCBLOCK => 6, # documentation block 22162306a36Sopenharmony_ci STATE_INLINE => 7, # gathering doc outside main block 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_cimy $state; 22462306a36Sopenharmony_cimy $in_doc_sect; 22562306a36Sopenharmony_cimy $leading_space; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci# Inline documentation state 22862306a36Sopenharmony_ciuse constant { 22962306a36Sopenharmony_ci STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE) 23062306a36Sopenharmony_ci STATE_INLINE_NAME => 1, # looking for member name (@foo:) 23162306a36Sopenharmony_ci STATE_INLINE_TEXT => 2, # looking for member documentation 23262306a36Sopenharmony_ci STATE_INLINE_END => 3, # done 23362306a36Sopenharmony_ci STATE_INLINE_ERROR => 4, # error - Comment without header was found. 23462306a36Sopenharmony_ci # Spit a warning as it's not 23562306a36Sopenharmony_ci # proper kernel-doc and ignore the rest. 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_cimy $inline_doc_state; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#declaration types: can be 24062306a36Sopenharmony_ci# 'function', 'struct', 'union', 'enum', 'typedef' 24162306a36Sopenharmony_cimy $decl_type; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci# Name of the kernel-doc identifier for non-DOC markups 24462306a36Sopenharmony_cimy $identifier; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cimy $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 24762306a36Sopenharmony_cimy $doc_end = '\*/'; 24862306a36Sopenharmony_cimy $doc_com = '\s*\*\s*'; 24962306a36Sopenharmony_cimy $doc_com_body = '\s*\* ?'; 25062306a36Sopenharmony_cimy $doc_decl = $doc_com . '(\w+)'; 25162306a36Sopenharmony_ci# @params and a strictly limited set of supported section names 25262306a36Sopenharmony_ci# Specifically: 25362306a36Sopenharmony_ci# Match @word: 25462306a36Sopenharmony_ci# @...: 25562306a36Sopenharmony_ci# @{section-name}: 25662306a36Sopenharmony_ci# while trying to not match literal block starts like "example::" 25762306a36Sopenharmony_ci# 25862306a36Sopenharmony_cimy $doc_sect = $doc_com . 25962306a36Sopenharmony_ci '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:([^:].*)?$'; 26062306a36Sopenharmony_cimy $doc_content = $doc_com_body . '(.*)'; 26162306a36Sopenharmony_cimy $doc_block = $doc_com . 'DOC:\s*(.*)?'; 26262306a36Sopenharmony_cimy $doc_inline_start = '^\s*/\*\*\s*$'; 26362306a36Sopenharmony_cimy $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)'; 26462306a36Sopenharmony_cimy $doc_inline_end = '^\s*\*/\s*$'; 26562306a36Sopenharmony_cimy $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$'; 26662306a36Sopenharmony_cimy $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; 26762306a36Sopenharmony_cimy $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*\w+\)\s*;'; 26862306a36Sopenharmony_cimy $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)}; 26962306a36Sopenharmony_cimy $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cimy %parameterdescs; 27262306a36Sopenharmony_cimy %parameterdesc_start_lines; 27362306a36Sopenharmony_cimy @parameterlist; 27462306a36Sopenharmony_cimy %sections; 27562306a36Sopenharmony_cimy @sectionlist; 27662306a36Sopenharmony_cimy %section_start_lines; 27762306a36Sopenharmony_cimy $sectcheck; 27862306a36Sopenharmony_cimy $struct_actual; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cimy $contents = ""; 28162306a36Sopenharmony_cimy $new_start_line = 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci# the canonical section names. see also $doc_sect above. 28462306a36Sopenharmony_cimy $section_default = "Description"; # default section 28562306a36Sopenharmony_cimy $section_intro = "Introduction"; 28662306a36Sopenharmony_cimy $section = $section_default; 28762306a36Sopenharmony_cimy $section_context = "Context"; 28862306a36Sopenharmony_cimy $section_return = "Return"; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cimy $undescribed = "-- undescribed --"; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cireset_state(); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciwhile ($ARGV[0] =~ m/^--?(.*)/) { 29562306a36Sopenharmony_ci my $cmd = $1; 29662306a36Sopenharmony_ci shift @ARGV; 29762306a36Sopenharmony_ci if ($cmd eq "man") { 29862306a36Sopenharmony_ci $output_mode = "man"; 29962306a36Sopenharmony_ci @highlights = @highlights_man; 30062306a36Sopenharmony_ci $blankline = $blankline_man; 30162306a36Sopenharmony_ci } elsif ($cmd eq "rst") { 30262306a36Sopenharmony_ci $output_mode = "rst"; 30362306a36Sopenharmony_ci @highlights = @highlights_rst; 30462306a36Sopenharmony_ci $blankline = $blankline_rst; 30562306a36Sopenharmony_ci } elsif ($cmd eq "none") { 30662306a36Sopenharmony_ci $output_mode = "none"; 30762306a36Sopenharmony_ci } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document 30862306a36Sopenharmony_ci $modulename = shift @ARGV; 30962306a36Sopenharmony_ci } elsif ($cmd eq "function") { # to only output specific functions 31062306a36Sopenharmony_ci $output_selection = OUTPUT_INCLUDE; 31162306a36Sopenharmony_ci $function = shift @ARGV; 31262306a36Sopenharmony_ci $function_table{$function} = 1; 31362306a36Sopenharmony_ci } elsif ($cmd eq "nosymbol") { # Exclude specific symbols 31462306a36Sopenharmony_ci my $symbol = shift @ARGV; 31562306a36Sopenharmony_ci $nosymbol_table{$symbol} = 1; 31662306a36Sopenharmony_ci } elsif ($cmd eq "export") { # only exported symbols 31762306a36Sopenharmony_ci $output_selection = OUTPUT_EXPORTED; 31862306a36Sopenharmony_ci %function_table = (); 31962306a36Sopenharmony_ci } elsif ($cmd eq "internal") { # only non-exported symbols 32062306a36Sopenharmony_ci $output_selection = OUTPUT_INTERNAL; 32162306a36Sopenharmony_ci %function_table = (); 32262306a36Sopenharmony_ci } elsif ($cmd eq "export-file") { 32362306a36Sopenharmony_ci my $file = shift @ARGV; 32462306a36Sopenharmony_ci push(@export_file_list, $file); 32562306a36Sopenharmony_ci } elsif ($cmd eq "v") { 32662306a36Sopenharmony_ci $verbose = 1; 32762306a36Sopenharmony_ci } elsif ($cmd eq "Werror") { 32862306a36Sopenharmony_ci $Werror = 1; 32962306a36Sopenharmony_ci } elsif ($cmd eq "Wreturn") { 33062306a36Sopenharmony_ci $Wreturn = 1; 33162306a36Sopenharmony_ci } elsif ($cmd eq "Wshort-desc") { 33262306a36Sopenharmony_ci $Wshort_desc = 1; 33362306a36Sopenharmony_ci } elsif ($cmd eq "Wcontents-before-sections") { 33462306a36Sopenharmony_ci $Wcontents_before_sections = 1; 33562306a36Sopenharmony_ci } elsif ($cmd eq "Wall") { 33662306a36Sopenharmony_ci $Wreturn = 1; 33762306a36Sopenharmony_ci $Wshort_desc = 1; 33862306a36Sopenharmony_ci $Wcontents_before_sections = 1; 33962306a36Sopenharmony_ci } elsif (($cmd eq "h") || ($cmd eq "help")) { 34062306a36Sopenharmony_ci pod2usage(-exitval => 0, -verbose => 2); 34162306a36Sopenharmony_ci } elsif ($cmd eq 'no-doc-sections') { 34262306a36Sopenharmony_ci $no_doc_sections = 1; 34362306a36Sopenharmony_ci } elsif ($cmd eq 'enable-lineno') { 34462306a36Sopenharmony_ci $enable_lineno = 1; 34562306a36Sopenharmony_ci } elsif ($cmd eq 'show-not-found') { 34662306a36Sopenharmony_ci $show_not_found = 1; # A no-op but don't fail 34762306a36Sopenharmony_ci } elsif ($cmd eq "sphinx-version") { 34862306a36Sopenharmony_ci my $ver_string = shift @ARGV; 34962306a36Sopenharmony_ci if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) { 35062306a36Sopenharmony_ci $sphinx_major = $1; 35162306a36Sopenharmony_ci if (defined($2)) { 35262306a36Sopenharmony_ci $sphinx_minor = substr($2,1); 35362306a36Sopenharmony_ci } else { 35462306a36Sopenharmony_ci $sphinx_minor = 0; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci if (defined($3)) { 35762306a36Sopenharmony_ci $sphinx_patch = substr($3,1) 35862306a36Sopenharmony_ci } else { 35962306a36Sopenharmony_ci $sphinx_patch = 0; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci } else { 36262306a36Sopenharmony_ci die "Sphinx version should either major.minor or major.minor.patch format\n"; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci } else { 36562306a36Sopenharmony_ci # Unknown argument 36662306a36Sopenharmony_ci pod2usage( 36762306a36Sopenharmony_ci -message => "Argument unknown!\n", 36862306a36Sopenharmony_ci -exitval => 1, 36962306a36Sopenharmony_ci -verbose => 99, 37062306a36Sopenharmony_ci -sections => 'SYNOPSIS', 37162306a36Sopenharmony_ci -output => \*STDERR, 37262306a36Sopenharmony_ci ); 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci if ($#ARGV < 0){ 37562306a36Sopenharmony_ci pod2usage( 37662306a36Sopenharmony_ci -message => "FILE argument missing\n", 37762306a36Sopenharmony_ci -exitval => 1, 37862306a36Sopenharmony_ci -verbose => 99, 37962306a36Sopenharmony_ci -sections => 'SYNOPSIS', 38062306a36Sopenharmony_ci -output => \*STDERR, 38162306a36Sopenharmony_ci ); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci# continue execution near EOF; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci# The C domain dialect changed on Sphinx 3. So, we need to check the 38862306a36Sopenharmony_ci# version in order to produce the right tags. 38962306a36Sopenharmony_cisub findprog($) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci foreach(split(/:/, $ENV{PATH})) { 39262306a36Sopenharmony_ci return "$_/$_[0]" if(-x "$_/$_[0]"); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cisub get_sphinx_version() 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci my $ver; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci my $cmd = "sphinx-build"; 40162306a36Sopenharmony_ci if (!findprog($cmd)) { 40262306a36Sopenharmony_ci my $cmd = "sphinx-build3"; 40362306a36Sopenharmony_ci if (!findprog($cmd)) { 40462306a36Sopenharmony_ci $sphinx_major = 1; 40562306a36Sopenharmony_ci $sphinx_minor = 2; 40662306a36Sopenharmony_ci $sphinx_patch = 0; 40762306a36Sopenharmony_ci printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n", 40862306a36Sopenharmony_ci $sphinx_major, $sphinx_minor, $sphinx_patch; 40962306a36Sopenharmony_ci return; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci open IN, "$cmd --version 2>&1 |"; 41462306a36Sopenharmony_ci while (<IN>) { 41562306a36Sopenharmony_ci if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { 41662306a36Sopenharmony_ci $sphinx_major = $1; 41762306a36Sopenharmony_ci $sphinx_minor = $2; 41862306a36Sopenharmony_ci $sphinx_patch = $3; 41962306a36Sopenharmony_ci last; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci # Sphinx 1.2.x uses a different format 42262306a36Sopenharmony_ci if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { 42362306a36Sopenharmony_ci $sphinx_major = $1; 42462306a36Sopenharmony_ci $sphinx_minor = $2; 42562306a36Sopenharmony_ci $sphinx_patch = $3; 42662306a36Sopenharmony_ci last; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci close IN; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci# get kernel version from env 43362306a36Sopenharmony_cisub get_kernel_version() { 43462306a36Sopenharmony_ci my $version = 'unknown kernel version'; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (defined($ENV{'KERNELVERSION'})) { 43762306a36Sopenharmony_ci $version = $ENV{'KERNELVERSION'}; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci return $version; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci# 44362306a36Sopenharmony_cisub print_lineno { 44462306a36Sopenharmony_ci my $lineno = shift; 44562306a36Sopenharmony_ci if ($enable_lineno && defined($lineno)) { 44662306a36Sopenharmony_ci print ".. LINENO " . $lineno . "\n"; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cisub emit_warning { 45162306a36Sopenharmony_ci my $location = shift; 45262306a36Sopenharmony_ci my $msg = shift; 45362306a36Sopenharmony_ci print STDERR "$location: warning: $msg"; 45462306a36Sopenharmony_ci ++$warnings; 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci## 45762306a36Sopenharmony_ci# dumps section contents to arrays/hashes intended for that purpose. 45862306a36Sopenharmony_ci# 45962306a36Sopenharmony_cisub dump_section { 46062306a36Sopenharmony_ci my $file = shift; 46162306a36Sopenharmony_ci my $name = shift; 46262306a36Sopenharmony_ci my $contents = join "\n", @_; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci if ($name =~ m/$type_param/) { 46562306a36Sopenharmony_ci $name = $1; 46662306a36Sopenharmony_ci $parameterdescs{$name} = $contents; 46762306a36Sopenharmony_ci $sectcheck = $sectcheck . $name . " "; 46862306a36Sopenharmony_ci $parameterdesc_start_lines{$name} = $new_start_line; 46962306a36Sopenharmony_ci $new_start_line = 0; 47062306a36Sopenharmony_ci } elsif ($name eq "@\.\.\.") { 47162306a36Sopenharmony_ci $name = "..."; 47262306a36Sopenharmony_ci $parameterdescs{$name} = $contents; 47362306a36Sopenharmony_ci $sectcheck = $sectcheck . $name . " "; 47462306a36Sopenharmony_ci $parameterdesc_start_lines{$name} = $new_start_line; 47562306a36Sopenharmony_ci $new_start_line = 0; 47662306a36Sopenharmony_ci } else { 47762306a36Sopenharmony_ci if (defined($sections{$name}) && ($sections{$name} ne "")) { 47862306a36Sopenharmony_ci # Only warn on user specified duplicate section names. 47962306a36Sopenharmony_ci if ($name ne $section_default) { 48062306a36Sopenharmony_ci emit_warning("${file}:$.", "duplicate section name '$name'\n"); 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci $sections{$name} .= $contents; 48362306a36Sopenharmony_ci } else { 48462306a36Sopenharmony_ci $sections{$name} = $contents; 48562306a36Sopenharmony_ci push @sectionlist, $name; 48662306a36Sopenharmony_ci $section_start_lines{$name} = $new_start_line; 48762306a36Sopenharmony_ci $new_start_line = 0; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci## 49362306a36Sopenharmony_ci# dump DOC: section after checking that it should go out 49462306a36Sopenharmony_ci# 49562306a36Sopenharmony_cisub dump_doc_section { 49662306a36Sopenharmony_ci my $file = shift; 49762306a36Sopenharmony_ci my $name = shift; 49862306a36Sopenharmony_ci my $contents = join "\n", @_; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if ($no_doc_sections) { 50162306a36Sopenharmony_ci return; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return if (defined($nosymbol_table{$name})); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci if (($output_selection == OUTPUT_ALL) || 50762306a36Sopenharmony_ci (($output_selection == OUTPUT_INCLUDE) && 50862306a36Sopenharmony_ci defined($function_table{$name}))) 50962306a36Sopenharmony_ci { 51062306a36Sopenharmony_ci dump_section($file, $name, $contents); 51162306a36Sopenharmony_ci output_blockhead({'sectionlist' => \@sectionlist, 51262306a36Sopenharmony_ci 'sections' => \%sections, 51362306a36Sopenharmony_ci 'module' => $modulename, 51462306a36Sopenharmony_ci 'content-only' => ($output_selection != OUTPUT_ALL), }); 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci## 51962306a36Sopenharmony_ci# output function 52062306a36Sopenharmony_ci# 52162306a36Sopenharmony_ci# parameterdescs, a hash. 52262306a36Sopenharmony_ci# function => "function name" 52362306a36Sopenharmony_ci# parameterlist => @list of parameters 52462306a36Sopenharmony_ci# parameterdescs => %parameter descriptions 52562306a36Sopenharmony_ci# sectionlist => @list of sections 52662306a36Sopenharmony_ci# sections => %section descriptions 52762306a36Sopenharmony_ci# 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cisub output_highlight { 53062306a36Sopenharmony_ci my $contents = join "\n",@_; 53162306a36Sopenharmony_ci my $line; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci# DEBUG 53462306a36Sopenharmony_ci# if (!defined $contents) { 53562306a36Sopenharmony_ci# use Carp; 53662306a36Sopenharmony_ci# confess "output_highlight got called with no args?\n"; 53762306a36Sopenharmony_ci# } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci# print STDERR "contents b4:$contents\n"; 54062306a36Sopenharmony_ci eval $dohighlight; 54162306a36Sopenharmony_ci die $@ if $@; 54262306a36Sopenharmony_ci# print STDERR "contents af:$contents\n"; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci foreach $line (split "\n", $contents) { 54562306a36Sopenharmony_ci if (! $output_preformatted) { 54662306a36Sopenharmony_ci $line =~ s/^\s*//; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci if ($line eq ""){ 54962306a36Sopenharmony_ci if (! $output_preformatted) { 55062306a36Sopenharmony_ci print $lineprefix, $blankline; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci } else { 55362306a36Sopenharmony_ci if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { 55462306a36Sopenharmony_ci print "\\&$line"; 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci print $lineprefix, $line; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci print "\n"; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci## 56462306a36Sopenharmony_ci# output function in man 56562306a36Sopenharmony_cisub output_function_man(%) { 56662306a36Sopenharmony_ci my %args = %{$_[0]}; 56762306a36Sopenharmony_ci my ($parameter, $section); 56862306a36Sopenharmony_ci my $count; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci print ".SH NAME\n"; 57362306a36Sopenharmony_ci print $args{'function'} . " \\- " . $args{'purpose'} . "\n"; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci print ".SH SYNOPSIS\n"; 57662306a36Sopenharmony_ci if ($args{'functiontype'} ne "") { 57762306a36Sopenharmony_ci print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n"; 57862306a36Sopenharmony_ci } else { 57962306a36Sopenharmony_ci print ".B \"" . $args{'function'} . "\n"; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci $count = 0; 58262306a36Sopenharmony_ci my $parenth = "("; 58362306a36Sopenharmony_ci my $post = ","; 58462306a36Sopenharmony_ci foreach my $parameter (@{$args{'parameterlist'}}) { 58562306a36Sopenharmony_ci if ($count == $#{$args{'parameterlist'}}) { 58662306a36Sopenharmony_ci $post = ");"; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci $type = $args{'parametertypes'}{$parameter}; 58962306a36Sopenharmony_ci if ($type =~ m/$function_pointer/) { 59062306a36Sopenharmony_ci # pointer-to-function 59162306a36Sopenharmony_ci print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n"; 59262306a36Sopenharmony_ci } else { 59362306a36Sopenharmony_ci $type =~ s/([^\*])$/$1 /; 59462306a36Sopenharmony_ci print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n"; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci $count++; 59762306a36Sopenharmony_ci $parenth = ""; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci print ".SH ARGUMENTS\n"; 60162306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 60262306a36Sopenharmony_ci my $parameter_name = $parameter; 60362306a36Sopenharmony_ci $parameter_name =~ s/\[.*//; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci print ".IP \"" . $parameter . "\" 12\n"; 60662306a36Sopenharmony_ci output_highlight($args{'parameterdescs'}{$parameter_name}); 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 60962306a36Sopenharmony_ci print ".SH \"", uc $section, "\"\n"; 61062306a36Sopenharmony_ci output_highlight($args{'sections'}{$section}); 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci## 61562306a36Sopenharmony_ci# output enum in man 61662306a36Sopenharmony_cisub output_enum_man(%) { 61762306a36Sopenharmony_ci my %args = %{$_[0]}; 61862306a36Sopenharmony_ci my ($parameter, $section); 61962306a36Sopenharmony_ci my $count; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci print ".SH NAME\n"; 62462306a36Sopenharmony_ci print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n"; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci print ".SH SYNOPSIS\n"; 62762306a36Sopenharmony_ci print "enum " . $args{'enum'} . " {\n"; 62862306a36Sopenharmony_ci $count = 0; 62962306a36Sopenharmony_ci foreach my $parameter (@{$args{'parameterlist'}}) { 63062306a36Sopenharmony_ci print ".br\n.BI \" $parameter\"\n"; 63162306a36Sopenharmony_ci if ($count == $#{$args{'parameterlist'}}) { 63262306a36Sopenharmony_ci print "\n};\n"; 63362306a36Sopenharmony_ci last; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci else { 63662306a36Sopenharmony_ci print ", \n.br\n"; 63762306a36Sopenharmony_ci } 63862306a36Sopenharmony_ci $count++; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci print ".SH Constants\n"; 64262306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 64362306a36Sopenharmony_ci my $parameter_name = $parameter; 64462306a36Sopenharmony_ci $parameter_name =~ s/\[.*//; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci print ".IP \"" . $parameter . "\" 12\n"; 64762306a36Sopenharmony_ci output_highlight($args{'parameterdescs'}{$parameter_name}); 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 65062306a36Sopenharmony_ci print ".SH \"$section\"\n"; 65162306a36Sopenharmony_ci output_highlight($args{'sections'}{$section}); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci## 65662306a36Sopenharmony_ci# output struct in man 65762306a36Sopenharmony_cisub output_struct_man(%) { 65862306a36Sopenharmony_ci my %args = %{$_[0]}; 65962306a36Sopenharmony_ci my ($parameter, $section); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n"; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci print ".SH NAME\n"; 66462306a36Sopenharmony_ci print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n"; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci my $declaration = $args{'definition'}; 66762306a36Sopenharmony_ci $declaration =~ s/\t/ /g; 66862306a36Sopenharmony_ci $declaration =~ s/\n/"\n.br\n.BI \"/g; 66962306a36Sopenharmony_ci print ".SH SYNOPSIS\n"; 67062306a36Sopenharmony_ci print $args{'type'} . " " . $args{'struct'} . " {\n.br\n"; 67162306a36Sopenharmony_ci print ".BI \"$declaration\n};\n.br\n\n"; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci print ".SH Members\n"; 67462306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 67562306a36Sopenharmony_ci ($parameter =~ /^#/) && next; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci my $parameter_name = $parameter; 67862306a36Sopenharmony_ci $parameter_name =~ s/\[.*//; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 68162306a36Sopenharmony_ci print ".IP \"" . $parameter . "\" 12\n"; 68262306a36Sopenharmony_ci output_highlight($args{'parameterdescs'}{$parameter_name}); 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 68562306a36Sopenharmony_ci print ".SH \"$section\"\n"; 68662306a36Sopenharmony_ci output_highlight($args{'sections'}{$section}); 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci## 69162306a36Sopenharmony_ci# output typedef in man 69262306a36Sopenharmony_cisub output_typedef_man(%) { 69362306a36Sopenharmony_ci my %args = %{$_[0]}; 69462306a36Sopenharmony_ci my ($parameter, $section); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci print ".SH NAME\n"; 69962306a36Sopenharmony_ci print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n"; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 70262306a36Sopenharmony_ci print ".SH \"$section\"\n"; 70362306a36Sopenharmony_ci output_highlight($args{'sections'}{$section}); 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cisub output_blockhead_man(%) { 70862306a36Sopenharmony_ci my %args = %{$_[0]}; 70962306a36Sopenharmony_ci my ($parameter, $section); 71062306a36Sopenharmony_ci my $count; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 71562306a36Sopenharmony_ci print ".SH \"$section\"\n"; 71662306a36Sopenharmony_ci output_highlight($args{'sections'}{$section}); 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci## 72162306a36Sopenharmony_ci# output in restructured text 72262306a36Sopenharmony_ci# 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci# 72562306a36Sopenharmony_ci# This could use some work; it's used to output the DOC: sections, and 72662306a36Sopenharmony_ci# starts by putting out the name of the doc section itself, but that tends 72762306a36Sopenharmony_ci# to duplicate a header already in the template file. 72862306a36Sopenharmony_ci# 72962306a36Sopenharmony_cisub output_blockhead_rst(%) { 73062306a36Sopenharmony_ci my %args = %{$_[0]}; 73162306a36Sopenharmony_ci my ($parameter, $section); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 73462306a36Sopenharmony_ci next if (defined($nosymbol_table{$section})); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci if ($output_selection != OUTPUT_INCLUDE) { 73762306a36Sopenharmony_ci print ".. _$section:\n\n"; 73862306a36Sopenharmony_ci print "**$section**\n\n"; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci print_lineno($section_start_lines{$section}); 74162306a36Sopenharmony_ci output_highlight_rst($args{'sections'}{$section}); 74262306a36Sopenharmony_ci print "\n"; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci# 74762306a36Sopenharmony_ci# Apply the RST highlights to a sub-block of text. 74862306a36Sopenharmony_ci# 74962306a36Sopenharmony_cisub highlight_block($) { 75062306a36Sopenharmony_ci # The dohighlight kludge requires the text be called $contents 75162306a36Sopenharmony_ci my $contents = shift; 75262306a36Sopenharmony_ci eval $dohighlight; 75362306a36Sopenharmony_ci die $@ if $@; 75462306a36Sopenharmony_ci return $contents; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci# 75862306a36Sopenharmony_ci# Regexes used only here. 75962306a36Sopenharmony_ci# 76062306a36Sopenharmony_cimy $sphinx_literal = '^[^.].*::$'; 76162306a36Sopenharmony_cimy $sphinx_cblock = '^\.\.\ +code-block::'; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_cisub output_highlight_rst { 76462306a36Sopenharmony_ci my $input = join "\n",@_; 76562306a36Sopenharmony_ci my $output = ""; 76662306a36Sopenharmony_ci my $line; 76762306a36Sopenharmony_ci my $in_literal = 0; 76862306a36Sopenharmony_ci my $litprefix; 76962306a36Sopenharmony_ci my $block = ""; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci foreach $line (split "\n",$input) { 77262306a36Sopenharmony_ci # 77362306a36Sopenharmony_ci # If we're in a literal block, see if we should drop out 77462306a36Sopenharmony_ci # of it. Otherwise pass the line straight through unmunged. 77562306a36Sopenharmony_ci # 77662306a36Sopenharmony_ci if ($in_literal) { 77762306a36Sopenharmony_ci if (! ($line =~ /^\s*$/)) { 77862306a36Sopenharmony_ci # 77962306a36Sopenharmony_ci # If this is the first non-blank line in a literal 78062306a36Sopenharmony_ci # block we need to figure out what the proper indent is. 78162306a36Sopenharmony_ci # 78262306a36Sopenharmony_ci if ($litprefix eq "") { 78362306a36Sopenharmony_ci $line =~ /^(\s*)/; 78462306a36Sopenharmony_ci $litprefix = '^' . $1; 78562306a36Sopenharmony_ci $output .= $line . "\n"; 78662306a36Sopenharmony_ci } elsif (! ($line =~ /$litprefix/)) { 78762306a36Sopenharmony_ci $in_literal = 0; 78862306a36Sopenharmony_ci } else { 78962306a36Sopenharmony_ci $output .= $line . "\n"; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci } else { 79262306a36Sopenharmony_ci $output .= $line . "\n"; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci } 79562306a36Sopenharmony_ci # 79662306a36Sopenharmony_ci # Not in a literal block (or just dropped out) 79762306a36Sopenharmony_ci # 79862306a36Sopenharmony_ci if (! $in_literal) { 79962306a36Sopenharmony_ci $block .= $line . "\n"; 80062306a36Sopenharmony_ci if (($line =~ /$sphinx_literal/) || ($line =~ /$sphinx_cblock/)) { 80162306a36Sopenharmony_ci $in_literal = 1; 80262306a36Sopenharmony_ci $litprefix = ""; 80362306a36Sopenharmony_ci $output .= highlight_block($block); 80462306a36Sopenharmony_ci $block = "" 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci if ($block) { 81062306a36Sopenharmony_ci $output .= highlight_block($block); 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci foreach $line (split "\n", $output) { 81362306a36Sopenharmony_ci print $lineprefix . $line . "\n"; 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_cisub output_function_rst(%) { 81862306a36Sopenharmony_ci my %args = %{$_[0]}; 81962306a36Sopenharmony_ci my ($parameter, $section); 82062306a36Sopenharmony_ci my $oldprefix = $lineprefix; 82162306a36Sopenharmony_ci my $start = ""; 82262306a36Sopenharmony_ci my $is_macro = 0; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci if ($sphinx_major < 3) { 82562306a36Sopenharmony_ci if ($args{'typedef'}) { 82662306a36Sopenharmony_ci print ".. c:type:: ". $args{'function'} . "\n\n"; 82762306a36Sopenharmony_ci print_lineno($declaration_start_line); 82862306a36Sopenharmony_ci print " **Typedef**: "; 82962306a36Sopenharmony_ci $lineprefix = ""; 83062306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 83162306a36Sopenharmony_ci $start = "\n\n**Syntax**\n\n ``"; 83262306a36Sopenharmony_ci $is_macro = 1; 83362306a36Sopenharmony_ci } else { 83462306a36Sopenharmony_ci print ".. c:function:: "; 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci } else { 83762306a36Sopenharmony_ci if ($args{'typedef'} || $args{'functiontype'} eq "") { 83862306a36Sopenharmony_ci $is_macro = 1; 83962306a36Sopenharmony_ci print ".. c:macro:: ". $args{'function'} . "\n\n"; 84062306a36Sopenharmony_ci } else { 84162306a36Sopenharmony_ci print ".. c:function:: "; 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci if ($args{'typedef'}) { 84562306a36Sopenharmony_ci print_lineno($declaration_start_line); 84662306a36Sopenharmony_ci print " **Typedef**: "; 84762306a36Sopenharmony_ci $lineprefix = ""; 84862306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 84962306a36Sopenharmony_ci $start = "\n\n**Syntax**\n\n ``"; 85062306a36Sopenharmony_ci } else { 85162306a36Sopenharmony_ci print "``" if ($is_macro); 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci if ($args{'functiontype'} ne "") { 85562306a36Sopenharmony_ci $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; 85662306a36Sopenharmony_ci } else { 85762306a36Sopenharmony_ci $start .= $args{'function'} . " ("; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci print $start; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci my $count = 0; 86262306a36Sopenharmony_ci foreach my $parameter (@{$args{'parameterlist'}}) { 86362306a36Sopenharmony_ci if ($count ne 0) { 86462306a36Sopenharmony_ci print ", "; 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci $count++; 86762306a36Sopenharmony_ci $type = $args{'parametertypes'}{$parameter}; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci if ($type =~ m/$function_pointer/) { 87062306a36Sopenharmony_ci # pointer-to-function 87162306a36Sopenharmony_ci print $1 . $parameter . ") (" . $2 . ")"; 87262306a36Sopenharmony_ci } else { 87362306a36Sopenharmony_ci print $type; 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci if ($is_macro) { 87762306a36Sopenharmony_ci print ")``\n\n"; 87862306a36Sopenharmony_ci } else { 87962306a36Sopenharmony_ci print ")\n\n"; 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci if (!$args{'typedef'}) { 88262306a36Sopenharmony_ci print_lineno($declaration_start_line); 88362306a36Sopenharmony_ci $lineprefix = " "; 88462306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 88562306a36Sopenharmony_ci print "\n"; 88662306a36Sopenharmony_ci } 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci # 88962306a36Sopenharmony_ci # Put our descriptive text into a container (thus an HTML <div>) to help 89062306a36Sopenharmony_ci # set the function prototypes apart. 89162306a36Sopenharmony_ci # 89262306a36Sopenharmony_ci print ".. container:: kernelindent\n\n"; 89362306a36Sopenharmony_ci $lineprefix = " "; 89462306a36Sopenharmony_ci print $lineprefix . "**Parameters**\n\n"; 89562306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 89662306a36Sopenharmony_ci my $parameter_name = $parameter; 89762306a36Sopenharmony_ci $parameter_name =~ s/\[.*//; 89862306a36Sopenharmony_ci $type = $args{'parametertypes'}{$parameter}; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if ($type ne "") { 90162306a36Sopenharmony_ci print $lineprefix . "``$type``\n"; 90262306a36Sopenharmony_ci } else { 90362306a36Sopenharmony_ci print $lineprefix . "``$parameter``\n"; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci print_lineno($parameterdesc_start_lines{$parameter_name}); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci $lineprefix = " "; 90962306a36Sopenharmony_ci if (defined($args{'parameterdescs'}{$parameter_name}) && 91062306a36Sopenharmony_ci $args{'parameterdescs'}{$parameter_name} ne $undescribed) { 91162306a36Sopenharmony_ci output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 91262306a36Sopenharmony_ci } else { 91362306a36Sopenharmony_ci print $lineprefix . "*undescribed*\n"; 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci $lineprefix = " "; 91662306a36Sopenharmony_ci print "\n"; 91762306a36Sopenharmony_ci } 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci output_section_rst(@_); 92062306a36Sopenharmony_ci $lineprefix = $oldprefix; 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_cisub output_section_rst(%) { 92462306a36Sopenharmony_ci my %args = %{$_[0]}; 92562306a36Sopenharmony_ci my $section; 92662306a36Sopenharmony_ci my $oldprefix = $lineprefix; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci foreach $section (@{$args{'sectionlist'}}) { 92962306a36Sopenharmony_ci print $lineprefix . "**$section**\n\n"; 93062306a36Sopenharmony_ci print_lineno($section_start_lines{$section}); 93162306a36Sopenharmony_ci output_highlight_rst($args{'sections'}{$section}); 93262306a36Sopenharmony_ci print "\n"; 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci print "\n"; 93562306a36Sopenharmony_ci} 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_cisub output_enum_rst(%) { 93862306a36Sopenharmony_ci my %args = %{$_[0]}; 93962306a36Sopenharmony_ci my ($parameter); 94062306a36Sopenharmony_ci my $oldprefix = $lineprefix; 94162306a36Sopenharmony_ci my $count; 94262306a36Sopenharmony_ci my $outer; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci if ($sphinx_major < 3) { 94562306a36Sopenharmony_ci my $name = "enum " . $args{'enum'}; 94662306a36Sopenharmony_ci print "\n\n.. c:type:: " . $name . "\n\n"; 94762306a36Sopenharmony_ci } else { 94862306a36Sopenharmony_ci my $name = $args{'enum'}; 94962306a36Sopenharmony_ci print "\n\n.. c:enum:: " . $name . "\n\n"; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci print_lineno($declaration_start_line); 95262306a36Sopenharmony_ci $lineprefix = " "; 95362306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 95462306a36Sopenharmony_ci print "\n"; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci print ".. container:: kernelindent\n\n"; 95762306a36Sopenharmony_ci $outer = $lineprefix . " "; 95862306a36Sopenharmony_ci $lineprefix = $outer . " "; 95962306a36Sopenharmony_ci print $outer . "**Constants**\n\n"; 96062306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 96162306a36Sopenharmony_ci print $outer . "``$parameter``\n"; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci if ($args{'parameterdescs'}{$parameter} ne $undescribed) { 96462306a36Sopenharmony_ci output_highlight_rst($args{'parameterdescs'}{$parameter}); 96562306a36Sopenharmony_ci } else { 96662306a36Sopenharmony_ci print $lineprefix . "*undescribed*\n"; 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci print "\n"; 96962306a36Sopenharmony_ci } 97062306a36Sopenharmony_ci print "\n"; 97162306a36Sopenharmony_ci $lineprefix = $oldprefix; 97262306a36Sopenharmony_ci output_section_rst(@_); 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cisub output_typedef_rst(%) { 97662306a36Sopenharmony_ci my %args = %{$_[0]}; 97762306a36Sopenharmony_ci my ($parameter); 97862306a36Sopenharmony_ci my $oldprefix = $lineprefix; 97962306a36Sopenharmony_ci my $name; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci if ($sphinx_major < 3) { 98262306a36Sopenharmony_ci $name = "typedef " . $args{'typedef'}; 98362306a36Sopenharmony_ci } else { 98462306a36Sopenharmony_ci $name = $args{'typedef'}; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci print "\n\n.. c:type:: " . $name . "\n\n"; 98762306a36Sopenharmony_ci print_lineno($declaration_start_line); 98862306a36Sopenharmony_ci $lineprefix = " "; 98962306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 99062306a36Sopenharmony_ci print "\n"; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci $lineprefix = $oldprefix; 99362306a36Sopenharmony_ci output_section_rst(@_); 99462306a36Sopenharmony_ci} 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cisub output_struct_rst(%) { 99762306a36Sopenharmony_ci my %args = %{$_[0]}; 99862306a36Sopenharmony_ci my ($parameter); 99962306a36Sopenharmony_ci my $oldprefix = $lineprefix; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci if ($sphinx_major < 3) { 100262306a36Sopenharmony_ci my $name = $args{'type'} . " " . $args{'struct'}; 100362306a36Sopenharmony_ci print "\n\n.. c:type:: " . $name . "\n\n"; 100462306a36Sopenharmony_ci } else { 100562306a36Sopenharmony_ci my $name = $args{'struct'}; 100662306a36Sopenharmony_ci if ($args{'type'} eq 'union') { 100762306a36Sopenharmony_ci print "\n\n.. c:union:: " . $name . "\n\n"; 100862306a36Sopenharmony_ci } else { 100962306a36Sopenharmony_ci print "\n\n.. c:struct:: " . $name . "\n\n"; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci } 101262306a36Sopenharmony_ci print_lineno($declaration_start_line); 101362306a36Sopenharmony_ci $lineprefix = " "; 101462306a36Sopenharmony_ci output_highlight_rst($args{'purpose'}); 101562306a36Sopenharmony_ci print "\n"; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci print ".. container:: kernelindent\n\n"; 101862306a36Sopenharmony_ci print $lineprefix . "**Definition**::\n\n"; 101962306a36Sopenharmony_ci my $declaration = $args{'definition'}; 102062306a36Sopenharmony_ci $lineprefix = $lineprefix . " "; 102162306a36Sopenharmony_ci $declaration =~ s/\t/$lineprefix/g; 102262306a36Sopenharmony_ci print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n"; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci $lineprefix = " "; 102562306a36Sopenharmony_ci print $lineprefix . "**Members**\n\n"; 102662306a36Sopenharmony_ci foreach $parameter (@{$args{'parameterlist'}}) { 102762306a36Sopenharmony_ci ($parameter =~ /^#/) && next; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci my $parameter_name = $parameter; 103062306a36Sopenharmony_ci $parameter_name =~ s/\[.*//; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 103362306a36Sopenharmony_ci $type = $args{'parametertypes'}{$parameter}; 103462306a36Sopenharmony_ci print_lineno($parameterdesc_start_lines{$parameter_name}); 103562306a36Sopenharmony_ci print $lineprefix . "``" . $parameter . "``\n"; 103662306a36Sopenharmony_ci $lineprefix = " "; 103762306a36Sopenharmony_ci output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 103862306a36Sopenharmony_ci $lineprefix = " "; 103962306a36Sopenharmony_ci print "\n"; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci print "\n"; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci $lineprefix = $oldprefix; 104462306a36Sopenharmony_ci output_section_rst(@_); 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci## none mode output functions 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_cisub output_function_none(%) { 105062306a36Sopenharmony_ci} 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_cisub output_enum_none(%) { 105362306a36Sopenharmony_ci} 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_cisub output_typedef_none(%) { 105662306a36Sopenharmony_ci} 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_cisub output_struct_none(%) { 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_cisub output_blockhead_none(%) { 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci## 106562306a36Sopenharmony_ci# generic output function for all types (function, struct/union, typedef, enum); 106662306a36Sopenharmony_ci# calls the generated, variable output_ function name based on 106762306a36Sopenharmony_ci# functype and output_mode 106862306a36Sopenharmony_cisub output_declaration { 106962306a36Sopenharmony_ci no strict 'refs'; 107062306a36Sopenharmony_ci my $name = shift; 107162306a36Sopenharmony_ci my $functype = shift; 107262306a36Sopenharmony_ci my $func = "output_${functype}_$output_mode"; 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci return if (defined($nosymbol_table{$name})); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (($output_selection == OUTPUT_ALL) || 107762306a36Sopenharmony_ci (($output_selection == OUTPUT_INCLUDE || 107862306a36Sopenharmony_ci $output_selection == OUTPUT_EXPORTED) && 107962306a36Sopenharmony_ci defined($function_table{$name})) || 108062306a36Sopenharmony_ci ($output_selection == OUTPUT_INTERNAL && 108162306a36Sopenharmony_ci !($functype eq "function" && defined($function_table{$name})))) 108262306a36Sopenharmony_ci { 108362306a36Sopenharmony_ci &$func(@_); 108462306a36Sopenharmony_ci $section_counter++; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci} 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci## 108962306a36Sopenharmony_ci# generic output function - calls the right one based on current output mode. 109062306a36Sopenharmony_cisub output_blockhead { 109162306a36Sopenharmony_ci no strict 'refs'; 109262306a36Sopenharmony_ci my $func = "output_blockhead_" . $output_mode; 109362306a36Sopenharmony_ci &$func(@_); 109462306a36Sopenharmony_ci $section_counter++; 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci## 109862306a36Sopenharmony_ci# takes a declaration (struct, union, enum, typedef) and 109962306a36Sopenharmony_ci# invokes the right handler. NOT called for functions. 110062306a36Sopenharmony_cisub dump_declaration($$) { 110162306a36Sopenharmony_ci no strict 'refs'; 110262306a36Sopenharmony_ci my ($prototype, $file) = @_; 110362306a36Sopenharmony_ci my $func = "dump_" . $decl_type; 110462306a36Sopenharmony_ci &$func(@_); 110562306a36Sopenharmony_ci} 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_cisub dump_union($$) { 110862306a36Sopenharmony_ci dump_struct(@_); 110962306a36Sopenharmony_ci} 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_cisub dump_struct($$) { 111262306a36Sopenharmony_ci my $x = shift; 111362306a36Sopenharmony_ci my $file = shift; 111462306a36Sopenharmony_ci my $decl_type; 111562306a36Sopenharmony_ci my $members; 111662306a36Sopenharmony_ci my $type = qr{struct|union}; 111762306a36Sopenharmony_ci # For capturing struct/union definition body, i.e. "{members*}qualifiers*" 111862306a36Sopenharmony_ci my $qualifiers = qr{$attribute|__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned}; 111962306a36Sopenharmony_ci my $definition_body = qr{\{(.*)\}\s*$qualifiers*}; 112062306a36Sopenharmony_ci my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;}; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci if ($x =~ /($type)\s+(\w+)\s*$definition_body/) { 112362306a36Sopenharmony_ci $decl_type = $1; 112462306a36Sopenharmony_ci $declaration_name = $2; 112562306a36Sopenharmony_ci $members = $3; 112662306a36Sopenharmony_ci } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) { 112762306a36Sopenharmony_ci $decl_type = $1; 112862306a36Sopenharmony_ci $declaration_name = $3; 112962306a36Sopenharmony_ci $members = $2; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci if ($members) { 113362306a36Sopenharmony_ci if ($identifier ne $declaration_name) { 113462306a36Sopenharmony_ci emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n"); 113562306a36Sopenharmony_ci return; 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci # ignore members marked private: 113962306a36Sopenharmony_ci $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; 114062306a36Sopenharmony_ci $members =~ s/\/\*\s*private:.*//gosi; 114162306a36Sopenharmony_ci # strip comments: 114262306a36Sopenharmony_ci $members =~ s/\/\*.*?\*\///gos; 114362306a36Sopenharmony_ci # strip attributes 114462306a36Sopenharmony_ci $members =~ s/\s*$attribute/ /gi; 114562306a36Sopenharmony_ci $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos; 114662306a36Sopenharmony_ci $members =~ s/\s*__packed\s*/ /gos; 114762306a36Sopenharmony_ci $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; 114862306a36Sopenharmony_ci $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; 114962306a36Sopenharmony_ci $members =~ s/\s*____cacheline_aligned/ /gos; 115062306a36Sopenharmony_ci # unwrap struct_group(): 115162306a36Sopenharmony_ci # - first eat non-declaration parameters and rewrite for final match 115262306a36Sopenharmony_ci # - then remove macro, outer parens, and trailing semicolon 115362306a36Sopenharmony_ci $members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos; 115462306a36Sopenharmony_ci $members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos; 115562306a36Sopenharmony_ci $members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos; 115662306a36Sopenharmony_ci $members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci my $args = qr{([^,)]+)}; 115962306a36Sopenharmony_ci # replace DECLARE_BITMAP 116062306a36Sopenharmony_ci $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; 116162306a36Sopenharmony_ci $members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos; 116262306a36Sopenharmony_ci $members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; 116362306a36Sopenharmony_ci # replace DECLARE_HASHTABLE 116462306a36Sopenharmony_ci $members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos; 116562306a36Sopenharmony_ci # replace DECLARE_KFIFO 116662306a36Sopenharmony_ci $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos; 116762306a36Sopenharmony_ci # replace DECLARE_KFIFO_PTR 116862306a36Sopenharmony_ci $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos; 116962306a36Sopenharmony_ci # replace DECLARE_FLEX_ARRAY 117062306a36Sopenharmony_ci $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos; 117162306a36Sopenharmony_ci #replace DEFINE_DMA_UNMAP_ADDR 117262306a36Sopenharmony_ci $members =~ s/DEFINE_DMA_UNMAP_ADDR\s*\($args\)/dma_addr_t $1/gos; 117362306a36Sopenharmony_ci #replace DEFINE_DMA_UNMAP_LEN 117462306a36Sopenharmony_ci $members =~ s/DEFINE_DMA_UNMAP_LEN\s*\($args\)/__u32 $1/gos; 117562306a36Sopenharmony_ci my $declaration = $members; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci # Split nested struct/union elements as newer ones 117862306a36Sopenharmony_ci while ($members =~ m/$struct_members/) { 117962306a36Sopenharmony_ci my $newmember; 118062306a36Sopenharmony_ci my $maintype = $1; 118162306a36Sopenharmony_ci my $ids = $4; 118262306a36Sopenharmony_ci my $content = $3; 118362306a36Sopenharmony_ci foreach my $id(split /,/, $ids) { 118462306a36Sopenharmony_ci $newmember .= "$maintype $id; "; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci $id =~ s/[:\[].*//; 118762306a36Sopenharmony_ci $id =~ s/^\s*\**(\S+)\s*/$1/; 118862306a36Sopenharmony_ci foreach my $arg (split /;/, $content) { 118962306a36Sopenharmony_ci next if ($arg =~ m/^\s*$/); 119062306a36Sopenharmony_ci if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) { 119162306a36Sopenharmony_ci # pointer-to-function 119262306a36Sopenharmony_ci my $type = $1; 119362306a36Sopenharmony_ci my $name = $2; 119462306a36Sopenharmony_ci my $extra = $3; 119562306a36Sopenharmony_ci next if (!$name); 119662306a36Sopenharmony_ci if ($id =~ m/^\s*$/) { 119762306a36Sopenharmony_ci # anonymous struct/union 119862306a36Sopenharmony_ci $newmember .= "$type$name$extra; "; 119962306a36Sopenharmony_ci } else { 120062306a36Sopenharmony_ci $newmember .= "$type$id.$name$extra; "; 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci } else { 120362306a36Sopenharmony_ci my $type; 120462306a36Sopenharmony_ci my $names; 120562306a36Sopenharmony_ci $arg =~ s/^\s+//; 120662306a36Sopenharmony_ci $arg =~ s/\s+$//; 120762306a36Sopenharmony_ci # Handle bitmaps 120862306a36Sopenharmony_ci $arg =~ s/:\s*\d+\s*//g; 120962306a36Sopenharmony_ci # Handle arrays 121062306a36Sopenharmony_ci $arg =~ s/\[.*\]//g; 121162306a36Sopenharmony_ci # The type may have multiple words, 121262306a36Sopenharmony_ci # and multiple IDs can be defined, like: 121362306a36Sopenharmony_ci # const struct foo, *bar, foobar 121462306a36Sopenharmony_ci # So, we remove spaces when parsing the 121562306a36Sopenharmony_ci # names, in order to match just names 121662306a36Sopenharmony_ci # and commas for the names 121762306a36Sopenharmony_ci $arg =~ s/\s*,\s*/,/g; 121862306a36Sopenharmony_ci if ($arg =~ m/(.*)\s+([\S+,]+)/) { 121962306a36Sopenharmony_ci $type = $1; 122062306a36Sopenharmony_ci $names = $2; 122162306a36Sopenharmony_ci } else { 122262306a36Sopenharmony_ci $newmember .= "$arg; "; 122362306a36Sopenharmony_ci next; 122462306a36Sopenharmony_ci } 122562306a36Sopenharmony_ci foreach my $name (split /,/, $names) { 122662306a36Sopenharmony_ci $name =~ s/^\s*\**(\S+)\s*/$1/; 122762306a36Sopenharmony_ci next if (($name =~ m/^\s*$/)); 122862306a36Sopenharmony_ci if ($id =~ m/^\s*$/) { 122962306a36Sopenharmony_ci # anonymous struct/union 123062306a36Sopenharmony_ci $newmember .= "$type $name; "; 123162306a36Sopenharmony_ci } else { 123262306a36Sopenharmony_ci $newmember .= "$type $id.$name; "; 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci } 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci $members =~ s/$struct_members/$newmember/; 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci # Ignore other nested elements, like enums 124262306a36Sopenharmony_ci $members =~ s/(\{[^\{\}]*\})//g; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci create_parameterlist($members, ';', $file, $declaration_name); 124562306a36Sopenharmony_ci check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci # Adjust declaration for better display 124862306a36Sopenharmony_ci $declaration =~ s/([\{;])/$1\n/g; 124962306a36Sopenharmony_ci $declaration =~ s/\}\s+;/};/g; 125062306a36Sopenharmony_ci # Better handle inlined enums 125162306a36Sopenharmony_ci do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci my @def_args = split /\n/, $declaration; 125462306a36Sopenharmony_ci my $level = 1; 125562306a36Sopenharmony_ci $declaration = ""; 125662306a36Sopenharmony_ci foreach my $clause (@def_args) { 125762306a36Sopenharmony_ci $clause =~ s/^\s+//; 125862306a36Sopenharmony_ci $clause =~ s/\s+$//; 125962306a36Sopenharmony_ci $clause =~ s/\s+/ /; 126062306a36Sopenharmony_ci next if (!$clause); 126162306a36Sopenharmony_ci $level-- if ($clause =~ m/(\})/ && $level > 1); 126262306a36Sopenharmony_ci if (!($clause =~ m/^\s*#/)) { 126362306a36Sopenharmony_ci $declaration .= "\t" x $level; 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci $declaration .= "\t" . $clause . "\n"; 126662306a36Sopenharmony_ci $level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/)); 126762306a36Sopenharmony_ci } 126862306a36Sopenharmony_ci output_declaration($declaration_name, 126962306a36Sopenharmony_ci 'struct', 127062306a36Sopenharmony_ci {'struct' => $declaration_name, 127162306a36Sopenharmony_ci 'module' => $modulename, 127262306a36Sopenharmony_ci 'definition' => $declaration, 127362306a36Sopenharmony_ci 'parameterlist' => \@parameterlist, 127462306a36Sopenharmony_ci 'parameterdescs' => \%parameterdescs, 127562306a36Sopenharmony_ci 'parametertypes' => \%parametertypes, 127662306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 127762306a36Sopenharmony_ci 'sections' => \%sections, 127862306a36Sopenharmony_ci 'purpose' => $declaration_purpose, 127962306a36Sopenharmony_ci 'type' => $decl_type 128062306a36Sopenharmony_ci }); 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci else { 128362306a36Sopenharmony_ci print STDERR "${file}:$.: error: Cannot parse struct or union!\n"; 128462306a36Sopenharmony_ci ++$errors; 128562306a36Sopenharmony_ci } 128662306a36Sopenharmony_ci} 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_cisub show_warnings($$) { 129062306a36Sopenharmony_ci my $functype = shift; 129162306a36Sopenharmony_ci my $name = shift; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci return 0 if (defined($nosymbol_table{$name})); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci return 1 if ($output_selection == OUTPUT_ALL); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci if ($output_selection == OUTPUT_EXPORTED) { 129862306a36Sopenharmony_ci if (defined($function_table{$name})) { 129962306a36Sopenharmony_ci return 1; 130062306a36Sopenharmony_ci } else { 130162306a36Sopenharmony_ci return 0; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci if ($output_selection == OUTPUT_INTERNAL) { 130562306a36Sopenharmony_ci if (!($functype eq "function" && defined($function_table{$name}))) { 130662306a36Sopenharmony_ci return 1; 130762306a36Sopenharmony_ci } else { 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci if ($output_selection == OUTPUT_INCLUDE) { 131262306a36Sopenharmony_ci if (defined($function_table{$name})) { 131362306a36Sopenharmony_ci return 1; 131462306a36Sopenharmony_ci } else { 131562306a36Sopenharmony_ci return 0; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci die("Please add the new output type at show_warnings()"); 131962306a36Sopenharmony_ci} 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cisub dump_enum($$) { 132262306a36Sopenharmony_ci my $x = shift; 132362306a36Sopenharmony_ci my $file = shift; 132462306a36Sopenharmony_ci my $members; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci # ignore members marked private: 132762306a36Sopenharmony_ci $x =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi; 132862306a36Sopenharmony_ci $x =~ s/\/\*\s*private:.*}/}/gosi; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci $x =~ s@/\*.*?\*/@@gos; # strip comments. 133162306a36Sopenharmony_ci # strip #define macros inside enums 133262306a36Sopenharmony_ci $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) { 133562306a36Sopenharmony_ci $declaration_name = $2; 133662306a36Sopenharmony_ci $members = $1; 133762306a36Sopenharmony_ci } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { 133862306a36Sopenharmony_ci $declaration_name = $1; 133962306a36Sopenharmony_ci $members = $2; 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci if ($members) { 134362306a36Sopenharmony_ci if ($identifier ne $declaration_name) { 134462306a36Sopenharmony_ci if ($identifier eq "") { 134562306a36Sopenharmony_ci emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n"); 134662306a36Sopenharmony_ci } else { 134762306a36Sopenharmony_ci emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n"); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci return; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci $declaration_name = "(anonymous)" if ($declaration_name eq ""); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci my %_members; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci $members =~ s/\s+$//; 135662306a36Sopenharmony_ci $members =~ s/\([^;]*?[\)]//g; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci foreach my $arg (split ',', $members) { 135962306a36Sopenharmony_ci $arg =~ s/^\s*(\w+).*/$1/; 136062306a36Sopenharmony_ci push @parameterlist, $arg; 136162306a36Sopenharmony_ci if (!$parameterdescs{$arg}) { 136262306a36Sopenharmony_ci $parameterdescs{$arg} = $undescribed; 136362306a36Sopenharmony_ci if (show_warnings("enum", $declaration_name)) { 136462306a36Sopenharmony_ci emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n"); 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci $_members{$arg} = 1; 136862306a36Sopenharmony_ci } 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci while (my ($k, $v) = each %parameterdescs) { 137162306a36Sopenharmony_ci if (!exists($_members{$k})) { 137262306a36Sopenharmony_ci if (show_warnings("enum", $declaration_name)) { 137362306a36Sopenharmony_ci emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n"); 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci output_declaration($declaration_name, 137962306a36Sopenharmony_ci 'enum', 138062306a36Sopenharmony_ci {'enum' => $declaration_name, 138162306a36Sopenharmony_ci 'module' => $modulename, 138262306a36Sopenharmony_ci 'parameterlist' => \@parameterlist, 138362306a36Sopenharmony_ci 'parameterdescs' => \%parameterdescs, 138462306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 138562306a36Sopenharmony_ci 'sections' => \%sections, 138662306a36Sopenharmony_ci 'purpose' => $declaration_purpose 138762306a36Sopenharmony_ci }); 138862306a36Sopenharmony_ci } else { 138962306a36Sopenharmony_ci print STDERR "${file}:$.: error: Cannot parse enum!\n"; 139062306a36Sopenharmony_ci ++$errors; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci} 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_cimy $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x; 139562306a36Sopenharmony_cimy $typedef_ident = qr { \*?\s*(\w\S+)\s* }x; 139662306a36Sopenharmony_cimy $typedef_args = qr { \s*\((.*)\); }x; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_cimy $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x; 139962306a36Sopenharmony_cimy $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cisub dump_typedef($$) { 140262306a36Sopenharmony_ci my $x = shift; 140362306a36Sopenharmony_ci my $file = shift; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci $x =~ s@/\*.*?\*/@@gos; # strip comments. 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci # Parse function typedef prototypes 140862306a36Sopenharmony_ci if ($x =~ $typedef1 || $x =~ $typedef2) { 140962306a36Sopenharmony_ci $return_type = $1; 141062306a36Sopenharmony_ci $declaration_name = $2; 141162306a36Sopenharmony_ci my $args = $3; 141262306a36Sopenharmony_ci $return_type =~ s/^\s+//; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci if ($identifier ne $declaration_name) { 141562306a36Sopenharmony_ci emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"); 141662306a36Sopenharmony_ci return; 141762306a36Sopenharmony_ci } 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci create_parameterlist($args, ',', $file, $declaration_name); 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci output_declaration($declaration_name, 142262306a36Sopenharmony_ci 'function', 142362306a36Sopenharmony_ci {'function' => $declaration_name, 142462306a36Sopenharmony_ci 'typedef' => 1, 142562306a36Sopenharmony_ci 'module' => $modulename, 142662306a36Sopenharmony_ci 'functiontype' => $return_type, 142762306a36Sopenharmony_ci 'parameterlist' => \@parameterlist, 142862306a36Sopenharmony_ci 'parameterdescs' => \%parameterdescs, 142962306a36Sopenharmony_ci 'parametertypes' => \%parametertypes, 143062306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 143162306a36Sopenharmony_ci 'sections' => \%sections, 143262306a36Sopenharmony_ci 'purpose' => $declaration_purpose 143362306a36Sopenharmony_ci }); 143462306a36Sopenharmony_ci return; 143562306a36Sopenharmony_ci } 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 143862306a36Sopenharmony_ci $x =~ s/\(*.\)\s*;$/;/; 143962306a36Sopenharmony_ci $x =~ s/\[*.\]\s*;$/;/; 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci if ($x =~ /typedef.*\s+(\w+)\s*;/) { 144362306a36Sopenharmony_ci $declaration_name = $1; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci if ($identifier ne $declaration_name) { 144662306a36Sopenharmony_ci emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"); 144762306a36Sopenharmony_ci return; 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci output_declaration($declaration_name, 145162306a36Sopenharmony_ci 'typedef', 145262306a36Sopenharmony_ci {'typedef' => $declaration_name, 145362306a36Sopenharmony_ci 'module' => $modulename, 145462306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 145562306a36Sopenharmony_ci 'sections' => \%sections, 145662306a36Sopenharmony_ci 'purpose' => $declaration_purpose 145762306a36Sopenharmony_ci }); 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci else { 146062306a36Sopenharmony_ci print STDERR "${file}:$.: error: Cannot parse typedef!\n"; 146162306a36Sopenharmony_ci ++$errors; 146262306a36Sopenharmony_ci } 146362306a36Sopenharmony_ci} 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_cisub save_struct_actual($) { 146662306a36Sopenharmony_ci my $actual = shift; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci # strip all spaces from the actual param so that it looks like one string item 146962306a36Sopenharmony_ci $actual =~ s/\s*//g; 147062306a36Sopenharmony_ci $struct_actual = $struct_actual . $actual . " "; 147162306a36Sopenharmony_ci} 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_cisub create_parameterlist($$$$) { 147462306a36Sopenharmony_ci my $args = shift; 147562306a36Sopenharmony_ci my $splitter = shift; 147662306a36Sopenharmony_ci my $file = shift; 147762306a36Sopenharmony_ci my $declaration_name = shift; 147862306a36Sopenharmony_ci my $type; 147962306a36Sopenharmony_ci my $param; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci # temporarily replace commas inside function pointer definition 148262306a36Sopenharmony_ci my $arg_expr = qr{\([^\),]+}; 148362306a36Sopenharmony_ci while ($args =~ /$arg_expr,/) { 148462306a36Sopenharmony_ci $args =~ s/($arg_expr),/$1#/g; 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci foreach my $arg (split($splitter, $args)) { 148862306a36Sopenharmony_ci # strip comments 148962306a36Sopenharmony_ci $arg =~ s/\/\*.*\*\///; 149062306a36Sopenharmony_ci # ignore argument attributes 149162306a36Sopenharmony_ci $arg =~ s/\sPOS0?\s/ /; 149262306a36Sopenharmony_ci # strip leading/trailing spaces 149362306a36Sopenharmony_ci $arg =~ s/^\s*//; 149462306a36Sopenharmony_ci $arg =~ s/\s*$//; 149562306a36Sopenharmony_ci $arg =~ s/\s+/ /; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if ($arg =~ /^#/) { 149862306a36Sopenharmony_ci # Treat preprocessor directive as a typeless variable just to fill 149962306a36Sopenharmony_ci # corresponding data structures "correctly". Catch it later in 150062306a36Sopenharmony_ci # output_* subs. 150162306a36Sopenharmony_ci push_parameter($arg, "", "", $file); 150262306a36Sopenharmony_ci } elsif ($arg =~ m/\(.+\)\s*\(/) { 150362306a36Sopenharmony_ci # pointer-to-function 150462306a36Sopenharmony_ci $arg =~ tr/#/,/; 150562306a36Sopenharmony_ci $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/; 150662306a36Sopenharmony_ci $param = $1; 150762306a36Sopenharmony_ci $type = $arg; 150862306a36Sopenharmony_ci $type =~ s/([^\(]+\(\*?)\s*$param/$1/; 150962306a36Sopenharmony_ci save_struct_actual($param); 151062306a36Sopenharmony_ci push_parameter($param, $type, $arg, $file, $declaration_name); 151162306a36Sopenharmony_ci } elsif ($arg) { 151262306a36Sopenharmony_ci $arg =~ s/\s*:\s*/:/g; 151362306a36Sopenharmony_ci $arg =~ s/\s*\[/\[/g; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci my @args = split('\s*,\s*', $arg); 151662306a36Sopenharmony_ci if ($args[0] =~ m/\*/) { 151762306a36Sopenharmony_ci $args[0] =~ s/(\*+)\s*/ $1/; 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci my @first_arg; 152162306a36Sopenharmony_ci if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) { 152262306a36Sopenharmony_ci shift @args; 152362306a36Sopenharmony_ci push(@first_arg, split('\s+', $1)); 152462306a36Sopenharmony_ci push(@first_arg, $2); 152562306a36Sopenharmony_ci } else { 152662306a36Sopenharmony_ci @first_arg = split('\s+', shift @args); 152762306a36Sopenharmony_ci } 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci unshift(@args, pop @first_arg); 153062306a36Sopenharmony_ci $type = join " ", @first_arg; 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci foreach $param (@args) { 153362306a36Sopenharmony_ci if ($param =~ m/^(\*+)\s*(.*)/) { 153462306a36Sopenharmony_ci save_struct_actual($2); 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci push_parameter($2, "$type $1", $arg, $file, $declaration_name); 153762306a36Sopenharmony_ci } 153862306a36Sopenharmony_ci elsif ($param =~ m/(.*?):(\d+)/) { 153962306a36Sopenharmony_ci if ($type ne "") { # skip unnamed bit-fields 154062306a36Sopenharmony_ci save_struct_actual($1); 154162306a36Sopenharmony_ci push_parameter($1, "$type:$2", $arg, $file, $declaration_name) 154262306a36Sopenharmony_ci } 154362306a36Sopenharmony_ci } 154462306a36Sopenharmony_ci else { 154562306a36Sopenharmony_ci save_struct_actual($param); 154662306a36Sopenharmony_ci push_parameter($param, $type, $arg, $file, $declaration_name); 154762306a36Sopenharmony_ci } 154862306a36Sopenharmony_ci } 154962306a36Sopenharmony_ci } 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci} 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_cisub push_parameter($$$$$) { 155462306a36Sopenharmony_ci my $param = shift; 155562306a36Sopenharmony_ci my $type = shift; 155662306a36Sopenharmony_ci my $org_arg = shift; 155762306a36Sopenharmony_ci my $file = shift; 155862306a36Sopenharmony_ci my $declaration_name = shift; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci if (($anon_struct_union == 1) && ($type eq "") && 156162306a36Sopenharmony_ci ($param eq "}")) { 156262306a36Sopenharmony_ci return; # ignore the ending }; from anon. struct/union 156362306a36Sopenharmony_ci } 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci $anon_struct_union = 0; 156662306a36Sopenharmony_ci $param =~ s/[\[\)].*//; 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci if ($type eq "" && $param =~ /\.\.\.$/) 156962306a36Sopenharmony_ci { 157062306a36Sopenharmony_ci if (!$param =~ /\w\.\.\.$/) { 157162306a36Sopenharmony_ci # handles unnamed variable parameters 157262306a36Sopenharmony_ci $param = "..."; 157362306a36Sopenharmony_ci } 157462306a36Sopenharmony_ci elsif ($param =~ /\w\.\.\.$/) { 157562306a36Sopenharmony_ci # for named variable parameters of the form `x...`, remove the dots 157662306a36Sopenharmony_ci $param =~ s/\.\.\.$//; 157762306a36Sopenharmony_ci } 157862306a36Sopenharmony_ci if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { 157962306a36Sopenharmony_ci $parameterdescs{$param} = "variable arguments"; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci elsif ($type eq "" && ($param eq "" or $param eq "void")) 158362306a36Sopenharmony_ci { 158462306a36Sopenharmony_ci $param="void"; 158562306a36Sopenharmony_ci $parameterdescs{void} = "no arguments"; 158662306a36Sopenharmony_ci } 158762306a36Sopenharmony_ci elsif ($type eq "" && ($param eq "struct" or $param eq "union")) 158862306a36Sopenharmony_ci # handle unnamed (anonymous) union or struct: 158962306a36Sopenharmony_ci { 159062306a36Sopenharmony_ci $type = $param; 159162306a36Sopenharmony_ci $param = "{unnamed_" . $param . "}"; 159262306a36Sopenharmony_ci $parameterdescs{$param} = "anonymous\n"; 159362306a36Sopenharmony_ci $anon_struct_union = 1; 159462306a36Sopenharmony_ci } 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci # warn if parameter has no description 159762306a36Sopenharmony_ci # (but ignore ones starting with # as these are not parameters 159862306a36Sopenharmony_ci # but inline preprocessor statements); 159962306a36Sopenharmony_ci # Note: It will also ignore void params and unnamed structs/unions 160062306a36Sopenharmony_ci if (!defined $parameterdescs{$param} && $param !~ /^#/) { 160162306a36Sopenharmony_ci $parameterdescs{$param} = $undescribed; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (show_warnings($type, $declaration_name) && $param !~ /\./) { 160462306a36Sopenharmony_ci emit_warning("${file}:$.", "Function parameter or member '$param' not described in '$declaration_name'\n"); 160562306a36Sopenharmony_ci } 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci # strip spaces from $param so that it is one continuous string 160962306a36Sopenharmony_ci # on @parameterlist; 161062306a36Sopenharmony_ci # this fixes a problem where check_sections() cannot find 161162306a36Sopenharmony_ci # a parameter like "addr[6 + 2]" because it actually appears 161262306a36Sopenharmony_ci # as "addr[6", "+", "2]" on the parameter list; 161362306a36Sopenharmony_ci # but it's better to maintain the param string unchanged for output, 161462306a36Sopenharmony_ci # so just weaken the string compare in check_sections() to ignore 161562306a36Sopenharmony_ci # "[blah" in a parameter string; 161662306a36Sopenharmony_ci ###$param =~ s/\s*//g; 161762306a36Sopenharmony_ci push @parameterlist, $param; 161862306a36Sopenharmony_ci $org_arg =~ s/\s\s+/ /g; 161962306a36Sopenharmony_ci $parametertypes{$param} = $org_arg; 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_cisub check_sections($$$$$) { 162362306a36Sopenharmony_ci my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_; 162462306a36Sopenharmony_ci my @sects = split ' ', $sectcheck; 162562306a36Sopenharmony_ci my @prms = split ' ', $prmscheck; 162662306a36Sopenharmony_ci my $err; 162762306a36Sopenharmony_ci my ($px, $sx); 162862306a36Sopenharmony_ci my $prm_clean; # strip trailing "[array size]" and/or beginning "*" 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci foreach $sx (0 .. $#sects) { 163162306a36Sopenharmony_ci $err = 1; 163262306a36Sopenharmony_ci foreach $px (0 .. $#prms) { 163362306a36Sopenharmony_ci $prm_clean = $prms[$px]; 163462306a36Sopenharmony_ci $prm_clean =~ s/\[.*\]//; 163562306a36Sopenharmony_ci $prm_clean =~ s/$attribute//i; 163662306a36Sopenharmony_ci # ignore array size in a parameter string; 163762306a36Sopenharmony_ci # however, the original param string may contain 163862306a36Sopenharmony_ci # spaces, e.g.: addr[6 + 2] 163962306a36Sopenharmony_ci # and this appears in @prms as "addr[6" since the 164062306a36Sopenharmony_ci # parameter list is split at spaces; 164162306a36Sopenharmony_ci # hence just ignore "[..." for the sections check; 164262306a36Sopenharmony_ci $prm_clean =~ s/\[.*//; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci ##$prm_clean =~ s/^\**//; 164562306a36Sopenharmony_ci if ($prm_clean eq $sects[$sx]) { 164662306a36Sopenharmony_ci $err = 0; 164762306a36Sopenharmony_ci last; 164862306a36Sopenharmony_ci } 164962306a36Sopenharmony_ci } 165062306a36Sopenharmony_ci if ($err) { 165162306a36Sopenharmony_ci if ($decl_type eq "function") { 165262306a36Sopenharmony_ci emit_warning("${file}:$.", 165362306a36Sopenharmony_ci "Excess function parameter " . 165462306a36Sopenharmony_ci "'$sects[$sx]' " . 165562306a36Sopenharmony_ci "description in '$decl_name'\n"); 165662306a36Sopenharmony_ci } 165762306a36Sopenharmony_ci } 165862306a36Sopenharmony_ci } 165962306a36Sopenharmony_ci} 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci## 166262306a36Sopenharmony_ci# Checks the section describing the return value of a function. 166362306a36Sopenharmony_cisub check_return_section { 166462306a36Sopenharmony_ci my $file = shift; 166562306a36Sopenharmony_ci my $declaration_name = shift; 166662306a36Sopenharmony_ci my $return_type = shift; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci # Ignore an empty return type (It's a macro) 166962306a36Sopenharmony_ci # Ignore functions with a "void" return type. (But don't ignore "void *") 167062306a36Sopenharmony_ci if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) { 167162306a36Sopenharmony_ci return; 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci if (!defined($sections{$section_return}) || 167562306a36Sopenharmony_ci $sections{$section_return} eq "") { 167662306a36Sopenharmony_ci emit_warning("${file}:$.", 167762306a36Sopenharmony_ci "No description found for return value of " . 167862306a36Sopenharmony_ci "'$declaration_name'\n"); 167962306a36Sopenharmony_ci } 168062306a36Sopenharmony_ci} 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci## 168362306a36Sopenharmony_ci# takes a function prototype and the name of the current file being 168462306a36Sopenharmony_ci# processed and spits out all the details stored in the global 168562306a36Sopenharmony_ci# arrays/hashes. 168662306a36Sopenharmony_cisub dump_function($$) { 168762306a36Sopenharmony_ci my $prototype = shift; 168862306a36Sopenharmony_ci my $file = shift; 168962306a36Sopenharmony_ci my $noret = 0; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci print_lineno($new_start_line); 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci $prototype =~ s/^static +//; 169462306a36Sopenharmony_ci $prototype =~ s/^extern +//; 169562306a36Sopenharmony_ci $prototype =~ s/^asmlinkage +//; 169662306a36Sopenharmony_ci $prototype =~ s/^inline +//; 169762306a36Sopenharmony_ci $prototype =~ s/^__inline__ +//; 169862306a36Sopenharmony_ci $prototype =~ s/^__inline +//; 169962306a36Sopenharmony_ci $prototype =~ s/^__always_inline +//; 170062306a36Sopenharmony_ci $prototype =~ s/^noinline +//; 170162306a36Sopenharmony_ci $prototype =~ s/^__FORTIFY_INLINE +//; 170262306a36Sopenharmony_ci $prototype =~ s/__init +//; 170362306a36Sopenharmony_ci $prototype =~ s/__init_or_module +//; 170462306a36Sopenharmony_ci $prototype =~ s/__deprecated +//; 170562306a36Sopenharmony_ci $prototype =~ s/__flatten +//; 170662306a36Sopenharmony_ci $prototype =~ s/__meminit +//; 170762306a36Sopenharmony_ci $prototype =~ s/__must_check +//; 170862306a36Sopenharmony_ci $prototype =~ s/__weak +//; 170962306a36Sopenharmony_ci $prototype =~ s/__sched +//; 171062306a36Sopenharmony_ci $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//; 171162306a36Sopenharmony_ci $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//; 171262306a36Sopenharmony_ci $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//; 171362306a36Sopenharmony_ci my $define = $prototype =~ s/^#\s*define\s+//; #ak added 171462306a36Sopenharmony_ci $prototype =~ s/__attribute_const__ +//; 171562306a36Sopenharmony_ci $prototype =~ s/__attribute__\s*\(\( 171662306a36Sopenharmony_ci (?: 171762306a36Sopenharmony_ci [\w\s]++ # attribute name 171862306a36Sopenharmony_ci (?:\([^)]*+\))? # attribute arguments 171962306a36Sopenharmony_ci \s*+,? # optional comma at the end 172062306a36Sopenharmony_ci )+ 172162306a36Sopenharmony_ci \)\)\s+//x; 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci # Yes, this truly is vile. We are looking for: 172462306a36Sopenharmony_ci # 1. Return type (may be nothing if we're looking at a macro) 172562306a36Sopenharmony_ci # 2. Function name 172662306a36Sopenharmony_ci # 3. Function parameters. 172762306a36Sopenharmony_ci # 172862306a36Sopenharmony_ci # All the while we have to watch out for function pointer parameters 172962306a36Sopenharmony_ci # (which IIRC is what the two sections are for), C types (these 173062306a36Sopenharmony_ci # regexps don't even start to express all the possibilities), and 173162306a36Sopenharmony_ci # so on. 173262306a36Sopenharmony_ci # 173362306a36Sopenharmony_ci # If you mess with these regexps, it's a good idea to check that 173462306a36Sopenharmony_ci # the following functions' documentation still comes out right: 173562306a36Sopenharmony_ci # - parport_register_device (function pointer parameters) 173662306a36Sopenharmony_ci # - atomic_set (macro) 173762306a36Sopenharmony_ci # - pci_match_device, __copy_to_user (long return type) 173862306a36Sopenharmony_ci my $name = qr{[a-zA-Z0-9_~:]+}; 173962306a36Sopenharmony_ci my $prototype_end1 = qr{[^\(]*}; 174062306a36Sopenharmony_ci my $prototype_end2 = qr{[^\{]*}; 174162306a36Sopenharmony_ci my $prototype_end = qr{\(($prototype_end1|$prototype_end2)\)}; 174262306a36Sopenharmony_ci my $type1 = qr{[\w\s]+}; 174362306a36Sopenharmony_ci my $type2 = qr{$type1\*+}; 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci if ($define && $prototype =~ m/^()($name)\s+/) { 174662306a36Sopenharmony_ci # This is an object-like macro, it has no return type and no parameter 174762306a36Sopenharmony_ci # list. 174862306a36Sopenharmony_ci # Function-like macros are not allowed to have spaces between 174962306a36Sopenharmony_ci # declaration_name and opening parenthesis (notice the \s+). 175062306a36Sopenharmony_ci $return_type = $1; 175162306a36Sopenharmony_ci $declaration_name = $2; 175262306a36Sopenharmony_ci $noret = 1; 175362306a36Sopenharmony_ci } elsif ($prototype =~ m/^()($name)\s*$prototype_end/ || 175462306a36Sopenharmony_ci $prototype =~ m/^($type1)\s+($name)\s*$prototype_end/ || 175562306a36Sopenharmony_ci $prototype =~ m/^($type2+)\s*($name)\s*$prototype_end/) { 175662306a36Sopenharmony_ci $return_type = $1; 175762306a36Sopenharmony_ci $declaration_name = $2; 175862306a36Sopenharmony_ci my $args = $3; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci create_parameterlist($args, ',', $file, $declaration_name); 176162306a36Sopenharmony_ci } else { 176262306a36Sopenharmony_ci emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n"); 176362306a36Sopenharmony_ci return; 176462306a36Sopenharmony_ci } 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if ($identifier ne $declaration_name) { 176762306a36Sopenharmony_ci emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n"); 176862306a36Sopenharmony_ci return; 176962306a36Sopenharmony_ci } 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci my $prms = join " ", @parameterlist; 177262306a36Sopenharmony_ci check_sections($file, $declaration_name, "function", $sectcheck, $prms); 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci # This check emits a lot of warnings at the moment, because many 177562306a36Sopenharmony_ci # functions don't have a 'Return' doc section. So until the number 177662306a36Sopenharmony_ci # of warnings goes sufficiently down, the check is only performed in 177762306a36Sopenharmony_ci # -Wreturn mode. 177862306a36Sopenharmony_ci # TODO: always perform the check. 177962306a36Sopenharmony_ci if ($Wreturn && !$noret) { 178062306a36Sopenharmony_ci check_return_section($file, $declaration_name, $return_type); 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci # The function parser can be called with a typedef parameter. 178462306a36Sopenharmony_ci # Handle it. 178562306a36Sopenharmony_ci if ($return_type =~ /typedef/) { 178662306a36Sopenharmony_ci output_declaration($declaration_name, 178762306a36Sopenharmony_ci 'function', 178862306a36Sopenharmony_ci {'function' => $declaration_name, 178962306a36Sopenharmony_ci 'typedef' => 1, 179062306a36Sopenharmony_ci 'module' => $modulename, 179162306a36Sopenharmony_ci 'functiontype' => $return_type, 179262306a36Sopenharmony_ci 'parameterlist' => \@parameterlist, 179362306a36Sopenharmony_ci 'parameterdescs' => \%parameterdescs, 179462306a36Sopenharmony_ci 'parametertypes' => \%parametertypes, 179562306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 179662306a36Sopenharmony_ci 'sections' => \%sections, 179762306a36Sopenharmony_ci 'purpose' => $declaration_purpose 179862306a36Sopenharmony_ci }); 179962306a36Sopenharmony_ci } else { 180062306a36Sopenharmony_ci output_declaration($declaration_name, 180162306a36Sopenharmony_ci 'function', 180262306a36Sopenharmony_ci {'function' => $declaration_name, 180362306a36Sopenharmony_ci 'module' => $modulename, 180462306a36Sopenharmony_ci 'functiontype' => $return_type, 180562306a36Sopenharmony_ci 'parameterlist' => \@parameterlist, 180662306a36Sopenharmony_ci 'parameterdescs' => \%parameterdescs, 180762306a36Sopenharmony_ci 'parametertypes' => \%parametertypes, 180862306a36Sopenharmony_ci 'sectionlist' => \@sectionlist, 180962306a36Sopenharmony_ci 'sections' => \%sections, 181062306a36Sopenharmony_ci 'purpose' => $declaration_purpose 181162306a36Sopenharmony_ci }); 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci} 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_cisub reset_state { 181662306a36Sopenharmony_ci $function = ""; 181762306a36Sopenharmony_ci %parameterdescs = (); 181862306a36Sopenharmony_ci %parametertypes = (); 181962306a36Sopenharmony_ci @parameterlist = (); 182062306a36Sopenharmony_ci %sections = (); 182162306a36Sopenharmony_ci @sectionlist = (); 182262306a36Sopenharmony_ci $sectcheck = ""; 182362306a36Sopenharmony_ci $struct_actual = ""; 182462306a36Sopenharmony_ci $prototype = ""; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci $state = STATE_NORMAL; 182762306a36Sopenharmony_ci $inline_doc_state = STATE_INLINE_NA; 182862306a36Sopenharmony_ci} 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_cisub tracepoint_munge($) { 183162306a36Sopenharmony_ci my $file = shift; 183262306a36Sopenharmony_ci my $tracepointname = 0; 183362306a36Sopenharmony_ci my $tracepointargs = 0; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci if ($prototype =~ m/TRACE_EVENT\((.*?),/) { 183662306a36Sopenharmony_ci $tracepointname = $1; 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) { 183962306a36Sopenharmony_ci $tracepointname = $1; 184062306a36Sopenharmony_ci } 184162306a36Sopenharmony_ci if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) { 184262306a36Sopenharmony_ci $tracepointname = $2; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci $tracepointname =~ s/^\s+//; #strip leading whitespace 184562306a36Sopenharmony_ci if ($prototype =~ m/TP_PROTO\((.*?)\)/) { 184662306a36Sopenharmony_ci $tracepointargs = $1; 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 184962306a36Sopenharmony_ci emit_warning("${file}:$.", "Unrecognized tracepoint format: \n". 185062306a36Sopenharmony_ci "$prototype\n"); 185162306a36Sopenharmony_ci } else { 185262306a36Sopenharmony_ci $prototype = "static inline void trace_$tracepointname($tracepointargs)"; 185362306a36Sopenharmony_ci $identifier = "trace_$identifier"; 185462306a36Sopenharmony_ci } 185562306a36Sopenharmony_ci} 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_cisub syscall_munge() { 185862306a36Sopenharmony_ci my $void = 0; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's 186162306a36Sopenharmony_ci## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) { 186262306a36Sopenharmony_ci if ($prototype =~ m/SYSCALL_DEFINE0/) { 186362306a36Sopenharmony_ci $void = 1; 186462306a36Sopenharmony_ci## $prototype = "long sys_$1(void)"; 186562306a36Sopenharmony_ci } 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name 186862306a36Sopenharmony_ci if ($prototype =~ m/long (sys_.*?),/) { 186962306a36Sopenharmony_ci $prototype =~ s/,/\(/; 187062306a36Sopenharmony_ci } elsif ($void) { 187162306a36Sopenharmony_ci $prototype =~ s/\)/\(void\)/; 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci # now delete all of the odd-number commas in $prototype 187562306a36Sopenharmony_ci # so that arg types & arg names don't have a comma between them 187662306a36Sopenharmony_ci my $count = 0; 187762306a36Sopenharmony_ci my $len = length($prototype); 187862306a36Sopenharmony_ci if ($void) { 187962306a36Sopenharmony_ci $len = 0; # skip the for-loop 188062306a36Sopenharmony_ci } 188162306a36Sopenharmony_ci for (my $ix = 0; $ix < $len; $ix++) { 188262306a36Sopenharmony_ci if (substr($prototype, $ix, 1) eq ',') { 188362306a36Sopenharmony_ci $count++; 188462306a36Sopenharmony_ci if ($count % 2 == 1) { 188562306a36Sopenharmony_ci substr($prototype, $ix, 1) = ' '; 188662306a36Sopenharmony_ci } 188762306a36Sopenharmony_ci } 188862306a36Sopenharmony_ci } 188962306a36Sopenharmony_ci} 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_cisub process_proto_function($$) { 189262306a36Sopenharmony_ci my $x = shift; 189362306a36Sopenharmony_ci my $file = shift; 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) { 189862306a36Sopenharmony_ci # do nothing 189962306a36Sopenharmony_ci } 190062306a36Sopenharmony_ci elsif ($x =~ /([^\{]*)/) { 190162306a36Sopenharmony_ci $prototype .= $1; 190262306a36Sopenharmony_ci } 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) { 190562306a36Sopenharmony_ci $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 190662306a36Sopenharmony_ci $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 190762306a36Sopenharmony_ci $prototype =~ s@^\s+@@gos; # strip leading spaces 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci # Handle prototypes for function pointers like: 191062306a36Sopenharmony_ci # int (*pcs_config)(struct foo) 191162306a36Sopenharmony_ci $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos; 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci if ($prototype =~ /SYSCALL_DEFINE/) { 191462306a36Sopenharmony_ci syscall_munge(); 191562306a36Sopenharmony_ci } 191662306a36Sopenharmony_ci if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ || 191762306a36Sopenharmony_ci $prototype =~ /DEFINE_SINGLE_EVENT/) 191862306a36Sopenharmony_ci { 191962306a36Sopenharmony_ci tracepoint_munge($file); 192062306a36Sopenharmony_ci } 192162306a36Sopenharmony_ci dump_function($prototype, $file); 192262306a36Sopenharmony_ci reset_state(); 192362306a36Sopenharmony_ci } 192462306a36Sopenharmony_ci} 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_cisub process_proto_type($$) { 192762306a36Sopenharmony_ci my $x = shift; 192862306a36Sopenharmony_ci my $file = shift; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 193162306a36Sopenharmony_ci $x =~ s@^\s+@@gos; # strip leading spaces 193262306a36Sopenharmony_ci $x =~ s@\s+$@@gos; # strip trailing spaces 193362306a36Sopenharmony_ci $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci if ($x =~ /^#/) { 193662306a36Sopenharmony_ci # To distinguish preprocessor directive from regular declaration later. 193762306a36Sopenharmony_ci $x .= ";"; 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci while (1) { 194162306a36Sopenharmony_ci if ( $x =~ /([^\{\};]*)([\{\};])(.*)/ ) { 194262306a36Sopenharmony_ci if( length $prototype ) { 194362306a36Sopenharmony_ci $prototype .= " " 194462306a36Sopenharmony_ci } 194562306a36Sopenharmony_ci $prototype .= $1 . $2; 194662306a36Sopenharmony_ci ($2 eq '{') && $brcount++; 194762306a36Sopenharmony_ci ($2 eq '}') && $brcount--; 194862306a36Sopenharmony_ci if (($2 eq ';') && ($brcount == 0)) { 194962306a36Sopenharmony_ci dump_declaration($prototype, $file); 195062306a36Sopenharmony_ci reset_state(); 195162306a36Sopenharmony_ci last; 195262306a36Sopenharmony_ci } 195362306a36Sopenharmony_ci $x = $3; 195462306a36Sopenharmony_ci } else { 195562306a36Sopenharmony_ci $prototype .= $x; 195662306a36Sopenharmony_ci last; 195762306a36Sopenharmony_ci } 195862306a36Sopenharmony_ci } 195962306a36Sopenharmony_ci} 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_cisub map_filename($) { 196362306a36Sopenharmony_ci my $file; 196462306a36Sopenharmony_ci my ($orig_file) = @_; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci if (defined($ENV{'SRCTREE'})) { 196762306a36Sopenharmony_ci $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; 196862306a36Sopenharmony_ci } else { 196962306a36Sopenharmony_ci $file = $orig_file; 197062306a36Sopenharmony_ci } 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci if (defined($source_map{$file})) { 197362306a36Sopenharmony_ci $file = $source_map{$file}; 197462306a36Sopenharmony_ci } 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci return $file; 197762306a36Sopenharmony_ci} 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_cisub process_export_file($) { 198062306a36Sopenharmony_ci my ($orig_file) = @_; 198162306a36Sopenharmony_ci my $file = map_filename($orig_file); 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci if (!open(IN,"<$file")) { 198462306a36Sopenharmony_ci print STDERR "Error: Cannot open file $file\n"; 198562306a36Sopenharmony_ci ++$errors; 198662306a36Sopenharmony_ci return; 198762306a36Sopenharmony_ci } 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci while (<IN>) { 199062306a36Sopenharmony_ci if (/$export_symbol/) { 199162306a36Sopenharmony_ci next if (defined($nosymbol_table{$2})); 199262306a36Sopenharmony_ci $function_table{$2} = 1; 199362306a36Sopenharmony_ci } 199462306a36Sopenharmony_ci if (/$export_symbol_ns/) { 199562306a36Sopenharmony_ci next if (defined($nosymbol_table{$2})); 199662306a36Sopenharmony_ci $function_table{$2} = 1; 199762306a36Sopenharmony_ci } 199862306a36Sopenharmony_ci } 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci close(IN); 200162306a36Sopenharmony_ci} 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci# 200462306a36Sopenharmony_ci# Parsers for the various processing states. 200562306a36Sopenharmony_ci# 200662306a36Sopenharmony_ci# STATE_NORMAL: looking for the /** to begin everything. 200762306a36Sopenharmony_ci# 200862306a36Sopenharmony_cisub process_normal() { 200962306a36Sopenharmony_ci if (/$doc_start/o) { 201062306a36Sopenharmony_ci $state = STATE_NAME; # next line is always the function name 201162306a36Sopenharmony_ci $in_doc_sect = 0; 201262306a36Sopenharmony_ci $declaration_start_line = $. + 1; 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci} 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci# 201762306a36Sopenharmony_ci# STATE_NAME: Looking for the "name - description" line 201862306a36Sopenharmony_ci# 201962306a36Sopenharmony_cisub process_name($$) { 202062306a36Sopenharmony_ci my $file = shift; 202162306a36Sopenharmony_ci my $descr; 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci if (/$doc_block/o) { 202462306a36Sopenharmony_ci $state = STATE_DOCBLOCK; 202562306a36Sopenharmony_ci $contents = ""; 202662306a36Sopenharmony_ci $new_start_line = $.; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci if ( $1 eq "" ) { 202962306a36Sopenharmony_ci $section = $section_intro; 203062306a36Sopenharmony_ci } else { 203162306a36Sopenharmony_ci $section = $1; 203262306a36Sopenharmony_ci } 203362306a36Sopenharmony_ci } elsif (/$doc_decl/o) { 203462306a36Sopenharmony_ci $identifier = $1; 203562306a36Sopenharmony_ci my $is_kernel_comment = 0; 203662306a36Sopenharmony_ci my $decl_start = qr{$doc_com}; 203762306a36Sopenharmony_ci # test for pointer declaration type, foo * bar() - desc 203862306a36Sopenharmony_ci my $fn_type = qr{\w+\s*\*\s*}; 203962306a36Sopenharmony_ci my $parenthesis = qr{\(\w*\)}; 204062306a36Sopenharmony_ci my $decl_end = qr{[-:].*}; 204162306a36Sopenharmony_ci if (/^$decl_start([\w\s]+?)$parenthesis?\s*$decl_end?$/) { 204262306a36Sopenharmony_ci $identifier = $1; 204362306a36Sopenharmony_ci } 204462306a36Sopenharmony_ci if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) { 204562306a36Sopenharmony_ci $decl_type = $1; 204662306a36Sopenharmony_ci $identifier = $2; 204762306a36Sopenharmony_ci $is_kernel_comment = 1; 204862306a36Sopenharmony_ci } 204962306a36Sopenharmony_ci # Look for foo() or static void foo() - description; or misspelt 205062306a36Sopenharmony_ci # identifier 205162306a36Sopenharmony_ci elsif (/^$decl_start$fn_type?(\w+)\s*$parenthesis?\s*$decl_end?$/ || 205262306a36Sopenharmony_ci /^$decl_start$fn_type?(\w+.*)$parenthesis?\s*$decl_end$/) { 205362306a36Sopenharmony_ci $identifier = $1; 205462306a36Sopenharmony_ci $decl_type = 'function'; 205562306a36Sopenharmony_ci $identifier =~ s/^define\s+//; 205662306a36Sopenharmony_ci $is_kernel_comment = 1; 205762306a36Sopenharmony_ci } 205862306a36Sopenharmony_ci $identifier =~ s/\s+$//; 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci $state = STATE_BODY; 206162306a36Sopenharmony_ci # if there's no @param blocks need to set up default section 206262306a36Sopenharmony_ci # here 206362306a36Sopenharmony_ci $contents = ""; 206462306a36Sopenharmony_ci $section = $section_default; 206562306a36Sopenharmony_ci $new_start_line = $. + 1; 206662306a36Sopenharmony_ci if (/[-:](.*)/) { 206762306a36Sopenharmony_ci # strip leading/trailing/multiple spaces 206862306a36Sopenharmony_ci $descr= $1; 206962306a36Sopenharmony_ci $descr =~ s/^\s*//; 207062306a36Sopenharmony_ci $descr =~ s/\s*$//; 207162306a36Sopenharmony_ci $descr =~ s/\s+/ /g; 207262306a36Sopenharmony_ci $declaration_purpose = $descr; 207362306a36Sopenharmony_ci $state = STATE_BODY_MAYBE; 207462306a36Sopenharmony_ci } else { 207562306a36Sopenharmony_ci $declaration_purpose = ""; 207662306a36Sopenharmony_ci } 207762306a36Sopenharmony_ci 207862306a36Sopenharmony_ci if (!$is_kernel_comment) { 207962306a36Sopenharmony_ci emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_"); 208062306a36Sopenharmony_ci $state = STATE_NORMAL; 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci if (($declaration_purpose eq "") && $Wshort_desc) { 208462306a36Sopenharmony_ci emit_warning("${file}:$.", "missing initial short description on line:\n$_"); 208562306a36Sopenharmony_ci } 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci if ($identifier eq "" && $decl_type ne "enum") { 208862306a36Sopenharmony_ci emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_"); 208962306a36Sopenharmony_ci $state = STATE_NORMAL; 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci if ($verbose) { 209362306a36Sopenharmony_ci print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n"; 209462306a36Sopenharmony_ci } 209562306a36Sopenharmony_ci } else { 209662306a36Sopenharmony_ci emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n"); 209762306a36Sopenharmony_ci $state = STATE_NORMAL; 209862306a36Sopenharmony_ci } 209962306a36Sopenharmony_ci} 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci# 210362306a36Sopenharmony_ci# STATE_BODY and STATE_BODY_MAYBE: the bulk of a kerneldoc comment. 210462306a36Sopenharmony_ci# 210562306a36Sopenharmony_cisub process_body($$) { 210662306a36Sopenharmony_ci my $file = shift; 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { 210962306a36Sopenharmony_ci dump_section($file, $section, $contents); 211062306a36Sopenharmony_ci $section = $section_default; 211162306a36Sopenharmony_ci $new_start_line = $.; 211262306a36Sopenharmony_ci $contents = ""; 211362306a36Sopenharmony_ci } 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci if (/$doc_sect/i) { # case insensitive for supported section names 211662306a36Sopenharmony_ci $newsection = $1; 211762306a36Sopenharmony_ci $newcontents = $2; 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci # map the supported section names to the canonical names 212062306a36Sopenharmony_ci if ($newsection =~ m/^description$/i) { 212162306a36Sopenharmony_ci $newsection = $section_default; 212262306a36Sopenharmony_ci } elsif ($newsection =~ m/^context$/i) { 212362306a36Sopenharmony_ci $newsection = $section_context; 212462306a36Sopenharmony_ci } elsif ($newsection =~ m/^returns?$/i) { 212562306a36Sopenharmony_ci $newsection = $section_return; 212662306a36Sopenharmony_ci } elsif ($newsection =~ m/^\@return$/) { 212762306a36Sopenharmony_ci # special: @return is a section, not a param description 212862306a36Sopenharmony_ci $newsection = $section_return; 212962306a36Sopenharmony_ci } 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci if (($contents ne "") && ($contents ne "\n")) { 213262306a36Sopenharmony_ci if (!$in_doc_sect && $Wcontents_before_sections) { 213362306a36Sopenharmony_ci emit_warning("${file}:$.", "contents before sections\n"); 213462306a36Sopenharmony_ci } 213562306a36Sopenharmony_ci dump_section($file, $section, $contents); 213662306a36Sopenharmony_ci $section = $section_default; 213762306a36Sopenharmony_ci } 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci $in_doc_sect = 1; 214062306a36Sopenharmony_ci $state = STATE_BODY; 214162306a36Sopenharmony_ci $contents = $newcontents; 214262306a36Sopenharmony_ci $new_start_line = $.; 214362306a36Sopenharmony_ci while (substr($contents, 0, 1) eq " ") { 214462306a36Sopenharmony_ci $contents = substr($contents, 1); 214562306a36Sopenharmony_ci } 214662306a36Sopenharmony_ci if ($contents ne "") { 214762306a36Sopenharmony_ci $contents .= "\n"; 214862306a36Sopenharmony_ci } 214962306a36Sopenharmony_ci $section = $newsection; 215062306a36Sopenharmony_ci $leading_space = undef; 215162306a36Sopenharmony_ci } elsif (/$doc_end/) { 215262306a36Sopenharmony_ci if (($contents ne "") && ($contents ne "\n")) { 215362306a36Sopenharmony_ci dump_section($file, $section, $contents); 215462306a36Sopenharmony_ci $section = $section_default; 215562306a36Sopenharmony_ci $contents = ""; 215662306a36Sopenharmony_ci } 215762306a36Sopenharmony_ci # look for doc_com + <text> + doc_end: 215862306a36Sopenharmony_ci if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { 215962306a36Sopenharmony_ci emit_warning("${file}:$.", "suspicious ending line: $_"); 216062306a36Sopenharmony_ci } 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_ci $prototype = ""; 216362306a36Sopenharmony_ci $state = STATE_PROTO; 216462306a36Sopenharmony_ci $brcount = 0; 216562306a36Sopenharmony_ci $new_start_line = $. + 1; 216662306a36Sopenharmony_ci } elsif (/$doc_content/) { 216762306a36Sopenharmony_ci if ($1 eq "") { 216862306a36Sopenharmony_ci if ($section eq $section_context) { 216962306a36Sopenharmony_ci dump_section($file, $section, $contents); 217062306a36Sopenharmony_ci $section = $section_default; 217162306a36Sopenharmony_ci $contents = ""; 217262306a36Sopenharmony_ci $new_start_line = $.; 217362306a36Sopenharmony_ci $state = STATE_BODY; 217462306a36Sopenharmony_ci } else { 217562306a36Sopenharmony_ci if ($section ne $section_default) { 217662306a36Sopenharmony_ci $state = STATE_BODY_WITH_BLANK_LINE; 217762306a36Sopenharmony_ci } else { 217862306a36Sopenharmony_ci $state = STATE_BODY; 217962306a36Sopenharmony_ci } 218062306a36Sopenharmony_ci $contents .= "\n"; 218162306a36Sopenharmony_ci } 218262306a36Sopenharmony_ci } elsif ($state == STATE_BODY_MAYBE) { 218362306a36Sopenharmony_ci # Continued declaration purpose 218462306a36Sopenharmony_ci chomp($declaration_purpose); 218562306a36Sopenharmony_ci $declaration_purpose .= " " . $1; 218662306a36Sopenharmony_ci $declaration_purpose =~ s/\s+/ /g; 218762306a36Sopenharmony_ci } else { 218862306a36Sopenharmony_ci my $cont = $1; 218962306a36Sopenharmony_ci if ($section =~ m/^@/ || $section eq $section_context) { 219062306a36Sopenharmony_ci if (!defined $leading_space) { 219162306a36Sopenharmony_ci if ($cont =~ m/^(\s+)/) { 219262306a36Sopenharmony_ci $leading_space = $1; 219362306a36Sopenharmony_ci } else { 219462306a36Sopenharmony_ci $leading_space = ""; 219562306a36Sopenharmony_ci } 219662306a36Sopenharmony_ci } 219762306a36Sopenharmony_ci $cont =~ s/^$leading_space//; 219862306a36Sopenharmony_ci } 219962306a36Sopenharmony_ci $contents .= $cont . "\n"; 220062306a36Sopenharmony_ci } 220162306a36Sopenharmony_ci } else { 220262306a36Sopenharmony_ci # i dont know - bad line? ignore. 220362306a36Sopenharmony_ci emit_warning("${file}:$.", "bad line: $_"); 220462306a36Sopenharmony_ci } 220562306a36Sopenharmony_ci} 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci 220862306a36Sopenharmony_ci# 220962306a36Sopenharmony_ci# STATE_PROTO: reading a function/whatever prototype. 221062306a36Sopenharmony_ci# 221162306a36Sopenharmony_cisub process_proto($$) { 221262306a36Sopenharmony_ci my $file = shift; 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci if (/$doc_inline_oneline/) { 221562306a36Sopenharmony_ci $section = $1; 221662306a36Sopenharmony_ci $contents = $2; 221762306a36Sopenharmony_ci if ($contents ne "") { 221862306a36Sopenharmony_ci $contents .= "\n"; 221962306a36Sopenharmony_ci dump_section($file, $section, $contents); 222062306a36Sopenharmony_ci $section = $section_default; 222162306a36Sopenharmony_ci $contents = ""; 222262306a36Sopenharmony_ci } 222362306a36Sopenharmony_ci } elsif (/$doc_inline_start/) { 222462306a36Sopenharmony_ci $state = STATE_INLINE; 222562306a36Sopenharmony_ci $inline_doc_state = STATE_INLINE_NAME; 222662306a36Sopenharmony_ci } elsif ($decl_type eq 'function') { 222762306a36Sopenharmony_ci process_proto_function($_, $file); 222862306a36Sopenharmony_ci } else { 222962306a36Sopenharmony_ci process_proto_type($_, $file); 223062306a36Sopenharmony_ci } 223162306a36Sopenharmony_ci} 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci# 223462306a36Sopenharmony_ci# STATE_DOCBLOCK: within a DOC: block. 223562306a36Sopenharmony_ci# 223662306a36Sopenharmony_cisub process_docblock($$) { 223762306a36Sopenharmony_ci my $file = shift; 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci if (/$doc_end/) { 224062306a36Sopenharmony_ci dump_doc_section($file, $section, $contents); 224162306a36Sopenharmony_ci $section = $section_default; 224262306a36Sopenharmony_ci $contents = ""; 224362306a36Sopenharmony_ci $function = ""; 224462306a36Sopenharmony_ci %parameterdescs = (); 224562306a36Sopenharmony_ci %parametertypes = (); 224662306a36Sopenharmony_ci @parameterlist = (); 224762306a36Sopenharmony_ci %sections = (); 224862306a36Sopenharmony_ci @sectionlist = (); 224962306a36Sopenharmony_ci $prototype = ""; 225062306a36Sopenharmony_ci $state = STATE_NORMAL; 225162306a36Sopenharmony_ci } elsif (/$doc_content/) { 225262306a36Sopenharmony_ci if ( $1 eq "" ) { 225362306a36Sopenharmony_ci $contents .= $blankline; 225462306a36Sopenharmony_ci } else { 225562306a36Sopenharmony_ci $contents .= $1 . "\n"; 225662306a36Sopenharmony_ci } 225762306a36Sopenharmony_ci } 225862306a36Sopenharmony_ci} 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci# 226162306a36Sopenharmony_ci# STATE_INLINE: docbook comments within a prototype. 226262306a36Sopenharmony_ci# 226362306a36Sopenharmony_cisub process_inline($$) { 226462306a36Sopenharmony_ci my $file = shift; 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci # First line (state 1) needs to be a @parameter 226762306a36Sopenharmony_ci if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { 226862306a36Sopenharmony_ci $section = $1; 226962306a36Sopenharmony_ci $contents = $2; 227062306a36Sopenharmony_ci $new_start_line = $.; 227162306a36Sopenharmony_ci if ($contents ne "") { 227262306a36Sopenharmony_ci while (substr($contents, 0, 1) eq " ") { 227362306a36Sopenharmony_ci $contents = substr($contents, 1); 227462306a36Sopenharmony_ci } 227562306a36Sopenharmony_ci $contents .= "\n"; 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci $inline_doc_state = STATE_INLINE_TEXT; 227862306a36Sopenharmony_ci # Documentation block end */ 227962306a36Sopenharmony_ci } elsif (/$doc_inline_end/) { 228062306a36Sopenharmony_ci if (($contents ne "") && ($contents ne "\n")) { 228162306a36Sopenharmony_ci dump_section($file, $section, $contents); 228262306a36Sopenharmony_ci $section = $section_default; 228362306a36Sopenharmony_ci $contents = ""; 228462306a36Sopenharmony_ci } 228562306a36Sopenharmony_ci $state = STATE_PROTO; 228662306a36Sopenharmony_ci $inline_doc_state = STATE_INLINE_NA; 228762306a36Sopenharmony_ci # Regular text 228862306a36Sopenharmony_ci } elsif (/$doc_content/) { 228962306a36Sopenharmony_ci if ($inline_doc_state == STATE_INLINE_TEXT) { 229062306a36Sopenharmony_ci $contents .= $1 . "\n"; 229162306a36Sopenharmony_ci # nuke leading blank lines 229262306a36Sopenharmony_ci if ($contents =~ /^\s*$/) { 229362306a36Sopenharmony_ci $contents = ""; 229462306a36Sopenharmony_ci } 229562306a36Sopenharmony_ci } elsif ($inline_doc_state == STATE_INLINE_NAME) { 229662306a36Sopenharmony_ci $inline_doc_state = STATE_INLINE_ERROR; 229762306a36Sopenharmony_ci emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_"); 229862306a36Sopenharmony_ci } 229962306a36Sopenharmony_ci } 230062306a36Sopenharmony_ci} 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_cisub process_file($) { 230462306a36Sopenharmony_ci my $file; 230562306a36Sopenharmony_ci my $initial_section_counter = $section_counter; 230662306a36Sopenharmony_ci my ($orig_file) = @_; 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci $file = map_filename($orig_file); 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci if (!open(IN_FILE,"<$file")) { 231162306a36Sopenharmony_ci print STDERR "Error: Cannot open file $file\n"; 231262306a36Sopenharmony_ci ++$errors; 231362306a36Sopenharmony_ci return; 231462306a36Sopenharmony_ci } 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci $. = 1; 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci $section_counter = 0; 231962306a36Sopenharmony_ci while (<IN_FILE>) { 232062306a36Sopenharmony_ci while (s/\\\s*$//) { 232162306a36Sopenharmony_ci $_ .= <IN_FILE>; 232262306a36Sopenharmony_ci } 232362306a36Sopenharmony_ci # Replace tabs by spaces 232462306a36Sopenharmony_ci while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; 232562306a36Sopenharmony_ci # Hand this line to the appropriate state handler 232662306a36Sopenharmony_ci if ($state == STATE_NORMAL) { 232762306a36Sopenharmony_ci process_normal(); 232862306a36Sopenharmony_ci } elsif ($state == STATE_NAME) { 232962306a36Sopenharmony_ci process_name($file, $_); 233062306a36Sopenharmony_ci } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE || 233162306a36Sopenharmony_ci $state == STATE_BODY_WITH_BLANK_LINE) { 233262306a36Sopenharmony_ci process_body($file, $_); 233362306a36Sopenharmony_ci } elsif ($state == STATE_INLINE) { # scanning for inline parameters 233462306a36Sopenharmony_ci process_inline($file, $_); 233562306a36Sopenharmony_ci } elsif ($state == STATE_PROTO) { 233662306a36Sopenharmony_ci process_proto($file, $_); 233762306a36Sopenharmony_ci } elsif ($state == STATE_DOCBLOCK) { 233862306a36Sopenharmony_ci process_docblock($file, $_); 233962306a36Sopenharmony_ci } 234062306a36Sopenharmony_ci } 234162306a36Sopenharmony_ci 234262306a36Sopenharmony_ci # Make sure we got something interesting. 234362306a36Sopenharmony_ci if ($initial_section_counter == $section_counter && $ 234462306a36Sopenharmony_ci output_mode ne "none") { 234562306a36Sopenharmony_ci if ($output_selection == OUTPUT_INCLUDE) { 234662306a36Sopenharmony_ci emit_warning("${file}:1", "'$_' not found\n") 234762306a36Sopenharmony_ci for keys %function_table; 234862306a36Sopenharmony_ci } 234962306a36Sopenharmony_ci else { 235062306a36Sopenharmony_ci emit_warning("${file}:1", "no structured comments found\n"); 235162306a36Sopenharmony_ci } 235262306a36Sopenharmony_ci } 235362306a36Sopenharmony_ci close IN_FILE; 235462306a36Sopenharmony_ci} 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_ciif ($output_mode eq "rst") { 235862306a36Sopenharmony_ci get_sphinx_version() if (!$sphinx_major); 235962306a36Sopenharmony_ci} 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci$kernelversion = get_kernel_version(); 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci# generate a sequence of code that will splice in highlighting information 236462306a36Sopenharmony_ci# using the s// operator. 236562306a36Sopenharmony_cifor (my $k = 0; $k < @highlights; $k++) { 236662306a36Sopenharmony_ci my $pattern = $highlights[$k][0]; 236762306a36Sopenharmony_ci my $result = $highlights[$k][1]; 236862306a36Sopenharmony_ci# print STDERR "scanning pattern:$pattern, highlight:($result)\n"; 236962306a36Sopenharmony_ci $dohighlight .= "\$contents =~ s:$pattern:$result:gs;\n"; 237062306a36Sopenharmony_ci} 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci# Read the file that maps relative names to absolute names for 237362306a36Sopenharmony_ci# separate source and object directories and for shadow trees. 237462306a36Sopenharmony_ciif (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 237562306a36Sopenharmony_ci my ($relname, $absname); 237662306a36Sopenharmony_ci while(<SOURCE_MAP>) { 237762306a36Sopenharmony_ci chop(); 237862306a36Sopenharmony_ci ($relname, $absname) = (split())[0..1]; 237962306a36Sopenharmony_ci $relname =~ s:^/+::; 238062306a36Sopenharmony_ci $source_map{$relname} = $absname; 238162306a36Sopenharmony_ci } 238262306a36Sopenharmony_ci close(SOURCE_MAP); 238362306a36Sopenharmony_ci} 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ciif ($output_selection == OUTPUT_EXPORTED || 238662306a36Sopenharmony_ci $output_selection == OUTPUT_INTERNAL) { 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci push(@export_file_list, @ARGV); 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci foreach (@export_file_list) { 239162306a36Sopenharmony_ci chomp; 239262306a36Sopenharmony_ci process_export_file($_); 239362306a36Sopenharmony_ci } 239462306a36Sopenharmony_ci} 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ciforeach (@ARGV) { 239762306a36Sopenharmony_ci chomp; 239862306a36Sopenharmony_ci process_file($_); 239962306a36Sopenharmony_ci} 240062306a36Sopenharmony_ciif ($verbose && $errors) { 240162306a36Sopenharmony_ci print STDERR "$errors errors\n"; 240262306a36Sopenharmony_ci} 240362306a36Sopenharmony_ciif ($verbose && $warnings) { 240462306a36Sopenharmony_ci print STDERR "$warnings warnings\n"; 240562306a36Sopenharmony_ci} 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ciif ($Werror && $warnings) { 240862306a36Sopenharmony_ci print STDERR "$warnings warnings as Errors\n"; 240962306a36Sopenharmony_ci exit($warnings); 241062306a36Sopenharmony_ci} else { 241162306a36Sopenharmony_ci exit($output_mode eq "none" ? 0 : $errors) 241262306a36Sopenharmony_ci} 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci__END__ 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci=head1 OPTIONS 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci=head2 Output format selection (mutually exclusive): 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci=over 8 242162306a36Sopenharmony_ci 242262306a36Sopenharmony_ci=item -man 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_ciOutput troff manual page format. 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci=item -rst 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ciOutput reStructuredText format. This is the default. 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci=item -none 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ciDo not output documentation, only warnings. 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci=back 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci=head2 Output format modifiers 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci=head3 reStructuredText only 243962306a36Sopenharmony_ci 244062306a36Sopenharmony_ci=over 8 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci=item -sphinx-version VERSION 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ciUse the ReST C domain dialect compatible with a specific Sphinx Version. 244562306a36Sopenharmony_ci 244662306a36Sopenharmony_ciIf not specified, kernel-doc will auto-detect using the sphinx-build version 244762306a36Sopenharmony_cifound on PATH. 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci=back 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci=head2 Output selection (mutually exclusive): 245262306a36Sopenharmony_ci 245362306a36Sopenharmony_ci=over 8 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci=item -export 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ciOnly output documentation for the symbols that have been exported using 245862306a36Sopenharmony_ciEXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE. 245962306a36Sopenharmony_ci 246062306a36Sopenharmony_ci=item -internal 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ciOnly output documentation for the symbols that have NOT been exported using 246362306a36Sopenharmony_ciEXPORT_SYMBOL() and related macros in any input FILE or -export-file FILE. 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci=item -function NAME 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ciOnly output documentation for the given function or DOC: section title. 246862306a36Sopenharmony_ciAll other functions and DOC: sections are ignored. 246962306a36Sopenharmony_ci 247062306a36Sopenharmony_ciMay be specified multiple times. 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci=item -nosymbol NAME 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_ciExclude the specified symbol from the output documentation. 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ciMay be specified multiple times. 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_ci=back 247962306a36Sopenharmony_ci 248062306a36Sopenharmony_ci=head2 Output selection modifiers: 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_ci=over 8 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci=item -no-doc-sections 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_ciDo not output DOC: sections. 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci=item -export-file FILE 248962306a36Sopenharmony_ci 249062306a36Sopenharmony_ciSpecify an additional FILE in which to look for EXPORT_SYMBOL information. 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ciTo be used with -export or -internal. 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ciMay be specified multiple times. 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci=back 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci=head3 reStructuredText only 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci=over 8 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci=item -enable-lineno 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ciEnable output of .. LINENO lines. 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci=back 250762306a36Sopenharmony_ci 250862306a36Sopenharmony_ci=head2 Other parameters: 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci=over 8 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci=item -h, -help 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ciPrint this help. 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci=item -v 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ciVerbose output, more warnings and other information. 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci=item -Werror 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ciTreat warnings as errors. 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci=back 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci=cut 2527