summaryrefslogtreecommitdiffstats
path: root/tools/gccld/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gccld/util.cpp')
-rw-r--r--tools/gccld/util.cpp287
1 files changed, 287 insertions, 0 deletions
diff --git a/tools/gccld/util.cpp b/tools/gccld/util.cpp
new file mode 100644
index 0000000..d51a8a9
--- /dev/null
+++ b/tools/gccld/util.cpp
@@ -0,0 +1,287 @@
+//===- util.cpp - Utility functions ---------------------------------------===//
+//
+// This file contains utility functions for gccld. It essentially holds
+// anything from the original gccld.cpp source that was either incidental
+// or not inlined.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "Config/string.h"
+
+#include <fstream>
+#include <string>
+#include <set>
+
+//
+// Function: PrintAndReturn ()
+//
+// Description:
+// Prints a message (usually error message) to standard error (stderr) and
+// returns a value usable for an exit status.
+//
+// Inputs:
+// progname - The name of the program (i.e. argv[0]).
+// Message - The message to print to standard error.
+// Extra - Extra information to print between the program name and thei
+// message. It is optional.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// Returns a value that can be used as the exit status (i.e. for exit()).
+//
+int
+PrintAndReturn (const char *progname,
+ const std::string &Message,
+ const std::string &Extra = "")
+{
+ std::cerr << progname << Extra << ": " << Message << "\n";
+ return 1;
+}
+
+//
+// Function: IsArchive ()
+//
+// Description:
+// Determine if the specified file is an ar archive. It determines this by
+// checking the magic string at the beginning of the file.
+//
+// Inputs:
+// filename - A C++ string containing the name of the file.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// TRUE - The file is an archive.
+// FALSE - The file is not an archive.
+//
+bool
+IsArchive (const std::string &filename)
+{
+ std::string ArchiveMagic("!<arch>\012");
+ char buf[1 + ArchiveMagic.size()];
+
+ std::ifstream f(filename.c_str());
+ f.read(buf, ArchiveMagic.size());
+ buf[ArchiveMagic.size()] = '\0';
+ return ArchiveMagic == buf;
+}
+
+//
+// Function: GetAllDefinedSymbols ()
+//
+// Description:
+// Find all of the defined symbols in the specified module.
+//
+// Inputs:
+// M - The module in which to find defined symbols.
+//
+// Outputs:
+// DefinedSymbols - A set of C++ strings that will contain the name of all
+// defined symbols.
+//
+// Return value:
+// None.
+//
+void
+GetAllDefinedSymbols (Module *M, std::set<std::string> &DefinedSymbols)
+{
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
+ DefinedSymbols.insert(I->getName());
+ for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
+ if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
+ DefinedSymbols.insert(I->getName());
+}
+
+//
+// Function: GetAllUndefinedSymbols ()
+//
+// Description:
+// This calculates the set of undefined symbols that still exist in an LLVM
+// module. This is a bit tricky because there may be two symbols with the
+// same name but different LLVM types that will be resolved to each other but
+// aren't currently (thus we need to treat it as resolved).
+//
+// Inputs:
+// M - The module in which to find undefined symbols.
+//
+// Outputs:
+// UndefinedSymbols - A set of C++ strings containing the name of all
+// undefined symbols.
+//
+// Return value:
+// None.
+//
+void
+GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols)
+{
+ std::set<std::string> DefinedSymbols;
+ UndefinedSymbols.clear(); // Start out empty
+
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (I->hasName()) {
+ if (I->isExternal())
+ UndefinedSymbols.insert(I->getName());
+ else if (!I->hasInternalLinkage())
+ DefinedSymbols.insert(I->getName());
+ }
+ for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
+ if (I->hasName()) {
+ if (I->isExternal())
+ UndefinedSymbols.insert(I->getName());
+ else if (!I->hasInternalLinkage())
+ DefinedSymbols.insert(I->getName());
+ }
+
+ // Prune out any defined symbols from the undefined symbols set...
+ for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
+ I != UndefinedSymbols.end(); )
+ if (DefinedSymbols.count(*I))
+ UndefinedSymbols.erase(I++); // This symbol really is defined!
+ else
+ ++I; // Keep this symbol in the undefined symbols list
+}
+
+//
+//
+// Function: copy_env()
+//
+// Description:
+// This function takes an array of environment variables and makes a
+// copy of it. This copy can then be manipulated any way the caller likes
+// without affecting the process's real environment.
+//
+// Inputs:
+// envp - An array of C strings containing an environment.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// NULL - An error occurred.
+//
+// Otherwise, a pointer to a new array of C strings is returned. Every string
+// in the array is a duplicate of the one in the original array (i.e. we do
+// not copy the char *'s from one array to another).
+//
+char **
+copy_env (char ** const envp)
+{
+ // The new environment list
+ char ** newenv;
+
+ // The number of entries in the old environment list
+ int entries;
+
+ //
+ // Count the number of entries in the old list;
+ //
+ for (entries = 0; envp[entries] != NULL; entries++)
+ {
+ ;
+ }
+
+ //
+ // Add one more entry for the NULL pointer that ends the list.
+ //
+ ++entries;
+
+ //
+ // If there are no entries at all, just return NULL.
+ //
+ if (entries == 0)
+ {
+ return NULL;
+ }
+
+ //
+ // Allocate a new environment list.
+ //
+ if ((newenv = new (char *) [entries]) == NULL)
+ {
+ return NULL;
+ }
+
+ //
+ // Make a copy of the list. Don't forget the NULL that ends the list.
+ //
+ entries = 0;
+ while (envp[entries] != NULL)
+ {
+ newenv[entries] = new char[strlen (envp[entries]) + 1];
+ strcpy (newenv[entries], envp[entries]);
+ ++entries;
+ }
+ newenv[entries] = NULL;
+
+ return newenv;
+}
+
+
+//
+// Function: remove_env()
+//
+// Description:
+// Remove the specified environment variable from the environment array.
+//
+// Inputs:
+// name - The name of the variable to remove. It cannot be NULL.
+// envp - The array of environment variables. It cannot be NULL.
+//
+// Outputs:
+// envp - The pointer to the specified variable name is removed.
+//
+// Return value:
+// None.
+//
+// Notes:
+// This is mainly done because functions to remove items from the environment
+// are not available across all platforms. In particular, Solaris does not
+// seem to have an unsetenv() function or a setenv() function (or they are
+// undocumented if they do exist).
+//
+void
+remove_env (const char * name, char ** const envp)
+{
+ // Pointer for scanning arrays
+ register char * p;
+
+ // Index for selecting elements of the environment array
+ register int index;
+
+ for (index=0; envp[index] != NULL; index++)
+ {
+ //
+ // Find the first equals sign in the array and make it an EOS character.
+ //
+ p = strchr (envp[index], '=');
+ if (p == NULL)
+ {
+ continue;
+ }
+ else
+ {
+ *p = '\0';
+ }
+
+ //
+ // Compare the two strings. If they are equal, zap this string.
+ // Otherwise, restore it.
+ //
+ if (!strcmp (name, envp[index]))
+ {
+ *envp[index] = '\0';
+ }
+ else
+ {
+ *p = '=';
+ }
+ }
+
+ return;
+}
+