Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

genwrap.h 11.9 KB
Newer Older
1 2 3 4 5 6
/* General cross-platform development wrappers */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
 *																			*
9 10
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
11 12
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
13 14
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
15 16 17 18 19 20 21 22 23 24 25
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * 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
26
#include <string.h>		/* strerror() */
27
#include <time.h>		/* clock_t */
28
#include "gen_defs.h"	/* ulong */
29
#include "wrapdll.h"	/* DLLEXPORT and */
30

31
#if defined(__unix__)
32
	#include <sched.h>		/* sched_yield */
33
	#include <time.h>	/* clock_t */
34
	#include <sys/time.h>	/* struct timeval */
deuce's avatar
deuce committed
35
	#include <strings.h>	/* strcasecmp() */
36
	#include <unistd.h>		/* usleep */
rswindell's avatar
rswindell committed
37

38
	#ifdef XPDEV_THREAD_SAFE
39
		#include <pthread.h>/* Check for GNU PTH libs */
40 41 42
		#ifdef _PTH_PTHREAD_H_
			#include <pth.h>
		#endif
rswindell's avatar
rswindell committed
43
		#define GetCurrentThreadId()	pthread_self()
44
	#endif
45 46
#elif defined(_WIN32)
	#include <process.h>	/* getpid() */
47 48 49
	#ifndef __MINGW32__
        typedef DWORD pid_t;
	#endif
50 51
#endif

52 53 54 55 56
#if !defined(_WIN32)
	/* Simple Win32 function equivalents */
	#define GetCurrentProcessId()		getpid()
#endif

57 58 59 60 61 62 63
/* utime() support */
#if defined(_MSC_VER) || defined(__WATCOMC__)
	#include <sys/utime.h>
#else
	#include <utime.h>
#endif

64
#if defined(__cplusplus)
65 66
extern "C" {
#endif
67 68 69 70 71 72 73 74 75 76 77

/*
 * 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)
78 79
#elif defined(_WIN32)
#include <malloc.h>
80
#endif
81 82 83 84 85 86 87 88

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

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

89
	#define DESCRIBE_COMPILER(str) SAFEPRINTF2(str,"BCC %X.%02X" \
90
		,__BORLANDC__>>8,__BORLANDC__&0xff);
91 92 93

#elif defined(_MSC_VER)

94
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"MSC %u", _MSC_VER);
95

96 97 98 99 100 101 102 103 104 105
#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__);

106 107
#elif defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)

108
	#define DESCRIBE_COMPILER(str) SAFEPRINTF3(str,"GCC %u.%u.%u" \
109 110 111 112
		,__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);

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

113
	#define DESCRIBE_COMPILER(str) SAFEPRINTF2(str,"GCC %u.%u" \
114 115
		,__GNUC__,__GNUC_MINOR__);

rswindell's avatar
rswindell committed
116 117
#elif defined(__WATCOMC__)

118
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"WATC %d" \
rswindell's avatar
rswindell committed
119 120
		,__WATCOMC__);

121 122
#elif defined(__DMC__)	/* Digital Mars C/C++ */

123
	#define DESCRIBE_COMPILER(str) SAFEPRINTF(str,"DMC %X.%02X" \
124
		,__DMC__>>8,__DMC__&0xff);
125

126 127
#else /* Unknown compiler */

128
	#define DESCRIBE_COMPILER(str) SAFECOPY(str,"UNKNOWN COMPILER");
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

#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"
149 150
#elif defined(__OpenBSD__)
	#define PLATFORM_DESC	"OpenBSD"
deuce's avatar
deuce committed
151 152
#elif defined(__NetBSD__)
	#define PLATFORM_DESC	"NetBSD"
deuce's avatar
deuce committed
153
#elif defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
154
	#define PLATFORM_DESC	"MacOSX"
155 156
#elif defined(BSD)
	#define PLATFORM_DESC	"BSD"
157 158 159 160
#elif defined(__solaris__)
	#define PLATFORM_DESC	"Solaris"
#elif defined(__sun__)
	#define PLATFORM_DESC	"SunOS"
161 162
#elif defined(__gnu__)
	#define PLATFORM_DESC	"GNU/Hurd"
deuce's avatar
deuce committed
163 164
#elif defined(__QNX__)
	#define PLATFORM_DESC	"QNX"
165 166
#elif defined(__unix__)
	#define PLATFORM_DESC	"Unix"
deuce's avatar
deuce committed
167 168
#elif defined(__HAIKU__)
	#define PLATFORM_DESC	"Haiku"
169
#else
170
	#error "Need to describe target platform"
171 172
#endif

rswindell's avatar
rswindell committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#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"
189
#elif __ARM_ARCH == 5 || _M_ARM == 5
190
	#define ARCHITECTURE_DESC "armv5"
191
#elif __ARM_ARCH == 6 || _M_ARM == 6
192
	#define ARCHITECTURE_DESC "armv6"
193
#elif __ARM_ARCH == 7 || _M_ARM == 7
194
	#define ARCHITECTURE_DESC "armv7"
195 196
#elif __ARM_ARCH == 8 || _M_ARM == 8 
	#define ARCHITECTURE_DESC "armv8"
197 198
#elif defined(__aarch64__)
	#define ARCHITECTURE_DESC "arm64"
rswindell's avatar
rswindell committed
199 200 201 202 203 204 205 206 207 208
#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

209 210 211 212
/*********************/
/* String Functionss */
/*********************/

213 214 215
#ifndef USE_SNPRINTF
	#define snprintf		safe_snprintf
#endif
216

217
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__)
218 219 220
#if !defined(snprintf)
	#define snprintf		_snprintf
#endif
221
	#define vsnprintf		_vsnprintf
222
	#define NEEDS_STRLCPY
223 224
#endif

rswindell's avatar
rswindell committed
225 226 227 228 229
#if defined(__WATCOMC__)
	#define vsnprintf(s,l,f,a)	vsprintf(s,f,a)
#endif

#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
230
	DLLEXPORT char* ultoa(ulong, char*, int radix);
231 232 233
#endif

#if defined(__unix__)
234 235 236
	DLLEXPORT char*	strupr(char* str);
	DLLEXPORT char*	strlwr(char* str);
	DLLEXPORT char* strrev(char* str);
237
	#if !defined(stricmp)
238 239
		#define stricmp			strcasecmp
		#define strnicmp		strncasecmp
240 241 242
	#endif
#endif

243 244 245 246
#if defined(NEEDS_STRLCPY)
	size_t strlcpy(char *dst, const char *src, size_t size);
#endif

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

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

260
#define STRERROR(x)		strerror(x)
261

262
/* Re-entrant version of strerror() */
263
DLLEXPORT char*		safe_strerror(int errnum, char* buf, size_t buflen);
264

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

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

#if defined(_WIN32)

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

#elif defined(__OS2__)

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

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

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

302
	#define YIELD()			SLEEP(1)
303

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

	/*
	 * 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

333 334 335

#else	/* Unsupported OS */

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

#endif
339

340 341 342 343 344 345 346
/* 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

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

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

353
/* Mimic the Borland randomize() and random() CRTL functions */
354 355 356 357 358 359 360 361
DLLEXPORT void		xp_randomize(void);
DLLEXPORT long		xp_random(int);

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

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

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

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

392 393
DLLEXPORT BOOL		check_pid(pid_t);
DLLEXPORT BOOL		terminate_pid(pid_t);
394

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

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