/* Utility functions for finding files relative to GCC binaries.
   Copyright (C) 1992-2021 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
<http://www.gnu.org/licenses/>.  */

#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);
}
