This file is indexed.

/usr/include/wibble/exception.h is in libwibble-dev 1.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
// -*- C++ -*-
#ifndef WIBBLE_EXCEPTION_H
#define WIBBLE_EXCEPTION_H

/*
 * Generic base exception hierarchy
 *
 * Copyright (C) 2003,2004,2005,2006  Enrico Zini <enrico@debian.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

#include <wibble/test.h> // for assert
#include <exception>
#include <typeinfo>
#include <string>
#include <sstream>
#include <iterator>
#include <vector>

/*! \file
 * This file provides the root of the exception hierarchy.  The goal of this
 * hierarchy is to provide the most possible information on what caused the
 * exception at the least possible cost for the programmer.
 * 
 * Every exception is the descendent of Exception that, in turn, extends the
 * std::exception class of the STL.
 *
 * Further descendents of Exception add functionality and automatisms to error
 * message generation:
 *
 *  - ContextException extends Exception to provide informations on the context
 *    in which the exception was raised
 *  - ConsistencyCheckException extends ContextException to be a base class for
 *    all exception raised on failure of a consistency check;
 *    IndexOutOfRangeException is one example of such exceptions, to be used
 *    when checking that a value (such as an index) fails betweed two given
 *    bounds.
 *  - SystemException extends ContextException to carry informations about
 *    error conditions reported by external services, like the Operating
 *    System, a database interface or an interface used to communicate to some
 *    network server.  In particular, it provides the logic needed to make use
 *    of the error descriptions provided by the external services, as
 *    strerror(3) does for the operating system's error conditions.
 *    FileException is an example of such exceptions, to be used to report
 *    error conditions happened during File I/O.
 * 
 * Example exception raising:
 * \code
 * 		void MyFile::open(const char* fname) throw (FileException)
 * 		{
 * 			if ((fd = open(fname, O_RDONLY)) == -1)
 * 				throw FileException(errno, stringf::fmt("opening %s read-only", fname));
 * 		}
 * \endcode
 *
 * Example exception catching:
 * \code
 *      try {
 * 			myfile.open("/tmp/foo");
 * 		} catch (FileException& e) {
 * 			fprintf(stderr, "%.*s: aborting.\n", PFSTR(e.toString()));
 * 			exit(1);
 * 		}
 * \endcode
 */

namespace wibble {
namespace exception {

/// Basic unexpected handler
/**
 * This is an unexpected handler provided by the library.  It prints to stderr
 * a stack trace and all possible available informations about the escaped
 * exception.
 *
 * To have the function names in the stack trace, the executables need to be
 * linked using the -rdynamic flag.
 */
void DefaultUnexpected();

/// Install an unexpected handler for the duration of its scope.  Install
/// DefaultUnexpected if no handler is provided.
class InstallUnexpected
{
protected:	
	void (*old)();
public:
	InstallUnexpected(void (*func)() = DefaultUnexpected);
	~InstallUnexpected();
};

// TODO this needs to be made useful with threading as well
struct AddContext {
    static std::vector< std::string > *s_context;

    static std::vector< std::string > &context() {
        if ( s_context )
            return *s_context;
        s_context = new std::vector< std::string >();
        return *s_context;
    }

    template< typename O >
    static void copyContext( O out ) {
        std::copy( context().begin(), context().end(), out );
    }

    std::string m_context;

    AddContext( std::string s )
        : m_context( s )
    {
        context().push_back( s );
    }

    ~AddContext() {
        assert_eq( context().back(), m_context );
        context().pop_back();
    }
};

/// Store context information for an exception
class Context
{
protected:
	std::vector<std::string> m_context;

public:
    Context() throw ()
    {
        AddContext::copyContext( std::back_inserter( m_context ) );
    }

    Context(const std::string& context) throw ()
    {
        AddContext::copyContext( std::back_inserter( m_context ) );
        addContext(context);
    }

