diff options
Diffstat (limited to 'tools/gccld/util.cpp')
-rw-r--r-- | tools/gccld/util.cpp | 287 |
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; +} + |