mirror of
https://github.com/zerotier/lf.git
synced 2026-05-22 16:24:00 -07:00
389 lines
14 KiB
C
389 lines
14 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* (c)2019-2021 ZeroTier, Inc.
|
|
* https://www.zerotier.com/
|
|
*/
|
|
|
|
#ifndef ZT_LF_COMMON_H
|
|
#define ZT_LF_COMMON_H
|
|
|
|
/* Uncommment to trace DB internals -- this dumps a LOT of information! */
|
|
/* #define ZTLF_TRACE 1 */
|
|
|
|
/* Only necessary on some old 32-bit machines which aren't "officially" supported, but do it anyway. */
|
|
#ifndef _FILE_OFFSET_BITS
|
|
#define _FILE_OFFSET_BITS 64
|
|
#endif
|
|
#ifndef _LARGEFILE_SOURCE
|
|
#define _LARGEFILE_SOURCE 1
|
|
#endif
|
|
|
|
#ifndef _DEFAULT_SOURCE
|
|
#define _DEFAULT_SOURCE 1
|
|
#endif
|
|
#ifndef _BSD_SOURCE
|
|
#define _BSD_SOURCE 1
|
|
#endif
|
|
#ifndef __USE_UNIX98
|
|
#define __USE_UNIX98 1
|
|
#endif
|
|
#ifndef _POSIX_C_SOURCE
|
|
#define _POSIX_C_SOURCE 200809L
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <stdarg.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include <dirent.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifndef PATH_MAX
|
|
#define PATH_MAX 1024
|
|
#endif
|
|
|
|
/* TODO: Windows support is not complete, but we have some stubs */
|
|
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
|
|
|
|
#include <WinSock2.h>
|
|
#include <windows.h>
|
|
|
|
#ifndef __WINDOWS__
|
|
#define __WINDOWS__ 1
|
|
#endif
|
|
|
|
#define ZTLF_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop))
|
|
#define ZTLF_PATH_SEPARATOR "\\"
|
|
#define ZTLF_PATH_SEPARATOR_C '\\'
|
|
#define ZTLF_EOL "\r\n"
|
|
|
|
#else /* not Windows -------------------------------------------------- */
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <arpa/inet.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <sched.h>
|
|
|
|
#ifndef MAP_FILE /* legacy flag, not used on some platforms */
|
|
#define MAP_FILE 0
|
|
#endif
|
|
|
|
#define ZTLF_PACKED_STRUCT(D) D __attribute__((packed))
|
|
#define ZTLF_PATH_SEPARATOR "/"
|
|
#define ZTLF_PATH_SEPARATOR_C '/'
|
|
#define ZTLF_EOL "\n"
|
|
|
|
#endif /* Windows or non-Windows? ------------------------------------- */
|
|
|
|
/* Branch optimization macros if supported, otherwise these are no-ops. */
|
|
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
|
#ifndef likely
|
|
#define likely(x) __builtin_expect((x),1)
|
|
#endif
|
|
#ifndef unlikely
|
|
#define unlikely(x) __builtin_expect((x),0)
|
|
#endif
|
|
#else
|
|
#ifndef likely
|
|
#define likely(x) (x)
|
|
#endif
|
|
#ifndef unlikely
|
|
#define unlikely(x) (x)
|
|
#endif
|
|
#endif
|
|
|
|
/* Assume little-endian byte order if not defined. */
|
|
#ifndef __BYTE_ORDER__
|
|
#ifndef __ORDER_LITTLE_ENDIAN__
|
|
#define __ORDER_LITTLE_ENDIAN__ 4321
|
|
#endif
|
|
#ifndef __ORDER_BIG_ENDIAN__
|
|
#define __ORDER_BIG_ENDIAN__ 1234
|
|
#endif
|
|
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
|
#endif
|
|
|
|
#if __WORDSIZE == 64 || __SIZEOF_POINTER__ == 8 || defined(__LP64__) || defined(_M_AMD64) || defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64)
|
|
#define ZTLF_64BIT 1
|
|
#endif
|
|
|
|
/* Define a macro to byte swap 64-bit values if needed. */
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
|
#define ZTLF_htonll(n) ((uint64_t)(__builtin_bswap64((uint64_t)(n))))
|
|
#else
|
|
static inline uint64_t ZTLF_htonll(const uint64_t n)
|
|
{
|
|
return (
|
|
((n & 0x00000000000000ffULL) << 56) |
|
|
((n & 0x000000000000ff00ULL) << 40) |
|
|
((n & 0x0000000000ff0000ULL) << 24) |
|
|
((n & 0x00000000ff000000ULL) << 8) |
|
|
((n & 0x000000ff00000000ULL) >> 8) |
|
|
((n & 0x0000ff0000000000ULL) >> 24) |
|
|
((n & 0x00ff000000000000ULL) >> 40) |
|
|
((n & 0xff00000000000000ULL) >> 56)
|
|
);
|
|
}
|
|
#endif
|
|
#else
|
|
#define ZTLF_htonll(n) ((uint64_t)(n))
|
|
#endif
|
|
#define ZTLF_ntohll(n) ZTLF_htonll((n))
|
|
|
|
/* Macros to safely deal with longer values in packed structures or unaligned arrays */
|
|
#if defined(_M_AMD64) || defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
|
|
|
/* x86/x64 is an alignment honey badger, so it's fastest to just type cast and get/set primitive values. */
|
|
|
|
#define ZTLF_UNALIGNED_OKAY 1
|
|
|
|
#define ZTLF_setu16(f,v) (f) = (uint16_t)htons((uint16_t)(v))
|
|
#define ZTLF_setu32(f,v) (f) = (uint32_t)htonl((uint32_t)(v))
|
|
#define ZTLF_setu64(f,v) (f) = (uint64_t)ZTLF_htonll((uint64_t)(v))
|
|
|
|
#define ZTLF_getu16(f) ((uint16_t)ntohs((uint16_t)(f)))
|
|
#define ZTLF_getu32(f) ((uint32_t)ntohl((uint32_t)(f)))
|
|
#define ZTLF_getu64(f) ((uint64_t)ZTLF_ntohll((uint64_t)(f)))
|
|
|
|
#define ZTLF_set16(f,v) (f) = (int16_t)htons((uint16_t)(v))
|
|
#define ZTLF_set32(f,v) (f) = (int32_t)htonl((uint32_t)(v))
|
|
#define ZTLF_set64(f,v) (f) = (int64_t)ZTLF_htonll((uint64_t)(v))
|
|
|
|
#define ZTLF_get16(f) ((int16_t)ntohs((uint16_t)(f)))
|
|
#define ZTLF_get32(f) ((int32_t)ntohl((uint32_t)(f)))
|
|
#define ZTLF_get64(f) ((int64_t)ZTLF_ntohll((uint64_t)(f)))
|
|
|
|
#define ZTLF_setu16_le(f,v) (f) = ((uint16_t)(v))
|
|
#define ZTLF_setu32_le(f,v) (f) = ((uint32_t)(v))
|
|
#define ZTLF_setu64_le(f,v) (f) = ((uint64_t)(v))
|
|
|
|
#define ZTLF_getu16_le(f) ((uint16_t)(f))
|
|
#define ZTLF_getu32_le(f) ((uint32_t)(f))
|
|
#define ZTLF_getu64_le(f) ((uint64_t)(f))
|
|
|
|
#define ZTLF_set16_le(f,v) (f) = ((int16_t)(v))
|
|
#define ZTLF_set32_le(f,v) (f) = ((int32_t)(v))
|
|
#define ZTLF_set64_le(f,v) (f) = ((int64_t)(v))
|
|
|
|
#define ZTLF_get16_le(f) ((int16_t)(f))
|
|
#define ZTLF_get32_le(f) ((int32_t)(f))
|
|
#define ZTLF_get64_le(f) ((int64_t)(f))
|
|
|
|
#else /* quite a few other CPUs don't like unaligned access, so assume we can't ---------------- */
|
|
|
|
#define ZTLF_setu16(f,v) { \
|
|
const uint16_t _setu_v = (uint16_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)(_setu_v); }
|
|
#define ZTLF_setu32(f,v) { \
|
|
const uint32_t _setu_v = (uint32_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)(_setu_v); }
|
|
#define ZTLF_setu64(f,v) { \
|
|
const uint64_t _setu_v = (uint64_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 56); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 48); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 40); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 32); \
|
|
((uint8_t *)&(f))[4] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[5] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[6] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[7] = (uint8_t)(_setu_v); }
|
|
|
|
#define ZTLF_getu16(f) ( \
|
|
(((uint16_t)(((uint8_t *)&(f))[0])) << 8) | \
|
|
((uint16_t)(((uint8_t *)&(f))[1])) )
|
|
#define ZTLF_getu32(f) ( \
|
|
(((uint32_t)(((uint8_t *)&(f))[0])) << 24) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[1])) << 16) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[2])) << 8) | \
|
|
((uint32_t)(((uint8_t *)&(f))[3])) )
|
|
#define ZTLF_getu64(f) ( \
|
|
(((uint64_t)(((uint8_t *)&(f))[0])) << 56) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[1])) << 48) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[2])) << 40) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[3])) << 32) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[4])) << 24) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[5])) << 16) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[6])) << 8) | \
|
|
((uint64_t)(((uint8_t *)&(f))[7])) )
|
|
|
|
#define ZTLF_set16(f,v) { \
|
|
const uint16_t _setu_v = (uint16_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)(_setu_v); }
|
|
#define ZTLF_set32(f,v) { \
|
|
const uint32_t _setu_v = (uint32_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)(_setu_v); }
|
|
#define ZTLF_set64(f,v) { \
|
|
const uint64_t _setu_v = (uint64_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v) >> 56); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 48); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 40); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 32); \
|
|
((uint8_t *)&(f))[4] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[5] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[6] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[7] = (uint8_t)(_setu_v); }
|
|
|
|
#define ZTLF_get16(f) ((int16_t)( \
|
|
(((uint16_t)(((uint8_t *)&(f))[0])) << 8) | \
|
|
((uint16_t)(((uint8_t *)&(f))[1])) ))
|
|
#define ZTLF_get32(f) ((int32_t)( \
|
|
(((uint32_t)(((uint8_t *)&(f))[0])) << 24) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[1])) << 16) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[2])) << 8) | \
|
|
((uint32_t)(((uint8_t *)&(f))[3])) ))
|
|
#define ZTLF_get64(f) ((int64_t)( \
|
|
(((uint64_t)(((uint8_t *)&(f))[0])) << 56) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[1])) << 48) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[2])) << 40) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[3])) << 32) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[4])) << 24) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[5])) << 16) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[6])) << 8) | \
|
|
((uint64_t)(((uint8_t *)&(f))[7])) ))
|
|
|
|
#define ZTLF_setu16_le(f,v) { \
|
|
const uint16_t _setu_v = (uint16_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)((_setu_v)); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v >> 8)); }
|
|
#define ZTLF_setu32_le(f,v) { \
|
|
const uint32_t _setu_v = (uint32_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)(_setu_v); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 24); }
|
|
#define ZTLF_setu64_le(f,v) { \
|
|
const uint64_t _setu_v = (uint64_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)(_setu_v); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[4] = (uint8_t)((_setu_v) >> 32); \
|
|
((uint8_t *)&(f))[5] = (uint8_t)((_setu_v) >> 40); \
|
|
((uint8_t *)&(f))[6] = (uint8_t)((_setu_v) >> 48); \
|
|
((uint8_t *)&(f))[7] = (uint8_t)((_setu_v) >> 56); }
|
|
|
|
#define ZTLF_getu16_le(f) ( \
|
|
((uint16_t)(((uint8_t *)&(f))[0])) | \
|
|
(((uint16_t)(((uint8_t *)&(f))[1])) << 8) )
|
|
#define ZTLF_getu32_le(f) ( \
|
|
((uint32_t)(((uint8_t *)&(f))[0])) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[1])) << 8) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[2])) << 16) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[3])) << 24) )
|
|
#define ZTLF_getu64_le(f) ( \
|
|
((uint64_t)(((uint8_t *)&(f))[0])) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[1])) << 8) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[2])) << 16) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[3])) << 24) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[4])) << 32) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[5])) << 40) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[6])) << 48) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[7])) << 56) )
|
|
|
|
#define ZTLF_set16_le(f,v) { \
|
|
const uint16_t _setu_v = (uint16_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)(_setu_v); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 8); }
|
|
#define ZTLF_set32_le(f,v) { \
|
|
const uint32_t _setu_v = (uint32_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)(_setu_v); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 24); }
|
|
#define ZTLF_set64_le(f,v) { \
|
|
const uint64_t _setu_v = (uint64_t)(v); \
|
|
((uint8_t *)&(f))[0] = (uint8_t)(_setu_v); \
|
|
((uint8_t *)&(f))[1] = (uint8_t)((_setu_v) >> 8); \
|
|
((uint8_t *)&(f))[2] = (uint8_t)((_setu_v) >> 16); \
|
|
((uint8_t *)&(f))[3] = (uint8_t)((_setu_v) >> 24); \
|
|
((uint8_t *)&(f))[4] = (uint8_t)((_setu_v) >> 32); \
|
|
((uint8_t *)&(f))[5] = (uint8_t)((_setu_v) >> 40); \
|
|
((uint8_t *)&(f))[6] = (uint8_t)((_setu_v) >> 48); \
|
|
((uint8_t *)&(f))[7] = (uint8_t)((_setu_v) >> 56); }
|
|
|
|
#define ZTLF_get16_le(f) ((int16_t)( \
|
|
(((uint16_t)(((uint8_t *)&(f))[0])) << 8) | \
|
|
((uint16_t)(((uint8_t *)&(f))[1])) ))
|
|
#define ZTLF_get32_le(f) ((int32_t)( \
|
|
(((uint32_t)(((uint8_t *)&(f))[0])) << 24) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[1])) << 16) | \
|
|
(((uint32_t)(((uint8_t *)&(f))[2])) << 8) | \
|
|
((uint32_t)(((uint8_t *)&(f))[3])) ))
|
|
#define ZTLF_get64_le(f) ((int64_t)( \
|
|
((uint64_t)(((uint8_t *)&(f))[0])) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[1])) << 8) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[2])) << 16) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[3])) << 24) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[4])) << 32) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[5])) << 40) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[6])) << 48) | \
|
|
(((uint64_t)(((uint8_t *)&(f))[7])) << 56) ))
|
|
|
|
#endif /* ---------------------------------------------------------------------------------------------- */
|
|
|
|
#define ZTLF_NEG(e) (((e) <= 0) ? (e) : -(e))
|
|
#define ZTLF_POS(e) (((e) >= 0) ? (e) : -(e))
|
|
|
|
/* These values must be the same as the log levels in Go code. */
|
|
#define ZTLF_LOG_LEVEL_FATAL 0
|
|
#define ZTLF_LOG_LEVEL_WARNING 1
|
|
#define ZTLF_LOG_LEVEL_NORMAL 2
|
|
#define ZTLF_LOG_LEVEL_VERBOSE 3
|
|
#define ZTLF_LOG_LEVEL_TRACE 4
|
|
|
|
// Arguments are: level, source file, line, message, and an externally supplied logger argument.
|
|
typedef void (*LogOutputCallback)(int,const char *,int,const char *,void *);
|
|
|
|
static inline void ZTLF_L_func(LogOutputCallback logger,void *loggerArg,int level,const char *srcf,int line,const char *fmt,...)
|
|
{
|
|
va_list ap;
|
|
char msg[4096];
|
|
va_start(ap, fmt);
|
|
(void)vsnprintf(msg,sizeof(msg),fmt,ap);
|
|
va_end(ap);
|
|
msg[sizeof(msg)-1] = (char)0;
|
|
|
|
if (!srcf)
|
|
srcf = "<unknown>";
|
|
|
|
logger(level,srcf,line,msg,loggerArg);
|
|
}
|
|
|
|
#define ZTLF_L(...) ZTLF_L_func(logger,(void *)loggerArg,2,__FILE__,__LINE__,__VA_ARGS__)
|
|
#define ZTLF_L_warning(...) ZTLF_L_func(logger,(void *)loggerArg,1,__FILE__,__LINE__,__VA_ARGS__)
|
|
#define ZTLF_L_fatal(...) ZTLF_L_func(logger,(void *)loggerArg,0,__FILE__,__LINE__,__VA_ARGS__)
|
|
#define ZTLF_L_verbose(...) ZTLF_L_func(logger,(void *)loggerArg,3,__FILE__,__LINE__,__VA_ARGS__)
|
|
#ifdef ZTLF_TRACE
|
|
#define ZTLF_L_trace(...) ZTLF_L_func(logger,(void *)loggerArg,4,__FILE__,__LINE__,__VA_ARGS__)
|
|
#else
|
|
#define ZTLF_L_trace(...)
|
|
#endif
|
|
|
|
#define ZTLF_MALLOC_CHECK(m) if (unlikely(!((m)))) { fprintf(stderr,"malloc() failed!" ZTLF_EOL); fflush(stderr); abort(); }
|
|
|
|
#endif
|