X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=include%2Fplatform.h;h=2b57cd5a2b1f623d5970bad76874cff5879756ec;hb=80c5b6893d4708b3683ad9a51c990a326a8f1dff;hp=1706de0bf201298892b07624ebb5ce2b8892c506;hpb=9e58921e7ef9f4a9eaad1c672e94e685d019425d;p=oweals%2Fbusybox.git diff --git a/include/platform.h b/include/platform.h index 1706de0bf..2b57cd5a2 100644 --- a/include/platform.h +++ b/include/platform.h @@ -1,11 +1,29 @@ /* vi: set sw=4 ts=4: */ /* - Copyright 2006, Bernhard Fischer + * Copyright 2006, Bernhard Reutner-Fischer + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#ifndef BB_PLATFORM_H +#define BB_PLATFORM_H 1 - Licensed under the GPL v2 or later, see the file LICENSE in this tarball. -*/ -#ifndef __PLATFORM_H -#define __PLATFORM_H 1 +/* Assume all these functions exist by default. Platforms where it is not + * true will #undef them below. + */ +#define HAVE_CLEARENV 1 +#define HAVE_FDATASYNC 1 +#define HAVE_DPRINTF 1 +#define HAVE_MEMRCHR 1 +#define HAVE_MKDTEMP 1 +#define HAVE_PTSNAME_R 1 +#define HAVE_SETBIT 1 +#define HAVE_SIGHANDLER_T 1 +#define HAVE_STPCPY 1 +#define HAVE_STRCASESTR 1 +#define HAVE_STRCHRNUL 1 +#define HAVE_STRSEP 1 +#define HAVE_STRSIGNAL 1 +#define HAVE_VASPRINTF 1 /* Convenience macros to test the version of gcc. */ #undef __GNUC_PREREQ @@ -17,9 +35,9 @@ #endif /* __restrict is known in EGCS 1.2 and above. */ -#if !__GNUC_PREREQ (2,92) +#if !__GNUC_PREREQ(2,92) # ifndef __restrict -# define __restrict /* Ignore */ +# define __restrict # endif #endif @@ -27,7 +45,7 @@ macros freely, and know that they will come into play for the version of gcc in which they are supported. */ -#if !__GNUC_PREREQ (2,7) +#if !__GNUC_PREREQ(2,7) # ifndef __attribute__ # define __attribute__(x) # endif @@ -36,162 +54,232 @@ #undef inline #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L /* it's a keyword */ +#elif __GNUC_PREREQ(2,7) +# define inline __inline__ #else -# if __GNUC_PREREQ (2,7) -# define inline __inline__ -# else -# define inline -# endif +# define inline #endif #ifndef __const # define __const const #endif -# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -# define ATTRIBUTE_PACKED __attribute__ ((__packed__)) -# define ATTRIBUTE_ALIGNED(m) __attribute__ ((__aligned__(m))) -# if __GNUC_PREREQ (3,0) -# define ALWAYS_INLINE __attribute__ ((always_inline)) inline +#define UNUSED_PARAM __attribute__ ((__unused__)) +#define NORETURN __attribute__ ((__noreturn__)) +/* "The malloc attribute is used to tell the compiler that a function + * may be treated as if any non-NULL pointer it returns cannot alias + * any other pointer valid when the function returns. This will often + * improve optimization. Standard functions with this property include + * malloc and calloc. realloc-like functions have this property as long + * as the old pointer is never referred to (including comparing it + * to the new pointer) after the function returns a non-NULL value." + */ +#define RETURNS_MALLOC __attribute__ ((malloc)) +#define PACKED __attribute__ ((__packed__)) +#define ALIGNED(m) __attribute__ ((__aligned__(m))) + +/* __NO_INLINE__: some gcc's do not honor inlining! :( */ +#if __GNUC_PREREQ(3,0) && !defined(__NO_INLINE__) +# define ALWAYS_INLINE __attribute__ ((always_inline)) inline /* I've seen a toolchain where I needed __noinline__ instead of noinline */ -# define NOINLINE __attribute__((__noinline__)) -# if !ENABLE_WERROR -# define ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) -# define ATTRIBUTE_UNUSED_RESULT __attribute__ ((warn_unused_result)) -# else -# define ATTRIBUTE_DEPRECATED /* n/a */ -# define ATTRIBUTE_UNUSED_RESULT /* n/a */ -# endif +# define NOINLINE __attribute__((__noinline__)) +# if !ENABLE_WERROR +# define DEPRECATED __attribute__ ((__deprecated__)) +# define UNUSED_PARAM_RESULT __attribute__ ((warn_unused_result)) # else -# define ALWAYS_INLINE inline /* n/a */ -# define NOINLINE /* n/a */ -# define ATTRIBUTE_DEPRECATED /* n/a */ -# define ATTRIBUTE_UNUSED_RESULT /* n/a */ +# define DEPRECATED +# define UNUSED_PARAM_RESULT # endif +#else +# define ALWAYS_INLINE inline +# define NOINLINE +# define DEPRECATED +# define UNUSED_PARAM_RESULT +#endif /* -fwhole-program makes all symbols local. The attribute externally_visible forces a symbol global. */ -# if __GNUC_PREREQ (4,1) -# define EXTERNALLY_VISIBLE __attribute__(( visibility("default") )); +#if __GNUC_PREREQ(4,1) +# define EXTERNALLY_VISIBLE __attribute__(( visibility("default") )) //__attribute__ ((__externally_visible__)) -# else -# define EXTERNALLY_VISIBLE -# endif /* GNUC >= 4.1 */ +#else +# define EXTERNALLY_VISIBLE +#endif + +/* At 4.4 gcc become much more anal about this, need to use "aliased" types */ +#if __GNUC_PREREQ(4,4) +# define FIX_ALIASING __attribute__((__may_alias__)) +#else +# define FIX_ALIASING +#endif /* We use __extension__ in some places to suppress -pedantic warnings about GCC extensions. This feature didn't work properly before gcc 2.8. */ -#if !__GNUC_PREREQ (2,8) +#if !__GNUC_PREREQ(2,8) # ifndef __extension__ # define __extension__ # endif #endif /* gcc-2.95 had no va_copy but only __va_copy. */ -#if !__GNUC_PREREQ (3,0) +#if !__GNUC_PREREQ(3,0) # include # if !defined va_copy && defined __va_copy # define va_copy(d,s) __va_copy((d),(s)) # endif #endif +/* FAST_FUNC is a qualifier which (possibly) makes function call faster + * and/or smaller by using modified ABI. It is usually only needed + * on non-static, busybox internal functions. Recent versions of gcc + * optimize statics automatically. FAST_FUNC on static is required + * only if you need to match a function pointer's type */ +#if __GNUC_PREREQ(3,0) && defined(i386) /* || defined(__x86_64__)? */ +/* stdcall makes callee to pop arguments from stack, not caller */ +# define FAST_FUNC __attribute__((regparm(3),stdcall)) +/* #elif ... - add your favorite arch today! */ +#else +# define FAST_FUNC +#endif + +/* Make all declarations hidden (-fvisibility flag only affects definitions) */ +/* (don't include system headers after this until corresponding pop!) */ +#if __GNUC_PREREQ(4,1) +# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)") +# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop") +#else +# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN +# define POP_SAVED_FUNCTION_VISIBILITY +#endif + /* ---- Endian Detection ------------------------------------ */ -#if (defined __digital__ && defined __unix__) +#include +#if defined(__digital__) && defined(__unix__) # include -# define __BIG_ENDIAN__ (BYTE_ORDER == BIG_ENDIAN) -# define __BYTE_ORDER BYTE_ORDER -#elif !defined __APPLE__ +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__APPLE__) +# include /* rlimit */ +# include +# define bswap_64 __bswap64 +# define bswap_32 __bswap32 +# define bswap_16 __bswap16 +#else # include # include #endif -#ifdef __BIG_ENDIAN__ +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN # define BB_BIG_ENDIAN 1 # define BB_LITTLE_ENDIAN 0 -#elif __BYTE_ORDER == __BIG_ENDIAN +#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN +# define BB_BIG_ENDIAN 0 +# define BB_LITTLE_ENDIAN 1 +#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN # define BB_BIG_ENDIAN 1 # define BB_LITTLE_ENDIAN 0 -#else +#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN # define BB_BIG_ENDIAN 0 # define BB_LITTLE_ENDIAN 1 +#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN +# define BB_BIG_ENDIAN 1 +# define BB_LITTLE_ENDIAN 0 +#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN +# define BB_BIG_ENDIAN 0 +# define BB_LITTLE_ENDIAN 1 +#elif defined(__386__) +# define BB_BIG_ENDIAN 0 +# define BB_LITTLE_ENDIAN 1 +#else +# error "Can't determine endianness" #endif -#if BB_BIG_ENDIAN -#define SWAP_BE16(x) (x) -#define SWAP_BE32(x) (x) -#define SWAP_BE64(x) (x) -#define SWAP_LE16(x) bswap_16(x) -#define SWAP_LE32(x) bswap_32(x) -#define SWAP_LE64(x) bswap_64(x) -#else -#define SWAP_BE16(x) bswap_16(x) -#define SWAP_BE32(x) bswap_32(x) -#define SWAP_BE64(x) bswap_64(x) -#define SWAP_LE16(x) (x) -#define SWAP_LE32(x) (x) -#define SWAP_LE64(x) (x) +#if ULONG_MAX > 0xffffffff +# define bb_bswap_64(x) bswap_64(x) #endif -/* ---- Networking ------------------------------------------ */ -#ifndef __APPLE__ -# include +/* SWAP_LEnn means "convert CPU<->little_endian by swapping bytes" */ +#if BB_BIG_ENDIAN +# define SWAP_BE16(x) (x) +# define SWAP_BE32(x) (x) +# define SWAP_BE64(x) (x) +# define SWAP_LE16(x) bswap_16(x) +# define SWAP_LE32(x) bswap_32(x) +# define SWAP_LE64(x) bb_bswap_64(x) +# define IF_BIG_ENDIAN(...) __VA_ARGS__ +# define IF_LITTLE_ENDIAN(...) #else -# include +# define SWAP_BE16(x) bswap_16(x) +# define SWAP_BE32(x) bswap_32(x) +# define SWAP_BE64(x) bb_bswap_64(x) +# define SWAP_LE16(x) (x) +# define SWAP_LE32(x) (x) +# define SWAP_LE64(x) (x) +# define IF_BIG_ENDIAN(...) +# define IF_LITTLE_ENDIAN(...) __VA_ARGS__ #endif -#ifndef __socklen_t_defined -typedef int socklen_t; +/* ---- Unaligned access ------------------------------------ */ + +#include +typedef int bb__aliased_int FIX_ALIASING; +typedef uint16_t bb__aliased_uint16_t FIX_ALIASING; +typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; + +/* NB: unaligned parameter should be a pointer, aligned one - + * a lvalue. This makes it more likely to not swap them by mistake + */ +#if defined(i386) || defined(__x86_64__) || defined(__powerpc__) +# define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp)) +# define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p)) +# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) +# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v)) +# define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v)) +/* #elif ... - add your favorite arch today! */ +#else +/* performs reasonably well (gcc usually inlines memcpy here) */ +# define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int))) +# define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2)) +# define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4)) +# define move_to_unaligned16(u16p, v) do { \ + uint16_t __t = (v); \ + memcpy((u16p), &__t, 4); \ +} while (0) +# define move_to_unaligned32(u32p, v) do { \ + uint32_t __t = (v); \ + memcpy((u32p), &__t, 4); \ +} while (0) #endif /* ---- Compiler dependent settings ------------------------- */ -#if (defined __digital__ && defined __unix__) + +#if (defined __digital__ && defined __unix__) \ + || defined __APPLE__ \ + || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ +# undef HAVE_CLEARENV +# undef HAVE_FDATASYNC # undef HAVE_MNTENT_H +# undef HAVE_PTSNAME_R +# undef HAVE_SYS_STATFS_H +# undef HAVE_SIGHANDLER_T +# undef HAVE_XTABS +# undef HAVE_DPRINTF #else # define HAVE_MNTENT_H 1 -#endif /* ___digital__ && __unix__ */ - -/* linux/loop.h relies on __u64. Make sure we have that as a proper type - * until userspace is widely fixed. */ -#ifndef __GNUC__ -#if defined __INTEL_COMPILER -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif /* __INTEL_COMPILER */ -#endif /* ifndef __GNUC__ */ +# define HAVE_SYS_STATFS_H 1 +# define HAVE_XTABS 1 +#endif /*----- Kernel versioning ------------------------------------*/ -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) - -/* ---- miscellaneous --------------------------------------- */ -#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 5 && \ - !defined(__dietlibc__) && \ - !defined(_NEWLIB_VERSION) && \ - !(defined __digital__ && defined __unix__) -# error "Sorry, this libc version is not supported :(" -#endif +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -/* Don't perpetuate e2fsck crap into the headers. Clean up e2fsck instead. */ +/* ---- Miscellaneous --------------------------------------- */ #if defined __GLIBC__ || defined __UCLIBC__ \ - || defined __dietlibc__ || defined _NEWLIB_VERSION -#include -#define HAVE_FEATURES_H -#include -#define HAVE_STDINT_H -#else -/* Largest integral types. */ -#if __BIG_ENDIAN__ -typedef long intmax_t; -typedef unsigned long uintmax_t; -#else -__extension__ -typedef long long intmax_t; -__extension__ -typedef unsigned long long uintmax_t; -#endif + || defined __dietlibc__ || defined _NEWLIB_VERSION +# include #endif /* Size-saving "small" ints (arch-dependent) */ @@ -208,20 +296,22 @@ typedef unsigned smalluint; /* ISO C Standard: 7.16 Boolean type and values */ #if (defined __digital__ && defined __unix__) /* old system without (proper) C99 support */ -#define bool smalluint +# define bool smalluint #else /* modern system, so use it */ -#include +# include #endif /* Try to defeat gcc's alignment of "char message[]"-like data */ #if 1 /* if needed: !defined(arch1) && !defined(arch2) */ -#define ALIGN1 __attribute__((aligned(1))) -#define ALIGN2 __attribute__((aligned(2))) +# define ALIGN1 __attribute__((aligned(1))) +# define ALIGN2 __attribute__((aligned(2))) +# define ALIGN4 __attribute__((aligned(4))) #else /* Arches which MUST have 2 or 4 byte alignment for everything are here */ -#define ALIGN1 -#define ALIGN2 +# define ALIGN1 +# define ALIGN2 +# define ALIGN4 #endif @@ -233,111 +323,116 @@ typedef unsigned smalluint; #if ENABLE_NOMMU || \ (defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \ __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__) -#define BB_MMU 0 -#define BB_NOMMU 1 -#define USE_FOR_NOMMU(...) __VA_ARGS__ -#define USE_FOR_MMU(...) +# define BB_MMU 0 +# define USE_FOR_NOMMU(...) __VA_ARGS__ +# define USE_FOR_MMU(...) #else -#define BB_MMU 1 -/* BB_NOMMU is not defined in this case! */ -#define USE_FOR_NOMMU(...) -#define USE_FOR_MMU(...) __VA_ARGS__ -#endif - -/* Platforms that haven't got dprintf need to implement fdprintf() in - * libbb. This would require a platform.c. It's not going to be cleaned - * out of the tree, so stop saying it should be. */ -#if !defined(__dietlibc__) -/* Needed for: glibc */ -/* Not needed for: dietlibc */ -/* Others: ?? (add as needed) */ -#define fdprintf dprintf +# define BB_MMU 1 +# define USE_FOR_NOMMU(...) +# define USE_FOR_MMU(...) __VA_ARGS__ #endif -#if defined(__dietlibc__) -static ALWAYS_INLINE char* strchrnul(const char *s, char c) -{ - while (*s && *s != c) ++s; - return (char*)s; -} -#endif +#if defined(__digital__) && defined(__unix__) -/* Don't use lchown with glibc older than 2.1.x ... uClibc lacks it */ -#if (defined __GLIBC__ && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 1) || \ - defined __UC_LIBC__ -# define lchown chown -#endif +# include +# include +# define PRIu32 "u" +/* use legacy setpgrp(pid_t,pid_t) for now. move to platform.c */ +# define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me, __me); } while (0) +# if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET +# define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET) +# endif +# if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY +# define ADJ_FREQUENCY MOD_FREQUENCY +# endif +# if !defined ADJ_TIMECONST && defined MOD_TIMECONST +# define ADJ_TIMECONST MOD_TIMECONST +# endif +# if !defined ADJ_TICK && defined MOD_CLKB +# define ADJ_TICK MOD_CLKB +# endif -/* THIS SHOULD BE CLEANED OUT OF THE TREE ENTIRELY */ -/* FIXME: fix tar.c! */ -#ifndef FNM_LEADING_DIR -#define FNM_LEADING_DIR 0 -#endif +# undef HAVE_STPCPY -#if (defined __digital__ && defined __unix__) -#include -#define HAVE_STANDARDS_H -#include -#define HAVE_INTTYPES_H -#define PRIu32 "u" +#else -/* use legacy setpgrp(pid_t,pid_t) for now. move to platform.c */ -#define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me,__me); } while (0) +# define bb_setpgrp() setpgrp() -#if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET -#define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET) -#endif -#if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY -#define ADJ_FREQUENCY MOD_FREQUENCY -#endif -#if !defined ADJ_TIMECONST && defined MOD_TIMECONST -#define ADJ_TIMECONST MOD_TIMECONST #endif -#if !defined ADJ_TICK && defined MOD_CLKB -#define ADJ_TICK MOD_CLKB + +#include +#define fdprintf dprintf + +#if defined(__dietlibc__) +# undef HAVE_STRCHRNUL #endif -#else -#define bb_setpgrp() setpgrp() +#if defined(__WATCOMC__) +# undef HAVE_DPRINTF +# undef HAVE_MEMRCHR +# undef HAVE_MKDTEMP +# undef HAVE_SETBIT +# undef HAVE_STPCPY +# undef HAVE_STRCASESTR +# undef HAVE_STRCHRNUL +# undef HAVE_STRSEP +# undef HAVE_STRSIGNAL +# undef HAVE_VASPRINTF #endif -#if defined(__linux__) -#include -/* Make sure we have all the new mount flags we actually try to use. */ -#ifndef MS_BIND -#define MS_BIND (1<<12) +#if defined(__FreeBSD__) +# undef HAVE_STRCHRNUL #endif -#ifndef MS_MOVE -#define MS_MOVE (1<<13) + +/* + * Now, define prototypes for all the functions defined in platform.c + * These must come after all the HAVE_* macros are defined (or not) + */ + +#ifndef HAVE_DPRINTF +extern int dprintf(int fd, const char *format, ...); #endif -#ifndef MS_RECURSIVE -#define MS_RECURSIVE (1<<14) + +#ifndef HAVE_MEMRCHR +extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC; #endif -#ifndef MS_SILENT -#define MS_SILENT (1<<15) + +#ifndef HAVE_MKDTEMP +extern char *mkdtemp(char *template) FAST_FUNC; #endif -/* The shared subtree stuff, which went in around 2.6.15. */ -#ifndef MS_UNBINDABLE -#define MS_UNBINDABLE (1<<17) +#ifndef HAVE_SETBIT +# define setbit(a, b) ((a)[(b) >> 3] |= 1 << ((b) & 7)) +# define clrbit(a, b) ((a)[(b) >> 3] &= ~(1 << ((b) & 7))) #endif -#ifndef MS_PRIVATE -#define MS_PRIVATE (1<<18) + +#ifndef HAVE_SIGHANDLER_T +typedef void (*sighandler_t)(int); #endif -#ifndef MS_SLAVE -#define MS_SLAVE (1<<19) + +#ifndef HAVE_STPCPY +extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; #endif -#ifndef MS_SHARED -#define MS_SHARED (1<<20) + +#ifndef HAVE_STRCASESTR +extern char *strcasestr(const char *s, const char *pattern) FAST_FUNC; #endif +#ifndef HAVE_STRCHRNUL +extern char *strchrnul(const char *s, int c) FAST_FUNC; +#endif -#if !defined(BLKSSZGET) -#define BLKSSZGET _IO(0x12, 104) +#ifndef HAVE_STRSEP +extern char *strsep(char **stringp, const char *delim) FAST_FUNC; #endif -#if !defined(BLKGETSIZE64) -#define BLKGETSIZE64 _IOR(0x12,114,size_t) + +#ifndef HAVE_STRSIGNAL +/* Not exactly the same: instead of "Stopped" it shows "STOP" etc */ +# define strsignal(sig) get_signame(sig) #endif + +#ifndef HAVE_VASPRINTF +extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC; #endif -#endif /* platform.h */ +#endif