// Reconcile DEP-5 debian/copyright to licensecheck report on source tree
//
// Copyright : 2024-2026 P Blackman
// License   : BSD-2-clause
//
// Exclude files, folders and licenses likely to lead to false positives

unit exclude;
{$mode delphi}

interface

function IgnoreFile (Fname : AnsiString) : Boolean;
function CheckAlias (Dep5, Actual : String) : Boolean;
procedure LoadExcludes;


implementation uses Classes, StrUtils, SysUtils, Support, Options;
{$warn 6058 off} // Don't need to hear about inlining issues

const GenConfig  : String = '/usr/share/lrc/lrc.config';    // General exclusions
      LocConfig  : String = 'debian/lrc.config';           // Specific to package
      AliasSep   : Char = '|';

var
    ExcludedFiles,
    ExcludedDirs,
    LicenseAlias : tStringList;


function CheckForAlias (Line : String) : Boolean;
var Pos : Integer;
    AName,
    Avalue : String;
begin
    Pos := PosEx (AliasSep, Line, 2);
    if Pos > 0 then
    begin
        AName  := Trim (LeftStr (Line, Pos-1));
        AValue := Trim (MidStr  (Line, Pos+1, 255));

        CheckForAlias := True;
        LicenseAlias.AddPair (AName, AValue);
    end
    else
        CheckForAlias := False;
end;

procedure LoadFile (var Files, Dirs : tStringList; var MyFile : text);
var Line : String;
begin
    while NOT EOF (MyFile) do
    begin
        ReadLn (MyFile, Line);

        if length (Line) = 0 then
            // Empty line
        else
        if Line[1] < Chr(20) then
            // Blank line
        else
        if Line[1]  = '#' then
            // Comment
        else
        if Line[1]  = '-' then
            CheckParam (Line)   // Command Line Option
        else
        begin
            if Line[Length(Line)] = '/' then
                Dirs.Add (Line)
            else
            if not CheckForAlias (Line) then
                Files.Add (Line)
        end;
    end;
end;

procedure LoadExcludes;
var MyFile : text;
begin
    ExcludedFiles := tStringList.Create;
    ExcludedDirs  := tStringList.Create;
    LicenseAlias  := tStringList.Create;

    LicenseAlias.NameValueSeparator := AliasSep;

    if OpenFile (GenConfig, MyFile) then
    begin
        LoadFile (ExcludedFiles, ExcludedDirs, MyFile);
        Close (MyFile);
    end
    else
        Writeln ('  Failed to open ', GenConfig);

    if OpenFile (LocConfig, MyFile) then
    begin
        LoadFile (ExcludedFiles, ExcludedDirs, MyFile);
        Close (MyFile);
    end;
end;

// Check if the end of the path name matches an exclusion
function CheckDirs (Path : AnsiString) : Boolean;
var Dir : Integer;
begin
    Dir := 0;
    result := False;

    while NOT result and (Dir < ExcludedDirs.Count) do
    begin
        result := EndsText (ExcludedDirs[Dir], Path);
        inc (Dir);
    end;
end;

// Check if beginning of file name matches an exclusion
function CheckFiles (FullName : AnsiString) : Boolean;
var FileNum : Integer;
begin
    FileNum := 0;
    result := False;

    while NOT result and (FileNum < ExcludedFiles.Count) do
    begin
        result := StartsText (ExcludedFiles[FileNum], FullName);

        if ContainsStr (FullName, '/') then
            // Maybe a sub-directory
            result := result or EndsText (ExcludedFiles[FileNum], FullName);

        inc (FileNum);
    end;
end;

function CheckAlias (Dep5, Actual : String) : Boolean;
var MyIndex : Integer;
begin
    CheckAlias := False;
    MyIndex := LicenseAlias.IndexOfName (Dep5);

    if MyIndex <> -1 then
        if Actual = LicenseAlias.ValueFromIndex [MyIndex] then
            CheckAlias := True;
end;

function IgnoreFile (Fname : AnsiString) : Boolean;
var FullName, Path : AnsiString;
begin
    FullName := ExtractFileName (Fname);
    Path     := ExtractFilePath (Fname);

    // Check file names with or without the path
    result := CheckDirs (Path) or CheckFiles (FullName) or CheckFiles (FName);
end;

end.
