########################################################################
##
## Copyright (C) 2026 The Octave Project Developers
##
## See the file COPYRIGHT.md in the top-level directory of this
## distribution or <https://octave.org/copyright/>.
##
## This file is part of Octave.
##
## Octave is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING.  If not, see
## <https://www.gnu.org/licenses/>.
##
########################################################################

## -*- texinfo -*-
## @deftypefn {} {@var{deps} =} __mcc_dependencies__ (@var{input_files})
## Analyze .m file dependencies and return list of all required files.
##
## This is an internal function used by @code{mcc}.
## @end deftypefn

function deps = __mcc_dependencies__ (input_files)

  deps = {};
  processed = {};
  to_process = input_files;

  while (! isempty (to_process))
    current_file = to_process{1};
    to_process(1) = [];

    ## Skip if already processed
    if (any (strcmp (processed, current_file)))
      continue;
    endif

    ## Add to processed list
    processed{end+1} = current_file;
    deps{end+1} = current_file;

    ## Read file and extract function calls
    try
      file_content = fileread (current_file);
      
      ## Extract function names from function calls
      ## Pattern: function_name( or function_name ( or function_name\n
      ## This is a simple regex - may need refinement
      tokens = regexp (file_content, 
                      '([a-zA-Z_][a-zA-Z0-9_]*)\s*\(', 
                      'tokens');
      
      if (isempty (tokens))
        continue;
      endif
      
      for i = 1:length (tokens)
        ## tokens{i} is a cell array containing the matched groups
        ## Each match returns a cell array with captured groups
        if (! iscell (tokens{i}) || isempty (tokens{i}))
          continue;
        endif
        
        ## Extract the first captured group (function name)
        ## tokens{i} is a 1x1 cell containing another cell with the match
        try
          func_name = tokens{i}{1};
          
          ## Validate function name is a string
          if (! ischar (func_name) || isempty (func_name))
            continue;
          endif
          
          ## Ensure func_name is a row vector for strcmp
          func_name = func_name(:).';
          
          ## Skip built-in functions and operators
          builtin_list = {"if", "for", "while", "switch", "try", "catch",
                          "end", "else", "elseif", "case", "otherwise",
                          "return", "break", "continue", "function",
                          "endfunction", "endfor", "endwhile", "endif",
                          "endswitch", "endtry", "endclassdef", "endmethods",
                          "endproperties", "endevents", "endenumeration",
                          "true", "false", "pi", "e", "eps", "inf", "nan",
                          "i", "j", "realmax", "realmin"};
          if (any (strcmp (builtin_list, func_name)))
            continue;
          endif
        catch
          ## If there's any error extracting the function name, skip it
          continue;
        end_try_catch

        ## Try to find the function file
        func_file = which (func_name);
        
        if (! isempty (func_file) && exist (func_file, "file") == 2)
          ## Check if it's a .m file (not built-in)
          [~, ~, ext] = fileparts (func_file);
          if (strcmp (ext, ".m") || strcmp (ext, ".mex"))
            ## Check if it's not already in our list
            if (! any (strcmp (processed, func_file)) && 
                ! any (strcmp (to_process, func_file)))
              to_process{end+1} = func_file;
            endif
          endif
        endif
      endfor

    catch err
      ## If we can't read the file, just continue
      warning ("__mcc_dependencies__: could not analyze file '%s': %s",
               current_file, err.message);
    end_try_catch
  endwhile

endfunction






