From bc51b928d6355590b7fb7e7553541193e1cf762a Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sun, 15 Aug 2004 08:14:33 +0000 Subject: [PATCH] Initial implementations of the ErrorCode and Path concepts for Linux. llvm-svn: 15763 --- llvm/lib/System/ErrorCode.cpp | 38 +++ llvm/lib/System/Path.cpp | 90 ++++++ llvm/lib/System/linux/ErrorCode.cpp | 57 ++++ llvm/lib/System/linux/LinuxCommon.h | 157 ++++++++++ llvm/lib/System/linux/Path.cpp | 450 ++++++++++++++++++++++++++++ 5 files changed, 792 insertions(+) create mode 100644 llvm/lib/System/ErrorCode.cpp create mode 100644 llvm/lib/System/Path.cpp create mode 100644 llvm/lib/System/linux/ErrorCode.cpp create mode 100644 llvm/lib/System/linux/LinuxCommon.h create mode 100644 llvm/lib/System/linux/Path.cpp diff --git a/llvm/lib/System/ErrorCode.cpp b/llvm/lib/System/ErrorCode.cpp new file mode 100644 index 000000000000..5f340cc7b5f2 --- /dev/null +++ b/llvm/lib/System/ErrorCode.cpp @@ -0,0 +1,38 @@ +//===- ErrorCode.cpp - Define the ErrorCode class ---------------*- C++ -*-===// +// +// Copyright (C) 2004 eXtensible Systems, Inc. All Rights Reserved. +// +// This program is open source software; you can redistribute it and/or modify +// it under the terms of the University of Illinois Open Source License. See +// LICENSE.TXT (distributed with this software) for details. +// +// This program 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. +// +//===----------------------------------------------------------------------===// +// +// This file defines the members of the llvm::sys::ErrorCode class. This class +// is used to hold operating system and other error codes in a platform +// agnostic manner. +// +//===----------------------------------------------------------------------===// +/// @file lib/System/ErrorCode.h +/// @author Reid Spencer (original author) +/// @version \verbatim $Id$ \endverbatim +/// @date 2004/08/14 +/// @since 1.4 +/// @brief Declares the llvm::sys::ErrorCode class. +//===----------------------------------------------------------------------===// + +#include "llvm/System/ErrorCode.h" + +namespace llvm { +namespace sys { + +} +} + +#include "linux/ErrorCode.cpp" + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/llvm/lib/System/Path.cpp b/llvm/lib/System/Path.cpp new file mode 100644 index 000000000000..a0c76dbd2062 --- /dev/null +++ b/llvm/lib/System/Path.cpp @@ -0,0 +1,90 @@ +//===- Path.cpp - Path Operating System Concept -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// Copyright (C) 2004 eXtensible Systems, Inc. All Rights Reserved. +// +// This program is open source software; you can redistribute it and/or modify +// it under the terms of the University of Illinois Open Source License. See +// LICENSE.TXT (distributed with this software) for details. +// +// This program 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. +// +//===----------------------------------------------------------------------===// +// +// This file implements the common Path concept for a variety of platforms. +// A path is simply the name of some file system storage place. Paths can be +// either directories or files. +// +//===----------------------------------------------------------------------===// +/// @file lib/System/Path.cpp +/// @author Reid Spencer (original author) +/// @version \verbatim $Id$ \endverbatim +/// @date 2004/08/14 +/// @since 1.4 +/// @brief Defines the llvm::sys::Path class. +//===----------------------------------------------------------------------===// + +#include "llvm/System/Path.h" + +namespace llvm { +namespace sys { + +ErrorCode +Path::append_directory( const std::string& dirname ) throw() { + this->append( dirname ); + make_directory(); + return NOT_AN_ERROR; +} + +ErrorCode +Path::append_file( const std::string& filename ) throw() { + this->append( filename ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::create( bool create_parents)throw() { + ErrorCode result ( NOT_AN_ERROR ); + if ( is_directory() ) { + if ( create_parents ) { + result = this->create_directories( ); + } else { + result = this->create_directory( ); + } + } else if ( is_file() ) { + if ( create_parents ) { + result = this->create_directories( ); + } + if ( result ) { + result = this->create_file( ); + } + } else { + result = ErrorCode(ERR_SYS_INVALID_ARG); + } + return result; +} + +ErrorCode +Path::remove() throw() { + ErrorCode result( NOT_AN_ERROR ); + if ( is_directory() ) { + if ( exists() ) + this->remove_directory( ); + } else if ( is_file() ) { + if ( exists() ) this->remove_file( ); + } else { + result = ErrorCode(ERR_SYS_INVALID_ARG); + } + return result; +} + +} +} + +// Include the platform specific portions of this class +#include "linux/Path.cpp" + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/llvm/lib/System/linux/ErrorCode.cpp b/llvm/lib/System/linux/ErrorCode.cpp new file mode 100644 index 000000000000..193964a939e8 --- /dev/null +++ b/llvm/lib/System/linux/ErrorCode.cpp @@ -0,0 +1,57 @@ +//===- ErrorCode.cpp - Define the ErrorCode class ---------------*- C++ -*-===// +// +// Copyright (C) 2004 eXtensible Systems, Inc. All Rights Reserved. +// +// This program is open source software; you can redistribute it and/or modify +// it under the terms of the University of Illinois Open Source License. See +// LICENSE.TXT (distributed with this software) for details. +// +// This program 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. +// +//===----------------------------------------------------------------------===// +// +// This file defines the linux specific members of the llvm::sys::ErrorCode +// class. +// +//===----------------------------------------------------------------------===// +/// @file lib/System/ErrorCode.h +/// @author Reid Spencer (original author) +/// @version \verbatim $Id$ \endverbatim +/// @date 2004/08/14 +/// @since 1.4 +/// @brief Declares the linux specific methods of llvm::sys::ErrorCode class. +//===----------------------------------------------------------------------===// + +namespace llvm { +namespace sys { + +std::string +ErrorCode::description() const throw() +{ + switch (domain()) { + case OSDomain: + char buffer[1024]; + if (0 != strerror_r(index(),buffer,1024) ) + return ""; + return buffer; + + case SystemDomain: + switch (index()) { + case ERR_SYS_INVALID_ARG: + return "Invalid argument to lib/System call"; + default: + return "Unknown lib/System Error"; + } + break; + + default: + return "Unknown Error"; + } +} + +} +} + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/llvm/lib/System/linux/LinuxCommon.h b/llvm/lib/System/linux/LinuxCommon.h new file mode 100644 index 000000000000..ac850aa9d404 --- /dev/null +++ b/llvm/lib/System/linux/LinuxCommon.h @@ -0,0 +1,157 @@ +//===- LinuxCommon.h - Common Declarations For Linux ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// Copyright (C) 2004 eXtensible Systems, Inc. All Rights Reserved. +// +// This program is open source software; you can redistribute it and/or modify +// it under the terms of the University of Illinois Open Source License. See +// LICENSE.TXT (distributed with this software) for details. +// +// This program 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. +// +//===----------------------------------------------------------------------===// +/// @file lib/System/linux/Common.h +/// @author Reid Spencer (original author) +/// @version \verbatim $Id$ \endverbatim +/// @date 2004/08/14 +/// @since 1.4 +/// @brief Provides common linux specific declarations and includes. +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include +#include + +#define FATAL(arg) \ + { llvm::sys::panic(LLVM_CONTEXT, arg); } + +#define RETURN_ERRNO \ + return ErrorCode(LLVM_ERROR_CODE(OSDomain,errno)) + +#define RETURN_OSERROR(code) \ + return ErrorCode(LLVM_ERROR_CODE(OSDomain,code)) + +#ifdef assert +#define ASSERT_ARG(expr) \ + if ( ! (expr) ) {\ + return ErrorCode(ERR_SYS_INVALID_ARG);\ + } +#else +#define ASSERT_ARG(expr) +#endif + +#define CHECK(var,call,args,msg) \ + { \ + if ( -1 == ( var = ::call args )) { \ + panic(LLVM_CONTEXT, msg); \ + } \ + } + +#define RETURN_ON_ERROR(call,args) \ + { \ + errno = 0; \ + if ( 0 > ( call args ) ) { \ + RETURN_ERRNO; \ + } \ + } + +#define RETURN_ON_ERRORCODE(call,args) \ + { \ + ErrorCode code = call args ; \ + if ( ! code ) \ + return code; \ + } + +#define PTHREAD_CALL( call, args, cleanup ) \ + { \ + int errcode = ::call args ; \ + if ( errcode != 0 ) { \ + cleanup ; \ + RETURN_ERRNO ; \ + } \ + } + +#define CLEANUP_CALL( call, args, cleanup ) \ + { \ + int result = call args ; \ + if ( result != 0 ) { \ + cleanup ; \ + RETURN_ERRNO ; \ + } \ + } + +// Define our realtime signals +#define SIG_LOOP_TERMINATE ( SIGRTMIN + 3 ) +#define SIG_USER_EVENT_1 ( SIGRTMIN + 4 ) +#define SIG_USER_EVENT_2 ( SIGRTMIN + 5 ) +#define SIG_USER_EVENT_3 ( SIGRTMIN + 6 ) +#define SIG_USER_EVENT_4 ( SIGRTMIN + 7 ) +#define SIG_USER_EVENT_5 ( SIGRTMIN + 8 ) +#define SIG_USER_EVENT_6 ( SIGRTMIN + 9 ) +#define SIG_USER_EVENT_7 ( SIGRTMIN + 10 ) +#define SIG_USER_EVENT_8 ( SIGRTMIN + 11 ) +#define SIG_AIO_1 ( SIGRTMIN + 12 ) +#define SIG_AIO_2 ( SIGRTMIN + 13 ) +#define SIG_AIO_3 ( SIGRTMIN + 14 ) +#define SIG_AIO_4 ( SIGRTMIN + 15 ) +#define SIG_AIO_5 ( SIGRTMIN + 16 ) +#define SIG_AIO_6 ( SIGRTMIN + 17 ) +#define SIG_AIO_7 ( SIGRTMIN + 18 ) +#define SIG_AIO_8 ( SIGRTMIN + 19 ) + +namespace llvm { +namespace sys { + +#if 0 +inline void +time_t2TimeValue( time_t t, TimeValue &tv ) +{ + TimeValue::Seconds_Type seconds = t; + seconds -= TimeValue::posix_zero_time.seconds(); + tv.set( seconds, 0 ); +} + +inline void +TimeValue2timespec( const TimeValue& tv, struct timespec & ts ) +{ + uint64_t seconds; + uint64_t nanos; + tv.timespec_time( seconds, nanos ); + ts.tv_sec = static_cast(seconds); + ts.tv_nsec = static_cast(nanos); +} + +inline void +timeval2TimeValue( struct timeval& tval, TimeValue& tv ) +{ + TimeValue::Seconds_Type seconds = tval.tv_sec; + seconds -= TimeValue::posix_zero_time.seconds(); + tv.set( seconds, tval.tv_usec * XPS_NANOSECONDS_PER_MICROSECOND ); +} + +extern pid_t pid_; ///< This processes' process identification number +extern int pagesize_; ///< The virtual memory page size of this machine +extern long arg_max_; ///< The maximum size in bytes of arguments to exec() +extern long child_max_; ///< The maximum processes per user. +extern long clk_tck_; ///< The number of clock ticks per second on this machine +extern long stream_max_; ///< The maximum number of streams that can be opened +extern long tzname_max_; ///< The maximum length of a timezone name +extern long file_max_; ///< The maximum number of files that can be opened +extern long line_max_; ///< The maximum length of an I/O line +extern long job_control_; ///< Non-zero if POSIX job control enabled +extern long saved_ids_; ///< ? +extern long phys_pages_; ///< Total number of physical pages +extern long avphys_pages_; ///< Average number of free physical pages + +#endif + +} +} +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab diff --git a/llvm/lib/System/linux/Path.cpp b/llvm/lib/System/linux/Path.cpp new file mode 100644 index 000000000000..a0eed86fe20f --- /dev/null +++ b/llvm/lib/System/linux/Path.cpp @@ -0,0 +1,450 @@ +//===- Path.cpp - Path Operating System Concept -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// Copyright (C) 2004 eXtensible Systems, Inc. All Rights Reserved. +// +// This program is open source software; you can redistribute it and/or modify +// it under the terms of the University of Illinois Open Source License. See +// LICENSE.TXT (distributed with this software) for details. +// +// This program 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. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +/// @file lib/System/linux/Path.cpp +/// @author Reid Spencer (original author) +/// @version \verbatim $Id$ \endverbatim +/// @date 2003/04/17 +/// @since 1.4 +/// @brief Implements the linux specific portion of class llvm::sys::Path +//////////////////////////////////////////////////////////////////////////////// + +#include "LinuxCommon.h" +#include +#include + +namespace llvm { +namespace sys { + +Path::Path(ConstructSpecial which) throw() { + switch (which) { + case CONSTRUCT_TEMP_FILE: + this->make_temp_file(); + break; + case CONSTRUCT_TEMP_DIR: + this->make_temp_directory(); + break; + } +} + +bool +Path::is_file() const throw() { + if ( !empty() && ((*this)[length()-1] != '/' )) + return true; + return false; +} + +bool +Path::is_directory() const throw() { + if ((!empty()) && ((*this)[length()-1] == '/' )) + return true; + return false; +} + +ErrorCode +Path::make_directory() throw() { + char end[2]; + end[0] = '/'; + end[1] = 0; + if ( empty() ) + this->assign( end ); + else if ( (*this)[length()-1] != '/' ) + this->append( end ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::make_temp_directory() throw() { + char temp_name[64]; + ::strcpy(temp_name,"/tmp/llvm_XXXXXX"); + char* res = ::mkdtemp(temp_name); + if ( res == 0 ) + RETURN_ERRNO; + *this = temp_name; + make_directory(); + return NOT_AN_ERROR; +} + +ErrorCode +Path::make_file() throw() { + if ( (*this)[length()-1] == '/' ) + this->erase( this->length()-1, 1 ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::make_temp_file() throw() { + char temp_name[64]; + ::strcpy(temp_name,"/tmp/llvm_XXXXXX"); + int fd = ::mkstemp(temp_name); + if ( fd == -1 ) + RETURN_ERRNO; + ::close(fd); + *this = temp_name; + return NOT_AN_ERROR; +} + +ErrorCode +Path::exists() throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + RETURN_ON_ERROR( access,( pathname, F_OK | R_OK ) ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::create_directory() throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + RETURN_ON_ERROR( mkdir, ( pathname, S_IRWXU | S_IRWXG ) ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::create_directories() throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + char * next = index(pathname,'/'); + if ( pathname[0] == '/' ) + next = index(&pathname[1],'/'); + while ( next != 0 ) + { + *next = 0; + if ( 0 != access( pathname, F_OK | R_OK ) ) + RETURN_ON_ERROR( mkdir, (pathname, S_IRWXU | S_IRWXG ) ); + char* save = next; + next = index(pathname,'/'); + *save = '/'; + } + return NOT_AN_ERROR; +} + +ErrorCode +Path::remove_directory( ) throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + RETURN_ON_ERROR( rmdir, (pathname) ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::create_file( ) throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + RETURN_ON_ERROR( creat, ( pathname, S_IRUSR | S_IWUSR ) ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::remove_file( ) throw() { + char pathname[MAXPATHLEN]; + this->fill(pathname,MAXPATHLEN); + int lastchar = this->length() - 1 ; + if (pathname[lastchar] == '/') + pathname[lastchar] = 0; + RETURN_ON_ERROR( unlink, (pathname) ); + return NOT_AN_ERROR; +} + +ErrorCode +Path::find_lib( const char * file ) throw() +{ + ASSERT_ARG( file != 0 ); + +#if 0 + ACE_TCHAR tempcopy[MAXPATHLEN + 1]; + ACE_TCHAR searchpathname[MAXPATHLEN + 1]; + ACE_TCHAR searchfilename[MAXPATHLEN + 1]; + + // Create a copy of filename to work with. + if (ACE_OS::strlen (filename) + 1 + > (sizeof tempcopy / sizeof (ACE_TCHAR))) + { + errno = ENOMEM; + return -1; + } + else + ACE_OS::strcpy (tempcopy, filename); + + // Insert canonical directory separators. + ACE_TCHAR *separator_ptr; + +#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/') + // Make all the directory separators "canonical" to simplify + // subsequent code. + ACE_Lib_Find::strrepl (tempcopy, ACE_DIRECTORY_SEPARATOR_CHAR, '/'); +#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */ + + // Separate filename from pathname. + separator_ptr = ACE_OS::strrchr (tempcopy, '/'); + + // This is a relative path. + if (separator_ptr == 0) + { + searchpathname[0] = '\0'; + ACE_OS::strcpy (searchfilename, tempcopy); + } + else // This is an absolute path. + { + ACE_OS::strcpy (searchfilename, separator_ptr + 1); + separator_ptr[1] = '\0'; + ACE_OS::strcpy (searchpathname, tempcopy); + } + + int got_suffix = 0; + + // Check to see if this has an appropriate DLL suffix for the OS + // platform. + ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.'); + + const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX; + + if (s != 0) + { + // If we have a dot, we have a suffix + got_suffix = 1; + + // Check whether this matches the appropriate platform-specific + // suffix. + if (ACE_OS::strcmp (s, dll_suffix) != 0) + { + ACE_ERROR ((LM_WARNING, + ACE_LIB_TEXT ("Warning: improper suffix for a ") + ACE_LIB_TEXT ("shared library on this platform: %s\n"), + s)); + } + } + + // Make sure we've got enough space in searchfilename. + if (ACE_OS::strlen (searchfilename) + + ACE_OS::strlen (ACE_DLL_PREFIX) + + got_suffix ? 0 : ACE_OS::strlen (dll_suffix) >= (sizeof searchfilename / + sizeof (ACE_TCHAR))) + { + errno = ENOMEM; + return -1; + } + + // Use absolute pathname if there is one. + if (ACE_OS::strlen (searchpathname) > 0) + { + if (ACE_OS::strlen (searchfilename) + + ACE_OS::strlen (searchpathname) >= maxpathnamelen) + { + errno = ENOMEM; + return -1; + } + else + { +#if (ACE_DIRECTORY_SEPARATOR_CHAR != '/') + // Revert to native path name separators. + ACE_Lib_Find::strrepl (searchpathname, + '/', + ACE_DIRECTORY_SEPARATOR_CHAR); +#endif /* ACE_DIRECTORY_SEPARATOR_CHAR */ + // First, try matching the filename *without* adding a + // prefix. +#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%s%s"), + searchpathname, + searchfilename, + got_suffix ? ACE_static_cast (ACE_TCHAR *, + ACE_LIB_TEXT ("")) + : ACE_static_cast (ACE_TCHAR *, + dll_suffix)); +#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%s%s"), + searchpathname, + searchfilename, + got_suffix ? ACE_LIB_TEXT ("") : dll_suffix); +#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + if (ACE_OS::access (pathname, F_OK) == 0) + return 0; + + // Second, try matching the filename *with* adding a prefix. +#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%s%s%s"), + searchpathname, + ACE_DLL_PREFIX, + searchfilename, + got_suffix ? ACE_static_cast (ACE_TCHAR *, + ACE_LIB_TEXT ("")) + : ACE_static_cast (ACE_TCHAR *, + dll_suffix)); +#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%s%s%s"), + searchpathname, + ACE_DLL_PREFIX, + searchfilename, + got_suffix ? ACE_LIB_TEXT ("") : dll_suffix); +#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + if (ACE_OS::access (pathname, F_OK) == 0) + return 0; + } + } + + // Use relative filenames via LD_LIBRARY_PATH or PATH (depending on + // OS platform). + else + { + ACE_TCHAR *ld_path = +#if defined ACE_DEFAULT_LD_SEARCH_PATH + ACE_DEFAULT_LD_SEARCH_PATH; +#else + ACE_OS::getenv (ACE_LD_SEARCH_PATH); +#endif /* ACE_DEFAULT_LD_SEARCH_PATH */ + + if (ld_path != 0 + && (ld_path = ACE_OS::strdup (ld_path)) != 0) + { + // strtok has the strange behavior of not separating the + // string ":/foo:/bar" into THREE tokens. One would expect + // that the first iteration the token would be an empty + // string, the second iteration would be "/foo", and the + // third iteration would be "/bar". However, this is not + // the case; one only gets two iterations: "/foo" followed + // by "/bar". + + // This is especially a problem in parsing Unix paths + // because it is permissible to specify 'the current + // directory' as an empty entry. So, we introduce the + // following special code to cope with this: + + // Look at each dynamic lib directory in the search path. + + ACE_TCHAR *nextholder = 0; + const ACE_TCHAR *path_entry = + ACE_Lib_Find::strsplit_r (ld_path, + ACE_LD_SEARCH_PATH_SEPARATOR_STR, + nextholder); + int result = 0; + + for (;;) + { + // Check if at end of search path. + if (path_entry == 0) + { + errno = ENOENT; + result = -1; + break; + } + else if (ACE_OS::strlen (path_entry) + + 1 + + ACE_OS::strlen (searchfilename) + >= maxpathnamelen) + { + errno = ENOMEM; + result = -1; + break; + } + // This works around the issue where a path might have + // an empty component indicating 'current directory'. + // We need to do it here rather than anywhere else so + // that the loop condition will still work. + else if (path_entry[0] == '\0') + path_entry = ACE_LIB_TEXT ("."); + + // First, try matching the filename *without* adding a + // prefix. +#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%c%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + searchfilename, + got_suffix ? ACE_static_cast (ACE_TCHAR *, + ACE_LIB_TEXT ("")) + : ACE_static_cast (ACE_TCHAR *, + dll_suffix)); +#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%c%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + searchfilename, + got_suffix ? ACE_LIB_TEXT ("") : dll_suffix); +#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + if (ACE_OS::access (pathname, F_OK) == 0) + break; + + // Second, try matching the filename *with* adding a + // prefix. +#if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%c%s%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + ACE_DLL_PREFIX, + searchfilename, + got_suffix ? ACE_static_cast (ACE_TCHAR *, + ACE_LIB_TEXT ("")) + : ACE_static_cast (ACE_TCHAR *, + dll_suffix)); +#else /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + ACE_OS::sprintf (pathname, + ACE_LIB_TEXT ("%s%c%s%s%s"), + path_entry, + ACE_DIRECTORY_SEPARATOR_CHAR, + ACE_DLL_PREFIX, + searchfilename, + got_suffix ? ACE_LIB_TEXT ("") : dll_suffix); +#endif /* ! defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) */ + if (ACE_OS::access (pathname, F_OK) == 0) + break; + + // Fetch the next item in the path + path_entry = ACE_Lib_Find::strsplit_r (0, + ACE_LD_SEARCH_PATH_SEPARATOR_STR, + nextholder); + } + + ACE_OS::free ((void *) ld_path); + return result; + } + } + errno = ENOENT; + return -1; +#endif + + /// @todo FIXME: Convert ACE code + *this = Path( file ); + + return NOT_AN_ERROR; +} + +} +} + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab