genwrap.h 12.4 KB
Newer Older
1
2
3
/* General cross-platform development wrappers */

/* $Id$ */
4
// vi: tabstop=4
5
6
7
8
9

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
10
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
11
 *																			*
12
13
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
14
15
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
16
17
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#ifndef _GENWRAP_H
#define _GENWRAP_H

#include <stdio.h>		/* sprintf */
deuce's avatar
deuce committed
41
#include <string.h>		/* strerror() */
42
#include <time.h>		/* clock_t */
43
#include "gen_defs.h"	/* ulong */
44
#include "wrapdll.h"	/* DLLEXPORT and DLLCALL */
45

46
#if defined(__unix__)
47
	#include <sched.h>		/* sched_yield */
48
	#include <time.h>	/* clock_t */
49
	#include <sys/time.h>	/* struct timeval */
deuce's avatar
deuce committed
50
	#include <strings.h>	/* strcasecmp() */
51
	#include <unistd.h>		/* usleep */
rswindell's avatar
rswindell committed
52

53
	#ifdef XPDEV_THREAD_SAFE
54
		#include <pthread.h>/* Check for GNU PTH libs */
55
56
57
		#ifdef _PTH_PTHREAD_H_
			#include <pth.h>
		#endif
rswindell's avatar
rswindell committed
58
		#define GetCurrentThreadId()	pthread_self()
59
	#endif
60
61
#elif defined(_WIN32)
	#include <process.h>	/* getpid() */
62
63
64
	#ifndef __MINGW32__
        typedef DWORD pid_t;
	#endif
65
66
#endif

67
68
69
70
71
#if !defined(_WIN32)
	/* Simple Win32 function equivalents */
	#define GetCurrentProcessId()		getpid()
#endif

72
73
74
75
76
77
78
/* utime() support */
#if defined(_MSC_VER) || defined(__WATCOMC__)
	#include <sys/utime.h>
#else
	#include <utime.h>
#endif

79
#if defined(__cplusplus)
80
81
extern "C" {
#endif
82
83
84
85
86
87
88
89
90
91
92

/*
 * The alloca() function can't be implemented in C, and on some
 * platforms it can't be implemented at all as a callable function.
 * The GNU C compiler provides a built-in alloca() which we can use;
 * On platforms where alloca() is not in libc, programs which use
 * it will fail to link when compiled with non-GNU compilers.
 */
#if __GNUC__ >= 2 || defined(__INTEL_COMPILER)
#undef  alloca  /* some GNU bits try to get cute and define this on their own */
#define alloca(sz) __builtin_alloca(sz)
93
94
#elif defined(_WIN32)
#include <malloc.h>
95
#endif
96
97
98
99
100
101
102
103

/*********************/
/* Compiler-specific */
/*********************/

/* Compiler Description */
#if defined(__BORLANDC__)

104
	#define DESCRIBE_COMPILER(str) SAFEPRINTF2(str,"BCC %X.%02X" \
105
		,__BORLANDC__>>8,__BORLANDC__&0xff);
106
107
108

#elif defined(_MSC_VER)

109
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"MSC %u", _MSC_VER);
110

111
112
113
114
115
116
117
118
119
120
#elif defined(__clang__) && defined(__clang_patchlevel__)

	#define DESCRIBE_COMPILER(str) SAFEPRINTF3(str,"Clang %u.%u.%u" \
		,__clang_major__,__clang_minor__,__clang_patchlevel__);

#elif defined(__clang__) && defined(__clang_minor__)

	#define DESCRIBE_COMPILER(str) SAFEPRINTF2(str,"Clang %u.%u" \
		,__clang_major__,__clang_minor__);

121
122
#elif defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)

123
	#define DESCRIBE_COMPILER(str) SAFEPRINTF3(str,"GCC %u.%u.%u" \
124
125
126
127
		,__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);

#elif defined(__GNUC__) && defined(__GNUC_MINOR__)

128
	#define DESCRIBE_COMPILER(str) SAFEPRINTF2(str,"GCC %u.%u" \
