2286 lines · 62.6 KB · Text
RawDownload
    foreach $parameter (@{$args{'parameterlist'}}) {	($parameter =~ /^#/) && next; 	my $parameter_name = $parameter;	$parameter_name =~ s/\[.*//; 	($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;	$type = $args{'parametertypes'}{$parameter};        print_lineno($parameterdesc_start_lines{$parameter_name});	print "``" . $parameter . "``\n";	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";    if (($output_selection == OUTPUT_ALL) ||	(($output_selection == OUTPUT_INCLUDE ||	  $output_selection == OUTPUT_EXPORTED) &&	 defined($function_table{$name})) ||	(($output_selection == OUTPUT_EXCLUDE ||	  $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;     if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) {	my $decl_type = $1;	$declaration_name = $2;	my $members = $3; 	# 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__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)/ /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; 	# replace DECLARE_BITMAP	$members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;	$members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;	# replace DECLARE_HASHTABLE	$members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;	# replace DECLARE_KFIFO	$members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;	# replace DECLARE_KFIFO_PTR	$members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; 	my $declaration = $members; 	# Split nested struct/union elements as newer ones	while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) {		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|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/$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 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;		}	}	if ($output_selection == OUTPUT_EXCLUDE) {		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;     $x =~ s@/\*.*?\*/@@gos;	# strip comments.    # strip #define macros inside enums    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;     if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) {	$declaration_name = $1;	my $members = $2;	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;    }} sub dump_typedef($$) {    my $x = shift;    my $file = shift;     $x =~ s@/\*.*?\*/@@gos;	# strip comments.     # Parse function prototypes    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||	$x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { 	# Function typedefs	$return_type = $1;	$declaration_name = $2;	my $args = $3; 	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; 	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    while ($args =~ /(\([^\),]+),/) {	$args =~ s/(\([^\),]+),/$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, $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", $file, $declaration_name);		}		elsif ($param =~ m/(.*?):(\d+)/) {		    if ($type ne "") { # skip unnamed bit-fields			save_struct_actual($1);			push_parameter($1, "$type:$2", $file, $declaration_name)		    }		}		else {		    save_struct_actual($param);		    push_parameter($param, $type, $file, $declaration_name);		}	    }	}    }} sub push_parameter($$$$) {	my $param = shift;	my $type = shift;	my $file = shift;	my $declaration_name = shift; 	if (($anon_struct_union == 1) && ($type eq "") &&	    ($param eq "}")) {		return;		# ignore the ending }; from anon. struct/union	} 	$anon_struct_union = 0;	$param =~ s/[\[\)].*//; 	if ($type eq "" && $param =~ /\.\.\.$/)	{	    if (!$param =~ /\w\.\.\.$/) {	      # handles unnamed variable parameters	      $param = "...";	    }	    elsif ($param =~ /\w\.\.\.$/) {	      # for named variable parameters of the form `x...`, remove the dots	      $param =~ s/\.\.\.$//;	    }	    if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {		$parameterdescs{$param} = "variable arguments";	    }	}	elsif ($type eq "" && ($param eq "" or $param eq "void"))	{	    $param="void";	    $parameterdescs{void} = "no arguments";	}	elsif ($type eq "" && ($param eq "struct" or $param eq "union"))	# handle unnamed (anonymous) union or struct:	{		$type = $param;		$param = "{unnamed_" . $param . "}";		$parameterdescs{$param} = "anonymous\n";		$anon_struct_union = 1;	} 	# warn if parameter has no description	# (but ignore ones starting with # as these are not parameters	# but inline preprocessor statements);

Lines 1001–1500 of 2286. Previous lines