Home | History | Annotate | Download | only in Host
      1 //===-- FileSpec.h ----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef liblldb_FileSpec_h_
     11 #define liblldb_FileSpec_h_
     12 #if defined(__cplusplus)
     13 
     14 #include "lldb/lldb-private.h"
     15 #include "lldb/Core/ConstString.h"
     16 #include "lldb/Core/STLUtils.h"
     17 #include "lldb/Host/TimeValue.h"
     18 
     19 namespace lldb_private {
     20 
     21 //----------------------------------------------------------------------
     22 /// @class FileSpec FileSpec.h "lldb/Host/FileSpec.h"
     23 /// @brief A file utility class.
     24 ///
     25 /// A file specification class that divides paths up into a directory
     26 /// and basename. These string values of the paths are put into uniqued
     27 /// string pools for fast comparisons and efficient memory usage.
     28 ///
     29 /// Another reason the paths are split into the directory and basename
     30 /// is to allow efficient debugger searching. Often in a debugger the
     31 /// user types in the basename of the file, for example setting a
     32 /// breakpoint by file and line, or specifying a module (shared library)
     33 /// to limit the scope in which to execute a command. The user rarely
     34 /// types in a full path. When the paths are already split up, it makes
     35 /// it easy for us to compare only the basenames of a lot of file
     36 /// specifications without having to split up the file path each time
     37 /// to get to the basename.
     38 //----------------------------------------------------------------------
     39 class FileSpec
     40 {
     41 public:
     42     typedef enum FileType
     43     {
     44         eFileTypeInvalid = -1,
     45         eFileTypeUnknown = 0,
     46         eFileTypeDirectory,
     47         eFileTypePipe,
     48         eFileTypeRegular,
     49         eFileTypeSocket,
     50         eFileTypeSymbolicLink,
     51         eFileTypeOther
     52     } FileType;
     53 
     54     FileSpec();
     55 
     56     //------------------------------------------------------------------
     57     /// Constructor with path.
     58     ///
     59     /// Takes a path to a file which can be just a filename, or a full
     60     /// path. If \a path is not NULL or empty, this function will call
     61     /// FileSpec::SetFile (const char *path, bool resolve).
     62     ///
     63     /// @param[in] path
     64     ///     The full or partial path to a file.
     65     ///
     66     /// @param[in] resolve_path
     67     ///     If \b true, then we resolve the path with realpath,
     68     ///     if \b false we trust the path is in canonical form already.
     69     ///
     70     /// @see FileSpec::SetFile (const char *path, bool resolve)
     71     //------------------------------------------------------------------
     72     explicit FileSpec (const char *path, bool resolve_path);
     73 
     74     //------------------------------------------------------------------
     75     /// Copy constructor
     76     ///
     77     /// Makes a copy of the uniqued directory and filename strings from
     78     /// \a rhs.
     79     ///
     80     /// @param[in] rhs
     81     ///     A const FileSpec object reference to copy.
     82     //------------------------------------------------------------------
     83     FileSpec (const FileSpec& rhs);
     84 
     85     //------------------------------------------------------------------
     86     /// Copy constructor
     87     ///
     88     /// Makes a copy of the uniqued directory and filename strings from
     89     /// \a rhs if it is not NULL.
     90     ///
     91     /// @param[in] rhs
     92     ///     A const FileSpec object pointer to copy if non-NULL.
     93     //------------------------------------------------------------------
     94     FileSpec (const FileSpec* rhs);
     95 
     96     //------------------------------------------------------------------
     97     /// Destructor.
     98     //------------------------------------------------------------------
     99     ~FileSpec ();
    100 
    101     //------------------------------------------------------------------
    102     /// Assignment operator.
    103     ///
    104     /// Makes a copy of the uniqued directory and filename strings from
    105     /// \a rhs.
    106     ///
    107     /// @param[in] rhs
    108     ///     A const FileSpec object reference to assign to this object.
    109     ///
    110     /// @return
    111     ///     A const reference to this object.
    112     //------------------------------------------------------------------
    113     const FileSpec&
    114     operator= (const FileSpec& rhs);
    115 
    116     //------------------------------------------------------------------
    117     /// Equal to operator
    118     ///
    119     /// Tests if this object is equal to \a rhs.
    120     ///
    121     /// @param[in] rhs
    122     ///     A const FileSpec object reference to compare this object
    123     ///     to.
    124     ///
    125     /// @return
    126     ///     \b true if this object is equal to \a rhs, \b false
    127     ///     otherwise.
    128     //------------------------------------------------------------------
    129     bool
    130     operator== (const FileSpec& rhs) const;
    131 
    132     //------------------------------------------------------------------
    133     /// Not equal to operator
    134     ///
    135     /// Tests if this object is not equal to \a rhs.
    136     ///
    137     /// @param[in] rhs
    138     ///     A const FileSpec object reference to compare this object
    139     ///     to.
    140     ///
    141     /// @return
    142     ///     \b true if this object is equal to \a rhs, \b false
    143     ///     otherwise.
    144     //------------------------------------------------------------------
    145     bool
    146     operator!= (const FileSpec& rhs) const;
    147 
    148     //------------------------------------------------------------------
    149     /// Less than to operator
    150     ///
    151     /// Tests if this object is less than \a rhs.
    152     ///
    153     /// @param[in] rhs
    154     ///     A const FileSpec object reference to compare this object
    155     ///     to.
    156     ///
    157     /// @return
    158     ///     \b true if this object is less than \a rhs, \b false
    159     ///     otherwise.
    160     //------------------------------------------------------------------
    161     bool
    162     operator< (const FileSpec& rhs) const;
    163 
    164     //------------------------------------------------------------------
    165     /// Convert to pointer operator.
    166     ///
    167     /// This allows code to check a FileSpec object to see if it
    168     /// contains anything valid using code such as:
    169     ///
    170     /// @code
    171     /// FileSpec file_spec(...);
    172     /// if (file_spec)
    173     /// { ...
    174     /// @endcode
    175     ///
    176     /// @return
    177     ///     A pointer to this object if either the directory or filename
    178     ///     is valid, NULL otherwise.
    179     //------------------------------------------------------------------
    180     operator bool() const;
    181 
    182     //------------------------------------------------------------------
    183     /// Logical NOT operator.
    184     ///
    185     /// This allows code to check a FileSpec object to see if it is
    186     /// invalid using code such as:
    187     ///
    188     /// @code
    189     /// FileSpec file_spec(...);
    190     /// if (!file_spec)
    191     /// { ...
    192     /// @endcode
    193     ///
    194     /// @return
    195     ///     Returns \b true if the object has an empty directory and
    196     ///     filename, \b false otherwise.
    197     //------------------------------------------------------------------
    198     bool
    199     operator! () const;
    200 
    201     //------------------------------------------------------------------
    202     /// Clears the object state.
    203     ///
    204     /// Clear this object by releasing both the directory and filename
    205     /// string values and reverting them to empty strings.
    206     //------------------------------------------------------------------
    207     void
    208     Clear ();
    209 
    210     //------------------------------------------------------------------
    211     /// Compare two FileSpec objects.
    212     ///
    213     /// If \a full is true, then both the directory and the filename
    214     /// must match. If \a full is false, then the directory names for
    215     /// \a lhs and \a rhs are only compared if they are both not empty.
    216     /// This allows a FileSpec object to only contain a filename
    217     /// and it can match FileSpec objects that have matching
    218     /// filenames with different paths.
    219     ///
    220     /// @param[in] lhs
    221     ///     A const reference to the Left Hand Side object to compare.
    222     ///
    223     /// @param[in] rhs
    224     ///     A const reference to the Right Hand Side object to compare.
    225     ///
    226     /// @param[in] full
    227     ///     If true, then both the directory and filenames will have to
    228     ///     match for a compare to return zero (equal to). If false
    229     ///     and either directory from \a lhs or \a rhs is empty, then
    230     ///     only the filename will be compared, else a full comparison
    231     ///     is done.
    232     ///
    233     /// @return
    234     ///     @li -1 if \a lhs is less than \a rhs
    235     ///     @li 0 if \a lhs is equal to \a rhs
    236     ///     @li 1 if \a lhs is greater than \a rhs
    237     //------------------------------------------------------------------
    238     static int
    239     Compare (const FileSpec& lhs, const FileSpec& rhs, bool full);
    240 
    241     static bool
    242     Equal (const FileSpec& a, const FileSpec& b, bool full);
    243 
    244     //------------------------------------------------------------------
    245     /// Dump this object to a Stream.
    246     ///
    247     /// Dump the object to the supplied stream \a s. If the object
    248     /// contains a valid directory name, it will be displayed followed
    249     /// by a directory delimiter, and the filename.
    250     ///
    251     /// @param[in] s
    252     ///     The stream to which to dump the object descripton.
    253     //------------------------------------------------------------------
    254     void
    255     Dump (Stream *s) const;
    256 
    257     //------------------------------------------------------------------
    258     /// Existence test.
    259     ///
    260     /// @return
    261     ///     \b true if the file exists on disk, \b false otherwise.
    262     //------------------------------------------------------------------
    263     bool
    264     Exists () const;
    265 
    266 
    267     //------------------------------------------------------------------
    268     /// Expanded existence test.
    269     ///
    270     /// Call into the Host to see if it can help find the file (e.g. by
    271     /// searching paths set in the environment, etc.).
    272     ///
    273     /// If found, sets the value of m_directory to the directory where
    274     /// the file was found.
    275     ///
    276     /// @return
    277     ///     \b true if was able to find the file using expanded search
    278     ///     methods, \b false otherwise.
    279     //------------------------------------------------------------------
    280     bool
    281     ResolveExecutableLocation ();
    282 
    283     //------------------------------------------------------------------
    284     /// Canonicalize this file path (basically running the static
    285     /// FileSpec::Resolve method on it). Useful if you asked us not to
    286     /// resolve the file path when you set the file.
    287     //------------------------------------------------------------------
    288     bool
    289     ResolvePath ();
    290 
    291     uint64_t
    292     GetByteSize() const;
    293 
    294     //------------------------------------------------------------------
    295     /// Directory string get accessor.
    296     ///
    297     /// @return
    298     ///     A reference to the directory string object.
    299     //------------------------------------------------------------------
    300     ConstString &
    301     GetDirectory ();
    302 
    303     //------------------------------------------------------------------
    304     /// Directory string const get accessor.
    305     ///
    306     /// @return
    307     ///     A const reference to the directory string object.
    308     //------------------------------------------------------------------
    309     const ConstString &
    310     GetDirectory () const;
    311 
    312     //------------------------------------------------------------------
    313     /// Filename string get accessor.
    314     ///
    315     /// @return
    316     ///     A reference to the filename string object.
    317     //------------------------------------------------------------------
    318     ConstString &
    319     GetFilename ();
    320 
    321     //------------------------------------------------------------------
    322     /// Filename string const get accessor.
    323     ///
    324     /// @return
    325     ///     A const reference to the filename string object.
    326     //------------------------------------------------------------------
    327     const ConstString &
    328     GetFilename () const;
    329 
    330     //------------------------------------------------------------------
    331     /// Returns true if the filespec represents an implementation source
    332     /// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
    333     /// extension).
    334     ///
    335     /// @return
    336     ///     \b true if the filespec represents an implementation source
    337     ///     file, \b false otherwise.
    338     //------------------------------------------------------------------
    339     bool
    340     IsSourceImplementationFile () const;
    341 
    342     //------------------------------------------------------------------
    343     /// Returns true if the filespec represents path that is relative
    344     /// path to the current working directory.
    345     ///
    346     /// @return
    347     ///     \b true if the filespec represents a current working
    348     ///     directory relative path, \b false otherwise.
    349     //------------------------------------------------------------------
    350     bool
    351     IsRelativeToCurrentWorkingDirectory () const;
    352 
    353     TimeValue
    354     GetModificationTime () const;
    355 
    356     //------------------------------------------------------------------
    357     /// Extract the full path to the file.
    358     ///
    359     /// Extract the directory and path into a fixed buffer. This is
    360     /// needed as the directory and path are stored in separate string
    361     /// values.
    362     ///
    363     /// @param[out] path
    364     ///     The buffer in which to place the extracted full path.
    365     ///
    366     /// @param[in] max_path_length
    367     ///     The maximum length of \a path.
    368     ///
    369     /// @return
    370     ///     Returns the number of characters that would be needed to
    371     ///     properly copy the full path into \a path. If the returned
    372     ///     number is less than \a max_path_length, then the path is
    373     ///     properly copied and terminated. If the return value is
    374     ///     >= \a max_path_length, then the path was truncated (but is
    375     ///     still NULL terminated).
    376     //------------------------------------------------------------------
    377     size_t
    378     GetPath (char *path, size_t max_path_length) const;
    379 
    380     //------------------------------------------------------------------
    381     /// Extract the full path to the file.
    382     ///
    383     /// Extract the directory and path into a std::string, which is returned.
    384     ///
    385     /// @return
    386     ///     Returns a std::string with the directory and filename
    387     ///     concatenated.
    388     //------------------------------------------------------------------
    389     std::string
    390     GetPath () const;
    391 
    392     //------------------------------------------------------------------
    393     /// Extract the extension of the file.
    394     ///
    395     /// Returns a ConstString that represents the extension of the filename
    396     /// for this FileSpec object. If this object does not represent a file,
    397     /// or the filename has no extension, ConstString(NULL) is returned.
    398     /// The dot ('.') character is not returned as part of the extension
    399     ///
    400     /// @return
    401     ///     Returns the extension of the file as a ConstString object.
    402     //------------------------------------------------------------------
    403     ConstString
    404     GetFileNameExtension () const;
    405 
    406     //------------------------------------------------------------------
    407     /// Return the filename without the extension part
    408     ///
    409     /// Returns a ConstString that represents the filename of this object
    410     /// without the extension part (e.g. for a file named "foo.bar", "foo"
    411     /// is returned)
    412     ///
    413     /// @return
    414     ///     Returns the filename without extension
    415     ///     as a ConstString object.
    416     //------------------------------------------------------------------
    417     ConstString
    418     GetFileNameStrippingExtension () const;
    419 
    420     FileType
    421     GetFileType () const;
    422 
    423     bool
    424     IsDirectory () const
    425     {
    426         return GetFileType() == FileSpec::eFileTypeDirectory;
    427     }
    428 
    429     bool
    430     IsPipe () const
    431     {
    432         return GetFileType() == FileSpec::eFileTypePipe;
    433     }
    434 
    435     bool
    436     IsRegularFile () const
    437     {
    438         return GetFileType() == FileSpec::eFileTypeRegular;
    439     }
    440 
    441     bool
    442     IsSocket () const
    443     {
    444         return GetFileType() == FileSpec::eFileTypeSocket;
    445     }
    446 
    447     bool
    448     IsSymbolicLink () const
    449     {
    450         return GetFileType() == FileSpec::eFileTypeSymbolicLink;
    451     }
    452 
    453     //------------------------------------------------------------------
    454     /// Get the memory cost of this object.
    455     ///
    456     /// Return the size in bytes that this object takes in memory. This
    457     /// returns the size in bytes of this object, not any shared string
    458     /// values it may refer to.
    459     ///
    460     /// @return
    461     ///     The number of bytes that this object occupies in memory.
    462     ///
    463     /// @see ConstString::StaticMemorySize ()
    464     //------------------------------------------------------------------
    465     size_t
    466     MemorySize () const;
    467 
    468     //------------------------------------------------------------------
    469     /// Memory map part of, or the entire contents of, a file.
    470     ///
    471     /// Returns a shared pointer to a data buffer that contains all or
    472     /// part of the contents of a file. The data is memory mapped and
    473     /// will lazily page in data from the file as memory is accessed.
    474     /// The data that is mappped will start \a offset bytes into the
    475     /// file, and \a length bytes will be mapped. If \a length is
    476     /// greater than the number of bytes available in the file starting
    477     /// at \a offset, the number of bytes will be appropriately
    478     /// truncated. The final number of bytes that get mapped can be
    479     /// verified using the DataBuffer::GetByteSize() function on the return
    480     /// shared data pointer object contents.
    481     ///
    482     /// @param[in] offset
    483     ///     The offset in bytes from the beginning of the file where
    484     ///     memory mapping should begin.
    485     ///
    486     /// @param[in] length
    487     ///     The size in bytes that should be mapped starting \a offset
    488     ///     bytes into the file. If \a length is \c SIZE_MAX, map
    489     ///     as many bytes as possible.
    490     ///
    491     /// @return
    492     ///     A shared pointer to the memeory mapped data. This shared
    493     ///     pointer can contain a NULL DataBuffer pointer, so the contained
    494     ///     pointer must be checked prior to using it.
    495     //------------------------------------------------------------------
    496     lldb::DataBufferSP
    497     MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const;
    498 
    499     //------------------------------------------------------------------
    500     /// Read part of, or the entire contents of, a file into a heap based data buffer.
    501     ///
    502     /// Returns a shared pointer to a data buffer that contains all or
    503     /// part of the contents of a file. The data copies into a heap based
    504     /// buffer that lives in the DataBuffer shared pointer object returned.
    505     /// The data that is cached will start \a offset bytes into the
    506     /// file, and \a length bytes will be mapped. If \a length is
    507     /// greater than the number of bytes available in the file starting
    508     /// at \a offset, the number of bytes will be appropriately
    509     /// truncated. The final number of bytes that get mapped can be
    510     /// verified using the DataBuffer::GetByteSize() function.
    511     ///
    512     /// @param[in] offset
    513     ///     The offset in bytes from the beginning of the file where
    514     ///     memory mapping should begin.
    515     ///
    516     /// @param[in] length
    517     ///     The size in bytes that should be mapped starting \a offset
    518     ///     bytes into the file. If \a length is \c SIZE_MAX, map
    519     ///     as many bytes as possible.
    520     ///
    521     /// @return
    522     ///     A shared pointer to the memeory mapped data. This shared
    523     ///     pointer can contain a NULL DataBuffer pointer, so the contained
    524     ///     pointer must be checked prior to using it.
    525     //------------------------------------------------------------------
    526     lldb::DataBufferSP
    527     ReadFileContents (off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = NULL) const;
    528 
    529     size_t
    530     ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const;
    531 
    532 
    533     //------------------------------------------------------------------
    534     /// Read the entire contents of a file as data that can be used
    535     /// as a C string.
    536     ///
    537     /// Read the entire contents of a file and ensure that the data
    538     /// is NULL terminated so it can be used as a C string.
    539     ///
    540     /// @return
    541     ///     A shared pointer to the data. This shared pointer can
    542     ///     contain a NULL DataBuffer pointer, so the contained pointer
    543     ///     must be checked prior to using it.
    544     //------------------------------------------------------------------
    545     lldb::DataBufferSP
    546     ReadFileContentsAsCString(Error *error_ptr = NULL);
    547     //------------------------------------------------------------------
    548     /// Change the file specificed with a new path.
    549     ///
    550     /// Update the contents of this object with a new path. The path will
    551     /// be split up into a directory and filename and stored as uniqued
    552     /// string values for quick comparison and efficient memory usage.
    553     ///
    554     /// @param[in] path
    555     ///     A full, partial, or relative path to a file.
    556     ///
    557     /// @param[in] resolve_path
    558     ///     If \b true, then we will try to resolve links the path using
    559     ///     the static FileSpec::Resolve.
    560     //------------------------------------------------------------------
    561     void
    562     SetFile (const char *path, bool resolve_path);
    563 
    564     bool
    565     IsResolved () const
    566     {
    567         return m_is_resolved;
    568     }
    569 
    570     //------------------------------------------------------------------
    571     /// Set if the file path has been resolved or not.
    572     ///
    573     /// If you know a file path is already resolved and avoided passing
    574     /// a \b true parameter for any functions that take a "bool
    575     /// resolve_path" parameter, you can set the value manually using
    576     /// this call to make sure we don't try and resolve it later, or try
    577     /// and resolve a path that has already been resolved.
    578     ///
    579     /// @param[in] is_resolved
    580     ///     A boolean value that will replace the current value that
    581     ///     indicates if the paths in this object have been resolved.
    582     //------------------------------------------------------------------
    583     void
    584     SetIsResolved (bool is_resolved)
    585     {
    586         m_is_resolved = is_resolved;
    587     }
    588     //------------------------------------------------------------------
    589     /// Read the file into an array of strings, one per line.
    590     ///
    591     /// Opens and reads the file in this object into an array of strings,
    592     /// one string per line of the file. Returns a boolean indicating
    593     /// success or failure.
    594     ///
    595     /// @param[out] lines
    596     ///     The string array into which to read the file.
    597     ///
    598     /// @result
    599     ///     Returns the number of lines that were read from the file.
    600     //------------------------------------------------------------------
    601     size_t
    602     ReadFileLines (STLStringArray &lines);
    603 
    604     //------------------------------------------------------------------
    605     /// Resolves user name and links in \a src_path, and writes the output
    606     /// to \a dst_path.  Note if the path pointed to by \a src_path does not
    607     /// exist, the contents of \a src_path will be copied to \a dst_path
    608     /// unchanged.
    609     ///
    610     /// @param[in] src_path
    611     ///     Input path to be resolved.
    612     ///
    613     /// @param[in] dst_path
    614     ///     Buffer to store the resolved path.
    615     ///
    616     /// @param[in] dst_len
    617     ///     Size of the buffer pointed to by dst_path.
    618     ///
    619     /// @result
    620     ///     The number of characters required to write the resolved path.  If the
    621     ///     resolved path doesn't fit in dst_len, dst_len-1 characters will
    622     ///     be written to \a dst_path, but the actual required length will still be returned.
    623     //------------------------------------------------------------------
    624     static size_t
    625     Resolve (const char *src_path, char *dst_path, size_t dst_len);
    626 
    627     //------------------------------------------------------------------
    628     /// Resolves the user name at the beginning of \a src_path, and writes the output
    629     /// to \a dst_path.  Note, \a src_path can contain other path components after the
    630     /// user name, they will be copied over, and if the path doesn't start with "~" it
    631     /// will also be copied over to \a dst_path.
    632     ///
    633     /// @param[in] src_path
    634     ///     Input path to be resolved.
    635     ///
    636     /// @param[in] dst_path
    637     ///     Buffer to store the resolved path.
    638     ///
    639     /// @param[in] dst_len
    640     ///     Size of the buffer pointed to by dst_path.
    641     ///
    642     /// @result
    643     ///     The number of characters required to write the resolved path, or 0 if
    644     ///     the user name could not be found.  If the
    645     ///     resolved path doesn't fit in dst_len, dst_len-1 characters will
    646     ///     be written to \a dst_path, but the actual required length will still be returned.
    647     //------------------------------------------------------------------
    648     static size_t
    649     ResolveUsername (const char *src_path, char *dst_path, size_t dst_len);
    650 
    651     static size_t
    652     ResolvePartialUsername (const char *partial_name, StringList &matches);
    653 
    654     enum EnumerateDirectoryResult
    655     {
    656         eEnumerateDirectoryResultNext,  // Enumerate next entry in the current directory
    657         eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not
    658         eEnumerateDirectoryResultExit,  // Exit from the current directory at the current level.
    659         eEnumerateDirectoryResultQuit   // Stop directory enumerations at any level
    660     };
    661 
    662     typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton,
    663                                                                         FileType file_type,
    664                                                                         const FileSpec &spec
    665 );
    666 
    667     static EnumerateDirectoryResult
    668     EnumerateDirectory (const char *dir_path,
    669                         bool find_directories,
    670                         bool find_files,
    671                         bool find_other,
    672                         EnumerateDirectoryCallbackType callback,
    673                         void *callback_baton);
    674 
    675 protected:
    676     //------------------------------------------------------------------
    677     // Member variables
    678     //------------------------------------------------------------------
    679     ConstString m_directory;    ///< The uniqued directory path
    680     ConstString m_filename;     ///< The uniqued filename path
    681     mutable bool m_is_resolved; ///< True if this path has been resolved.
    682 };
    683 
    684 //----------------------------------------------------------------------
    685 /// Dump a FileSpec object to a stream
    686 //----------------------------------------------------------------------
    687 Stream& operator << (Stream& s, const FileSpec& f);
    688 
    689 } // namespace lldb_private
    690 
    691 #endif  // #if defined(__cplusplus)
    692 #endif  // liblldb_FileSpec_h_
    693