#!/local/bin/perl

sub Usage {
    print STDERR "Usage: adjustMan [-v] [-d][[-p <pairFileName>] | <headerFileName>]\n";
    print STDERR "                 <sourceFile> ...\n";
    print STDERR "  -v                : Verbose\n";
    print STDERR "  -d                : Debug\n";
    print STDERR "  -p <pairFileName> : Two-column text file where the\n";
    print STDERR "      entry in the second column is the name of the\n";
    print STDERR "      include-file which contains the function prototypes\n";
    print STDERR "      of each <sourceFile>.\n";
    exit 1;
}

sub Help {
    print STDERR "Program to adjust the XITE manual page descriptions\n";
    print STDERR "in the C source code in order to make them match\n";
    print STDERR "source function headers.\n"
}

sub GetFilePairs {
    # Return an associative array with keys equal to source file names
    # and values equal to the corresponding header files

    local($PairFile) = @_;
    local(%files);

    if ($Debug == 1) {print STDOUT "Open $PairFile\n";}
    open(PAIRFILE, $PairFile) || die "Can't open file $PairFile.\n";
    while (<PAIRFILE>) {
	$_ =~ s/^# *//;  # Also read the commented lines
	split;
	$files{@_[0]} = @_[1];
    }

    close(PAIRFILE);
    if ($Debug == 1) {print STDOUT "Closed $PairFile\n";}
    %files;
} # sub GetFilePairs

sub GetHeaderFileAndDirNames {
  local($SourceFileName, $NewHeaderFile, $HeaderFile, $Dir) = @_;
  local($OldHeaderFile);

  if ($Debug == 1) {
      print STDOUT "GetHeaderFileAndDirNames entered.\n";
  }

  if (defined($HeaderFile)) {
      $OldHeaderFile = $HeaderFile;
  } else {
      $OldHeaderFile = "";
  }
  $HeaderFile = $NewHeaderFile;

  # Remove directory part of name
  if ($HeaderFile =~ /.*\/(.+\.h)/) {
      $HeaderFile = $1;
  } elsif ($HeaderFile =~ /(.+\.h)/) {
      $HeaderFile = $1;
  } else {
      print STDERR "Header filename does not have extension '.h'.\n";
      exit 1
  }

  $HeaderFileStem = $HeaderFile;
  $HeaderFileStem =~ s/(.+)\.h/\1/;

  # Find directory of current source file (and header file)
  $OldDir = $Dir;
  if ($SourceFileName =~ /(.+)\/[$SourceFileChars]+/) {
      $Dir = $1;
  } else {
      $Dir = ".";
  }

  if ($Debug == 1) {
      print STDOUT "GetHeaderFileAndDirNames leaving.\n";
  }

  ($HeaderFile, $HeaderFileStem, $Dir, $OldHeaderFile);  
} # sub GetHeaderFileAndDirNames

sub GetFuncDecls {
    local($SourceFileName, $NewHeaderFile, $HeaderFile, $OldDir) = @_;
    local($HeaderFileStem, $Dir);

    if ($Debug == 1) {
	print STDOUT "GetFuncDecls entered.\n";
    }

    ($HeaderFile, $HeaderFileStem, $Dir, $OldHeaderFile) =
	&GetHeaderFileAndDirNames($SourceFileName, $NewHeaderFile,
				  $HeaderFile, $OldDir);

    if ($Dir ne $OldDir) {
	# Give feedback on missing declarations etc. when a directory is
	# done. This assumes that files from one directory are processed
	# prior to files from another directory (as given on the command line)

	&Report();
	undef %Found;
	undef @NameFuncs;
    }
    if ($HeaderFile ne $OldHeaderFile) {
	if ($Debug == 1) {print STDOUT "Open $Dir\/$HeaderFile\n";}
	open(HEADERFILE, "$Dir\/$HeaderFile")
	    || die "Can't open file $Dir\/$HeaderFile.\n";
	@headerFile = <HEADERFILE>;

	@Funcs =
	 grep(/^extern\s+[\w\*]+\s+[\w\*]*\s*\**\s*\w+\s*\([$ParamChars\,]+\)/,
		 @headerFile);
	close(HEADERFILE);
	if ($Debug == 1) {print STDOUT "Closed $Dir\/$HeaderFile\n";}
    }

    if ($Debug == 1) {
	print STDOUT "GetFuncDecls leaving.\n";
    }

    ($HeaderFile, $Dir, @Funcs);
} # sub GetFuncDecls

