moving along slowly
[retroray] / src / util.c
1 /*
2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include "util.h"
23
24 void *malloc_nf_impl(size_t sz, const char *file, int line)
25 {
26         void *p;
27         if(!(p = malloc(sz))) {
28                 fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)sz);
29                 abort();
30         }
31         return p;
32 }
33
34 void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line)
35 {
36         void *p;
37         if(!(p = calloc(num, sz))) {
38                 fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)(num * sz));
39                 abort();
40         }
41         return p;
42 }
43
44 void *realloc_nf_impl(void *p, size_t sz, const char *file, int line)
45 {
46         if(!(p = realloc(p, sz))) {
47                 fprintf(stderr, "%s:%d failed to realloc %lu bytes\n", file, line, (unsigned long)sz);
48                 abort();
49         }
50         return p;
51 }
52
53 char *strdup_nf_impl(const char *s, const char *file, int line)
54 {
55         int len;
56         char *res;
57
58         len = strlen(s);
59         if(!(res = malloc(len + 1))) {
60                 fprintf(stderr, "%s:%d failed to duplicate string\n", file, line);
61                 abort();
62         }
63         memcpy(res, s, len + 1);
64         return res;
65 }
66
67
68 int match_prefix(const char *str, const char *prefix)
69 {
70         while(*str && *prefix) {
71                 if(*str++ != *prefix++) {
72                         return 0;
73                 }
74         }
75         return *prefix ? 0 : 1;
76 }
77
78 #if defined(__APPLE__) && !defined(TARGET_IPHONE)
79 #include <xmmintrin.h>
80
81 void enable_fpexcept(void)
82 {
83         unsigned int bits;
84         bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW;
85         _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~bits);
86 }
87
88 void disable_fpexcept(void)
89 {
90         unsigned int bits;
91         bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW;
92         _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | bits);
93 }
94
95 #elif defined(__GLIBC__) && !defined(__MINGW32__)
96 #ifndef __USE_GNU
97 #define __USE_GNU
98 #endif
99 #include <fenv.h>
100
101 void enable_fpexcept(void)
102 {
103         feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
104 }
105
106 void disable_fpexcept(void)
107 {
108         fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
109 }
110
111 #elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__)
112 #include <float.h>
113
114 #if defined(__MINGW32__) && !defined(_EM_OVERFLOW)
115 /* if gcc's float.h gets precedence, the mingw MSVC includes won't be declared */
116 #define _MCW_EM                 0x8001f
117 #define _EM_INVALID             0x10
118 #define _EM_ZERODIVIDE  0x08
119 #define _EM_OVERFLOW    0x04
120 unsigned int __cdecl _clearfp(void);
121 unsigned int __cdecl _controlfp(unsigned int, unsigned int);
122 #elif defined(__WATCOMC__)
123 #define _clearfp        _clear87
124 #define _controlfp      _control87
125 #endif
126
127 void enable_fpexcept(void)
128 {
129         _clearfp();
130         _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM);
131 }
132
133 void disable_fpexcept(void)
134 {
135         _clearfp();
136         _controlfp(_controlfp(0, 0) | (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM);
137 }
138 #else
139 void enable_fpexcept(void) {}
140 void disable_fpexcept(void) {}
141 #endif