]> icculus.org git repositories - taylor/freespace2.git/blob - src/platform/unix.cpp
SDL2 port - stage 2
[taylor/freespace2.git] / src / platform / unix.cpp
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10
11 #include "pstypes.h"
12
13 // use system versions of this stuff in here rather than the vm_* versions
14 #undef malloc
15 #undef free
16 #undef strdup
17
18
19 #define MAX_LINE_WIDTH 128
20
21 void strlwr (char * str)
22 {
23         while (*str) {*str = tolower (*str); str++; }
24 }
25
26 void strupr (char * str)
27 {
28         while (*str) {*str = toupper (*str); str++; }
29 }
30
31 int filelength (int fd)
32 {
33         struct stat buf;
34         if (fstat (fd, &buf) == -1)
35                 return -1;
36                 
37         return buf.st_size;
38 }
39
40 unsigned long _beginthread (void (*pfuncStart)(void *), unsigned unStackSize, void* pArgList)
41 {
42         STUB_FUNCTION;
43         
44         return 0;
45 }
46
47 void Sleep (int mili)
48 {
49 #ifdef __APPLE__
50         // ughh, SDL_Delay causes a slowdown on Tiger for some reason and though I hate
51         // doing this, even the few Apple examples I've seen do this over what SDL_Delay does.
52         uint then = SDL_GetTicks() + mili;
53
54         while ( then > SDL_GetTicks() );
55 #else
56         SDL_Delay( long(mili) );
57 #endif
58 }
59
60 void OutputDebugString (const char *str)
61 {
62         fprintf(stderr, "OutputDebugString: %s\n", str);
63 }
64
65 int WSAGetLastError()
66 {
67         return errno;
68 }
69
70 // make specified directory, recursively
71 // NOTE: since this is for use with CFILE this code assumes that there will be a trailing '/'
72 //       or a trailing filename.  any directory name not followed by a '/' will be considered a file
73 int _mkdir(const char *path)
74 {
75         int status = 1;         // if we don't ever call mkdir() to update this then assume we are in error
76         char *c, tmp_path[MAX_PATH] = { 0 };
77
78         strncpy(tmp_path, path, MAX_PATH-1);
79
80         c = &tmp_path[1];
81
82         while (c++) {
83                 c = strchr(c, '/');
84
85                 if (c) {
86                         *c = '\0';
87
88                         status = mkdir(tmp_path, 0700);
89
90 #ifndef NDEBUG
91                         int m_error = errno;
92
93                         if (status && (m_error != EEXIST) ) {
94                                 Warning(__FILE__, __LINE__, "Cannot mkdir %s: %s", tmp_path, strerror(m_error));
95                         }
96 #endif
97
98                         *c = '/';
99                 }
100         }
101
102         return status;
103 }
104
105 void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
106 {
107         if (path == NULL)
108                 return;
109
110         /* fs2 only uses fname */
111         if (fname != NULL) {
112                 const char *ls = strrchr(path, '/');
113                 if (ls != NULL) {
114                         ls++;           // move past '/'
115                 } else {
116                         ls = path;
117                 }
118         
119                 const char *lp = strrchr(path, '.');
120                 if (lp == NULL) {
121                         lp = ls + strlen(ls);   // move to the end
122                 }
123         
124                 int dist = lp-ls;
125                 if (dist > (_MAX_FNAME-1))
126                         dist = _MAX_FNAME-1;
127                 
128                 strncpy(fname, ls, dist);
129                 fname[dist] = 0;        // add null, just in case
130         }
131 }
132
133 int MulDiv(int a, int b, int c)
134 {
135         /* slow long long version */
136         __extension__ long long aa = a;
137         __extension__ long long bb = b;
138         __extension__ long long cc = c;
139         
140         __extension__ long long dd = aa * bb;
141         __extension__ long long ee = dd / cc;
142         
143         int retr = (int) ee;
144         
145         return retr;
146 }
147
148 /* mem debug junk */
149 #ifndef NDEBUG
150 //#define WANT_DEBUG
151 #endif
152
153 int TotalRam = 0;
154
155 #ifdef WANT_DEBUG
156 typedef struct RAM {
157         void *addr;
158         int size;
159         
160         char *file;
161         int line;
162         
163         RAM *next;
164 } RAM;
165
166 static RAM *RamTable;
167 #endif
168
169 #ifndef NDEBUG
170 void vm_free(void* ptr, const char *file, int line)
171 #else
172 void vm_free(void* ptr)
173 #endif
174 {
175 #ifdef WANT_DEBUG
176         fprintf(stderr, "FREE: %s:%d addr = %p\n", file, line, ptr);
177         
178         RAM *item = RamTable;
179         RAM **mark = &RamTable;
180         
181         while (item != NULL) {
182                 if (item->addr == ptr) {
183                         RAM *tmp = item;
184                         
185                         *mark = item->next;
186                         
187                         free(tmp->addr);
188                         free(tmp);
189                         
190                         return;
191                 }
192                 
193                 mark = &(item->next);
194                 
195                 item = item->next;
196         }
197         
198         fprintf(stderr, "ERROR: vm_free caught invalid free: addr = %p, file = %s/%d\n", ptr, file, line);
199 #else   
200         free(ptr);
201 #endif
202 }
203
204 #ifndef NDEBUG
205 void *vm_malloc(int size, const char *file, int line)
206 #else
207 void *vm_malloc(int size)
208 #endif
209 {
210 #ifdef WANT_DEBUG
211         fprintf(stderr, "MALLOC: %s:%d %d bytes\n", file, line, size);
212         
213         RAM *next = (RAM *)malloc(sizeof(RAM));
214         
215         next->addr = malloc(size);
216         next->size = size;
217         next->file = file;
218         next->line = line;
219         
220         next->next = RamTable;
221         RamTable = next;
222         
223         return next->addr;
224 #else
225         return malloc(size);
226 #endif  
227 }
228
229 #ifndef NDEBUG
230 char *vm_strdup(char const* str, const char *file, int line)
231 #else
232 char *vm_strdup(char const* str)
233 #endif
234 {
235 #ifdef WANT_DEBUG
236         fprintf(stderr, "STRDUP: %s:%d\n", file, line);
237         
238         RAM *next = (RAM *)malloc(sizeof(RAM));
239         
240         next->addr = strdup(str);
241         next->size = strlen(str)+1;
242         next->file = file;
243         next->line = line;
244         
245         next->next = RamTable;
246         RamTable = next;
247         
248         return (char *)next->addr;
249 #else
250         return strdup(str);
251 #endif
252 }
253
254 void vm_dump()
255 {
256 #ifdef WANT_DEBUG
257         int i = 0;
258         int mem = 0;
259         fprintf(stderr, "\nDumping allocated memory:\n");
260         
261         RAM *ptr = RamTable;
262         while (ptr) {
263                 fprintf(stderr, "%d: file: %s:%d: addr:%p size:%d\n", i, ptr->file, ptr->line, ptr->addr, ptr->size);
264                 mem += ptr->size;
265                 ptr = ptr->next;
266                 i++;
267         }
268         
269         fprintf(stderr, "\nTotal of %d left-over bytes from %d allocations\n", mem, i);
270 #endif  
271 }
272
273 void windebug_memwatch_init()
274 {
275         TotalRam = 0;
276 }
277
278 /* error message debugging junk */
279 /*
280 int Log_debug_output_to_file = 0;
281
282 void load_filter_info(void)
283 {
284 //      STUB_FUNCTION;
285 }
286
287 void outwnd_printf(char* id, char* format, ...)
288 {
289         char tmp[MAX_LINE_WIDTH*4];
290         va_list args;
291
292         va_start (args, format);
293         vsprintf (tmp, format, args);
294         va_end(args);
295         fprintf (stderr, "%s: %s\n", id, tmp);
296 }
297
298 void outwnd_printf2(char* format, ...)
299 {
300         char tmp[MAX_LINE_WIDTH*4];
301         va_list args;
302
303         va_start (args, format);
304         vsprintf (tmp, format, args);
305         va_end(args);
306         fprintf (stderr, "General: %s", tmp);
307 }
308
309 void outwnd_close()
310 {
311 //      STUB_FUNCTION;
312 }
313 */
314
315 extern void gr_force_windowed();
316
317 void Warning( const char * filename, int line, const char * format, ... )
318 {
319         char tmp[MAX_LINE_WIDTH*4] = { 0 };
320         char tmp2[MAX_LINE_WIDTH*4] = { 0 };
321         va_list args;
322
323         va_start(args, format);
324         vsnprintf(tmp, sizeof(tmp), format, args);
325         va_end(args);
326 //      fprintf (stderr, "Warning: (%s:%d): %s\n", filename, line, tmp);
327         snprintf(tmp2, sizeof(tmp2), "Warning: %s\n\nFile:%s\nLine: %d", tmp, filename, line);
328
329         gr_force_windowed();
330
331         SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning!", tmp2, NULL);
332 }
333
334 void Error( const char * filename, int line, const char * format, ... )
335 {
336         char tmp[MAX_LINE_WIDTH*4] = { 0 };
337         char tmp2[MAX_LINE_WIDTH*4] = { 0 };
338         va_list args;
339
340         va_start (args, format);
341         vsnprintf (tmp, sizeof(tmp), format, args);
342         va_end(args);
343 //      fprintf (stderr, "Error: (%s:%d): %s\n", filename, line, tmp);
344         snprintf(tmp2, sizeof(tmp2), "Error: %s\n\nFile:%s\nLine: %d", tmp, filename, line);
345
346         gr_force_windowed();
347
348         SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error!", tmp2, NULL);
349
350         exit (1);
351 }
352
353 void WinAssert(const char * text, const char *filename, int line)
354 {
355         fprintf (stderr, "Assertion: (%s:%d) %s\n", filename, line, text);
356 //      exit(1);
357 }