29 #if defined (HAVE_CONFIG_H)
42 #if defined (DOS) || defined (OS2) || defined (WIN32) || defined (__MSDOS__)
47 #define MONOCASE_FILENAMES
51 #if defined (__MINGW32__)
83 #if defined (__DJGPP__) || ! defined (DOSISH)
85 #define ST_NLINK_TRICK
89 #define access ln_access
90 #define fopen ln_fopen
91 #define rename ln_rename
104 #define DIR_SEP_STRING "/"
105 #define IS_DEVICE_SEP(ch) ((ch) == ':')
106 #define NAME_BEGINS_WITH_DEVICE(name) ((name.length ()>0) && IS_DEVICE_SEP((name)[1]))
108 #define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
111 #define DIR_SEP_STRING "/"
116 #define IS_DIR_SEP(ch) ((ch) == DIR_SEP)
118 #ifndef IS_DEVICE_SEP
119 #define IS_DEVICE_SEP(ch) 0
121 #ifndef NAME_BEGINS_WITH_DEVICE
122 #define NAME_BEGINS_WITH_DEVICE(name) 0
139 #include <sys/types.h>
151 #ifndef _POSIX_NAME_MAX
152 #define _POSIX_NAME_MAX 255
156 #define NAME_MAX _POSIX_NAME_MAX
163 #if defined (SEPCHAR) && defined (SEPCHAR_STR)
164 #define ENV_SEP SEPCHAR
165 #define ENV_SEP_STRING SEPCHAR_STR
166 #elif defined (DOSISH)
168 #define ENV_SEP_STRING ";"
171 #define ENV_SEP_STRING ":"
176 #define IS_ENV_SEP(ch) ((ch) == ENV_SEP)
186 #ifndef _POSIX_PATH_MAX
187 #define _POSIX_PATH_MAX 255
192 #define PATH_MAX MAXPATHLEN
194 #define PATH_MAX _POSIX_PATH_MAX
205 #define KPSE_DEBUG_P(bit) (kpathsea_debug & (1 << (bit)))
207 #define KPSE_DEBUG_STAT 0
208 #define KPSE_DEBUG_HASH 1
209 #define KPSE_DEBUG_FOPEN 2
210 #define KPSE_DEBUG_PATHS 3
211 #define KPSE_DEBUG_EXPAND 4
212 #define KPSE_DEBUG_SEARCH 5
213 #define KPSE_DEBUG_VARS 6
214 #define KPSE_LAST_DEBUG KPSE_DEBUG_VARS
217 #define DEBUGF_START() do { gnulib::fputs ("kdebug:", stderr)
218 #define DEBUGF_END() gnulib::fflush (stderr); } while (0)
220 #define DEBUGF(str) \
221 DEBUGF_START (); gnulib::fputs (str, stderr); DEBUGF_END ()
222 #define DEBUGF1(str, e1) \
223 DEBUGF_START (); gnulib::fprintf (stderr, str, e1); DEBUGF_END ()
224 #define DEBUGF2(str, e1, e2) \
225 DEBUGF_START (); gnulib::fprintf (stderr, str, e1, e2); DEBUGF_END ()
226 #define DEBUGF3(str, e1, e2, e3) \
227 DEBUGF_START (); gnulib::fprintf (stderr, str, e1, e2, e3); DEBUGF_END ()
228 #define DEBUGF4(str, e1, e2, e3, e4) \
229 DEBUGF_START (); gnulib::fprintf (stderr, str, e1, e2, e3, e4); DEBUGF_END ()
237 #if defined (WIN32) && !defined (__MINGW32__)
251 #define MAXPATHLEN _MAX_PATH
257 #define access _access
259 #define strdup _strdup
261 #define S_IFMT _S_IFMT
262 #define S_IFDIR _S_IFDIR
267 #define _WINSOCKAPI_ 1
285 #define FATAL_PERROR(str) \
288 gnulib::fputs ("pathsearch: ", stderr); \
289 perror (str); exit (EXIT_FAILURE); \
296 gnulib::fputs ("pathsearch: fatal: ", stderr); \
297 gnulib::fputs (str, stderr); \
298 gnulib::fputs (".\n", stderr); \
326 #define STR_LLIST(sl) ((sl).str)
327 #define STR_LLIST_MOVED(sl) ((sl).moved)
328 #define STR_LLIST_NEXT(sl) ((sl).next)
338 static std::string
kpse_expand (
const std::string& s);
341 const std::string& dflt);
344 const std::string& path_elt,
bool all);
358 xfopen (
const std::string& filename,
const char *mode)
362 assert (! filename.empty () && mode);
364 f = gnulib::fopen (filename.c_str (), mode);
370 DEBUGF3 (
"fopen (%s, %s) => 0x%lx\n", filename.c_str (), mode,
371 reinterpret_cast<intptr_t
> (
f));
400 size_t len = key.length ();
401 for (
size_t i = 0; i < len; i++)
402 n = (n + n + key[i]) % table.
size;
425 DEBUGF1 (
"hash_lookup (%s) =>", key.c_str ());
427 gnulib::fputs (
" (nil)\n", stderr);
431 for (
int i = 0; i < len; i++)
433 gnulib::putc (
' ', stderr);
434 gnulib::fputs (ret[i].c_str (), stderr);
436 gnulib::putc (
'\n', stderr);
438 gnulib::fflush (stderr);
483 b =
e = std::string::npos;
504 b =
e = std::string::npos;
527 DEBUGF2 (
"variable: %s = %s\n", var.c_str (),
528 tmp.empty () ?
"(nil)" : tmp.c_str ());
541 unsigned ret_len = 0;
543 std::string ret = name;
545 size_t len = name.length ();
547 for (
size_t i = 0; i < len; i++)
561 ret[ret_len++] = name[i];
565 ret.resize (ret_len);
579 const char *t = fn.c_str ();
580 return (GetFileAttributes (t) != 0xFFFFFFFF
581 && ! (GetFileAttributes (t) & FILE_ATTRIBUTE_DIRECTORY));
587 const char *t = fn.c_str ();
588 return (access (t, R_OK) == 0
589 &&
stat (t, &(st)) == 0 && ! S_ISDIR (st.st_mode));
611 else if (errno == ENAMETOOLONG)
621 ret = std::string ();
632 perror (name.c_str ());
635 ret = std::string ();
647 size_t len = filename.length ();
649 int absolute = (len > 0 &&
IS_DIR_SEP (filename[0]))
656 || (len > 1 && filename[0] ==
'\\' && filename[1] ==
'\\')
660 int explicit_relative
663 && filename[0] ==
'.'
665 || (len > 2 && filename[1] ==
'.' &&
IS_DIR_SEP (filename[2]))));
667 return absolute || explicit_relative;
685 static FILE *log_file = 0;
686 static bool first_time =
true;
695 if (! log_name.empty ())
697 log_file =
xfopen (log_name.c_str (),
"a");
700 perror (log_name.c_str ());
707 for (
int e = 0; e < filenames.
length () && ! filenames[e].
empty (); e++)
709 std::string filename = filenames[e];
713 gnulib::fprintf (log_file,
"%lu %s\n",
714 static_cast<unsigned long> (time (0)),
721 gnulib::fputs (filename.c_str (), stderr);
745 const std::string dir =
STR_LLIST (*elt);
747 std::string potential = dir + name;
794 std::string elt = *pi;
797 bool allow_disk_search =
true;
799 if (elt.length () > 1 && elt[0] ==
'!' && elt[1] ==
'!')
804 allow_disk_search =
false;
805 elt = elt.substr (2);
811 while (elt.length () > 3
816 elt = elt.substr (1);
822 while (elt.length () > 1
824 elt = elt.substr (1);
839 if (allow_disk_search && found.
empty ())
848 if (! found.
empty ())
854 ret_list.
append (found[0]);
872 search (
const std::string& path,
const std::string& original_name,
873 bool must_exist,
bool all)
886 DEBUGF4 (
"start search (file=%s, must_exist=%d, find_all=%d, path=%s).\n",
887 name.c_str (), must_exist, all, path.c_str ());
897 first_search =
false;
905 DEBUGF1 (
"search (%s) =>", original_name.c_str ());
910 gnulib::putc (
'\n', stderr);
942 return ret_list.
empty () ? std::string () : ret_list[0];
954 return search (path, name,
true,
true);
970 std::string elt = *pi;
975 bool allow_disk_search =
true;
977 if (elt.length () > 1 && elt[0] ==
'!' && elt[1] ==
'!')
983 allow_disk_search =
false;
984 elt = elt.substr (2);
991 while (elt.length () > 3
996 elt = elt.substr (1);
1002 while (elt.length () > 1
1004 elt = elt.substr (1);
1009 for (dirs_elt = *dirs; dirs_elt; dirs_elt =
STR_LLIST_NEXT (*dirs_elt))
1011 const std::string dir =
STR_LLIST (*dirs_elt);
1013 int len = names.
length ();
1014 for (
int i = 0; i < len && !done; i++)
1016 std::string name = names[i];
1035 if (allow_disk_search && found.
empty ())
1052 if (! found.
empty ())
1058 ret_list.
append (found[0]);
1071 bool must_exist,
bool all)
1077 gnulib::fputs (
"start find_first_of ((", stderr);
1079 int len = names.
length ();
1081 for (
int i = 0; i < len; i++)
1084 gnulib::fputs (names[i].c_str (), stderr);
1086 gnulib::fprintf (stderr,
", %s", names[i].c_str ());
1089 gnulib::fprintf (stderr,
"), path=%s, must_exist=%d).\n",
1090 path.c_str (), must_exist);
1093 for (
int i = 0; i < names.
length (); i++)
1095 std::string name = names[i];
1105 if (! ret_list.
empty ())
1117 first_search =
false;
1126 gnulib::fputs (
"find_first_of (", stderr);
1128 int len = names.
length ();
1130 for (
int i = 0; i < len; i++)
1133 gnulib::fputs (names[i].c_str (), stderr);
1135 gnulib::fprintf (stderr,
", %s", names[i].c_str ());
1138 gnulib::fputs (
") =>", stderr);
1144 gnulib::putc (
'\n', stderr);
1162 return ret_list.
empty () ? std::string () : ret_list[0];
1191 std::string expansion;
1194 if (name.empty () || name[0] !=
'~')
1202 else if (name.length () == 1)
1206 if (expansion.empty ())
1220 size_t home_len = home.length ();
1224 home = home.substr (1);
1230 expansion = home + name.substr (c);
1241 while (name.length () > c && !
IS_DIR_SEP (name[c]))
1244 std::string user = name.substr (1, c-1);
1251 std::string home = p ? p.
dir () : std::string (
".");
1258 home = home.substr (1);
1261 if (name.length () > c &&
IS_DIR_SEP (home[home.length () - 1]))
1264 expansion = name.length () > c ? home : home + name.substr (c);
1298 if (kpse_dot.empty ())
1303 std::string elt = *pi;
1308 size_t elt_len = elt.length ();
1311 || (elt_len > 1 && elt[0] ==
'!' && elt[1] ==
'!'))
1313 else if (elt_len == 1 && elt[0] ==
'.')
1315 else if (elt_len > 1 && elt[0] ==
'.' &&
IS_DIR_SEP (elt[1]))
1321 int len = ret.length ();
1340 for (
int i = 0; i < expansions.
length (); i++)
1345 if (x != expansions[i])
1357 ret.resize (ret.length () - 1);
1383 std::string elt = *pi;
1390 size_t len = ret.length ();
1419 std::string elt = *pi;
1424 if (elt.length () > 1 && elt[0] ==
'!' && elt[1] ==
'!')
1425 elt = elt.substr (2);
1430 while (elt.length () > 3
1435 elt = elt.substr (1);
1441 while (elt.length () > 1
1443 elt = elt.substr (1);
1456 const std::string thedir =
STR_LLIST (*dir);
1457 unsigned dirlen = thedir.length ();
1487 #define brace_whitespace(c) (! (c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
1510 else if (arr2.
empty ())
1514 int len1 = arr1.
length ();
1515 int len2 = arr2.
length ();
1520 for (
int i = 0; i < len2; i++)
1521 for (
int j = 0; j < len1; j++)
1522 result[k++] = arr1[j] + arr2[i];
1539 std::string preamble = text.substr (0, i);
1552 (*current_liboctave_warning_handler)
1553 (
"%s: Unmatched {", text.c_str ());
1559 std::string amble = text.substr (start, i-start);
1562 std::string postamble = text.substr (i+1);
1582 size_t text_len = text.
length ();
1586 for (start = 0, i = 0, c = 1; c && start < text_len; start = ++i)
1593 i = (i0 < i1 ? i0 : i1);
1595 std::string tem = text.substr (start, i-start);
1599 if (result.
empty ())
1615 int c = 0, level = 0, quoted = 0, pass_next = 0;
1617 size_t text_len = text.length ();
1621 for (; i < text_len; i++)
1633 if (c ==
'\\' && (quoted == 0 || quoted ==
'"' || quoted ==
'`'))
1646 if (c ==
'"' || c ==
'\'' || c ==
'`')
1652 if (c == satisfy && !level && !quoted)
1664 if ((c !=
'{') || i == 0 || (text[i-1] !=
'$'))
1670 else if (c ==
'}' && level)
1711 #define EXPAND_DEFAULT(try_path, source_string) \
1714 if (! try_path.empty ()) \
1716 info.raw_path = try_path; \
1717 info.path = kpse_expand_default (try_path, info.path); \
1718 info.path_source = source_string; \
1734 match (
const std::string& filename_arg,
const std::string& path_elt_arg)
1736 const char *filename = filename_arg.c_str ();
1737 const char *path_elt = path_elt_arg.c_str ();
1739 const char *original_filename = filename;
1740 bool matched =
false;
1742 for (; *filename && *path_elt; filename++, path_elt++)
1744 if (*filename == *path_elt)
1748 && original_filename < filename &&
IS_DIR_SEP (path_elt[-1]))
1764 for (; !matched && *filename; filename++)
1767 if (
IS_DIR_SEP (filename[-1]) && *filename == *path_elt)
1768 matched =
match (filename, path_elt);
1782 if (! matched && *path_elt == 0)
1798 matched = *filename == 0;
1815 elt_in_db (
const std::string& db_dir,
const std::string& path_elt)
1819 size_t db_dir_len = db_dir.length ();
1820 size_t path_elt_len = path_elt.length ();
1824 while (! found && db_dir[i] == path_elt[i])
1828 if (i == db_dir_len)
1833 else if (i == path_elt_len)
1850 const std::string& orig_path_elt,
bool all)
1855 bool relevant =
false;
1857 std::string name = name_arg;
1870 std::string path_elt;
1871 size_t last_slash = name.rfind (
'/');
1872 if (last_slash != std::string::npos && last_slash != 0)
1874 std::string dir_part = name.substr (0, last_slash);
1875 name = name.substr (last_slash + 1);
1878 path_elt = orig_path_elt;
1885 for (
int e = 0; ! relevant && e < db_dir_list.
length (); e++)
1886 relevant =
elt_in_db (db_dir_list[e], path_elt);
1896 int len = aliases.
length ();
1898 for (
int i = len; i > 0; i--)
1899 aliases[i] = aliases[i - 1];
1904 for (
int i = 0; i < len && !done; i++)
1906 std::string atry = aliases[i];
1915 int db_dirs_len = db_dirs.
length ();
1916 for (
int j = 0; j < db_dirs_len && !done; j++)
1918 std::string db_file = db_dirs[j] + atry;
1919 bool matched =
match (db_file, path_elt);
1923 DEBUGF3 (
"db:match (%s,%s) = %d\n",
1924 db_file.c_str (), path_elt.c_str (), matched);
1945 int aliases_len = aliases.
length ();
1947 for (
int k = 1; k < aliases_len && found.empty (); k++)
1949 std::string aatry = db_dirs[j] + aliases[k];
1957 if (! found.empty ())
1961 if (! (all || found.empty ()))
1983 std::string expansion;
1985 size_t path_len = path.length ();
1988 expansion = fallback;
1993 expansion = path_len == 1 ? fallback : fallback + path;
2002 expansion = path + fallback;
2010 for (
size_t i = 0; i < path_len; i++)
2012 if (i + 1 < path_len
2019 expansion = path.substr (0, i+1) + fallback + path.substr (i+1);
2041 char last_char = dir[dir.length () - 1];
2043 std::string saved_dir = dir;
2058 unsigned int fa = GetFileAttributes (fn.c_str ());
2059 return (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
2062 return stat (fn.c_str (), &stats) == 0 && S_ISDIR (stats.st_mode);
2107 new_cache[i].
key = the_cache[i].
key;
2113 the_cache = new_cache;
2130 if (key == the_cache[p].key)
2131 return the_cache[p].
value;
2150 static std::string dirname;
2161 std::map<std::string, long> link_table;
2165 if (link_table.find (fn) != link_table.end ())
2166 ret = link_table[fn];
2171 ret =
stat (fn.c_str (), &stats) == 0 && S_ISDIR (stats.st_mode)
2172 ? stats.st_nlink :
static_cast<unsigned> (-1);
2174 link_table[fn] = ret;
2178 DEBUGF2 (
"dir_links (%s) => %ld\n", fn.c_str (), ret);
2189 unsigned elt_length,
const std::string& post)
2192 WIN32_FIND_DATA find_file_data;
2200 std::string name = elt.substr (0, elt_length);
2207 dirname = name +
"/*.*";
2209 hnd = FindFirstFile (dirname.c_str (), &find_file_data);
2211 if (hnd == INVALID_HANDLE_VALUE)
2224 name.resize (elt_length);
2231 if (find_file_data.cFileName[0] !=
'.')
2234 name += find_file_data.cFileName;
2236 if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2240 unsigned potential_len = name.length ();
2242 do_subdir (str_list_ptr, name, potential_len, post);
2244 name.resize (elt_length);
2247 proceed = FindNextFile (hnd, &find_file_data);
2255 dir = gnulib::opendir (name.c_str ());
2270 name.resize (elt_length);
2273 while ((e = gnulib::readdir (dir)))
2278 if (e->d_name[0] !=
'.')
2292 unsigned potential_len = name.length ();
2305 #ifdef ST_NLINK_TRICK
2309 do_subdir (str_list_ptr, name, potential_len, post);
2310 #ifdef ST_NLINK_TRICK
2311 else if (post.empty ())
2319 name.resize (elt_length);
2338 size_t elt_len = elt.length ();
2343 while (dir < elt_len)
2348 if (++dir < elt_len &&
IS_DIR_SEP (elt[dir]))
2354 std::string post = elt.substr (i);
2356 do_subdir (str_list_ptr, elt, dir, post);
2411 DEBUGF1 (
"path element %s =>", elt.c_str ());
2416 gnulib::fprintf (stderr,
" %s", (
STR_LLIST (*e)).c_str ());
2418 gnulib::putc (
'\n', stderr);
2419 gnulib::fflush (stderr);
2430 int ret = gnulib::closedir (d);
2433 FATAL (
"closedir failed");
2484 if (unmoved != mover)
2492 for (before_mover = unmoved;
STR_LLIST_NEXT (*before_mover) != mover;
2525 expansions[var] = xp;
2533 return (expansions.find (var) != expansions.end ()) ? expansions[var] :
false;
2541 expand (std::string &expansion,
const std::string& var)
2545 (*current_liboctave_warning_handler)
2546 (
"kpathsea: variable '%s' references itself (eventually)",
2554 if (! value.empty ())
2566 #ifndef IS_VAR_START
2567 #define IS_VAR_START(c) ((c) == '$')
2570 #define IS_VAR_CHAR(c) (isalnum (c) || (c) == '_')
2572 #ifndef IS_VAR_BEGIN_DELIMITER
2573 #define IS_VAR_BEGIN_DELIMITER(c) ((c) == '{')
2575 #ifndef IS_VAR_END_DELIMITER
2576 #define IS_VAR_END_DELIMITER(c) ((c) == '}')
2585 std::string expansion;
2587 size_t src_len = src.length ();
2590 for (
size_t i = 0; i < src_len; i++)
2609 expand (expansion, src.substr (i, var_end - i + 1));
2616 size_t var_end = ++i;
2621 if (var_end == src_len)
2623 (*current_liboctave_warning_handler)
2624 (
"%s: No matching } for ${", src.c_str ());
2629 expand (expansion, src.substr (i, var_end - i));
2636 (*current_liboctave_warning_handler)
2637 (
"%s: Unrecognized variable construct '$%c'",
2638 src.c_str (), src[i]);
2644 expansion += src[i];