sub MakeFuncDecl {
    local($Debug, $FType, $Ast, $FName, $Pars) = @_;
    local(@Pars, @FDecl, $i,$ParT, $Aster, $ParN);

    if ($Debug == 1) {
	print STDOUT "MakeFuncDecl entered.\n";
	print STDOUT "$FType" . "." . "$Ast" . "." . "$FName" . "." .
	    "$Pars" . "." . "@Pars" . "." . "@FDecl" . "." . "$i" . "." .
	    "$ParT" . "." . "$Aster" . "." . "$ParN" . "\n";
    }

    @Pars = split(',', $Pars);
    if ($Debug == 1) {print STDOUT "@Pars\n";}

    @FDecl = " " x 16 . "| " . "$FType" . " " . "$Ast" . 
	"$FName" . "(";

    $i = 0;
    while (defined($_ = shift(@Pars))) {
	if (/\(\s*void\s*\)/) {
	    # Special treatment for the single-word parameter case of "void"
	    ($ParT, $Aster, $ParN) = ("void", "", "");
	} elsif (/\s*\.\.\.\s*/) {
	    # Special treatment for the parameter case of "..."
	    ($ParT, $Aster, $ParN) = ("", "", "...");
	} else {
	    ($ParT, $Aster, $ParN) =
		/^\s*(\w+)\s*(\**)\s*([$ParamChars]+)\s*/;
	}

	if (length("$FDecl[$i]" . "$_") < 65) {
	    $FDecl[$i] .= " $ParT" . "$Aster" . " " . "$ParN" . ",";
	} else {
	    $FDecl[$i++] .= "\n";
	    $FDecl[$i] .= " " x 16 . "|   " . 
		" $ParT" . "$Aster" . " " . "$ParN" . ",";
	}
	if ($Debug == 1) {
	    print STDOUT "." . "$ParT" . "." . "$Aster" . 
		"." . "$ParN" . ".\n";
	}
    }

    chop($FDecl[$i]);
    $FDecl[$i] .= ");\n";

    if ($Debug == 1) {
	print STDOUT "@FDecl";
	print STDOUT "MakeFuncDecl leaving.\n";
    }

    @FDecl;
} # sub MakeFuncDecl

