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 }