2007-10-02 03:18:26 +04:00
/*
2006-09-19 02:49:20 +04:00
Unix SMB / CIFS implementation .
macros to go along with the lib / replace / portability layer code
Copyright ( C ) Andrew Tridgell 2005
Copyright ( C ) Jelmer Vernooij 2006
2007-10-02 03:18:26 +04:00
Copyright ( C ) Jeremy Allison 2007.
2006-09-19 02:49:20 +04:00
* * NOTE ! The following LGPL license applies to the replace
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2007-10-02 03:18:26 +04:00
2006-09-19 02:49:20 +04:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 05:44:42 +04:00
version 3 of the License , or ( at your option ) any later version .
2006-09-19 02:49:20 +04:00
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2006-09-19 02:49:20 +04:00
*/
# ifndef _LIBREPLACE_REPLACE_H
# define _LIBREPLACE_REPLACE_H
2006-10-11 15:38:40 +04:00
# ifndef NO_CONFIG_H
2006-09-19 02:49:20 +04:00
# include "config.h"
2006-10-11 15:38:40 +04:00
# endif
2006-09-19 02:49:20 +04:00
# ifdef HAVE_STANDARDS_H
# include <standards.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <errno.h>
# if defined(_MSC_VER) || defined(__MINGW32__)
# include "win32_replace.h"
# endif
# ifdef HAVE_STDINT_H
# include <stdint.h>
/* force off HAVE_INTTYPES_H so that roken doesn't try to include both,
which causes a warning storm on irix */
# undef HAVE_INTTYPES_H
# elif HAVE_INTTYPES_H
2008-10-14 05:42:54 +04:00
# define __STDC_FORMAT_MACROS
2006-09-19 02:49:20 +04:00
# include <inttypes.h>
# endif
2008-10-14 06:12:53 +04:00
# ifndef __PRI64_PREFIX
# if __WORDSIZE == 64
# define __PRI64_PREFIX "l"
# else
# define __PRI64_PREFIX "ll"
# endif
# endif
/* Decimal notation. */
# ifndef PRId8
# define PRId8 "d"
# endif
# ifndef PRId16
# define PRId16 "d"
# endif
# ifndef PRId32
# define PRId32 "d"
# endif
# ifndef PRId64
# define PRId64 __PRI64_PREFIX "d"
# endif
# ifndef PRIi8
# define PRIi8 "i"
# endif
# ifndef PRIi8
# define PRIi16 "i"
# endif
# ifndef PRIi8
# define PRIi32 "i"
# endif
# ifndef PRIi8
# define PRIi64 __PRI64_PREFIX "i"
# endif
# ifndef PRIu8
# define PRIu8 "u"
# endif
# ifndef PRIu16
# define PRIu16 "u"
# endif
# ifndef PRIu32
# define PRIu32 "u"
# endif
# ifndef PRIu64
# define PRIu64 __PRI64_PREFIX "u"
# endif
2006-09-19 02:49:20 +04:00
# ifdef HAVE_STRING_H
# include <string.h>
# endif
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# if STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
# endif
# ifndef HAVE_STRERROR
extern char * sys_errlist [ ] ;
# define strerror(i) sys_errlist[i]
# endif
# ifndef HAVE_ERRNO_DECL
extern int errno ;
# endif
# ifndef HAVE_STRDUP
# define strdup rep_strdup
char * rep_strdup ( const char * s ) ;
# endif
# ifndef HAVE_MEMMOVE
# define memmove rep_memmove
void * rep_memmove ( void * dest , const void * src , int size ) ;
# endif
# ifndef HAVE_MKTIME
# define mktime rep_mktime
2007-10-11 04:56:19 +04:00
/* prototype is in "system/time.h" */
2006-09-19 02:49:20 +04:00
# endif
# ifndef HAVE_TIMEGM
# define timegm rep_timegm
2007-10-11 04:56:19 +04:00
/* prototype is in "system/time.h" */
2006-09-19 02:49:20 +04:00
# endif
2008-05-07 15:10:31 +04:00
# ifndef HAVE_UTIME
# define utime rep_utime
/* prototype is in "system/time.h" */
# endif
# ifndef HAVE_UTIMES
# define utimes rep_utimes
/* prototype is in "system/time.h" */
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_STRLCPY
# define strlcpy rep_strlcpy
size_t rep_strlcpy ( char * d , const char * s , size_t bufsize ) ;
# endif
# ifndef HAVE_STRLCAT
# define strlcat rep_strlcat
size_t rep_strlcat ( char * d , const char * s , size_t bufsize ) ;
# endif
2006-10-02 13:20:18 +04:00
# if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
# undef HAVE_STRNDUP
2006-09-19 02:49:20 +04:00
# define strndup rep_strndup
char * rep_strndup ( const char * s , size_t n ) ;
# endif
2006-10-02 13:20:18 +04:00
# if (defined(BROKEN_STRNLEN) || !defined(HAVE_STRNLEN))
# undef HAVE_STRNLEN
2006-09-19 02:49:20 +04:00
# define strnlen rep_strnlen
size_t rep_strnlen ( const char * s , size_t n ) ;
# endif
2008-10-28 01:39:53 +03:00
# if !HAVE_DECL_ENVIRON
# ifdef __APPLE__
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
# else
extern char * * environ ;
# endif
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_SETENV
# define setenv rep_setenv
2007-04-16 13:20:52 +04:00
int rep_setenv ( const char * name , const char * value , int overwrite ) ;
# else
2007-04-16 16:43:54 +04:00
# ifndef HAVE_SETENV_DECL
2007-04-16 13:20:52 +04:00
int setenv ( const char * name , const char * value , int overwrite ) ;
# endif
2006-09-19 02:49:20 +04:00
# endif
2007-04-16 00:12:09 +04:00
# ifndef HAVE_UNSETENV
# define unsetenv rep_unsetenv
2007-10-04 21:20:49 +04:00
int rep_unsetenv ( const char * name ) ;
2007-04-16 00:12:09 +04:00
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_SETEUID
# define seteuid rep_seteuid
int rep_seteuid ( uid_t ) ;
# endif
# ifndef HAVE_SETEGID
# define setegid rep_setegid
int rep_setegid ( gid_t ) ;
# endif
2008-11-01 05:27:45 +03:00
# ifndef HAVE_CHOWN
# define chown rep_chown
int rep_chown ( const char * path , uid_t uid , gid_t gid ) ;
# endif
2008-11-01 05:30:47 +03:00
# ifndef HAVE_LINK
# define link rep_link
int rep_link ( const char * oldpath , const char * newpath ) ;
# endif
2008-11-01 05:33:39 +03:00
# ifndef HAVE_READLINK
# define readlink rep_readlink
int rep_readlink ( const char * path , char * buf , size_t bufsize ) ;
# endif
2008-11-01 05:35:58 +03:00
# ifndef HAVE_SYMLINK
# define symlink rep_symlink
int rep_symlink ( const char * oldpath , const char * newpath ) ;
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_SETLINEBUF
# define setlinebuf rep_setlinebuf
void rep_setlinebuf ( FILE * ) ;
# endif
# ifndef HAVE_STRCASESTR
# define strcasestr rep_strcasestr
char * rep_strcasestr ( const char * haystack , const char * needle ) ;
# endif
# ifndef HAVE_STRTOK_R
2007-10-04 21:20:49 +04:00
# define strtok_r rep_strtok_r
2006-09-19 02:49:20 +04:00
char * rep_strtok_r ( char * s , const char * delim , char * * save_ptr ) ;
# endif
# ifndef HAVE_STRTOLL
# define strtoll rep_strtoll
long long int rep_strtoll ( const char * str , char * * endptr , int base ) ;
# endif
# ifndef HAVE_STRTOULL
# define strtoull rep_strtoull
unsigned long long int rep_strtoull ( const char * str , char * * endptr , int base ) ;
# endif
# ifndef HAVE_FTRUNCATE
# define ftruncate rep_ftruncate
int rep_ftruncate ( int , off_t ) ;
# endif
# ifndef HAVE_INITGROUPS
2007-04-16 00:12:09 +04:00
# define initgroups rep_initgroups
2006-09-19 02:49:20 +04:00
int rep_initgroups ( char * name , gid_t id ) ;
# endif
# if !defined(HAVE_BZERO) && defined(HAVE_MEMSET)
# define bzero(a,b) memset((a),'\0',(b))
# endif
# ifndef HAVE_DLERROR
# define dlerror rep_dlerror
char * rep_dlerror ( void ) ;
# endif
# ifndef HAVE_DLOPEN
# define dlopen rep_dlopen
2007-06-02 13:10:08 +04:00
# ifdef DLOPEN_TAKES_UNSIGNED_FLAGS
void * rep_dlopen ( const char * name , unsigned int flags ) ;
# else
2006-09-19 02:49:20 +04:00
void * rep_dlopen ( const char * name , int flags ) ;
# endif
2007-06-02 13:10:08 +04:00
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_DLSYM
# define dlsym rep_dlsym
void * rep_dlsym ( void * handle , const char * symbol ) ;
# endif
# ifndef HAVE_DLCLOSE
# define dlclose rep_dlclose
int rep_dlclose ( void * handle ) ;
# endif
2007-01-15 22:10:54 +03:00
# ifndef HAVE_SOCKETPAIR
# define socketpair rep_socketpair
2008-03-18 19:20:47 +03:00
/* prototype is in system/network.h */
2007-01-15 22:10:54 +03:00
# endif
2006-09-19 02:49:20 +04:00
# ifndef PRINTF_ATTRIBUTE
2006-09-19 03:26:14 +04:00
# if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
2006-09-19 02:49:20 +04:00
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format , and a2 the index of the first
* argument . Note that some gcc 2. x versions don ' t handle this
* properly * */
# define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
# else
# define PRINTF_ATTRIBUTE(a1, a2)
# endif
# endif
2007-06-02 13:10:08 +04:00
# ifndef _DEPRECATED_
# if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
# define _DEPRECATED_ __attribute__ ((deprecated))
# else
# define _DEPRECATED_
# endif
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_VASPRINTF
# define vasprintf rep_vasprintf
2006-09-29 16:30:14 +04:00
int rep_vasprintf ( char * * ptr , const char * format , va_list ap ) PRINTF_ATTRIBUTE ( 2 , 0 ) ;
2006-09-19 02:49:20 +04:00
# endif
# if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
# define snprintf rep_snprintf
int rep_snprintf ( char * , size_t , const char * , . . . ) PRINTF_ATTRIBUTE ( 3 , 4 ) ;
# endif
# if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
# define vsnprintf rep_vsnprintf
2006-09-29 16:30:14 +04:00
int rep_vsnprintf ( char * , size_t , const char * , va_list ap ) PRINTF_ATTRIBUTE ( 3 , 0 ) ;
2006-09-19 02:49:20 +04:00
# endif
# ifndef HAVE_ASPRINTF
# define asprintf rep_asprintf
int rep_asprintf ( char * * , const char * , . . . ) PRINTF_ATTRIBUTE ( 2 , 3 ) ;
# endif
2006-09-29 16:30:14 +04:00
# ifndef HAVE_VSYSLOG
# ifdef HAVE_SYSLOG
# define vsyslog rep_vsyslog
void rep_vsyslog ( int facility_priority , const char * format , va_list arglist ) PRINTF_ATTRIBUTE ( 2 , 0 ) ;
# endif
# endif
2006-09-19 02:49:20 +04:00
/* we used to use these fns, but now we have good replacements
for snprintf and vsnprintf */
# define slprintf snprintf
# ifndef HAVE_VA_COPY
# undef va_copy
# ifdef HAVE___VA_COPY
# define va_copy(dest, src) __va_copy(dest, src)
# else
# define va_copy(dest, src) (dest) = (src)
# endif
# endif
# ifndef HAVE_VOLATILE
# define volatile
# endif
# ifndef HAVE_COMPARISON_FN_T
typedef int ( * comparison_fn_t ) ( const void * , const void * ) ;
# endif
2007-04-16 00:12:09 +04:00
# ifdef REPLACE_STRPTIME
# define strptime rep_strptime
struct tm ;
char * rep_strptime ( const char * buf , const char * format , struct tm * tm ) ;
# endif
2006-09-19 02:49:20 +04:00
/* Load header file for dynamic linking stuff */
# ifdef HAVE_DLFCN_H
# include <dlfcn.h>
# endif
# ifndef RTLD_LAZY
# define RTLD_LAZY 0
# endif
2007-05-24 11:15:36 +04:00
# ifndef RTLD_NOW
# define RTLD_NOW 0
# endif
# ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_SECURE_MKSTEMP
# define mkstemp(path) rep_mkstemp(path)
int rep_mkstemp ( char * temp ) ;
# endif
# ifndef HAVE_MKDTEMP
# define mkdtemp rep_mkdtemp
char * rep_mkdtemp ( char * template ) ;
# endif
2007-06-06 13:27:43 +04:00
# ifndef HAVE_PREAD
# define pread rep_pread
ssize_t rep_pread ( int __fd , void * __buf , size_t __nbytes , off_t __offset ) ;
# endif
# ifndef HAVE_PWRITE
# define pwrite rep_pwrite
ssize_t rep_pwrite ( int __fd , const void * __buf , size_t __nbytes , off_t __offset ) ;
# endif
2007-10-02 03:18:26 +04:00
2008-03-18 14:16:47 +03:00
# if !defined(HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA)
2007-10-10 16:09:06 +04:00
# define inet_ntoa rep_inet_ntoa
/* prototype is in "system/network.h" */
# endif
2007-10-02 03:18:26 +04:00
# ifndef HAVE_INET_PTON
2007-10-02 23:27:25 +04:00
# define inet_pton rep_inet_pton
2007-10-10 16:09:06 +04:00
/* prototype is in "system/network.h" */
2007-10-02 03:18:26 +04:00
# endif
# ifndef HAVE_INET_NTOP
2007-10-02 23:27:25 +04:00
# define inet_ntop rep_inet_ntop
2007-10-10 16:09:06 +04:00
/* prototype is in "system/network.h" */
2007-10-02 03:18:26 +04:00
# endif
2007-06-06 13:27:43 +04:00
2008-03-14 10:49:34 +03:00
# ifndef HAVE_INET_ATON
# define inet_aton rep_inet_aton
/* prototype is in "system/network.h" */
# endif
2008-02-26 15:24:54 +03:00
# ifndef HAVE_CONNECT
# define connect rep_connect
/* prototype is in "system/network.h" */
# endif
# ifndef HAVE_GETHOSTBYNAME
# define gethostbyname rep_gethostbyname
/* prototype is in "system/network.h" */
# endif
2007-12-17 09:45:05 +03:00
# ifndef HAVE_GETIFADDRS
# define getifaddrs rep_getifaddrs
/* prototype is in "system/network.h" */
# endif
# ifndef HAVE_FREEIFADDRS
# define freeifaddrs rep_freeifaddrs
/* prototype is in "system/network.h" */
# endif
2006-09-19 02:49:20 +04:00
# ifdef HAVE_LIMITS_H
# include <limits.h>
# endif
2007-09-20 13:12:18 +04:00
# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# endif
2006-09-19 02:49:20 +04:00
/* The extra casts work around common compiler bugs. */
# define _TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
It is necessary at least when t = = time_t . */
# define _TYPE_MINIMUM(t) ((t) (_TYPE_SIGNED (t) \
? ~ ( t ) 0 < < ( sizeof ( t ) * CHAR_BIT - 1 ) : ( t ) 0 ) )
# define _TYPE_MAXIMUM(t) ((t) (~ (t) 0 - _TYPE_MINIMUM (t)))
# ifndef HOST_NAME_MAX
2007-11-09 04:25:45 +03:00
# define HOST_NAME_MAX 255
2006-09-19 02:49:20 +04:00
# endif
2007-09-19 18:57:20 +04:00
/*
* Some older systems seem not to have MAXHOSTNAMELEN
* defined .
*/
# ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN HOST_NAME_MAX
# endif
2006-09-19 02:49:20 +04:00
# ifndef UINT16_MAX
# define UINT16_MAX 65535
# endif
# ifndef UINT32_MAX
# define UINT32_MAX (4294967295U)
# endif
# ifndef UINT64_MAX
# define UINT64_MAX ((uint64_t)-1)
# endif
# ifndef CHAR_BIT
# define CHAR_BIT 8
# endif
# ifndef INT32_MAX
# define INT32_MAX _TYPE_MAXIMUM(int32_t)
# endif
# ifdef HAVE_STDBOOL_H
# include <stdbool.h>
# endif
# if !defined(HAVE_BOOL)
# ifdef HAVE__Bool
# define bool _Bool
# else
2006-09-19 07:38:35 +04:00
typedef int bool ;
# endif
# endif
2006-09-19 07:29:44 +04:00
/*
* to prevent < rpcsvc / yp_prot . h > from doing a redefine of ' bool '
*
* IRIX , HPUX , MacOS 10 and Solaris need BOOL_DEFINED
* Tru64 needs _BOOL_EXISTS
2006-09-21 12:48:18 +04:00
* AIX needs _BOOL , _TRUE , _FALSE
2006-09-19 07:29:44 +04:00
*/
2006-09-19 07:38:35 +04:00
# ifndef BOOL_DEFINED
2006-09-19 07:29:44 +04:00
# define BOOL_DEFINED
2006-09-19 07:38:35 +04:00
# endif
# ifndef _BOOL_EXISTS
2006-09-19 07:29:44 +04:00
# define _BOOL_EXISTS
2006-09-19 02:49:20 +04:00
# endif
2006-09-21 12:48:18 +04:00
# ifndef _BOOL
# define _BOOL
# endif
2006-09-19 07:38:35 +04:00
# ifndef __bool_true_false_are_defined
# define __bool_true_false_are_defined
2006-09-19 02:49:20 +04:00
# endif
# ifndef true
# define true (1)
# endif
# ifndef false
# define false (0)
# endif
2006-09-21 12:48:18 +04:00
# ifndef _TRUE
2006-09-24 06:29:12 +04:00
# define _TRUE true
2006-09-21 12:48:18 +04:00
# endif
# ifndef _FALSE
2006-09-24 06:29:12 +04:00
# define _FALSE false
2006-09-21 12:48:18 +04:00
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_FUNCTION_MACRO
# ifdef HAVE_func_MACRO
# define __FUNCTION__ __func__
# else
# define __FUNCTION__ ("")
# endif
# endif
# ifndef MIN
# define MIN(a,b) ((a)<(b)?(a):(b))
# endif
# ifndef MAX
# define MAX(a,b) ((a)>(b)?(a):(b))
# endif
2007-11-07 08:47:57 +03:00
# if !defined(HAVE_VOLATILE)
# define volatile
# endif
2007-09-20 13:12:18 +04:00
/**
this is a warning hack . The idea is to use this everywhere that we
get the " discarding const " warning from gcc . That doesn ' t actually
fix the problem of course , but it means that when we do get to
cleaning them up we can do it by searching the code for
discard_const .
It also means that other error types aren ' t as swamped by the noise
of hundreds of const warnings , so we are more likely to notice when
we get new errors .
Please only add more uses of this macro when you find it
_really_ hard to fix const warnings . Our aim is to eventually use
this function in only a very few places .
Also , please call this via the discard_const_p ( ) macro interface , as that
makes the return type safe .
*/
2008-04-18 11:30:50 +04:00
# define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
2007-09-20 13:12:18 +04:00
/** Type-safe version of discard_const */
# define discard_const_p(type, ptr) ((type *)discard_const(ptr))
2006-09-19 02:49:20 +04:00
# ifndef __STRING
# define __STRING(x) #x
# endif
2007-09-19 18:57:20 +04:00
# ifndef __STRINGSTRING
2007-04-16 23:46:06 +04:00
# define __STRINGSTRING(x) __STRING(x)
# endif
# ifndef __LINESTR__
# define __LINESTR__ __STRINGSTRING(__LINE__)
# endif
2007-04-16 23:23:00 +04:00
# ifndef __location__
2007-04-16 23:46:06 +04:00
# define __location__ __FILE__ ":" __LINESTR__
2007-04-16 23:23:00 +04:00
# endif
2007-04-17 12:03:29 +04:00
/**
* zero a structure
*/
# define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
/**
* zero a structure given a pointer to the structure
*/
# define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
/**
* zero a structure given a pointer to the structure - no zero check
*/
# define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x)))
/* zero an array - note that sizeof(array) must work - ie. it must not be a
pointer */
# define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x))
/**
* work out how many elements there are in a static array
*/
# define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/**
* pointer difference macro
*/
# define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
2006-09-19 02:49:20 +04:00
# if MMAP_BLACKLIST
# undef HAVE_MMAP
# endif
2007-09-20 13:12:18 +04:00
# ifdef __COMPAR_FN_T
# define QSORT_CAST (__compar_fn_t)
# endif
# ifndef QSORT_CAST
# define QSORT_CAST (int (*)(const void *, const void *))
# endif
2007-11-11 09:31:34 +03:00
# ifndef PATH_MAX
# define PATH_MAX 1024
# endif
2007-11-16 05:27:26 +03:00
# ifndef MAX_DNS_NAME_LENGTH
# define MAX_DNS_NAME_LENGTH 256 /* Actually 255 but +1 for terminating null. */
# endif
2008-10-18 19:49:41 +04:00
# ifndef HAVE_CRYPT
char * ufc_crypt ( const char * key , const char * salt ) ;
# define crypt ufc_crypt
# else
2008-10-20 12:38:03 +04:00
# ifdef HAVE_CRYPT_H
2008-10-18 19:49:41 +04:00
# include <crypt.h>
# endif
2008-10-20 12:38:03 +04:00
# endif
2008-10-18 19:49:41 +04:00
2006-09-19 02:49:20 +04:00
# endif /* _LIBREPLACE_REPLACE_H */