31#if defined (HAVE_CONFIG_H)
55#if defined (OCTAVE_USE_WINDOWS_API)
56# define WIN32_LEAN_AND_MEAN 1
62#define IS_DEVICE_SEP(ch) octave::sys::file_ops::is_dev_sep (ch)
63#define NAME_BEGINS_WITH_DEVICE(name) \
64 (name.length () > 0 && IS_DEVICE_SEP ((name)[1]))
66#define DIR_SEP_STRING octave::sys::file_ops::dir_sep_str ()
67#define IS_DIR_SEP(ch) octave::sys::file_ops::is_dir_sep (ch)
69#define ENV_SEP octave::directory_path::path_sep_char ()
70#define ENV_SEP_STRING octave::directory_path::path_sep_str ()
71#define IS_ENV_SEP(ch) octave::directory_path::is_path_sep (ch)
74#define OCTAVE_KPSE_DEBUG 0
78kpse_path_iterator::set_end ()
85 m_b = m_e = std::string::npos;
89 while (m_e < m_len && ! octave::directory_path::is_path_sep (m_path[m_e]))
95kpse_path_iterator::next ()
100 while (m_b < m_len && octave::directory_path::is_path_sep (m_path[m_b]))
104 m_b = m_e = std::string::npos;
112kpse_truncate_filename (
const std::string& name)
115 unsigned ret_len = 0;
117 std::string ret = name;
119 std::size_t m_len = name.length ();
121 for (std::size_t i = 0; i < m_len; i++)
128 else if (c_len > octave::sys::dir_entry::max_name_length ())
135 ret[ret_len++] = name[i];
139 ret.resize (ret_len);
149READABLE (
const std::string& fn)
151#if defined (OCTAVE_USE_WINDOWS_API)
153 std::wstring w_fn = octave::sys::u8_to_wstring (fn);
155 DWORD f_attr = GetFileAttributesW (w_fn.c_str ());
157 return (f_attr != 0xFFFFFFFF && ! (f_attr & FILE_ATTRIBUTE_DIRECTORY));
163 const char *t = fn.c_str ();
167 octave::sys::file_stat fs (fn);
169 retval = fs && ! fs.is_dir ();
184kpse_readable_file (
const std::string& name)
192#if defined (ENAMETOOLONG)
194 else if (errno == ENAMETOOLONG)
196 ret = kpse_truncate_filename (name);
201 if (! READABLE (ret))
215 perror (name.c_str ());
225kpse_absolute_p (
const std::string& filename,
int relative_ok)
227 return (octave::sys::env::absolute_pathname (filename)
229 && octave::sys::env::rooted_relative_pathname (filename)));
237static bool first_search =
true;
242log_search (
const std::list<std::string>& filenames)
244 for (
const auto& filename : filenames)
246 octave::sys::time now;
247 std::cerr << now.unix_time () <<
' ' << filename << std::endl;
262static std::list<std::string>
263dir_search (
const std::string& dir,
const std::string& name,
266 std::list<std::string> ret;
268 std::string potential = dir + name;
270 std::string tmp = kpse_readable_file (potential);
274 ret.push_back (potential);
286static std::list<std::string>
287absolute_search (
const std::string& name)
289 std::list<std::string> ret_list;
290 std::string found = kpse_readable_file (name);
294 ret_list.push_back (found);
302static std::list<std::string>
303path_search (
const std::string& path,
const std::string& name,
bool all)
305 std::list<std::string> ret_list;
310 std::string elt = *pi;
312 std::list<std::string> found;
317 while (elt.length () > 3
322 elt = elt.substr (1);
325#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
326 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
330 while (elt.length () > 1
332 elt = elt.substr (1);
338 found = std::list<std::string> ();
346 found = dir_search (dir, name, all);
350 if (! found.empty ())
353 ret_list.splice (ret_list.end (), found);
356 ret_list.push_back (found.front ());
370kpse_tilde_expand (
const std::string& name)
372 std::string expansion;
375 if (name.empty () || name[0] !=
'~')
382 else if (name.length () == 1)
384 expansion = octave::sys::env::get_home_directory ();
386 if (expansion.empty ())
395 std::string home = octave::sys::env::get_home_directory ();
400 std::size_t home_len = home.length ();
402#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
403 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
406 home = home.substr (1);
413 expansion = home + name.substr (c);
418#if defined (HAVE_PWD_H)
423 while (name.length () > c && !
IS_DIR_SEP (name[c]))
426 std::string user = name.substr (1, c-1);
430 octave::sys::password p = octave::sys::password::getpwnam (user);
433 std::string home = (p ? p.dir () :
".");
438# if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
439 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
442 home = home.substr (1);
446 if (name.length () > c &&
IS_DIR_SEP (home.back ()))
449 expansion = (name.length () > c ? home : home + name.substr (c));
465static std::list<std::string>
466search (
const std::string& path,
const std::string& original_name,
bool all)
468 std::list<std::string> ret_list;
472 std::string name = kpse_tilde_expand (original_name);
476 absolute_p = kpse_absolute_p (name,
true);
479 std::cerr <<
"kpse: start search (file=" << name
480 <<
", find_all=" << all <<
", path=" << path <<
")." << std::endl;
484 ret_list = (absolute_p ? absolute_search (name)
485 : path_search (path, name, all));
491 first_search =
false;
497 std::cerr <<
"kpse: search (" << original_name <<
") =>";
498 log_search (ret_list);
499 std::cerr << std::endl;
522 std::list<std::string> ret_list = search (path, name,
false);
524 return ret_list.empty () ?
"" : ret_list.front ();
530std::list<std::string>
533 return search (path, name,
true);
540std::list<std::string>
542 const std::list<std::string>& names,
bool all)
544 std::list<std::string> ret_list;
549 std::string elt = *pi;
552 std::list<std::string> found;
557 while (elt.length () > 3
562 elt = elt.substr (1);
565#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
566 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
570 while (elt.length () > 1
572 elt = elt.substr (1);
581 for (
auto it = names.cbegin (); it != names.cend () && ! done; it++)
583 std::string name = *it;
588 found = std::list<std::string> ();
592 found = dir_search (dir, name, all);
595 if (! found.empty ())
598 ret_list.splice (ret_list.end (), found);
601 ret_list.push_back (found.front ());
612static std::list<std::string>
613find_first_of (
const std::string& path,
const std::list<std::string>& names,
616 std::list<std::string> ret_list;
619 std::cerr <<
"kpse: start find_first_of (";
621 for (
auto p = names.cbegin (); p != names.cend (); p++)
623 if (p == names.cbegin ())
626 std::cerr <<
", " << *p;
629 std::cerr <<
"), path=" << path <<
'.' << std::endl;
632 for (
const auto& name : names)
634 if (kpse_absolute_p (name,
true))
638 ret_list = absolute_search (name);
640 if (! ret_list.empty ())
652 first_search =
false;
659 std::cerr <<
"kpse: find_first_of (";
661 for (
auto p = names.cbegin (); p != names.cend (); p++)
663 if (p == names.cbegin ())
666 std::cerr <<
", " << *p;
671 log_search (ret_list);
673 std::cerr << std::endl;
685 const std::list<std::string>& names)
687 std::list<std::string> ret_list = find_first_of (path, names,
false);
689 return ret_list.empty () ?
"" : ret_list.front ();
699std::list<std::string>
701 const std::list<std::string>& names)
703 return find_first_of (path, names,
true);
719 std::string elt = kpse_tilde_expand (*pi);
726 while (elt.length () > 3
731 elt = elt.substr (1);
734#if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
735 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
739 while (elt.length () > 1
741 elt = elt.substr (1);
749 std::size_t dirlen = dir.length ();
780#define brace_whitespace(c) (! (c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
795static std::list<std::string>
796array_concat (
const std::list<std::string>& arr1,
797 const std::list<std::string>& arr2)
799 std::list<std::string> result;
803 else if (arr2.empty ())
807 for (
const auto& elt_2 : arr2)
808 for (
const auto& elt_1 : arr1)
809 result.push_back (elt_1 + elt_2);
815static int brace_gobbler (
const std::string&,
int&,
int);
816static std::list<std::string> expand_amble (
const std::string&);
819static std::list<std::string>
820brace_expand (
const std::string& text)
824 int c = brace_gobbler (text, i,
'{');
826 std::string preamble = text.substr (0, i);
828 std::list<std::string> result (1, preamble);
834 c = brace_gobbler (text, i,
'}');
839 (*current_liboctave_warning_with_id_handler)
840 (
"Octave:pathsearch-syntax",
841 "%s: Unmatched {", text.c_str ());
843 result = std::list<std::string> (1, text);
847 std::string amble = text.substr (start, i-start);
848 result = array_concat (result, expand_amble (amble));
850 std::string postamble = text.substr (i+1);
851 result = array_concat (result, brace_expand (postamble));
859static int brace_arg_separator =
',';
864static std::list<std::string>
865expand_amble (
const std::string& text)
867 std::list<std::string> result;
869 std::size_t text_len = text.length ();
873 for (start = 0, i = 0, c = 1; c && start < text_len; start = ++i)
876 int c0 = brace_gobbler (text, i0, brace_arg_separator);
878 int c1 = brace_gobbler (text, i1,
ENV_SEP);
880 i = (i0 < i1 ? i0 : i1);
882 std::string tem = text.substr (start, i-start);
884 std::list<std::string> partial = brace_expand (tem);
889 result.splice (result.end (), partial);
900brace_gobbler (
const std::string& text,
int& indx,
int satisfy)
907 std::size_t text_len = text.length ();
909 std::size_t i = indx;
911 for (; i < text_len; i++)
923 if (c ==
'\\' && (quoted == 0 || quoted ==
'"' || quoted ==
'`'))
936 if (c ==
'"' || c ==
'\'' || c ==
'`')
942 if (c == satisfy && ! level && ! quoted)
954 if ((c !=
'{') || i == 0 || (text[i-1] !=
'$'))
960 else if (c ==
'}' && level)
965 c = (c == satisfy) ? c : 0;
985 if (octave::sys::dir_exists (elt))
989 char last_char = ret.back ();
std::string kpse_path_find_first_of(const std::string &path, const std::list< std::string > &names)
#define NAME_BEGINS_WITH_DEVICE(name)
std::string kpse_element_dir(const std::string &elt)
std::string kpse_path_expand(const std::string &path)
std::list< std::string > kpse_all_path_find_first_of(const std::string &path, const std::list< std::string > &names)
std::list< std::string > kpse_all_path_search(const std::string &path, const std::string &name)
#define brace_whitespace(c)
std::list< std::string > path_find_first_of(const std::string &path, const std::list< std::string > &names, bool all)
#define IS_DEVICE_SEP(ch)
std::string kpse_path_search(const std::string &path, const std::string &name)
int octave_access_r_ok(void)
int octave_access_wrapper(const char *nm, int mode)