function addPaths(h, type, varargin)
%ADDPATHS - This adds a source path, or vector of SOURCE paths to
%the source vector.  Duplicates are removed from the input, as well as
%entries that are already in the vector.
    
% Copyright 2005-2023 The MathWorks, Inc.
  
  %check the args to make sure they all conform to the expected format
  [argsOK, paths, groups] = locCheckArgs(h,type, varargin{:});
  if ~(argsOK)
      error(message('coder_compile:CoderCompile:badMethodArguments',...
                     'RTW.BuildInfoBuildObj.addPaths'));
  end
  
  % the caller has nothing to insert, return
  if isempty(paths)
      return;
  end
  
  % if there are no entries currently in the vector, we can skip the code to
  % check for duplicate entries
  switch (type)
    case 'include'
      firstInsertion = isempty(h.Inc.Paths);
    case 'source'
      firstInsertion = isempty(h.Src.Paths);
    case 'syslib'
      firstInsertion = isempty(h.SysLib.Paths);
  end
  if (~firstInsertion)
      % if this is a single insertion, the vector optimized code below is very
      % inefficient because it must perform a ismember When there is only 1
      % entry, it is either in the list or not.  By using find and we can
      % speed up the check.
      if (length(paths) == 1)
          switch (type)
            case 'include'
              p = h.Inc.Paths.findobj('Value',paths{1});
            case 'source'
              p = h.Src.Paths.findobj('Value',paths{1});
            case 'syslib'
              p = h.SysLib.Paths.findobj('Value',paths{1});
          end
          % if the path already exists in the list, then just return, since
          % there is nothing to insert.
          if ~isempty(p)
              return;
          end
      else
          switch (type)
            case 'include'
              cur_paths = get(h.Inc.Paths, 'Value');
            case 'source'
              cur_paths = get(h.Src.Paths, 'Value');
            case 'syslib'
              cur_paths = get(h.SysLib.Paths, 'Value');
          end
          idx = ~ismember(paths,cur_paths);
          % reduce all of the input vectors to the subset of unique entries
          paths  = paths(idx);
          groups = groups(idx);
      end
  end

  % if all the insertions are duplicates, just return
  if isempty(paths)
      return;
  end
  
  cnt = length(paths);


  % some paths need to prepend the list.  check the group labels coming in and sort them accordingly.
  prependIdx = strcmp(groups,'MDLREF');
  frontIdx = sum(prependIdx);
  endIdx = cnt - frontIdx;
  
  frontPath = RTW.BuildInfoString.empty;
  endPath = RTW.BuildInfoString.empty;

  for i=cnt:-1:1
      if prependIdx(i)
          frontPath(frontIdx) = RTW.BuildInfoString(paths{i},...
                                                    groups{i},...
                                                    [type ' path']);
          frontIdx = frontIdx -1;
      else
          endPath(endIdx) = RTW.BuildInfoString(paths{i},...
                                                groups{i},...
                                                [type ' path']);
          
          endIdx = endIdx -1;
      end
  end
    
  % note that the newSrcPath must be transposed , because it is 1xN while
  % h.Src.Paths is Nx1
  switch (type)
    case 'include'
      h.Inc.Paths    = [frontPath'; h.Inc.Paths; endPath'];
    case 'source'
      h.Src.Paths    = [frontPath'; h.Src.Paths; endPath'];
    case 'syslib'
      h.SysLib.Paths = [frontPath'; h.SysLib.Paths; endPath'];
  end

%------------------------------------------------------------------------------
function [argsOK, paths, groups] = locCheckArgs(h, type, pathsIn, groupsIn)

  argsOK = true;
  paths = {};
  groups = {};
  
  % The group argument is optional
  if (nargin < 3) || (nargin > 4)
      argsOK = false;
      return;
  end

  % make sure the type was specified correctly
  if ischar(type)
      tf = strcmp(type,{'include', 'source','syslib'});
      if ~any(tf)
          argsOK = false;
          return;
      end
  else
      argsOK = false;
      return;
  end

  % all of the args must be cell arrays for the caller.  If a char array
  % or scalar is sent int, just convert them to cell arrays
  
  % the first arg is the path, if it is not a cell array of strings, make
  % sure it is a char array.
  if ischar(pathsIn)
      paths = {pathsIn};
  else
      if ~iscell(pathsIn)
          % this is an incompatible data type.
          argsOK = false;
          return;
      end
      paths  = pathsIn;
  end
  
  % we need the long version of the path, with all relative paths reduced
  paths = coder.make.internal.transformPaths(paths,'pathType','full','ignoreErrors',true);
  paths = RTW.reduceRelativePath(paths);

  % make sure all of the fileseps are the 'correct' one
  paths = regexprep(paths,'[\\/]',h.Settings.FileSep);

  if (nargin >= 4)
      % if the argument is not a cell array (i.e. a single value) create a
      % cell array the same length as paths and fill it with that value.
      if iscell(groupsIn)
          groups = groupsIn;
          % the paths and groups cell array must have the same length
          if (length(paths) ~= length(groups))
              argsOK = false;
              return;
          end
      else
          if ~ischar(groupsIn)
              argsOK = false;
              return;
          end
          groups(1:length(paths)) = {groupsIn};
      end
  else
      groups(1:length(paths)) = {''};
  end

  % remove empty paths and the corresponding groups
  idx = ~strcmp(paths, '');
  paths  = paths(idx);
  groups = groups(idx);
  
  % remove any duplicate entries if the list is longer than 1
  if (length(paths) > 1)
      % remove any duplicate entries.  Note that the call to RTW.unique will
      % remove the trailing filesep characters if they exist.
      [paths,idx] = RTW.unique(paths,'removetrailingfilesep');
      
      % reduce all of the input vectors to the subset of unique entries
      groups = groups(idx);

      % finally, check for empty paths.  If the path is empty, the whole
      % entry should be removed.
      idx = ~strcmp(paths, '');

      paths  = paths(idx);
      groups = groups(idx);
  end

  % the final thing needed is to replace special dirs with the tokens.  For
  % example: h.Settings.Matlabroot with $(MATLAB_ROOT).
  paths = h.Settings.tokenizePaths(paths);
      
  % Handle paths of the form $$(TOKEN)
  if coder.make.internal.featureOn('BuildInfoRootFolders')
      paths = coder.make.internal.processPathsForDoubleDollarSyntax(paths);
  end