sub MakeNameList {
    # Using global array %Found

    local($Debug, $NameLine, $lineNo, $Line, @NameFuncs) = @_;
    local($i, @Line);

    if ($Debug == 1) {
	print STDOUT "MakeNameList entered.\n";
    }

    if ($Debug == 1 && $NameLine == 1) {
	print STDOUT "Name: section found in line $lineNo.\n";
    }
    if ($Line =~ m/ - /) {
	if ($Debug == 1) {
	    print STDOUT 
		"Name: section separating hyphen found on line $lineNo.\n";
	}
    }

    @Line = split(' ', $Line);
    for ($i = 0; $i <= $#Line; $i++) {

	if ($Line[$i] eq "-") {
	    splice(@Line, $i);
	    last;
	}

	# Remove any apostrophes ("'")
	$Line[$i] =~ s/'*(.+)'*/\1/;

	# Remove trailing comma
	if ($Line[$i] =~ m/,$/) {
	    chop $Line[$i];
	}

	# If the line started with "|", skip this "|"-entry
	if ($Line[$i] =~ m/^\|$/) {
	    splice(@Line, $i--, 1);
	    next;
	}

	# Already registered?
	if ($Found{$Line[$i]} & 2) {
	    splice(@Line, $i--, 1);
	}
    }

    if ($NameLine == 1) {
	splice(@Line, 0, 1);
    }

    if ($#NameFuncs >= 0) {
	push(@NameFuncs, @Line);
    } else {
	splice(@NameFuncs, 0, 0, @Line);
    }

    if ($Line =~ m/\s- */) {
	for ($i = 0; $i <= $#NameFuncs; $i++) {
	    $Found{$NameFuncs[$i]} |= 2;
	    $FoundLocal{$NameFuncs[$i]} |= 2;
	}
    }
    
    if ($Debug == 1) {
	print STDOUT "Names: * @NameFuncs *\n";
    }

    if ($Debug == 1) {
	print STDOUT "MakeNameList leaving.\n";
    }

    return(@NameFuncs);

} # sub MakeNameList

	      
sub SyntaxLine {
    # Using global arrays @SourceLines and %Found.

    local($SourceLine, $SyntaxLineNo, $HeaderFile, $lineNo, $FuncName,
	  $StartLine, $StopLine, $Debug, $nFuncDecls,
	  $nNameFuncs) = @_;
    local($OldLine, $SyntaxLine, $i);

    if ($Debug == 1) {
	print STDOUT "SyntaxLine entered.\n";
	print STDOUT "$nFuncDecls" . "." . "$nNameFuncs" . "\n" . "@_\n";
    }

    if ($nFuncDecls > 0) {@FuncDecl = @_[10..10+$nFuncDecls];}
    elsif ($nFuncDecls == 0) {@FuncDecl = @_[10];}
    else {print STDERR "Error: Missing function declaration.\n";}

    @NameFuncs = @_[10+$nFuncDecls+1..10+$nFuncDecls+1+$nNameFuncs];
    if ($Debug == 1) {print STDOUT "@FuncDecl\n" . "@NameFuncs\n";}

    if ($SyntaxLineNo == 1) {
	# First line of Syntax: section.
	$SyntaxLine = sprintf("%s%s%s%s",
			      "Syntax:         ",
			      "| #include <xite/",
			      $HeaderFile,
			      ">\n");
	if ($SourceLine =~ m/#include/) {
	    # First Syntax: section line is an include directive.
	    # Replace by new include directive.
	    # This line is finished, so return. Get new source line.
	    splice(@SourceLines, $lineNo, 1, $SyntaxLine);
	    return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 1,
		   @NameFuncs);
	} else {
	    # First Syntax: section line is not an include directive
	    # Insert the include directive above this line, and continue
	    # checking this line.

	    $SourceLine =~ s/^Syntax:\s+(.+)/                \1/;
	    if ($SourceLine =~ m/^\s+\|\s*$/) {
		splice(@SourceLines, $lineNo, 1, $SyntaxLine, $SourceLine);
		$lineNo++;
	    } else {
		splice(@SourceLines, $lineNo, 1, $SyntaxLine,
		       "                | \n", $SourceLine);
		$lineNo += 2;
	    }
	}
    } # First Syntax: line

    if ($SourceLine =~ m/[ *]+$FuncName[\s]*\(/) {
	# This could be the start of a function declaration.
	if ($StartLine != -1) {
	    print STDERR
		"Error: Found $FuncName more than once in $ARGV\n";
	}
	$StartLine = $lineNo;
	if ($Debug == 1) {print STDOUT "Found in line $lineNo.\n";}

	# Return and go to new source line, remember this function.
	return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 2, @NameFuncs);
    } elsif (($SourceLine =~ m/^(\s+)(\|*)/) && $StartLine != -1) {
	# Line starting with white-space and possibly "|", but not
	# containing the function name.

	if (length($2) == 0) {
	    # Continuation line
	    if ($Debug == 1) {print STDOUT "Continuation line.\n";}
	    return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 3,
		   @NameFuncs);
	}

	# Could be
	# 1) End of function declaration, only white-sp and poss. "|"
	# 2) K&R Parameter specification
	# 3) Start of new function declaration
	if ($SourceLine =~ m/[^\s|]/) {
	    # Not only white-space and possibly "|", 2) and 3)
	    # remain.
	    # 3) is distinguished by the occurence of a left
	    # parenthesis, except that a function parameter in 2)
	    # has the same feature. In the latter case, there must
	    # be a right parenthesis without intervening characters
	    # (other than possibly white-space).
	    
	    if ($SourceLine !~ m/\(\s*\)/) {
		# NOT function parameter, so we consider other
		# parameter or start of new function.

		if ($SourceLine =~ m/\(/) {
		    # New function declaration
		    $StopLine = $lineNo - 1;
		    if ($Debug == 1) {
			print STDOUT "New function declaration.\n";
		    }
		} else {
		    # Other parameter
		    if ($Debug == 1) {
			print STDOUT "Other parameter.\n";
		    }
		    return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 4,
			   @NameFuncs);
		}
	    } else {
		# Function parameter, 2) from above
		if ($Debug == 1) {
		    print STDOUT "Function parameter.\n";
		}
		return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 5,
		       @NameFuncs);
	    }
	} else {
	    # Only white-space and possibly "|"
	    # Found end of function declaration
	    if ($Debug == 1) {
		print STDOUT
		    "End of function declaration " .
			"(only white-space and possibly '|').\n";
	    }
	    $StopLine = $lineNo - 1;
	}
    } elsif ($StartLine != -1) {
	# No initial white-space
	# Found end of function declaration
	if ($Debug == 1) {
	    print STDOUT
		"End of function declaration (no initial white-space).\n";
	}
	$SyntaxLineNo = -1;
	$StopLine = $lineNo - 1;
    } elsif ($SourceLine !~ m/^(\s+)/ && $StartLine == -1){
	# No initial white-space, must be end of Syntax: section
	if ($Debug == 1) {
	    print STDOUT "End of Syntax: section.\n";
	}
	$SyntaxLineNo = -1;
	return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 8, @NameFuncs);
    } else {
	if ($Debug == 1) {
	    print STDOUT "Not found yet.\n";
	}
	return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 6, @NameFuncs);
    } # Not found yet
    
    if ($StopLine != -1) {
	if ($Debug == 1) {
	    print STDOUT "taking out:\n";
	    print STDOUT "@SourceLines[$StartLine..$StopLine]";
	}
	splice(@SourceLines, $StartLine, $StopLine - $StartLine + 1,
	       @FuncDecl);
	# Function has been treated
	$Found{$FuncName} |= 8;
	$FoundLocal{$FuncName} |= 8;
	
	# Remove name from list of named, but un-treated functions
	for ($i = 0; $i <= $#NameFuncs; $i++) {
	    if ($NameFuncs[$i] eq $FuncName) {
		splice(@NameFuncs, $i--, 1);
	    }
	}
	
	if ($Debug == 1) {
	    print STDOUT "putting in:\n";
	    print STDOUT "@FuncDecl\n";
	}

	$StopLine = $StartLine + $#FuncDecl;

	return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 7, @NameFuncs);
    } # Found end of function declaration

    if ($Debug == 1) {
	print STDOUT "SyntaxLine leaving.\n";
    }
    return($lineNo, $SyntaxLineNo, $StartLine, $StopLine, 0, @NameFuncs);

} # sub SyntaxLine

