1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_ERRORS
19 #define INCLUDED_ERRORS
20 
21 /*
22 
23 The overly-complex error system works as follows:
24 
25 A source file (typically a .h) can declare errors as follows:
26 
27 	ERROR_GROUP(ModuleName);
28 	ERROR_TYPE(ModuleName, FrobnificationFailed);
29 	ERROR_SUBGROUP(ModuleName, ComponentName);
30 	ERROR_TYPE(ModuleName_ComponentName, FileNotFound);
31 
32 etc, to build up a hierarchy of error types.
33 
34 Then you have to run the /build/errorlist/errorlist.pl script, to regenerate
35 the Errors.cpp file.
36 
37 Then you can use the declared errors as an error code:
38 
39 	PSRETURN foo() { return PSRETURN_ModuleName_FrobnificationFailed; }
40 
41 	if (ret != PSRETURN_OK)
42 		... // something failed
43 
44 	if (ret)
45 		... // something failed
46 
47 	if (ret == PSRETURN_ModuleName_FrobnificationFailed)
48 		... // particular error
49 
50 	if (ERROR_IS(ret, PSRETURN_ModuleName))
51 		... // matches any type PSRETURN_ModuleName_* (and PSRETURN_ModuleName_*_* etc)
52 
53 And you can use it as an exception:
54 
55 	void foo() { throw PSERROR_ModuleName_FrobnificationFailed(); }
56 
57 	void bar() { throw PSERROR_ModuleName_FrobnificationFailed("More informative message"); }
58 
59 	try {
60 		foo();
61 	} catch (PSERROR_ModuleName_FrobnificationFailed& e) {
62 		// catches that particular error type
63 	} catch (PSERROR_ModuleName& e) {
64 		// catches anything in the hierarchy
65 	} catch (PSERROR& e) {
66 		std::cout << e.what();
67 	}
68 
69 plus a few extra things for converting between error codes and exceptions.
70 
71 */
72 
73 #include <exception>
74 
75 typedef u32 PSRETURN;
76 
77 class PSERROR : public std::exception
78 {
79 public:
80 	PSERROR(const char* msg);
81 	virtual const char* what() const throw ();
82 	virtual PSRETURN getCode() const = 0; // for functions that catch exceptions then return error codes
83 private:
84 	const char* m_msg;
85 };
86 
87 #define ERROR_GROUP(a) class PSERROR_##a : public PSERROR { protected: PSERROR_##a(const char* msg); }; \
88 						extern const PSRETURN MASK__PSRETURN_##a; \
89 						extern const PSRETURN CODE__PSRETURN_##a
90 
91 #define ERROR_SUBGROUP(a,b) class PSERROR_##a##_##b : public PSERROR_##a { protected: PSERROR_##a##_##b(const char* msg); }; \
92 						extern const PSRETURN MASK__PSRETURN_##a##_##b; \
93 						extern const PSRETURN CODE__PSRETURN_##a##_##b
94 
95 
96 #define ERROR_TYPE(a,b) class PSERROR_##a##_##b : public PSERROR_##a { public: PSERROR_##a##_##b(); PSERROR_##a##_##b(const char* msg); PSRETURN getCode() const; }; \
97 						extern const PSRETURN MASK__PSRETURN_##a##_##b; \
98 						extern const PSRETURN CODE__PSRETURN_##a##_##b; \
99 						extern const PSRETURN PSRETURN_##a##_##b
100 
101 #define ERROR_IS(a, b) ( ((a) & MASK__PSRETURN_##b) == CODE__PSRETURN_##b )
102 
103 const PSRETURN PSRETURN_OK = 0;
104 const PSRETURN MASK__PSRETURN_OK = 0xFFFFFFFF;
105 const PSRETURN CODE__PSRETURN_OK = 0;
106 
107 const char* GetErrorString(PSRETURN code);
108 void ThrowError(PSRETURN code);
109 
110 #endif
111