diff --git a/support/lib/Support/StringExtras.cpp b/support/lib/Support/StringExtras.cpp new file mode 100644 index 00000000000..2229df049ac --- /dev/null +++ b/support/lib/Support/StringExtras.cpp @@ -0,0 +1,66 @@ + + +#include "llvm/Support/StringExtras.h" +#include "llvm/ConstPoolVals.h" +#include "llvm/DerivedTypes.h" + +// Can we treat the specified array as a string? Only if it is an array of +// ubytes or non-negative sbytes. +// +bool isStringCompatible(ConstPoolArray *CPA) { + const Type *ETy = cast(CPA->getType())->getElementType(); + if (ETy == Type::UByteTy) return true; + if (ETy != Type::SByteTy) return false; + + for (unsigned i = 0; i < CPA->getNumOperands(); ++i) + if (cast(CPA->getOperand(i))->getValue() < 0) + return false; + + return true; +} + +// toOctal - Convert the low order bits of X into an octal letter +static inline char toOctal(int X) { + return (X&7)+'0'; +} + +// getAsCString - Return the specified array as a C compatible string, only if +// the predicate isStringCompatible is true. +// +string getAsCString(ConstPoolArray *CPA) { + if (isStringCompatible(CPA)) { + string Result; + const Type *ETy = cast(CPA->getType())->getElementType(); + Result = "\""; + for (unsigned i = 0; i < CPA->getNumOperands(); ++i) { + unsigned char C = (ETy == Type::SByteTy) ? + (unsigned char)cast(CPA->getOperand(i))->getValue() : + (unsigned char)cast(CPA->getOperand(i))->getValue(); + + if (isprint(C)) { + Result += C; + } else { + switch(C) { + case '\a': Result += "\\a"; break; + case '\b': Result += "\\b"; break; + case '\f': Result += "\\f"; break; + case '\n': Result += "\\n"; break; + case '\r': Result += "\\r"; break; + case '\t': Result += "\\t"; break; + case '\v': Result += "\\v"; break; + default: + Result += '\\'; + Result += toOctal(C >> 6); + Result += toOctal(C >> 3); + Result += toOctal(C >> 0); + break; + } + } + } + Result += "\""; + + return Result; + } else { + return CPA->getStrValue(); + } +}