sub ParseArguments {
    local($FilePair, $Verbose, $Debug, $i, %files);

    $FilePair = 0; $Verbose = 0;
     Option: while ($_ = $ARGV[0], /^-/) {
	 shift @ARGV;
	 last if /^--$/;
	 if (/^-p/) {
	     %files = &GetFilePairs($ARGV[0]);
	     shift @ARGV;
	     $FilePair=1;
	     next Option;
	 }
	 if (/^-h/) { &Help; &Usage }
	 if (/^-v/) { $Verbose = 1; }
	 if (/^-d/) { $Debug = 1;}
     }

    if ($#ARGV == -1) {
	print STDERR "\n";
	&Help;
	print STDERR "\n";
	&Usage;
    }

    if ($FilePair == 0) {
	if ($#ARGV < 1) {
	    print STDERR "\n";
	    &Help;
	    print STDERR "\n";
	    &Usage;
	}

	for ($i = 1; $i <= $#ARGV; $i++) {
	    $files{$ARGV[$i]} = $ARGV[0];
	}
	shift @ARGV;
    } else {
	print STDERR "Comments (\#) in the syntax section of the manual\n";
	print STDERR "page description are not included in the output.\n";
    }

    if ($Debug == 1) {
	print STDOUT "ParseArguments leaving.\n";
    }

    ($Verbose, $Debug, $i, %files);

} # sub ParseArguments

