opnsense-src/lib/Frontend/DocumentXML.cpp

339 lines
10 KiB
C++
Raw Normal View History

2009-06-02 13:58:47 -04:00
//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
2009-10-14 14:03:49 -04:00
// This file implements the XML document class, which provides the means to
2009-06-02 13:58:47 -04:00
// dump out the AST in a XML form that exposes type details and other fields.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
2009-06-22 04:08:35 -04:00
#include "clang/AST/ASTContext.h"
2009-06-02 13:58:47 -04:00
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
namespace clang {
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
Out(out),
Ctx(0),
2009-10-14 14:03:49 -04:00
HasCurrentNodeSubNodes(false) {
2009-06-22 04:08:35 -04:00
NodeStack.push(rootName);
2009-06-02 13:58:47 -04:00
Out << "<?xml version=\"1.0\"?>\n<" << rootName;
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
DocumentXML& DocumentXML::addSubNode(const std::string& name) {
2009-06-02 13:58:47 -04:00
if (!HasCurrentNodeSubNodes)
Out << ">\n";
2009-06-22 04:08:35 -04:00
NodeStack.push(name);
2009-06-02 13:58:47 -04:00
HasCurrentNodeSubNodes = false;
Indent();
2009-06-22 04:08:35 -04:00
Out << "<" << NodeStack.top();
2009-06-02 13:58:47 -04:00
return *this;
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
void DocumentXML::Indent() {
2009-06-22 04:08:35 -04:00
for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
2009-06-02 13:58:47 -04:00
Out << ' ';
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
DocumentXML& DocumentXML::toParent() {
assert(NodeStack.size() > 1 && "too much backtracking");
2009-06-02 13:58:47 -04:00
2009-10-14 14:03:49 -04:00
if (HasCurrentNodeSubNodes) {
2009-06-02 13:58:47 -04:00
Indent();
2009-06-22 04:08:35 -04:00
Out << "</" << NodeStack.top() << ">\n";
2009-10-14 14:03:49 -04:00
} else
2009-06-02 13:58:47 -04:00
Out << "/>\n";
2009-06-22 04:08:35 -04:00
NodeStack.pop();
2009-06-02 13:58:47 -04:00
HasCurrentNodeSubNodes = true;
2009-10-14 14:03:49 -04:00
return *this;
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
namespace {
2009-06-22 04:08:35 -04:00
enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
2009-06-02 13:58:47 -04:00
2009-10-14 14:03:49 -04:00
unsigned getNewId(tIdType idType) {
2009-06-02 13:58:47 -04:00
static unsigned int idCounts[ID_LAST] = { 0 };
return ++idCounts[idType];
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
inline std::string getPrefixedId(unsigned uId, tIdType idType) {
2009-06-22 04:08:35 -04:00
static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
2009-06-02 13:58:47 -04:00
char buffer[20];
char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
*--BufPtr = idPrefix[idType];
return BufPtr;
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
template<class T, class V>
2009-10-14 14:03:49 -04:00
bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) {
2009-06-02 13:58:47 -04:00
typename T::iterator i = idMap.find(value);
bool toAdd = i == idMap.end();
2009-10-14 14:03:49 -04:00
if (toAdd)
2009-06-02 13:58:47 -04:00
idMap.insert(typename T::value_type(value, getNewId(idType)));
return toAdd;
}
} // anon NS
2009-06-22 04:08:35 -04:00
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
std::string DocumentXML::escapeString(const char* pStr,
std::string::size_type len) {
2009-06-02 13:58:47 -04:00
std::string value;
value.reserve(len + 1);
char buffer[16];
for (unsigned i = 0; i < len; ++i) {
switch (char C = pStr[i]) {
default:
if (isprint(C))
value += C;
2009-10-14 14:03:49 -04:00
else {
2009-06-02 13:58:47 -04:00
sprintf(buffer, "\\%03o", C);
value += buffer;
}
break;
case '\n': value += "\\n"; break;
case '\t': value += "\\t"; break;
case '\a': value += "\\a"; break;
case '\b': value += "\\b"; break;
case '\r': value += "\\r"; break;
case '&': value += "&amp;"; break;
case '<': value += "&lt;"; break;
case '>': value += "&gt;"; break;
case '"': value += "&quot;"; break;
case '\'': value += "&apos;"; break;
}
}
return value;
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
void DocumentXML::finalize() {
2009-06-22 04:08:35 -04:00
assert(NodeStack.size() == 1 && "not completely backtracked");
2009-06-02 13:58:47 -04:00
addSubNode("ReferenceSection");
addSubNode("Types");
2009-10-14 14:03:49 -04:00
for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
i != e; ++i) {
2009-11-18 09:59:57 -05:00
if (i->first.hasLocalQualifiers()) {
2009-06-22 04:08:35 -04:00
writeTypeToXML(i->first);
2009-06-02 13:58:47 -04:00
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
}
2009-10-14 14:03:49 -04:00
for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(),
e = BasicTypes.end(); i != e; ++i) {
2009-06-22 04:08:35 -04:00
writeTypeToXML(i->first);
2009-06-02 13:58:47 -04:00
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
toParent().addSubNode("Contexts");
2009-10-14 14:03:49 -04:00
for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(),
e = Contexts.end(); i != e; ++i) {
2009-06-02 13:58:47 -04:00
addSubNode(i->first->getDeclKindName());
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
2009-10-14 14:03:49 -04:00
if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first))
2009-06-02 13:58:47 -04:00
addAttribute("name", ND->getNameAsString());
2009-10-14 14:03:49 -04:00
if (const TagDecl *TD = dyn_cast<TagDecl>(i->first))
2009-06-02 13:58:47 -04:00
addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL));
2009-10-14 14:03:49 -04:00
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first))
addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL));
2009-06-02 13:58:47 -04:00
if (const DeclContext* parent = i->first->getParent())
2009-06-22 04:08:35 -04:00
addAttribute("context", parent);
2009-06-02 13:58:47 -04:00
toParent();
}
toParent().addSubNode("Files");
2009-10-14 14:03:49 -04:00
for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(),
e = SourceFiles.end(); i != e; ++i) {
2009-06-02 13:58:47 -04:00
addSubNode("File");
addAttribute("id", getPrefixedId(i->second, ID_FILE));
addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
toParent();
}
toParent().toParent();
2009-10-14 14:03:49 -04:00
2009-06-02 13:58:47 -04:00
// write the root closing node (which has always subnodes)
2009-06-22 04:08:35 -04:00
Out << "</" << NodeStack.top() << ">\n";
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
void DocumentXML::addAttribute(const char* pAttributeName,
const QualType& pType) {
2009-06-02 13:58:47 -04:00
addTypeRecursively(pType);
2009-06-22 04:08:35 -04:00
addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
void DocumentXML::addPtrAttribute(const char* pAttributeName,
const Type* pType) {
2009-06-22 04:08:35 -04:00
addTypeRecursively(pType);
addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
void DocumentXML::addTypeRecursively(const QualType& pType)
{
if (addToMap(Types, pType))
{
2009-06-22 04:08:35 -04:00
addTypeRecursively(pType.getTypePtr());
2009-06-02 13:58:47 -04:00
// beautifier: a non-qualified type shall be transparent
2009-11-18 09:59:57 -05:00
if (!pType.hasLocalQualifiers())
2009-06-02 13:58:47 -04:00
{
2009-10-14 14:03:49 -04:00
Types[pType] = BasicTypes[pType.getTypePtr()];
2009-06-02 13:58:47 -04:00
}
}
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-22 04:08:35 -04:00
void DocumentXML::addTypeRecursively(const Type* pType)
2009-06-02 13:58:47 -04:00
{
if (addToMap(BasicTypes, pType))
{
2009-06-22 04:08:35 -04:00
addParentTypes(pType);
/*
// FIXME: doesn't work in the immediate streaming approach
2009-10-14 14:03:49 -04:00
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
2009-06-22 04:08:35 -04:00
{
addSubNode("VariableArraySizeExpression");
PrintStmt(VAT->getSizeExpr());
toParent();
2009-06-02 13:58:47 -04:00
}
2009-06-22 04:08:35 -04:00
*/
2009-06-02 13:58:47 -04:00
}
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-22 04:08:35 -04:00
void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
2009-06-02 13:58:47 -04:00
{
addContextsRecursively(DC);
2009-06-22 04:08:35 -04:00
addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-22 04:08:35 -04:00
void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
{
if (const DeclContext* DC = dyn_cast<DeclContext>(D))
{
addContextsRecursively(DC);
addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
}
else
{
addToMap(Decls, D);
addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
}
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-22 04:08:35 -04:00
void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
{
addPtrAttribute(pName, static_cast<const DeclContext*>(D));
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
void DocumentXML::addContextsRecursively(const DeclContext *DC)
{
if (DC != 0 && addToMap(Contexts, DC))
{
addContextsRecursively(DC->getParent());
2009-10-14 14:03:49 -04:00
}
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
void DocumentXML::addSourceFileAttribute(const std::string& fileName)
{
addToMap(SourceFiles, fileName, ID_FILE);
addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
}
2009-06-22 04:08:35 -04:00
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-22 04:08:35 -04:00
void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
{
addToMap(Labels, L, ID_LABEL);
addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
{
SourceManager& SM = Ctx->getSourceManager();
SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
PresumedLoc PLoc;
2009-10-14 14:03:49 -04:00
if (!SpellingLoc.isInvalid())
2009-06-02 13:58:47 -04:00
{
PLoc = SM.getPresumedLoc(SpellingLoc);
addSourceFileAttribute(PLoc.getFilename());
addAttribute("line", PLoc.getLine());
addAttribute("col", PLoc.getColumn());
}
// else there is no error in some cases (eg. CXXThisExpr)
return PLoc;
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
void DocumentXML::addLocationRange(const SourceRange& R)
{
PresumedLoc PStartLoc = addLocation(R.getBegin());
2009-10-14 14:03:49 -04:00
if (R.getBegin() != R.getEnd())
2009-06-02 13:58:47 -04:00
{
SourceManager& SM = Ctx->getSourceManager();
SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd());
2009-10-14 14:03:49 -04:00
if (!SpellingLoc.isInvalid())
2009-06-02 13:58:47 -04:00
{
PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc);
2009-10-14 14:03:49 -04:00
if (PStartLoc.isInvalid() ||
2009-06-02 13:58:47 -04:00
strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) {
addToMap(SourceFiles, PLoc.getFilename(), ID_FILE);
addAttribute("endfile", PLoc.getFilename());
addAttribute("endline", PLoc.getLine());
addAttribute("endcol", PLoc.getColumn());
} else if (PLoc.getLine() != PStartLoc.getLine()) {
addAttribute("endline", PLoc.getLine());
addAttribute("endcol", PLoc.getColumn());
} else {
addAttribute("endcol", PLoc.getColumn());
2009-10-14 14:03:49 -04:00
}
2009-06-02 13:58:47 -04:00
}
}
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
void DocumentXML::PrintDecl(Decl *D)
{
2009-06-22 04:08:35 -04:00
writeDeclToXML(D);
2009-06-02 13:58:47 -04:00
}
2009-10-14 14:03:49 -04:00
//---------------------------------------------------------
2009-06-02 13:58:47 -04:00
} // NS clang