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-2020 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)
      DAStudio.error('RTW:buildInfo: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'],...
                                                    h.Settings);
          frontIdx = frontIdx -1;
      else
          endPath(endIdx) = RTW.BuildInfoString(Paths{i},...
                                                Groups{i},...
                                                [type ' path'],...
                                                h.Settings);
          
          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);

  % the filesep is regexp'ed into the paths.  If it is'\' it needs
  % to be doubled because '\' is the regexp escape char.
  if strcmp(h.Settings.FileSep,'\')
      regexp_filesep = '\\';
  else
      regexp_filesep = h.Settings.FileSep;
  end
      
  % make sure all of the fileseps are the 'correct' one
  Paths = regexprep(Paths,'[\\/]',regexp_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).
  specialDirs = h.Settings.getSpecialDirsAndTokens();
  sDirs = regexptranslate('escape',specialDirs.dirs);
  
  % Look ahead assertion to match file separator or end of input text
  endOfPathExpr = "(?=\\|\/|$)";

  % g2177208: if matlabroot is "/MATLAB", do not replace paths like 
  % "/MATLAB workingFolder"
  sDirsExpr = string(sDirs)+endOfPathExpr;

  if ispc
      Paths = regexprep(Paths, sDirsExpr, specialDirs.toks,'ignorecase');
  else
      Paths = regexprep(Paths, sDirsExpr, specialDirs.toks);
  end
