os_fixes.hpp
1: #ifndef OS_FIXES_HPP
2: #define OS_FIXES_HPP
3: /*------------------------------------------------------------------------------
4:
5: Author: Andy Rushton
6: Copyright: (c) Southampton University 1999-2004
7: (c) Andy Rushton 2004-2009
8: License: BSD License, see ../docs/license.html
9:
10: Contains work arounds for OS or Compiler specific problems to try to make
11: them look more alike
12:
13: It is strongly recommended that this header be included as the first
14: #include in every source file
15:
16: ------------------------------------------------------------------------------*/
17:
18: ////////////////////////////////////////////////////////////////////////////////
19: // Problem with MicroSoft defining two different macros to identify Windows
20: ////////////////////////////////////////////////////////////////////////////////
21:
22: #if defined(_WIN32) || defined(_WIN32_WCE)
23: #define MSWINDOWS
24: #endif
25:
26: ////////////////////////////////////////////////////////////////////////////////
27: // Problems with unnecessary or unfixable compiler warnings
28: ////////////////////////////////////////////////////////////////////////////////
29:
30: #if defined(_MSC_VER)
31: // Microsoft Visual Studio
32: // shut up the following irritating warnings
33: // 4275 - VC6, exported class was derived from a class that was not exported
34: // 4786 - VC6, identifier string exceeded maximum allowable length and was truncated (only affects debugger)
35: // 4305 - VC6, identifier type was converted to a smaller type
36: // 4503 - VC6, decorated name was longer than the maximum the compiler allows (only affects debugger)
37: // 4309 - VC6, type conversion operation caused a constant to exceeded the space allocated for it
38: // 4290 - VC6, C++ exception specification ignored
39: // 4800 - VC6, forcing value to bool 'true' or 'false' (performance warning)
40: // 4675 - VC7.1, "change" in function overload resolution _might_ have altered program
41: // 4996 - VC8, 'xxxx' was declared deprecated
42: #pragma warning(disable: 4275 4786 4305 4503 4309 4290 4800 4675 4996)
43: #endif
44:
45: #if defined(__BORLANDC__)
46: // Borland
47: // Shut up the following irritating warnings
48: // 8008 - Condition is always true.
49: // Whenever the compiler encounters a constant comparison that (due to
50: // the nature of the value being compared) is always true or false, it
51: // issues this warning and evaluates the condition at compile time.
52: // 8060 - Possibly incorrect assignment.
53: // This warning is generated when the compiler encounters an assignment
54: // operator as the main operator of a conditional expression (part of
55: // an if, while, or do-while statement). This is usually a
56: // typographical error for the equality operator.
57: // 8066 - Unreachable code.
58: // A break, continue, goto, or return statement was not followed by a
59: // label or the end of a loop or function. The compiler checks while,
60: // do, and for loops with a constant test condition, and attempts to
61: // recognize loops that can't fall through.
62: #pragma warn -8008
63: #pragma warn -8060
64: #pragma warn -8066
65: #endif
66:
67: ////////////////////////////////////////////////////////////////////////////////
68: // Problems with redefinition of min/max in various different versions of library headers
69: ////////////////////////////////////////////////////////////////////////////////
70:
71: // The Windows headers define macros called max/min which conflict with the templates std::max and std::min.
72: // So, to avoid conflicts, MS removed the std::max/min rather than fixing the problem!
73: // From Visual Studio .NET (SV7, compiler version 13.00) the STL templates have been added correctly.
74: // This fix switches off the macros and reinstates the STL templates for earlier versions (SV6).
75: // Note that this could break MFC applications that rely on the macros (try it and see).
76:
77: // For MFC compatibility, only undef min and max in non-MFC programs - some bits of MFC
78: // use macro min/max in headers. For VC7 both the macros and template functions exist
79: // so there is no real need for the undefs but to it anyway for consistency. So, if
80: // using VC6 and MFC then template functions will not exist
81:
82: // I've created extra template function definitions minimum/maximum that avoid all the problems above
83:
84: #if defined(_MSC_VER) && !defined(_MFC_VER)
85: #define NOMINMAX
86: #undef max
87: #undef min
88: // replace missing template definitions in VC6
89: #if defined(_MSC_VER) && (_MSC_VER < 1300)
90: namespace std
91: {
92: template<typename T> const T& max(const T& l, const T& r) {return l > r ? l : r;}
93: template<typename T> const T& min(const T& l, const T& r) {return l < r ? l : r;}
94: }
95: #endif
96: #endif
97:
98: template<typename T> const T& maximum(const T& l, const T& r) {return l > r ? l : r;}
99: template<typename T> const T& minimum(const T& l, const T& r) {return l < r ? l : r;}
100:
101: ////////////////////////////////////////////////////////////////////////////////
102: // Problem with missing __FUNCTION__ macro
103: ////////////////////////////////////////////////////////////////////////////////
104: // this macro is used in debugging but was missing in Visual Studio prior to version 7
105: // it also has a different name in Borland
106:
107: #if defined(_MSC_VER) && (_MSC_VER < 1300)
108: #define __FUNCTION__ 0
109: #endif
110:
111: #if defined(__BORLANDC__)
112: #define __FUNCTION__ __FUNC__
113: #endif
114:
115: ////////////////////////////////////////////////////////////////////////////////
116: // Problems with differences between namespaces
117: ////////////////////////////////////////////////////////////////////////////////
118:
119: // problem in gcc pre-v3 where the sub-namespaces in std aren't present
120: // this mean that the statement "using namespace std::rel_ops" created an error because the namespace didn't exist
121:
122: // I've done a fix here that creates an empty namespace for this case, but I
123: // do *not* try to move the contents of std::rel_ops into namespace std
124: // This fix only works if you use "using namespace std::rel_ops" to bring in the template relational operators (e.g. != defined i.t.o. ==)
125:
126: #if defined(__GNUC__)
127: namespace std
128: {
129: namespace rel_ops
130: {
131: }
132: }
133: #endif
134:
135: ////////////////////////////////////////////////////////////////////////////////
136: // Problems with the typename keyword
137: ////////////////////////////////////////////////////////////////////////////////
138:
139: // There are problems with using the 'typename' keyword. Technically, if you
140: // use a type member of a template class (i.e. a type declared within the
141: // template class by a local typedef), you need to tell the compiler that it
142: // is a type name. This is because the compiler cannot work out whether a
143: // member is a type, a method or a data field at compile time. However,
144: // support for the typename keyword has traditionally been incomplete in both
145: // gcc and Visual Studio. I have used macros to try to resolve this issue. The
146: // macros add the keyword for compiler versions that require it and omit it
147: // for compiler versions that do not support it
148:
149: // There are five places where typename keywords cause problems:
150: //
151: // 1) in a typedef where a template class's member type is being mapped onto
152: // a type definition within another template class or function
153: // e.g. template<typename T> fn () {
154: // typedef typename someclass<T>::member_type local_type;
155: // ^^^^^^^^
156: // Note that the typename keyword is only required when the type is of this form - a member of a template class
157: // This situation is handled by the macro TYPEDEF_TYPENAME
158: //
159: // 2) in a function parameter declaration, with similar rules to the above
160: // e.g. template<typename T> fn (typename someclass<T>::member_type)
161: // ^^^^^^^^
162: // Note that the typename keyword is only required when the type is of this form - a member of a template class
163: // This situation is handled by the macro PARAMETER_TYPENAME
164: //
165: // 3) in instantiating a template, the parameter to the template, with similar rules to the above
166: // e.g. template_class<typename someclass<T>::member_type>
167: // ^^^^^^^^
168: // Note that the typename keyword is only required when the type is of this form - a member of a template class
169: // This situation is handled by the macro TEMPLATE_TYPENAME
170: // 4) Return expressions
171: // e.g. return typename ntree<T>::const_iterator(this,m_root);
172: // ^^^^^^^^
173: // Note that this typename is only required when the return type is a member of a template class
174: // 5) Creating temporary objects when passing arguments to a function or constructor
175: // e.g. return typename ntree<T>::const_prefix_iterator(typename ntree<T>::const_iterator(this,m_root));
176: // ^^^^^^^^
177: // Note that the typename keyword is only required when the temporary's type is a member of a template class
178:
179: // default values, overridden for individual problem cases below
180: #define TYPEDEF_TYPENAME typename
181: #define PARAMETER_TYPENAME typename
182: #define TEMPLATE_TYPENAME typename
183: #define RETURN_TYPENAME typename
184: #define TEMPORARY_TYPENAME typename
185:
186: #if defined(__GNUC__)
187: // GCC
188: // - pre-version 3 didn't handle typename in any of these cases
189: // - version 3 onwards, typename is required for all three cases as per default
190: #if __GNUC__ < 3
191: // gcc prior to v3
192: #undef TYPEDEF_TYPENAME
193: #define TYPEDEF_TYPENAME
194: #undef PARAMETER_TYPENAME
195: #define PARAMETER_TYPENAME
196: #undef TEMPLATE_TYPENAME
197: #define TEMPLATE_TYPENAME
198: #undef RETURN_TYPENAME
199: #define RETURN_TYPENAME
200: #undef TEMPORARY_TYPENAME
201: #define TEMPORARY_TYPENAME
202: #endif
203: #endif
204:
205: #if defined(_MSC_VER)
206: // Visual Studio
207: // - version 6 (compiler v.12) cannot handle typename in any of these cases
208: // - version 7 (.NET) (compiler v.13) requires a typename in a parameter specification but supports all
209: // - version 8 (2005) (compiler v.14) requires parameters and templates, supports all
210: #if _MSC_VER < 1300
211: // compiler version 12 and earlier
212: #undef TYPEDEF_TYPENAME
213: #define TYPEDEF_TYPENAME
214: #undef PARAMETER_TYPENAME
215: #define PARAMETER_TYPENAME
216: #undef TEMPLATE_TYPENAME
217: #define TEMPLATE_TYPENAME
218: #undef RETURN_TYPENAME
219: #define RETURN_TYPENAME
220: #undef TEMPORARY_TYPENAME
221: #define TEMPORARY_TYPENAME
222: #endif
223: #endif
224:
225: ////////////////////////////////////////////////////////////////////////////////
226: // problems with missing functions
227: ////////////////////////////////////////////////////////////////////////////////
228:
229: #if defined(_MSC_VER) || defined(__BORLANDC__)
230: unsigned sleep(unsigned seconds);
231: #else
232: #include <unistd.h>
233: #endif
234:
235: ////////////////////////////////////////////////////////////////////////////////
236: // Function for establishing endian-ness
237: ////////////////////////////////////////////////////////////////////////////////
238: // Different machine architectures store data using different byte orders.
239: // This is referred to as Big- and Little-Endian Byte Ordering.
240: //
241: // The issue is: where does a pointer to an integer type actually point?
242: //
243: // In both conventions, the address points to the left of the word but:
244: // Big-Endian - The most significant byte is on the left end of a word
245: // Little-Endian - The least significant byte is on the left end of a word
246: //
247: // Bytes are addressed left to right, so in big-endian order byte 0 is the
248: // msB, whereas in little-endian order byte 0 is the lsB. For example,
249: // Intel-based machines store data in little-endian byte order so byte 0 is
250: // the lsB.
251: //
252: // This function establishes byte order at run-time
253:
254: bool little_endian(void);
255:
256: ////////////////////////////////////////////////////////////////////////////////
257: #endif