sub Report {
    local($key);

    foreach $key (sort(keys %Found)) {
	# 0 : Candidate, i.e. it was found in the header file.
	# 1 : Mentioned in the source file.
	# 2 : Mentioned in Name: section.
	# 4 : Mentioned in /*[FD] line.
	# 8 : Treated.
	
	if ($Found{$key} != 15) {
	    if (($Found{$key} & 7) != 7) {print STDERR "Warning: $key ";}
	    if (!($Found{$key} & 1)) {
		print STDERR "in source-file, but not in header-file, ";
	    }
	    
	    if ($Found{$key} & 1) {
		# Mentioned somewhere in source-file
		if (!($Found{$key} & 2)) {
		    print STDERR "not in name-section in man-comment, ";
		}
		if (!($Found{$key} & 4)) {
		    print STDERR "not in /*[FD] in man-comment, ";
		}
		if (!($Found{$key} & 8)) {
		    print STDERR "not treated.";
		}
	    }
	    if (($Found{$key} & 7) != 7) {print STDERR "\n";}
	}
	
    }				# foreach $key

} # sub Report

($Verbose, $Debug, $i, %files) = &ParseArguments();

# Global variables
$ParamChars = '][()\w\s\*\.';
$SourceFileChars = 'A-Za-z_0-9.';

