2294 lines · 62.4 KB · Text
RawDownload
 sub dump_enum($$) {    my $x = shift;    my $file = shift;     $x =~ s@/\*.*?\*/@@gos;	# strip comments.    $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {	$declaration_name = $1;	my $members = $2; 	foreach my $arg (split ',', $members) {	    $arg =~ s/^\s*(\w+).*/$1/;	    push @parameterlist, $arg;	    if (!$parameterdescs{$arg}) {		$parameterdescs{$arg} = $undescribed;		print STDERR "Warning(${file}:$.): Enum value '$arg' ".		    "not described in enum '$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 "Error(${file}:$.): Cannot parse enum!\n";	++$errors;    }} sub dump_typedef($$) {    my $x = shift;    my $file = shift;     $x =~ s@/\*.*?\*/@@gos;	# strip comments.    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 "Error(${file}:$.): 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 $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);	} 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);		}		elsif ($param =~ m/(.*?):(\d+)/) {		    if ($type ne "") { # skip unnamed bit-fields			save_struct_actual($1);			push_parameter($1, "$type:$2", $file)		    }		}		else {		    save_struct_actual($param);		    push_parameter($param, $type, $file);		}	    }	}    }} sub push_parameter($$$) {	my $param = shift;	my $type = shift;	my $file = shift; 	if (($anon_struct_union == 1) && ($type eq "") &&	    ($param eq "}")) {		return;		# ignore the ending }; from anon. struct/union	} 	$anon_struct_union = 0;	my $param_name = $param;	$param_name =~ s/\[.*//; 	if ($type eq "" && $param =~ /\.\.\.$/)	{	    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);	# also ignore unnamed structs/unions;	if (!$anon_struct_union) {	if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) { 	    $parameterdescs{$param_name} = $undescribed; 	    if (($type eq 'function') || ($type eq 'enum')) {		print STDERR "Warning(${file}:$.): Function parameter ".		    "or member '$param' not " .		    "described in '$declaration_name'\n";	    }	    print STDERR "Warning(${file}:$.):" .			 " No description found for parameter '$param'\n";	    ++$warnings;	}	} 	$param = xml_escape($param); 	# strip spaces from $param so that it is one continuous string	# on @parameterlist;	# this fixes a problem where check_sections() cannot find	# a parameter like "addr[6 + 2]" because it actually appears	# as "addr[6", "+", "2]" on the parameter list;	# but it's better to maintain the param string unchanged for output,	# so just weaken the string compare in check_sections() to ignore	# "[blah" in a parameter string;	###$param =~ s/\s*//g;	push @parameterlist, $param;	$parametertypes{$param} = $type;} sub check_sections($$$$$$) {	my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;	my @sects = split ' ', $sectcheck;	my @prms = split ' ', $prmscheck;	my $err;	my ($px, $sx);	my $prm_clean;		# strip trailing "[array size]" and/or beginning "*" 	foreach $sx (0 .. $#sects) {		$err = 1;		foreach $px (0 .. $#prms) {			$prm_clean = $prms[$px];			$prm_clean =~ s/\[.*\]//;			$prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;			# ignore array size in a parameter string;			# however, the original param string may contain			# spaces, e.g.:  addr[6 + 2]			# and this appears in @prms as "addr[6" since the			# parameter list is split at spaces;			# hence just ignore "[..." for the sections check;			$prm_clean =~ s/\[.*//; 			##$prm_clean =~ s/^\**//;			if ($prm_clean eq $sects[$sx]) {				$err = 0;				last;			}		}		if ($err) {			if ($decl_type eq "function") {				print STDERR "Warning(${file}:$.): " .					"Excess function parameter " .					"'$sects[$sx]' " .					"description in '$decl_name'\n";				++$warnings;			} else {				if ($nested !~ m/\Q$sects[$sx]\E/) {				    print STDERR "Warning(${file}:$.): " .					"Excess struct/union/enum/typedef member " .					"'$sects[$sx]' " .					"description in '$decl_name'\n";				    ++$warnings;				}			}		}	}} ### takes a function prototype and the name of the current file being# processed and spits out all the details stored in the global# arrays/hashes.sub dump_function($$) {    my $prototype = shift;    my $file = shift;     $prototype =~ s/^static +//;    $prototype =~ s/^extern +//;    $prototype =~ s/^asmlinkage +//;    $prototype =~ s/^inline +//;    $prototype =~ s/^__inline__ +//;    $prototype =~ s/^__inline +//;    $prototype =~ s/^__always_inline +//;    $prototype =~ s/^noinline +//;    $prototype =~ s/__devinit +//;    $prototype =~ s/__init +//;    $prototype =~ s/__init_or_module +//;    $prototype =~ s/__must_check +//;    $prototype =~ s/^#\s*define\s+//; #ak added    $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;     # Yes, this truly is vile.  We are looking for:    # 1. Return type (may be nothing if we're looking at a macro)    # 2. Function name    # 3. Function parameters.    #    # All the while we have to watch out for function pointer parameters    # (which IIRC is what the two sections are for), C types (these    # regexps don't even start to express all the possibilities), and    # so on.    #    # If you mess with these regexps, it's a good idea to check that    # the following functions' documentation still comes out right:    # - parport_register_device (function pointer parameters)    # - atomic_set (macro)    # - pci_match_device, __copy_to_user (long return type)     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||	$prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||	$prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {	$return_type = $1;	$declaration_name = $2;	my $args = $3; 	create_parameterlist($args, ',', $file);    } else {	print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";	++$errors;	return;    } 	my $prms = join " ", @parameterlist;	check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");     output_declaration($declaration_name,		       'function',		       {'function' => $declaration_name,			'module' => $modulename,			'functiontype' => $return_type,			'parameterlist' => \@parameterlist,			'parameterdescs' => \%parameterdescs,			'parametertypes' => \%parametertypes,			'sectionlist' => \@sectionlist,			'sections' => \%sections,			'purpose' => $declaration_purpose		       });} sub reset_state {    $function = "";    %constants = ();    %parameterdescs = ();    %parametertypes = ();    @parameterlist = ();    %sections = ();    @sectionlist = ();    $sectcheck = "";    $struct_actual = "";    $prototype = "";     $state = 0;} sub tracepoint_munge($) {	my $file = shift;	my $tracepointname = 0;	my $tracepointargs = 0; 	if ($prototype =~ m/TRACE_EVENT\((.*?),/) {		$tracepointname = $1;	}	if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {		$tracepointname = $1;	}	if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {		$tracepointname = $2;	}	$tracepointname =~ s/^\s+//; #strip leading whitespace	if ($prototype =~ m/TP_PROTO\((.*?)\)/) {		$tracepointargs = $1;	}	if (($tracepointname eq 0) || ($tracepointargs eq 0)) {		print STDERR "Warning(${file}:$.): Unrecognized tracepoint format: \n".			     "$prototype\n";	} else {		$prototype = "static inline void trace_$tracepointname($tracepointargs)";	}} sub syscall_munge() {	my $void = 0; 	$prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs##	if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {	if ($prototype =~ m/SYSCALL_DEFINE0/) {		$void = 1;##		$prototype = "long sys_$1(void)";	} 	$prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name	if ($prototype =~ m/long (sys_.*?),/) {		$prototype =~ s/,/\(/;	} elsif ($void) {		$prototype =~ s/\)/\(void\)/;	} 	# now delete all of the odd-number commas in $prototype	# so that arg types & arg names don't have a comma between them	my $count = 0;	my $len = length($prototype);	if ($void) {		$len = 0;	# skip the for-loop	}	for (my $ix = 0; $ix < $len; $ix++) {		if (substr($prototype, $ix, 1) eq ',') {			$count++;			if ($count % 2 == 1) {				substr($prototype, $ix, 1) = ' ';			}		}	}} sub process_state3_function($$) {    my $x = shift;    my $file = shift;     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line     if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {	# do nothing    }    elsif ($x =~ /([^\{]*)/) {	$prototype .= $1;    }     if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {	$prototype =~ s@/\*.*?\*/@@gos;	# strip comments.	$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.	$prototype =~ s@^\s+@@gos; # strip leading spaces	if ($prototype =~ /SYSCALL_DEFINE/) {		syscall_munge();	}	if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||	    $prototype =~ /DEFINE_SINGLE_EVENT/)	{		tracepoint_munge($file);	}	dump_function($prototype, $file);	reset_state();    }} sub process_state3_type($$) {    my $x = shift;    my $file = shift;     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.    $x =~ s@^\s+@@gos; # strip leading spaces    $x =~ s@\s+$@@gos; # strip trailing spaces    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line     if ($x =~ /^#/) {	# To distinguish preprocessor directive from regular declaration later.	$x .= ";";    }     while (1) {	if ( $x =~ /([^{};]*)([{};])(.*)/ ) {	    $prototype .= $1 . $2;	    ($2 eq '{') && $brcount++;	    ($2 eq '}') && $brcount--;	    if (($2 eq ';') && ($brcount == 0)) {		dump_declaration($prototype, $file);		reset_state();		last;	    }	    $x = $3;	} else {	    $prototype .= $x;	    last;	}    }} # xml_escape: replace <, >, and & in the text stream;## however, formatting controls that are generated internally/locally in the# kernel-doc script are not escaped here; instead, they begin life like# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings# are converted to their mnemonic-expected output, without the 4 * '\' & ':',# just before actual output; (this is done by local_unescape())sub xml_escape($) {	my $text = shift;	if (($output_mode eq "text") || ($output_mode eq "man")) {		return $text;

Lines 1501–2000 of 2294. Previous lines