void kpse_clear_dir_cache P1H(void) { while (cache_length > 0) { str_llist_type elt = *the_cache[--cache_length].value; while (elt) { str_llist_type next = STR_LLIST_NEXT (*elt); string s = STR_LLIST (*elt); if (s) free (s); free (elt); elt = next; } } if (the_cache) free (the_cache); the_cache = NULL; }
/* Expand all special constructs in a path, and include only the actually existing directories in the result. */ string kpse_path_expand P1C(const_string, path) { string ret; string xpath; string elt; unsigned len; /* Initialise ret to the empty string. */ ret = (string)xmalloc (1); *ret = 0; len = 0; /* Expand variables and braces first. */ xpath = kpse_brace_expand (path); /* Now expand each of the path elements, printing the results */ for (elt = kpse_path_element (xpath); elt; elt = kpse_path_element (NULL)) { str_llist_type *dirs; /* Skip and ignore magic leading chars. */ if (*elt == '!' && *(elt + 1) == '!') elt += 2; /* Search the disk for all dirs in the component specified. Be faster to check the database, but this is more reliable. */ dirs = kpse_element_dirs (elt); if (dirs && *dirs) { str_llist_elt_type *dir; for (dir = *dirs; dir; dir = STR_LLIST_NEXT (*dir)) { string thedir = STR_LLIST (*dir); unsigned dirlen = strlen (thedir); string save_ret = ret; /* We need to retain trailing slash if that's the root directory. * On unix, "/" is root dir, "" often taken to be current dir. * On windows, "C:/" is root dir of drive C, and "C:" is current * on drive C. There's no need to look at other cases, like UNC * names. */ if (dirlen == 1 || (dirlen == 3 && NAME_BEGINS_WITH_DEVICE (thedir) && IS_DIR_SEP (thedir[2]))) { ret = concat3 (ret, thedir, ENV_SEP_STRING); len += dirlen + 1; ret[len - 1] = ENV_SEP; } else { ret = concat (ret, thedir); len += dirlen; ret [len - 1] = ENV_SEP; } free (save_ret); } } } /* Get rid of trailing ':', if any. */ if (len != 0) ret[len - 1] = 0; return ret; }
static str_list_type dir_list_search_list P3C(str_llist_type *, dirs, const_string*, names, boolean, search_all) { str_llist_elt_type *elt; str_list_type ret; unsigned allocated = INIT_ALLOC; string potential = XTALLOC(allocated, char); ret = str_list_init (); for (elt = *dirs; elt; elt = STR_LLIST_NEXT(*elt)) { const_string dir = STR_LLIST (*elt); unsigned dir_len = strlen (dir); int i; for (i = 0; names[i]; i++) { const_string name = names[i]; unsigned name_len; /* Don't bother with absolute & explicit relative. */ if (kpse_absolute_p(name, true)) continue; name_len = strlen(name); while (dir_len + name_len + 1 > allocated) { allocated += allocated; XRETALLOC (potential, allocated, char); } strcpy (potential, dir); strcat (potential+dir_len, name); if (kpse_readable_file (potential)) { str_list_add (&ret, potential); /* Move this element towards the top of the list. */ str_llist_float (dirs, elt); /* If caller only wanted one file returned, no need to terminate the list with NULL; the caller knows to only look at the first element. */ if (!search_all) return ret; /* Start new filename. */ allocated = INIT_ALLOC; potential = XTALLOC(allocated, char); } } } /* If we get here, either we didn't find any files, or we were finding all the files. But we're done with the last filename, anyway. */ free (potential); return ret; }
str_llist_type * kpathsea_element_dirs (kpathsea kpse, string elt) { str_llist_type *ret; unsigned i; /* If given nothing, return nothing. */ if (!elt || !*elt) return NULL; /* Normalize ELT before looking for a cached value. */ i = kpathsea_normalize_path (kpse, elt); /* If we've already cached the answer for ELT, return it. */ ret = cached (kpse, elt); if (ret) return ret; /* We're going to have a real directory list to return. */ ret = XTALLOC1 (str_llist_type); *ret = NULL; /* We handle the hard case in a subroutine. */ expand_elt (kpse, ret, elt, i); /* Remember the directory list we just found, in case future calls are made with the same ELT. */ cache (kpse, elt, ret); #ifdef KPSE_DEBUG if (KPATHSEA_DEBUG_P (KPSE_DEBUG_EXPAND)) { DEBUGF1 ("path element %s =>", elt); if (ret) { str_llist_elt_type *e; for (e = *ret; e; e = STR_LLIST_NEXT (*e)) fprintf (stderr, " %s", STR_LLIST (*e)); } putc ('\n', stderr); fflush (stderr); } #endif /* KPSE_DEBUG */ return ret; }
void print_element_dirs (const_string elt) { str_llist_type *dirs; printf ("Directories of %s:\t", elt ? elt : "(nil)"); fflush (stdout); dirs = kpathsea_element_dirs (kpse_def, elt); if (!dirs) printf ("(nil)"); else { str_llist_elt_type *dir; for (dir = *dirs; dir; dir = STR_LLIST_NEXT (*dir)) { string d = STR_LLIST (*dir); printf ("%s ", *d ? d : "`'"); } } putchar ('\n'); }