/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * compat.h: Some defines and inlines for non-gnu systems * */ #ifndef SPL_COMPAT_H #define SPL_COMPAT_H #include #if defined __GNUC__ && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) # define UNUSED(x) x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else # define UNUSED(x) x #endif #if defined __MACH__ && defined __APPLE__ # define COMPAT_MEMRCHR # define COMPAT_STRNDUPA # define COMPAT_STRNDUP # define COMPAT_MEMMEM # define COMPAT_DPRINTF # define COMPAT_SENDFILE #elif !(defined __GLIBC__ && defined __GLIBC_MINOR__) || defined _FORCE_COMPAT_FUNCS # define COMPAT_ALLOCA # define COMPAT_MEMRCHR # define COMPAT_STRSEP # define COMPAT_STRNDUPA # define COMPAT_STRNDUP # define COMPAT_MEMMEM # define COMPAT_ASPRINTF # define COMPAT_VASPRINTF # define COMPAT_DPRINTF # define COMPAT_SENDFILE #endif #ifdef COMPAT_ALLOCA # define my_alloca(_s) __builtin_alloca(_s) #else # define my_alloca alloca #endif #ifdef COMPAT_MEMRCHR static inline void *my_memrchr(const void *s, int c, size_t n) { const char *sx = s; for (int counter = n; counter >= 0; counter--) if (sx[counter] == c) return (void*)(sx+counter); return 0; } #else # define my_memrchr memrchr #endif #ifdef COMPAT_STRSEP static inline char *my_strsep(char **s, const char *ct) { char *begin = *s, *end = *s; if (!begin) return 0; while (*end && !strchr(ct, *end)) end++; if (*end) { *end = 0; *s = end+1; } else *s = 0; return begin; } #else # define my_strsep strsep #endif #ifdef COMPAT_STRNDUPA # define my_strndupa(s, n) \ ({ \ char *__new = (char *) __builtin_alloca ((n) + 1); \ strncpy(__new, (s), (n)); \ __new[(n)] = '\0'; __new; \ }) #else # define my_strndupa strndupa #endif #ifdef COMPAT_STRNDUP # define my_strndup(s, n) \ ({ \ char *__new = (char *) malloc ((n) + 1); \ strncpy(__new, (s), (n)); \ __new[(n)] = '\0'; __new; \ }) #else # define my_strndup strndup #endif #ifdef COMPAT_MEMMEM static inline void *my_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { if (needlelen <= haystacklen) { for (unsigned int i=0; i <= haystacklen-needlelen; i++) if (!memcmp(haystack+i, needle, needlelen)) return (void*)(haystack+i); } return 0; } #else # define my_memmem memmem #endif #if defined USEWIN32API #ifndef COMPAT_H_NO_WIN_INCL # include # include # include #endif # define MY_O_BINARY O_BINARY # define my_sleep(sec) Sleep((sec)*1000) #else # define MY_O_BINARY 0 # define my_sleep sleep #endif #ifdef COMPAT_ASPRINTF # define my_asprintf(__result, fmt, ...) \ ({ \ int __size = 64, __rc; \ *(__result) = malloc(__size + 1); \ while (1) { \ __rc = snprintf(*(__result), __size + 1, \ (fmt), ## __VA_ARGS__); \ if (__rc >= 0 && __rc < __size) break; \ __size *= 2; \ *(__result) = realloc(*(__result), __size + 1); \ } \ __rc; \ }) #else # define my_asprintf asprintf #endif #ifdef COMPAT_VASPRINTF # define my_vasprintf(__result, fmt, ap) \ ({ \ int __size = 64, __rc; \ *(__result) = malloc(__size + 1); \ while (1) { \ va_list apc; \ va_copy(apc, ap); \ __rc = vsnprintf(*(__result), __size + 1, \ (fmt), (apc)); \ va_end(apc); \ if (__rc >= 0 && __rc < __size) break; \ __size *= 2; \ *(__result) = realloc(*(__result), __size + 1); \ } \ __rc; \ }) #else # define my_vasprintf vasprintf #endif #ifdef COMPAT_DPRINTF # include static inline int my_dprintf(int fd, const char *fmt, ...) \ { \ char *data; \ va_list ap; \ va_start(ap, fmt); \ const int rc = my_vasprintf(&data, fmt, ap); \ va_end(ap); \ for (int written = 0, rc2; written < rc; written += rc2) { \ rc2 = write(fd, data+written, rc-written); \ if (rc2 <= 0) break; \ } \ free(data); \ return rc; \ } #else # define my_dprintf dprintf #endif #ifdef COMPAT_SENDFILE # include static inline ssize_t my_sendfile(int out_fd, int in_fd, off_t UNUSED(*offset), size_t count) { char buffer[count]; const int read_rc = read(in_fd, buffer, count); if (read_rc <= 0) return read_rc; int write_rc = 0; while (write_rc < read_rc) { int rc = write(out_fd, buffer+write_rc, read_rc-write_rc); if (rc <= 0) return rc ? rc : write_rc; write_rc += rc; } return write_rc; } #else # define my_sendfile sendfile #endif #endif