    void addContext(const std::string& c) throw () { m_context.push_back(c); }
    std::string formatContext() const throw ()
    {
        if (m_context.empty())
            return "no context information available";
        
        std::stringstream res;
        std::copy( m_context.begin(), m_context.end(),
                   std::ostream_iterator< std::string >( res, ", \n    " ) );
        std::string r = res.str();
        return std::string( r, 0, r.length() - 7 );
    }

    const std::vector<std::string>& context() const throw ()
    {
        return m_context;
    }
};

/// Base class for all exceptions
/**
 * This is the base class for all exceptions used in the system.  It provides
 * an interface to get a (hopefully detailed) textual description of the
 * exception, and a tag describing the type of exception.  Further
 * functionality will be provided by subclassers
 */
class Generic : public std::exception, public Context
{
protected:
	mutable std::string m_formatted;

public:
	Generic() throw () {}
	Generic(const std::string& context) throw () : Context(context) {}
	virtual ~Generic() throw () {}

	/// Get a string tag identifying the exception type
	virtual const char* type() const throw () { return "Generic"; }

	/// Get a string describing what happened that threw the exception
	virtual std::string desc() const throw ()
	{
		return "an unspecified problem happened; if you see this message, please report a bug to the maintainer";
	}

	/**
	 * Format in a string all available information about the exception.
	 * 
	 * The formatted version is cached because this function is used to
	 * implement the default what() method, which needs to return a stable
	 * c_str() pointer.
	 */
	virtual const std::string& fullInfo() const throw ()
	{
		if (m_formatted.empty())
			m_formatted = desc() + ". Context:\n    "
                                      + formatContext();
		return m_formatted;
	}

	virtual const char* what() const throw () { return fullInfo().c_str(); }
};

/// Exception thrown when some long event is interrupted by an external event
/// (like a system call being interrupted by a signal)
/**
 * It is a direct child of ContextException, and has the very same semantics.
 *
 * \warning Any function throwing InterruptedException must allow to be called
 * again with the same parameters to retry the operation
 */
class Interrupted : public Generic
{
public:
	Interrupted() throw () {}
	Interrupted(const std::string& context) throw () : Generic(context) {}

	virtual const char* type() const throw () { return "Interrupted"; }
};

/// Exception thrown when some system wait is interrupted by a signal
/**
 * It is a direct child of InterruptedException, and has the very same
 * semantics.
 *
 * \warning Any function throwing WaitInterruptedException must allow to be
 * called again with the same parameters to retry the operation
 */
class WaitInterrupted : public Interrupted
{
public:
	WaitInterrupted(const std::string& context) throw () :
		Interrupted(context) {}

	virtual const char* type() const throw () { return "WaitInterrupted"; }
};

/// Exception thrown when some consistency check fails
/**
 * It is a direct child of ContextException, and has the very same semantics.
 */
class Consistency : public Generic
{
	std::string m_error;

public:
	Consistency(const std::string& context, const std::string& error = std::string()) throw () :
		Generic(context), m_error(error) {}
	~Consistency() throw () {}

	virtual const char* type() const throw () { return "Consistency"; }

	virtual std::string desc() const throw ()
	{
		if (m_error.empty())
			return "consistency check failed";
		return m_error;
	}
};

struct BadCast : public Consistency
{
    BadCast( const std::string &context ) throw()
        : Consistency( context )
    {}
    ~BadCast() throw() {}
    virtual std::string typeinfo() const throw() { return "unknown types"; }
    virtual std::string desc() const throw() {
        return std::string( "bad cast: " ) + typeinfo();
    }
};

#ifndef NO_RTTI
template< typename From, typename To >
struct BadCastExt : public BadCast
{
    BadCastExt( const std::string &error = std::string() ) throw()
        : BadCast( error )
    {}
    ~BadCastExt() throw() {}
    virtual std::string typeinfo() const throw() { return std::string( "from " )
                                                       + typeid( From ).name()
                                                       + " to "
                                                       + typeid( To ).name(); }
};
#endif

/**
 * Exception thrown when some value is out of range
 *
 * Usage:
 * \code
 * if (age < 200)
 *   throw OutOfRange("age", "ensuring that no mere mortal is using the system");
 * \endcode
 */
class OutOfRange : public Consistency
{
protected:
	std::string m_var_desc;

public:
	OutOfRange(const std::string& var_desc, const std::string& context) throw ()
		: Consistency(context), m_var_desc(var_desc) {}
	~OutOfRange() throw () {}

