Synopsis - Cross-Reference

File: /Synopsis/Parsers/Cxx/STrace.hh
  1//
  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: