xoreos  0.0.5
system.h
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* Based on ScummVM (<http://scummvm.org>) code, which is released
26  * under the terms of version 2 or later of the GNU General Public
27  * License.
28  *
29  * The original copyright note in ScummVM reads as follows:
30  *
31  * ScummVM is the legal property of its developers, whose names
32  * are too numerous to list here. Please refer to the COPYRIGHT
33  * file distributed with this source distribution.
34  *
35  * This program is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU General Public License
37  * as published by the Free Software Foundation; either version 2
38  * of the License, or (at your option) any later version.
39  *
40  * This program is distributed in the hope that it will be useful,
41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43  * GNU General Public License for more details.
44  *
45  * You should have received a copy of the GNU General Public License
46  * along with this program; if not, write to the Free Software
47  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
48  */
49 
50 #ifndef COMMON_SYSTEM_H
51 #define COMMON_SYSTEM_H
52 
53 #if defined(HAVE_CONFIG_H)
54  #include "config.h"
55 #endif
56 
57 #include "src/common/noreturn.h"
58 #include "src/common/fallthrough.h"
59 
60 #if defined(_MSC_VER)
61 
62  #include <cstdarg>
63  #include <cstdio>
64  #include <cstdlib>
65 
66  #define snprintf c99_snprintf
67  #define vsnprintf c99_vsnprintf
68 
69  #ifndef HAVE_STRTOLL
70  #define strtoll _strtoi64
71  #define HAVE_STRTOLL 1
72  #endif
73 
74  #ifndef HAVE_STRTOULL
75  #define strtoull _strtoui64
76  #define HAVE_STRTOULL 1
77  #endif
78 
79  #if !defined(XOREOS_LITTLE_ENDIAN) && !defined(XOREOS_BIG_ENDIAN)
80  #define XOREOS_LITTLE_ENDIAN 1
81  #endif
82 
83  #define FORCEINLINE __forceinline
84  #define PLUGIN_EXPORT __declspec(dllexport)
85 
86  static FORCEINLINE int c99_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
87  int count = -1;
88 
89  if (size != 0)
90  count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
91  if (count == -1)
92  count = _vscprintf(format, ap);
93 
94  return count;
95  }
96 
97  static FORCEINLINE int c99_snprintf(char *str, size_t size, const char *format, ...) {
98  int count;
99  va_list ap;
100 
101  va_start(ap, format);
102  count = c99_vsnprintf(str, size, format, ap);
103  va_end(ap);
104 
105  return count;
106  }
107 
108  #ifndef WIN32
109  #define WIN32
110  #endif
111 
112  #define IGNORE_UNUSED_VARIABLES __pragma(warning(disable : 4101))
113 
114 #elif defined(__MINGW32__)
115 
116  #if !defined(XOREOS_LITTLE_ENDIAN) && !defined(XOREOS_BIG_ENDIAN)
117  #define XOREOS_LITTLE_ENDIAN 1
118  #endif
119 
120  #define PLUGIN_EXPORT __declspec(dllexport)
121 
122  #ifndef WIN32
123  #define WIN32
124  #endif
125 
126 #elif defined(UNIX)
127 
128  #if !defined(XOREOS_LITTLE_ENDIAN) && !defined(XOREOS_BIG_ENDIAN)
129  #if defined(HAVE_CONFIG_H)
130  #if defined(WORDS_BIGENDIAN)
131  #define XOREOS_BIG_ENDIAN 1
132  #else
133  #define XOREOS_LITTLE_ENDIAN 1
134  #endif
135  #endif
136  #endif
137 
138 #else
139  #error No system type defined
140 #endif
141 
142 //
143 // GCC specific stuff
144 //
145 #if defined(__GNUC__)
146  #define PACKED_STRUCT __attribute__((__packed__))
147  #define GCC_PRINTF(x,y) __attribute__((__format__(printf, x, y)))
148 
149  #if (__GNUC__ >= 3)
150  // Macro to ignore several "unused variable" warnings produced by GCC
151  #define IGNORE_UNUSED_VARIABLES _Pragma("GCC diagnostic ignored \"-Wunused-variable\"") \
152  _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"")
153  #endif
154 
155  #if !defined(FORCEINLINE) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
156  #define FORCEINLINE inline __attribute__((__always_inline__))
157  #endif
158 
159 #else
160  #define PACKED_STRUCT
161  #define GCC_PRINTF(x,y)
162 #endif
163 
164 #if defined(__cplusplus)
165  #define UNUSED(x)
166 #else
167  #if defined(__GNUC__)
168  #define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
169  #else
170  #define UNUSED(x) UNUSED_ ## x
171  #endif
172 #endif
173 
174 #if defined(__clang__)
175  // clang does not know the "unused-but-set-variable" (but claims to be GCC)
176  #undef IGNORE_UNUSED_VARIABLES
177  #define IGNORE_UNUSED_VARIABLES _Pragma("GCC diagnostic ignored \"-Wunused-variable\"")
178 #endif
179 
180 //
181 // Fallbacks for various functions
182 //
183 
184 #ifndef HAVE_STRTOF
185  #define strtof c99_strtof
186 
187  static FORCEINLINE float c99_strtof(const char *nptr, char **endptr) {
188  return (float) strtod(nptr, endptr);
189  }
190 
191  #define HAVE_STRTOF 1
192 #endif
193 
194 #ifndef HAVE_STRTOLL
195  #define strtoll c99_strtoll
196 
197  #include <cctype>
198  #include <cerrno>
199  #include <climits>
200 
201  #ifndef LLONG_MAX
202  #define LLONG_MAX 0x7FFFFFFFFFFFFFFFlL
203  #endif
204 
205  #ifndef LLONG_MIN
206  #define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL-1)
207  #endif
208 
217  static long long c99_strtoll(const char *nptr, char **endptr, int base) {
218  const char *s;
219  long long acc, cutoff;
220  int c;
221  int neg, any, cutlim;
222 
223  /*
224  * Skip white space and pick up leading +/- sign if any.
225  * If base is 0, allow 0x for hex and 0 for octal, else
226  * assume decimal; if base is already 16, allow 0x.
227  */
228  s = nptr;
229  do {
230  c = (unsigned char) *s++;
231  } while (isspace(c));
232  if (c == '-') {
233  neg = 1;
234  c = *s++;
235  } else {
236  neg = 0;
237  if (c == '+')
238  c = *s++;
239  }
240  if ((base == 0 || base == 16) &&
241  c == '0' && (*s == 'x' || *s == 'X')) {
242  c = s[1];
243  s += 2;
244  base = 16;
245  }
246  if (base == 0)
247  base = c == '0' ? 8 : 10;
248 
249  /*
250  * Compute the cutoff value between legal numbers and illegal
251  * numbers. That is the largest legal value, divided by the
252  * base. An input number that is greater than this value, if
253  * followed by a legal input character, is too big. One that
254  * is equal to this value may be valid or not; the limit
255  * between valid and invalid numbers is then based on the last
256  * digit. For instance, if the range for long longs is
257  * [-9223372036854775808..9223372036854775807] and the input base
258  * is 10, cutoff will be set to 922337203685477580 and cutlim to
259  * either 7 (neg==0) or 8 (neg==1), meaning that if we have
260  * accumulated a value > 922337203685477580, or equal but the
261  * next digit is > 7 (or 8), the number is too big, and we will
262  * return a range error.
263  *
264  * Set any if any `digits' consumed; make it negative to indicate
265  * overflow.
266  */
267  cutoff = neg ? LLONG_MIN : LLONG_MAX;
268  cutlim = cutoff % base;
269  cutoff /= base;
270  if (neg) {
271  if (cutlim > 0) {
272  cutlim -= base;
273  cutoff += 1;
274  }
275  cutlim = -cutlim;
276  }
277  for (acc = 0, any = 0;; c = (unsigned char) *s++) {
278  if (isdigit(c))
279  c -= '0';
280  else if (isalpha(c))
281  c -= isupper(c) ? 'A' - 10 : 'a' - 10;
282  else
283  break;
284  if (c >= base)
285  break;
286  if (any < 0)
287  continue;
288  if (neg) {
289  if (acc < cutoff || (acc == cutoff && c > cutlim)) {
290  any = -1;
291  acc = LLONG_MIN;
292  errno = ERANGE;
293  } else {
294  any = 1;
295  acc *= base;
296  acc -= c;
297  }
298  } else {
299  if (acc > cutoff || (acc == cutoff && c > cutlim)) {
300  any = -1;
301  acc = LLONG_MAX;
302  errno = ERANGE;
303  } else {
304  any = 1;
305  acc *= base;
306  acc += c;
307  }
308  }
309  }
310  if (endptr != 0)
311  *endptr = any ? const_cast<char *>(s - 1) : const_cast<char *>(nptr);
312  return (acc);
313  }
314 
315  #define HAVE_STRTOLL 1
316 #endif
317 
318 #ifndef HAVE_STRTOULL
319  #define strtoull c99_strtoull
320 
321  #include <cctype>
322  #include <cerrno>
323  #include <climits>
324 
325  #ifndef ULLONG_MAX
326  #define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL
327  #endif
328 
337  static unsigned long long c99_strtoull(const char *nptr, char **endptr, int base) {
338  const char *s;
339  unsigned long long acc, cutoff;
340  int c;
341  int neg, any, cutlim;
342 
343  /*
344  * See c99_strtoll() for comments as to the logic used.
345  */
346  s = nptr;
347  do {
348  c = (unsigned char) *s++;
349  } while (isspace(c));
350  if (c == '-') {
351  neg = 1;
352  c = *s++;
353  } else {
354  neg = 0;
355  if (c == '+')
356  c = *s++;
357  }
358  if ((base == 0 || base == 16) &&
359  c == '0' && (*s == 'x' || *s == 'X')) {
360  c = s[1];
361  s += 2;
362  base = 16;
363  }
364  if (base == 0)
365  base = c == '0' ? 8 : 10;
366 
367  cutoff = ULLONG_MAX / (unsigned long long)base;
368  cutlim = ULLONG_MAX % (unsigned long long)base;
369  for (acc = 0, any = 0;; c = (unsigned char) *s++) {
370  if (isdigit(c))
371  c -= '0';
372  else if (isalpha(c))
373  c -= isupper(c) ? 'A' - 10 : 'a' - 10;
374  else
375  break;
376  if (c >= base)
377  break;
378  if (any < 0)
379  continue;
380  if (acc > cutoff || (acc == cutoff && c > cutlim)) {
381  any = -1;
382  acc = ULLONG_MAX;
383  errno = ERANGE;
384  } else {
385  any = 1;
386  acc *= static_cast<unsigned long long>(base);
387  acc += c;
388  }
389  }
390  if (neg && any > 0)
391  acc = -acc;
392  if (endptr != 0)
393  *endptr = any ? const_cast<char *>(s - 1) : const_cast<char *>(nptr);
394  return (acc);
395  }
396 
397  #define HAVE_STRTOULL 1
398 #endif
399 
400 // Compatibility macro for dealing with the explicit bool cast problem.
401 #if __cplusplus < 201103L
402  #define XOREOS_EXPLICIT_OPERATOR_CONV
403 #else
404  #define XOREOS_EXPLICIT_OPERATOR_CONV explicit
405 #endif
406 
407 //
408 // Fallbacks / default values for various special macros
409 //
410 #ifndef FORCEINLINE
411  #define FORCEINLINE inline
412 #endif
413 
414 #ifndef STRINGBUFLEN
415  #define STRINGBUFLEN 1024
416 #endif
417 
418 #ifndef MAXPATHLEN
419  #define MAXPATHLEN 256
420 #endif
421 
422 #ifndef IGNORE_UNUSED_VARIABLES
423  #define IGNORE_UNUSED_VARIABLES
424 #endif
425 
426 #endif // COMMON_SYSTEM_H
Compiler-specific defines to declare a function non-returning.
#define LLONG_MAX
Definition: system.h:202
static FORCEINLINE float c99_strtof(const char *nptr, char **endptr)
Definition: system.h:187
static long long c99_strtoll(const char *nptr, char **endptr, int base)
Convert a string to a long long.
Definition: system.h:217
static unsigned long long c99_strtoull(const char *nptr, char **endptr, int base)
Convert a string to an unsigned long long.
Definition: system.h:337
#define LLONG_MIN
Definition: system.h:206
#define ULLONG_MAX
Definition: system.h:326
Compiler-specific defines to mark an implicit switch-case fallthrough.
#define FORCEINLINE
Definition: system.h:411