Synopsis - Cross-Reference
File: src/Synopsis/PTree/Display.cc1// 2// Copyright (C) 2004 Stefan Seefeld 3// All rights reserved. 4// Licensed to the public under the terms of the GNU LGPL (>= 2), 5// see the file COPYING for details. 6// 7 8#include <Synopsis/PTree/Display.hh> 9#include <typeinfo> 10#include <memory> 11#include <cstdlib> 12#if defined(__GNUC__) && __GNUC__ >= 3 13# include <cxxabi.h> 14 15# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 16namespace abi 17{ 18 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*); 19} 20# endif 21#endif 22 23namespace 24{ 25 26struct free_mem 27{ 28 free_mem(char *p) : p(p) {} 29 ~free_mem() { std::free(p);} 30 char * p; 31}; 32 33std::string demangle(char const *mangled) 34{ 35#if defined(__GNUC__) && __GNUC__ >= 3 36 std::string demangled; 37 int status; 38 free_mem keeper(abi::__cxa_demangle(mangled, 0, 0, &status)); 39 assert(status != -3); // invalid argument error 40 if (status == -1) { throw std::bad_alloc();} 41 else 42 // On failure return the mangled name. 43 demangled = status == -2 ? mangled : keeper.p; 44 return demangled.substr(17); // skip 'Synopsis::PTree::' prefix 45#else 46 return mangled; 47#endif 48} 49} 50 51using namespace Synopsis; 52using namespace PTree; 53 54Display::Display(std::ostream &os, bool encoded) 55 : my_os(os), 56 my_indent(0), 57 my_encoded(encoded) 58{ 59} 60 61void Display::display(Node const *n) 62{ 63 if (n) const_cast<Node *>(n)->accept(this); 64 else my_os << "nil"; 65 my_os.put('\n'); 66} 67 68void Display::visit(Atom *a) 69{ 70 char const *p = a->position(); 71 size_t n = a->length(); 72 73 // Recall that [, ], and @ are special characters. 74 75 if(n < 1) return; 76 else if(n == 1 && *p == '@') 77 { 78 my_os << "\\@"; 79 return; 80 } 81 82 char c = *p++; 83 if(c == '[' || c == ']') my_os << '\\' << c; // [ and ] at the beginning are escaped. 84 else my_os << c; 85 while(--n > 0) my_os << *p++; 86} 87 88void Display::visit(List *l) 89{ 90 Node *rest = l; 91 my_os << '['; 92 while(rest != 0) 93 { 94 if(rest->is_atom()) 95 { 96 my_os << "@ "; 97 rest->accept(this); 98 rest = 0; 99 } 100 else 101 { 102 Node *head = rest->car(); 103 if(head == 0) my_os << "nil"; 104 else 105 { 106 head->accept(this); 107 } 108 rest = rest->cdr(); 109 if(rest != 0) my_os << ' '; 110 } 111 } 112 my_os << ']'; 113} 114 115void Display::visit(DupAtom *a) 116{ 117 char const *pos = a->position(); 118 size_t length = a->length(); 119 120 if(length == 1 && *pos == '@') 121 { 122 my_os << "\\@"; 123 return; 124 } 125 126 my_os << '`'; 127 for(size_t i = 0; i < length; ++i) 128 if(pos[i] == '[' || pos[i] == ']') my_os << '\\' << pos[i]; 129 else my_os << pos[i]; 130 my_os << '`'; 131} 132 133void Display::visit(Brace *l) 134{ 135 ++my_indent; 136 my_os << "[{"; 137 Node *body = second(l); 138 if(!body) 139 { 140 newline(); 141 my_os << "nil"; 142 } 143 else 144 while(body) 145 { 146 newline(); 147 if(body->is_atom()) 148 { 149 my_os << "@ "; 150 body->accept(this); 151 } 152 else 153 { 154 Node *head = body->car(); 155 if(!head) my_os << "nil"; 156 else 157 { 158 head->accept(this); 159 } 160 } 161 body = body->cdr(); 162 } 163 --my_indent; 164 newline(); 165 my_os << "}]"; 166} 167 168void Display::newline() 169{ 170 my_os.put('\n'); 171 for(size_t i = 0; i != my_indent; ++i) my_os.put(' '); 172} 173 174void Display::print_encoded(List *l) 175{ 176 if (my_encoded) 177 { 178 Encoding const &type = l->encoded_type(); 179 if(!type.empty()) my_os << '#' << type; 180 Encoding const &name = l->encoded_name(); 181 if(!name.empty()) my_os << '@' << name; 182 } 183 visit(static_cast<List *>(l)); 184} 185 186RTTIDisplay::RTTIDisplay(std::ostream &os, bool encoded) 187 : my_os(os), 188 my_indent(0), 189 my_encoded(encoded) 190{ 191} 192 193void RTTIDisplay::display(Node const *n) 194{ 195 if (n) const_cast<Node *>(n)->accept(this); 196 else my_os << "nil"; 197 my_os.put('\n'); 198} 199 200void RTTIDisplay::visit(Atom *a) 201{ 202 newline(); 203 my_os << demangle(typeid(*a).name()) << ": "; 204 char const *p = a->position(); 205 size_t n = a->length(); 206 207 if(n < 1) return; 208 else if(n == 1 && *p == '@') 209 { 210 my_os << "\\@"; 211 return; 212 } 213 214 my_os << *p++; 215 while(--n > 0) my_os << *p++; 216} 217 218void RTTIDisplay::visit(List *l) 219{ 220 newline(); 221 my_os << demangle(typeid(*l).name()) << ": "; 222 if (my_encoded) 223 { 224 Encoding type = l->encoded_type(); 225 if(!type.empty()) 226 { 227 my_os << "type=" << type << ' '; 228 } 229 Encoding name = l->encoded_name(); 230 if(!name.empty()) 231 { 232 my_os << "name=" << name; 233 } 234 } 235 ++my_indent; 236 Node *rest = l; 237 while(rest != 0) 238 { 239 if(rest->is_atom()) 240 { 241 rest->accept(this); 242 rest = 0; 243 } 244 else 245 { 246 Node *head = rest->car(); 247 if(head == 0) 248 { 249 newline(); 250 my_os << "nil"; 251 } 252 else 253 { 254 head->accept(this); 255 } 256 rest = rest->cdr(); 257 } 258 } 259 --my_indent; 260} 261 262void RTTIDisplay::visit(DupAtom *a) 263{ 264 newline(); 265 my_os << demangle(typeid(*a).name()) << ": "; 266 char const *pos = a->position(); 267 size_t length = a->length(); 268 269 if(length == 1 && *pos == '@') 270 { 271 my_os << "\\@"; 272 return; 273 } 274 275 my_os << '`'; 276 for(size_t i = 0; i < length; ++i) my_os << pos[i]; 277 my_os << '`'; 278} 279 280void RTTIDisplay::newline() 281{ 282 my_os.put('\n'); 283 for(size_t i = 0; i != my_indent; ++i) my_os.put(' '); 284} 285 286DotFileGenerator::DotFileGenerator(std::ostream &os) : my_os(os) {} 287void DotFileGenerator::write(PTree::Node const *ptree) 288{ 289 my_os << "digraph PTree\n{\n" 290 << "node[fillcolor=\"#ffffcc\", pencolor=\"#424242\" style=\"filled\"];\n"; 291 const_cast<Node *>(ptree)->accept(this); 292 my_os << '}' << std::endl; 293} 294 295void DotFileGenerator::visit(PTree::Atom *a) 296{ 297 my_os << (long)a 298 << " [label=\"" << std::string(a->position(), a->length()) 299 << "\" fillcolor=\"#ffcccc\"];\n"; 300} 301 302void DotFileGenerator::visit(PTree::List *l) 303{ 304 my_os << (long)l 305 << " [label=\"" << demangle(typeid(*l).name()) << "\"];\n"; 306 if (l->car()) 307 { 308 l->car()->accept(this); 309 my_os << (long)l << "->" 310 << (long)l->car() << ';' << std::endl; 311 } 312 if (l->cdr()) 313 { 314 l->cdr()->accept(this); 315 my_os << (long)l << "->" 316 << (long)l->cdr() << ';' << std::endl; 317 } 318} 319
Generated on Tue May 13 02:39:10 2008 by
synopsis (version 0.10)
synopsis (version 0.10)