aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/llvm-ar/llvm-ar.cpp305
1 files changed, 247 insertions, 58 deletions
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index e9a4dbf..33c14b5 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -35,58 +35,68 @@ using std::cout;
#define ARFMAG "\n" /* header trailer string */
#define ARMAG "!<arch>\n" /* magic string */
#define SARMAG 8 /* length of magic string */
+#define VERSION "llvm-ar is a part of the LLVM compiler infrastructure.\nPlease see http://llvm.cs.uiuc.edu for more information.\n";
-namespace {
-
- // Each file member is preceded by a file member header. Which is
- // of the following format:
- //
- // char ar_name[16] - '/' terminated file member name.
- // If the file name does not fit, a dummy name is used.
- // char ar_date[12] - file date in decimal
- // char ar_uid[6] - User id of file owner in decimal.
- // char ar_gid[6] - Group ID file belongs to in decimal.
- // char ar_mode[8] - File mode in octal.
- // char ar_size[10] - Size of file in decimal.
- // char ar_fmag[2] - Trailer of header file, a newline.
- struct ar_hdr {
- char name[16];
- char date[12];
- char uid[6];
- char gid[6];
- char mode[8];
- char size[10];
- char fmag[2];
- void init() {
- memset(name,' ',16);
- memset(date,' ',12);
- memset(uid,' ',6);
- memset(gid,' ',6);
- memset(mode,' ',8);
- memset(size,' ',10);
- memset(fmag,' ',2);
+
+// Each file member is preceded by a file member header. Which is
+// of the following format:
+//
+// char ar_name[16] - '/' terminated file member name.
+// If the file name does not fit, a dummy name is used.
+// char ar_date[12] - file date in decimal
+// char ar_uid[6] - User id of file owner in decimal.
+// char ar_gid[6] - Group ID file belongs to in decimal.
+// char ar_mode[8] - File mode in octal.
+// char ar_size[10] - Size of file in decimal.
+// char ar_fmag[2] - Trailer of header file, a newline.
+struct ar_hdr {
+ char name[16];
+ char date[12];
+ char uid[6];
+ char gid[6];
+ char mode[8];
+ char size[10];
+ char fmag[2];
+ void init() {
+ memset(name,' ',16);
+ memset(date,' ',12);
+ memset(uid,' ',6);
+ memset(gid,' ',6);
+ memset(mode,' ',8);
+ memset(size,' ',10);
+ memset(fmag,' ',2);
}
- };
-}
+};
-//Option to generate symbol table or not
-//running llvm-ar -s is the same as ranlib
-cl::opt<bool> SymbolTableOption ("s", cl::desc("Generate an archive symbol table"));
-//Archive name
-cl::opt<string> Archive (cl::Positional, cl::desc("<archive file>"),
- cl::Required);
+//Option for X32_64, not used but must allow it to be present.
+cl::opt<bool> X32Option ("X32_64", cl::desc("Ignored option spelt -X32_64, for compatibility with AIX"), cl::Optional);
-//For now we require one or more member files, this should change so
-//we can just run llvm-ar -s on an archive to generate the symbol
-//table
-cl::list<string> Members(cl::ConsumeAfter, cl::desc("<archive members>..."));
+//llvm-ar options
+cl::opt<string> Options(cl::Positional, cl::desc("{dmpqrstx}[abcfilNoPsSuvV] "), cl::Required);
+//llvm-ar options
+cl::list<string> RestofArgs(cl::Positional, cl::desc("[relpos] [count]] <archive-file> [members..]"), cl::Optional);
-static inline bool Error(std::string *ErrorStr, const char *Message) {
- if (ErrorStr) *ErrorStr = Message;
- return true;
-}
+//booleans to represent Operation, only one can be preformed at a time
+bool Print, Delete, Move, QuickAppend, InsertWithReplacement, DisplayTable;
+bool Extract;
+
+//Modifiers to follow operation to vary behavior
+bool AddAfter, AddBefore, Create, TruncateNames, InsertBefore, UseCount;
+bool OriginalDates, FullPath, SymTable, OnlyUpdate, Verbose;
+
+//Realtive Pos Arg
+string RelPos;
+
+//Count, use for multiple entries in the archive with the same name
+int Count;
+
+//Archive
+string Archive;
+
+//Member Files
+vector<string> Members;
// WriteSymbolTable - Writes symbol table to ArchiveFile, return false
@@ -248,13 +258,15 @@ bool WriteSymbolTable(std::ofstream &ArchiveFile) {
// 4) Keep track of total offset into file, and insert a newline if it is odd.
//
bool AddMemberToArchive(string Member, std::ofstream &ArchiveFile) {
-
+
+ cout << "Member File Start: " << ArchiveFile.tellp() << "\n";
+
ar_hdr Hdr; //Header for archive member file.
-
+
//stat the file to get info
struct stat StatBuf;
if (stat(Member.c_str(), &StatBuf) == -1 || StatBuf.st_size == 0)
- cout << "ERROR\n";
+ return false;
//fill in header
@@ -312,9 +324,11 @@ bool AddMemberToArchive(string Member, std::ofstream &ArchiveFile) {
//write to archive file
ArchiveFile.write((char*)buf,Length);
-
+
// Unmmap the memberfile
munmap((char*)buf, Length);
+
+ cout << "Member File End: " << ArchiveFile.tellp() << "\n";
return true;
}
@@ -324,6 +338,8 @@ bool AddMemberToArchive(string Member, std::ofstream &ArchiveFile) {
//
void CreateArchive() {
+ std::cerr << "Archive File: " << Archive << "\n";
+
//Create archive file for output.
std::ofstream ArchiveFile(Archive.c_str());
@@ -337,7 +353,7 @@ void CreateArchive() {
ArchiveFile << ARMAG;
//If the '-s' option was specified, generate symbol table.
- if(SymbolTableOption) {
+ if(SymTable) {
cout << "Symbol Table Start: " << ArchiveFile.tellp() << "\n";
if(!WriteSymbolTable(ArchiveFile)) {
std::cerr << "Error creating symbol table. Exiting program.";
@@ -346,31 +362,204 @@ void CreateArchive() {
cout << "Symbol Table End: " << ArchiveFile.tellp() << "\n";
}
//Loop over all member files, and add to the archive.
- for(unsigned i=0; i<Members.size(); ++i) {
+ for(unsigned i=0; i < Members.size(); ++i) {
if(ArchiveFile.tellp() % 2 != 0)
ArchiveFile << ARFMAG;
-
- cout << "Member File Start: " << ArchiveFile.tellp() << "\n";
-
if(AddMemberToArchive(Members[i],ArchiveFile) != true) {
- std::cerr << "Error adding file to archive. Exiting program.";
+ std::cerr << "Error adding " << Members[i] << "to archive. Exiting program.\n";
exit(1);
}
- cout << "Member File End: " << ArchiveFile.tellp() << "\n";
}
//Close archive file.
ArchiveFile.close();
}
+//Print out usage for errors in command line
+void printUse() {
+ std::cout << "USAGE: ar [-X32_64] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file [files..]\n\n";
+
+ std::cout << "commands:\n" <<
+ "d - delete file(s) from the archive\n"
+ << "m[ab] - move file(s) in the archive\n"
+ << "p - print file(s) found in the archive\n"
+ << "q[f] - quick append file(s) to the archive\n"
+ << "r[ab][f][u] - replace existing or insert new file(s) into the archive\n"
+ << "t - display contents of archive\n"
+ << "x[o] - extract file(s) from the archive\n";
+
+ std::cout << "\ncommand specific modifiers:\n"
+ << "[a] - put file(s) after [member-name]\n"
+ << "[b] - put file(s) before [member-name] (same as [i])\n"
+ << "[N] - use instance [count] of name\n"
+ << "[f] - truncate inserted file names\n"
+ << "[P] - use full path names when matching\n"
+ << "[o] - preserve original dates\n"
+ << "[u] - only replace files that are newer than current archive contents\n";
+
+ std::cout << "generic modifiers:\n"
+ << "[c] - do not warn if the library had to be created\n"
+ << "[s] - create an archive index (cf. ranlib)\n"
+ << "[S] - do not build a symbol table\n"
+ << "[v] - be verbose\n"
+ << "[V] - display the version number\n";
+ exit(1);
+}
+
+
+//Print version
+void printVersion() {
+ cout << VERSION;
+ exit(0);
+}
+
+//Extract the memberfile name from the command line
+void getRelPos() {
+ if(RestofArgs.size() > 0) {
+ RelPos = RestofArgs[0];
+ RestofArgs.erase(RestofArgs.begin());
+ }
+ //Throw error if needed and not present
+ else
+ printUse();
+}
+
+//Extract count from the command line
+void getCount() {
+ if(RestofArgs.size() > 0) {
+ Count = atoi(RestofArgs[0].c_str());
+ RestofArgs.erase(RestofArgs.begin());
+ }
+ //Throw error if needed and not present
+ else
+ printUse();
+}
+
+//Get the Archive File Name from the command line
+void getArchive() {
+ std::cerr << RestofArgs.size() << "\n";
+ if(RestofArgs.size() > 0) {
+ Archive = RestofArgs[0];
+ RestofArgs.erase(RestofArgs.begin());
+ }
+ //Throw error if needed and not present
+ else
+ printUse();
+}
+
+
+//Copy over remaining items in RestofArgs to our Member File vector.
+//This is just for clarity.
+void getMembers() {
+ std::cerr << RestofArgs.size() << "\n";
+ if(RestofArgs.size() > 0)
+ Members = vector<string>(RestofArgs);
+}
+
+// Parse the operations and operation modifiers
+// FIXME: Not all of these options has been implemented, but we still
+// do all the command line parsing for them.
+void parseCL() {
+
+ //Keep track of number of operations. We can only specify one
+ //per execution
+ unsigned NumOperations = 0;
+
+ for(unsigned i=0; i<Options.size(); ++i) {
+ switch(Options[i]) {
+ case 'd':
+ ++NumOperations;
+ Delete = true;
+ break;
+ case 'm':
+ ++NumOperations;
+ Move = true;
+ break;
+ case 'p':
+ ++NumOperations;
+ Print = true;
+ break;
+ case 'r':
+ ++NumOperations;
+ InsertWithReplacement = true;
+ break;
+ case 't':
+ ++NumOperations;
+ DisplayTable = true;
+ break;
+ case 'x':
+ ++NumOperations;
+ Extract = true;
+ break;
+ case 'a':
+ AddAfter = true;
+ getRelPos();
+ break;
+ case 'b':
+ AddBefore = true;
+ getRelPos();
+ break;
+ case 'c':
+ Create = true;
+ break;
+ case 'f':
+ TruncateNames = true;
+ break;
+ case 'i':
+ InsertBefore = true;
+ getRelPos();
+ break;
+ case 'l':
+ break;
+ case 'N':
+ UseCount = true;
+ getCount();
+ break;
+ case 'o':
+ OriginalDates = true;
+ break;
+ case 'P':
+ FullPath = true;
+ break;
+ case 's':
+ SymTable = true;
+ break;
+ case 'S':
+ SymTable = false;
+ break;
+ case 'u':
+ OnlyUpdate = true;
+ break;
+ case 'v':
+ Verbose = true;
+ break;
+ case 'V':
+ printVersion();
+ break;
+ default:
+ printUse();
+ }
+ }
+
+ //Check that only one operation has been specified
+ if(NumOperations > 1)
+ printUse();
+
+ getArchive();
+ getMembers();
+
+}
int main(int argc, char **argv) {
//Parse Command line options
- cl::ParseCommandLineOptions(argc, argv, " llvm-ar\n");
+ cl::ParseCommandLineOptions(argc, argv);
+ parseCL();
//Create archive!
- CreateArchive();
+ if(Create)
+ CreateArchive();
return 0;
}
+