	virtual const char* type() const throw () { return "OutOfRange"; }

	/// Get a short description of the variable that has been checked
	virtual std::string var_desc() const throw () { return m_var_desc; }

	virtual std::string desc() const throw () { return m_var_desc + " out of range"; }
};

/// Exception thrown when index checking fails
/**
 * This exception is to be thrown when an index checking fails, providing
 * informations on the acceptable index range and on the offending value.
 * The context should be a description of the index, possibly preceeded by a
 * description of in what context did the index checking happen.
 * 
 * Example:
 * \code
 *  if (age < 18)
 *     throw IndexOutOfRangeException("age", age, 18, 0, "obtaining driver license");
 *
 *  if (i < 0 || i > 100)
 *  	throw IndexOutOfRangeException("percentage of items sold", i, 0, 100, "checking input consistency");
 * \endcode
 */
template <class C>
class ValOutOfRange : public OutOfRange
{
protected:
	C m_val;
	C m_inf;
	C m_sup;

public:
	/** Construct the exception; minBound and maxBound are the bounds of the
	 * valid index range (inclusive).
	 */
	ValOutOfRange(const std::string& var_desc, C val, C inf, C sup,
			const std::string& context) throw ()
					: OutOfRange(var_desc, context),
						m_val(val), m_inf(inf), m_sup(sup) {}
	
	///@name Methods used to get informations about the index and its bounds
	//@{
	/// Get the value that caused the index to go out-of-bounds
	virtual C val() const throw () { return m_val; }
	/// Get the minimum allowed value for this index
	virtual C inf() const throw () { return m_inf; }
	/// Get the maximum allowed value for this index
	virtual C sup() const throw () { return m_sup; }
	//@}

	virtual const char* type() const throw ()
	{
		return "ValOutOfRange<>";
	}

	virtual std::string desc() const throw ();
};

/// Base class for system exceptions
/**
 * This is the base class for exceptions that depend on system events, like
 * exceptions on file or network I/O, on database access and so on.
 * SystemExceptions introduces the keeping of an error code with an associated
 * string description, and by defaults provides the textual description for
 * Unix errno error codes.
 * The exception context should be phrased like "doing X".
 *
 * Example:
 * \code
 * 		const char* fname = "foo.bar";
 * 		if ((fd = open(fname, O_RDONLY)) == -1)
 * 			// Should not throw SystemException, but a more specialized derived
 * 			// class like FileException
 * 			throw SystemException(errno, stringf::fmt("opening %s read-only", fname));
 * \endcode
 */
class System : public Generic
{
protected:
	int m_errno;

public:
	System(const std::string& context) throw ();
	System(int code, const std::string& context) throw ();

	virtual const char* type() const throw () { return "System"; }

	/// Get the system error code associated to the exception
	virtual int code() const throw () { return m_errno; }

	/// Get the description of the error code
	virtual std::string desc() const throw ();
};

/// Base class for exceptions for file I/O
/**
 * It is a direct child of SystemException, and has the very same semantics.
 * Like in SystemException, the error code description provided is a
 * description for errno values.
 */
class File : public System
{
protected:
	std::string m_name;

public:
	File(const std::string& name, const std::string& context)	throw () :
		System(context), m_name(name) {}
	~File() throw () {}

	virtual const char* type() const throw () { return "File"; }

	virtual std::string desc() const throw () { return m_name + ": " + System::desc(); }
};

}
}

// vim:set ts=4 sw=4:
#endif