31 #if defined (HAVE_CONFIG_H)
55 #if defined (OCTAVE_USE_WINDOWS_API)
56 # define WIN32_LEAN_AND_MEAN 1
63 #define IS_DEVICE_SEP(ch) octave::sys::file_ops::is_dev_sep (ch)
64 #define NAME_BEGINS_WITH_DEVICE(name) \
65 (name.length () > 0 && IS_DEVICE_SEP ((name)[1]))
67 #define DIR_SEP_STRING octave::sys::file_ops::dir_sep_str ()
68 #define IS_DIR_SEP(ch) octave::sys::file_ops::is_dir_sep (ch)
70 #define ENV_SEP octave::directory_path::path_sep_char ()
71 #define ENV_SEP_STRING octave::directory_path::path_sep_str ()
72 #define IS_ENV_SEP(ch) octave::directory_path::is_path_sep (ch)
75 #if ! defined (NO_DEBUG)
81 # define KPSE_DEBUG_P(bit) (kpse_debug & (1 << (bit)))
83 # define KPSE_DEBUG_STAT 0
84 # define KPSE_DEBUG_EXPAND 1
85 # define KPSE_DEBUG_SEARCH 2
86 # define KPSE_DEBUG_VARS 3
87 # define KPSE_LAST_DEBUG KPSE_DEBUG_VARS
94 kpse_path_iterator::set_end ()
100 else if (m_e > m_len)
101 m_b = m_e = std::string::npos;
107 while (m_e < m_len && ! octave::directory_path::is_path_sep (m_path[m_e]))
113 kpse_path_iterator::next ()
118 while (m_b < m_len && octave::directory_path::is_path_sep (m_path[m_b]))
122 m_b = m_e = std::string::npos;
131 kpse_truncate_filename (
const std::string& name)
134 unsigned ret_len = 0;
136 std::string ret = name;
138 std::size_t m_len = name.length ();
140 for (std::size_t i = 0; i < m_len; i++)
147 else if (c_len > octave::sys::dir_entry::max_name_length ())
154 ret[ret_len++] = name[i];
158 ret.resize (ret_len);
169 READABLE (
const std::string& fn)
171 #if defined (OCTAVE_USE_WINDOWS_API)
175 DWORD f_attr = GetFileAttributesW (w_fn.c_str ());
177 return (f_attr != 0xFFFFFFFF && ! (f_attr & FILE_ATTRIBUTE_DIRECTORY));
183 const char *t = fn.c_str ();
187 octave::sys::file_stat fs (fn);
189 retval = fs && ! fs.is_dir ();
204 kpse_readable_file (
const std::string& name)
212 #if defined (ENAMETOOLONG)
214 else if (errno == ENAMETOOLONG)
216 ret = kpse_truncate_filename (name);
221 if (! READABLE (ret))
235 perror (name.c_str ());
245 kpse_absolute_p (
const std::string& filename,
int relative_ok)
247 return (octave::sys::env::absolute_pathname (filename)
249 && octave::sys::env::rooted_relative_pathname (filename)));
258 static bool first_search =
true;
263 log_search (
const std::list<std::string>& filenames)
267 for (
const auto& filename : filenames)
269 octave::sys::time now;
270 std::cerr << now.unix_time () <<
' ' << filename << std::endl;
285 static std::list<std::string>
286 dir_search (
const std::string& dir,
const std::string& name,
289 std::list<std::string> ret;
291 std::string potential = dir + name;
293 std::string tmp = kpse_readable_file (potential);
297 ret.push_back (potential);
309 static std::list<std::string>
310 absolute_search (
const std::string& name)
312 std::list<std::string> ret_list;
313 std::string found = kpse_readable_file (name);
317 ret_list.push_back (found);
325 static std::list<std::string>
326 path_search (
const std::string& path,
const std::string& name,
bool all)
328 std::list<std::string> ret_list;
333 std::string elt = *pi;
335 std::list<std::string> found;
340 while (elt.length () > 3
345 elt = elt.substr (1);
348 #if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
349 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
353 while (elt.length () > 1
355 elt = elt.substr (1);
362 found = std::list<std::string> ();
371 found = dir_search (dir, name, all);
375 if (! found.empty ())
378 ret_list.splice (ret_list.end (), found);
381 ret_list.push_back (found.front ());
395 kpse_tilde_expand (
const std::string& name)
397 std::string expansion;
400 if (name.empty () || name[0] !=
'~')
408 else if (name.length () == 1)
410 expansion = octave::sys::env::get_home_directory ();
412 if (expansion.empty ())
421 std::string home = octave::sys::env::get_home_directory ();
426 std::size_t home_len = home.length ();
428 #if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
429 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
432 home = home.substr (1);
439 expansion = home + name.substr (c);
445 #if defined (HAVE_PWD_H)
450 while (name.length () > c && !
IS_DIR_SEP (name[c]))
453 std::string user = name.substr (1, c-1);
457 octave::sys::password p = octave::sys::password::getpwnam (user);
460 std::string home = (p ? p.dir () :
".");
465 # if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
466 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
469 home = home.substr (1);
473 if (name.length () > c &&
IS_DIR_SEP (home.back ()))
476 expansion = (name.length () > c ? home : home + name.substr (c));
493 static std::list<std::string>
494 search (
const std::string& path,
const std::string& original_name,
497 std::list<std::string> ret_list;
501 std::string name = kpse_tilde_expand (original_name);
505 absolute_p = kpse_absolute_p (name,
true);
508 std::cerr <<
"kdebug: start search (file=" << name
509 <<
", find_all=" << all <<
", path=" << path <<
")."
513 ret_list = (absolute_p
514 ? absolute_search (name)
515 : path_search (path, name, all));
521 first_search =
false;
529 std::cerr <<
"kdebug: search (" << original_name <<
") =>";
531 log_search (ret_list);
534 std::cerr << std::endl;
557 std::list<std::string> ret_list = search (path, name,
false);
559 return ret_list.empty () ?
"" : ret_list.front ();
565 std::list<std::string>
568 return search (path, name,
true);
575 std::list<std::string>
577 const std::list<std::string>& names,
bool all)
579 std::list<std::string> ret_list;
584 std::string elt = *pi;
587 std::list<std::string> found;
593 while (elt.length () > 3
598 elt = elt.substr (1);
601 #if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
602 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
606 while (elt.length () > 1
608 elt = elt.substr (1);
617 for (
auto it = names.cbegin (); it != names.cend () && ! done; it++)
619 std::string name = *it;
624 found = std::list<std::string> ();
629 found = dir_search (dir, name, all);
632 if (! found.empty ())
635 ret_list.splice (ret_list.end (), found);
638 ret_list.push_back (found.front ());
649 static std::list<std::string>
650 find_first_of (
const std::string& path,
const std::list<std::string>& names,
653 std::list<std::string> ret_list;
657 std::cerr <<
"kdebug: start find_first_of (";
659 for (
auto p = names.cbegin (); p != names.cend (); p++)
661 if (p == names.cbegin ())
664 std::cerr <<
", " << *p;
667 std::cerr <<
"), path=" << path <<
'.' << std::endl;
670 for (
const auto& name : names)
672 if (kpse_absolute_p (name,
true))
678 ret_list = absolute_search (name);
680 if (! ret_list.empty ())
692 first_search =
false;
701 std::cerr <<
"kdebug: find_first_of (";
703 for (
auto p = names.cbegin (); p != names.cend (); p++)
705 if (p == names.cbegin ())
708 std::cerr <<
", " << *p;
714 log_search (ret_list);
717 std::cerr << std::endl;
731 const std::list<std::string>& names)
733 std::list<std::string> ret_list = find_first_of (path, names,
false);
735 return ret_list.empty () ?
"" : ret_list.front ();
745 std::list<std::string>
747 const std::list<std::string>& names)
749 return find_first_of (path, names,
true);
765 std::string elt = kpse_tilde_expand (*pi);
772 while (elt.length () > 3
777 elt = elt.substr (1);
780 #if (! defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
781 && ! defined (DOUBLE_SLASH_IS_DISTINCT_ROOT))
785 while (elt.length () > 1
787 elt = elt.substr (1);
795 std::size_t dirlen = dir.length ();
826 #define brace_whitespace(c) (! (c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
842 static std::list<std::string>
843 array_concat (
const std::list<std::string>& arr1,
844 const std::list<std::string>& arr2)
846 std::list<std::string> result;
850 else if (arr2.empty ())
854 for (
const auto& elt_2 : arr2)
855 for (
const auto& elt_1 : arr1)
856 result.push_back (elt_1 + elt_2);
862 static int brace_gobbler (
const std::string&,
int&,
int);
863 static std::list<std::string> expand_amble (
const std::string&);
866 static std::list<std::string>
867 brace_expand (
const std::string&
text)
871 int c = brace_gobbler (
text, i,
'{');
873 std::string preamble =
text.substr (0, i);
875 std::list<std::string> result (1, preamble);
881 c = brace_gobbler (
text, i,
'}');
886 (*current_liboctave_warning_with_id_handler)
887 (
"Octave:pathsearch-syntax",
888 "%s: Unmatched {",
text.c_str ());
890 result = std::list<std::string> (1,
text);
894 std::string amble =
text.substr (start, i-start);
895 result = array_concat (result, expand_amble (amble));
897 std::string postamble =
text.substr (i+1);
898 result = array_concat (result, brace_expand (postamble));
906 static int brace_arg_separator =
',';
912 static std::list<std::string>
913 expand_amble (
const std::string&
text)
915 std::list<std::string> result;
917 std::size_t text_len =
text.length ();
921 for (start = 0, i = 0, c = 1; c && start < text_len; start = ++i)
924 int c0 = brace_gobbler (
text, i0, brace_arg_separator);
928 i = (i0 < i1 ? i0 : i1);
930 std::string tem =
text.substr (start, i-start);
932 std::list<std::string> partial = brace_expand (tem);
937 result.splice (result.end (), partial);
948 brace_gobbler (
const std::string&
text,
int& indx,
int satisfy)
955 std::size_t text_len =
text.length ();
957 std::size_t i = indx;
959 for (; i < text_len; i++)
971 if (c ==
'\\' && (quoted == 0 || quoted ==
'"' || quoted ==
'`'))
984 if (c ==
'"' || c ==
'\'' || c ==
'`')
990 if (c == satisfy && ! level && ! quoted)
1002 if ((c !=
'{') || i == 0 || (
text[i-1] !=
'$'))
1008 else if (c ==
'}' && level)
1013 c = (c == satisfy) ? c : 0;
1037 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)
#define KPSE_DEBUG_SEARCH
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 KPSE_DEBUG_P(bit)
#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)
bool dir_exists(const std::string &dirname)
std::wstring u8_to_wstring(const std::string &utf8_string)
int octave_access_r_ok(void)
int octave_access_wrapper(const char *nm, int mode)