/* Utility functions for finding files relative to GCC binaries. Copyright (C) 1992-2017 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #include "config.h" #include "system.h" #include "filenames.h" #include "file-find.h" static bool debug = false; void find_file_set_debug (bool debug_state) { debug = debug_state; } char * find_a_file (struct path_prefix *pprefix, const char *name, int mode) { char *temp; struct prefix_list *pl; int len = pprefix->max_len + strlen (name) + 1; if (debug) fprintf (stderr, "Looking for '%s'\n", name); #ifdef HOST_EXECUTABLE_SUFFIX len += strlen (HOST_EXECUTABLE_SUFFIX); #endif temp = XNEWVEC (char, len); /* Determine the filename to execute (special case for absolute paths). */ if (IS_ABSOLUTE_PATH (name)) { if (access (name, mode) == 0) { strcpy (temp, name); if (debug) fprintf (stderr, " - found: absolute path\n"); return temp; } #ifdef HOST_EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ strcpy (temp, name); strcat (temp, HOST_EXECUTABLE_SUFFIX); if (access (temp, mode) == 0) return temp; #endif if (debug) fprintf (stderr, " - failed to locate using absolute path\n"); } else for (pl = pprefix->plist; pl; pl = pl->next) { struct stat st; strcpy (temp, pl->prefix); strcat (temp, name); if (stat (temp, &st) >= 0 && ! S_ISDIR (st.st_mode) && access (temp, mode) == 0) return temp; #ifdef HOST_EXECUTABLE_SUFFIX /* Some systems have a suffix for executable files. So try appending that. */ strcat (temp, HOST_EXECUTABLE_SUFFIX); if (stat (temp, &st) >= 0 && ! S_ISDIR (st.st_mode) && access (temp, mode) == 0) return temp; #endif } if (debug && pprefix->plist == NULL) fprintf (stderr, " - failed: no entries in prefix list\n"); free (temp); return 0; } /* Add an entry for PREFIX to prefix list PREFIX. Add at beginning if FIRST is true. */ void do_add_prefix (struct path_prefix *pprefix, const char *prefix, bool first) { struct prefix_list *pl, **prev; int len; if (pprefix->plist && !first) { for (pl = pprefix->plist; pl->next; pl = pl->next) ; prev = &pl->next; } else prev = &pprefix->plist; /* Keep track of the longest prefix. */ len = strlen (prefix); if (len > pprefix->max_len) pprefix->max_len = len; pl = XNEW (struct prefix_list); pl->prefix = xstrdup (prefix); if (*prev) pl->next = *prev; else pl->next = (struct prefix_list *) 0; *prev = pl; } /* Add an entry for PREFIX at the end of prefix list PREFIX. */ void add_prefix (struct path_prefix *pprefix, const char *prefix) { do_add_prefix (pprefix, prefix, false); } /* Add an entry for PREFIX at the begin of prefix list PREFIX. */ void add_prefix_begin (struct path_prefix *pprefix, const char *prefix) { do_add_prefix (pprefix, prefix, true); } /* Take the value of the environment variable ENV, break it into a path, and add of the entries to PPREFIX. */ void prefix_from_env (const char *env, struct path_prefix *pprefix) { const char *p; p = getenv (env); if (p) prefix_from_string (p, pprefix); } void prefix_from_string (const char *p, struct path_prefix *pprefix) { const char *startp, *endp; char *nstore = XNEWVEC (char, strlen (p) + 3); if (debug) fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); startp = endp = p; while (1) { if (*endp == PATH_SEPARATOR || *endp == 0) { strncpy (nstore, startp, endp-startp); if (endp == startp) { strcpy (nstore, "./"); } else if (! IS_DIR_SEPARATOR (endp[-1])) { nstore[endp-startp] = DIR_SEPARATOR; nstore[endp-startp+1] = 0; } else nstore[endp-startp] = 0; if (debug) fprintf (stderr, " - add prefix: %s\n", nstore); add_prefix (pprefix, nstore); if (*endp == 0) break; endp = startp = endp + 1; } else endp++; } free (nstore); } void remove_prefix (const char *prefix, struct path_prefix *pprefix) { struct prefix_list *remove, **prev, **remove_prev = NULL; int max_len = 0; if (pprefix->plist) { prev = &pprefix->plist; for (struct prefix_list *pl = pprefix->plist; pl->next; pl = pl->next) { if (strcmp (prefix, pl->prefix) == 0) { remove = pl; remove_prev = prev; continue; } int l = strlen (pl->prefix); if (l > max_len) max_len = l; prev = &pl; } if (remove_prev) { *remove_prev = remove->next; free (remove); } pprefix->max_len = max_len; } }