129
130
		,__GNUC__,__GNUC_MINOR__);

rswindell's avatar
rswindell committed
131
132
#elif defined(__WATCOMC__)

133
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"WATC %d" \
rswindell's avatar
rswindell committed
134
135
		,__WATCOMC__);

136
137
#elif defined(__DMC__)	/* Digital Mars C/C++ */

138
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"DMC %X.%02X" \
139
		,__DMC__>>8,__DMC__&0xff);
140

141
142
#else /* Unknown compiler */

143
	#define DESCRIBE_COMPILER(str) SAFECOPY(str,"UNKNOWN COMPILER");
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

#endif

/**********/
/* Macros */
/**********/

/* Target Platform Description */
#if defined(_WIN64)
	#define PLATFORM_DESC	"Win64"
#elif defined(_WIN32)
	#define PLATFORM_DESC	"Win32"
#elif defined(__OS2__)
	#define PLATFORM_DESC	"OS/2"
#elif defined(__MSDOS__)
	#define PLATFORM_DESC	"DOS"
#elif defined(__linux__)
	#define PLATFORM_DESC	"Linux"
#elif defined(__FreeBSD__)
	#define PLATFORM_DESC	"FreeBSD"
164
165
#elif defined(__OpenBSD__)
	#define PLATFORM_DESC	"OpenBSD"
deuce's avatar
deuce committed
166
167
#elif defined(__NetBSD__)
	#define PLATFORM_DESC	"NetBSD"
deuce's avatar
deuce committed
168
#elif defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
169
	#define PLATFORM_DESC	"MacOSX"
170
171
#elif defined(BSD)
	#define PLATFORM_DESC	"BSD"
172
173
174
175
#elif defined(__solaris__)
	#define PLATFORM_DESC	"Solaris"
#elif defined(__sun__)
	#define PLATFORM_DESC	"SunOS"
176
177
#elif defined(__gnu__)
	#define PLATFORM_DESC	"GNU/Hurd"
deuce's avatar
deuce committed
178
179
#elif defined(__QNX__)
	#define PLATFORM_DESC	"QNX"
180
181
#elif defined(__unix__)
	#define PLATFORM_DESC	"Unix"
deuce's avatar
deuce committed
182
183
#elif defined(__HAIKU__)
	#define PLATFORM_DESC	"Haiku"
184
#else
185
	#error "Need to describe target platform"
186
187
#endif

rswindell's avatar
rswindell committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__amd64__)
	#define ARCHITECTURE_DESC "x64"
#elif defined(__i386__) || _M_IX86 == 300
	#define ARCHITECTURE_DESC "i386"
#elif defined(__i486__) || _M_IX86 == 400
	#define ARCHITECTURE_DESC "i486"
#elif defined(__i586__) || _M_IX86 == 500
	#define ARCHITECTURE_DESC "i586"
#elif defined(__i686__) || _M_IX86 == 600
	#define ARCHITECTURE_DESC "i686"
#elif defined(__i786__) || _M_IX86 == 700
	#define ARCHITECTURE_DESC "i786"
#elif defined(_X86_) || defined(__x86__) || defined(_M_IX86)
	#define ARCHITECTURE_DESC "x86"
#elif defined(__mips__)
	#define ARCHITECTURE_DESC "mips"
#elif defined(__arm__)
	#define ARCHITECTURE_DESC "arm"
#elif defined(_M_PPC) || defined(__ppc__)
	#define ARCHITECTURE_DESC "ppc"
#elif defined(_M_IA64) || defined(__ia64__)
	#define ARCHITECTURE_DESC "ia64"
#else
	#error "Need to describe target architecture"
#endif

214
215
216
217
/*********************/
/* String Functionss */
/*********************/

218
219
220
#ifndef USE_SNPRINTF
	#define snprintf		safe_snprintf
#endif
221

222
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__)
223
224
225
#if !defined(snprintf)
	#define snprintf		_snprintf
#endif
226
	#define vsnprintf		_vsnprintf
227
228
#endif