sourceFile: while ($ARGV = shift) {
    if (!defined($files{$ARGV})) {
	print STDERR "Warning: No header-file defined for $ARGV. Skipping.\n";
	next sourceFile;
    }
    
    $SyntaxLineNo = -1;
    $PotentialFuncNo = -1;
    undef %FoundLocal;
    undef @NameFuncs;

    if ($Debug == 1) {print STDOUT keys %FoundLocal;
		      print STDOUT values %FoundLocal;}
    if ($Debug == 1) {print STDOUT keys %Local;
		      print STDOUT values %Local;}

    open(SOURCEFILE, $ARGV) || die "Can't open file $ARGV.\n";
    @SourceLines = <SOURCEFILE>;                    # Read in complete file.
    
    if ($HeaderFile ne $files{$ARGV}) {
	($HeaderFile, $Dir, @Funcs) =
	    &GetFuncDecls($ARGV, $files{$ARGV}, $HeaderFile, $Dir);
    }
    
    if ($Verbose) {print STDERR "$ARGV\n";}

    $lineNo = 0; $StartLine = -1; $StopLine = -1;
  line: while (($lineNo <= $#SourceLines) &&
	       ($SourceLine = $_ = $SourceLines[$lineNo])) {


      if (($ManDescLineNo < 1) && /^\/\*[FD]:\w+\*$/) {
	  $ManDescLineNo = 1;
      } elsif (($ManDescLineNo >= 1) && /^\*\/$/) {
	  $ManDescLineNo = -1;
	  if ($Debug == 1) {
	      print STDOUT "End of manual page section.\n";
	      print STDOUT "$_\n";
	  }
      }
      
      if ($ManDescLineNo >= 1) {
	  # Inside manual page description.
	  if ($ManDescLineNo == 1) {
	      $ManPageName = /^\/\*[FD]:(\w+)/;
	  }
	  
	  if ($NameLine = /^Name:\s+/ .. /-/) {
	      # Name: section of manual page description.
	      # Store the named functions in array @NameFuncs.
	      
	      @NameFuncs =
		  &MakeNameList($Debug, $NameLine, $lineNo, $_, @NameFuncs);

	      next line;
	  }

	  if (($SyntaxLineNo < 0) && /^Syntax:\s+/) {
	      $SyntaxLineNo = 0;
	  } elsif (($SyntaxLineNo >= 0) && /^\S+/ && ($#NameFuncs < 0)) {
	      $SyntaxLineNo = -1;
	      if ($Debug == 1) {
		  print STDOUT "End of Syntax: section:\n";
		  print STDOUT "$_\n";
	      }
	  }

	  if ($SyntaxLineNo >= 0) {
	      # Trippel '.' in the above line to not evaluate the right
	      # side expression the first time the left side is true.
	      
	      # Inside syntax part of manual page description.

	      $funcNo = $#Funcs;
	    func:  while (($funcNo >= 0) && ($Func = $_ = $Funcs[$funcNo--])) {

		if (($PotentialFuncNo != -1) && $Debug == 1) {
		    print STDOUT "$PotentialFuncNo" . "." . "$funcNo\n";
		}
		if (($PotentialFuncNo != -1) &&
		    $PotentialFuncNo != $funcNo + 1) {
		    next func;
		}

		# Parse function declaration, one-word function type
		($FuncType, $Space1, $Asterisks, $Space2, $FuncName, $Params) =
		/^extern\s+(\w+)(\s*)(\**)(\s*)(\w+)\s*\(([$ParamChars\,]+)\)/;

		if ($FuncType eq "") {
		    # Two-word function type.
		    ($FuncType, $Space1, $FuncType2, $Space2, $Asterisks,
		     $Space3, $FuncName, $Params) = 
      /^extern\s+(\w+)(\s+)(\w+)(\s*)(\**)(\s*)(\w+)\s*\(([$ParamChars\,]+)\)/;

		    $FuncType = $FuncType . " " . $FuncType2;
		}

		if ($Debug == 1) {
		    print STDOUT "$FuncType" . "." . "$FuncType2" . "." .
			"$Asterisks" . "." . "$Space3" . "." . "$FuncName"
			    . "." . "$Params";
		}

		if (!defined($Found{$FuncName})) {
		    # Use logical or-ing to record the treatment of this
		    # function.
		    # 0 : Candidate, i.e. it was found in the header file.
		    # 1 : Mentioned somewhere in the source file.
		    # 2 : Mentioned in Name: section.
		    # 4 : Mentioned in /*[FD].
		    # 8 : Treated.
		    $Found{$FuncName} = 0;
		    $FoundLocal{$FuncName} = 0;
		}

		if ((($Found{$FuncName} & 8) != 0) ||
		    (($FoundLocal{$FuncName} & 8) != 0)) {
		    # Already taken care of.
		    if ($Debug == 1) {
			print STDOUT "Already done with $FuncName.\n";
		    }

		    next func;
		}

		# Is this function mentioned in the source file?
		if ((($Found{$FuncName} & 1) == 0) &&
		    (grep(/[ *]+$FuncName\s*\(/, @SourceLines) == 0)) {
		    $FoundLocal{$FuncName} |= 8;
		    if ($Debug == 1) {
			print STDOUT "Not in source file: $FuncName.\n";
		    }

		    next func;
		}
		$Found{$FuncName} |= 1;
		$FoundLocal{$FuncName} |= 1; 
		
		# Function mentioned in "/*[FD]"?
		if ((($Found{$FuncName} & 4) == 0) &&
		    (grep(/^\/\*[FD]:$FuncName[\*=]/, @SourceLines) == 0)) {
		    if ($Debug == 1) {
			print STDOUT "Not in /*[FD]: $FuncName.\n";
		    }

		    next func;
		}
		$Found{$FuncName} |= 4;
		$FoundLocal{$FuncName} |= 4;
		
		if ($Debug == 1) {
		    print STDOUT "$FuncType" . "." . "$Asterisks" . "." . 
			"$FuncName" . "." . "$Params" . ".\n";
		}
		
		@FuncDecl = &MakeFuncDecl(0, $FuncType, $Asterisks,
					  $FuncName, $Params);
		
		$SyntaxLineNo++;
		($lineNo, $SyntaxLineNo, $StartLine, $StopLine, $JumpLabel,
		 @NameFuncs)
		    = &SyntaxLine($SourceLine, $SyntaxLineNo, $HeaderFile,
				$lineNo, $FuncName, $StartLine, $StopLine,
				$Debug, $#FuncDecl, $#NameFuncs,
				@FuncDecl, @NameFuncs);
		
		if ($JumpLabel == 0) {
		    print STDERR "Error!!!!!!!!!!!\n";
		}
		elsif ($JumpLabel == 1) {
		    # Start fresh on new source line
		    $StartLine = -1; $StopLine = -1;
		    $PotentialFuncNo = -1;
		    next line;
		}
		elsif ($JumpLabel == 2) {
		    # May just have found the start of a declaration
		    # Remember present function and check next lines for
		    # end of declaration
		    if ($Debug == 1) {print STDOUT "$funcNo\n";}
		    $PotentialFuncNo = $funcNo+1;
		    next line;
		}
		elsif ($JumpLabel == 3) {
		    # Continuation line
		    next line;
		}
		elsif ($JumpLabel == 4) {
		    # Parameter
		    next line;
		}
		elsif ($JumpLabel == 5) {
		    # K&R function parameter
		    next line;
		}
		elsif ($JumpLabel == 6) {
		    # Present function not found, try next
		    $PotentialFuncNo = -1;
		    $SourceLine = @SourceLines[$lineNo];

		    next func;
		}
		elsif ($JumpLabel == 7) {
		    # Just finished a declaration. Start fresh with next line.
		    $PotentialFuncNo = -1;
		    $lineNo = $StopLine;
		    $StartLine = -1; $StopLine = -1;
		    if ($SyntaxLineNo == -1) {$ManDescLineNo = -1;}

		    next line;
		}
		elsif ($JumpLabel == 8) {
		    # End of Syntax: section
		    # Insert remaining function declarations.

		    $fNo = $#Funcs;
		  remaining:  while (($fNo >= 0) && ($F = $Funcs[$fNo--])) {

		      ($FuncType, $Asterisks, $FuncName, $Params) = 
		    $F =~
		    /^extern\s+(\w+)\s*(\**)\s*(\w+)\s*\(([$ParamChars\,]+)\)/;

		      if (($FoundLocal{$FuncName} & 2) != 0 &&
			  ($FoundLocal{$FuncName} & 8) == 0) {
			  # In Name: section, but not treated.

			  @FDecl = &MakeFuncDecl(0, $FuncType, $Asterisks,
						    $FuncName, $Params);

			  if ($SourceLines[$lineNo-1] =~ m/^\s+\|*$/) {
			      splice(@SourceLines, $lineNo, 0, @FDecl,
				     "                |\n");
			      $lineNo += $#FDecl + 1 + 1;
			  } else {
			      splice(@SourceLines, $lineNo, 0,
				     "                |\n",
				     @FDecl,
				     "                |\n");
			      $lineNo += $#FDecl + 1 + 2;
			  }

			  # Function has been treated
			  $Found{$FuncName} |= 8;
			  $FoundLocal{$FuncName} |= 8;
		      }
		  }

		    $SyntaxLineNo = -1;
		    $ManDescLineNo = -1;
		    
		    undef @NameFuncs;
		    
		    next line;
		}
	    } continue { # while func
	    } # continue func
	  } # Syntax part of manual page comment
      } # Inside manual page description
      
      next line;
  } continue { # while line

      $lineNo++;
  }
 
   
    $outFileName = "${ARGV}.$$";
    if ($Debug == 1) {print STDOUT "Open $outFileName\n";}
    open(OUTFILE, ">$outFileName") || die "Can't open file $outFileName.\n";
    print OUTFILE @SourceLines;
    close(OUTFILE);
    if ($Debug == 1) {print STDOUT "Closed $outFileName\n";}
    close(SOURCEFILE);
    if ($Debug == 1) {print STDOUT "Closed $ARGV\n";}
    
}				# sourceFile

&Report();
