Synopsis - Cross-Reference
File: /Synopsis/Parsers/Cxx/STrace.hh1// 2// Copyright (C) 2000 Stephen Davies 3// Copyright (C) 2000 Stefan Seefeld 4// All rights reserved. 5// Licensed to the public under the terms of the GNU LGPL (>= 2), 6// see the file COPYING for details. 7// 8 9#ifndef strace_hh_ 10#define strace_hh_ 11 12#include <string> 13#include <iostream> 14#include <sstream> 15#include <exception> 16#include <list> 17 18namespace Synopsis 19{ 20namespace PTree { class Node;} 21} 22#if defined(DEBUG) 23#define DO_TRACE 24//. A tracer class that can be used as a Guard around sections of code. The 25//. instances are kept in a class-static stack, and enter/leave messages are 26//. only printed when output is made at a given level. To work this, two 27//. indices to the stack level are used: slevel and dlevel. The Stack Level 28//. indicates the current depth of the stack, including non-displayed levels. 29//. The Display Level indicates the level up to which enter statements have 30//. been printed. Leave statements are only printed if slevel falls below 31//. dlevel. 32class STrace 33{ 34 //. A convenient typedef 35 typedef std::list<std::string> string_list; 36public: 37 //. Constructor 38 STrace(const std::string &s) 39 : m_scope(s) 40 { 41 m_list.push_back(indent() + "entering " + m_scope); 42 ++slevel; 43 } 44 //. Destructor, called when leaving a scope. Only print out leaving messages 45 //. if the enter was displayed. 46 ~STrace() 47 { 48 if (dlevel > --slevel) 49 { 50 // 'enter' message was displayed, so display leave message too 51 std::cout << indent() << "leaving " << m_scope << std::endl; 52 --dlevel; 53 } 54 else 55 // 'enter' message wasn't displayed, so remove it from list 56 m_list.pop_back(); 57 } 58 //. Insertion operator, used to start logging a line 59 std::ostream& operator <<(const std::string& s) 60 { 61 // Catch up on skipped enter messages 62 while (dlevel < slevel) 63 { 64 std::cout << m_list.front() << "\n"; 65 m_list.pop_front(); 66 ++dlevel; 67 } 68 // Start current log message at correct indent 69 std::cout << indent() << s; 70 return std::cout; 71 } 72 //. Insertion operator. Logs a Ptree 73 std::ostream& operator<<(Synopsis::PTree::Node *p); // defined in swalker.cc 74 //. Creates a new stringstream for use in buffering output 75 std::ostringstream& new_stream() 76 { 77 if (stream) 78 delete stream; 79 stream = new std::ostringstream; 80 *stream << m_scope << ": "; 81 return *stream; 82 } 83 //. Returns a string derived from the buffer for output 84 std::string get_stream_str() 85 { 86 if (stream) 87 return stream->str(); 88 return ""; 89 } 90 91private: 92 //. Returns a string representing the indent 93 std::string indent() 94 { 95 return std::string(slevel, ' '); 96 } 97 //. The scope of this STrace object 98 std::string m_scope; 99 //. The Stack-Level and Display-Level indices 100 static int slevel, dlevel; 101 //. A StringStream used for buffering output 102 static std::ostringstream* stream; 103 //. The FIFO queue of skipped enter-messages 104 static string_list m_list; 105}; 106 107//. An exception object indicating errors in translating the Ptree to an ASG. 108//. Upon invocation, will grab the error message stored by the ERROR macros in 109//. the STrace object 110class TranslateError : public std::exception 111{ 112public: 113 //. The message 114 std::string message; 115 //. The node that was being translated 116 mutable Synopsis::PTree::Node *node; 117 118 //. Constructor. Extracts the error message from the STracer (set by ERROR macros) 119 TranslateError(STrace& trace, Synopsis::PTree::Node *p = 0) 120 : node(p) 121 { 122 message = trace.get_stream_str(); 123 trace << "Error: " << message << std::endl; 124 } 125 //. Copy constructor 126 TranslateError(const TranslateError& e) 127 : message(e.message), node(e.node) 128 { } 129 //. Destructor 130 ~TranslateError() throw() 131 {} 132 133 //. overridden std::exception method (not that the original works too well) 134 virtual const char* what() const throw () 135 { 136 return "TranslateError"; 137 } 138 //. Returns the error message 139 std::string str() const 140 { 141 return message; 142 } 143 //. Sets a node for the error, if not already set. 144 void set_node(Synopsis::PTree::Node *p) const 145 { 146 if (!node) 147 node = p; 148 } 149}; 150#define ERROR(message) (trace.new_stream() << message, TranslateError(trace)) 151#define nodeERROR(node, message) (trace.new_stream() << message, TranslateError(trace, node)) 152#define LOG(message) trace << message << std::endl 153#define nodeLOG(message) trace << message; 154 155 156#else // DEBUG 157 158//. Dummy STrace guard for release code - should be optimized away 159class STrace 160{ 161public: 162 STrace(const std::string &) 163 { } 164 ~STrace() 165 { } 166}; 167 168//. Exception thrown by errors when translating the Ptree into an ASG 169class TranslateError : public std::exception 170{ 171public: 172 char const * str() 173 { 174 return ""; 175 } 176 virtual const char* what() const throw () 177 { 178 return "TranslateError"; 179 } 180 void set_node(Synopsis::PTree::Node *) const 181 { } 182}; 183#define ERROR(message) TranslateError() 184#define nodeERROR(node, message) TranslateError() 185#define LOG(trash) 186#define nodeLOG(trash) 187 188#endif 189 190 191#endif 192// vim: set ts=8 sts=4 sw=4 et: