llvm-ar.cpp revision 0de66b5cc8766102197c565a32bc7f9436b607da
197f752f6d501f507b5ed433a28f8e6f09cbe5170Chris Lattner//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// 27c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// The LLVM Compiler Infrastructure 47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 5d607491480761386ccc64ff1facc3208c6436e39Tanya Lattner// This file was developed by the LLVM research group and is distributed under 6d607491480761386ccc64ff1facc3208c6436e39Tanya Lattner// the University of Illinois Open Source License. See LICENSE.TXT for details. 77c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//===----------------------------------------------------------------------===// 914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner// 103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Builds up (relatively) standard unix archive files (.a) containing LLVM 113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// bytecode or other files. 1214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner// 1314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner//===----------------------------------------------------------------------===// 144fa9fd3035780e7733f4b4510d1f98c70f65bfd7Brian Gaeke 1514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner#include "llvm/Module.h" 163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer#include "llvm/Bytecode/Archive.h" 17551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer#include "llvm/Support/Compressor.h" 19551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/FileUtilities.h" 20bed85ff010b95923646ed4e187a5d432cedf67daChris Lattner#include "llvm/System/Signals.h" 2186f42bdad93677fa0ca33b27afb0f493028376cbReid Spencer#include <iostream> 223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer#include <algorithm> 233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer#include <iomanip> 2414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerusing namespace llvm; 2657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Option for compatibility with ASIX, not used but must allow it to be present. 28bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstatic cl::opt<bool> 29bede58363c647a4e73112fdfb409e9af7051301eReid SpencerX32Option ("X32_64", cl::Hidden, 30bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::desc("Ignored option for compatibility with AIX")); 313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 32bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// llvm-ar operation code and modifier flags. This must come first. 33bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstatic cl::opt<std::string> 343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerOptions(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); 353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 36bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// llvm-ar remaining positional arguments. 37bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstatic cl::list<std::string> 383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerRestOfArgs(cl::Positional, cl::OneOrMore, 393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer cl::desc("[relpos] [count] <archive-file> [members]...")); 403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 41bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// MoreHelp - Provide additional help output explaining the operations and 42bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// modifiers of llvm-ar. This object instructs the CommandLine library 43bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// to print the text of the constructor when the --help option is given. 44bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstatic cl::extrahelp MoreHelp( 45bede58363c647a4e73112fdfb409e9af7051301eReid Spencer "\nOPERATIONS:\n" 46bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " d[NsS] - delete file(s) from the archive\n" 47bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " m[abiSs] - move file(s) in the archive\n" 48bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " p[kN] - print file(s) found in the archive\n" 49bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " q[ufsS] - quick append file(s) to the archive\n" 50bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " r[abfiuzRsS] - replace or insert file(s) into the archive\n" 51bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " t - display contents of archive\n" 52bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " x[No] - extract file(s) from the archive\n" 53bede58363c647a4e73112fdfb409e9af7051301eReid Spencer "\nMODIFIERS (operation specific):\n" 54bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [a] - put file(s) after [relpos]\n" 55bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [b] - put file(s) before [relpos] (same as [i])\n" 56bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [f] - truncate inserted file names\n" 57bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [i] - put file(s) before [relpos] (same as [b])\n" 58bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [k] - always print bytecode files (default is to skip them)\n" 59bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [N] - use instance [count] of name\n" 60bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [o] - preserve original dates\n" 61bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [P] - use full path names when matching\n" 62bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [R] - recurse through directories when inserting\n" 63bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [s] - create an archive index (cf. ranlib)\n" 64bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [S] - do not build a symbol table\n" 65bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [u] - update only files newer than archive contents\n" 66bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [z] - compress files before inserting/extracting\n" 67bede58363c647a4e73112fdfb409e9af7051301eReid Spencer "\nMODIFIERS (generic):\n" 68bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [c] - do not warn if the library had to be created\n" 69bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [v] - be verbose about actions taken\n" 70bede58363c647a4e73112fdfb409e9af7051301eReid Spencer " [V] - be *really* verbose about actions taken\n" 71bede58363c647a4e73112fdfb409e9af7051301eReid Spencer); 72bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This enumeration delineates the kinds of operations on an archive 743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// that are permitted. 753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerenum ArchiveOperation { 763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NoOperation, ///< An operation hasn't been specified 773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Print, ///< Print the contents of the archive 783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Delete, ///< Delete the specified members 793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Move, ///< Move members to end or as given by {a,b,i} modifiers 803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer QuickAppend, ///< Quickly append to end of archive 813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ReplaceOrInsert, ///< Replace or Insert members 823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer DisplayTable, ///< Display the table of contents 833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Extract, ///< Extract files back to file system 8457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner}; 8514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Modifiers to follow operation to vary behavior 873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddAfter = false; ///< 'a' modifier 883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool AddBefore = false; ///< 'b' modifier 893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Create = false; ///< 'c' modifier 903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool TruncateNames = false; ///< 'f' modifier 913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool InsertBefore = false; ///< 'i' modifier 923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool DontSkipBytecode = false; ///< 'k' modifier 933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool UseCount = false; ///< 'N' modifier 943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OriginalDates = false; ///< 'o' modifier 953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool FullPath = false; ///< 'P' modifier 963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool RecurseDirectories = false; ///< 'R' modifier 973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool SymTable = true; ///< 's' & 'S' modifiers 983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool OnlyUpdate = false; ///< 'u' modifier 993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Verbose = false; ///< 'v' modifier 1003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool ReallyVerbose = false; ///< 'V' modifier 1013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerbool Compression = false; ///< 'z' modifier 1023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Relative Positional Argument (for insert/move). This variable holds 1043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the name of the archive member to which the 'a', 'b' or 'i' modifier 1053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// refers. Only one of 'a', 'b' or 'i' can be specified so we only need 1063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// one variable. 1073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string RelPos; 1083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// Select which of multiple entries in the archive with the same name should be 1103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// used (specified with -N) for the delete and extract operations. 1113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerint Count = 1; 1123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the name of the archive file as given on the 1143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// command line. 1153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::string ArchiveName; 1163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the list of member files to proecess, as given 1183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// on the command line. 1193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencerstd::vector<std::string> Members; 1203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This variable holds the (possibly expanded) list of path objects that 1223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// correspond to files we will 123bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstd::set<sys::Path> Paths; 1243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// The Archive object to which all the editing operations will be sent. 1263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchive* TheArchive = 0; 1273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 1283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getRelPos - Extract the member filename from the command line for 1293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the [relpos] argument associated with a, b, and i modifiers 1303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getRelPos() { 1313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RelPos = RestOfArgs[0]; 1333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [relpos] for a, b, or i modifier"; 1373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 13857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getCount - Extract the [count] argument associated with the N modifier 1403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// from the command line and check its value. 1413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getCount() { 1423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Count = atoi(RestOfArgs[0].c_str()); 1443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Expected [count] value with N modifier"; 14857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Non-positive counts are not allowed 1503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count < 1) 1513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Invalid [count] value (not a positive integer)"; 1523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 15357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getArchive - Get the archive file name from the command line 1553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getArchive() { 1563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) { 1573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveName = RestOfArgs[0]; 1583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer RestOfArgs.erase(RestOfArgs.begin()); 1593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 1603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 1613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "An archive name must be specified."; 1623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 16357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 1643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// getMembers - Copy over remaining items in RestOfArgs to our Members vector 1653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// This is just for clarity. 1663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid getMembers() { 1673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if(RestOfArgs.size() > 0) 1683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Members = std::vector<std::string>(RestOfArgs); 1693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 17014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// parseCommandLine - Parse the command line options as presented and return the 1723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// operation specified. Process all modifiers and check to make sure that 1733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// constraints on modifier/operation pairs have not been violated. 1743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid SpencerArchiveOperation parseCommandLine() { 17514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of number of operations. We can only specify one 1773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // per execution. 1783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumOperations = 0; 17914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the number of positional modifiers (a,b,i). Only 1813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // one can be specified. 1823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned NumPositional = 0; 18314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of which operation was requested 1853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = NoOperation; 18614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 1873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for(unsigned i=0; i<Options.size(); ++i) { 1883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch(Options[i]) { 1893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'd': ++NumOperations; Operation = Delete; break; 1903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'm': ++NumOperations; Operation = Move ; break; 1913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'p': ++NumOperations; Operation = Print; break; 1923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'r': ++NumOperations; Operation = ReplaceOrInsert; break; 1933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 't': ++NumOperations; Operation = DisplayTable; break; 1943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'x': ++NumOperations; Operation = Extract; break; 1953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'c': Create = true; break; 1963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'f': TruncateNames = true; break; 1973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'k': DontSkipBytecode = true; break; 1983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'l': /* accepted but unused */ break; 1993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'o': OriginalDates = true; break; 2003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'P': FullPath = true; break; 2013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'R': RecurseDirectories = true; break; 2023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 's': SymTable = true; break; 2033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'S': SymTable = false; break; 2043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'u': OnlyUpdate = true; break; 2053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'v': Verbose = true; break; 2063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'V': Verbose = ReallyVerbose = true; break; 2073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'z': Compression = true; break; 2083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'a': 2093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddAfter = true; 2113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'b': 2143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer AddBefore = true; 2163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'i': 2193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getRelPos(); 2203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer InsertBefore = true; 2213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer NumPositional++; 2223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case 'N': 2243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getCount(); 2253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer UseCount = true; 2263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 2273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer default: 228bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 22914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 23114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // At this point, the next thing on the command line must be 2333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive name. 2343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getArchive(); 23514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Everything on the command line at this point is a member. 2373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer getMembers(); 23814baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform various checks on the operation/modifier specification 2403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to make sure we are dealing with a legal request. 2413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations == 0) 2423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You must specify at least one of the operations"; 2433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumOperations > 1) 2443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one operation may be specified"; 2453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (NumPositional > 1) 2463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "You may only specify one of a, b, and i modifiers"; 2473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter || AddBefore || InsertBefore) 2483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Operation != Move && Operation != ReplaceOrInsert) 2493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'a', 'b' and 'i' modifiers can only be specified with " 2503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer "the 'm' or 'r' operations"; 2513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories && Operation != ReplaceOrInsert) 2523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'R' modifiers is only applicabe to the 'r' operation"; 2533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates && Operation != Extract) 2543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'o' modifier is only applicable to the 'x' operation"; 2553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) 2563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; 2573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OnlyUpdate && Operation != ReplaceOrInsert) 2583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'u' modifier is only applicable to the 'r' operation"; 2593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) 2603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; 2613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Count > 1 && Members.size() > 1) 2623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw "Only one member name may be specified with the 'N' modifier"; 2633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 2643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return the parsed operation to the caller 2653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return Operation; 26614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 26714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// recurseDirectories - Implements the "R" modifier. This function scans through 2693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the Paths vector (built by buildPaths, below) and replaces any directories it 2703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// finds with all the files in that directory (recursively). It uses the 2713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// sys::Path::getDirectoryContent method to perform the actual directory scans. 272bede58363c647a4e73112fdfb409e9af7051301eReid Spencerstd::set<sys::Path> recurseDirectories(const sys::Path& path) { 2733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer assert(path.isDirectory() && "Oops, can't recurse a file"); 274bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> result; 2753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RecurseDirectories) { 276bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> content; 2773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer path.getDirectoryContents(content); 278bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (std::set<sys::Path>::iterator I = content.begin(), E = content.end(); 2793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I) { 2803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->isDirectory()) { 281bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> moreResults = recurseDirectories(*I); 282bede58363c647a4e73112fdfb409e9af7051301eReid Spencer result.insert(moreResults.begin(), moreResults.end()); 2833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 284bede58363c647a4e73112fdfb409e9af7051301eReid Spencer result.insert(*I); 2853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 2863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 28714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 2883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return result; 2893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 29014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 2913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// buildPaths - Convert the strings in the Members vector to sys::Path objects 2923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// and make sure they are valid and exist exist. This check is only needed for 2933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the operations that add/replace files to the archive ('q' and 'r') 2943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid buildPaths(bool checkExistence = true) { 2953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (unsigned i = 0; i < Members.size(); i++) { 2963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path aPath; 2973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!aPath.setFile(Members[i])) 2983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File member name invalid: ") + Members[i]; 2993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (checkExistence) { 3003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!aPath.exists()) 3013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("File does not exist: ") + Members[i]; 3023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path::StatusInfo si; 3033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer aPath.getStatusInfo(si); 3043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (si.isDir) { 305bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> dirpaths = recurseDirectories(aPath); 306bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(dirpaths.begin(),dirpaths.end()); 3073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 308bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 311bede58363c647a4e73112fdfb409e9af7051301eReid Spencer Paths.insert(aPath); 3123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 31314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 31414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 31514baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 316bede58363c647a4e73112fdfb409e9af7051301eReid Spencer// printSymbolTable - print out the archive's symbol table. 317bede58363c647a4e73112fdfb409e9af7051301eReid Spencervoid printSymbolTable() { 318bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::cout << "\nArchive Symbol Table:\n"; 319bede58363c647a4e73112fdfb409e9af7051301eReid Spencer const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); 320bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); 321bede58363c647a4e73112fdfb409e9af7051301eReid Spencer I != E; ++I ) { 322bede58363c647a4e73112fdfb409e9af7051301eReid Spencer unsigned offset = TheArchive->getFirstFileOffset() + I->second; 323bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::cout << " " << std::setw(9) << offset << "\t" << I->first <<"\n"; 324bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 325bede58363c647a4e73112fdfb409e9af7051301eReid Spencer} 326bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 3273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doPrint - Implements the 'p' operation. This function traverses the archive 3283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// looking for members that match the path list. It is careful to uncompress 3293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// things that should be and to skip bytecode files unless the 'k' modifier was 3303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// given. 3313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doPrint() { 3323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(false); 3333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 3343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 3353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 3363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty() || 3373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 3383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 3393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 3403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Skip things that don't make sense to print 3420fdd363a26b0c35d2e4b9b0e9831b14d79a549dcReid Spencer if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || 3430fdd363a26b0c35d2e4b9b0e9831b14d79a549dcReid Spencer I->isBSD4SymbolTable() || (!DontSkipBytecode && 3443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (I->isBytecode() || I->isCompressedBytecode()))) 3453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer continue; 3463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) 3483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "Printing " << I->getPath().get() << "\n"; 3493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 3503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->isCompressedBytecode()) 351b55bc06bad38162735f6e5ae2765be686fb47b2cReid Spencer Compressor::decompressToStream(data+4,I->getSize()-4,std::cout); 3523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else if (I->isCompressed()) { 353b55bc06bad38162735f6e5ae2765be686fb47b2cReid Spencer Compressor::decompressToStream(data,I->getSize(),std::cout); 3543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 3553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned len = I->getSize(); 3563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout.write(data, len); 3573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 3593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 3603a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 3613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 36214baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 3633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 36414baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// putMode - utility function for printing out the file mode when the 't' 3663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// operation is in verbose mode. 367bede58363c647a4e73112fdfb409e9af7051301eReid Spencervoid printMode(unsigned mode) { 3683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 004) 3693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "r"; 3703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 3713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "-"; 3723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 002) 3733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "w"; 3743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 3753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "-"; 3763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (mode & 001) 3773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "x"; 3783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 3793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "-"; 3803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 38114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 3823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDisplayTable - Implement the 't' operation. This function prints out just 3833a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the file names of each of the members. However, if verbose mode is requested 3843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// ('v' modifier) then the file type, permission mode, user, group, size, and 3853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// modification time are also printed. 3863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doDisplayTable() { 3873a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(false); 3883a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 3893a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 3903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty() || 3913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 3923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Verbose) { 3933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // FIXME: Output should be this format: 3943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile 3953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->isBytecode()) 3963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "b"; 3973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else if (I->isCompressedBytecode()) 3983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "B"; 3993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else if (I->isCompressed()) 4003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "Z"; 4013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else 4023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << " "; 4033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned mode = I->getMode(); 404bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 6) & 007); 405bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode((mode >> 3) & 007); 406bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printMode(mode & 007); 4073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << " " << std::setw(4) << I->getUser(); 4083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << "/" << std::setw(4) << I->getGroup(); 4093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << " " << std::setw(8) << I->getSize(); 4103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << " " << std::setw(20) << 411b55bc06bad38162735f6e5ae2765be686fb47b2cReid Spencer I->getModTime().toString().substr(4); 4123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << " " << I->getPath().get() << "\n"; 4133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 4143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cout << I->getPath().get() << "\n"; 4153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 41614baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 41714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner } 418bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 419bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 42014baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner} 42114baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 4223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doExtract - Implement the 'x' operation. This function extracts files back to 4233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// the file system, making sure to uncompress any that were compressed. 4243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doExtract() { 4253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(false); 4263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 4273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 4293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty() || 4303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { 4313a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure the intervening directories are created 4333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->hasPath()) { 4343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path dirs(I->getPath()); 4353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer dirs.elideFile(); 4363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer dirs.createDirectory(/*create_parents=*/true); 4373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Open up a file stream for writing 4403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::ofstream file(I->getPath().c_str()); 4413a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the data and its length 4433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer const char* data = reinterpret_cast<const char*>(I->getData()); 4443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned len = I->getSize(); 4453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Write the data, making sure to uncompress things first 4473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I->isCompressed()) { 448b55bc06bad38162735f6e5ae2765be686fb47b2cReid Spencer Compressor::decompressToStream(data,len,file); 4493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 4503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer file.write(data,len); 4513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer file.close(); 4533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we're supposed to retain the original modification times, etc. do so 4553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // now. 4563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (OriginalDates) 4573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I->getPath().setStatusInfo(I->getStatusInfo()); 4583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4593a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 46057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 46157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doDelete - Implement the delete operation. This function deletes zero or more 4633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// members from the archive. Note that if the count is specified, there should 4643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// be no more than one path in the Paths list or else this algorithm breaks. 4653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// That check is enforced in parseCommandLine (above). 4663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doDelete() { 4673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(false); 4683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty()) return; 4693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer unsigned countDown = Count; 4703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 4713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ) { 4723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { 4733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (countDown == 1) { 4743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator J = I; 4753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 476bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->erase(J); 4773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else 4783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer countDown--; 4793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 4803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ++I; 4813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 4823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 48357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 485bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->writeToDisk(SymTable,TruncateNames,Compression); 486bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 487bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 48857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 48957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 4903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doMore - Implement the move operation. This function re-arranges just the 4913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// order of the archive members so that when the archive is written the move 4923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// of the members is accomplished. Note the use of the RelPos variable to 4933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// determine where the items should be moved to. 4943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doMove() { 4953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(false); 4973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 4983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // By default and convention the place to move members to is the end of the 4993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // archive. 5003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator moveto_spot = TheArchive->end(); 5013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // However, if the relative positioning modifiers were used, we need to scan 5033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // the archive to find the member in question. If we don't find it, its no 5043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // crime, we just move to the end. 5053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddBefore || InsertBefore || AddAfter) { 5063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5073a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E; ++I ) { 5083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (RelPos == I->getPath().get()) { 5093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (AddAfter) { 5103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot++; 5123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 5133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer moveto_spot = I; 5143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 5163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 5173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 51857bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 51957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep a list of the paths remaining to be moved 521bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 5223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5233a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Scan the archive again, this time looking for the members to move to the 5243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // moveto_spot. 5253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); 5263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 527bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path>::iterator found = 5283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::find(remaining.begin(),remaining.end(),I->getPath()); 5293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 5303a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (I != moveto_spot) 531bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->splice(moveto_spot,*TheArchive,I); 5323a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 5333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 53457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 53557bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5363a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 537bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->writeToDisk(SymTable,TruncateNames,Compression); 538bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 539bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 54057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 54157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doQuickAppend - Implements the 'q' operation. This function just 5433a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// indiscriminantly adds the members to the archive and rebuilds it. 5443a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doQuickAppend() { 5453a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Get the list of paths to append. 5463a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(true); 5473a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty()) return; 5483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5493a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Append them quickly. 550bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); 5513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PI != PE; ++PI) { 5523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer TheArchive->addFileBefore(*PI,TheArchive->end()); 5533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 55457bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 556bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->writeToDisk(SymTable,TruncateNames,Compression); 557bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 558bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 55957bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 56057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 5613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// doReplaceOrInsert - Implements the 'r' operation. This function will replace 5623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// any existing files or insert new ones into the archive. 5633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencervoid doReplaceOrInsert() { 5643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Build the list of files to be added/replaced. 5663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer buildPaths(true); 5673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (Paths.empty()) return; 5683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Keep track of the paths that remain to be inserted. 570bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::set<sys::Path> remaining(Paths); 5713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Default the insertion spot to the end of the archive 5733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer Archive::iterator insert_spot = TheArchive->end(); 5743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Iterate over the archive contents 5763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); 5773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I != E && !remaining.empty(); ++I ) { 5783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 5793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this archive member matches one of the paths we're trying 5803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // to replace. 5810de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 5820de66b5cc8766102197c565a32bc7f9436b607daReid Spencer std::set<sys::Path>::iterator found = remaining.end(); 5830de66b5cc8766102197c565a32bc7f9436b607daReid Spencer for (std::set<sys::Path>::iterator RI = remaining.begin(), 5840de66b5cc8766102197c565a32bc7f9436b607daReid Spencer RE = remaining.end(); RI != RE; ++RI ) { 5850de66b5cc8766102197c565a32bc7f9436b607daReid Spencer std::string compare(RI->get()); 5860de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (TruncateNames && compare.length() > 15) { 5870de66b5cc8766102197c565a32bc7f9436b607daReid Spencer const char* nm = compare.c_str(); 5880de66b5cc8766102197c565a32bc7f9436b607daReid Spencer unsigned len = compare.length(); 5890de66b5cc8766102197c565a32bc7f9436b607daReid Spencer size_t slashpos = compare.rfind('/'); 5900de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (slashpos != std::string::npos) { 5910de66b5cc8766102197c565a32bc7f9436b607daReid Spencer nm += slashpos + 1; 5920de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len -= slashpos +1; 5930de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 5940de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (len > 15) 5950de66b5cc8766102197c565a32bc7f9436b607daReid Spencer len = 15; 5960de66b5cc8766102197c565a32bc7f9436b607daReid Spencer compare.assign(nm,len); 5970de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 5980de66b5cc8766102197c565a32bc7f9436b607daReid Spencer if (compare == I->getPath().get()) { 5990de66b5cc8766102197c565a32bc7f9436b607daReid Spencer found = RI; 6000de66b5cc8766102197c565a32bc7f9436b607daReid Spencer break; 6010de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6020de66b5cc8766102197c565a32bc7f9436b607daReid Spencer } 6030de66b5cc8766102197c565a32bc7f9436b607daReid Spencer 6043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (found != remaining.end()) { 605bede58363c647a4e73112fdfb409e9af7051301eReid Spencer sys::Path::StatusInfo si; 606bede58363c647a4e73112fdfb409e9af7051301eReid Spencer found->getStatusInfo(si); 607bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (si.isDir) { 608bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (OnlyUpdate) { 609bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item only if it is newer. 610bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (si.modTime > I->getModTime()) 611bede58363c647a4e73112fdfb409e9af7051301eReid Spencer I->replaceWith(*found); 612bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } else { 613bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Replace the item regardless of time stamp 6143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer I->replaceWith(*found); 615bede58363c647a4e73112fdfb409e9af7051301eReid Spencer } 6163a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 617bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // We purposefully ignore directories. 6183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Remove it from our "to do" list 6213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer remaining.erase(found); 6223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 62357bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6243a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Determine if this is the place where we should insert 6253a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if ((AddBefore || InsertBefore) && (RelPos == I->getPath().get())) 6263a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 6273a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer else if (AddAfter && (RelPos == I->getPath().get())) { 6283a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot = I; 6293a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer insert_spot++; 63057bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 63157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner } 63257bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6333a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // If we didn't replace all the members, some will remain and need to be 6343a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // inserted at the previously computed insert-spot. 6353a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!remaining.empty()) { 636bede58363c647a4e73112fdfb409e9af7051301eReid Spencer for (std::set<sys::Path>::iterator PI = remaining.begin(), 6373a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer PE = remaining.end(); PI != PE; ++PI) { 6383a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer TheArchive->addFileBefore(*PI,insert_spot); 6393a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 6403a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 64157bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner 6423a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // We're done editting, reconstruct the archive. 643bede58363c647a4e73112fdfb409e9af7051301eReid Spencer TheArchive->writeToDisk(SymTable,TruncateNames,Compression); 644bede58363c647a4e73112fdfb409e9af7051301eReid Spencer if (ReallyVerbose) 645bede58363c647a4e73112fdfb409e9af7051301eReid Spencer printSymbolTable(); 64657bd7966049f77d93ed937780bee8a6c4e260cefTanya Lattner} 64714baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 6483a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer// main - main program for llvm-ar .. see comments in the code 64914baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattnerint main(int argc, char **argv) { 6503a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6513a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Have the command line options parsed and handle things 6523a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // like --help and --version. 6533a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer cl::ParseCommandLineOptions(argc, argv, 6543a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer " LLVM Archiver (llvm-ar)\n\n" 6553a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer " This program archives bytecode files into single libraries\n" 6563a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ); 6573a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6583a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Print a stack trace if we signal out. 6599de7b334ec6f80a15f093f11b339f5741c964b34Reid Spencer sys::PrintStackTraceOnErrorSignal(); 660f73b4ca7f9c5e4a19c3fba9fa0280768b4c64891Chris Lattner 6613a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer int exitCode = 0; 6623a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6633a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we don't exit with "unhandled exception". 6643a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer try { 6653a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Do our own parsing of the command line because the CommandLine utility 6663a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // can't handle the grouped positional parameters without a dash. 6673a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer ArchiveOperation Operation = parseCommandLine(); 6683a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6693a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Check the path name of the archive 6703a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer sys::Path ArchivePath; 6713a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!ArchivePath.setFile(ArchiveName)) 6723a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer throw std::string("Archive name invalid: ") + ArchiveName; 6733a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 6743a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Create or open the archive object. 6753a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!ArchivePath.exists()) { 6763a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Produce a warning if we should and we're creating the archive 6773a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer if (!Create) 6783a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cerr << argv[0] << ": creating " << ArchivePath.get() << "\n"; 6793a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer TheArchive = Archive::CreateEmpty(ArchivePath); 6803a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } else { 6813a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer TheArchive = Archive::OpenAndLoad(ArchivePath); 6823a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 68314baebf4ee48b2c34b3a2eec972f89e1c8806263Tanya Lattner 6843a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Make sure we're not fooling ourselves. 6853a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer assert(TheArchive && "Unable to instantiate the archive"); 6863a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 687bede58363c647a4e73112fdfb409e9af7051301eReid Spencer // Make sure we clean up the archive even on failure. 688bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::auto_ptr<Archive> AutoArchive(TheArchive); 689bede58363c647a4e73112fdfb409e9af7051301eReid Spencer 6903a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Perform the operation 6913a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer switch (Operation) { 6923a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case Print: doPrint(); break; 6933a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case Delete: doDelete(); break; 6943a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case Move: doMove(); break; 6953a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case QuickAppend: /* FALL THROUGH */ 6963a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case ReplaceOrInsert: doReplaceOrInsert(); break; 6973a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case DisplayTable: doDisplayTable(); break; 6983a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case Extract: doExtract(); break; 6993a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer case NoOperation: 7003a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cerr << argv[0] << ": No operation was selected.\n"; 7013a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer break; 7023a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 7033a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const char*msg) { 7043a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are usage errors, thrown only by the various checks in the 7053a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // code above. 7063a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cerr << argv[0] << ": " << msg << "\n\n"; 707bede58363c647a4e73112fdfb409e9af7051301eReid Spencer cl::PrintHelpMessage(); 7083a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 1; 7093a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (const std::string& msg) { 7103a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // These errors are thrown by LLVM libraries (e.g. lib System) and represent 7113a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // a more serious error so we bump the exitCode and don't print the usage. 7123a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer std::cerr << argv[0] << ": " << msg << "\n"; 7133a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 2; 7143a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } catch (...) { 7153a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // This really shouldn't happen, but just in case .... 716bede58363c647a4e73112fdfb409e9af7051301eReid Spencer std::cerr << argv[0] << ": An unexpected unknown exception occurred.\n"; 7173a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer exitCode = 3; 7183a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer } 7193a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer 7203a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer // Return result code back to operating system. 7213a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer return exitCode; 7223a1582b5b2f497bf0b2bcdf30a3430025b063ec4Reid Spencer} 723