1883 lines · 50.4 KB · Text
RawDownload
### 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/^fastcall +//;    $prototype =~ s/^asmlinkage +//;    $prototype =~ s/^inline +//;    $prototype =~ s/^__inline__ +//;    $prototype =~ s/^#define +//; #ak added    $prototype =~ s/__attribute__ \(\([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*\(([^\{]*)\)/)  {	$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;    }     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 process_file($); # Read the file that maps relative names to absolute names for# separate source and object directories and for shadow trees.if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {	my ($relname, $absname);	while(<SOURCE_MAP>) {		chop();		($relname, $absname) = (split())[0..1];		$relname =~ s:^/+::;		$source_map{$relname} = $absname;	}	close(SOURCE_MAP);} if ($filelist) {	open(FLIST,"<$filelist") or die "Can't open file list $filelist";	while(<FLIST>) {		chop;		process_file($_);	}} foreach (@ARGV) {    chomp;    process_file($_);}if ($verbose && $errors) {  print STDERR "$errors errors\n";}if ($verbose && $warnings) {  print STDERR "$warnings warnings\n";} exit($errors); sub reset_state {    $function = "";    %constants = ();    %parameterdescs = ();    %parametertypes = ();    @parameterlist = ();    %sections = ();    @sectionlist = ();    $prototype = "";     $state = 0;} sub process_state3_function($$) {    my $x = shift;    my $file = shift;     if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) {	# do nothing    }    elsif ($x =~ /([^\{]*)/) {        $prototype .= $1;    }    if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {        $prototype =~ s@/\*.*?\*/@@gos;	# strip comments.	$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.	$prototype =~ s@^\s+@@gos; # strip leading spaces	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    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;	}    }} # replace <, >, and &sub xml_escape($) {	my $text = shift;	$text =~ s/\&/\\\\\\amp;/g;	$text =~ s/\</\\\\\\lt;/g;	$text =~ s/\>/\\\\\\gt;/g;	return $text;} sub process_file($) {    my $file;    my $identifier;    my $func;    my $initial_section_counter = $section_counter;     if (defined($ENV{'SRCTREE'})) {	$file = "$ENV{'SRCTREE'}" . "/" . "@_";    }    else {	$file = "@_";    }    if (defined($source_map{$file})) {	$file = $source_map{$file};    }     if (!open(IN,"<$file")) {	print STDERR "Error: Cannot open file $file\n";	++$errors;	return;    }     $section_counter = 0;    while (<IN>) {	if ($state == 0) {	    if (/$doc_start/o) {		$state = 1;		# next line is always the function name	    }	} elsif ($state == 1) {	# this line is the function name (always)	    if (/$doc_block/o) {		$state = 4;		$contents = "";		if ( $1 eq "" ) {			$section = $section_intro;		} else {			$section = $1;		}            }	    elsif (/$doc_decl/o) {		$identifier = $1;		if (/\s*([\w\s]+?)\s*-/) {		    $identifier = $1;		} 		$state = 2;		if (/-(.*)/) {		    $declaration_purpose = xml_escape($1);		} else {		    $declaration_purpose = "";		}		if ($identifier =~ m/^struct/) {		    $decl_type = 'struct';		} elsif ($identifier =~ m/^union/) {		    $decl_type = 'union';		} elsif ($identifier =~ m/^enum/) {		    $decl_type = 'enum';		} elsif ($identifier =~ m/^typedef/) {		    $decl_type = 'typedef';		} else {		    $decl_type = 'function';		} 		if ($verbose) {		    print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";		}	    } else {		print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",		" - I thought it was a doc line\n";		++$warnings;		$state = 0;	    }	} elsif ($state == 2) {	# look for head: lines, and include content	    if (/$doc_sect/o) {		$newsection = $1;		$newcontents = $2; 		if ($contents ne "") {		    dump_section($section, xml_escape($contents));		    $section = $section_default;		} 		$contents = $newcontents;		if ($contents ne "") {		    $contents .= "\n";		}		$section = $newsection;	    } elsif (/$doc_end/) { 		if ($contents ne "") {		    dump_section($section, xml_escape($contents));		    $section = $section_default;		    $contents = "";		} 		$prototype = "";		$state = 3;		$brcount = 0;#	    print STDERR "end of doc comment, looking for prototype\n";	    } elsif (/$doc_content/) {		# miguel-style comment kludge, look for blank lines after		# @parameter line to signify start of description		if ($1 eq "" &&			($section =~ m/^@/ || $section eq $section_context)) {		    dump_section($section, xml_escape($contents));		    $section = $section_default;		    $contents = "";		} else {		    $contents .= $1."\n";		}	    } else {		# i dont know - bad line?  ignore.		print STDERR "Warning(${file}:$.): bad line: $_";		++$warnings;	    }	} elsif ($state == 3) {	# scanning for function { (end of prototype)	    if ($decl_type eq 'function') {	        process_state3_function($_, $file);	    } else {	        process_state3_type($_, $file);	    }	} elsif ($state == 4) {		# Documentation block	        if (/$doc_block/) {			dump_section($section, $contents);			output_intro({'sectionlist' => \@sectionlist,				      'sections' => \%sections });			$contents = "";			$function = "";			%constants = ();			%parameterdescs = ();			%parametertypes = ();			@parameterlist = ();			%sections = ();			@sectionlist = ();			$prototype = "";			if ( $1 eq "" ) {				$section = $section_intro;			} else {				$section = $1;			}                }		elsif (/$doc_end/)		{			dump_section($section, $contents);			output_intro({'sectionlist' => \@sectionlist,				      'sections' => \%sections });			$contents = "";			$function = "";			%constants = ();			%parameterdescs = ();			%parametertypes = ();			@parameterlist = ();			%sections = ();			@sectionlist = ();			$prototype = "";			$state = 0;		}		elsif (/$doc_content/)		{			if ( $1 eq "" )			{				$contents .= $blankline;			}			else			{				$contents .= $1 . "\n";			}        	}          }    }    if ($initial_section_counter == $section_counter) {	print STDERR "Warning(${file}): no structured comments found\n";	if ($output_mode eq "xml") {	    # The template wants at least one RefEntry here; make one.	    print "<refentry>\n";	    print " <refnamediv>\n";	    print "  <refname>\n";	    print "   ${file}\n";	    print "  </refname>\n";	    print "  <refpurpose>\n";	    print "   Document generation inconsistency\n";	    print "  </refpurpose>\n";	    print " </refnamediv>\n";	    print " <refsect1>\n";	    print "  <title>\n";	    print "   Oops\n";	    print "  </title>\n";	    print "  <warning>\n";	    print "   <para>\n";	    print "    The template for this document tried to insert\n";	    print "    the structured comment from the file\n";	    print "    <filename>${file}</filename> at this point,\n";	    print "    but none was found.\n";	    print "    This dummy section is inserted to allow\n";	    print "    generation to continue.\n";	    print "   </para>\n";	    print "  </warning>\n";	    print " </refsect1>\n";	    print "</refentry>\n";	}    }}

Lines 1501–1883 of 1883. Previous lines