rswindell's avatar
rswindell committed
229
230
231
232
233
#if defined(__WATCOMC__)
	#define vsnprintf(s,l,f,a)	vsprintf(s,f,a)
#endif

#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
234
235
236
237
238
239
	DLLEXPORT char* DLLCALL ultoa(ulong, char*, int radix);
#endif

#if defined(__unix__)
	DLLEXPORT char*	DLLCALL strupr(char* str);
	DLLEXPORT char*	DLLCALL strlwr(char* str);
240
	DLLEXPORT char* DLLCALL	strrev(char* str);
241
	#if !defined(stricmp)
242
243
		#define stricmp			strcasecmp
		#define strnicmp		strncasecmp
244
245
246
	#endif
#endif

247
#if defined(_WIN32)
248
249
250
	DLLEXPORT char* DLLCALL strcasestr(const char* haystack, const char* needle);
#endif

251
252
/* Skip white-space chars at beginning of string */
DLLEXPORT char*		DLLCALL skipsp(char* str);
253
254
/* Truncate white-space chars off end of string */
DLLEXPORT char*		DLLCALL truncsp(char* str);
255
256
/* Truncate white-space chars off end of every \n-terminated line in string */
DLLEXPORT char*		DLLCALL truncsp_lines(char* str);
257
258
259
/* Truncate new-line chars off end of string */
DLLEXPORT char*		DLLCALL truncnl(char* str);

260
261
262
263
264
265
#if defined(__unix__)
	#define STRERROR(x)		strerror(x)
#else
	#define STRERROR(x)		truncsp(strerror(x))
#endif

266
267
268
269
270
271
/*********************/
/* Utility Functions */
/*********************/
/* Thunking for multi-threaded specific implementations of "errno" */
DLLEXPORT int DLLCALL	get_errno(void);

272
273
274
/**********************************/
/* Common Utility Macro Functions */
/**********************************/
275
276
277

#if defined(_WIN32)

278
	#define YIELD()			Sleep(1) /* Must sleep at least 1ms to avoid 100% CPU utilization */
279
	#define	MAYBE_YIELD()	Sleep(0)
280
	#define SLEEP(x)		Sleep(x)
281
282
	#define	popen			_popen
	#define pclose			_pclose
283
	#define tzname			_tzname
284
285
286

#elif defined(__OS2__)

287
	#define YIELD()			DosSleep(1)	/* Must sleep at least 1ms to avoid 100% CPU utilization */
288
	#define	MAYBE_YIELD()	DosSleep(0)
289
	#define SLEEP(x)		DosSleep(x)
290

291
#elif defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
292

293
	#if defined(_PTH_PTHREAD_H_)
294
295
		#define SLEEP(x)		({ int sleep_msecs=x; struct timeval tv; \
								tv.tv_sec=(sleep_msecs/1000); tv.tv_usec=((sleep_msecs%1000)*1000); \
296
								pth_nap(tv); })
297
	#else
298
299
300
		#define SLEEP(x)		({	int sleep_msecs=x; struct timespec ts={0}; \
								ts.tv_sec=(sleep_msecs/1000); ts.tv_nsec=((sleep_msecs%1000)*1000000); \
								nanosleep(&ts, NULL); })
301
302
	#endif

303
	#define YIELD()			SLEEP(1)
304

305
	#if defined(XPDEV_THREAD_SAFE)
306
		#if defined(__FreeBSD__)
307
			#define MAYBE_YIELD()			pthread_yield()
308
		#elif defined(_PTH_PTHREAD_H_)
309
			#define MAYBE_YIELD()			pth_yield(NULL)
310
		#elif defined(_POSIX_PRIORITY_SCHEDULING)
311
			#define MAYBE_YIELD()			sched_yield()
312
		#else
313
			#define MAYBE_YIELD()			YIELD()
314
315
316
		#endif
	#else
		#if defined(_POSIX_PRIORITY_SCHEDULING)
317
			#define	MAYBE_YIELD()			sched_yield()
318
		#else
319
			#define MAYBE_YIELD()			YIELD()
320
321
		#endif
	#endif
