/*
#ident	"@(#)smail/src:RELEASE-3_2_0_121:smail.h,v 1.28 2005/08/26 19:59:40 woods Exp"
 */

/*
 *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
 *    Copyright (C) 1992  Ronald S. Karr
 * 
 * See the file COPYING, distributed with smail, for restriction
 * and warranty information.
 */

/*
 * smail.h:
 *	miscellaneous general macros used in the smail source files.
 */

/*
 * typedefs for general use
 *
 * WARNING: be damn sure these are private!
 */

/*
 * This is a special type used to keep the width and alignment of the storage
 * for boolean configuration attributes the same regardless of whether they're
 * main config file attributes (and thus each stored in separate variables, or
 * they are combined in a driver's private flags variable.
 *
 * We use an "unsigned long int" so as to accommodate at least 32 bits on even
 * "small" platforms.
 */
typedef unsigned long int	smail_bool_t;	/* boolean flags */

/*
 * #defines for general use
 */

#undef TRUE				/* SunOS-5 defines this in <rpc/types.h> */
#define TRUE		1		/* All true wisdom is found on T-shirts */
#undef FALSE				/* SunOS-5 defines this in <rpc/types.h> */
#define FALSE		0		/* This fortune is false */
#define SUCCEED		0		/* function succeeded (XXX deprecate!) */
#define FAIL		(-1)		/* function failed */

#define EQ(a, b)	(strcmp((a), (b)) == 0) /* TRUE if strings a and b equal */
#define EQIC(a, b)	(strcmpic((a), (b)) == 0) /* as EQ() but case is insignificant */

/*
 * compare a header name 'nm' with a header field 'hf' to see if names match
 * return TRUE if match, FALSE if no match
 */
#define HDREQ(nm, hf)	(!strncmpic((nm), (hf), strlen((nm))) &&	\
			 ((hf)[strlen((nm))] == ':' ||			\
			  isspace((int) (hf)[strlen((nm))])))
/*
 * size for various names used in the configuration tables read from
 * the startup file, or compiled in with default.c.
 */
#define	CONFIG_NAMSIZ	16		/* 15 chars plus a nul byte */

/*
 * user and group ids are preset to BOGUS_USER and BOGUS_GROUP in order to
 * prevent them from being mistaken for root and wheel, and also these values
 * are normally used as defaults for the NOBODOY_[UG]ID to force the correct
 * values to be computed at runtime (see compute_nobody()).
 *
 * These values should of course also be invalid IDs on the target platform.
 */
#define BOGUS_USER	((uid_t) (-1))	/* not a valid user id */
#define BOGUS_GROUP	((gid_t) (-1))	/* not a valid group id */

/*
 * return the integer offset from the start of a given structure type
 * to a given tag.  (XXX should use (void *), especially for __STDC__)
 */
#define OFFSET(type, tag) \
    (int) ((char *) (&((struct type *) 0)->tag) - (char *) (struct type *) 0)

/* FIXME: get rid of this ugly hack! */
/* return the number of elements in an array. */
#define TABLESIZE(table) \
    (sizeof(table) / sizeof((table)[0]))

/* FIXME: get rid of this ugly hack! */
/* return a pointer to the end of a table. */
#define ENDTABLE(table) \
    ((table) + TABLESIZE(table))

/*
 * #defines for portability (may be used in other headers)
 */

#if !defined(sgi) && !defined(__STDC__)
/* damned SGI compiler complains if you undef an ANSI thing!!! */
# ifdef	NULL				/* make sure NULL is 0 */
#  undef NULL
# endif
# define NULL		0		/* the one true C `nil' pointer value */
#endif

#undef BELL
#if defined(__STDC__)
# define BELL		'\a'
#else
# define BELL		'\007'
#endif

#ifndef __P		/* in *BSD's <sys/cdefs.h>, included by everything! */
# if ((__STDC__ - 0) > 0) || defined(__cplusplus)
#  define __P(protos)	protos		/* full-blown ANSI C */
# else
#  define __P(protos)	()		/* traditional C */
# endif
#endif

#ifndef volatile	/* in *BSD's <sys/cdefs.h>, included by everything! */
# if !defined(__STDC__) && !defined(__cplusplus)/* ((__STDC__ - 0) > 0) ??? */
#  define volatile	/* NOTHING (most compilers won't optimize global variables) */
# endif
#endif

#ifndef const		/* in *BSD's <sys/cdefs.h>, included by everything! */
# if ((__STDC__ - 0) <= 0) && !defined(__cplusplus)
#  define const		/* NOTHING */
# endif
#endif

/*
 * Macro to test if we're using a GNU C compiler of a specific vintage
 * or later, for e.g. features that appeared in a particular version
 * of GNU C.  Usage:
 *
 *	#if __GNUC_PREREQ__(major, minor)
 *	...cool feature...
 *	#else
 *	...delete feature...
 *	#endif
 */
#if defined(__GNUC__) && !defined(__GNUC_PREREQ__)
#define	__GNUC_PREREQ__(x, y)						\
	((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) ||			\
	 (__GNUC__ > (x)))
#elif !defined(__GNUC_PREREQ__)
#define	__GNUC_PREREQ__(x, y)	0
#endif

/* adapt for GCC's lack of adherence to lint's standard ARGSUSED comment */
#if !__GNUC_PREREQ__(2, 5) && !defined(__attribute__)
# define __attribute__(x)	/* delete __attribute__ if non-gcc or old gcc */
#endif
/* old way.... */
#ifdef __GNUC__
# define GCC_UNUSED_HACK	__attribute__((unused))
#else
# define GCC_UNUSED_HACK	/* nothing */
#endif

/* NetBSD gained strsignal(3) sometime just prior to 1.0 */
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 100000000)
# define HAVE_STRSIGNAL		1
#endif
/* Note that __NetBSD_Version__ is only in 1.3.3 and -current >= 1.3C */
#if !defined(__NetBSD_Version__) && defined(NetBSD) && (NetBSD >= 1994100)
# define HAVE_STRSIGNAL		1
#endif

/* FreeBSD gained strsignal(3) sometime just prior to 4.0 */
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 400017)
# define HAVE_STRSIGNAL		1
#endif

/*
 * unfortunately doing these directly as typedefs would invite compile errors
 *
 * Worse, this way may re-define how the type is seen in our sources, though
 * hopefully any clashes in any system API/ABI calls will have been prototyped
 * with the correct typedef in an already-included system header.
 *
 * That won't stop know-it-all-compilers such as GCC from complaining though.
 */
#if !defined(pid_t) && !defined(HAVE_TYPE_PID_T)
typedef int		smail_pid_t;
# define pid_t		smail_pid_t
#endif
#if !defined(gid_t) && !defined(HAVE_TYPE_GID_T)
typedef unsigned int	smail_gid_t;
# define gid_t		smail_gid_t
#endif
#if !defined(uid_t) && !defined(HAVE_TYPE_UID_T)
typedef unsigned int	smail_uid_t;
# define uid_t		smail_uid_t
#endif
#if !defined(ssize_t) && !defined(HAVE_TYPE_SSIZE_T)
/* a signed version of size_t */
typedef unsigned long int smail_ssize_t;	/* XXX true for most 32-bit systems */
# define ssize_t	smail_ssize_t
#endif
#if !defined(blkcnt_t) && !defined(HAVE_TYPE_BLKCNT_T)
/* p1003.1-2001 blocks allocated for a file, e.g. struct stat st_blocks (signed) */
typedef long int	smail_blkcnt_t;		/* XXX true for older 32-bit systems */
# define blkcnt_t	smail_blkcnt_t
#endif
#if !defined(fsblkcnt_t) && !defined(HAVE_TYPE_FSBLKCNT_T)
/* p1003.1-2001 blocks allocated/free on a filesystem, e.g. struct stat[v]fs f_blocks (unsigned) */
typedef unsigned long int smail_fsblkcnt_t;	/* XXX true for older 32-bit systems */
# define fsblkcnt_t	smail_fsblkcnt_t
#endif
#if !defined(in_addr_t) && !defined(HAVE_TYPE_IN_ADDR_T)
typedef unsigned long int smail_in_addr_t;	/* XXX true for most 32-bit systems */
# define in_addr_t	smail_in_addr_t
#endif
#if !defined(in_port_t) && !defined(HAVE_TYPE_IN_PORT_T)
typedef unsigned short int smail_in_port_t;	/* XXX true for most 32-bit systems */
# define in_port_t	smail_in_port_t
#endif
#if !defined(socklen_t) && !defined(HAVE_TYPE_SOCKLEN_T)
typedef unsigned int	smail_socklen_t;	/* XXX true for most 32-bit systems */
# define socklen_t	smail_socklen_t
#endif

/* 
 * Local Variables:
 * c-file-style: "smail"
 * End:
 */
