/* 
   Copyright (C) 2003-2008 FreeIPMI Core Team

   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, 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.  
*/

#ifndef _FREEIPMI_PORTABILITY_H
#define	_FREEIPMI_PORTABILITY_H	1

#ifdef __cplusplus
extern "C" {
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include <stdio.h>	/* For FILE definition */
#include <stdlib.h>
#if STDC_HEADERS
#include <string.h>
#include <stdarg.h>
#endif /* STDC_HEADERS */
#include <sys/types.h>
#include <math.h>
#include <netdb.h>
#if HAVE_ALLOCA_H
#include <alloca.h>
#endif /* HAVE_ALLOCA_H */
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else /* !TIME_WITH_SYS_TIME */
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else /* !HAVE_SYS_TIME_H */
#include <time.h>
#endif /* !HAVE_SYS_TIME_H */
#endif  /* !TIME_WITH_SYS_TIME */

/* achu: I guess __func__ is the other macro people use?? */
#ifndef HAVE_FUNCTION_MACRO
#define __FUNCTION__ __func__
#endif  

/* achu: not on Solaris */
#ifndef UINT_MAX
#define UINT_MAX 4294967295U
#endif

#if  __WORDSIZE == 64
#define FI_64 "%l"
#else
#define FI_64 "%ll"
#endif

# if ENABLE_NLS
#  include <libintl.h>
#  define _(Text) gettext (Text)
# else
#  define textdomain(Domain)
#  define _(Text) Text
# endif
# define N_(Text) Text

#if !defined(O_SYNC) && defined(O_FSYNC)
#define O_SYNC	O_FSYNC
#endif

/* FreeBSD don't have log2(), exp10() and exp2() */
#ifndef HAVE_LOG2
#define log2(x)		(M_LOG2E * log((x)))
#endif
#ifndef HAVE_EXP10
#define exp10(x)	(pow(10.0, (x)))
#endif
#ifndef HAVE_EXP2
#define exp2(x)		(pow(2.0, (x)))
#endif

/* FreeBSD don't have strdupa */
#ifndef strdupa
/* Duplicate S, returning an identical alloca'd string.  */
# define strdupa(s)					\
	({						\
		const char *__old = (s);		\
		size_t __len = strlen (__old) + 1;	\
		char *__new = (char *) alloca (__len);	\
		(char *) memcpy (__new, __old, __len);	\
	})
#endif

#ifndef HAVE_MEMCPY
static inline void*
freeipmi_memcpy (void *dest, const void *src, size_t n)
{
  while (0 <= --n) ((unsigned char*)dest) [n] = ((unsigned char*)src) [n];
  return dest;
}
#define memcpy freeipmi_memcpy
#endif /* HAVE_MEMCPY */

#ifndef HAVE_MEMPCPY
#define mempcpy freeipmi_mempcpy
void *freeipmi_mempcpy (void *to, const void *from, size_t size);
#endif /* HAVE_MEMPCPY */

#  ifndef HAVE_MEMSET
static inline void*
freeipmi_memset (void *s, int c, size_t n)
{
  while (0 <= --n) ((unsigned char*)s) [n] = (unsigned char) c;
  return s;
}
#define memset freeipmi_memset
#endif /* HAVE_MEMSET */

#ifndef HAVE_STRCHR
static inline char*
freeipmi_strchr (const char* s, int c)
{
  while (*s != '\0')
    if (*s == (char)c) return s;
    else s++;
  return NULL;
}
# define strchr	freeipmi_strchr
#endif /* HAVE_STRCHR */

/* FreeBSD don't have strndup() */
#ifndef HAVE_STRNDUP
#define strndup	freeipmi_strndup
char *freeipmi_strndup(const char *, size_t);
#endif

#ifndef HAVE_STRCHRNUL
#define strchrnul freeipmi_strchrnul
char *freeipmi_strchrnul(const char *s, int c);
#endif /* !HAVE_STRCHRNUL */

#ifndef HAVE_STRSEP
#define strsep freeipmi_strsep
char *freeipmi_strsep(char **stringp, const char *delim);
#endif /* !HAVE_STRSEP */

#ifndef HAVE_STRISTR
#define stristr freeipmi_stristr
char *freeipmi_stristr(const char *s1, const char *s2);
#endif /* !HAVE_STRISTR */

/* FreeBSD don't have getline() */
#ifndef HAVE_GETLINE
#define getline	freeipmi_getline
ssize_t freeipmi_getline(char **buf, size_t *bufsize, FILE *fp);
#endif

#ifndef HAVE_ASPRINTF
#define asprintf freeipmi_asprintf
int freeipmi_asprintf(char **strp, const char *fmt, ...);
#endif

/* achu: timeradd and timersub not in solaris 
 *
 * these definitions ripped from sys/time.h on linux.
 */
#ifndef timeradd
# define timeradd(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;                          \
    if ((result)->tv_usec >= 1000000)                                         \
      {                                                                       \
        ++(result)->tv_sec;                                                   \
        (result)->tv_usec -= 1000000;                                         \
      }                                                                       \
  } while (0)
#endif /* timeradd */

#ifndef timersub
# define timersub(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
    if ((result)->tv_usec < 0) {                                              \
      --(result)->tv_sec;                                                     \
      (result)->tv_usec += 1000000;                                           \
    }                                                                         \
  } while (0)
#endif /* timersub */

#if !defined(HAVE_FUNC_GETHOSTBYNAME_R_6) && !defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
int freeipmi_gethostbyname_r(const char *name,
                             struct hostent *ret,
                             char *buf,
                             size_t buflen,
                             struct hostent **result,
                             int *h_errnop);
#endif /* !defined(HAVE_FUNC_GETHOSTBYNAME_R_6) && !defined(HAVE_FUNC_GETHOSTBYNAME_R_5) */

#ifdef __cplusplus
}
#endif

#endif /* freeipmi-portability.h */
