1// $Header$
2//
3// Copyright (C) 2000 - 2004, by
4//
5// Carlo Wood, Run on IRC <carlo@alinoe.com>
6// RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
7// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
8//
9// This file may be distributed under the terms of the Q Public License
10// version 1.0 as appearing in the file LICENSE.QPL included in the
11// packaging of this file.
12//
13
14#ifndef LIBCWD_CLASS_LOCATION_INL
15#define LIBCWD_CLASS_LOCATION_INL
16
17#ifndef LIBCWD_CONFIG_H
18#include <libcwd/config.h>
19#endif
20
21#if CWDEBUG_LOCATION
22
23#ifndef LIBCWD_LIBRARIES_DEBUG_H
24#include <libcwd/libraries_debug.h>
25#endif
26#ifndef LIBCWD_PRIVATE_ASSERT_H
27#include <libcwd/private_assert.h>
28#endif
29#ifndef LIBCWD_PRIVATE_THREADING_H
30#include <libcwd/private_threading.h>
31#endif
32#ifndef LIBCWD_CLASS_LOCATION_H
33#include <libcwd/class_location.h>
34#endif
35#ifndef LIBCW_STRING
36#define LIBCW_STRING
37#include <string>
38#endif
39
40namespace libcwd {
41
42/**
43 * \brief Construct a location for address \p addr.
44 */
45inline
46location_ct::location_ct(void const* addr) : M_known(false)
47#if CWDEBUG_ALLOC
48    , M_hide(_private_::new_location)
49#endif
50{
51  LIBCWD_TSD_DECLARATION;
52  M_pc_location(addr LIBCWD_COMMA_TSD);
53}
54
55#if LIBCWD_THREAD_SAFE
56/*
57 * Construct a location for address addr,
58 * taking a thread-specific-data argument.
59 */
60inline
61location_ct::location_ct(void const* addr LIBCWD_COMMA_TSD_PARAM) : M_known(false)
62#if CWDEBUG_ALLOC
63     , M_hide(_private_::new_location)
64#endif
65{
66  M_pc_location(addr LIBCWD_COMMA_TSD);
67}
68#endif
69
70/**
71 * \brief Destructor.
72 */
73inline
74location_ct::~location_ct()
75{
76  clear();
77}
78
79inline
80location_ct::location_ct(void) : M_func(S_uninitialized_location_ct_c), M_object_file(NULL), M_known(false)
81#if CWDEBUG_ALLOC
82    , M_hide(_private_::new_location)
83#endif
84{
85}
86
87/**
88 * \brief Point this location to a different program counter address.
89 */
90inline
91void
92location_ct::pc_location(void const* addr)
93{
94  clear();
95  LIBCWD_TSD_DECLARATION;
96  M_pc_location(addr LIBCWD_COMMA_TSD);
97}
98
99inline
100bool
101location_ct::is_known(void) const
102{
103  return M_known;
104}
105
106inline
107std::string
108location_ct::file(void) const
109{
110#if CWDEBUG_DEBUGM
111  LIBCWD_TSD_DECLARATION;
112  LIBCWD_ASSERT( !__libcwd_tsd.internal );		// Returning a string, using a userspace allocator!
113#endif
114  LIBCWD_ASSERT( M_known );
115  return M_filename;
116}
117
118inline
119unsigned int
120location_ct::line(void) const
121{
122  LIBCWD_ASSERT( M_known );
123  return M_line;
124}
125
126inline
127char const*
128location_ct::mangled_function_name(void) const
129{
130  return M_func;
131}
132
133inline
134location_format_t
135location_format(location_format_t format)
136{
137  LIBCWD_TSD_DECLARATION;
138  location_format_t ret = __libcwd_tsd.format;
139  __libcwd_tsd.format = format;
140  return ret;
141}
142
143namespace _private_ {
144
145template<class OSTREAM>
146  void print_location_on(OSTREAM& os, location_ct const& location)
147  {
148    if (location.M_known)
149    {
150      LIBCWD_TSD_DECLARATION;
151      if ((__libcwd_tsd.format & show_objectfile))
152	os << location.M_object_file->filename() << ':';
153      if ((__libcwd_tsd.format & show_function))
154	os << location.M_func << ':';
155      if ((__libcwd_tsd.format & show_path))
156	os << location.M_filepath.get() << ':' << location.M_line;
157      else
158	os << location.M_filename << ':' << location.M_line;
159    }
160    else if (location.M_object_file)
161      os << location.M_object_file->filename() << ':' << location.M_func;
162    else
163      os << "<unknown object file> (at " << location.unknown_pc() << ')';
164  }
165
166} // namespace _private_
167
168#if !(__GNUC__ == 3 && __GNUC_MINOR__ < 4)	// See class_location.h
169/**
170 * \brief Write \a location to ostream \a os.
171 * \ingroup group_locations
172 *
173 * Write the contents of a location_ct object to an ostream in the form <i>source-file</i>:<i>line-number</i>,
174 * or writes <i>objectfile</i>:<i>mangledfuncname</i> when the location is unknown.
175 * If the <i>source-file</i>:<i>line-number</i> is known, then it may be prepended by the object file
176 * and/or the mangled function name anyway if this was requested through \ref location_format.
177 * That function can also be used to cause the <i>source-file</i> to be printed with its full path.
178 */
179inline
180std::ostream&
181operator<<(std::ostream& os, location_ct const& location)
182{
183  _private_::print_location_on(os, location);
184  return os;
185}
186#endif
187
188} // namespace libcwd
189
190#endif // CWDEBUG_LOCATION
191#endif // LIBCWD_CLASS_LOCATION_INL
192