322
323
324
325
326
327
328
329
330
331
332
333

	/*
	 * QNX doesn't support fork() in threaded apps (yet) using vfork() instead
	 * works, but relies on undefined behaviours not being nasty.  On most OSs
	 * vfork() will share the stack between the parent and child...
	 */
	#if defined(__QNX__)
		#define FORK()	vfork()
	#else
		#define FORK()	fork()
	#endif

334
335
336

#else	/* Unsupported OS */

337
	#error "Unsupported Target: Need some macros and/or function prototypes here."
338
339

#endif
340

341
342
343
344
345
346
347
/* Command processor/shell environment variable name */
#ifdef __unix__
	#define OS_CMD_SHELL_ENV_VAR	"SHELL"
#else	/* DOS/Windows/OS2 */
	#define OS_CMD_SHELL_ENV_VAR	"COMSPEC"
#endif

348
/* Win32 implementations of recursive (thread-safe) std C time functions on Unix */
349
#if !defined(__unix__)
350

351
	DLLEXPORT char*			DLLCALL		strtok_r(char *str, const char *delim, char **last);
352
#endif
353

354
/* Mimic the Borland randomize() and random() CRTL functions */
355
DLLEXPORT void		DLLCALL xp_randomize(void);
356
DLLEXPORT long		DLLCALL	xp_random(int);
357

358
DLLEXPORT long double  	DLLCALL	xp_timer(void);
359
DLLEXPORT char*		DLLCALL os_version(char *str);
360
DLLEXPORT char*		DLLCALL os_cmdshell(void);
361
DLLEXPORT char*		DLLCALL	lastchar(const char* str);
362
363
364
365
366
DLLEXPORT int		DLLCALL safe_snprintf(char *dst, size_t size, const char *fmt, ...)
#if defined(__GNUC__)   // Catch printf-format errors
    __attribute__ ((format (printf, 3 , 4)));            // 1 is 'this'
#endif
;
367

368
/* C string/char escape-sequence processing */
369
370
371
372
373
DLLEXPORT char*		DLLCALL c_escape_str(const char* src, char* dst, size_t maxlen, BOOL ctrl_only);
DLLEXPORT char*		DLLCALL c_escape_char(char ch);
DLLEXPORT char*		DLLCALL c_unescape_str(char* str);
DLLEXPORT char		DLLCALL c_unescape_char_ptr(const char* str, char** endptr);
DLLEXPORT char		DLLCALL c_unescape_char(char ch);
374

375
376
/* Power-of-2 byte count string parser (e.g. "100K" returns 102400 if unit is 1) */
DLLEXPORT int64_t	DLLCALL	parse_byte_count(const char*, ulong unit);
377
DLLEXPORT double	DLLCALL parse_duration(const char*);
378
DLLEXPORT char*		DLLCALL duration_to_str(double value, char* str, size_t size);
379
DLLEXPORT char*		DLLCALL duration_to_vstr(double value, char* str, size_t size);
380
DLLEXPORT char*		DLLCALL byte_count_to_str(int64_t bytes, char* str, size_t size);
381
DLLEXPORT char*		DLLCALL byte_estimate_to_str(int64_t bytes, char* str, size_t size, ulong unit, int precision);
382

383
/* Microsoft (e.g. DOS/Win32) real-time system clock API (ticks since process started) */
384
typedef		clock_t				msclock_t;
385
#if defined(_WIN32) || defined(__OS2__)
386
387
	#define		MSCLOCKS_PER_SEC	CLOCKS_PER_SEC	/* e.g. 18.2 on DOS, 1000.0 on Win32 */
	#define		msclock()			clock()
388
#else
389
390
	#define		MSCLOCKS_PER_SEC	1000
	msclock_t	msclock(void);
391
#endif
rswindell's avatar
rswindell committed
392

393
394
395
DLLEXPORT BOOL		DLLCALL check_pid(pid_t);
DLLEXPORT BOOL		DLLCALL	terminate_pid(pid_t);

396
#if defined(__cplusplus)
397
398
399
400
}
#endif

#endif	/* Don't add anything after this line */