picrin/lib/include/picrin/setup.h

487 lines
8.8 KiB
C

/**
* See Copyright Notice in picrin.h
*/
#include "picconf.h"
#ifndef PIC_USE_LIBC
# define PIC_USE_LIBC 1
#endif
#ifndef PIC_USE_PORT
# define PIC_USE_PORT 1
#endif
#ifndef PIC_USE_CALLCC
# define PIC_USE_CALLCC 1
#endif
#ifndef PIC_USE_READ
# define PIC_USE_READ 1
#endif
#ifndef PIC_USE_WRITE
# define PIC_USE_WRITE 1
#endif
#ifndef PIC_USE_EVAL
# define PIC_USE_EVAL 1
#endif
#ifndef PIC_USE_FILE
# define PIC_USE_FILE 1
#endif
#ifndef PIC_USE_ERROR
# define PIC_USE_ERROR 1
#endif
#if !PIC_USE_PORT && PIC_USE_READ
# error PIC_USE_READ requires PIC_USE_PORT
#endif
#if !PIC_USE_PORT && PIC_USE_WRITE
# error PIC_USE_WRITE requires PIC_USE_PORT
#endif
#if !PIC_USE_PORT && PIC_USE_FILE
# error PIC_USE_FILE requires PIC_USE_PORT
#endif
#if !PIC_USE_LIBC && PIC_USE_FILE
# error PIC_USE_FILE requires PIC_USE_LIBC
#endif
#if !PIC_USE_LIBC && PIC_USE_CALLCC
# error PIC_USE_CALLCC requires PIC_USE_LIBC
#endif
#if !PIC_USE_CALLCC && PIC_USE_ERROR
# error PIC_USE_ERROR requires PIC_USE_CALLCC
#endif
#if PIC_USE_CALLCC
# include <setjmp.h>
# define PIC_JMPBUF jmp_buf
# define PIC_SETJMP(buf) setjmp(buf)
#else
# define PIC_JMPBUF char
# define PIC_SETJMP(buf) ((void)(buf), 0)
#endif
#ifndef PIC_BUFSIZ
# define PIC_BUFSIZ 1024
#endif
#ifndef PIC_ARENA_SIZE
# define PIC_ARENA_SIZE (8 * 1024)
#endif
#ifndef PIC_HEAP_PAGE_SIZE
# define PIC_HEAP_PAGE_SIZE (4 * 1024 * 1024)
#endif
#ifndef PIC_PAGE_REQUEST_THRESHOLD
# define PIC_PAGE_REQUEST_THRESHOLD(total) ((total) * 77 / 100)
#endif
/* check compatibility */
#if __STDC_VERSION__ >= 199901L
# include <stdbool.h>
#else
# define bool char
# define true 1
# define false 0
#endif
#if __STDC_VERSION__ >= 199901L
# include <stddef.h>
#elif ! defined(offsetof)
# define offsetof(s,m) ((size_t)(&(((s *)0)->m) - 0))
#endif
#if __STDC_VERSION__ >= 199901L
# include <stdint.h>
#else
# if INT_MAX > 2147483640L /* imported from luaconf.h */
typedef int int32_t;
typedef unsigned int uint32_t;
# else
typedef long int32_t;
typedef unsigned long uint32_t;
# endif
#endif
#if __STDC_VERSION__ >= 201112L
# include <stdnoreturn.h>
# define PIC_NORETURN noreturn
#elif __GNUC__ || __clang__
# define PIC_NORETURN __attribute__((noreturn))
#else
# define PIC_NORETURN
#endif
/*
* normalize inline keyword; PIC_*_INLINE macros have the same semantics as c99
*/
#if __STDC_VERSION__ >= 199901L
# define PIC_STATIC_INLINE static inline
#elif __GNUC__ || __clang__
# define PIC_STATIC_INLINE static __inline__
#else
# define PIC_STATIC_INLINE static
#endif
#if defined __GNUC__ && !defined __GNUC_STDC_INLINE__ && !defined __GNUC_GNU_INLINE__
# define __GNUC_GNU_INLINE__ 1
#endif
/* PIC_INLINE does not necessarily unify identical definitions */
#if defined __GNUC_GNU_INLINE__
# define PIC_EXTERN_INLINE inline
# define PIC_INLINE extern inline
#elif __STDC_VERSION__ >= 199901L
# define PIC_EXTERN_INLINE extern inline
# define PIC_INLINE inline
#else
# define PIC_EXTERN_INLINE
# define PIC_INLINE static
#endif
#if defined(__cplusplus)
# define PIC_UNUSED(v)
#elif __GNUC__ || __clang__
# define PIC_UNUSED(v) v __attribute__((unused))
#else
# define PIC_UNUSED(v) v
#endif
#define PIC_GENSYM2_(x,y) PIC_G##x##_##y##_
#define PIC_GENSYM1_(x,y) PIC_GENSYM2_(x,y)
#if defined(__COUNTER__)
# define PIC_GENSYM(x) PIC_GENSYM1_(__COUNTER__,x)
#else
# define PIC_GENSYM(x) PIC_GENSYM1_(__LINE__,x)
#endif
#if __GNUC__
# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#if GCC_VERSION >= 40500 || __clang__
# define PIC_UNREACHABLE() (assert(false), __builtin_unreachable())
#else
# define PIC_UNREACHABLE() (assert(false))
#endif
#if __GNUC__
# undef GCC_VERSION
#endif
#define PIC_SWAP(type,a,b) PIC_SWAP_HELPER_(type, PIC_GENSYM(tmp), a, b)
#define PIC_SWAP_HELPER_(type,tmp,a,b) \
do { \
type tmp = (a); \
(a) = (b); \
(b) = tmp; \
} while (0)
#if PIC_USE_LIBC
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
#else
# define assert(v) (void)0
PIC_STATIC_INLINE int
isspace(int c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\f' || c == '\n';
}
PIC_STATIC_INLINE int
tolower(int c)
{
return ('A' <= c && c <= 'Z') ? c - 'A' + 'a' : c;
}
PIC_STATIC_INLINE int
isdigit(int c)
{
return '0' <= c && c <= '9';
}
PIC_STATIC_INLINE char *
strchr(const char *s, int c)
{
do {
if (*s == c)
return (char *)s;
} while (*s++ != '\0');
return NULL;
}
PIC_STATIC_INLINE size_t
strlen(const char *s)
{
size_t l = 0;
while (*s++) {
l++;
}
return l;
}
PIC_STATIC_INLINE int
strcmp(const char *s1, const char *s2)
{
while (*s1 && *s1 == *s2) {
s1++;
s2++;
}
return (unsigned)*s1 - (unsigned)*s2;
}
PIC_STATIC_INLINE long
strtol(const char *nptr, char **endptr, int base)
{
long l = 0;
char c;
int n;
while (1) {
c = *nptr;
if ('0' <= c && c <= '9')
n = c - '0';
else if ('a' <= c && c <= 'z')
n = c - 'a' + 10;
else if ('A' <= c && c <= 'Z')
n = c - 'A' + 10;
else
goto exit;
if (base <= n)
goto exit;
l = l * base + n;
nptr++;
}
exit:
if (endptr)
*endptr = (char *)nptr;
return l;
}
PIC_STATIC_INLINE void *
memset(void *s, int n, size_t c)
{
char *p = s;
while (c-- > 0) {
*p++ = n;
}
return s;
}
PIC_STATIC_INLINE void *
memcpy(void *dst, const void *src, size_t n)
{
const char *s = src;
char *d = dst;
while (n-- > 0) {
*d++ = *s++;
}
return d;
}
PIC_STATIC_INLINE void *
memmove(void *dst, const void *src, size_t n)
{
const char *s = src;
char *d = dst;
if (d <= s || d >= s + n) {
memcpy(dst, src, n);
} else {
s += n;
d += n;
while (n-- > 0) {
*--d = *--s;
}
}
return d;
}
PIC_STATIC_INLINE int
memcmp(const void *b1, const void *b2, size_t n)
{
const char *s1 = b1, *s2 = b2;
while (*s1 == *s2 && n-- > 0) {
s1++;
s2++;
}
return (unsigned)*s1 - (unsigned)*s2;
}
PIC_STATIC_INLINE char *
strcpy(char *dst, const char *src)
{
char *d = dst;
while ((*dst++ = *src++) != 0);
return d;
}
PIC_STATIC_INLINE double
atof(const char *nptr)
{
int c;
double f, g, h;
int exp, s, i, e;
unsigned u;
/* note that picrin_read always assures that *nptr is a digit, never a '+' or '-' */
/* in other words, the result of atof will always be positive */
/* mantissa */
/* pre '.' */
u = *nptr++ - '0';
while (isdigit(c = *nptr)) {
u = u * 10 + (*nptr++ - '0');
}
if (c == '.') {
nptr++;
/* after '.' */
g = 0, e = 0;
while (isdigit(c = *nptr)) {
g = g * 10 + (*nptr++ - '0');
e++;
}
h = 1.0;
while (e-- > 0) {
h /= 10;
}
f = u + g * h;
}
else {
f = u;
}
/* suffix, i.e., exponent */
s = 0;
exp = 0;
c = *nptr;
if (c == 'e' && c == 'E') {
nptr++;
switch ((c = *nptr++)) {
case '-':
s = 1;
case '+':
c = *nptr++;
default:
exp = c - '0';
while (isdigit(c = *nptr)) {
exp = exp * 10 + (*nptr++ - '0');
}
}
}
e = 10;
for (i = 0; exp; ++i) {
if ((exp & 1) != 0) {
f = s ? f / e : (f * e);
}
e *= e;
exp >>= 1;
}
return f;
}
#endif
PIC_STATIC_INLINE double
pic_atod(const char *str)
{
return atof(str);
}
#if PIC_USE_FILE
# include <stdio.h>
#endif
#if PIC_USE_LIBC
PIC_STATIC_INLINE void
pic_dtoa(double dval, char *buf)
{
sprintf(buf, "%g", dval);
}
#else
PIC_STATIC_INLINE void
pic_dtoa(double dval, char *buf)
{
# define fabs(x) ((x) >= 0 ? (x) : -(x))
long lval, tlval;
int ival;
int scnt, ecnt, cnt = 0;
if (dval < 0) {
dval = -dval;
buf[cnt++] = '-';
}
lval = tlval = (long)dval;
scnt = cnt;
do {
buf[cnt++] = '0' + (tlval % 10);
} while ((tlval /= 10) != 0);
ecnt = cnt;
while (scnt < ecnt) {
char c = buf[scnt];
buf[scnt++] = buf[--ecnt];
buf[ecnt] = c;
}
buf[cnt++] = '.';
dval -= lval;
if ((ival = fabs(dval) * 1e4 + 0.5) == 0) {
buf[cnt++] = '0';
buf[cnt++] = '0';
buf[cnt++] = '0';
buf[cnt++] = '0';
} else {
if (ival < 1000) buf[cnt++] = '0';
if (ival < 100) buf[cnt++] = '0';
if (ival < 10) buf[cnt++] = '0';
scnt = cnt;
do {
buf[cnt++] = '0' + (ival % 10);
} while ((ival /= 10) != 0);
ecnt = cnt;
while (scnt < ecnt) {
char c = buf[scnt];
buf[scnt++] = buf[--ecnt];
buf[ecnt] = c;
}
}
buf[cnt] = 0;
}
#endif
/* optional features available? */
#if (defined(__GNUC__) || defined(__clang__)) && ! defined(__STRICT_ANSI__)
# define PIC_DIRECT_THREADED_VM 1
#else
# define PIC_DIRECT_THREADED_VM 0
#endif
#if __x86_64__ && (defined(__GNUC__) || defined(__clang__)) && ! defined(__STRICT_ANSI__)
# include <stdint.h>
# define PIC_NAN_BOXING 1
#else
# define PIC_NAN_BOXING 0
#endif