Flow123d
sys_function_stack.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file
26  * @brief Stack trace, using macro F_ENTRY to put a trace point.
27  *
28  */
29 
30 #ifndef SYS_FUNCTION_STACK_HH_
31 #define SYS_FUNCTION_STACK_HH_
32 
33 #include <cstdio>
34 #include <iostream>
35 #include <vector>
36 
37 
38 /**
39  * @def F_ENTRY
40  *
41  * Unless Flow123d_NODEBUG is defined, it creates instance of the Trace class, providing compile time information
42  * about the place of usage.
43  *
44  * @def F_STACK_SHOW
45  *
46  * Just shortcut to both static output methods of the Trace class.
47  */
48 
49 #ifdef DEBUG_FUNCTION_STACK
50 
51 /*
52  * __SOMETHING__ stands for name of local instance of the Trace class. That means that
53  * F_ENTRY macro can be used only once in each function (otherwise it is redeclaration error).
54  */
55 //macros to convert number to quoted string using preprocessor
56 #define TO_XSTR(s) TO_STR(s)
57 #define TO_STR(s) #s
58 
59 // quoted strings in source are fused into one by preprocessor
60 //__func__ can not be converted to quoted string and fused with preprocessor - it is created later (in compiler stage)
61 #define F_ENTRY flow::Trace __SOMETHING__( "Tracepoint: " __FILE__ ", ", __func__, "(), line " TO_XSTR(__LINE__) "." )
62 
63 #define F_STACK_SHOW(stream) flow::Trace::stack_print(stream)
64 
65 #else
66 
67 #define F_STACK_SHOW(stream)
68 #define F_ENTRY
69 
70 #endif
71 
72 namespace flow
73 {
74  struct Trace_helper {
75  const char * str_file;
76  const char * str_func;
77  const char * str_line;
78  };
79  /**
80  * @brief This class provides function call stack.
81  *
82  * Then the backtrace of the called functions can be reported in the case of an error.
83  * Operations with the stack should be only through #F_ENTRY and #F_STACK_SHOW(stream).
84  * To include a function in the call stack just use macro #F_ENTRY at the very beginning of the function.
85  * #F_ENTRY macro is nonempty only for the debugging version. For the release version, i.e. when Flow123d_NODEBUG
86  * is defined, #F_ENTRY is empty and produce no run-time overhead.
87  *
88  */
89  class Trace
90  {
91  public:
92  /**
93  * Constructor, takes source filename and func_name of a function, and line number line_no
94  * of the call of #F_ENTRY. Forms a message string and put it onto stack.
95  */
96  explicit Trace( const char * const trace_str, const char * const trace_str2, const char * const trace_str3 )
97  {
98  if (stack_depth == -1) {
99  stack_depth=0;
101  }
102  (*program_stack)[stack_depth].str_file = trace_str;
103  (*program_stack)[stack_depth].str_func = trace_str2;
104  (*program_stack)[stack_depth].str_line = trace_str3;
105  stack_depth++;
106  }
107 
108  /**
109  * Destructor, automatically called on the function exit. Pop out the stack message of that function.
110  */
112  {
113  stack_depth--;
114  }
115 
116  /**
117  * Prints the stack into a given file.
118  */
119  static void stack_print( FILE * fw )
120  {
121  fprintf( fw, "Stack trace, depth: %d\n", stack_depth );
122  for( int i = stack_depth-1; i >= 0 ; --i )
123  fprintf( fw, " %s%s%s\n", (*program_stack)[i].str_file, (*program_stack)[i].str_func, (*program_stack)[i].str_line );
124  }
125 
126  /**
127  * As previous, but output into C++ output stream.
128  */
129  static void stack_print( std::ostream * os )
130  {
131  *os << "Stack trace, depth: " << stack_depth << std::endl;
132  for( int i = stack_depth-1; i >= 0 ; --i )
133  *os << (*program_stack)[i].str_file << (*program_stack)[i].str_func << (*program_stack)[i].str_line << std::endl;
134  }
135  private:
136  /**
137  * Static stack of trace messages.
138  */
139  static int stack_depth;
141  };
142 }
143 
144 #endif /* SYS_FUNCTION_STACK_HH_ */