2503 lines · 65.9 KB · Text
RawDownload
	output_highlight_rst($args{'parameterdescs'}{$parameter_name});	print "\n";    }    print "\n";     $lineprefix = $oldprefix;    output_section_rst(@_);} ## none mode output functions sub output_function_none(%) {} sub output_enum_none(%) {} sub output_typedef_none(%) {} sub output_struct_none(%) {} sub output_blockhead_none(%) {} ### generic output function for all types (function, struct/union, typedef, enum);# calls the generated, variable output_ function name based on# functype and output_modesub output_declaration {    no strict 'refs';    my $name = shift;    my $functype = shift;    my $func = "output_${functype}_$output_mode";     return if (defined($nosymbol_table{$name}));     if (($output_selection == OUTPUT_ALL) ||	(($output_selection == OUTPUT_INCLUDE ||	  $output_selection == OUTPUT_EXPORTED) &&	 defined($function_table{$name})) ||	($output_selection == OUTPUT_INTERNAL &&	 !($functype eq "function" && defined($function_table{$name}))))    {	&$func(@_);	$section_counter++;    }} ### generic output function - calls the right one based on current output mode.sub output_blockhead {    no strict 'refs';    my $func = "output_blockhead_" . $output_mode;    &$func(@_);    $section_counter++;} ### takes a declaration (struct, union, enum, typedef) and# invokes the right handler. NOT called for functions.sub dump_declaration($$) {    no strict 'refs';    my ($prototype, $file) = @_;    my $func = "dump_" . $decl_type;    &$func(@_);} sub dump_union($$) {    dump_struct(@_);} sub dump_struct($$) {    my $x = shift;    my $file = shift;    my $decl_type;    my $members;    my $type = qr{struct|union};    # For capturing struct/union definition body, i.e. "{members*}qualifiers*"    my $qualifiers = qr{$attribute|__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned};    my $definition_body = qr{\{(.*)\}\s*$qualifiers*};    my $struct_members = qr{($type)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;};     if ($x =~ /($type)\s+(\w+)\s*$definition_body/) {	$decl_type = $1;	$declaration_name = $2;	$members = $3;    } elsif ($x =~ /typedef\s+($type)\s*$definition_body\s*(\w+)\s*;/) {	$decl_type = $1;	$declaration_name = $3;	$members = $2;    }     if ($members) {	if ($identifier ne $declaration_name) {	    print STDERR "${file}:$.: warning: expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n";	    return;	} 	# ignore members marked private:	$members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;	$members =~ s/\/\*\s*private:.*//gosi;	# strip comments:	$members =~ s/\/\*.*?\*\///gos;	# strip attributes	$members =~ s/\s*$attribute/ /gi;	$members =~ s/\s*__aligned\s*\([^;]*\)/ /gos;	$members =~ s/\s*__packed\s*/ /gos;	$members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;	$members =~ s/\s*____cacheline_aligned_in_smp/ /gos;	$members =~ s/\s*____cacheline_aligned/ /gos;	# unwrap struct_group():	# - first eat non-declaration parameters and rewrite for final match	# - then remove macro, outer parens, and trailing semicolon	$members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;	$members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;	$members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;	$members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos; 	my $args = qr{([^,)]+)};	# replace DECLARE_BITMAP	$members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;	$members =~ s/DECLARE_PHY_INTERFACE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, PHY_INTERFACE_MODE_MAX)/gos;	$members =~ s/DECLARE_BITMAP\s*\($args,\s*$args\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;	# replace DECLARE_HASHTABLE	$members =~ s/DECLARE_HASHTABLE\s*\($args,\s*$args\)/unsigned long $1\[1 << (($2) - 1)\]/gos;	# replace DECLARE_KFIFO	$members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos;	# replace DECLARE_KFIFO_PTR	$members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$2 \*$1/gos;	# replace DECLARE_FLEX_ARRAY	$members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos;	my $declaration = $members; 	# Split nested struct/union elements as newer ones	while ($members =~ m/$struct_members/) {		my $newmember;		my $maintype = $1;		my $ids = $4;		my $content = $3;		foreach my $id(split /,/, $ids) {			$newmember .= "$maintype $id; "; 			$id =~ s/[:\[].*//;			$id =~ s/^\s*\**(\S+)\s*/$1/;			foreach my $arg (split /;/, $content) {				next if ($arg =~ m/^\s*$/);				if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {					# pointer-to-function					my $type = $1;					my $name = $2;					my $extra = $3;					next if (!$name);					if ($id =~ m/^\s*$/) {						# anonymous struct/union						$newmember .= "$type$name$extra; ";					} else {						$newmember .= "$type$id.$name$extra; ";					}				} else {					my $type;					my $names;					$arg =~ s/^\s+//;					$arg =~ s/\s+$//;					# Handle bitmaps					$arg =~ s/:\s*\d+\s*//g;					# Handle arrays					$arg =~ s/\[.*\]//g;					# The type may have multiple words,					# and multiple IDs can be defined, like:					#	const struct foo, *bar, foobar					# So, we remove spaces when parsing the					# names, in order to match just names					# and commas for the names					$arg =~ s/\s*,\s*/,/g;					if ($arg =~ m/(.*)\s+([\S+,]+)/) {						$type = $1;						$names = $2;					} else {						$newmember .= "$arg; ";						next;					}					foreach my $name (split /,/, $names) {						$name =~ s/^\s*\**(\S+)\s*/$1/;						next if (($name =~ m/^\s*$/));						if ($id =~ m/^\s*$/) {							# anonymous struct/union							$newmember .= "$type $name; ";						} else {							$newmember .= "$type $id.$name; ";						}					}				}			}		}		$members =~ s/$struct_members/$newmember/;	} 	# Ignore other nested elements, like enums	$members =~ s/(\{[^\{\}]*\})//g; 	create_parameterlist($members, ';', $file, $declaration_name);	check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual); 	# Adjust declaration for better display	$declaration =~ s/([\{;])/$1\n/g;	$declaration =~ s/\}\s+;/};/g;	# Better handle inlined enums	do {} while ($declaration =~ s/(enum\s+\{[^\}]+),([^\n])/$1,\n$2/); 	my @def_args = split /\n/, $declaration;	my $level = 1;	$declaration = "";	foreach my $clause (@def_args) {		$clause =~ s/^\s+//;		$clause =~ s/\s+$//;		$clause =~ s/\s+/ /;		next if (!$clause);		$level-- if ($clause =~ m/(\})/ && $level > 1);		if (!($clause =~ m/^\s*#/)) {			$declaration .= "\t" x $level;		}		$declaration .= "\t" . $clause . "\n";		$level++ if ($clause =~ m/(\{)/ && !($clause =~m/\}/));	}	output_declaration($declaration_name,			   'struct',			   {'struct' => $declaration_name,			    'module' => $modulename,			    'definition' => $declaration,			    'parameterlist' => \@parameterlist,			    'parameterdescs' => \%parameterdescs,			    'parametertypes' => \%parametertypes,			    'sectionlist' => \@sectionlist,			    'sections' => \%sections,			    'purpose' => $declaration_purpose,			    'type' => $decl_type			   });    }    else {	print STDERR "${file}:$.: error: Cannot parse struct or union!\n";	++$errors;    }}  sub show_warnings($$) {	my $functype = shift;	my $name = shift; 	return 0 if (defined($nosymbol_table{$name})); 	return 1 if ($output_selection == OUTPUT_ALL); 	if ($output_selection == OUTPUT_EXPORTED) {		if (defined($function_table{$name})) {			return 1;		} else {			return 0;		}	}        if ($output_selection == OUTPUT_INTERNAL) {		if (!($functype eq "function" && defined($function_table{$name}))) {			return 1;		} else {			return 0;		}	}	if ($output_selection == OUTPUT_INCLUDE) {		if (defined($function_table{$name})) {			return 1;		} else {			return 0;		}	}	die("Please add the new output type at show_warnings()");} sub dump_enum($$) {    my $x = shift;    my $file = shift;    my $members;      $x =~ s@/\*.*?\*/@@gos;	# strip comments.    # strip #define macros inside enums    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;     if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) {	$declaration_name = $2;	$members = $1;    } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {	$declaration_name = $1;	$members = $2;    }     if ($members) {	if ($identifier ne $declaration_name) {	    if ($identifier eq "") {		print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n";	    } else {		print STDERR "${file}:$.: warning: expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n";	    }	    return;	}	$declaration_name = "(anonymous)" if ($declaration_name eq ""); 	my %_members; 	$members =~ s/\s+$//; 	foreach my $arg (split ',', $members) {	    $arg =~ s/^\s*(\w+).*/$1/;	    push @parameterlist, $arg;	    if (!$parameterdescs{$arg}) {		$parameterdescs{$arg} = $undescribed;	        if (show_warnings("enum", $declaration_name)) {			print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n";		}	    }	    $_members{$arg} = 1;	} 	while (my ($k, $v) = each %parameterdescs) {	    if (!exists($_members{$k})) {	        if (show_warnings("enum", $declaration_name)) {		     print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n";		}	    }        } 	output_declaration($declaration_name,			   'enum',			   {'enum' => $declaration_name,			    'module' => $modulename,			    'parameterlist' => \@parameterlist,			    'parameterdescs' => \%parameterdescs,			    'sectionlist' => \@sectionlist,			    'sections' => \%sections,			    'purpose' => $declaration_purpose			   });    } else {	print STDERR "${file}:$.: error: Cannot parse enum!\n";	++$errors;    }} my $typedef_type = qr { ((?:\s+[\w\*]+\b){1,8})\s* }x;my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x;my $typedef_args = qr { \s*\((.*)\); }x; my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x;my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x; sub dump_typedef($$) {    my $x = shift;    my $file = shift;     $x =~ s@/\*.*?\*/@@gos;	# strip comments.     # Parse function typedef prototypes    if ($x =~ $typedef1 || $x =~ $typedef2) {	$return_type = $1;	$declaration_name = $2;	my $args = $3;	$return_type =~ s/^\s+//; 	if ($identifier ne $declaration_name) {	    print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";	    return;	} 	create_parameterlist($args, ',', $file, $declaration_name); 	output_declaration($declaration_name,			   'function',			   {'function' => $declaration_name,			    'typedef' => 1,			    'module' => $modulename,			    'functiontype' => $return_type,			    'parameterlist' => \@parameterlist,			    'parameterdescs' => \%parameterdescs,			    'parametertypes' => \%parametertypes,			    'sectionlist' => \@sectionlist,			    'sections' => \%sections,			    'purpose' => $declaration_purpose			   });	return;    }     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {	$x =~ s/\(*.\)\s*;$/;/;	$x =~ s/\[*.\]\s*;$/;/;    }     if ($x =~ /typedef.*\s+(\w+)\s*;/) {	$declaration_name = $1; 	if ($identifier ne $declaration_name) {	    print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";	    return;	} 	output_declaration($declaration_name,			   'typedef',			   {'typedef' => $declaration_name,			    'module' => $modulename,			    'sectionlist' => \@sectionlist,			    'sections' => \%sections,			    'purpose' => $declaration_purpose			   });    }    else {	print STDERR "${file}:$.: error: Cannot parse typedef!\n";	++$errors;    }} sub save_struct_actual($) {    my $actual = shift;     # strip all spaces from the actual param so that it looks like one string item    $actual =~ s/\s*//g;    $struct_actual = $struct_actual . $actual . " ";} sub create_parameterlist($$$$) {    my $args = shift;    my $splitter = shift;    my $file = shift;    my $declaration_name = shift;    my $type;    my $param;     # temporarily replace commas inside function pointer definition    my $arg_expr = qr{\([^\),]+};    while ($args =~ /$arg_expr,/) {	$args =~ s/($arg_expr),/$1#/g;    }     foreach my $arg (split($splitter, $args)) {	# strip comments	$arg =~ s/\/\*.*\*\///;	# strip leading/trailing spaces	$arg =~ s/^\s*//;	$arg =~ s/\s*$//;	$arg =~ s/\s+/ /; 	if ($arg =~ /^#/) {	    # Treat preprocessor directive as a typeless variable just to fill	    # corresponding data structures "correctly". Catch it later in	    # output_* subs.	    push_parameter($arg, "", "", $file);	} elsif ($arg =~ m/\(.+\)\s*\(/) {	    # pointer-to-function	    $arg =~ tr/#/,/;	    $arg =~ m/[^\(]+\(\*?\s*([\w\[\]\.]*)\s*\)/;	    $param = $1;	    $type = $arg;	    $type =~ s/([^\(]+\(\*?)\s*$param/$1/;	    save_struct_actual($param);	    push_parameter($param, $type, $arg, $file, $declaration_name);	} elsif ($arg) {	    $arg =~ s/\s*:\s*/:/g;	    $arg =~ s/\s*\[/\[/g; 	    my @args = split('\s*,\s*', $arg);	    if ($args[0] =~ m/\*/) {		$args[0] =~ s/(\*+)\s*/ $1/;	    } 	    my @first_arg;	    if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {		    shift @args;		    push(@first_arg, split('\s+', $1));		    push(@first_arg, $2);	    } else {		    @first_arg = split('\s+', shift @args);	    } 	    unshift(@args, pop @first_arg);	    $type = join " ", @first_arg; 	    foreach $param (@args) {		if ($param =~ m/^(\*+)\s*(.*)/) {		    save_struct_actual($2); 		    push_parameter($2, "$type $1", $arg, $file, $declaration_name);		}		elsif ($param =~ m/(.*?):(\d+)/) {		    if ($type ne "") { # skip unnamed bit-fields			save_struct_actual($1);			push_parameter($1, "$type:$2", $arg, $file, $declaration_name)		    }		}		else {		    save_struct_actual($param);		    push_parameter($param, $type, $arg, $file, $declaration_name);		}

Lines 1001–1500 of 2503. Previous lines