FileSpec.cpp revision 0c2921f5b9dab2ca1832bb746ab3aa3f66fdd0b5
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton#include <dirent.h>
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <fcntl.h>
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <libgen.h>
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/stat.h>
1590df56354288b44e5b6c2844c52f1e0eefd5509bGreg Clayton#include <string.h>
16a39fa4b8c67886e0d7df0752fe176ad7723e305fJim Ingham#include <fstream>
178da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton
18a39fa4b8c67886e0d7df0752fe176ad7723e305fJim Ingham#include "lldb/Host/Config.h" // Have to include this before we test the define...
1914ef59fe5728d862c040cf5a6b99c384229a34eeGreg Clayton#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
20a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham#include <pwd.h>
218da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton#endif
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice#include "llvm/ADT/StringRef.h"
2422defe8b06df5b1f09b53bda255ef07513abc04cGreg Clayton#include "llvm/Support/Path.h"
2522defe8b06df5b1f09b53bda255ef07513abc04cGreg Clayton#include "llvm/Support/Program.h"
26e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
272f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton#include "lldb/Host/File.h"
285f54ac373b119a4c6693e4875c48aa761fba0c86Greg Clayton#include "lldb/Host/FileSpec.h"
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBufferHeap.h"
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBufferMemoryMap.h"
3149ce8969d3154e1560106cfe530444c09410f217Greg Clayton#include "lldb/Core/RegularExpression.h"
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Stream.h"
33eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice#include "lldb/Host/Host.h"
3452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton#include "lldb/Utility/CleanUp.h"
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerGetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
43ff44ab42e9f5d8e4d550e11d1b69413e0bc75b71Greg Clayton    if (file_spec->GetPath (resolved_path, sizeof(resolved_path)))
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::stat (resolved_path, stats_ptr) == 0;
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4814ef59fe5728d862c040cf5a6b99c384229a34eeGreg Clayton#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
498da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic const char*
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerGetCachedGlobTildeSlash()
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    static std::string g_tilde;
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (g_tilde.empty())
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
56a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        struct passwd *user_entry;
57a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_entry = getpwuid(geteuid());
58a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (user_entry != NULL)
59a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            g_tilde = user_entry->pw_dir;
60a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (g_tilde.empty())
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return NULL;
6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return g_tilde.c_str();
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6782cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
6882cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton
69a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Resolves the username part of a path of the form ~user/other/directories, and
70a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// writes the result into dst_path.
71a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Returns 0 if there WAS a ~ in the path but the username couldn't be resolved.
72a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// Otherwise returns the number of characters copied into dst_path.  If the return
73a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham// is >= dst_len, then the resolved path is too long...
7454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Claytonsize_t
75a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim InghamFileSpec::ResolveUsername (const char *src_path, char *dst_path, size_t dst_len)
76a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham{
7782cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton    if (src_path == NULL || src_path[0] == '\0')
7882cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton        return 0;
7982cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton
8082cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
8182cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton
82a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    char user_home[PATH_MAX];
83a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    const char *user_name;
84a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
85b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
86a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    // If there's no ~, then just copy src_path straight to dst_path (they may be the same string...)
87a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (src_path[0] != '~')
88a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
8954e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton        size_t len = strlen (src_path);
90a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (len >= dst_len)
91a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        {
92b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            ::bcopy (src_path, dst_path, dst_len - 1);
93b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            dst_path[dst_len] = '\0';
94a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        }
95a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        else
96b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton            ::bcopy (src_path, dst_path, len + 1);
97b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
98a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return len;
99a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
100a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
1019c3cfe397d6040a46677e201c2682cc2a5163fe9Eli Friedman    const char *first_slash = ::strchr (src_path, '/');
102a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    char remainder[PATH_MAX];
103a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
104a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (first_slash == NULL)
105a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
106a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // The whole name is the username (minus the ~):
107a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_name = src_path + 1;
108a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        remainder[0] = '\0';
109a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
110a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
111a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
11236da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        size_t user_name_len = first_slash - src_path - 1;
113b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        ::memcpy (user_home, src_path + 1, user_name_len);
114a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_home[user_name_len] = '\0';
115a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        user_name = user_home;
116a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
117b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        ::strcpy (remainder, first_slash);
118a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
119b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton
120a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (user_name == NULL)
121a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return 0;
122a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    // User name of "" means the current user...
123a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
124a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    struct passwd *user_entry;
12554e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton    const char *home_dir = NULL;
126a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
127a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (user_name[0] == '\0')
128a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
129a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        home_dir = GetCachedGlobTildeSlash();
130a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
131a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
132a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
133b1a9862ba1ceb219b6042ff3f8c6ff591867ae26Greg Clayton        user_entry = ::getpwnam (user_name);
134a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (user_entry != NULL)
135a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            home_dir = user_entry->pw_dir;
136a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
137a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
138a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (home_dir == NULL)
139a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return 0;
140a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    else
141a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        return ::snprintf (dst_path, dst_len, "%s%s", home_dir, remainder);
14282cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton#else
14382cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton    // Resolving home directories is not supported, just copy the path...
14482cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton    return ::snprintf (dst_path, dst_len, "%s", src_path);
14582cfaed47126a17b4fa21e42e05546e7a041b9e3Greg Clayton#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
146a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham}
147a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
14854e7afa84d945f9137f9372ecde432f9e1a702fcGreg Claytonsize_t
149158842ca982c53aca6c5ad7345d7b261e309292dJim InghamFileSpec::ResolvePartialUsername (const char *partial_name, StringList &matches)
150158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham{
151158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
152158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    size_t extant_entries = matches.GetSize();
153158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham
154158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    setpwent();
155158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    struct passwd *user_entry;
156158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    const char *name_start = partial_name + 1;
157158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    std::set<std::string> name_list;
158158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham
159158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    while ((user_entry = getpwent()) != NULL)
160158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    {
161158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham        if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name)
162158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham        {
163158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham            std::string tmp_buf("~");
164158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham            tmp_buf.append(user_entry->pw_name);
165158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham            tmp_buf.push_back('/');
166158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham            name_list.insert(tmp_buf);
167158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham        }
168158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    }
169158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    std::set<std::string>::iterator pos, end = name_list.end();
170158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    for (pos = name_list.begin(); pos != end; pos++)
171158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    {
172158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham        matches.AppendString((*pos).c_str());
173158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    }
174158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    return matches.GetSize() - extant_entries;
175158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham#else
176158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    // Resolving home directories is not supported, just copy the path...
177158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham    return 0;
178158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
179158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham}
180158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham
181158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham
182158842ca982c53aca6c5ad7345d7b261e309292dJim Ingham
183158842ca982c53aca6c5ad7345d7b261e309292dJim Inghamsize_t
18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Resolve (const char *src_path, char *dst_path, size_t dst_len)
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (src_path == NULL || src_path[0] == '\0')
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return 0;
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Glob if needed for ~/, otherwise copy in case src_path is same as dst_path...
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char unglobbed_path[PATH_MAX];
19114ef59fe5728d862c040cf5a6b99c384229a34eeGreg Clayton#ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
192a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    if (src_path[0] == '~')
193a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    {
19454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton        size_t return_count = ResolveUsername(src_path, unglobbed_path, sizeof(unglobbed_path));
195a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham
196a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // If we couldn't find the user referred to, or the resultant path was too long,
197a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        // then just copy over the src_path.
198a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham        if (return_count == 0 || return_count >= sizeof(unglobbed_path))
199a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham            ::snprintf (unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
200a30baf5b257c7a62c5888679e7c1ac8eb47ca6d7Jim Ingham    }
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
20214ef59fe5728d862c040cf5a6b99c384229a34eeGreg Clayton#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
2038da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton    {
2048da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton    	::snprintf(unglobbed_path, sizeof(unglobbed_path), "%s", src_path);
2058da92a74478ff2465e092aea92ce29ad7ad6ddddGreg Clayton    }
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Now resolve the path if needed
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (::realpath (unglobbed_path, resolved_path))
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Success, copy the resolved path
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::snprintf(dst_path, dst_len, "%s", resolved_path);
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Failed, just copy the unglobbed path
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return ::snprintf(dst_path, dst_len, "%s", unglobbed_path);
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec() :
22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory(),
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename()
22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Default constructor that can take an optional full path to a
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file on disk.
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
231c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::FileSpec(const char *pathname, bool resolve_path) :
232c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    m_directory(),
233d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_filename(),
234d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved(false)
235c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
236c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (pathname && pathname[0])
237c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        SetFile(pathname, resolve_path);
238c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
239c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
240c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham//------------------------------------------------------------------
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec& rhs) :
24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory (rhs.m_directory),
245d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_filename (rhs.m_filename),
246d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved (rhs.m_is_resolved)
24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copy constructor
25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileSpec(const FileSpec* rhs) :
25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory(),
25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename()
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (rhs)
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        *this = *rhs;
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Virtual destrcuctor in case anyone inherits from this class.
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::~FileSpec()
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Assignment operator.
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst FileSpec&
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator= (const FileSpec& rhs)
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (this != &rhs)
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_directory = rhs.m_directory;
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_filename = rhs.m_filename;
278d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        m_is_resolved = rhs.m_is_resolved;
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return *this;
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Update the contents of this object with a new path. The path will
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// be split up into a directory and filename and stored as uniqued
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values for quick comparison and efficient memory usage.
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
289d6d806ceff943ca26c008f704013f18920685cfdGreg ClaytonFileSpec::SetFile (const char *pathname, bool resolve)
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
293d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    m_is_resolved = false;
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pathname == NULL || pathname[0] == '\0')
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
298c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    bool path_fit = true;
299c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
300c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (resolve)
301c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
302c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1);
303d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        m_is_resolved = path_fit;
304c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
305c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    else
306c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    {
307d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // Copy the path because "basename" and "dirname" want to muck with the
308d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // path buffer
309d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (::strlen (pathname) > sizeof(resolved_path) - 1)
310c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham            path_fit = false;
311c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        else
312d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            ::strcpy (resolved_path, pathname);
313c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    }
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
315c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
316c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (path_fit)
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char *filename = ::basename (resolved_path);
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (filename)
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_filename.SetCString (filename);
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Truncate the basename off the end of the resolved path
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Only attempt to get the dirname if it looks like we have a path
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strchr(resolved_path, '/'))
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char *directory = ::dirname (resolved_path);
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Make sure we didn't get our directory resolved to "." without having
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // specified
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (directory)
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_directory.SetCString(directory);
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_resolved_path_slash = strrchr(resolved_path, '/');
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (last_resolved_path_slash)
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        *last_resolved_path_slash = '\0';
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        m_directory.SetCString(resolved_path);
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_directory.SetCString(resolved_path);
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Convert to pointer operator. This allows code to check any FileSpec
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they contain anything valid using code such as:
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (file_spec)
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
35631cf0e7c5ff8233eccef28ca22d025d7b490cb7aGreg ClaytonFileSpec::operator bool() const
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
35831cf0e7c5ff8233eccef28ca22d025d7b490cb7aGreg Clayton    return m_filename || m_directory;
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Logical NOT operator. This allows code to check any FileSpec
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// objects to see if they are invalid using code such as:
36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  if (!file_spec)
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  {}
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!() const
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return !m_directory && !m_filename;
37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Equal to operator
37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
37724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator== (const FileSpec& rhs) const
37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
380d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    if (m_filename == rhs.m_filename)
381d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    {
382d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (m_directory == rhs.m_directory)
383d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            return true;
384d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
385d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // TODO: determine if we want to keep this code in here.
386d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // The code below was added to handle a case where we were
387d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // trying to set a file and line breakpoint and one path
388d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // was resolved, and the other not and the directory was
389d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // in a mount point that resolved to a more complete path:
390d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling
391d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // this out...
392d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (IsResolved() && rhs.IsResolved())
393d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
394d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            // Both paths are resolved, no need to look further...
395d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            return false;
396d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
397d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
398d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        FileSpec resolved_lhs(*this);
399d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
400d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // If "this" isn't resolved, resolve it
401d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (!IsResolved())
402d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
403d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            if (resolved_lhs.ResolvePath())
404d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            {
405d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // This path wasn't resolved but now it is. Check if the resolved
406d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // directory is the same as our unresolved directory, and if so,
407d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // we can mark this object as resolved to avoid more future resolves
408d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                m_is_resolved = (m_directory == resolved_lhs.m_directory);
409d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            }
410d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            else
411d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                return false;
412d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
413d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
414d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        FileSpec resolved_rhs(rhs);
415d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        if (!rhs.IsResolved())
416d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        {
417d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            if (resolved_rhs.ResolvePath())
418d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            {
419d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // rhs's path wasn't resolved but now it is. Check if the resolved
420d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // directory is the same as rhs's unresolved directory, and if so,
421d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                // we can mark this object as resolved to avoid more future resolves
4229b8550ee5ca4bb85b67352e1c63a1abf7f4a3809Jim Ingham                rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory);
423d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            }
424d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton            else
425d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton                return false;
426d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        }
427d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
428d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // If we reach this point in the code we were able to resolve both paths
429d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // and since we only resolve the paths if the basenames are equal, then
430d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        // we can just check if both directories are equal...
431d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        return resolved_lhs.GetDirectory() == resolved_rhs.GetDirectory();
432d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    }
433d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return false;
43424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
43524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
43624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
43724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Not equal to operator
43824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
43924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
44024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator!= (const FileSpec& rhs) const
44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
442d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return !(*this == rhs);
44324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Less than operator
44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::operator< (const FileSpec& rhs) const
45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return FileSpec::Compare(*this, rhs, true) < 0;
45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
45324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump a FileSpec object to a stream
45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerStream&
45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerlldb_private::operator << (Stream &s, const FileSpec& f)
45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    f.Dump(&s);
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return s;
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Clear this object by releasing both the directory and filename
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// string values and making them both the empty string.
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Clear()
47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_directory.Clear();
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_filename.Clear();
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Compare two FileSpec objects. If "full" is true, then both
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// the directory and the filename must match. If "full" is false,
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// then the directory names for "a" and "b" are only compared if
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// they are both non-empty. This allows a FileSpec object to only
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// contain a filename and it can match FileSpec objects that have
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// matching filenames with different paths.
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// and "1" if "a" is greater than "b".
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full)
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int result = 0;
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is true, then we must compare both the directory and filename.
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If full is false, then if either directory is empty, then we match on
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // the basename only, and if both directories have valid values, we still
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // do a full compare. This allows for matching when we just have a filename
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // in one of the FileSpec objects.
49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (full || (a.m_directory && b.m_directory))
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        result = ConstString::Compare(a.m_directory, b.m_directory);
50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (result)
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return result;
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return ConstString::Compare (a.m_filename, b.m_filename);
50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
510d6d47976b71187907c1cdeea86fabf7d5534314fJim Ingham    if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return a.m_filename == b.m_filename;
512d6d47976b71187907c1cdeea86fabf7d5534314fJim Ingham    else
513d6d47976b71187907c1cdeea86fabf7d5534314fJim Ingham        return a == b;
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dump the object to the supplied stream. If the object contains
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// a valid directory name, it will be displayed followed by a
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// directory delimiter, and the filename.
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Dump(Stream *s) const
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5265581a7e69714aa6c08833e060de85237ec2a690aJason Molenda    static ConstString g_slash_only ("/");
527fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata    if (s)
528fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata    {
529fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata        m_directory.Dump(s);
5305581a7e69714aa6c08833e060de85237ec2a690aJason Molenda        if (m_directory && m_directory != g_slash_only)
531fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata            s->PutChar('/');
532fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata        m_filename.Dump(s);
533fb2d05b85d8185f06d97d2c5444652fa74c246c3Enrico Granata    }
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns true if the file exists.
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::Exists () const
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return GetFileStats (this, &file_stats);
544eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice}
545eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice
546eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Ticebool
547eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline TiceFileSpec::ResolveExecutableLocation ()
548eddffe93d2c9ebb575e7b03fe1c5e71f9ecaf9f1Caroline Tice{
549537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton    if (!m_directory)
550e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    {
55127345db7bc4167078014798032137b0452f4cab9Greg Clayton        const char *file_cstr = m_filename.GetCString();
55227345db7bc4167078014798032137b0452f4cab9Greg Clayton        if (file_cstr)
553e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        {
55427345db7bc4167078014798032137b0452f4cab9Greg Clayton            const std::string file_str (file_cstr);
55527345db7bc4167078014798032137b0452f4cab9Greg Clayton            llvm::sys::Path path = llvm::sys::Program::FindProgramByName (file_str);
55627345db7bc4167078014798032137b0452f4cab9Greg Clayton            const std::string &path_str = path.str();
55727345db7bc4167078014798032137b0452f4cab9Greg Clayton            llvm::StringRef dir_ref = llvm::sys::path::parent_path(path_str);
55827345db7bc4167078014798032137b0452f4cab9Greg Clayton            //llvm::StringRef dir_ref = path.getDirname();
55927345db7bc4167078014798032137b0452f4cab9Greg Clayton            if (! dir_ref.empty())
560e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            {
56127345db7bc4167078014798032137b0452f4cab9Greg Clayton                // FindProgramByName returns "." if it can't find the file.
56227345db7bc4167078014798032137b0452f4cab9Greg Clayton                if (strcmp (".", dir_ref.data()) == 0)
56327345db7bc4167078014798032137b0452f4cab9Greg Clayton                    return false;
56427345db7bc4167078014798032137b0452f4cab9Greg Clayton
56527345db7bc4167078014798032137b0452f4cab9Greg Clayton                m_directory.SetCString (dir_ref.data());
56627345db7bc4167078014798032137b0452f4cab9Greg Clayton                if (Exists())
567e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                    return true;
56827345db7bc4167078014798032137b0452f4cab9Greg Clayton                else
56927345db7bc4167078014798032137b0452f4cab9Greg Clayton                {
57027345db7bc4167078014798032137b0452f4cab9Greg Clayton                    // If FindProgramByName found the file, it returns the directory + filename in its return results.
57127345db7bc4167078014798032137b0452f4cab9Greg Clayton                    // We need to separate them.
57227345db7bc4167078014798032137b0452f4cab9Greg Clayton                    FileSpec tmp_file (dir_ref.data(), false);
57327345db7bc4167078014798032137b0452f4cab9Greg Clayton                    if (tmp_file.Exists())
57427345db7bc4167078014798032137b0452f4cab9Greg Clayton                    {
57527345db7bc4167078014798032137b0452f4cab9Greg Clayton                        m_directory = tmp_file.m_directory;
57627345db7bc4167078014798032137b0452f4cab9Greg Clayton                        return true;
57727345db7bc4167078014798032137b0452f4cab9Greg Clayton                    }
578e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice                }
579e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice            }
580e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice        }
581e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    }
582e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice
583e9ca3a4130bfb76765256549e01c759da8ec2f1dCaroline Tice    return false;
584c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham}
585c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham
586c4547c59f2e8390bdbf92484c851be06395b8e77Jim Inghambool
587c4547c59f2e8390bdbf92484c851be06395b8e77Jim InghamFileSpec::ResolvePath ()
588c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham{
589d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    if (m_is_resolved)
590d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton        return true;    // We have already resolved this path
591d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton
592d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    char path_buf[PATH_MAX];
593c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    if (!GetPath (path_buf, PATH_MAX))
594c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham        return false;
595d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    // SetFile(...) will set m_is_resolved correctly if it can resolve the path
596c4547c59f2e8390bdbf92484c851be06395b8e77Jim Ingham    SetFile (path_buf, true);
597d6d806ceff943ca26c008f704013f18920685cfdGreg Clayton    return m_is_resolved;
59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattneruint64_t
60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetByteSize() const
60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return file_stats.st_size;
60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return 0;
60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::FileType
61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFileType () const
61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        mode_t file_type = file_stats.st_mode & S_IFMT;
61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (file_type)
61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFDIR:   return eFileTypeDirectory;
61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFIFO:   return eFileTypePipe;
62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFREG:   return eFileTypeRegular;
62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFSOCK:  return eFileTypeSocket;
62224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case S_IFLNK:   return eFileTypeSymbolicLink;
62324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
62424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
62524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
62652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        return eFileTypeUnknown;
62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eFileTypeInvalid;
62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerTimeValue
63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetModificationTime () const
63324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
63424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    TimeValue mod_time;
63524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    struct stat file_stats;
63624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetFileStats (this, &file_stats))
637b586901fb633b898e19bdfc8d605b4e89a3ab5b8Eli Friedman        mod_time.OffsetWithSeconds(file_stats.st_mtime);
63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return mod_time;
63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
64224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string get accessor.
64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
64424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
64524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory()
64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
65024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
65124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Directory string const get accessor.
65224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
65324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
65424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetDirectory() const
65524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
65624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_directory;
65724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
65824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
65924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
66024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string get accessor.
66124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
66224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerConstString &
66324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename()
66424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
66524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
66624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
66724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
66824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
66924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Filename string const get accessor.
67024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ConstString &
67224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::GetFilename() const
67324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
67424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename;
67524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
67624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
67724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
67824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Extract the directory and path into a fixed buffer. This is
67924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// needed as the directory and path are stored in separate string
68024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values.
68124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
68249ce682dfa7993d31206cea19ce7006cd3f3077eGreg Claytonsize_t
68349ce682dfa7993d31206cea19ce7006cd3f3077eGreg ClaytonFileSpec::GetPath(char *path, size_t path_max_len) const
68424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
68549ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    if (path_max_len)
68624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
68749ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *dirname = m_directory.GetCString();
68849ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton        const char *filename = m_filename.GetCString();
68924b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        if (dirname)
69024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
69124b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            if (filename)
69249ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s/%s", dirname, filename);
69324b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton            else
69449ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton                return ::snprintf (path, path_max_len, "%s", dirname);
69524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
69624b48ff28b7c60dd4598212c3e77935a0fc1142dGreg Clayton        else if (filename)
69724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
69849ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton            return ::snprintf (path, path_max_len, "%s", filename);
69924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
70024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
70159df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata    if (path)
70259df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata        path[0] = '\0';
70349ce682dfa7993d31206cea19ce7006cd3f3077eGreg Clayton    return 0;
70424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
70524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
70630518e01f8e264a310050cfc0e2857637fa32063Greg Claytonstd::string
70730518e01f8e264a310050cfc0e2857637fa32063Greg ClaytonFileSpec::GetPath (void) const
708bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda{
7095581a7e69714aa6c08833e060de85237ec2a690aJason Molenda    static ConstString g_slash_only ("/");
71030518e01f8e264a310050cfc0e2857637fa32063Greg Clayton    std::string path;
711bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    const char *dirname = m_directory.GetCString();
712bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    const char *filename = m_filename.GetCString();
713bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    if (dirname)
714bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    {
715bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda        path.append (dirname);
7165581a7e69714aa6c08833e060de85237ec2a690aJason Molenda        if (filename && m_directory != g_slash_only)
717bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda            path.append ("/");
718bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    }
719bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    if (filename)
720bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda        path.append (filename);
721bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda    return path;
722bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda}
723bf1fa97ab9a28890478daf70cdf6b8177ae3bbaeJason Molenda
72459df36f99b76e33852e6848a162f5c2851074ea2Enrico GranataConstString
72559df36f99b76e33852e6848a162f5c2851074ea2Enrico GranataFileSpec::GetFileNameExtension () const
72659df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata{
72749ce8969d3154e1560106cfe530444c09410f217Greg Clayton    if (m_filename)
72849ce8969d3154e1560106cfe530444c09410f217Greg Clayton    {
72949ce8969d3154e1560106cfe530444c09410f217Greg Clayton        const char *filename = m_filename.GetCString();
73049ce8969d3154e1560106cfe530444c09410f217Greg Clayton        const char* dot_pos = strrchr(filename, '.');
73149ce8969d3154e1560106cfe530444c09410f217Greg Clayton        if (dot_pos && dot_pos[1] != '\0')
73249ce8969d3154e1560106cfe530444c09410f217Greg Clayton            return ConstString(dot_pos+1);
73349ce8969d3154e1560106cfe530444c09410f217Greg Clayton    }
73449ce8969d3154e1560106cfe530444c09410f217Greg Clayton    return ConstString();
73559df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata}
73659df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata
73759df36f99b76e33852e6848a162f5c2851074ea2Enrico GranataConstString
73859df36f99b76e33852e6848a162f5c2851074ea2Enrico GranataFileSpec::GetFileNameStrippingExtension () const
73959df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata{
74059df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata    const char *filename = m_filename.GetCString();
74159df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata    if (filename == NULL)
74259df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata        return ConstString();
74359df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata
744cbed99955c9a7cadc457fd8af2ec6946124fa9a1Johnny Chen    const char* dot_pos = strrchr(filename, '.');
74559df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata    if (dot_pos == NULL)
74659df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata        return m_filename;
74759df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata
74859df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata    return ConstString(filename, dot_pos-filename);
74959df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata}
75059df36f99b76e33852e6848a162f5c2851074ea2Enrico Granata
75124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
75224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
75324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data is memory mapped and
75424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// will lazily page in data from the file as memory is accessed.
75524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is mappped will start "file_offset" bytes into the
75624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
75724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
75824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
75924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
76024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
76124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
76224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
76324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const
76424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
76524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
766102b2c2681c9a830afe25bfea35557421905e42cGreg Clayton    std::unique_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
76724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (mmap_data.get())
76824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
769683cb6970b55100f0f3aa9501b0c0ee8358a9c8cGreg Clayton        const size_t mapped_length = mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size);
770683cb6970b55100f0f3aa9501b0c0ee8358a9c8cGreg Clayton        if (((file_size == SIZE_MAX) && (mapped_length > 0)) || (mapped_length >= file_size))
77124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data_sp.reset(mmap_data.release());
77224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
77324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
77424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
77524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
77624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
77724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
77824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return the size in bytes that this object takes in memory. This
77924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// returns the size in bytes of this object, not any shared string
78024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// values it may refer to.
78124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
78224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnersize_t
78324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::MemorySize() const
78424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
78524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_filename.MemorySize() + m_directory.MemorySize();
78624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
78724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
788704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
789704363531ee4877ccc6d35d0702876096f54c67bGreg Claytonsize_t
7904b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg ClaytonFileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const
791704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton{
7924b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    Error error;
793704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    size_t bytes_read = 0;
794704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    char resolved_path[PATH_MAX];
795704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    if (GetPath(resolved_path, sizeof(resolved_path)))
796704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    {
7972f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        File file;
7982f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        error = file.Open(resolved_path, File::eOpenOptionRead);
7992f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        if (error.Success())
800704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        {
8012f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton            off_t file_offset_after_seek = file_offset;
8022f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton            bytes_read = dst_len;
8032f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton            error = file.Read(dst, bytes_read, file_offset_after_seek);
804704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton        }
805704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    }
8064b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    else
8074b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    {
8084b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton        error.SetErrorString("invalid file specification");
8094b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    }
8104b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    if (error_ptr)
8114b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton        *error_ptr = error;
812704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton    return bytes_read;
813704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton}
814704363531ee4877ccc6d35d0702876096f54c67bGreg Clayton
81524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
81624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns a shared pointer to a data buffer that contains all or
81724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// part of the contents of a file. The data copies into a heap based
81824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// buffer that lives in the DataBuffer shared pointer object returned.
81924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The data that is cached will start "file_offset" bytes into the
82024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// file, and "file_size" bytes will be mapped. If "file_size" is
82124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// greater than the number of bytes available in the file starting
82224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// at "file_offset", the number of bytes will be appropriately
82324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// truncated. The final number of bytes that get mapped can be
82424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// verified using the DataBuffer::GetByteSize() function.
82524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//------------------------------------------------------------------
82624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerDataBufferSP
8274b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg ClaytonFileSpec::ReadFileContents (off_t file_offset, size_t file_size, Error *error_ptr) const
82824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
8294b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    Error error;
83024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_sp;
83124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
83224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (GetPath(resolved_path, sizeof(resolved_path)))
83324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
8342f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        File file;
8352f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        error = file.Open(resolved_path, File::eOpenOptionRead);
8362f28ece553d2ef0d7b3e8d1419020591ec3818f9Greg Clayton        if (error.Success())
837fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        {
838fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            const bool null_terminate = false;
839fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            error = file.Read (file_size, file_offset, null_terminate, data_sp);
840fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        }
841fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    }
842fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    else
843fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    {
844fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        error.SetErrorString("invalid file specification");
845fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    }
846fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    if (error_ptr)
847fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        *error_ptr = error;
848fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    return data_sp;
849fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton}
850fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton
851fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg ClaytonDataBufferSP
852fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg ClaytonFileSpec::ReadFileContentsAsCString(Error *error_ptr)
853fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton{
854fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    Error error;
855fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    DataBufferSP data_sp;
856fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    char resolved_path[PATH_MAX];
857fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    if (GetPath(resolved_path, sizeof(resolved_path)))
858fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton    {
859fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        File file;
860fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        error = file.Open(resolved_path, File::eOpenOptionRead);
861fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        if (error.Success())
862fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        {
863fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            off_t offset = 0;
864fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            size_t length = SIZE_MAX;
865fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            const bool null_terminate = true;
866fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton            error = file.Read (length, offset, null_terminate, data_sp);
867fc04d2463ad654c28f9ee2ee836174cc86b7f8b8Greg Clayton        }
86824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
8694b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    else
8704b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    {
8714b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton        error.SetErrorString("invalid file specification");
8724b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    }
8734b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton    if (error_ptr)
8744b23ab33d221eaadf40f65a5b5fe3ca4475ff761Greg Clayton        *error_ptr = error;
87524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return data_sp;
87624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
87724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8783d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Claytonsize_t
87924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec::ReadFileLines (STLStringArray &lines)
88024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
88124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    lines.clear();
8823d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    char path[PATH_MAX];
8833d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    if (GetPath(path, sizeof(path)))
88424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
88581a96aa6242f7b559770f5dc62316253cb8cb0d4Greg Clayton        std::ifstream file_stream (path);
88624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8873d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        if (file_stream)
8883d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        {
8893d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            std::string line;
8903d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton            while (getline (file_stream, line))
8913d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton                lines.push_back (line);
8923d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton        }
8933d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    }
8943d0e2c2de1b965b6dc171a618ddb8144419ae6f5Greg Clayton    return lines.size();
89524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
89652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
89752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg ClaytonFileSpec::EnumerateDirectoryResult
89852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg ClaytonFileSpec::EnumerateDirectory
89952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton(
90052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    const char *dir_path,
90152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    bool find_directories,
90252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    bool find_files,
90352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    bool find_other,
90452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    EnumerateDirectoryCallbackType callback,
90552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    void *callback_baton
90652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton)
90752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton{
90852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    if (dir_path && dir_path[0])
90952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    {
91052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        lldb_utility::CleanUp <DIR *, int> dir_path_dir (opendir(dir_path), NULL, closedir);
91152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        if (dir_path_dir.is_valid())
91252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        {
9136f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX);
9146f9236af19e2d1916630efca7003788bc0ad955dJason Molenda#if defined (__APPLE_) && defined (__DARWIN_MAXPATHLEN)
9156f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            if (path_max < __DARWIN_MAXPATHLEN)
9166f9236af19e2d1916630efca7003788bc0ad955dJason Molenda                path_max = __DARWIN_MAXPATHLEN;
9176f9236af19e2d1916630efca7003788bc0ad955dJason Molenda#endif
9186f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            struct dirent *buf, *dp;
9196f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            buf = (struct dirent *) malloc (offsetof (struct dirent, d_name) + path_max + 1);
9206f9236af19e2d1916630efca7003788bc0ad955dJason Molenda
9216f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp)
92252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton            {
92352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                // Only search directories
92452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
92552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                {
92690df56354288b44e5b6c2844c52f1e0eefd5509bGreg Clayton                    size_t len = strlen(dp->d_name);
92790df56354288b44e5b6c2844c52f1e0eefd5509bGreg Clayton
92890df56354288b44e5b6c2844c52f1e0eefd5509bGreg Clayton                    if (len == 1 && dp->d_name[0] == '.')
92952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        continue;
93052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
93190df56354288b44e5b6c2844c52f1e0eefd5509bGreg Clayton                    if (len == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
93252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        continue;
93352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                }
93452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
93552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                bool call_callback = false;
93652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                FileSpec::FileType file_type = eFileTypeUnknown;
93752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
93852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                switch (dp->d_type)
93952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                {
94052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                default:
94152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_UNKNOWN:    file_type = eFileTypeUnknown;       call_callback = true;               break;
94252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_FIFO:       file_type = eFileTypePipe;          call_callback = find_other;         break;
94352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_CHR:        file_type = eFileTypeOther;         call_callback = find_other;         break;
94452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_DIR:        file_type = eFileTypeDirectory;     call_callback = find_directories;   break;
94552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_BLK:        file_type = eFileTypeOther;         call_callback = find_other;         break;
94652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_REG:        file_type = eFileTypeRegular;       call_callback = find_files;         break;
94752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_LNK:        file_type = eFileTypeSymbolicLink;  call_callback = find_other;         break;
94852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_SOCK:       file_type = eFileTypeSocket;        call_callback = find_other;         break;
949257082556976558deb1cb246d45c2ae1bdd7b34cGreg Clayton#if !defined(__OpenBSD__)
95052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                case DT_WHT:        file_type = eFileTypeOther;         call_callback = find_other;         break;
951257082556976558deb1cb246d45c2ae1bdd7b34cGreg Clayton#endif
95252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                }
95352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
95452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                if (call_callback)
95552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                {
95652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                    char child_path[PATH_MAX];
95752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                    const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s/%s", dir_path, dp->d_name);
9582bc9eb3ba78efc64a273729b480bafc3bbaa433aJohnny Chen                    if (child_path_len < (int)(sizeof(child_path) - 1))
95952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                    {
96052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        // Don't resolve the file type or path
96152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        FileSpec child_path_spec (child_path, false);
96252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
96352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        EnumerateDirectoryResult result = callback (callback_baton, file_type, child_path_spec);
96452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
96552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        switch (result)
96652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        {
96752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        case eEnumerateDirectoryResultNext:
96852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            // Enumerate next entry in the current directory. We just
96952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            // exit this switch and will continue enumerating the
97052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            // current directory as we currently are...
97152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            break;
97252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
97352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not
97452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            if (FileSpec::EnumerateDirectory (child_path,
97552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                                              find_directories,
97652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                                              find_files,
97752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                                              find_other,
97852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                                              callback,
97952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                                              callback_baton) == eEnumerateDirectoryResultQuit)
98052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            {
98152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                // The subdirectory returned Quit, which means to
98252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                // stop all directory enumerations at all levels.
9830c2921f5b9dab2ca1832bb746ab3aa3f66fdd0b5Jim Ingham                                if (buf)
9840c2921f5b9dab2ca1832bb746ab3aa3f66fdd0b5Jim Ingham                                    free (buf);
98552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                                return eEnumerateDirectoryResultQuit;
98652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            }
98752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            break;
98852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
98952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        case eEnumerateDirectoryResultExit:  // Exit from the current directory at the current level.
99052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            // Exit from this directory level and tell parent to
99152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            // keep enumerating.
99208f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda                            if (buf)
99308f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda                                free (buf);
99452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            return eEnumerateDirectoryResultNext;
99552fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
99652fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        case eEnumerateDirectoryResultQuit:  // Stop directory enumerations at any level
99708f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda                            if (buf)
99808f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda                                free (buf);
99952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                            return eEnumerateDirectoryResultQuit;
100052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                        }
100152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                    }
100252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton                }
100352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton            }
10046f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            if (buf)
10056f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            {
10066f9236af19e2d1916630efca7003788bc0ad955dJason Molenda                free (buf);
10076f9236af19e2d1916630efca7003788bc0ad955dJason Molenda            }
100852fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        }
100952fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    }
101052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    // By default when exiting a directory, we tell the parent enumeration
101152fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    // to continue enumerating.
101252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton    return eEnumerateDirectoryResultNext;
101352fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton}
101452fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton
101549ce8969d3154e1560106cfe530444c09410f217Greg Clayton//------------------------------------------------------------------
101649ce8969d3154e1560106cfe530444c09410f217Greg Clayton/// Returns true if the filespec represents an implementation source
101749ce8969d3154e1560106cfe530444c09410f217Greg Clayton/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
101849ce8969d3154e1560106cfe530444c09410f217Greg Clayton/// extension).
101949ce8969d3154e1560106cfe530444c09410f217Greg Clayton///
102049ce8969d3154e1560106cfe530444c09410f217Greg Clayton/// @return
102149ce8969d3154e1560106cfe530444c09410f217Greg Clayton///     \b true if the filespec represents an implementation source
102249ce8969d3154e1560106cfe530444c09410f217Greg Clayton///     file, \b false otherwise.
102349ce8969d3154e1560106cfe530444c09410f217Greg Clayton//------------------------------------------------------------------
102449ce8969d3154e1560106cfe530444c09410f217Greg Claytonbool
102549ce8969d3154e1560106cfe530444c09410f217Greg ClaytonFileSpec::IsSourceImplementationFile () const
102649ce8969d3154e1560106cfe530444c09410f217Greg Clayton{
102749ce8969d3154e1560106cfe530444c09410f217Greg Clayton    ConstString extension (GetFileNameExtension());
102849ce8969d3154e1560106cfe530444c09410f217Greg Clayton    if (extension)
102949ce8969d3154e1560106cfe530444c09410f217Greg Clayton    {
103049ce8969d3154e1560106cfe530444c09410f217Greg Clayton        static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$",
103149ce8969d3154e1560106cfe530444c09410f217Greg Clayton                                                      REG_EXTENDED | REG_ICASE);
103249ce8969d3154e1560106cfe530444c09410f217Greg Clayton        return g_source_file_regex.Execute (extension.GetCString());
103349ce8969d3154e1560106cfe530444c09410f217Greg Clayton    }
103449ce8969d3154e1560106cfe530444c09410f217Greg Clayton    return false;
103549ce8969d3154e1560106cfe530444c09410f217Greg Clayton}
103649ce8969d3154e1560106cfe530444c09410f217Greg Clayton
1037ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Claytonbool
1038ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg ClaytonFileSpec::IsRelativeToCurrentWorkingDirectory () const
1039ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton{
1040ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    const char *directory = m_directory.GetCString();
1041ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    if (directory && directory[0])
1042ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    {
1043ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        // If the path doesn't start with '/' or '~', return true
1044ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        switch (directory[0])
1045ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        {
1046ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        case '/':
1047ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        case '~':
1048ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton            return false;
1049ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        default:
1050ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton            return true;
1051ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        }
1052ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    }
1053ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    else if (m_filename)
1054ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    {
1055ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        // No directory, just a basename, return true
1056ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton        return true;
1057ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    }
1058ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    return false;
1059ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton}
1060