rem: is_done = (*pdir == NULL) ? -1 : 1;
add: is_done = (*pdir == 0) ? -1 : 1;
context: static	int	lt_dlpath_insertdir   LT_PARAMS((char **ppath,						 char *before,						 const char *dir));static	int	list_files_by_dir     LT_PARAMS((const char *dirnam,						 char **pargz,						 size_t *pargz_len));static	int	file_not_found	      LT_PARAMS((void));static	char	       *user_search_path= NULL;static	lt_dlloader    *loaders		= NULL;static	lt_dlhandle	handles 	= NULL;static	int		initialized 	= 0;/* Initialize libltdl. */intlt_dlinit (){  int	      errors   = 0;  LT_DLMUTEX_LOCK ();  /* Initialize only at first call. */  if (++initialized == 1)    {      handles = NULL;      user_search_path = NULL; /* empty search path */#if HAVE_LIBDL && !defined(__CYGWIN__)      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");#endif#if HAVE_SHL_LOAD      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");#endif#ifdef __WINDOWS__      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");#endif#ifdef __BEOS__      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");#endif#if HAVE_DLD      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");#endif      errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");      if (presym_init (presym.dlloader_data))	{	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));	  ++errors;	}      else if (errors != 0)	{	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));	  ++errors;	}    }  LT_DLMUTEX_UNLOCK ();  return errors;}intlt_dlpreload (preloaded)     const lt_dlsymlist *preloaded;{  int errors = 0;  if (preloaded)    {      errors = presym_add_symlist (preloaded);    }  else    {      presym_free_symlists();      LT_DLMUTEX_LOCK ();      if (default_preloaded_symbols)	{	  errors = lt_dlpreload (default_preloaded_symbols);	}      LT_DLMUTEX_UNLOCK ();    }  return errors;}intlt_dlpreload_default (preloaded)     const lt_dlsymlist *preloaded;{  LT_DLMUTEX_LOCK ();  default_preloaded_symbols = preloaded;  LT_DLMUTEX_UNLOCK ();  return 0;}intlt_dlexit (){  /* shut down libltdl */  lt_dlloader *loader;  int	       errors   = 0;  LT_DLMUTEX_LOCK ();  loader = loaders;  if (!initialized)    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));      ++errors;      goto done;    }  /* shut down only at last call. */  if (--initialized == 0)    {      int	level;      while (handles && LT_DLIS_RESIDENT (handles))	{	  handles = handles->next;	}      /* close all modules */      for (level = 1; handles; ++level)	{	  lt_dlhandle cur = handles;	  int saw_nonresident = 0;	  while (cur)	    {	      lt_dlhandle tmp = cur;	      cur = cur->next;	      if (!LT_DLIS_RESIDENT (tmp))		saw_nonresident = 1;	      if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)		{		  if (lt_dlclose (tmp))		    {		      ++errors;		    }		}	    }	  /* done if only resident modules are left */	  if (!saw_nonresident)	    break;	}      /* close all loaders */      while (loader)	{	  lt_dlloader *next = loader->next;	  lt_user_data data = loader->dlloader_data;	  if (loader->dlloader_exit && loader->dlloader_exit (data))	    {	      ++errors;	    }	  LT_DLMEM_REASSIGN (loader, next);	}      loaders = NULL;    } done:  LT_DLMUTEX_UNLOCK ();  return errors;}static inttryall_dlopen (handle, filename)     lt_dlhandle *handle;     const char *filename;{  lt_dlhandle	 cur;  lt_dlloader   *loader;  const char	*saved_error;  int		 errors		= 0;  LT_DLMUTEX_GETERROR (saved_error);  LT_DLMUTEX_LOCK ();  cur	 = handles;  loader = loaders;  /* check whether the module was already opened */  while (cur)    {      /* try to dlopen the program itself? */      if (!cur->info.filename && !filename)	{	  break;	}      if (cur->info.filename && filename	  && strcmp (cur->info.filename, filename) == 0)	{	  break;	}      cur = cur->next;    }  if (cur)    {      ++cur->info.ref_count;      *handle = cur;      goto done;    }  cur = *handle;  if (filename)    {      cur->info.filename = lt_estrdup (filename);      if (!cur->info.filename)	{	  ++errors;	  goto done;	}    }  else    {      cur->info.filename = NULL;    }  while (loader)    {      lt_user_data data = loader->dlloader_data;      cur->module = loader->module_open (data, filename);      if (cur->module != NULL)	{	  break;	}      loader = loader->next;    }  if (!loader)    {      LT_DLFREE (cur->info.filename);      ++errors;      goto done;    }  cur->loader	= loader;  LT_DLMUTEX_SETERROR (saved_error); done:  LT_DLMUTEX_UNLOCK ();  return errors;}static inttryall_dlopen_module (handle, prefix, dirname, dlname)     lt_dlhandle *handle;     const char *prefix;     const char *dirname;     const char *dlname;{  int      error	= 0;  char     *filename	= NULL;  size_t   filename_len	= 0;  size_t   dirname_len	= LT_STRLEN (dirname);  assert (handle);  assert (dirname);  assert (dlname);#ifdef LT_DIRSEP_CHAR  /* Only canonicalized names (i.e. with DIRSEP chars already converted)     should make it into this function:  */  assert (strchr (dirname, LT_DIRSEP_CHAR) == NULL);#endif  if (dirname[dirname_len -1] == '/')    --dirname_len;  filename_len = dirname_len + 1 + LT_STRLEN (dlname);  /* Allocate memory, and combine DIRNAME and MODULENAME into it.     The PREFIX (if any) is handled below.  */  filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);  if (!filename)    return 1;  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);  /* Now that we have combined DIRNAME and MODULENAME, if there is     also a PREFIX to contend with, simply recurse with the arguments     shuffled.  Otherwise, attempt to open FILENAME as a module.  */  if (prefix)    {      error += tryall_dlopen_module (handle,				     (const char *) 0, prefix, filename);    }  else if (tryall_dlopen (handle, filename) != 0)    {      ++error;    }  LT_DLFREE (filename);  return error;}static intfind_module (handle, dir, libdir, dlname, old_name, installed)     lt_dlhandle *handle;     const char *dir;     const char *libdir;     const char *dlname;     const char *old_name;     int installed;{  /* Try to open the old library first; if it was dlpreopened,     we want the preopened version of it, even if a dlopenable     module is available.  */  if (old_name && tryall_dlopen (handle, old_name) == 0)    {      return 0;    }  /* Try to open the dynamic library.  */  if (dlname)    {      /* try to open the installed module */      if (installed && libdir)	{	  if (tryall_dlopen_module (handle,				    (const char *) 0, libdir, dlname) == 0)	    return 0;	}      /* try to open the not-installed module */      if (!installed)	{	  if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)	    return 0;	}      /* maybe it was moved to another directory */      {	  if (tryall_dlopen_module (handle,				    (const char *) 0, dir, dlname) == 0)	    return 0;      }    }  return 1;}static intcanonicalize_path (path, pcanonical)     const char *path;     char **pcanonical;{  char *canonical = NULL;  assert (path && *path);  assert (pcanonical);  canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));  if (!canonical)    return 1;  {    size_t dest = 0;    size_t src;    for (src = 0; path[src] != LT_EOS_CHAR; ++src)      {	/* Path separators are not copied to the beginning or end of	   the destination, or if another separator would follow	   immediately.  */	if (path[src] == LT_PATHSEP_CHAR)	  {	    if ((dest == 0)		|| (path[1+ src] == LT_PATHSEP_CHAR)		|| (path[1+ src] == LT_EOS_CHAR))	      continue;	  }	/* Anything other than a directory separator is copied verbatim.  */	if ((path[src] != '/')#ifdef LT_DIRSEP_CHAR	    && (path[src] != LT_DIRSEP_CHAR)#endif	    )	  {	    canonical[dest++] = path[src];	  }	/* Directory separators are converted and copied only if they are	   not at the end of a path -- i.e. before a path separator or	   NULL terminator.  */	else if ((path[1+ src] != LT_PATHSEP_CHAR)		 && (path[1+ src] != LT_EOS_CHAR)#ifdef LT_DIRSEP_CHAR		 && (path[1+ src] != LT_DIRSEP_CHAR)#endif		 && (path[1+ src] != '/'))	  {	    canonical[dest++] = '/';	  }      }    /* Add an end-of-string marker at the end.  */    canonical[dest] = LT_EOS_CHAR;  }  /* Assign new value.  */  *pcanonical = canonical;  return 0;}static intargzize_path (path, pargz, pargz_len)     const char *path;     char **pargz;     size_t *pargz_len;{  error_t error;  assert (path);  assert (pargz);  assert (pargz_len);  if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))    {      switch (error)	{	case ENOMEM:	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));	  break;	default:	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));	  break;	}      return 1;    }  return 0;}/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element   of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns   non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,   it is appended to each SEARCH_PATH element before FUNC is called.  */static intforeach_dirinpath (search_path, base_name, func, data1, data2)     const char *search_path;     const char *base_name;     foreach_callback_func *func;     lt_ptr data1;     lt_ptr data2;{  int	 result		= 0;  int	 filenamesize	= 0;  size_t lenbase	= LT_STRLEN (base_name);  size_t argz_len	= 0;  char *argz		= NULL;  char *filename	= NULL;  char *canonical	= NULL;  LT_DLMUTEX_LOCK ();  if (!search_path || !*search_path)    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));      goto cleanup;    }  if (canonicalize_path (search_path, &canonical) != 0)    goto cleanup;  if (argzize_path (canonical, &argz, &argz_len) != 0)    goto cleanup;  {    char *dir_name = NULL;    while ((dir_name = argz_next (argz, argz_len, dir_name)))      {	size_t lendir = LT_STRLEN (dir_name);	if (lendir +1 +lenbase >= filenamesize)	{	  LT_DLFREE (filename);	  filenamesize	= lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */	  filename	= LT_EMALLOC (char, filenamesize);	  if (!filename)	    goto cleanup;	}	assert (filenamesize > lendir);	strcpy (filename, dir_name);	if (base_name && *base_name)	  {	    if (filename[lendir -1] != '/')	      filename[lendir++] = '/';	    strcpy (filename +lendir, base_name);	  }	if ((result = (*func) (filename, data1, data2)))	  {	    break;	  }      }  } cleanup:  LT_DLFREE (argz);  LT_DLFREE (canonical);  LT_DLFREE (filename);  LT_DLMUTEX_UNLOCK ();  return result;}/* If FILEPATH can be opened, store the name of the directory component   in DATA1, and the opened FILE* structure address in DATA2.  Otherwise   DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */static intfind_file_callback (filename, data1, data2)     char *filename;     lt_ptr data1;     lt_ptr data2;{  char	     **pdir	= (char **) data1;  FILE	     **pfile	= (FILE **) data2;  int	     is_done	= 0;  assert (filename && *filename);  assert (pdir);  assert (pfile);  if ((*pfile = fopen (filename, LT_READTEXT_MODE)))    {      char *dirend = strrchr (filename, '/');      if (dirend > filename)	*dirend   = LT_EOS_CHAR;      LT_DLFREE (*pdir);      *pdir   = lt_estrdup (filename);      is_done = (*pdir == NULL) ? -1 : 1;    }  return is_done;}static FILE *find_file (search_path, base_name, pdir)     const char *search_path;     const char *base_name;     char **pdir;{  FILE *file = NULL;  foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);  return file;}static intfind_handle_callback (filename, data, ignored)     char *filename;     lt_ptr data;     lt_ptr ignored;{  lt_dlhandle  *handle		= (lt_dlhandle *) data;  int		notfound	= access (filename, R_OK);  /* Bail out if file cannot be read...  */  if (notfound)    return 0;  /* Try to dlopen the file, but do not continue searching in any     case.  */  if (tryall_dlopen (handle, filename) != 0)    *handle = NULL;  return 1;}/* If HANDLE was found return it, otherwise return 0.  If HANDLE was   found but could not be opened, *HANDLE will be set to 0.  */static lt_dlhandle *find_handle (search_path, base_name, handle)     const char *search_path;     const char *base_name;     lt_dlhandle *handle;{  if (!search_path)    return 0;  if (!foreach_dirinpath (search_path, base_name, find_handle_callback,			  handle, 0))    return 0;  return handle;}static intload_deplibs (handle, deplibs)     lt_dlhandle handle;     char *deplibs;{#if LTDL_DLOPEN_DEPLIBS  char	*p, *save_search_path = NULL;  int   depcount = 0;  int	i;  char	**names = NULL;#endif  int	errors = 0;  handle->depcount = 0;#if LTDL_DLOPEN_DEPLIBS  if (!deplibs)    {      return errors;    }  ++errors;  LT_DLMUTEX_LOCK ();  if (user_search_path)    {      save_search_path = lt_estrdup (user_search_path);      if (!save_search_path)	goto cleanup;    }  /* extract search paths and count deplibs */  p = deplibs;  while (*p)    {      if (!isspace ((int) *p))	{	  char *end = p+1;	  while (*end && !isspace((int) *end))	    {	      ++end;	    }	  if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)	    {	      char save = *end;	      *end = '\0'; /* set a temporary string terminator */	      if (lt_dladdsearchdir(p+2))		{		  goto cleanup;		}	      *end = save;	    }	  else	    {	      ++depcount;	    }	  p = end;	}      else	{	  ++p;	}    }  /* restore the old search path */  LT_DLFREE (user_search_path);  user_search_path = save_search_path;  LT_DLMUTEX_UNLOCK ();  if (!depcount)    {      errors = 0;      goto cleanup;    }  names = LT_EMALLOC (char *, depcount * sizeof (char*));  if (!names)    goto cleanup;  /* now only extract the actual deplibs */  depcount = 0;  p = deplibs;  while (*p)    {      if (isspace ((int) *p))	{	  ++p;	}      else	{	  char *end = p+1;	  while (*end && !isspace ((int) *end))	    {	      ++end;	    }	  if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)	    {	      char *name;	      char save = *end;	      *end = '\0'; /* set a temporary string terminator */	      if (strncmp(p, "-l", 2) == 0)		{		  size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);		  name = LT_EMALLOC (char, 1+ name_len);		  if (name)		    sprintf (name, "lib%s", p+2);		}	      else		name = lt_estrdup(p);	      if (!name)		goto cleanup_names;	      names[depcount++] = name;	      *end = save;	    }	  p = end;	}    }  /* load the deplibs (in reverse order)     At this stage, don't worry if the deplibs do not load correctly,     they may already be statically linked into the loading application     for instance.  There will be a more enlightening error message     later on if the loaded module cannot resolve all of its symbols.  */  if (depcount)    {      int	j = 0;      handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);      if (!handle->deplibs)	goto cleanup;      for (i = 0; i < depcount; ++i)	{	  handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);	  if (handle->deplibs[j])	    {	      ++j;	    }	}      handle->depcount	= j;	/* Number of successfully loaded deplibs */      errors		= 0;    } cleanup_names:  for (i = 0; i < depcount; ++i)    {      LT_DLFREE (names[i]);    } cleanup:  LT_DLFREE (names);#endif  return errors;}static intunload_deplibs (handle)     lt_dlhandle handle;{  int i;  int errors = 0;  if (handle->depcount)    {      for (i = 0; i < handle->depcount; ++i)	{	  if (!LT_DLIS_RESIDENT (handle->deplibs[i]))	    {	      errors += lt_dlclose (handle->deplibs[i]);	    }	}    }  return errors;}static inttrim (dest, str)     char **dest;     const char *str;{  /* remove the leading and trailing "'" from str     and store the result in dest */  const char *end   = strrchr (str, '\'');  size_t len	    = LT_STRLEN (str);  char *tmp;  LT_DLFREE (*dest);  if (len > 3 && str[0] == '\'')    {      tmp = LT_EMALLOC (char, end - str);      if (!tmp)	return 1;      strncpy(tmp, &str[1], (end - str) - 1);      tmp[len-3] = LT_EOS_CHAR;      *dest = tmp;    }  else    {      *dest = NULL;    }  return 0;}static intfree_vars (dlname, oldname, libdir, deplibs)     char *dlname;     char *oldname;     char *libdir;     char *deplibs;{  LT_DLFREE (dlname);  LT_DLFREE (oldname);  LT_DLFREE (libdir);  LT_DLFREE (deplibs);  return 0;}static inttry_dlopen (phandle, filename)     lt_dlhandle *phandle;     const char *filename;{  const char *	ext		= NULL;  const char *	saved_error	= NULL;  char *	canonical	= NULL;  char *	base_name	= NULL;  char *	dir		= NULL;  char *	name		= NULL;  int		errors		= 0;  lt_dlhandle	newhandle;  assert (phandle);  assert (*phandle == NULL);  LT_DLMUTEX_GETERROR (saved_error);  /* dlopen self? */  if (!filename)    {      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);      if (*phandle == NULL)	return 1;      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));      newhandle	= *phandle;      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */      LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);      if (tryall_dlopen (&newhandle, 0) != 0)	{	  LT_DLFREE (*phandle);	  return 1;	}      goto register_handle;    }  assert (filename && *filename);  /* Doing this immediately allows internal functions to safely     assume only canonicalized paths are passed.  */  if (canonicalize_path (filename, &canonical) != 0)    {      ++errors;      goto cleanup;    }  /* If the canonical module name is a path (relative or absolute)     then split it into a directory part and a name part.  */  base_name = strrchr (canonical, '/');  if (base_name)    {      size_t dirlen = (1+ base_name) - canonical;      dir = LT_EMALLOC (char, 1+ dirlen);      if (!dir)	{	  ++errors;	  goto cleanup;	}      strncpy (dir, canonical, dirlen);      dir[dirlen] = LT_EOS_CHAR;      ++base_name;    }  else    LT_DLMEM_REASSIGN (base_name, canonical);  assert (base_name && *base_name);  /* Check whether we are opening a libtool module (.la extension).  */  ext = strrchr (base_name, '.');  if (ext && strcmp (ext, archive_ext) == 0)    {      /* this seems to be a libtool module */      FILE *	file	 = NULL;      char *	dlname	 = NULL;      char *	old_name = NULL;      char *	libdir	 = NULL;      char *	deplibs	 = NULL;      char *    line	 = NULL;      size_t	line_len;      /* if we can't find the installed flag, it is probably an	 installed libtool archive, produced with an old version	 of libtool */      int	installed = 1;      /* extract the module name from the file name */      name = LT_EMALLOC (char, ext - base_name + 1);      if (!name)	{	  ++errors;	  goto cleanup;	}      /* canonicalize the module name */      {        size_t i;        for (i = 0; i < ext - base_name; ++i)	  {	    if (isalnum ((int)(base_name[i])))	      {	        name[i] = base_name[i];	      }	    else	      {	        name[i] = '_';	      }	  }        name[ext - base_name] = LT_EOS_CHAR;      }      /* Now try to open the .la file.  If there is no directory name         component, try to find it first in user_search_path and then other         prescribed paths.  Otherwise (or in any case if the module was not         yet found) try opening just the module name as passed.  */      if (!dir)	{	  const char *search_path;	  LT_DLMUTEX_LOCK ();	  search_path = user_search_path;	  if (search_path)	    file = find_file (user_search_path, base_name, &dir);	  LT_DLMUTEX_UNLOCK ();	  if (!file)	    {	      search_path = getenv (LTDL_SEARCHPATH_VAR);	      if (search_path)		file = find_file (search_path, base_name, &dir);	    }#ifdef LTDL_SHLIBPATH_VAR	  if (!file)	    {	      search_path = getenv (LTDL_SHLIBPATH_VAR);	      if (search_path)		file = find_file (search_path, base_name, &dir);	    }#endif#ifdef LTDL_SYSSEARCHPATH	  if (!file && sys_search_path)	    {	      file = find_file (sys_search_path, base_name, &dir);	    }#endif	}      if (!file)	{	  file = fopen (filename, LT_READTEXT_MODE);	}      /* If we didn't find the file by now, it really isn't there.  Set	 the status flag, and bail out.  */      if (!file)	{	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));	  ++errors;	  goto cleanup;	}      line_len = LT_FILENAME_MAX;      line = LT_EMALLOC (char, line_len);      if (!line)	{	  fclose (file);	  ++errors;	  goto cleanup;	}      /* read the .la file */      while (!feof (file))	{	  if (!fgets (line, (int) line_len, file))	    {	      break;	    }	  /* Handle the case where we occasionally need to read a line	     that is longer than the initial buffer size.  */	  while (line[LT_STRLEN(line) -1] != '\n')	    {	      line = LT_DLREALLOC (char, line, line_len *2);	      if (!fgets (&line[line_len -1], (int) line_len +1, file))		{		  break;		}	      line_len *= 2;	    }	  if (line[0] == '\n' || line[0] == '#')	    {	      continue;	    }#undef  STR_DLNAME#define STR_DLNAME	"dlname="	  if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)	    {	      errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);	    }#undef  STR_OLD_LIBRARY#define STR_OLD_LIBRARY	"old_library="	  else if (strncmp (line, STR_OLD_LIBRARY,			    sizeof (STR_OLD_LIBRARY) - 1) == 0)	    {	      errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);	    }#undef  STR_LIBDIR#define STR_LIBDIR	"libdir="	  else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)	    {	      errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);	    }#undef  STR_DL_DEPLIBS#define STR_DL_DEPLIBS	"dependency_libs="	  else if (strncmp (line, STR_DL_DEPLIBS,			    sizeof (STR_DL_DEPLIBS) - 1) == 0)	    {	      errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);	    }	  else if (strcmp (line, "installed=yes\n") == 0)	    {	      installed = 1;	    }	  else if (strcmp (line, "installed=no\n") == 0)	    {	      installed = 0;	    }#undef  STR_LIBRARY_NAMES#define STR_LIBRARY_NAMES "library_names="	  else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,					sizeof (STR_LIBRARY_NAMES) - 1) == 0)	    {	      char *last_libname;	      errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);	      if (!errors		  && dlname		  && (last_libname = strrchr (dlname, ' ')) != NULL)		{		  last_libname = lt_estrdup (last_libname + 1);		  if (!last_libname)		    {		      ++errors;		      goto cleanup;		    }		  LT_DLMEM_REASSIGN (dlname, last_libname);		}	    }	  if (errors)	    break;	}      fclose (file);      LT_DLFREE (line);      /* allocate the handle */      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);      if (*phandle == NULL)	++errors;      if (errors)	{	  free_vars (dlname, old_name, libdir, deplibs);	  LT_DLFREE (*phandle);	  goto cleanup;	}      assert (*phandle);      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));      if (load_deplibs (*phandle, deplibs) == 0)	{	  newhandle = *phandle;	  /* find_module may replace newhandle */	  if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))	    {	      unload_deplibs (*phandle);	      ++errors;	    }	}      else	{	  ++errors;	}      free_vars (dlname, old_name, libdir, deplibs);      if (errors)	{	  LT_DLFREE (*phandle);	  goto cleanup;	}      if (*phandle != newhandle)	{	  unload_deplibs (*phandle);	}    }  else    {      /* not a libtool module */      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);      if (*phandle == NULL)	{	  ++errors;	  goto cleanup;	}      memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));      newhandle = *phandle;      /* If the module has no directory name component, try to find it	 first in user_search_path and then other prescribed paths.	 Otherwise (or in any case if the module was not yet found) try	 opening just the module name as passed.  */      if ((dir || (!find_handle (user_search_path, base_name, &newhandle)		   && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,				    &newhandle)#ifdef LTDL_SHLIBPATH_VAR		   && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,				    &newhandle)#endif#ifdef LTDL_SYSSEARCHPATH		   && !find_handle (sys_search_path, base_name, &newhandle)#endif		   )))	{          if (tryall_dlopen (&newhandle, filename) != 0)            {              newhandle = NULL;            }	}      if (!newhandle)	{	  LT_DLFREE (*phandle);	  ++errors;	  goto cleanup;	}    } register_handle:  LT_DLMEM_REASSIGN (*phandle, newhandle);  if ((*phandle)->info.ref_count == 0)    {      (*phandle)->info.ref_count	= 1;      LT_DLMEM_REASSIGN ((*phandle)->info.name, name);      LT_DLMUTEX_LOCK ();      (*phandle)->next		= handles;      handles			= *phandle;      LT_DLMUTEX_UNLOCK ();    }  LT_DLMUTEX_SETERROR (saved_error); cleanup:  LT_DLFREE (dir);  LT_DLFREE (name);  LT_DLFREE (canonical);  return errors;}lt_dlhandlelt_dlopen (filename)     const char *filename;{  lt_dlhandle handle = NULL;  /* Just incase we missed a code path in try_dlopen() that reports     an error, but forgets to reset handle... */  if (try_dlopen (&handle, filename) != 0)    return 0;  return handle;}/* If the last error messge store was `FILE_NOT_FOUND', then return   non-zero.  */static intfile_not_found (){  const char *error = NULL;  LT_DLMUTEX_GETERROR (error);  if (error == LT_DLSTRERROR (FILE_NOT_FOUND))    return 1;  return 0;}/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,   and if a file is still not found try again with SHLIB_EXT appended   instead.  */lt_dlhandlelt_dlopenext (filename)     const char *filename;{  lt_dlhandle	handle		= NULL;  char *	tmp		= NULL;  char *	ext		= NULL;  size_t	len;  int		errors		= 0;  if (!filename)    {      return lt_dlopen (filename);    }  assert (filename);  len = LT_STRLEN (filename);  ext = strrchr (filename, '.');  /* If FILENAME already bears a suitable extension, there is no need     to try appending additional extensions.  */  if (ext && ((strcmp (ext, archive_ext) == 0)#ifdef LTDL_SHLIB_EXT	      || (strcmp (ext, shlib_ext) == 0)#endif      ))    {      return lt_dlopen (filename);    }  /* First try appending ARCHIVE_EXT.  */  tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);  if (!tmp)    return 0;  strcpy (tmp, filename);  strcat (tmp, archive_ext);  errors = try_dlopen (&handle, tmp);  /* If we found FILENAME, stop searching -- whether we were able to     load the file as a module or not.  If the file exists but loading     failed, it is better to return an error message here than to     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not     in the module search path.  */  if (handle || ((errors > 0) && !file_not_found ()))    {      LT_DLFREE (tmp);      return handle;    }#ifdef LTDL_SHLIB_EXT  /* Try appending SHLIB_EXT.   */  if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))    {      LT_DLFREE (tmp);      tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);      if (!tmp)	return 0;      strcpy (tmp, filename);    }  else    {      tmp[len] = LT_EOS_CHAR;    }  strcat(tmp, shlib_ext);  errors = try_dlopen (&handle, tmp);  /* As before, if the file was found but loading failed, return now     with the current error message.  */  if (handle || ((errors > 0) && !file_not_found ()))    {      LT_DLFREE (tmp);      return handle;    }#endif  /* Still here?  Then we really did fail to locate any of the file     names we tried.  */  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));  LT_DLFREE (tmp);  return 0;}static intlt_argz_insert (pargz, pargz_len, before, entry)     char **pargz;     size_t *pargz_len;     char *before;     const char *entry;{  error_t error;  if ((error = argz_insert (pargz, pargz_len, before, entry)))    {      switch (error)	{	case ENOMEM:	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));	  break;	default:	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));	  break;	}      return 1;    }  return 0;}static intlt_argz_insertinorder (pargz, pargz_len, entry)     char **pargz;     size_t *pargz_len;     const char *entry;{  char *before = NULL;  assert (pargz);  assert (pargz_len);  assert (entry && *entry);  if (*pargz)    while ((before = argz_next (*pargz, *pargz_len, before)))      {	int cmp = strcmp (entry, before);	if (cmp < 0)  break;	if (cmp == 0) return 0;	/* No duplicates! */      }  return lt_argz_insert (pargz, pargz_len, before, entry);}static intlt_argz_insertdir (pargz, pargz_len, dirnam, dp)     char **pargz;     size_t *pargz_len;     const char *dirnam;     struct dirent *dp;{  char   *buf	    = NULL;  size_t buf_len    = 0;  char   *end	    = NULL;  size_t end_offset = 0;  size_t dir_len    = 0;  int    errors	    = 0;  assert (pargz);  assert (pargz_len);  assert (dp);  dir_len = LT_STRLEN (dirnam);  end     = dp->d_name + LT_D_NAMLEN(dp);  /* Ignore version numbers.  */  {    char *p;    for (p = end; p -1 > dp->d_name; --p)      if (strchr (".0123456789", p[-1]) == 0)	break;    if (*p == '.')      end = p;  }  /* Ignore filename extension.  */  {    char *p;    for (p = end -1; p > dp->d_name; --p)      if (*p == '.')	{	  end = p;	  break;	}  }  /* Prepend the directory name.  */  end_offset	= end - dp->d_name;  buf_len	= dir_len + 1+ end_offset;  buf		= LT_EMALLOC (char, 1+ buf_len);  if (!buf)    return ++errors;  assert (buf);  strcpy  (buf, dirnam);  strcat  (buf, "/");  strncat (buf, dp->d_name, end_offset);  buf[buf_len] = LT_EOS_CHAR;  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)    ++errors;  LT_DLFREE (buf);  return errors;}static intlist_files_by_dir (dirnam, pargz, pargz_len)     const char *dirnam;     char **pargz;     size_t *pargz_len;{  DIR	*dirp	  = NULL;  int    errors	  = 0;  assert (dirnam && *dirnam);  assert (pargz);  assert (pargz_len);  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');  dirp = opendir (dirnam);  if (dirp)    {      struct dirent *dp	= NULL;      while ((dp = readdir (dirp)))	if (dp->d_name[0] != '.')	  if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))	    {	      ++errors;	      break;	    }      closedir (dirp);    }  else    ++errors;  return errors;}/* If there are any files in DIRNAME, call the function passed in   DATA1 (with the name of each file and DATA2 as arguments).  */static intforeachfile_callback (dirname, data1, data2)     char *dirname;     lt_ptr data1;     lt_ptr data2;{  int (*func) LT_PARAMS((const char *filename, lt_ptr data))	= (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;  int	  is_done  = 0;  char   *argz     = NULL;  size_t  argz_len = 0;  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)    goto cleanup;  if (!argz)    goto cleanup;  {    char *filename = NULL;    while ((filename = argz_next (argz, argz_len, filename)))      if ((is_done = (*func) (filename, data2)))	break;  } cleanup:  LT_DLFREE (argz);  return is_done;}/* Call FUNC for each unique extensionless file in SEARCH_PATH, along   with DATA.  The filenames passed to FUNC would be suitable for   passing to lt_dlopenext.  The extensions are stripped so that   individual modules do not generate several entries (e.g. libfoo.la,   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,   then the same directories that lt_dlopen would search are examined.  */intlt_dlforeachfile (search_path, func, data)     const char *search_path;     int (*func) LT_PARAMS ((const char *filename, lt_ptr data));     lt_ptr data;{  int is_done = 0;  if (search_path)    {      /* If a specific path was passed, search only the directories	 listed in it.  */      is_done = foreach_dirinpath (search_path, 0,				   foreachfile_callback, func, data);    }  else    {      /* Otherwise search the default paths.  */      is_done = foreach_dirinpath (user_search_path, 0,				   foreachfile_callback, func, data);      if (!is_done)	{	  is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,				       foreachfile_callback, func, data);	}#ifdef LTDL_SHLIBPATH_VAR      if (!is_done)	{	  is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,				       foreachfile_callback, func, data);	}#endif#ifdef LTDL_SYSSEARCHPATH      if (!is_done)	{	  is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,				       foreachfile_callback, func, data);	}#endif    }  return is_done;}intlt_dlclose (handle)     lt_dlhandle handle;{  lt_dlhandle cur, last;  int errors = 0;  LT_DLMUTEX_LOCK ();  /* check whether the handle is valid */  last = cur = handles;  while (cur && handle != cur)    {      last = cur;      cur = cur->next;    }  if (!cur)    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));      ++errors;      goto done;    }  handle->info.ref_count--;  /* Note that even with resident modules, we must track the ref_count     correctly incase the user decides to reset the residency flag     later (even though the API makes no provision for that at the     moment).  */  if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))    {      lt_user_data data = handle->loader->dlloader_data;      if (handle != handles)	{	  last->next = handle->next;	}      else	{	  handles = handle->next;	}      errors += handle->loader->module_close (data, handle->module);      errors += unload_deplibs(handle);      /* It is up to the callers to free the data itself.  */      LT_DLFREE (handle->caller_data);      LT_DLFREE (handle->info.filename);      LT_DLFREE (handle->info.name);      LT_DLFREE (handle);      goto done;    }  if (LT_DLIS_RESIDENT (handle))    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));      ++errors;    } done:  LT_DLMUTEX_UNLOCK ();  return errors;}lt_ptrlt_dlsym (handle, symbol)     lt_dlhandle handle;     const char *symbol;{  size_t lensym;  char	lsym[LT_SYMBOL_LENGTH];  char	*sym;  lt_ptr address;  lt_user_data data;  if (!handle)    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));      return 0;    }  if (!symbol)    {      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));      return 0;    }  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)					+ LT_STRLEN (handle->info.name);  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)    {      sym = lsym;    }  else    {      sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);      if (!sym)	{	  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));	  return 0;	}    }  data = handle->loader->dlloader_data;  if (handle->info.name)    {      const char *saved_error;      LT_DLMUTEX_GETERROR (saved_error);      /* this is a libtool module */      if (handle->loader->sym_prefix)	{	  strcpy(sym, handle->loader->sym_prefix);	  strcat(sym, handle->info.name);	}      else	{	  strcpy(sym, handle->info.name);	}      strcat(sym, "_LTX_");      strcat(sym, symbol);      /* try "modulename_LTX_symbol" */      address = handle->loader->find_sym (data, handle->module, sym);      if (address)	{	  if (sym != lsym)	    {	      LT_DLFREE (sym);	    }	  return address;	}      LT_DLMUTEX_SETERROR (saved_error);    }  /* otherwise try "symbol" */  if (handle->loader->sym_prefix)    {      strcpy(sym, handle->loader->sym_prefix);      strcat(sym, symbol);    }  else    {      strcpy(sym, symbol);    }  address = handle->loader->find_sym (data, handle->module, sym);  if (sym != lsym)    {      LT_DLFREE (sym);    }  return address;}const char *lt_dlerror (){  const char *error;  LT_DLMUTEX_GETERROR (error);  LT_DLMUTEX_SETERROR (0);  return error ? error : LT_DLSTRERROR (UNKNOWN);}static intlt_dlpath_insertdir (ppath, before, dir)     char **ppath;     char *before;     const char *dir;{  int    errors		= 0;  char  *canonical	= NULL;  char  *argz		= NULL;  size_t argz_len	= 0;  assert (ppath);  assert (dir && *dir);  if (canonicalize_path (dir, &canonical) != 0)    {      ++errors;      goto cleanup;    }  assert (canonical && *canonical);  /* If *PPATH is empty, set it to DIR.  */  if (*ppath == NULL)    {      assert (!before);		/* BEFORE cannot be set without PPATH.  */      assert (dir);		/* Without DIR, don't call this function!  */      *ppath = lt_estrdup (dir);      if (*ppath == NULL)	++errors;      return errors;    }  assert (ppath && *ppath);  if (argzize_path (*ppath, &argz, &argz_len) != 0)    {      ++errors;      goto cleanup;    }  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works     if *PPATH is already canonicalized, and hence does not change length     with respect to ARGZ.  We canonicalize each entry as it is added to     the search path, and don't call this function with (uncanonicalized)     user paths, so this is a fair assumption.  */  if (before)    {      assert (*ppath <= before);      assert (before - *ppath <= strlen (*ppath));      before = before - *ppath + argz;    }  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)    {      ++errors;      goto cleanup;    }  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);  LT_DLMEM_REASSIGN (*ppath,  argz); cleanup:  LT_DLFREE (canonical);  LT_DLFREE (argz);  return errors;}