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