llvm.org GIT mirror llvm / dd04df0
For PR495: Get rid of the difference between file paths and directory paths. The Path class now simply stores a path that can refer to either a file or a directory. This required various changes in the implementation and interface of the class with the corresponding impact to its users. Doxygen comments were also updated to reflect these changes. Interface changes are: appendDirectory -> appendComponent appendFile -> appendComponent elideDirectory -> eraseComponent elideFile -> eraseComponent elideSuffix -> eraseSuffix renameFile -> rename setDirectory -> set setFile -> set Changes pass Dejagnu and llvm-test/SingleSource tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22349 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Spencer 14 years ago
29 changed file(s) with 280 addition(s) and 362 deletion(s). Raw diff Collapse all Expand all
4444 ~FileRemover() {
4545 if (DeleteIt)
4646 try {
47 Filename.destroyFile();
47 Filename.destroy();
4848 } catch (...) {} // Ignore problems deleting the file.
4949 }
5050
218218 bool isValid() const;
219219
220220 /// This function determines if the contents of the path name are
221 /// empty. That is, the path has a zero length.
221 /// empty. That is, the path has a zero length. This does NOT determine if
222 /// if the file is empty. Use the getSize method for that.
222223 /// @returns true iff the path is empty.
223224 /// @brief Determines if the path name is empty (invalid).
224225 bool isEmpty() const { return path.empty(); }
225226
226 /// This function determines if the path name in this object is intended
227 /// to reference a legal file name (as opposed to a directory name). This
228 /// function does not verify anything with the file system, it merely
229 /// determines if the syntax of the path represents a file name or not.
227 /// This function determines if the object referenced by this path is
228 /// a file or not. This function accesses the under lying file system to
229 /// determine the type of entity referenced by the path.
230230 /// @returns true if this path name references a file.
231231 /// @brief Determines if the path name references a file.
232232 bool isFile() const;
233233
234 /// This function determines if the path name in this object is intended
235 /// to reference a legal directory name (as opposed to a file name). This
236 /// function does not verify anything with the file system, it merely
237 /// determines if the syntax of the path represents a directory name or
238 /// not.
234 /// This function determines if the object referenced by this path is a
235 /// directory or not. This function accesses the underlying file system to
236 /// determine the type of entity referenced by the path.
239237 /// @returns true if the path name references a directory
240238 /// @brief Determines if the path name references a directory.
241239 bool isDirectory() const;
296294 bool isDynamicLibrary() const;
297295
298296 /// This function determines if the path name references an existing file
299 /// or directory in the file system. Unlike isFile and isDirectory, this
300 /// function actually checks for the existence of the file or directory.
301 /// @returns true if the pathname references an existing file.
297 /// or directory in the file system.
298 /// @returns true if the pathname references an existing file or
299 /// directory.
302300 /// @brief Determines if the path is a file or directory in
303301 /// the file system.
304302 bool exists() const;
305303
306304 /// This function determines if the path name references a readable file
307 /// or directory in the file system. Unlike isFile and isDirectory, this
308 /// function actually checks for the existence and readability (by the
309 /// current program) of the file or directory.
305 /// or directory in the file system. This function checks for
306 /// the existence and readability (by the current program) of the file
307 /// or directory.
310308 /// @returns true if the pathname references a readable file.
311309 /// @brief Determines if the path is a readable file or directory
312310 /// in the file system.
313311 bool canRead() const;
314312
315313 /// This function determines if the path name references a writable file
316 /// or directory in the file system. Unlike isFile and isDirectory, this
317 /// function actually checks for the existence and writability (by the
318 /// current program) of the file or directory.
314 /// or directory in the file system. This function checks for the
315 /// existence and writability (by the current program) of the file or
316 /// directory.
319317 /// @returns true if the pathname references a writable file.
320318 /// @brief Determines if the path is a writable file or directory
321319 /// in the file system.
322320 bool canWrite() const;
323321
324322 /// This function determines if the path name references an executable
325 /// file in the file system. Unlike isFile and isDirectory, this
326 /// function actually checks for the existence and executability (by
327 /// the current program) of the file.
323 /// file in the file system. This function checks for the existence and
324 /// executability (by the current program) of the file.
328325 /// @returns true if the pathname references an executable file.
329326 /// @brief Determines if the path is an executable file in the file
330327 /// system.
337334 /// @brief Returns the path as a std::string.
338335 const std::string& toString() const { return path; }
339336
340 /// This function returns the last component of the path name. If the
341 /// isDirectory() function would return true then this returns the name
342 /// of the last directory in the path. If the isFile() function would
343 /// return true then this function returns the name of the file without
344 /// any of the preceding directories.
337 /// This function returns the last component of the path name. The last
338 /// component is the file or directory name occuring after the last
339 /// directory separator.
345340 /// @returns std::string containing the last component of the path name.
346341 /// @brief Returns the last component of the path name.
347342 std::string getLast() const;
348343
349 /// This function strips off the path and suffix of the file name and
350 /// returns just the basename.
344 /// This function strips off the path and suffix of the file or directory
345 /// name and returns just the basename. For example /a/foo.bar would cause
346 /// this function to return "foo".
351347 /// @returns std::string containing the basename of the path
352348 /// @throws nothing
353349 /// @brief Get the base name of the path
360356 /// @brief Build a list of directory's contents.
361357 bool getDirectoryContents(std::set& paths) const;
362358
363 /// This method attempts to destroy the directory named by the last in
364 /// the Path name. If \p remove_contents is false, an attempt will be
365 /// made to remove just the directory that this Path object refers to
366 /// (the final Path component). If \p remove_contents is true, an attempt
367 /// will be made to remove the entire contents of the directory,
368 /// recursively.
359 /// This method attempts to destroy the file or directory named by the
360 /// last component of the Path. If the Path refers to a directory and the
361 /// \p destroy_contents is false, an attempt will be made to remove just
362 /// the directory (the final Path component). If \p destroy_contents is
363 /// true, an attempt will be made to remove the entire contents of the
364 /// directory, recursively. If the Path refers to a file, the
365 /// \p destroy_contents parameter is ignored.
369366 /// @param destroy_contents Indicates whether the contents of a destroyed
370367 /// directory should also be destroyed (recursively).
371 /// @returns false if the Path does not refer to a directory, true
372 /// otherwise.
368 /// @returns true if the file/directory was destroyed, false if the path
369 /// refers to something that is neither a file nor a directory.
373370 /// @throws std::string if there is an error.
374371 /// @brief Removes the file or directory from the filesystem.
375 bool destroyDirectory( bool destroy_contents = false ) const;
376
377 /// This method attempts to destroy the file named by the last item in the
378 /// Path name.
379 /// @returns false if the Path does not refer to a file, true otherwise.
380 /// @throws std::string if there is an error.
381 /// @brief Destroy the file this Path refers to.
382 bool destroyFile() const;
372 bool destroy( bool destroy_contents = false ) const;
383373
384374 /// Obtain a 'C' string for the path name.
385375 /// @returns a 'C' string containing the path name.
436426 /// @brief Make the file readable;
437427 void makeExecutable();
438428
439 /// This method attempts to set the Path object to \p unverified_path
440 /// and interpret the name as a directory name. The \p unverified_path
441 /// is verified. If verification succeeds then \p unverified_path
442 /// is accepted as a directory and true is returned. Otherwise,
443 /// the Path object remains unchanged and false is returned.
429 /// This method sets the Path object to \p unverified_path. This can fail
430 /// if the \p unverified_path does not pass the syntactic checks of the
431 /// isValid method. If verification fails, the Path object remains
432 /// unchanged and false is returned. Otherwise true is returned and the
433 /// Path object takes on the path value of \p unverified_path
444434 /// @returns true if the path was set, false otherwise.
445435 /// @param unverified_path The path to be set in Path object.
446436 /// @throws nothing
447437 /// @brief Set a full path from a std::string
448 bool setDirectory(const std::string& unverified_path);
449
450 /// This method attempts to set the Path object to \p unverified_path
451 /// and interpret the name as a file name. The \p unverified_path
452 /// is verified. If verification succeeds then \p unverified_path
453 /// is accepted as a file name and true is returned. Otherwise,
454 /// the Path object remains unchanged and false is returned.
455 /// @returns true if the path was set, false otherwise.
456 /// @param unverified_path The path to be set in Path object.
457 /// @throws nothing
458 /// @brief Set a full path from a std::string
459 bool setFile(const std::string& unverified_path);
460
461 /// The \p dirname is added to the end of the Path if it is a legal
462 /// directory name for the operating system. The precondition for this
463 /// function is that the Path must reference a directory name (i.e.
464 /// isDirectory() returns true).
465 /// @param dirname A string providing the directory name to
466 /// be added to the end of the path.
467 /// @returns false if the directory name could not be added
468 /// @throws nothing
469 /// @brief Adds the name of a directory to a Path.
470 bool appendDirectory( const std::string& dirname );
471
472 /// One directory component is removed from the Path name. The Path must
473 /// refer to a non-root directory name (i.e. isDirectory() returns true
474 /// but isRootDirectory() returns false). Upon exit, the Path will
475 /// refer to the directory above it.
476 /// @throws nothing
477 /// @returns false if the directory name could not be removed.
438 bool set(const std::string& unverified_path);
439
440 /// One path component is removed from the Path. If only one component is
441 /// present in the path, the Path object becomes empty. If the Path object
442 /// is empty, no change is made.
443 /// @throws nothing
444 /// @returns false if the path component could not be removed.
478445 /// @brief Removes the last directory component of the Path.
479 bool elideDirectory();
480
481 /// The \p filename is added to the end of the Path if it is a legal
482 /// directory name for the operating system. The precondition for this
483 /// function is that the Path reference a directory name (i.e.
484 /// isDirectory() returns true).
485 /// @throws nothing
486 /// @returns false if the file name could not be added.
487 /// @brief Appends the name of a file.
488 bool appendFile( const std::string& filename );
489
490 /// One file component is removed from the Path name. The Path must
491 /// refer to a file (i.e. isFile() returns true). Upon exit,
492 /// the Path will refer to the directory above it.
493 /// @throws nothing
494 /// @returns false if the file name could not be removed
495 /// @brief Removes the last file component of the path.
496 bool elideFile();
446 bool eraseComponent();
447
448 /// The \p component is added to the end of the Path if it is a legal
449 /// name for the operating system. A directory separator will be added if
450 /// needed.
451 /// @throws nothing
452 /// @returns false if the path component could not be added.
453 /// @brief Appends one path component to the Path.
454 bool appendComponent( const std::string& component );
497455
498456 /// A period and the \p suffix are appended to the end of the pathname.
499457 /// The precondition for this function is that the Path reference a file
505463 /// @brief Adds a period and the \p suffix to the end of the pathname.
506464 bool appendSuffix(const std::string& suffix);
507465
508 /// The suffix of the filename is removed. The suffix begins with and
466 /// The suffix of the filename is erased. The suffix begins with and
509467 /// includes the last . character in the filename after the last directory
510468 /// separator and extends until the end of the name. If no . character is
511469 /// after the last directory separator, then the file name is left
514472 /// @returns false if there was no suffix to remove, true otherwise.
515473 /// @throws nothing
516474 /// @brief Remove the suffix from a path name.
517 bool elideSuffix();
475 bool eraseSuffix();
518476
519477 /// The current Path name is made unique in the file system. Upon return,
520478 /// the Path will have been changed to make a unique file in the file
565523 /// @returns false if the Path does not refer to a file, true otherwise.
566524 /// @throws std::string if there is an file system error.
567525 /// @brief Rename one file as another.
568 bool renameFile(const Path& newName);
526 bool rename(const Path& newName);
569527
570528 /// This method sets the access time, modification time, and permission
571529 /// mode of the file associated with \p this as given by \p si.
186186 member->next = 0;
187187 member->prev = 0;
188188 member->parent = this;
189 member->path.setFile(pathname);
189 member->path.set(pathname);
190190 member->info.fileSize = MemberSize;
191191 member->info.modTime.fromEpochTime(atoi(Hdr->date));
192192 unsigned int mode;
449449 // Close up shop
450450 FinalFile.close();
451451 arch.close();
452 TmpArchive.destroyFile();
452 TmpArchive.destroy();
453453
454454 } else {
455455 // We don't have to insert the symbol table, so just renaming the temp
456456 // file to the correct name will suffice.
457 TmpArchive.renameFile(archPath);
457 TmpArchive.rename(archPath);
458458 }
459459 } catch (...) {
460460 // Make sure we clean up.
461461 if (TmpArchive.exists())
462 TmpArchive.destroyFile();
462 TmpArchive.destroy();
463463 throw;
464464 }
465465 }
186186 member->next = 0;
187187 member->prev = 0;
188188 member->parent = this;
189 member->path.setFile(pathname);
189 member->path.set(pathname);
190190 member->info.fileSize = MemberSize;
191191 member->info.modTime.fromEpochTime(atoi(Hdr->date));
192192 unsigned int mode;
449449 // Close up shop
450450 FinalFile.close();
451451 arch.close();
452 TmpArchive.destroyFile();
452 TmpArchive.destroy();
453453
454454 } else {
455455 // We don't have to insert the symbol table, so just renaming the temp
456456 // file to the correct name will suffice.
457 TmpArchive.renameFile(archPath);
457 TmpArchive.rename(archPath);
458458 }
459459 } catch (...) {
460460 // Make sure we clean up.
461461 if (TmpArchive.exists())
462 TmpArchive.destroyFile();
462 TmpArchive.destroy();
463463 throw;
464464 }
465465 }
171171 if (SourceText == 0) { // Read the file in if we haven't already.
172172 sys::Path tmpPath;
173173 if (!Directory.empty())
174 tmpPath.setDirectory(Directory);
175 tmpPath.appendFile(BaseName);
174 tmpPath.set(Directory);
175 tmpPath.appendComponent(BaseName);
176176 if (tmpPath.canRead())
177177 SourceText = new SourceFile(tmpPath.toString(), Descriptor);
178178 else
898898 // If the source library's module id is in the dependent library list of the
899899 // destination library, remove it since that module is now linked in.
900900 sys::Path modId;
901 modId.setFile(Src->getModuleIdentifier());
901 modId.set(Src->getModuleIdentifier());
902902 if (!modId.isEmpty())
903903 Dest->removeLibrary(modId.getBasename());
904904
6868
6969 void
7070 Linker::addPath(const sys::Path& path) {
71 assert(path.isDirectory() && "Can only insert directories into the path");
7271 LibPaths.push_back(path);
7372 }
7473
7675 Linker::addPaths(const std::vector& paths) {
7776 for (unsigned i = 0; i != paths.size(); ++i) {
7877 sys::Path aPath;
79 aPath.setDirectory(paths[i]);
78 aPath.set(paths[i]);
8079 LibPaths.push_back(aPath);
8180 }
8281 }
117116 static inline sys::Path IsLibrary(const std::string& Name,
118117 const sys::Path& Directory) {
119118
120 assert(Directory.isDirectory() && "Need to specify a directory");
121119 sys::Path FullPath(Directory);
122 FullPath.appendFile("lib" + Name);
123120
124 FullPath.appendSuffix("a");
125 if (FullPath.isArchive())
126 return FullPath;
121 // Make sure the directory actually is a directory in the file system.
122 if (FullPath.isDirectory())
123 {
124 // Try the libX.a form
125 FullPath.appendComponent("lib" + Name);
126 FullPath.appendSuffix("a");
127 if (FullPath.isArchive())
128 return FullPath;
127129
128 FullPath.elideSuffix();
129 FullPath.appendSuffix("bca");
130 if (FullPath.isArchive())
131 return FullPath;
130 // Try the libX.bca form
131 FullPath.eraseSuffix();
132 FullPath.appendSuffix("bca");
133 if (FullPath.isArchive())
134 return FullPath;
132135
133 FullPath.elideSuffix();
134 FullPath.appendSuffix(&(LTDL_SHLIB_EXT[1]));
135 if (FullPath.isDynamicLibrary()) // Native shared library?
136 return FullPath;
137 if (FullPath.isBytecodeFile()) // .so file containing bytecode?
138 return FullPath;
136 // Try the libX.so form
137 FullPath.eraseSuffix();
138 FullPath.appendSuffix(&(LTDL_SHLIB_EXT[1]));
139 if (FullPath.isDynamicLibrary()) // Native shared library?
140 return FullPath;
141 if (FullPath.isBytecodeFile()) // .so file containing bytecode?
142 return FullPath;
139143
144 // Not found .. fall through
145 }
146
147 // Indicate that the library was not found in the directory.
140148 FullPath.clear();
141149 return FullPath;
142150 }
4444 // if ProgramPath contains at least one / character, indicating that it is a
4545 // relative path to bugpoint itself.
4646 sys::Path Result ( ProgramPath );
47 Result.elideFile();
47 Result.eraseComponent();
4848 if (!Result.isEmpty()) {
49 Result.appendFile(ExeName);
49 Result.appendComponent(ExeName);
5050 if (Result.canExecute())
5151 return Result;
5252 }
6464 ErrorFile.close();
6565 }
6666
67 ErrorFilename.destroyFile();
67 ErrorFilename.destroy();
6868 throw ToolExecutionError(OS.str());
6969 }
7070
175175 void LLC::compileProgram(const std::string &Bytecode) {
176176 sys::Path OutputAsmFile;
177177 OutputAsm(Bytecode, OutputAsmFile);
178 OutputAsmFile.destroyFile();
178 OutputAsmFile.destroy();
179179 }
180180
181181 int LLC::ExecuteProgram(const std::string &Bytecode,
320320 void CBE::compileProgram(const std::string &Bytecode) {
321321 sys::Path OutputCFile;
322322 OutputC(Bytecode, OutputCFile);
323 OutputCFile.destroyFile();
323 OutputCFile.destroy();
324324 }
325325
326326 int CBE::ExecuteProgram(const std::string &Bytecode,
2626 Path::GetLLVMConfigDir() {
2727 Path result;
2828 #ifdef LLVM_ETCDIR
29 if (result.setDirectory(LLVM_ETCDIR))
29 if (result.set(LLVM_ETCDIR))
3030 return result;
3131 #endif
3232 return GetLLVMDefaultConfigDir();
7979 GetSystemLibraryPaths(LibPaths);
8080 for (unsigned i = 0; i < LibPaths.size(); ++i) {
8181 sys::Path FullPath(LibPaths[i]);
82 FullPath.appendFile("lib" + name + LTDL_SHLIB_EXT);
82 FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT);
8383 if (FullPath.isDynamicLibrary())
8484 return FullPath;
85 FullPath.elideSuffix();
85 FullPath.eraseSuffix();
8686 FullPath.appendSuffix("a");
8787 if (FullPath.isArchive())
8888 return FullPath;
8383 Path
8484 Path::GetRootDirectory() {
8585 Path result;
86 result.setDirectory("/");
86 result.set("/");
8787 return result;
8888 }
8989
9797 if (0 == mkdtemp(pathname))
9898 ThrowErrno(std::string(pathname) + ": can't create temporary directory");
9999 Path result;
100 result.setDirectory(pathname);
100 result.set(pathname);
101101 assert(result.isValid() && "mkdtemp didn't create a valid pathname!");
102102 return result;
103103 #elif defined(HAVE_MKSTEMP)
116116 if (-1 == ::mkdir(pathname, S_IRWXU)) // end race condition
117117 ThrowErrno(std::string(pathname) + ": can't create temporary directory");
118118 Path result;
119 result.setDirectory(pathname);
119 result.set(pathname);
120120 assert(result.isValid() && "mkstemp didn't create a valid pathname!");
121121 return result;
122122 #elif defined(HAVE_MKTEMP)
133133 if (-1 == ::mkdir(TmpName, S_IRWXU))
134134 ThrowErrno(std::string(TmpName) + ": can't create temporary directory");
135135 Path result;
136 result.setDirectory(TmpName);
136 result.set(TmpName);
137137 assert(result.isValid() && "mktemp didn't create a valid pathname!");
138138 return result;
139139 #else
154154 if (-1 == ::mkdir(pathname, S_IRWXU))
155155 ThrowErrno(std::string(pathname) + ": can't create temporary directory");
156156 Path result;
157 result.setDirectory(pathname);
157 result.set(pathname);
158158 assert(result.isValid() && "mkstemp didn't create a valid pathname!");
159159 return result;
160160 #endif
166166 Path tmpPath;
167167 while( delim != 0 ) {
168168 std::string tmp(at, size_t(delim-at));
169 if (tmpPath.setDirectory(tmp))
169 if (tmpPath.set(tmp))
170170 if (tmpPath.canRead())
171171 Paths.push_back(tmpPath);
172172 at = delim + 1;
173173 delim = strchr(at, ':');
174174 }
175175 if (*at != 0)
176 if (tmpPath.setDirectory(std::string(at)))
176 if (tmpPath.set(std::string(at)))
177177 if (tmpPath.canRead())
178178 Paths.push_back(tmpPath);
179179
203203 #ifdef LLVM_LIBDIR
204204 {
205205 Path tmpPath;
206 if (tmpPath.setDirectory(LLVM_LIBDIR))
206 if (tmpPath.set(LLVM_LIBDIR))
207207 if (tmpPath.canRead())
208208 Paths.push_back(tmpPath);
209209 }
221221 const char* home = getenv("HOME");
222222 if (home) {
223223 Path result;
224 if (result.setDirectory(home))
224 if (result.set(home))
225225 return result;
226226 }
227227 return GetRootDirectory();
229229
230230 bool
231231 Path::isFile() const {
232 return (isValid() && path[path.length()-1] != '/');
232 struct stat buf;
233 if (0 != stat(path.c_str(), &buf)) {
234 ThrowErrno(path + ": can't determine type of path object: ");
235 }
236 return S_ISREG(buf.st_mode);
233237 }
234238
235239 bool
236240 Path::isDirectory() const {
237 return (isValid() && path[path.length()-1] == '/');
241 struct stat buf;
242 if (0 != stat(path.c_str(), &buf)) {
243 ThrowErrno(path + ": can't determine type of path object: ");
244 }
245 return S_ISDIR(buf.st_mode);
238246 }
239247
240248 std::string
356364 info.user = buf.st_uid;
357365 info.group = buf.st_gid;
358366 info.isDir = S_ISDIR(buf.st_mode);
359 if (info.isDir && path[path.length()-1] != '/')
360 path += '/';
361367 }
362368
363369 static bool AddPermissionBits(const std::string& Filename, int bits) {
418424 ThrowErrno(aPath.path +
419425 ": can't determine file object type", stat_errno);
420426 }
421 if (S_ISDIR(buf.st_mode))
422 aPath.path += "/";
423427 result.insert(aPath);
424428 }
425429 }
429433 }
430434
431435 bool
432 Path::setDirectory(const std::string& a_path) {
433 if (a_path.size() == 0)
434 return false;
435 Path save(*this);
436 Path::set(const std::string& a_path) {
437 if (a_path.empty())
438 return false;
439 std::string save(path);
436440 path = a_path;
437 size_t last = a_path.size() -1;
438 if (a_path[last] != '/')
439 path += '/';
440441 if (!isValid()) {
441 path = save.path;
442 return false;
443 }
444 return true;
445 }
446
447 bool
448 Path::setFile(const std::string& a_path) {
449 if (a_path.size() == 0)
450 return false;
451 Path save(*this);
452 path = a_path;
453 size_t last = a_path.size() - 1;
454 while (last > 0 && a_path[last] == '/')
455 last--;
456 path.erase(last+1);
442 path = save;
443 return false;
444 }
445 return true;
446 }
447
448 bool
449 Path::appendComponent(const std::string& name) {
450 if (name.empty())
451 return false;
452 std::string save(path);
453 if (!path.empty()) {
454 size_t last = path.size() - 1;
455 if (path[last] != '/')
456 path += '/';
457 }
458 path += name;
457459 if (!isValid()) {
458 path = save.path;
459 return false;
460 }
461 return true;
462 }
463
464 bool
465 Path::appendDirectory(const std::string& dir) {
466 if (isFile())
467 return false;
468 Path save(*this);
469 path += dir;
470 path += "/";
471 if (!isValid()) {
472 path = save.path;
473 return false;
474 }
475 return true;
476 }
477
478 bool
479 Path::elideDirectory() {
480 if (isFile())
481 return false;
460 path = save;
461 return false;
462 }
463 return true;
464 }
465
466 bool
467 Path::eraseComponent() {
482468 size_t slashpos = path.rfind('/',path.size());
483 if (slashpos == 0 || slashpos == std::string::npos)
484 return false;
469 if (slashpos == 0 || slashpos == std::string::npos) {
470 path.erase();
471 return true;
472 }
485473 if (slashpos == path.size() - 1)
486474 slashpos = path.rfind('/',slashpos-1);
487 if (slashpos == std::string::npos)
488 return false;
475 if (slashpos == std::string::npos) {
476 path.erase();
477 return true;
478 }
489479 path.erase(slashpos);
490480 return true;
491481 }
492482
493483 bool
494 Path::appendFile(const std::string& file) {
495 if (!isDirectory())
496 return false;
497 Path save(*this);
498 path += file;
499 if (!isValid()) {
500 path = save.path;
501 return false;
502 }
503 return true;
504 }
505
506 bool
507 Path::elideFile() {
508 if (isDirectory())
509 return false;
510 size_t slashpos = path.rfind('/',path.size());
511 if (slashpos == std::string::npos)
512 return false;
513 path.erase(slashpos+1);
514 return true;
515 }
516
517 bool
518484 Path::appendSuffix(const std::string& suffix) {
519 if (isDirectory())
520 return false;
521 Path save(*this);
485 std::string save(path);
522486 path.append(".");
523487 path.append(suffix);
524488 if (!isValid()) {
525 path = save.path;
526 return false;
527 }
528 return true;
529 }
530
531 bool
532 Path::elideSuffix() {
533 if (isDirectory()) return false;
489 path = save;
490 return false;
491 }
492 return true;
493 }
494
495 bool
496 Path::eraseSuffix() {
497 std::string save(path);
534498 size_t dotpos = path.rfind('.',path.size());
535499 size_t slashpos = path.rfind('/',path.size());
536 if (slashpos != std::string::npos && dotpos != std::string::npos &&
500 if (slashpos != std::string::npos &&
501 dotpos != std::string::npos &&
537502 dotpos > slashpos) {
538503 path.erase(dotpos, path.size()-dotpos);
539 return true;
540 }
541 return false;
542 }
543
504 }
505 if (!isValid()) {
506 path = save;
507 return false;
508 }
509 return true;
510 }
544511
545512 bool
546513 Path::createDirectory( bool create_parents) {
547 // Make sure we're dealing with a directory
548 if (!isDirectory()) return false;
549
550514 // Get a writeable copy of the path name
551515 char pathname[MAXPATHLEN];
552516 path.copy(pathname,MAXPATHLEN);
585549
586550 bool
587551 Path::createFile() {
588 // Make sure we're dealing with a file
589 if (!isFile()) return false;
590
591552 // Create the file
592553 int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
593554 if (fd < 0)
599560
600561 bool
601562 Path::createTemporaryFile(bool reuse_current) {
602 // Make sure we're dealing with a file
603 if (!isFile())
604 return false;
605
606563 // Make this into a unique file name
607564 makeUnique( reuse_current );
608565
616573 }
617574
618575 bool
619 Path::destroyDirectory(bool remove_contents) const {
576 Path::destroy(bool remove_contents) const {
620577 // Make sure we're dealing with a directory
621 if (!isDirectory()) return false;
622
623 // If it doesn't exist, we're done.
624 if (!exists()) return true;
625
626 if (remove_contents) {
627 // Recursively descend the directory to remove its content
628 std::string cmd("/bin/rm -rf ");
629 cmd += path;
630 system(cmd.c_str());
631 } else {
632 // Otherwise, try to just remove the one directory
633 char pathname[MAXPATHLEN];
634 path.copy(pathname,MAXPATHLEN);
635 int lastchar = path.length() - 1 ;
636 if (pathname[lastchar] == '/')
637 pathname[lastchar] = 0;
638 else
639 pathname[lastchar+1] = 0;
640 if ( 0 != rmdir(pathname))
641 ThrowErrno(std::string(pathname) + ": can't destroy directory");
642 }
643 return true;
644 }
645
646 bool
647 Path::destroyFile() const {
648 if (!isFile()) return false;
649 if (0 != unlink(path.c_str()))
650 ThrowErrno(path + ": can't destroy file");
651 return true;
652 }
653
654 bool
655 Path::renameFile(const Path& newName) {
656 if (!isFile()) return false;
657 if (0 != rename(path.c_str(), newName.c_str()))
578 if (isFile()) {
579 if (0 != unlink(path.c_str()))
580 ThrowErrno(path + ": can't destroy file");
581 } else if (isDirectory()) {
582 if (remove_contents) {
583 // Recursively descend the directory to remove its content
584 std::string cmd("/bin/rm -rf ");
585 cmd += path;
586 system(cmd.c_str());
587 } else {
588 // Otherwise, try to just remove the one directory
589 char pathname[MAXPATHLEN];
590 path.copy(pathname,MAXPATHLEN);
591 int lastchar = path.length() - 1 ;
592 if (pathname[lastchar] == '/')
593 pathname[lastchar] = 0;
594 else
595 pathname[lastchar+1] = 0;
596 if ( 0 != rmdir(pathname))
597 ThrowErrno(std::string(pathname) + ": can't destroy directory");
598 }
599 }
600 else
601 return false;
602 return true;
603 }
604
605 bool
606 Path::rename(const Path& newName) {
607 if (0 != ::rename(path.c_str(), newName.c_str()))
658608 ThrowErrno(std::string("can't rename '") + path + "' as '" +
659609 newName.toString() + "' ");
660610 return true;
662612
663613 bool
664614 Path::setStatusInfo(const StatusInfo& si) const {
665 if (!isFile()) return false;
666615 struct utimbuf utb;
667616 utb.actime = si.modTime.toPosixTime();
668617 utb.modtime = utb.actime;
4141 if (progName.length() == 0) // no program
4242 return Path();
4343 Path temp;
44 if (!temp.setFile(progName)) // invalid name
44 if (!temp.set(progName)) // invalid name
4545 return Path();
4646 // FIXME: have to check for absolute filename - we cannot assume anything
4747 // about "." being in $PATH
6363
6464 // Check to see if this first directory contains the executable...
6565 Path FilePath;
66 if (FilePath.setDirectory(std::string(PathStr,Colon))) {
67 FilePath.appendFile(progName);
66 if (FilePath.set(std::string(PathStr,Colon))) {
67 FilePath.appendComponent(progName);
6868 if (FilePath.canExecute())
6969 return FilePath; // Found the executable!
7070 }
111111
112112 if (DirectoriesToRemove != 0)
113113 while (!DirectoriesToRemove->empty()) {
114 DirectoriesToRemove->back().destroyDirectory(true);
114 DirectoriesToRemove->back().destroy(true);
115115 DirectoriesToRemove->pop_back();
116116 }
117117
194194
195195 bool
196196 Path::isFile() const {
197 return (isValid() && path[path.length()-1] != '/');
197 WIN32_FILE_ATTRIBUTE_DATA fi;
198 if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
199 ThrowError(std::string(path) + ": Can't get status: ");
200 return fi.dwFileAttributes & FILE_ATTRIBUTE_NORMAL;
198201 }
199202
200203 bool
201204 Path::isDirectory() const {
202 return (isValid() && path[path.length()-1] == '/');
205 WIN32_FILE_ATTRIBUTE_DATA fi;
206 if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
207 ThrowError(std::string(path) + ": Can't get status: ");
208 return fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
203209 }
204210
205211 std::string
5757 if (BD.runPasses(Prefix, PfxOutput))
5858 return KeepPrefix;
5959
60 PrefixOutput.setFile(PfxOutput);
60 PrefixOutput.set(PfxOutput);
6161 OrigProgram = BD.Program;
6262
6363 BD.Program = ParseInputFile(PrefixOutput.toString());
6666 << PrefixOutput << "'!\n";
6767 exit(1);
6868 }
69 PrefixOutput.destroyFile();
69 PrefixOutput.destroy();
7070 }
7171
7272 std::cout << "Checking to see if these passes crash: "
280280 exit(1);
281281
282282 // Remove the intermediate C file
283 OutputCFile.destroyFile();
283 OutputCFile.destroy();
284284
285285 return "./" + SharedObjectFile;
286286 }
301301
302302 // If we're checking the program exit code, assume anything nonzero is bad.
303303 if (CheckProgramExitCode && ProgramExitedNonzero) {
304 Output.destroyFile();
304 Output.destroy();
305305 if (RemoveBytecode)
306 sys::Path(BytecodeFile).destroyFile();
306 sys::Path(BytecodeFile).destroy();
307307 return true;
308308 }
309309
320320 }
321321
322322 // Remove the generated output.
323 Output.destroyFile();
323 Output.destroy();
324324
325325 // Remove the bytecode file if we are supposed to.
326 if (RemoveBytecode) sys::Path(BytecodeFile).destroyFile();
326 if (RemoveBytecode)
327 sys::Path(BytecodeFile).destroy();
327328 return FilesDifferent;
328329 }
329330
9898 // If the prefix maintains the predicate by itself, only keep the prefix!
9999 if (BD.diffProgram(BytecodeResult)) {
100100 std::cout << " nope.\n";
101 sys::Path(BytecodeResult).destroyFile();
101 sys::Path(BytecodeResult).destroy();
102102 return KeepPrefix;
103103 }
104104 std::cout << " yup.\n"; // No miscompilation!
112112 << BytecodeResult << "'!\n";
113113 exit(1);
114114 }
115 sys::Path(BytecodeResult).destroyFile(); // No longer need the file on disk
115 sys::Path(BytecodeResult).destroy(); // No longer need the file on disk
116116
117117 // Don't check if there are no passes in the suffix.
118118 if (Suffix.empty())
774774 std::cerr << ": still failing!\n";
775775 else
776776 std::cerr << ": didn't fail.\n";
777 TestModuleBC.destroyFile();
778 SafeModuleBC.destroyFile();
779 sys::Path(SharedObject).destroyFile();
777 TestModuleBC.destroy();
778 SafeModuleBC.destroy();
779 sys::Path(SharedObject).destroy();
780780
781781 return Result;
782782 }
160160 // If we are supposed to delete the bytecode file or if the passes crashed,
161161 // remove it now. This may fail if the file was never created, but that's ok.
162162 if (DeleteOutput || !ExitedOK)
163 sys::Path(OutputFilename).destroyFile();
163 sys::Path(OutputFilename).destroy();
164164
165165 #ifndef PLATFORMINDEPENDENT
166166 if (!Quiet) {
213213 << BytecodeResult << "'!\n";
214214 exit(1);
215215 }
216 sys::Path(BytecodeResult).destroyFile(); // No longer need the file on disk
216 sys::Path(BytecodeResult).destroy(); // No longer need the file on disk
217217 return Ret;
218218 }
6464 ErrorFile.close();
6565 }
6666
67 ErrorFilename.destroyFile();
67 ErrorFilename.destroy();
6868 throw ToolExecutionError(OS.str());
6969 }
7070
175175 void LLC::compileProgram(const std::string &Bytecode) {
176176 sys::Path OutputAsmFile;
177177 OutputAsm(Bytecode, OutputAsmFile);
178 OutputAsmFile.destroyFile();
178 OutputAsmFile.destroy();
179179 }
180180
181181 int LLC::ExecuteProgram(const std::string &Bytecode,
320320 void CBE::compileProgram(const std::string &Bytecode) {
321321 sys::Path OutputCFile;
322322 OutputC(Bytecode, OutputCFile);
323 OutputCFile.destroyFile();
323 OutputCFile.destroy();
324324 }
325325
326326 int CBE::ExecuteProgram(const std::string &Bytecode,
151151 static bool isBytecodeLPath(const std::string &LibPath) {
152152 bool isBytecodeLPath = false;
153153
154 // Make sure the -L path has a '/' character
155 // because llvm-g++ passes them without the ending
156 // '/' char and sys::Path doesn't think it is a
157 // directory (see: sys::Path::isDirectory) without it
158 std::string dir = LibPath;
159 if ( dir[dir.length()-1] != '/' )
160 dir.append("/");
161
162 sys::Path LPath(dir);
154 sys::Path LPath(LibPath);
155
156 // Make sure its a directory
157 if (!LPath.isDirectory())
158 return isBytecodeLPath;
163159
164160 // Grab the contents of the -L path
165161 std::set Files;
312312
313313 if (!SaveTemps) {
314314 // Remove the assembly language file.
315 AssemblyFile.destroyFile();
315 AssemblyFile.destroy();
316316 // Remove the bytecode language file.
317 sys::Path(RealBytecodeOutput).destroyFile();
317 sys::Path(RealBytecodeOutput).destroy();
318318 }
319319
320320 } else if (NativeCBE) {
344344
345345 if (!SaveTemps) {
346346 // Remove the assembly language file.
347 CFile.destroyFile();
347 CFile.destroy();
348348 // Remove the bytecode language file.
349 sys::Path(RealBytecodeOutput).destroyFile();
349 sys::Path(RealBytecodeOutput).destroy();
350350 }
351351
352352 } else if (!LinkAsLibrary) {
292292 void buildPaths(bool checkExistence = true) {
293293 for (unsigned i = 0; i < Members.size(); i++) {
294294 sys::Path aPath;
295 if (!aPath.setFile(Members[i]))
295 if (!aPath.set(Members[i]))
296296 throw std::string("File member name invalid: ") + Members[i];
297297 if (checkExistence) {
298298 if (!aPath.exists())
430430 // Make sure the intervening directories are created
431431 if (I->hasPath()) {
432432 sys::Path dirs(I->getPath());
433 dirs.elideFile();
433 dirs.eraseComponent();
434434 dirs.createDirectory(/*create_parents=*/true);
435435 }
436436
668668
669669 // Check the path name of the archive
670670 sys::Path ArchivePath;
671 if (!ArchivePath.setFile(ArchiveName))
671 if (!ArchivePath.set(ArchiveName))
672672 throw std::string("Archive name invalid: ") + ArchiveName;
673673
674674 // Create or open the archive object.
479479 gcc, envp);
480480
481481 // Remove the assembly language file.
482 AssemblyFile.destroyFile();
482 AssemblyFile.destroy();
483483 } else if (NativeCBE) {
484484 sys::Path CFile (OutputFilename);
485485 CFile.appendSuffix("cbe.c");
504504 GenerateNative(OutputFilename, CFile.toString(), Libraries, gcc, envp);
505505
506506 // Remove the assembly language file.
507 CFile.destroyFile();
507 CFile.destroy();
508508
509509 } else {
510510 EmitShellScript(argv);
4949 //
5050 static inline std::auto_ptr LoadFile(const std::string &FN) {
5151 sys::Path Filename;
52 if (!Filename.setFile(FN)) {
52 if (!Filename.set(FN)) {
5353 std::cerr << "Invalid file name: '" << FN << "'\n";
5454 return std::auto_ptr();
5555 }
5858
5959 // Check the path name of the archive
6060 sys::Path ArchivePath;
61 if (!ArchivePath.setFile(ArchiveName))
61 if (!ArchivePath.set(ArchiveName))
6262 throw std::string("Archive name invalid: ") + ArchiveName;
6363
6464 // Make sure it exists, we don't create empty archives
133133 StringVector::const_iterator E = paths.end();
134134 while (I != E) {
135135 sys::Path tmp;
136 tmp.setDirectory(*I);
136 tmp.set(*I);
137137 IncludePaths.push_back(tmp);
138138 ++I;
139139 }
148148 StringVector::const_iterator E = paths.end();
149149 while (I != E) {
150150 sys::Path tmp;
151 tmp.setDirectory(*I);
151 tmp.set(*I);
152152 LibraryPaths.push_back(tmp);
153153 ++I;
154154 }
187187 void cleanup() {
188188 if (!isSet(KEEP_TEMPS_FLAG)) {
189189 if (TempDir.isDirectory() && TempDir.canWrite())
190 TempDir.destroyDirectory(/*remove_contents=*/true);
190 TempDir.destroy(/*remove_contents=*/true);
191191 } else {
192192 std::cout << "Temporary files are in " << TempDir << "\n";
193193 }
196196 sys::Path MakeTempFile(const std::string& basename,
197197 const std::string& suffix) {
198198 sys::Path result(TempDir);
199 if (!result.appendFile(basename))
199 if (!result.appendComponent(basename))
200200 throw basename + ": can't use this file name";
201201 if (!result.appendSuffix(suffix))
202202 throw suffix + ": can't use this file suffix";
447447 llvm::sys::Path GetPathForLinkageItem(const std::string& link_item,
448448 bool native = false) {
449449 sys::Path fullpath;
450 fullpath.setFile(link_item);
450 fullpath.set(link_item);
451451 if (fullpath.canRead())
452452 return fullpath;
453453 for (PathVector::iterator PI = LibraryPaths.begin(),
454454 PE = LibraryPaths.end(); PI != PE; ++PI) {
455 fullpath.setDirectory(PI->toString());
456 fullpath.appendFile(link_item);
455 fullpath.set(PI->toString());
456 fullpath.appendComponent(link_item);
457457 if (fullpath.canRead())
458458 return fullpath;
459459 if (native) {
462462 fullpath.appendSuffix("bc");
463463 if (fullpath.canRead())
464464 return fullpath;
465 fullpath.elideSuffix();
465 fullpath.eraseSuffix();
466466 fullpath.appendSuffix("o");
467467 if (fullpath.canRead())
468468 return fullpath;
469469 fullpath = *PI;
470 fullpath.appendFile(std::string("lib") + link_item);
470 fullpath.appendComponent(std::string("lib") + link_item);
471471 fullpath.appendSuffix("a");
472472 if (fullpath.canRead())
473473 return fullpath;
474 fullpath.elideSuffix();
474 fullpath.eraseSuffix();
475475 fullpath.appendSuffix("so");
476476 if (fullpath.canRead())
477477 return fullpath;
692692 /// The output of the translator is an LLVM Assembly program
693693 /// We need to translate it to bytecode
694694 Action* action = new Action();
695 action->program.setFile("llvm-as");
695 action->program.set("llvm-as");
696696 action->args.push_back(InFile.toString());
697697 action->args.push_back("-o");
698698 InFile.appendSuffix("bc");
734734 /// The output of the optimizer is an LLVM Assembly program
735735 /// We need to translate it to bytecode with llvm-as
736736 Action* action = new Action();
737 action->program.setFile("llvm-as");
737 action->program.set("llvm-as");
738738 action->args.push_back(InFile.toString());
739739 action->args.push_back("-f");
740740 action->args.push_back("-o");
763763 Action* action = new Action();
764764 if (isSet(EMIT_NATIVE_FLAG)) {
765765 // Use llc to get the native assembly file
766 action->program.setFile("llc");
766 action->program.set("llc");
767767 action->args.push_back(InFile.toString());
768768 action->args.push_back("-f");
769769 action->args.push_back("-o");
776776 actions.push_back(action);
777777 } else {
778778 // Just convert back to llvm assembly with llvm-dis
779 action->program.setFile("llvm-dis");
779 action->program.set("llvm-dis");
780780 action->args.push_back(InFile.toString());
781781 action->args.push_back("-f");
782782 action->args.push_back("-o");
819819
820820 // Set up the linking action with llvm-ld
821821 Action* link = new Action();
822 link->program.setFile("llvm-ld");
822 link->program.set("llvm-ld");
823823
824824 // Add in the optimization level requested
825825 switch (optLevel) {
317317 {
318318 std::string progname;
319319 if (parseProgramName(progname))
320 action.program.setFile(progname);
320 action.program.set(progname);
321321 else
322322 error("Expecting a program name");
323323
546546 // Try the environment variable
547547 const char* conf = getenv("LLVM_CONFIG_DIR");
548548 if (conf) {
549 confFile.setDirectory(conf);
550 confFile.appendFile(ftype);
549 confFile.set(conf);
550 confFile.appendComponent(ftype);
551551 if (!confFile.canRead())
552552 throw std::string("Configuration file for '") + ftype +
553553 "' is not available.";
555555 // Try the user's home directory
556556 confFile = sys::Path::GetUserHomeDirectory();
557557 if (!confFile.isEmpty()) {
558 confFile.appendDirectory(".llvm");
559 confFile.appendDirectory("etc");
560 confFile.appendFile(ftype);
558 confFile.appendComponent(".llvm");
559 confFile.appendComponent("etc");
560 confFile.appendComponent(ftype);
561561 if (!confFile.canRead())
562562 confFile.clear();
563563 }
564564 if (confFile.isEmpty()) {
565565 // Okay, try the LLVM installation directory
566566 confFile = sys::Path::GetLLVMConfigDir();
567 confFile.appendFile(ftype);
567 confFile.appendComponent(ftype);
568568 if (!confFile.canRead()) {
569569 // Okay, try the "standard" place
570570 confFile = sys::Path::GetLLVMDefaultConfigDir();
571 confFile.appendFile(ftype);
571 confFile.appendComponent(ftype);
572572 if (!confFile.canRead()) {
573573 throw std::string("Configuration file for '") + ftype +
574574 "' is not available.";
578578 }
579579 } else {
580580 confFile = configDir;
581 confFile.appendFile(ftype);
581 confFile.appendComponent(ftype);
582582 if (!confFile.canRead())
583583 throw std::string("Configuration file for '") + ftype +
584584 "' is not available.";