Initial implementations of the ErrorCode and Path concepts for Linux.
authorReid Spencer <rspencer@reidspencer.com>
Sun, 15 Aug 2004 08:14:33 +0000 (08:14 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Sun, 15 Aug 2004 08:14:33 +0000 (08:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15763 91177308-0d34-0410-b5e6-96231b3b80d8

lib/System/ErrorCode.cpp [new file with mode: 0644]
lib/System/Path.cpp [new file with mode: 0644]
lib/System/linux/ErrorCode.cpp [new file with mode: 0644]
lib/System/linux/LinuxCommon.h [new file with mode: 0644]
lib/System/linux/Path.cpp [new file with mode: 0644]

diff --git a/lib/System/ErrorCode.cpp b/lib/System/ErrorCode.cpp
new file mode 100644 (file)
index 0000000..5f340cc
--- /dev/null
@@ -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 <raspencer@x10sys.com> (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/lib/System/Path.cpp b/lib/System/Path.cpp
new file mode 100644 (file)
index 0000000..a0c76db
--- /dev/null
@@ -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 <raspencer@x10sys.com> (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/lib/System/linux/ErrorCode.cpp b/lib/System/linux/ErrorCode.cpp
new file mode 100644 (file)
index 0000000..193964a
--- /dev/null
@@ -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 <raspencer@x10sys.com> (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 "<Error Message Unavalabile>";
+      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/lib/System/linux/LinuxCommon.h b/lib/System/linux/LinuxCommon.h
new file mode 100644 (file)
index 0000000..ac850aa
--- /dev/null
@@ -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 <rspencer@x10sys.com> (original author)
+/// @version \verbatim $Id$ \endverbatim
+/// @date 2004/08/14
+/// @since 1.4
+/// @brief Provides common linux specific declarations and includes.
+//===----------------------------------------------------------------------===//
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <pthread.h>
+
+#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<time_t>(seconds);
+  ts.tv_nsec = static_cast<long int>(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/lib/System/linux/Path.cpp b/lib/System/linux/Path.cpp
new file mode 100644 (file)
index 0000000..a0eed86
--- /dev/null
@@ -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 <raspencer@users.sourceforge.net> (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 <sys/stat.h>
+#include <fcntl.h>
+
+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