Mercurial > hg > octave-lyh
comparison liboctave/kpse.cc @ 4389:fa9f6dde6c24
[project @ 2003-04-25 04:45:56 by jwe]
author | jwe |
---|---|
date | Fri, 25 Apr 2003 04:45:56 +0000 |
parents | 112a509bd2e6 |
children | c378263ef911 |
comparison
equal
deleted
inserted
replaced
4388:a3020cb1fe0f | 4389:fa9f6dde6c24 |
---|---|
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 | 20 |
21 #if defined (HAVE_CONFIG_H) | 21 #if defined (HAVE_CONFIG_H) |
22 #include <config.h> | 22 #include <config.h> |
23 #endif | 23 #endif |
24 | |
25 #include <string> | |
24 | 26 |
25 #include "kpse-config.h" | 27 #include "kpse-config.h" |
26 #include "kpse-xfns.h" | 28 #include "kpse-xfns.h" |
27 #include "kpse.h" | 29 #include "kpse.h" |
28 | 30 |
232 | 234 |
233 #ifdef KPSE_DEBUG | 235 #ifdef KPSE_DEBUG |
234 /* How to print the hash results when debugging. */ | 236 /* How to print the hash results when debugging. */ |
235 extern int kpse_debug_hash_lookup_int; | 237 extern int kpse_debug_hash_lookup_int; |
236 #endif | 238 #endif |
237 | |
238 /* fn.h: arbitrarily long filenames (or just strings). */ | |
239 | |
240 /* Arbitrarily long filenames; it's inconvenient to use obstacks here, | |
241 because we want to maintain a null terminator. Also used for | |
242 dynamically growing strings even when the null byte isn't necessary, | |
243 e.g., in `variable.c', since I don't want to pass obstacks around | |
244 everywhere, and one can't free parts of an obstack arbitrarily. */ | |
245 | |
246 typedef struct | |
247 { | |
248 char *str; | |
249 unsigned allocated; | |
250 unsigned length; /* includes the terminating null byte, if any */ | |
251 } fn_type; | |
252 | |
253 #define FN_STRING(fn) ((fn).str) | |
254 #define FN_ALLOCATED(fn) ((fn).allocated) | |
255 #define FN_LENGTH(fn) ((fn).length) | |
256 | 239 |
257 /* lib.h: other stuff. */ | 240 /* lib.h: other stuff. */ |
258 | 241 |
259 /* Define common sorts of messages. */ | 242 /* Define common sorts of messages. */ |
260 | 243 |
368 | 351 |
369 static char *concat (const char *s1, const char *s2); | 352 static char *concat (const char *s1, const char *s2); |
370 | 353 |
371 static char *concat3 (const char *s1, const char *s2, const char *s3); | 354 static char *concat3 (const char *s1, const char *s2, const char *s3); |
372 | 355 |
373 static char *concatn (const char *str1, ...); | |
374 | |
375 static char *find_suffix (const char *name); | 356 static char *find_suffix (const char *name); |
376 | 357 |
377 static char *kpse_truncate_filename (const char *name); | 358 static char *kpse_truncate_filename (const char *name); |
378 | 359 |
379 static char *kpse_readable_file (const char *name); | 360 static char *kpse_readable_file (const char *name); |
390 | 371 |
391 static void str_llist_add (str_llist_type *l, char *str); | 372 static void str_llist_add (str_llist_type *l, char *str); |
392 | 373 |
393 static void str_llist_float (str_llist_type *l, str_llist_elt_type *mover); | 374 static void str_llist_float (str_llist_type *l, str_llist_elt_type *mover); |
394 | 375 |
395 static fn_type fn_init (void); | 376 static std::string kpse_var_value (const char *var); |
396 | |
397 static fn_type fn_copy0 (const char *s, unsigned len); | |
398 | |
399 static void fn_free (fn_type *f); | |
400 | |
401 static void grow (fn_type *f, unsigned len); | |
402 | |
403 static void fn_1grow (fn_type *f, char c); | |
404 | |
405 static void fn_grow (fn_type *f, void *source, unsigned len); | |
406 | |
407 static void fn_str_grow (fn_type *f, const char *s); | |
408 | |
409 static void fn_shrink_to (fn_type *f, unsigned loc); | |
410 | |
411 static char *kpse_var_value (const char *var); | |
412 | 377 |
413 static void expanding (const char *var, int xp); | 378 static void expanding (const char *var, int xp); |
414 | 379 |
415 static int expanding_p (const char *var); | 380 static int expanding_p (const char *var); |
416 | 381 |
417 static void expand (fn_type *expansion, const char *start, const char *end); | 382 static std::string kpse_var_expand (const std::string& src); |
418 | |
419 static char *kpse_var_expand (const char *src); | |
420 | 383 |
421 #include <ctime> /* for `time' */ | 384 #include <ctime> /* for `time' */ |
422 | 385 |
423 /* The very first search is for texmf.cnf, called when someone tries to | 386 /* The very first search is for texmf.cnf, called when someone tries to |
424 initialize the TFM path or whatever. init_path calls kpse_cnf_get | 387 initialize the TFM path or whatever. init_path calls kpse_cnf_get |
440 static FILE *log_file = NULL; | 403 static FILE *log_file = NULL; |
441 static bool first_time = true; /* Need to open the log file? */ | 404 static bool first_time = true; /* Need to open the log file? */ |
442 | 405 |
443 if (first_time) { | 406 if (first_time) { |
444 /* Get name from either envvar or config file. */ | 407 /* Get name from either envvar or config file. */ |
445 char *log_name = kpse_var_value ("TEXMFLOG"); | 408 std::string log_name = kpse_var_value ("TEXMFLOG"); |
446 first_time = false; | 409 first_time = false; |
447 if (log_name) { | 410 if (! log_name.empty ()) { |
448 log_file = xfopen (log_name, "a"); | 411 log_file = xfopen (log_name.c_str (), "a"); |
449 if (!log_file) | 412 if (!log_file) |
450 perror (log_name); | 413 perror (log_name.c_str ()); |
451 free (log_name); | |
452 } | 414 } |
453 } | 415 } |
454 | 416 |
455 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH) || log_file) { | 417 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH) || log_file) { |
456 unsigned e; | 418 unsigned e; |
650 static char ** | 612 static char ** |
651 search (const char *path, const char *original_name, | 613 search (const char *path, const char *original_name, |
652 bool must_exist, bool all) | 614 bool must_exist, bool all) |
653 { | 615 { |
654 str_list_type ret_list; | 616 str_list_type ret_list; |
655 char *name; | |
656 bool absolute_p; | 617 bool absolute_p; |
657 | 618 |
658 /* Make a leading ~ count as an absolute filename, and expand $FOO's. */ | 619 /* Make a leading ~ count as an absolute filename, and expand $FOO's. */ |
659 name = kpse_expand (original_name); | 620 std::string tmp = kpse_expand (original_name); |
621 char *name = xstrdup (tmp.c_str ()); | |
660 | 622 |
661 /* If the first name is absolute or explicitly relative, no need to | 623 /* If the first name is absolute or explicitly relative, no need to |
662 consider PATH at all. */ | 624 consider PATH at all. */ |
663 absolute_p = kpse_absolute_p (name, true); | 625 absolute_p = kpse_absolute_p (name, true); |
664 | 626 |
942 | 904 |
943 /* If NAME has a leading ~ or ~user, Unix-style, expand it to the user's | 905 /* If NAME has a leading ~ or ~user, Unix-style, expand it to the user's |
944 home directory, and return a new malloced string. If no ~, or no | 906 home directory, and return a new malloced string. If no ~, or no |
945 <pwd.h>, just return NAME. */ | 907 <pwd.h>, just return NAME. */ |
946 | 908 |
947 static char * | 909 static std::string |
948 kpse_tilde_expand (const char *name) | 910 kpse_tilde_expand (const std::string& name) |
949 { | 911 { |
950 const char *expansion; | 912 std::string expansion; |
951 const char *home; | 913 |
952 | 914 assert (! name.empty ()); |
953 assert (name); | |
954 | 915 |
955 /* If no leading tilde, do nothing. */ | 916 /* If no leading tilde, do nothing. */ |
956 if (*name != '~') { | 917 if (name[0] != '~') { |
957 expansion = name; | 918 expansion = name; |
958 | 919 |
959 /* If a bare tilde, return the home directory or `.'. (Very unlikely | 920 /* If a bare tilde, return the home directory or `.'. (Very unlikely |
960 that the directory name will do anyone any good, but ... */ | 921 that the directory name will do anyone any good, but ... */ |
961 } else if (name[1] == 0) { | 922 } else if (name.length () == 1) { |
962 expansion = xstrdup (getenv ("HOME")); | 923 char *tmp = getenv ("HOME"); |
963 if (!expansion) { | 924 expansion = tmp ? tmp : "."; |
964 expansion = xstrdup ("."); | |
965 } | |
966 | 925 |
967 /* If `~/', remove any trailing / or replace leading // in $HOME. | 926 /* If `~/', remove any trailing / or replace leading // in $HOME. |
968 Should really check for doubled intermediate slashes, too. */ | 927 Should really check for doubled intermediate slashes, too. */ |
969 } else if (IS_DIR_SEP (name[1])) { | 928 } else if (IS_DIR_SEP (name[1])) { |
970 unsigned c = 1; | 929 unsigned c = 1; |
971 home = getenv ("HOME"); | 930 char *home = getenv ("HOME"); |
972 if (!home) { | 931 if (!home) { |
973 home = "."; | 932 home = "."; |
974 } | 933 } |
975 if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) { /* handle leading // */ | 934 if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) { /* handle leading // */ |
976 home++; | 935 home++; |
977 } | 936 } |
978 if (IS_DIR_SEP (home[strlen (home) - 1])) { /* omit / after ~ */ | 937 if (IS_DIR_SEP (home[strlen (home) - 1])) { /* omit / after ~ */ |
979 c++; | 938 c++; |
980 } | 939 } |
981 expansion = concat (home, name + c); | 940 expansion = std::string (home) + name.substr (c); |
982 | 941 |
983 /* If `~user' or `~user/', look up user in the passwd database (but | 942 /* If `~user' or `~user/', look up user in the passwd database (but |
984 OS/2 doesn't have this concept. */ | 943 OS/2 doesn't have this concept. */ |
985 } else | 944 } else |
986 #ifdef HAVE_PWD_H | 945 #ifdef HAVE_PWD_H |
987 { | 946 { |
988 struct passwd *p; | 947 struct passwd *p; |
989 char *user; | |
990 unsigned c = 2; | 948 unsigned c = 2; |
991 while (!IS_DIR_SEP (name[c]) && name[c] != 0) /* find user name */ | 949 while (!IS_DIR_SEP (name[c]) && name[c] != 0) /* find user name */ |
992 c++; | 950 c++; |
993 | 951 |
994 user = (char *) xmalloc (c); | 952 std::string user = name.substr (2, c-1); |
995 strncpy (user, name + 1, c - 1); | |
996 user[c - 1] = 0; | |
997 | 953 |
998 /* We only need the cast here for (deficient) systems | 954 /* We only need the cast here for (deficient) systems |
999 which do not declare `getpwnam' in <pwd.h>. */ | 955 which do not declare `getpwnam' in <pwd.h>. */ |
1000 p = (struct passwd *) getpwnam (user); | 956 p = (struct passwd *) getpwnam (user.c_str ()); |
1001 free (user); | |
1002 | 957 |
1003 /* If no such user, just use `.'. */ | 958 /* If no such user, just use `.'. */ |
1004 home = p ? p->pw_dir : "."; | 959 const char *home = p ? p->pw_dir : "."; |
1005 if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) { /* handle leading // */ | 960 if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) { /* handle leading // */ |
1006 home++; | 961 home++; |
1007 } | 962 } |
1008 if (IS_DIR_SEP (home[strlen (home) - 1]) && name[c] != 0) | 963 if (IS_DIR_SEP (home[strlen (home) - 1]) && name[c] != 0) |
1009 c++; /* If HOME ends in /, omit the / after ~user. */ | 964 c++; /* If HOME ends in /, omit the / after ~user. */ |
1010 | 965 |
1011 expansion = name[c] == 0 ? xstrdup (home) : concat (home, name + c); | 966 expansion = name[c] == 0 |
967 ? std::string (home) : std::string (home) + name.substr (c); | |
1012 } | 968 } |
1013 #else /* not HAVE_PWD_H */ | 969 #else /* not HAVE_PWD_H */ |
1014 expansion = name; | 970 expansion = name; |
1015 #endif /* not HAVE_PWD_H */ | 971 #endif /* not HAVE_PWD_H */ |
1016 | 972 |
1017 /* We may return the same thing as the original, and then we might not | 973 return expansion; |
1018 be returning a malloc-ed string. Callers beware. Sorry. */ | |
1019 return (char *) expansion; | |
1020 } | 974 } |
1021 | 975 |
1022 /* Do variable expansion first so ~${USER} works. (Besides, it's what the | 976 /* Do variable expansion first so ~${USER} works. (Besides, it's what the |
1023 shells do.) */ | 977 shells do.) */ |
1024 | 978 |
1025 char * | 979 std::string |
1026 kpse_expand (const char *s) | 980 kpse_expand (const std::string& s) |
1027 { | 981 { |
1028 char *var_expansion = kpse_var_expand (s); | 982 std::string var_expansion = kpse_var_expand (s); |
1029 char *tilde_expansion = kpse_tilde_expand (var_expansion); | 983 return kpse_tilde_expand (var_expansion); |
1030 | |
1031 /* `kpse_var_expand' always gives us new memory; `kpse_tilde_expand' | |
1032 doesn't, necessarily. So be careful that we don't free what we are | |
1033 about to return. */ | |
1034 if (tilde_expansion != var_expansion) | |
1035 free (var_expansion); | |
1036 | |
1037 return tilde_expansion; | |
1038 } | 984 } |
1039 | 985 |
1040 | 986 |
1041 /* Forward declarations of functions from the original expand.c */ | 987 /* Forward declarations of functions from the original expand.c */ |
1042 static char **brace_expand (const char *); | 988 static char **brace_expand (const char *); |
1043 static void free_array (char **); | 989 static void free_array (char **); |
1044 | 990 |
1045 /* If $KPSE_DOT is defined in the environment, prepend it to any relative | 991 /* If $KPSE_DOT is defined in the environment, prepend it to any relative |
1046 path components. */ | 992 path components. */ |
1047 | 993 |
1048 static char * | 994 static std::string |
1049 kpse_expand_kpse_dot (char *path) | 995 kpse_expand_kpse_dot (const std::string& path) |
1050 { | 996 { |
1051 char *ret, *elt; | 997 std::string ret; |
998 char *elt; | |
1052 char *kpse_dot = getenv("KPSE_DOT"); | 999 char *kpse_dot = getenv("KPSE_DOT"); |
1053 #ifdef MSDOS | 1000 #ifdef MSDOS |
1054 bool malloced_kpse_dot = false; | 1001 bool malloced_kpse_dot = false; |
1055 #endif | 1002 #endif |
1056 | 1003 |
1057 if (kpse_dot == NULL) | 1004 if (kpse_dot == NULL) |
1058 return path; | 1005 return path; |
1059 ret = (char *) xmalloc(1); | |
1060 *ret = 0; | |
1061 | 1006 |
1062 #ifdef MSDOS | 1007 #ifdef MSDOS |
1063 /* Some setups of ported Bash force $KPSE_DOT to have the //d/foo/bar | 1008 /* Some setups of ported Bash force $KPSE_DOT to have the //d/foo/bar |
1064 form (when `pwd' is used), which is not understood by libc and the OS. | 1009 form (when `pwd' is used), which is not understood by libc and the OS. |
1065 Convert them back to the usual d:/foo/bar form. */ | 1010 Convert them back to the usual d:/foo/bar form. */ |
1071 kpse_dot[1] = ':'; | 1016 kpse_dot[1] = ':'; |
1072 malloced_kpse_dot = true; | 1017 malloced_kpse_dot = true; |
1073 } | 1018 } |
1074 #endif | 1019 #endif |
1075 | 1020 |
1076 for (elt = kpse_path_element (path); elt; elt = kpse_path_element (NULL)) { | 1021 char *tmp = xstrdup (path.c_str ()); |
1077 char *save_ret = ret; | 1022 |
1023 for (elt = kpse_path_element (tmp); elt; elt = kpse_path_element (NULL)) { | |
1078 /* We assume that the !! magic is only used on absolute components. | 1024 /* We assume that the !! magic is only used on absolute components. |
1079 Single "." get special treatment, as does "./" or its equivalent. */ | 1025 Single "." get special treatment, as does "./" or its equivalent. */ |
1080 if (kpse_absolute_p (elt, false) || (elt[0] == '!' && elt[1] == '!')) { | 1026 if (kpse_absolute_p (elt, false) || (elt[0] == '!' && elt[1] == '!')) { |
1081 ret = concat3(ret, elt, ENV_SEP_STRING); | 1027 ret += std::string (elt) + ENV_SEP_STRING; |
1082 } else if (elt[0] == '.' && elt[1] == 0) { | 1028 } else if (elt[0] == '.' && elt[1] == 0) { |
1083 ret = concat3 (ret, kpse_dot, ENV_SEP_STRING); | 1029 ret += std::string (kpse_dot) + ENV_SEP_STRING; |
1084 } else if (elt[0] == '.' && IS_DIR_SEP(elt[1])) { | 1030 } else if (elt[0] == '.' && IS_DIR_SEP(elt[1])) { |
1085 ret = concatn (ret, kpse_dot, elt + 1, ENV_SEP_STRING, NULL); | 1031 ret += std::string (kpse_dot) + (elt + 1) + ENV_SEP_STRING; |
1086 } else { | 1032 } else { |
1087 ret = concatn (ret, kpse_dot, DIR_SEP_STRING, elt, ENV_SEP_STRING, NULL); | 1033 ret += std::string (kpse_dot) + DIR_SEP_STRING + elt + ENV_SEP_STRING; |
1088 } | 1034 } |
1089 free (save_ret); | |
1090 } | 1035 } |
1036 | |
1037 free (tmp); | |
1091 | 1038 |
1092 #ifdef MSDOS | 1039 #ifdef MSDOS |
1093 if (malloced_kpse_dot) free (kpse_dot); | 1040 if (malloced_kpse_dot) free (kpse_dot); |
1094 #endif | 1041 #endif |
1095 | 1042 |
1096 ret[strlen (ret) - 1] = 0; | 1043 int len = ret.length (); |
1044 if (len > 0) | |
1045 ret.resize (len - 1); | |
1046 | |
1097 return ret; | 1047 return ret; |
1098 } | 1048 } |
1099 | 1049 |
1100 /* Do brace expansion on ELT; then do variable and ~ expansion on each | 1050 /* Do brace expansion on ELT; then do variable and ~ expansion on each |
1101 element of the result; then do brace expansion again, in case a | 1051 element of the result; then do brace expansion again, in case a |
1102 variable definition contained braces (e.g., $TEXMF). Return a | 1052 variable definition contained braces (e.g., $TEXMF). Return a |
1103 string comprising all of the results separated by ENV_SEP_STRING. */ | 1053 string comprising all of the results separated by ENV_SEP_STRING. */ |
1104 | 1054 |
1105 static char * | 1055 static std::string |
1106 kpse_brace_expand_element (const char *elt) | 1056 kpse_brace_expand_element (const char *elt) |
1107 { | 1057 { |
1108 unsigned i; | 1058 unsigned i; |
1109 char **expansions = brace_expand (elt); | 1059 char **expansions = brace_expand (elt); |
1110 char *ret = (char *) xmalloc (1); | 1060 std::string ret; |
1111 *ret = 0; | |
1112 | 1061 |
1113 for (i = 0; expansions[i]; i++) { | 1062 for (i = 0; expansions[i]; i++) { |
1114 /* Do $ and ~ expansion on each element. */ | 1063 /* Do $ and ~ expansion on each element. */ |
1115 char *x = kpse_expand (expansions[i]); | 1064 std::string x = kpse_expand (expansions[i]); |
1116 char *save_ret = ret; | 1065 if (x != expansions[i]) { |
1117 if (!STREQ (x, expansions[i])) { | |
1118 /* If we did any expansions, do brace expansion again. Since | 1066 /* If we did any expansions, do brace expansion again. Since |
1119 recursive variable definitions are not allowed, this recursion | 1067 recursive variable definitions are not allowed, this recursion |
1120 must terminate. (In practice, it's unlikely there will ever be | 1068 must terminate. (In practice, it's unlikely there will ever be |
1121 more than one level of recursion.) */ | 1069 more than one level of recursion.) */ |
1122 char *save_x = x; | 1070 x = kpse_brace_expand_element (x.c_str ()); |
1123 x = kpse_brace_expand_element (x); | 1071 } |
1124 free (save_x); | 1072 ret += x + ENV_SEP_STRING; |
1125 } | |
1126 ret = concat3 (ret, x, ENV_SEP_STRING); | |
1127 free (save_ret); | |
1128 free (x); | |
1129 } | 1073 } |
1130 | 1074 |
1131 free_array (expansions); | 1075 free_array (expansions); |
1132 ret[strlen (ret) - 1] = 0; /* waste the trailing null */ | 1076 ret.resize (ret.length () - 1); |
1133 return ret; | 1077 return ret; |
1134 } | 1078 } |
1135 | 1079 |
1136 /* Be careful to not waste all the memory we allocate for each element. */ | 1080 /* Be careful to not waste all the memory we allocate for each element. */ |
1137 | 1081 |
1138 char * | 1082 std::string |
1139 kpse_brace_expand (const char *path) | 1083 kpse_brace_expand (const char *path) |
1140 { | 1084 { |
1141 char *kpse_dot_expansion; | |
1142 char *elt; | 1085 char *elt; |
1143 unsigned len; | 1086 unsigned len; |
1144 /* Must do variable expansion first because if we have | 1087 /* Must do variable expansion first because if we have |
1145 foo = .:~ | 1088 foo = .:~ |
1146 TEXINPUTS = $foo | 1089 TEXINPUTS = $foo |
1147 we want to end up with TEXINPUTS = .:/home/karl. | 1090 we want to end up with TEXINPUTS = .:/home/karl. |
1148 Since kpse_path_element is not reentrant, we must get all | 1091 Since kpse_path_element is not reentrant, we must get all |
1149 the path elements before we start the loop. */ | 1092 the path elements before we start the loop. */ |
1150 char *xpath = kpse_var_expand (path); | 1093 std::string tmp = kpse_var_expand (path); |
1151 char *ret = (char *) xmalloc (1); | 1094 const char *xpath = tmp.c_str (); |
1152 *ret = 0; | 1095 std::string ret; |
1153 | 1096 |
1154 for (elt = kpse_path_element (xpath); elt; elt = kpse_path_element (NULL)) { | 1097 for (elt = kpse_path_element (xpath); elt; elt = kpse_path_element (NULL)) { |
1155 char *save_ret = ret; | |
1156 /* Do brace expansion first, so tilde expansion happens in {~ka,~kb}. */ | 1098 /* Do brace expansion first, so tilde expansion happens in {~ka,~kb}. */ |
1157 char *expansion = kpse_brace_expand_element (elt); | 1099 std::string expansion = kpse_brace_expand_element (elt); |
1158 ret = concat3 (ret, expansion, ENV_SEP_STRING); | 1100 ret += expansion + ENV_SEP_STRING; |
1159 free (expansion); | |
1160 free (save_ret); | |
1161 } | 1101 } |
1162 | 1102 |
1163 /* Waste the last byte by overwriting the trailing env_sep with a null. */ | 1103 /* Waste the last byte by overwriting the trailing env_sep with a null. */ |
1164 len = strlen (ret); | 1104 len = ret.length (); |
1165 if (len != 0) | 1105 if (len > 0) |
1166 ret[len - 1] = 0; | 1106 ret.resize (len - 1); |
1167 free (xpath); | 1107 |
1168 | 1108 return kpse_expand_kpse_dot (ret); |
1169 kpse_dot_expansion = kpse_expand_kpse_dot (ret); | |
1170 if (kpse_dot_expansion != ret) | |
1171 free (ret); | |
1172 | |
1173 return kpse_dot_expansion; | |
1174 } | 1109 } |
1175 | 1110 |
1176 /* Expand all special constructs in a path, and include only the actually | 1111 /* Expand all special constructs in a path, and include only the actually |
1177 existing directories in the result. */ | 1112 existing directories in the result. */ |
1178 char * | 1113 char * |
1179 kpse_path_expand (const char *path) | 1114 kpse_path_expand (const char *path) |
1180 { | 1115 { |
1181 char *ret; | 1116 char *ret; |
1182 char *xpath; | |
1183 char *elt; | 1117 char *elt; |
1184 unsigned len; | 1118 unsigned len; |
1185 | 1119 |
1186 /* Initialise ret to the empty string. */ | 1120 /* Initialise ret to the empty string. */ |
1187 ret = (char *) xmalloc (1); | 1121 ret = (char *) xmalloc (1); |
1188 *ret = 0; | 1122 *ret = 0; |
1189 len = 0; | 1123 len = 0; |
1190 | 1124 |
1191 /* Expand variables and braces first. */ | 1125 /* Expand variables and braces first. */ |
1192 xpath = kpse_brace_expand (path); | 1126 std::string tmp = kpse_brace_expand (path); |
1127 const char *xpath = tmp.c_str (); | |
1193 | 1128 |
1194 /* Now expand each of the path elements, printing the results */ | 1129 /* Now expand each of the path elements, printing the results */ |
1195 for (elt = kpse_path_element (xpath); elt; elt = kpse_path_element (NULL)) { | 1130 for (elt = kpse_path_element (xpath); elt; elt = kpse_path_element (NULL)) { |
1196 str_llist_type *dirs; | 1131 str_llist_type *dirs; |
1197 | 1132 |
1655 EXPAND_DEFAULT (info->cnf_path, "texmf.cnf"); | 1590 EXPAND_DEFAULT (info->cnf_path, "texmf.cnf"); |
1656 EXPAND_DEFAULT (info->client_path, "program config file"); | 1591 EXPAND_DEFAULT (info->client_path, "program config file"); |
1657 if (var) | 1592 if (var) |
1658 EXPAND_DEFAULT (getenv (var), concat (var, " environment variable")); | 1593 EXPAND_DEFAULT (getenv (var), concat (var, " environment variable")); |
1659 EXPAND_DEFAULT (info->override_path, "application override variable"); | 1594 EXPAND_DEFAULT (info->override_path, "application override variable"); |
1660 info->path = kpse_brace_expand (info->path); | 1595 std::string tmp = kpse_brace_expand (info->path); |
1596 info->path = tmp.c_str (); | |
1661 } | 1597 } |
1662 | 1598 |
1663 | 1599 |
1664 /* Some file types have more than one suffix. */ | 1600 /* Some file types have more than one suffix. */ |
1665 | 1601 |
2467 int proceed; | 2403 int proceed; |
2468 #else | 2404 #else |
2469 DIR *dir; | 2405 DIR *dir; |
2470 struct dirent *e; | 2406 struct dirent *e; |
2471 #endif /* not WIN32 */ | 2407 #endif /* not WIN32 */ |
2472 fn_type name; | 2408 |
2473 | 2409 std::string name (elt, elt_length); |
2474 /* Some old compilers don't allow aggregate initialization. */ | 2410 |
2475 name = fn_copy0 (elt, elt_length); | |
2476 | |
2477 assert (IS_DIR_SEP (elt[elt_length - 1]) | 2411 assert (IS_DIR_SEP (elt[elt_length - 1]) |
2478 || IS_DEVICE_SEP (elt[elt_length - 1])); | 2412 || IS_DEVICE_SEP (elt[elt_length - 1])); |
2479 | 2413 |
2480 #if defined (WIN32) | 2414 #if defined (WIN32) |
2481 strcpy(dirname, FN_STRING(name)); | 2415 strcpy(dirname, name.c_str ()); |
2482 strcat(dirname, "/*.*"); /* "*.*" or "*" -- seems equivalent. */ | 2416 strcat(dirname, "/*.*"); /* "*.*" or "*" -- seems equivalent. */ |
2483 hnd = FindFirstFile(dirname, &find_file_data); | 2417 hnd = FindFirstFile(dirname, &find_file_data); |
2484 | 2418 |
2485 if (hnd == INVALID_HANDLE_VALUE) { | 2419 if (hnd == INVALID_HANDLE_VALUE) |
2486 fn_free(&name); | |
2487 return; | 2420 return; |
2488 } | |
2489 | 2421 |
2490 /* Include top level before subdirectories, if nothing to match. */ | 2422 /* Include top level before subdirectories, if nothing to match. */ |
2491 if (*post == 0) | 2423 if (*post == 0) |
2492 dir_list_add (str_list_ptr, FN_STRING (name)); | 2424 dir_list_add (str_list_ptr, name.c_str ()); |
2493 else { | 2425 else { |
2494 /* If we do have something to match, see if it exists. For | 2426 /* If we do have something to match, see if it exists. For |
2495 example, POST might be `pk/ljfour', and they might have a | 2427 example, POST might be `pk/ljfour', and they might have a |
2496 directory `$TEXMF/fonts/pk/ljfour' that we should find. */ | 2428 directory `$TEXMF/fonts/pk/ljfour' that we should find. */ |
2497 fn_str_grow (&name, post); | 2429 name += post; |
2498 expand_elt (str_list_ptr, FN_STRING (name), elt_length); | 2430 expand_elt (str_list_ptr, name.c_str (), elt_length); |
2499 fn_shrink_to (&name, elt_length); | 2431 name.resize (elt_length); |
2500 } | 2432 } |
2501 proceed = 1; | 2433 proceed = 1; |
2502 while (proceed) { | 2434 while (proceed) { |
2503 if (find_file_data.cFileName[0] != '.') { | 2435 if (find_file_data.cFileName[0] != '.') { |
2504 /* Construct the potential subdirectory name. */ | 2436 /* Construct the potential subdirectory name. */ |
2505 fn_str_grow (&name, find_file_data.cFileName); | 2437 name += find_file_data.cFileName; |
2506 if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | 2438 if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
2507 unsigned potential_len = FN_LENGTH (name); | |
2508 | |
2509 /* It's a directory, so append the separator. */ | 2439 /* It's a directory, so append the separator. */ |
2510 fn_str_grow (&name, DIR_SEP_STRING); | 2440 name += DIR_SEP_STRING; |
2511 | 2441 unsigned potential_len = name.length (); |
2512 do_subdir (str_list_ptr, FN_STRING (name), | 2442 do_subdir (str_list_ptr, name.c_str (), |
2513 potential_len, post); | 2443 potential_len, post); |
2514 } | 2444 } |
2515 fn_shrink_to (&name, elt_length); | 2445 name.resize (elt_length); |
2516 } | 2446 } |
2517 proceed = FindNextFile (hnd, &find_file_data); | 2447 proceed = FindNextFile (hnd, &find_file_data); |
2518 } | 2448 } |
2519 fn_free (&name); | |
2520 FindClose(hnd); | 2449 FindClose(hnd); |
2521 | 2450 |
2522 #else /* not WIN32 */ | 2451 #else /* not WIN32 */ |
2523 | 2452 |
2524 /* If we can't open it, quit. */ | 2453 /* If we can't open it, quit. */ |
2525 dir = opendir (FN_STRING (name)); | 2454 dir = opendir (name.c_str ()); |
2526 if (dir == NULL) | 2455 if (dir == NULL) |
2527 { | 2456 return; |
2528 fn_free (&name); | |
2529 return; | |
2530 } | |
2531 | 2457 |
2532 /* Include top level before subdirectories, if nothing to match. */ | 2458 /* Include top level before subdirectories, if nothing to match. */ |
2533 if (*post == 0) | 2459 if (*post == 0) |
2534 dir_list_add (str_list_ptr, FN_STRING (name)); | 2460 dir_list_add (str_list_ptr, name.c_str ()); |
2535 else | 2461 else |
2536 { /* If we do have something to match, see if it exists. For | 2462 { /* If we do have something to match, see if it exists. For |
2537 example, POST might be `pk/ljfour', and they might have a | 2463 example, POST might be `pk/ljfour', and they might have a |
2538 directory `$TEXMF/fonts/pk/ljfour' that we should find. */ | 2464 directory `$TEXMF/fonts/pk/ljfour' that we should find. */ |
2539 fn_str_grow (&name, post); | 2465 name += post; |
2540 expand_elt (str_list_ptr, FN_STRING (name), elt_length); | 2466 expand_elt (str_list_ptr, name.c_str (), elt_length); |
2541 fn_shrink_to (&name, elt_length); | 2467 name.resize (elt_length); |
2542 } | 2468 } |
2543 | 2469 |
2544 while ((e = readdir (dir)) != NULL) | 2470 while ((e = readdir (dir)) != NULL) |
2545 { /* If it begins with a `.', never mind. (This allows ``hidden'' | 2471 { /* If it begins with a `.', never mind. (This allows ``hidden'' |
2546 directories that the algorithm won't find.) */ | 2472 directories that the algorithm won't find.) */ |
2547 if (e->d_name[0] != '.') | 2473 if (e->d_name[0] != '.') |
2548 { | 2474 { |
2549 int links; | 2475 int links; |
2550 | 2476 |
2551 /* Construct the potential subdirectory name. */ | 2477 /* Construct the potential subdirectory name. */ |
2552 fn_str_grow (&name, e->d_name); | 2478 name += e->d_name; |
2553 | 2479 |
2554 /* If we can't stat it, or if it isn't a directory, continue. */ | 2480 /* If we can't stat it, or if it isn't a directory, continue. */ |
2555 links = dir_links (FN_STRING (name)); | 2481 links = dir_links (name.c_str ()); |
2556 | 2482 |
2557 if (links >= 0) | 2483 if (links >= 0) |
2558 { | 2484 { |
2559 unsigned potential_len = FN_LENGTH (name); | |
2560 | |
2561 /* It's a directory, so append the separator. */ | 2485 /* It's a directory, so append the separator. */ |
2562 fn_str_grow (&name, DIR_SEP_STRING); | 2486 name += DIR_SEP_STRING; |
2487 unsigned potential_len = name.length (); | |
2563 | 2488 |
2564 /* Should we recurse? To see if the subdirectory is a | 2489 /* Should we recurse? To see if the subdirectory is a |
2565 leaf, check if it has two links (one for . and one for | 2490 leaf, check if it has two links (one for . and one for |
2566 ..). This means that symbolic links to directories do | 2491 ..). This means that symbolic links to directories do |
2567 not affect the leaf-ness. This is arguably wrong, but | 2492 not affect the leaf-ness. This is arguably wrong, but |
2580 #else | 2505 #else |
2581 if (links > 2) | 2506 if (links > 2) |
2582 #endif /* not AMIGA */ | 2507 #endif /* not AMIGA */ |
2583 #endif /* not ST_NLINK_TRICK */ | 2508 #endif /* not ST_NLINK_TRICK */ |
2584 /* All criteria are met; find subdirectories. */ | 2509 /* All criteria are met; find subdirectories. */ |
2585 do_subdir (str_list_ptr, FN_STRING (name), | 2510 do_subdir (str_list_ptr, name.c_str (), |
2586 potential_len, post); | 2511 potential_len, post); |
2587 #ifdef ST_NLINK_TRICK | 2512 #ifdef ST_NLINK_TRICK |
2588 else if (*post == 0) | 2513 else if (*post == 0) |
2589 /* Nothing to match, no recursive subdirectories to | 2514 /* Nothing to match, no recursive subdirectories to |
2590 look for: we're done with this branch. Add it. */ | 2515 look for: we're done with this branch. Add it. */ |
2591 dir_list_add (str_list_ptr, FN_STRING (name)); | 2516 dir_list_add (str_list_ptr, name.c_str ()); |
2592 #endif | 2517 #endif |
2593 } | 2518 } |
2594 | 2519 |
2595 /* Remove the directory entry we just checked from `name'. */ | 2520 /* Remove the directory entry we just checked from `name'. */ |
2596 fn_shrink_to (&name, elt_length); | 2521 name.resize (elt_length); |
2597 } | 2522 } |
2598 } | 2523 } |
2599 | 2524 |
2600 fn_free (&name); | |
2601 xclosedir (dir); | 2525 xclosedir (dir); |
2602 #endif /* not WIN32 */ | 2526 #endif /* not WIN32 */ |
2603 } | 2527 } |
2604 | 2528 |
2605 | 2529 |
3133 strcat (answer, s3); | 3057 strcat (answer, s3); |
3134 | 3058 |
3135 return answer; | 3059 return answer; |
3136 } | 3060 } |
3137 | 3061 |
3138 /* concatn.c: Concatenate an arbitrary number of strings. */ | |
3139 | |
3140 /* OK, it would be epsilon more efficient to compute the total length | |
3141 and then do the copying ourselves, but I doubt it matters in reality. */ | |
3142 | |
3143 char * | |
3144 concatn (const char *str1, ...) | |
3145 { | |
3146 char *arg; | |
3147 char *ret; | |
3148 va_list ap; | |
3149 | |
3150 va_start (ap, str1); | |
3151 | |
3152 if (!str1) | |
3153 return NULL; | |
3154 | |
3155 ret = xstrdup (str1); | |
3156 | |
3157 while ((arg = va_arg (ap, char *)) != NULL) | |
3158 { | |
3159 char *temp = concat (ret, arg); | |
3160 free (ret); | |
3161 ret = temp; | |
3162 } | |
3163 va_end (ap); | |
3164 | |
3165 return ret; | |
3166 } | |
3167 | |
3168 /* debug.c: Help the user discover what's going on. */ | 3062 /* debug.c: Help the user discover what's going on. */ |
3169 | 3063 |
3170 #ifdef KPSE_DEBUG | 3064 #ifdef KPSE_DEBUG |
3171 | 3065 |
3172 unsigned int kpathsea_debug = 0; | 3066 unsigned int kpathsea_debug = 0; |
3489 | 3383 |
3490 /* We've moved it. */ | 3384 /* We've moved it. */ |
3491 STR_LLIST_MOVED (*mover) = 1; | 3385 STR_LLIST_MOVED (*mover) = 1; |
3492 } | 3386 } |
3493 | 3387 |
3494 /* fn.c: arbitrarily long filenames (or just strings). */ | |
3495 | |
3496 /* /usr/local/lib/texmf/fonts/public/cm/pk/ljfour/cmr10.300pk is 58 | |
3497 chars, so ASCII `K' seems a good choice. */ | |
3498 #define CHUNK_SIZE 75 | |
3499 | |
3500 fn_type | |
3501 fn_init (void) | |
3502 { | |
3503 fn_type ret; | |
3504 | |
3505 FN_ALLOCATED (ret) = FN_LENGTH (ret) = 0; | |
3506 FN_STRING (ret) = NULL; | |
3507 | |
3508 return ret; | |
3509 } | |
3510 | |
3511 fn_type | |
3512 fn_copy0 (const char *s, unsigned len) | |
3513 { | |
3514 fn_type ret; | |
3515 | |
3516 FN_ALLOCATED (ret) = CHUNK_SIZE > len ? CHUNK_SIZE : len + 1; | |
3517 FN_STRING (ret) = (char *) xmalloc (FN_ALLOCATED (ret)); | |
3518 | |
3519 strncpy (FN_STRING (ret), s, len); | |
3520 FN_STRING (ret)[len] = 0; | |
3521 FN_LENGTH (ret) = len + 1; | |
3522 | |
3523 return ret; | |
3524 } | |
3525 | |
3526 /* Don't think we ever try to free something that might usefully be | |
3527 empty, so give fatal error if nothing allocated. */ | |
3528 | |
3529 void | |
3530 fn_free (fn_type *f) | |
3531 { | |
3532 assert (FN_STRING (*f) != NULL); | |
3533 free (FN_STRING (*f)); | |
3534 FN_STRING (*f) = NULL; | |
3535 FN_ALLOCATED (*f) = 0; | |
3536 FN_LENGTH (*f) = 0; | |
3537 } | |
3538 | |
3539 /* An arithmetic increase seems more reasonable than geometric. We | |
3540 don't increase the length member since it may be more convenient for | |
3541 the caller to add than subtract when appending the stuff that will | |
3542 presumably follow. */ | |
3543 | |
3544 static void | |
3545 grow (fn_type *f, unsigned len) | |
3546 { | |
3547 while (FN_LENGTH (*f) + len > FN_ALLOCATED (*f)) | |
3548 { | |
3549 FN_ALLOCATED (*f) += CHUNK_SIZE; | |
3550 XRETALLOC (FN_STRING (*f), FN_ALLOCATED (*f), char); | |
3551 } | |
3552 } | |
3553 | |
3554 void | |
3555 fn_1grow (fn_type *f, char c) | |
3556 { | |
3557 grow (f, 1); | |
3558 FN_STRING (*f)[FN_LENGTH (*f)] = c; | |
3559 FN_LENGTH (*f)++; | |
3560 } | |
3561 | |
3562 void | |
3563 fn_grow (fn_type *f, void *source, unsigned len) | |
3564 { | |
3565 grow (f, len); | |
3566 strncpy (FN_STRING (*f) + FN_LENGTH (*f), (char *) source, len); | |
3567 FN_LENGTH (*f) += len; | |
3568 } | |
3569 | |
3570 void | |
3571 fn_str_grow (fn_type *f, const char *s) | |
3572 { | |
3573 unsigned more_len = strlen (s); | |
3574 grow (f, more_len); | |
3575 strcat (FN_STRING (*f), s); | |
3576 FN_LENGTH (*f) += more_len; | |
3577 } | |
3578 | |
3579 void | |
3580 fn_shrink_to (fn_type *f, unsigned loc) | |
3581 { | |
3582 assert (FN_LENGTH (*f) > loc); | |
3583 FN_STRING (*f)[loc] = 0; | |
3584 FN_LENGTH (*f) = loc + 1; | |
3585 } | |
3586 | |
3587 /* variable.c: variable expansion. */ | 3388 /* variable.c: variable expansion. */ |
3588 | 3389 |
3589 /* Here's the simple one, when a program just wants a value. */ | 3390 /* Here's the simple one, when a program just wants a value. */ |
3590 | 3391 |
3591 char * | 3392 std::string |
3592 kpse_var_value (const char *var) | 3393 kpse_var_value (const char *var) |
3593 { | 3394 { |
3594 char *ret = getenv (var); | 3395 std::string ret; |
3595 | 3396 |
3596 if (ret) | 3397 char *tmp = getenv (var); |
3398 | |
3399 if (tmp) | |
3597 ret = kpse_var_expand (ret); | 3400 ret = kpse_var_expand (ret); |
3598 | 3401 |
3599 #ifdef KPSE_DEBUG | 3402 #ifdef KPSE_DEBUG |
3600 if (KPSE_DEBUG_P (KPSE_DEBUG_VARS)) | 3403 if (KPSE_DEBUG_P (KPSE_DEBUG_VARS)) |
3601 DEBUGF2("variable: %s = %s\n", var, ret ? ret : "(nil)"); | 3404 DEBUGF2("variable: %s = %s\n", var, tmp ? tmp : "(nil)"); |
3602 #endif | 3405 #endif |
3603 | 3406 |
3604 return ret; | 3407 return ret; |
3605 } | 3408 } |
3606 | 3409 |
3653 /* Append the result of value of `var' to EXPANSION, where `var' begins | 3456 /* Append the result of value of `var' to EXPANSION, where `var' begins |
3654 at START and ends at END. If `var' is not set, do not complain. | 3457 at START and ends at END. If `var' is not set, do not complain. |
3655 This is a subroutine for the more complicated expansion function. */ | 3458 This is a subroutine for the more complicated expansion function. */ |
3656 | 3459 |
3657 static void | 3460 static void |
3658 expand (fn_type *expansion, const char *start, const char *end) | 3461 expand (std::string &expansion, const char *start, const char *end) |
3659 { | 3462 { |
3660 char *value; | |
3661 unsigned len = end - start + 1; | 3463 unsigned len = end - start + 1; |
3662 char *var = (char *) xmalloc (len + 1); | 3464 char *var = (char *) xmalloc (len + 1); |
3663 strncpy (var, start, len); | 3465 strncpy (var, start, len); |
3664 var[len] = 0; | 3466 var[len] = 0; |
3665 | 3467 |
3666 if (expanding_p (var)) { | 3468 if (expanding_p (var)) { |
3667 WARNING1 ("kpathsea: variable `%s' references itself (eventually)", var); | 3469 WARNING1 ("kpathsea: variable `%s' references itself (eventually)", var); |
3668 } else { | 3470 } else { |
3669 /* Check for an environment variable. */ | 3471 /* Check for an environment variable. */ |
3670 value = getenv (var); | 3472 char *value = getenv (var); |
3671 | 3473 |
3672 if (value) { | 3474 if (value) { |
3673 expanding (var, 1); | 3475 expanding (var, 1); |
3674 value = kpse_var_expand (value); | 3476 std::string tmp = kpse_var_expand (value); |
3675 expanding (var, 0); | 3477 expanding (var, 0); |
3676 fn_grow (expansion, value, strlen (value)); | 3478 expansion += tmp; |
3677 free (value); | |
3678 } | 3479 } |
3679 | 3480 |
3680 free (var); | 3481 free (var); |
3681 } | 3482 } |
3682 } | 3483 } |
3698 | 3499 |
3699 | 3500 |
3700 /* Maybe we should support some or all of the various shell ${...} | 3501 /* Maybe we should support some or all of the various shell ${...} |
3701 constructs, especially ${var-value}. */ | 3502 constructs, especially ${var-value}. */ |
3702 | 3503 |
3703 char * | 3504 std::string |
3704 kpse_var_expand (const char *src) | 3505 kpse_var_expand (const std::string& src_arg) |
3705 { | 3506 { |
3706 const char *s; | 3507 const char *src = src_arg.c_str (); |
3707 char *ret; | 3508 const char *s = src; |
3708 fn_type expansion; | 3509 std::string expansion; |
3709 expansion = fn_init (); | |
3710 | 3510 |
3711 /* Copy everything but variable constructs. */ | 3511 /* Copy everything but variable constructs. */ |
3712 for (s = src; *s; s++) { | 3512 for (s = src; *s; s++) { |
3713 if (IS_VAR_START (*s)) { | 3513 if (IS_VAR_START (*s)) { |
3714 s++; | 3514 s++; |
3721 do { | 3521 do { |
3722 var_end++; | 3522 var_end++; |
3723 } while (IS_VAR_CHAR (*var_end)); | 3523 } while (IS_VAR_CHAR (*var_end)); |
3724 | 3524 |
3725 var_end--; /* had to go one past */ | 3525 var_end--; /* had to go one past */ |
3726 expand (&expansion, s, var_end); | 3526 expand (expansion, s, var_end); |
3727 s = var_end; | 3527 s = var_end; |
3728 | 3528 |
3729 } else if (IS_VAR_BEGIN_DELIMITER (*s)) { | 3529 } else if (IS_VAR_BEGIN_DELIMITER (*s)) { |
3730 /* ${: scan ahead for matching delimiter, then expand. */ | 3530 /* ${: scan ahead for matching delimiter, then expand. */ |
3731 const char *var_end = ++s; | 3531 const char *var_end = ++s; |
3735 | 3535 |
3736 if (! *var_end) { | 3536 if (! *var_end) { |
3737 WARNING1 ("%s: No matching } for ${", src); | 3537 WARNING1 ("%s: No matching } for ${", src); |
3738 s = var_end - 1; /* will incr to null at top of loop */ | 3538 s = var_end - 1; /* will incr to null at top of loop */ |
3739 } else { | 3539 } else { |
3740 expand (&expansion, s, var_end - 1); | 3540 expand (expansion, s, var_end - 1); |
3741 s = var_end; /* will incr past } at top of loop*/ | 3541 s = var_end; /* will incr past } at top of loop*/ |
3742 } | 3542 } |
3743 | 3543 |
3744 } else { | 3544 } else { |
3745 /* $<something-else>: error. */ | 3545 /* $<something-else>: error. */ |
3746 WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s); | 3546 WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s); |
3747 /* Just ignore those chars and keep going. */ | 3547 /* Just ignore those chars and keep going. */ |
3748 } | 3548 } |
3749 } else | 3549 } else |
3750 fn_1grow (&expansion, *s); | 3550 expansion += *s; |
3751 } | 3551 } |
3752 fn_1grow (&expansion, 0); | 3552 |
3753 | 3553 return expansion; |
3754 ret = FN_STRING (expansion); | 3554 } |
3755 return ret; | |
3756 } |