1 //===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 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 // Builds up (relatively) standard unix archive files (.a) containing LLVM 11 // bitcode or other files. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/LLVMContext.h" 16 #include "llvm/Module.h" 17 #include "llvm/Bitcode/Archive.h" 18 #include "llvm/Support/CommandLine.h" 19 #include "llvm/Support/ManagedStatic.h" 20 #include "llvm/Support/PrettyStackTrace.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "llvm/System/Signals.h" 23 #include <iostream> 24 #include <algorithm> 25 #include <iomanip> 26 #include <memory> 27 using namespace llvm; 28 29 // Option for compatibility with AIX, not used but must allow it to be present. 30 static cl::opt<bool> 31 X32Option ("X32_64", cl::Hidden, 32 cl::desc("Ignored option for compatibility with AIX")); 33 34 // llvm-ar operation code and modifier flags. This must come first. 35 static cl::opt<std::string> 36 Options(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 37 38 // llvm-ar remaining positional arguments. 39 static cl::list<std::string> 40 RestOfArgs(cl::Positional, cl::OneOrMore, 41 cl::desc("[relpos] [count] <archive-file> [members]...")); 42 43 // MoreHelp - Provide additional help output explaining the operations and 44 // modifiers of llvm-ar. This object instructs the CommandLine library 45 // to print the text of the constructor when the --help option is given. 46 static cl::extrahelp MoreHelp( 47 "\nOPERATIONS:\n" 48 " d[NsS] - delete file(s) from the archive\n" 49 " m[abiSs] - move file(s) in the archive\n" 50 " p[kN] - print file(s) found in the archive\n" 51 " q[ufsS] - quick append file(s) to the archive\n" 52 " r[abfiuzRsS] - replace or insert file(s) into the archive\n" 53 " t - display contents of archive\n" 54 " x[No] - extract file(s) from the archive\n" 55 "\nMODIFIERS (operation specific):\n" 56 " [a] - put file(s) after [relpos]\n" 57 " [b] - put file(s) before [relpos] (same as [i])\n" 58 " [f] - truncate inserted file names\n" 59 " [i] - put file(s) before [relpos] (same as [b])\n" 60 " [k] - always print bitcode files (default is to skip them)\n" 61 " [N] - use instance [count] of name\n" 62 " [o] - preserve original dates\n" 63 " [P] - use full path names when matching\n" 64 " [R] - recurse through directories when inserting\n" 65 " [s] - create an archive index (cf. ranlib)\n" 66 " [S] - do not build a symbol table\n" 67 " [u] - update only files newer than archive contents\n" 68 " [z] - compress files before inserting/extracting\n" 69 "\nMODIFIERS (generic):\n" 70 " [c] - do not warn if the library had to be created\n" 71 " [v] - be verbose about actions taken\n" 72 " [V] - be *really* verbose about actions taken\n" 73 ); 74 75 // This enumeration delineates the kinds of operations on an archive 76 // that are permitted. 77 enum ArchiveOperation { 78 NoOperation, ///< An operation hasn't been specified 79 Print, ///< Print the contents of the archive 80 Delete, ///< Delete the specified members 81 Move, ///< Move members to end or as given by {a,b,i} modifiers 82 QuickAppend, ///< Quickly append to end of archive 83 ReplaceOrInsert, ///< Replace or Insert members 84 DisplayTable, ///< Display the table of contents 85 Extract ///< Extract files back to file system 86 }; 87 88 // Modifiers to follow operation to vary behavior 89 bool AddAfter = false; ///< 'a' modifier 90 bool AddBefore = false; ///< 'b' modifier 91 bool Create = false; ///< 'c' modifier 92 bool TruncateNames = false; ///< 'f' modifier 93 bool InsertBefore = false; ///< 'i' modifier 94 bool DontSkipBitcode = false; ///< 'k' modifier 95 bool UseCount = false; ///< 'N' modifier 96 bool OriginalDates = false; ///< 'o' modifier 97 bool FullPath = false; ///< 'P' modifier 98 bool RecurseDirectories = false; ///< 'R' modifier 99 bool SymTable = true; ///< 's' & 'S' modifiers 100 bool OnlyUpdate = false; ///< 'u' modifier 101 bool Verbose = false; ///< 'v' modifier 102 bool ReallyVerbose = false; ///< 'V' modifier 103 bool Compression = false; ///< 'z' modifier 104 105 // Relative Positional Argument (for insert/move). This variable holds 106 // the name of the archive member to which the 'a', 'b' or 'i' modifier 107 // refers. Only one of 'a', 'b' or 'i' can be specified so we only need 108 // one variable. 109 std::string RelPos; 110 111 // Select which of multiple entries in the archive with the same name should be 112 // used (specified with -N) for the delete and extract operations. 113 int Count = 1; 114 115 // This variable holds the name of the archive file as given on the 116 // command line. 117 std::string ArchiveName; 118 119 // This variable holds the list of member files to proecess, as given 120 // on the command line. 121 std::vector<std::string> Members; 122 123 // This variable holds the (possibly expanded) list of path objects that 124 // correspond to files we will 125 std::set<sys::Path> Paths; 126 127 // The Archive object to which all the editing operations will be sent. 128 Archive* TheArchive = 0; 129 130 // getRelPos - Extract the member filename from the command line for 131 // the [relpos] argument associated with a, b, and i modifiers 132 void getRelPos() { 133 if(RestOfArgs.size() > 0) { 134 RelPos = RestOfArgs[0]; 135 RestOfArgs.erase(RestOfArgs.begin()); 136 } 137 else 138 throw "Expected [relpos] for a, b, or i modifier"; 139 } 140 141 // getCount - Extract the [count] argument associated with the N modifier 142 // from the command line and check its value. 143 void getCount() { 144 if(RestOfArgs.size() > 0) { 145 Count = atoi(RestOfArgs[0].c_str()); 146 RestOfArgs.erase(RestOfArgs.begin()); 147 } 148 else 149 throw "Expected [count] value with N modifier"; 150 151 // Non-positive counts are not allowed 152 if (Count < 1) 153 throw "Invalid [count] value (not a positive integer)"; 154 } 155 156 // getArchive - Get the archive file name from the command line 157 void getArchive() { 158 if(RestOfArgs.size() > 0) { 159 ArchiveName = RestOfArgs[0]; 160 RestOfArgs.erase(RestOfArgs.begin()); 161 } 162 else 163 throw "An archive name must be specified."; 164 } 165 166 // getMembers - Copy over remaining items in RestOfArgs to our Members vector 167 // This is just for clarity. 168 void getMembers() { 169 if(RestOfArgs.size() > 0) 170 Members = std::vector<std::string>(RestOfArgs); 171 } 172 173 // parseCommandLine - Parse the command line options as presented and return the 174 // operation specified. Process all modifiers and check to make sure that 175 // constraints on modifier/operation pairs have not been violated. 176 ArchiveOperation parseCommandLine() { 177 178 // Keep track of number of operations. We can only specify one 179 // per execution. 180 unsigned NumOperations = 0; 181 182 // Keep track of the number of positional modifiers (a,b,i). Only 183 // one can be specified. 184 unsigned NumPositional = 0; 185 186 // Keep track of which operation was requested 187 ArchiveOperation Operation = NoOperation; 188 189 for(unsigned i=0; i<Options.size(); ++i) { 190 switch(Options[i]) { 191 case 'd': ++NumOperations; Operation = Delete; break; 192 case 'm': ++NumOperations; Operation = Move ; break; 193 case 'p': ++NumOperations; Operation = Print; break; 194 case 'q': ++NumOperations; Operation = QuickAppend; break; 195 case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 196 case 't': ++NumOperations; Operation = DisplayTable; break; 197 case 'x': ++NumOperations; Operation = Extract; break; 198 case 'c': Create = true; break; 199 case 'f': TruncateNames = true; break; 200 case 'k': DontSkipBitcode = true; break; 201 case 'l': /* accepted but unused */ break; 202 case 'o': OriginalDates = true; break; 203 case 'P': FullPath = true; break; 204 case 'R': RecurseDirectories = true; break; 205 case 's': SymTable = true; break; 206 case 'S': SymTable = false; break; 207 case 'u': OnlyUpdate = true; break; 208 case 'v': Verbose = true; break; 209 case 'V': Verbose = ReallyVerbose = true; break; 210 case 'z': Compression = true; break; 211 case 'a': 212 getRelPos(); 213 AddAfter = true; 214 NumPositional++; 215 break; 216 case 'b': 217 getRelPos(); 218 AddBefore = true; 219 NumPositional++; 220 break; 221 case 'i': 222 getRelPos(); 223 InsertBefore = true; 224 NumPositional++; 225 break; 226 case 'N': 227 getCount(); 228 UseCount = true; 229 break; 230 default: 231 cl::PrintHelpMessage(); 232 } 233 } 234 235 // At this point, the next thing on the command line must be 236 // the archive name. 237 getArchive(); 238 239 // Everything on the command line at this point is a member. 240 getMembers(); 241 242 // Perform various checks on the operation/modifier specification 243 // to make sure we are dealing with a legal request. 244 if (NumOperations == 0) 245 throw "You must specify at least one of the operations"; 246 if (NumOperations > 1) 247 throw "Only one operation may be specified"; 248 if (NumPositional > 1) 249 throw "You may only specify one of a, b, and i modifiers"; 250 if (AddAfter || AddBefore || InsertBefore) 251 if (Operation != Move && Operation != ReplaceOrInsert) 252 throw "The 'a', 'b' and 'i' modifiers can only be specified with " 253 "the 'm' or 'r' operations"; 254 if (RecurseDirectories && Operation != ReplaceOrInsert) 255 throw "The 'R' modifiers is only applicabe to the 'r' operation"; 256 if (OriginalDates && Operation != Extract) 257 throw "The 'o' modifier is only applicable to the 'x' operation"; 258 if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 259 throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 260 if (OnlyUpdate && Operation != ReplaceOrInsert) 261 throw "The 'u' modifier is only applicable to the 'r' operation"; 262 if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) 263 throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; 264 if (Count > 1 && Members.size() > 1) 265 throw "Only one member name may be specified with the 'N' modifier"; 266 267 // Return the parsed operation to the caller 268 return Operation; 269 } 270 271 // recurseDirectories - Implements the "R" modifier. This function scans through 272 // the Paths vector (built by buildPaths, below) and replaces any directories it 273 // finds with all the files in that directory (recursively). It uses the 274 // sys::Path::getDirectoryContent method to perform the actual directory scans. 275 bool 276 recurseDirectories(const sys::Path& path, 277 std::set<sys::Path>& result, std::string* ErrMsg) { 278 result.clear(); 279 if (RecurseDirectories) { 280 std::set<sys::Path> content; 281 if (path.getDirectoryContents(content, ErrMsg)) 282 return true; 283 284 for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 285 I != E; ++I) { 286 // Make sure it exists and is a directory 287 sys::PathWithStatus PwS(*I); 288 const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); 289 if (!Status) 290 return true; 291 if (Status->isDir) { 292 std::set<sys::Path> moreResults; 293 if (recurseDirectories(*I, moreResults, ErrMsg)) 294 return true; 295 result.insert(moreResults.begin(), moreResults.end()); 296 } else { 297 result.insert(*I); 298 } 299 } 300 } 301 return false; 302 } 303 304 // buildPaths - Convert the strings in the Members vector to sys::Path objects 305 // and make sure they are valid and exist exist. This check is only needed for 306 // the operations that add/replace files to the archive ('q' and 'r') 307 bool buildPaths(bool checkExistence, std::string* ErrMsg) { 308 for (unsigned i = 0; i < Members.size(); i++) { 309 sys::Path aPath; 310 if (!aPath.set(Members[i])) 311 throw std::string("File member name invalid: ") + Members[i]; 312 if (checkExistence) { 313 if (!aPath.exists()) 314 throw std::string("File does not exist: ") + Members[i]; 315 std::string Err; 316 sys::PathWithStatus PwS(aPath); 317 const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 318 if (!si) 319 throw Err; 320 if (si->isDir) { 321 std::set<sys::Path> dirpaths; 322 if (recurseDirectories(aPath, dirpaths, ErrMsg)) 323 return true; 324 Paths.insert(dirpaths.begin(),dirpaths.end()); 325 } else { 326 Paths.insert(aPath); 327 } 328 } else { 329 Paths.insert(aPath); 330 } 331 } 332 return false; 333 } 334 335 // printSymbolTable - print out the archive's symbol table. 336 void printSymbolTable() { 337 std::cout << "\nArchive Symbol Table:\n"; 338 const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 339 for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 340 I != E; ++I ) { 341 unsigned offset = TheArchive->getFirstFileOffset() + I->second; 342 std::cout << " " << std::setw(9) << offset << "\t" << I->first <<"\n"; 343 } 344 } 345 346 // doPrint - Implements the 'p' operation. This function traverses the archive 347 // looking for members that match the path list. It is careful to uncompress 348 // things that should be and to skip bitcode files unless the 'k' modifier was 349 // given. 350 bool doPrint(std::string* ErrMsg) { 351 if (buildPaths(false, ErrMsg)) 352 return true; 353 unsigned countDown = Count; 354 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 355 I != E; ++I ) { 356 if (Paths.empty() || 357 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 358 if (countDown == 1) { 359 const char* data = reinterpret_cast<const char*>(I->getData()); 360 361 // Skip things that don't make sense to print 362 if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 363 I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) 364 continue; 365 366 if (Verbose) 367 std::cout << "Printing " << I->getPath().toString() << "\n"; 368 369 unsigned len = I->getSize(); 370 std::cout.write(data, len); 371 } else { 372 countDown--; 373 } 374 } 375 } 376 return false; 377 } 378 379 // putMode - utility function for printing out the file mode when the 't' 380 // operation is in verbose mode. 381 void 382 printMode(unsigned mode) { 383 if (mode & 004) 384 std::cout << "r"; 385 else 386 std::cout << "-"; 387 if (mode & 002) 388 std::cout << "w"; 389 else 390 std::cout << "-"; 391 if (mode & 001) 392 std::cout << "x"; 393 else 394 std::cout << "-"; 395 } 396 397 // doDisplayTable - Implement the 't' operation. This function prints out just 398 // the file names of each of the members. However, if verbose mode is requested 399 // ('v' modifier) then the file type, permission mode, user, group, size, and 400 // modification time are also printed. 401 bool 402 doDisplayTable(std::string* ErrMsg) { 403 if (buildPaths(false, ErrMsg)) 404 return true; 405 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 406 I != E; ++I ) { 407 if (Paths.empty() || 408 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 409 if (Verbose) { 410 // FIXME: Output should be this format: 411 // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 412 if (I->isBitcode()) 413 std::cout << "b"; 414 else if (I->isCompressed()) 415 std::cout << "Z"; 416 else 417 std::cout << " "; 418 unsigned mode = I->getMode(); 419 printMode((mode >> 6) & 007); 420 printMode((mode >> 3) & 007); 421 printMode(mode & 007); 422 std::cout << " " << std::setw(4) << I->getUser(); 423 std::cout << "/" << std::setw(4) << I->getGroup(); 424 std::cout << " " << std::setw(8) << I->getSize(); 425 std::cout << " " << std::setw(20) << 426 I->getModTime().toString().substr(4); 427 std::cout << " " << I->getPath().toString() << "\n"; 428 } else { 429 std::cout << I->getPath().toString() << "\n"; 430 } 431 } 432 } 433 if (ReallyVerbose) 434 printSymbolTable(); 435 return false; 436 } 437 438 // doExtract - Implement the 'x' operation. This function extracts files back to 439 // the file system, making sure to uncompress any that were compressed 440 bool 441 doExtract(std::string* ErrMsg) { 442 if (buildPaths(false, ErrMsg)) 443 return true; 444 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 445 I != E; ++I ) { 446 if (Paths.empty() || 447 (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 448 449 // Make sure the intervening directories are created 450 if (I->hasPath()) { 451 sys::Path dirs(I->getPath()); 452 dirs.eraseComponent(); 453 if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) 454 return true; 455 } 456 457 // Open up a file stream for writing 458 std::ios::openmode io_mode = std::ios::out | std::ios::trunc | 459 std::ios::binary; 460 std::ofstream file(I->getPath().c_str(), io_mode); 461 462 // Get the data and its length 463 const char* data = reinterpret_cast<const char*>(I->getData()); 464 unsigned len = I->getSize(); 465 466 // Write the data. 467 file.write(data,len); 468 file.close(); 469 470 // If we're supposed to retain the original modification times, etc. do so 471 // now. 472 if (OriginalDates) 473 I->getPath().setStatusInfoOnDisk(I->getFileStatus()); 474 } 475 } 476 return false; 477 } 478 479 // doDelete - Implement the delete operation. This function deletes zero or more 480 // members from the archive. Note that if the count is specified, there should 481 // be no more than one path in the Paths list or else this algorithm breaks. 482 // That check is enforced in parseCommandLine (above). 483 bool 484 doDelete(std::string* ErrMsg) { 485 if (buildPaths(false, ErrMsg)) 486 return true; 487 if (Paths.empty()) 488 return false; 489 unsigned countDown = Count; 490 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 491 I != E; ) { 492 if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 493 if (countDown == 1) { 494 Archive::iterator J = I; 495 ++I; 496 TheArchive->erase(J); 497 } else 498 countDown--; 499 } else { 500 ++I; 501 } 502 } 503 504 // We're done editting, reconstruct the archive. 505 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 506 return true; 507 if (ReallyVerbose) 508 printSymbolTable(); 509 return false; 510 } 511 512 // doMore - Implement the move operation. This function re-arranges just the 513 // order of the archive members so that when the archive is written the move 514 // of the members is accomplished. Note the use of the RelPos variable to 515 // determine where the items should be moved to. 516 bool 517 doMove(std::string* ErrMsg) { 518 if (buildPaths(false, ErrMsg)) 519 return true; 520 521 // By default and convention the place to move members to is the end of the 522 // archive. 523 Archive::iterator moveto_spot = TheArchive->end(); 524 525 // However, if the relative positioning modifiers were used, we need to scan 526 // the archive to find the member in question. If we don't find it, its no 527 // crime, we just move to the end. 528 if (AddBefore || InsertBefore || AddAfter) { 529 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 530 I != E; ++I ) { 531 if (RelPos == I->getPath().toString()) { 532 if (AddAfter) { 533 moveto_spot = I; 534 moveto_spot++; 535 } else { 536 moveto_spot = I; 537 } 538 break; 539 } 540 } 541 } 542 543 // Keep a list of the paths remaining to be moved 544 std::set<sys::Path> remaining(Paths); 545 546 // Scan the archive again, this time looking for the members to move to the 547 // moveto_spot. 548 for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 549 I != E && !remaining.empty(); ++I ) { 550 std::set<sys::Path>::iterator found = 551 std::find(remaining.begin(),remaining.end(),I->getPath()); 552 if (found != remaining.end()) { 553 if (I != moveto_spot) 554 TheArchive->splice(moveto_spot,*TheArchive,I); 555 remaining.erase(found); 556 } 557 } 558 559 // We're done editting, reconstruct the archive. 560 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 561 return true; 562 if (ReallyVerbose) 563 printSymbolTable(); 564 return false; 565 } 566 567 // doQuickAppend - Implements the 'q' operation. This function just 568 // indiscriminantly adds the members to the archive and rebuilds it. 569 bool 570 doQuickAppend(std::string* ErrMsg) { 571 // Get the list of paths to append. 572 if (buildPaths(true, ErrMsg)) 573 return true; 574 if (Paths.empty()) 575 return false; 576 577 // Append them quickly. 578 for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 579 PI != PE; ++PI) { 580 if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) 581 return true; 582 } 583 584 // We're done editting, reconstruct the archive. 585 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 586 return true; 587 if (ReallyVerbose) 588 printSymbolTable(); 589 return false; 590 } 591 592 // doReplaceOrInsert - Implements the 'r' operation. This function will replace 593 // any existing files or insert new ones into the archive. 594 bool 595 doReplaceOrInsert(std::string* ErrMsg) { 596 597 // Build the list of files to be added/replaced. 598 if (buildPaths(true, ErrMsg)) 599 return true; 600 if (Paths.empty()) 601 return false; 602 603 // Keep track of the paths that remain to be inserted. 604 std::set<sys::Path> remaining(Paths); 605 606 // Default the insertion spot to the end of the archive 607 Archive::iterator insert_spot = TheArchive->end(); 608 609 // Iterate over the archive contents 610 for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 611 I != E && !remaining.empty(); ++I ) { 612 613 // Determine if this archive member matches one of the paths we're trying 614 // to replace. 615 616 std::set<sys::Path>::iterator found = remaining.end(); 617 for (std::set<sys::Path>::iterator RI = remaining.begin(), 618 RE = remaining.end(); RI != RE; ++RI ) { 619 std::string compare(RI->toString()); 620 if (TruncateNames && compare.length() > 15) { 621 const char* nm = compare.c_str(); 622 unsigned len = compare.length(); 623 size_t slashpos = compare.rfind('/'); 624 if (slashpos != std::string::npos) { 625 nm += slashpos + 1; 626 len -= slashpos +1; 627 } 628 if (len > 15) 629 len = 15; 630 compare.assign(nm,len); 631 } 632 if (compare == I->getPath().toString()) { 633 found = RI; 634 break; 635 } 636 } 637 638 if (found != remaining.end()) { 639 std::string Err; 640 sys::PathWithStatus PwS(*found); 641 const sys::FileStatus *si = PwS.getFileStatus(false, &Err); 642 if (!si) 643 return true; 644 if (!si->isDir) { 645 if (OnlyUpdate) { 646 // Replace the item only if it is newer. 647 if (si->modTime > I->getModTime()) 648 if (I->replaceWith(*found, ErrMsg)) 649 return true; 650 } else { 651 // Replace the item regardless of time stamp 652 if (I->replaceWith(*found, ErrMsg)) 653 return true; 654 } 655 } else { 656 // We purposefully ignore directories. 657 } 658 659 // Remove it from our "to do" list 660 remaining.erase(found); 661 } 662 663 // Determine if this is the place where we should insert 664 if ((AddBefore || InsertBefore) && (RelPos == I->getPath().toString())) 665 insert_spot = I; 666 else if (AddAfter && (RelPos == I->getPath().toString())) { 667 insert_spot = I; 668 insert_spot++; 669 } 670 } 671 672 // If we didn't replace all the members, some will remain and need to be 673 // inserted at the previously computed insert-spot. 674 if (!remaining.empty()) { 675 for (std::set<sys::Path>::iterator PI = remaining.begin(), 676 PE = remaining.end(); PI != PE; ++PI) { 677 if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) 678 return true; 679 } 680 } 681 682 // We're done editting, reconstruct the archive. 683 if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) 684 return true; 685 if (ReallyVerbose) 686 printSymbolTable(); 687 return false; 688 } 689 690 // main - main program for llvm-ar .. see comments in the code 691 int main(int argc, char **argv) { 692 // Print a stack trace if we signal out. 693 sys::PrintStackTraceOnErrorSignal(); 694 PrettyStackTraceProgram X(argc, argv); 695 LLVMContext &Context = getGlobalContext(); 696 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 697 698 // Have the command line options parsed and handle things 699 // like --help and --version. 700 cl::ParseCommandLineOptions(argc, argv, 701 "LLVM Archiver (llvm-ar)\n\n" 702 " This program archives bitcode files into single libraries\n" 703 ); 704 705 int exitCode = 0; 706 707 // Make sure we don't exit with "unhandled exception". 708 try { 709 // Do our own parsing of the command line because the CommandLine utility 710 // can't handle the grouped positional parameters without a dash. 711 ArchiveOperation Operation = parseCommandLine(); 712 713 // Check the path name of the archive 714 sys::Path ArchivePath; 715 if (!ArchivePath.set(ArchiveName)) 716 throw std::string("Archive name invalid: ") + ArchiveName; 717 718 // Create or open the archive object. 719 if (!ArchivePath.exists()) { 720 // Produce a warning if we should and we're creating the archive 721 if (!Create) 722 errs() << argv[0] << ": creating " << ArchivePath.toString() << "\n"; 723 TheArchive = Archive::CreateEmpty(ArchivePath, Context); 724 TheArchive->writeToDisk(); 725 } else { 726 std::string Error; 727 TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); 728 if (TheArchive == 0) { 729 errs() << argv[0] << ": error loading '" << ArchivePath << "': " 730 << Error << "!\n"; 731 return 1; 732 } 733 } 734 735 // Make sure we're not fooling ourselves. 736 assert(TheArchive && "Unable to instantiate the archive"); 737 738 // Make sure we clean up the archive even on failure. 739 std::auto_ptr<Archive> AutoArchive(TheArchive); 740 741 // Perform the operation 742 std::string ErrMsg; 743 bool haveError = false; 744 switch (Operation) { 745 case Print: haveError = doPrint(&ErrMsg); break; 746 case Delete: haveError = doDelete(&ErrMsg); break; 747 case Move: haveError = doMove(&ErrMsg); break; 748 case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; 749 case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; 750 case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; 751 case Extract: haveError = doExtract(&ErrMsg); break; 752 case NoOperation: 753 errs() << argv[0] << ": No operation was selected.\n"; 754 break; 755 } 756 if (haveError) { 757 errs() << argv[0] << ": " << ErrMsg << "\n"; 758 return 1; 759 } 760 } catch (const char*msg) { 761 // These errors are usage errors, thrown only by the various checks in the 762 // code above. 763 errs() << argv[0] << ": " << msg << "\n\n"; 764 cl::PrintHelpMessage(); 765 exitCode = 1; 766 } catch (const std::string& msg) { 767 // These errors are thrown by LLVM libraries (e.g. lib System) and represent 768 // a more serious error so we bump the exitCode and don't print the usage. 769 errs() << argv[0] << ": " << msg << "\n"; 770 exitCode = 2; 771 } catch (...) { 772 // This really shouldn't happen, but just in case .... 773 errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; 774 exitCode = 3; 775 } 776 777 // Return result code back to operating system. 778 return exitCode; 779 } 780