function lProbeSiteInfo = locateProbeSites(srcFiles, startStr, endStr, probeType)
%LOCATEPROBESITES locate probe sites identified by special comments

%   Copyright 2010-2015 The MathWorks, Inc.

    lProbeSites = struct('FileNameIdx', {}, 'TraceId', {}, ...
                         'StartFcnCharNo', {}, ...
                         'EndFcnCharNo', {} ...
                         );
                     
    lProbeTypes = {};

    % we should always have startStr
    assert(isequal(~length(startStr), 0), 'The 2ND argument is empty!');                     
                     
    pairwise = true;
    startEndExpr = sprintf('/\\*\\s+((%s)|(%s))\\s+(.*?)\\s+\\*/', ...
                           startStr, endStr);
    
    % check to see if we have end string
    if isequal(length(endStr), 0)
        % if we don't then we only regexp on the 'start' string
        startEndExpr = sprintf('/\\*\\s+(%s)\\s+(.*?)\\s+\\*/', ...
                               startStr);
        pairwise = false;
    end

    for i=1:length(srcFiles)
        srcFile = srcFiles{i};

        content = fileread(srcFile);
                
        [tokens, matchStart] = regexp...
            (content, startEndExpr, 'tokens');
        
        lineNumIdx = regexp(content, '\n');
        
        % Match corresponding start of block and end of block locations
        startEndComments = cell(size(tokens));
        idExpr = cell(size(tokens));
        for ii4=1:length(tokens)
            startEndComments{ii4} = tokens{ii4}{1};
            idExpr{ii4} = tokens{ii4}{2};
        end
        
        [idUnique, ~, ic] = unique(idExpr);

        if ~isempty(startEndComments)
            % Pre-allocate struct array
            lBase = length(lProbeSites);
            lProbeSites(end+length(idUnique)).FileNameIdx = [];          
            
            % Pre-allocate probe types cell array
            lProbeTypes(end+length(idUnique)) = {''}; %#ok
        end
        
        for ii1=1:length(idUnique) 
            idx = find(ic==ii1);
            idxStart_ = strcmp(startEndComments(idx), ...
                               startStr);
            idxStart = idx(idxStart_);
            
            % only do check for matched probe sites if we have
            % passed both, start and end name probes
            if pairwise 
                idxEnd = idx(~idxStart_);
                if length(idxEnd)~=1 || length(idxStart)~=1
                    DAStudio.error...
                        ('CoderProfile:ExecutionTime:UnmatchedProbeSites', ...
                         srcFile, idExpr{ii1});
                end
            end
            lProbeSites(lBase+ii1).FileNameIdx=i;
            lProbeSites(lBase+ii1).TraceId = ii1;
            lProbeSites(lBase+ii1).StartFcnCharNo = matchStart(idxStart);
            lProbeSites(lBase+ii1).StartLineNo =...
                find(lineNumIdx > lProbeSites(lBase+ii1).StartFcnCharNo, 1);
            if pairwise
                lProbeSites(lBase+ii1).EndFcnCharNo = matchStart(idxEnd);
                lProbeSites(lBase+ii1).EndLineNo =...
                    find(lineNumIdx > lProbeSites(lBase+ii1).EndFcnCharNo, 1);

            end
            lProbeTypes(lBase+ii1) = {probeType}; %#ok<AGROW>
        end
        
    end
    
    lModelTraceInfo = struct('CodeName', idUnique, ...
                             'CallSiteSids', cell(size(idUnique)), ...
                             'CallSiteNames', cell(size(idUnique)));
    
    lProbeSiteInfo.ModelTraceInfo = lModelTraceInfo;
    lProbeSiteInfo.FileNames = srcFiles;
    lProbeSiteInfo.ProbeSites = lProbeSites;
    lProbeSiteInfo.DeclarationsSite = [];
    lProbeSiteInfo.ProbeTypes = lProbeTypes;
