function [filesToInstrument, instrumentationUpToDate] = getFilesToInstrument...
    (buildInfo, filterReadOnlyFolders, lInstrPrefix, ...
    lOriginalBuildFolder)
% getFilesToInstrument identifies files that must be instrumented

%   Copyright 2009-2019 The MathWorks, Inc.

    
buildInfo.updateFilePathsAndExtensions;
concatenatePaths = true; replaceMatlabRoot = true;
[filesToInstrument, buildInfoGroup] = buildInfo.getSourceFiles...
    (concatenatePaths, replaceMatlabRoot);

% In some cases, the file separator for source file paths returned from
% buildInfo may vary (either \ or /) from one build to the next: ensure
% that file names are in a canonical form.
for i=1:length(filesToInstrument)
    filesToInstrument{i} = builtin('_canonicalizepath', filesToInstrument{i});
end

% Filter out files that may include platform specific or device driver code
% and should not be instrumented
keepIdx = ~strcmp(buildInfoGroup, 'SkipForSil');
filesToInstrument = filesToInstrument(keepIdx);

filesToInstrument = ...
    i_filterFilesToInstrument(filesToInstrument);

instrumentationUpToDate = false(size(filesToInstrument));

checkSumsStored = i_getChecksumsStored(lOriginalBuildFolder, lInstrPrefix);

if ~isempty(checkSumsStored.keys)
    
    checkSumsActual = coder.coverage.getInstrFileChecksums(filesToInstrument);
    
    for i=1:length(instrumentationUpToDate)
        key = filesToInstrument{i};
        
        if checkSumsStored.isKey(key) ...
                && isequal...
                (checkSumsStored(key), checkSumsActual(key))
            
            instrumentationUpToDate(i) = true;
        end
    end
end
if filterReadOnlyFolders
    allFolders = cell(size(filesToInstrument));
    for i=1:length(filesToInstrument)
        allFolders{i} = fileparts(filesToInstrument{i});
    end
    [folders, ~, idx] = unique(allFolders);
    folderReadOnly = false(size(folders));
    for i=1:length(folders)
        folderReadOnly(i) = i_isFolderReadOnly(folders{i});
    end
    folderReadOnly = folderReadOnly(idx);
    filesToInstrument = filesToInstrument(~folderReadOnly);
    instrumentationUpToDate = instrumentationUpToDate(~folderReadOnly);
end


function filesOut = i_filterFilesToInstrument(filesIn)

% Filter out files under the MATLAB install folder
mRoot=coder.make.internal.transformPaths(matlabroot);
keepIdx = true(size(filesIn));
for i=1:length(keepIdx)
    if strncmp(coder.make.internal.transformPaths(fullfile(filesIn{i})), mRoot, length(mRoot))
        keepIdx(i)=false;
    end
end
filesOut = filesIn(keepIdx);



function readOnly = i_isFolderReadOnly(folder)

[~, w] = fileattrib(folder);
readOnly = ~w.UserWrite;


function checkSumsStored = i_getChecksumsStored(folder, lInstrPrefix)

% Stored checksums
checkSumsStored = coder.coverage.CodeCoverageHook.coverageInfoFile...
    (folder, 'read', 'CodeChecksums');

% Stored value of instrumentation prefix
storedInstrPrefixBuildFolder = coder.coverage.CodeCoverageHook.coverageInfoFile...
    (folder, 'read', 'InstrumentationPrefix');

% With LDRA we have a different instrumentation prefix for SIL and PIL. If
% this has changed then the instrumentation is out of date.
if isempty(checkSumsStored) || ~strcmp(lInstrPrefix, storedInstrPrefixBuildFolder)
    % Force not up to date by clearing checksums
    checkSumsStored = containers.Map;
end
