/*
 * common.h  -  Common definitions for all host programs
 *
 * Copyright (C) 1996-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  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
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: common.h,v 1.22 2007/01/06 18:30:52 gkminix Exp $
 */

#ifndef COMMON_H
#define COMMON_H



/*
 * This file should not be included into any target source file
 */
#if defined(_TARGET_) || defined(_ASSEMBLY_)
#error Unable to include common.h into target source file
#endif



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



/*
 * Include commonly used C library headers
 */
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
#endif

#ifndef O_BINARY
# define O_BINARY 0
#endif

#include <errno.h>
#ifdef NEED_DECLARATION_ERRNO
extern int errno;
#endif

#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifndef MAXPATHLEN
# ifdef PATH_MAX
#  define MAXPATHLEN PATH_MAX
# else
#  define MAXPATHLEN 1024
# endif
#endif



/*
 * Define various macros to hide the differences between K&R and
 * ANSI C compilers.
 */
#if defined(__STDC__) || defined(_AIX) || (defined(__mips) && defined(_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
# ifndef HAVE_ANSI_CC
#  define HAVE_ANSI_CC 1
# endif
#else
# ifdef HAVE_ANSI_CC
#  undef HAVE_ANSI_CC
# endif
#endif

#ifndef voidstar
# ifdef HAVE_ANSI_CC
#  define voidstar void *
# else
#  define voidstar char *
# endif
#endif

#ifndef __P
# if defined(PROTOTYPES) || defined(HAVE_ANSI_CC)
#  define __P(args) args
# else
#  define __P(args) ()
# endif
#endif

#ifndef __F
# if defined(PROTOTYPES) || defined(HAVE_ANSI_CC)
#  define __F(arglist, args)	(args)
#  define __F_NOARGS		(void)
#  define AND			,
# else
#  define __F(arglist, args)	arglist args;
#  define __F_NOARGS		()
#  define AND			;
# endif
#endif

#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif



/*
 * Hide various GCC peculiarities
 */
#if !defined(__GNUC__) || __GNUC__ < 3
# define __attribute__(x)
#endif



/*
 * Define some generally useful macros. These are usually
 * already defined in sys/param.h, but on some systems they
 * might not.
 */
#ifndef roundup
# define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
#endif
#ifndef howmany
# define howmany(x, y)	(((x)+((y)-1))/(y))
#endif
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif



/*
 * sys/stat.h will also contain time_t which is required for nblib.h
 */
#include <sys/stat.h>

#ifdef STAT_MACROS_BROKEN
# ifdef S_ISDIR
#  undef S_ISDIR
# endif
# define S_ISDIR(mode)	(((mode) & S_IFMT) == S_IFDIR)
# ifdef S_ISREG
#  undef S_ISREG
# endif
# define S_ISREG(mode)	(((mode) & S_IFMT) == S_IFREG)
# ifdef S_ISCHR
#  undef S_ISCHR
# endif
# define S_ISCHR(mode)	(((mode) & S_IFMT) == S_IFCHR)
# ifdef S_ISBLK
#  undef S_ISBLK
# endif
# define S_ISBLK(mode)	(((mode) & S_IFMT) == S_IFBLK)
#endif

#ifdef HAVE_ASSERT_H
# include <assert.h>
#else
# undef assert
# define assert(expr)	((void)0)
#endif

#if defined(M_XENIX) && defined(I_286)
# undef __XENIX__
# define __XENIX__
#endif



/*
 * Check for packed attribute. This is necessary to match some C
 * structures to what the bootrom and the assembler modules expect.
 * Without the packed attribute at least the GNU C compiler aligns
 * byte variables to word boundaries which is not always correct.
 * Other compilers might be able to use the pack or align pragmas.
 */
#ifdef USE_PACKED
# define PACKED __attribute__((packed))
# undef USE_PRAGMA_PACK
# undef USE_PRAGMA_ALIGN
#endif

#ifdef USE_PRAGMA_PACK
# define PACKED
# undef USE_PACKED
# undef USE_PRAGMA_ALIGN
#endif

#ifdef USE_PRAGMA_ALIGN
# define PACKED
# undef USE_PACKED
# undef USE_PRAGMA_PACK
#endif

#ifndef PACKED
# define PACKED
#endif



/*
 * sys/types.h and unistd.h are required to include variable types
 * which define certain bit sized units.
 */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
# ifdef HAVE_STDINT_H
#  include <stdint.h>
# endif
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h>
#endif



/*
 * Define an integer type which has the same size as a pointer
 */
#ifndef HAVE_INTPTR_T
# if SIZEOF_INT_P == SIZEOF_UNSIGNED_LONG
typedef long		intptr_t;
typedef unsigned long	uintptr_t;
# else
#  if SIZEOF_INT_P == SIZEOF_UNSIGNED_INT
typedef int		intptr_t;
typedef unsigned int	uintptr_t;
#  else
#   if SIZEOF_INT_P == SIZEOF_UNSIGNED_SHORT
typedef short		intptr_t;
typedef unsigned short	uintptr_t;
#   else
#    error Unable to set size of pointer type
#   endif
#  endif
# endif
#endif



/*
 * Define maximum and minimum values for certain data types.
 */
#ifdef HAVE_LIMITS_H
# include <limits.h>
#else
# include <values.h>
#endif

#ifndef SHRT_MAX
# ifdef MAXSHORT
#  define SHRT_MAX MAXSHORT
# else
#  define SHRT_MAX ((short)(((unsigned short)(~0)) >> 1))
# endif
#endif

#ifndef INT_MAX
# ifdef MAXINT
#  define INT_MAX MAXINT
# else
#  define INT_MAX ((int)(((unsigned int)(~0)) >> 1))
# endif
#endif

#ifndef UINT_MAX
# define UINT_MAX ((unsigned int)(~0))
#endif

#ifndef LONG_MAX
# ifdef MAXLONG
#  define LONG_MAX MAXLONG
# else
#  define LONG_MAX ((long)(((unsigned long)(~0L)) >> 1))
# endif
#endif

#ifndef ULONG_MAX
# define ULONG_MAX ((unsigned long)(~0L))
#endif

#ifndef SHRT_MIN
# ifdef MINSHORT
#  define SHRT_MIN MINSHORT
# else
#  define SHRT_MIN ((short)(~SHRT_MAX))
# endif
#endif

#ifndef INT_MIN
# ifdef MININT
#  define INT_MIN MININT
# else
#  define INT_MIN ((int)(~INT_MAX))
# endif
#endif

#ifndef LONG_MIN
# ifdef MINLONG
#  define LONG_MIN MINLONG
# else
#  define LONG_MIN ((long)(~LONG_MAX))
# endif
#endif



/*
 * For seeking within files, re-define old BSD constants
 */
#if !defined(SEEK_SET) && defined(L_SET)
# define SEEK_SET	L_SET
#endif
#if !defined(SEEK_CUR) && defined(L_INCR)
# define SEEK_CUR	L_INCR
#endif
#if !defined(SEEK_END) && defined(L_XTND)
# define SEEK_END	L_XTND
#endif



/*
 * Check if we have proper networking support
 */
#if !defined(HAVE_NETDB_H) || !defined(HAVE_NETINET_IN_H) || !defined(HAVE_ARPA_INET_H)
#undef HAVE_INET
#else
#define HAVE_INET
#endif



/*
 * Different variants of UNIX use different ways accessing directories. Make
 * everything so that it looks like in dirent.h.
 */
#ifdef NEED_DIR
# if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
#  include <dirent.h>
#  undef NLENGTH
#  define NLENGTH(dirent) (strlen((dirent)->d_name))
# else
#  undef dirent
#  define dirent direct
#  undef NLENGTH
#  define NLENGTH(dirent) ((dirent)->d_namlen)
#  ifdef HAVE_SYS_NDIR_H
#   include <sys/ndir.h>
#  endif
#  ifdef HAVE_SYS_DIR_H
#   include <sys/dir.h>
#  endif
#  ifdef HAVE_NDIR_H
#   include <ndir.h>
#  endif
# endif
#endif



/*
 * Check for include files which define struct tm. Support for time_t is
 * included with sys/stat.h above, so for time_t alone we don't need this.
 */
#ifdef NEED_TIME
# ifdef TIME_WITH_SYS_TIME
#  include <time.h>
#  include <sys/time.h>
# else
#  if defined(HAVE_SYS_TIME_H) && defined(TM_IN_SYS_TIME)
#   include <sys/time.h>
#  else
#   include <time.h>
#  endif
# endif
#endif



/*
 * Do the usual checks for memory and string handling functions.
 */
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
# include <string.h>
# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
#  include <memory.h>
# endif
#else
# include <strings.h>
#endif



/*
 * Some glibc versions define strcmp as a macro even if they have it as
 * a routine. Unfortunately, the macro definition breaks YACC files.
 */
#if defined(__GLIBC__)
# ifdef strcmp
#  undef strcmp
# endif
#endif



/*
 * Next check for type definitions for 8, 16 and 32 bit variables.
 * The assembler modules expect most values in a specific size, and
 * we must ensure that the C programs produce the correct size.
 */
#ifdef USE_U_INT
# define __u8 u_int8_t
# define __u16 u_int16_t
# define __u32 u_int32_t
#else
# ifndef USE__UXX
#  ifndef U8_TYPE
#   if defined(CHAR_BIT) && CHAR_BIT == 8
#    define U8_TYPE unsigned char
#   else
#    error Unable to set 8-bit-type
#   endif
#  endif
#  ifndef U16_TYPE
#   if SIZEOF_UNSIGNED_INT == 2
#    define U16_TYPE unsigned int
#   else
#    if SIZEOF_UNSIGNED_SHORT == 2
#     define U16_TYPE unsigned short
#    else
#     error Unable to set 16-bit-type
#    endif
#   endif
#  endif
#  ifndef U32_TYPE
#   if SIZEOF_UNSIGNED_LONG == 4
#    define U32_TYPE unsigned long
#   else
#    if SIZEOF_UNSIGNED_INT == 4
#     define U32_TYPE unsigned int
#    else
#     error Unable to set 32-bit-type
#    endif
#   endif
#  endif
typedef U8_TYPE  __u8;
typedef U16_TYPE __u16;
typedef U32_TYPE __u32;
# endif
#endif



/*
 * Define some macros to allow a non-intel host system to produce
 * correct byte ordering code for the intel target system.
 */
#ifdef NEED_BINARY  /* No need to include this for utility programs */
# define swapbytes(a)	((((__u16)(a) & 0x00ff) << 8) | (((__u16)(a) & 0xff00) >> 8))
# define low_word(a)	((a) & 0x0000ffff)
# define high_word(a)	(((a) >> 16) & 0x0000ffff)
# define get_word(a)	((ttoh(getval(a))))
# define get_long(a)	((unsigned long)((ttoh(getval((a).high)) << 16) | \
						ttoh(getval((a).low))))
# ifndef WORDS_BIGENDIAN
#  define htot(a)		((__u16)(a))
#  define ttoh(a)		((unsigned short)(a))
# else
#  define htot(a)		((__u16)swapbytes(a))
#  define ttoh(a)		((unsigned short)swapbytes(a))
# endif
#endif /* NEED_BINARY */



/*
 * On some systems like SPARCs it is not possible to have integer variables
 * on misaligned addresses, so we have to use memcpy in that case.
 */
#ifdef NEED_BINARY  /* No need to include this for utility programs */
# ifdef USE_COPY

#  define assign(a, b)	mycopy((__u16 *)&(a), (__u16)(b))
	/*
	 * Copy a value out of a host system variable into a target system
	 * structure
	 */
	static inline void mycopy __F((a, b), __u16 *a AND const __u16 b)
	{
	  __u8 *p1 = (__u8 *)a;
	  __u8 *p2 = (__u8 *)&b;

	  /* Don't use memcpy here, that get's optimized away by gcc */
	  *p1++ = *p2++;
	  *p1   = *p2;
						   
	}

#  define getval(a)	mygetval((__u16 *)&(a))
	/*
	 * Return a value out of a target system structure
	 */
	static inline __u16 mygetval __F((a), const __u16 *a)
	{
	  __u16 b;
	  __u8 *p1 = (__u8 *)a;
	  __u8 *p2 = (__u8 *)&b;

	  /* Don't use memcpy here, that get's optimized away by gcc */
	  *p2++ = *p1++;
	  *p2   = *p1;
	  return(b);
	}

# else /* USE_COPY */

#  define assign(a, b)	a = b
#  define getval(a)	(a)

# endif /* USE_COPY */
#endif /* NEED_BINARY */



/*
 * Define the layout of Intel addresses and long words in memory.
 */
#ifdef USE_PRAGMA_PACK
#pragma pack(1)
#endif
#ifdef USE_PRAGMA_ALIGN
#pragma options align=packed
#endif

struct i_addr {
  __u16 offset;
  __u16 segment;
} PACKED;

typedef struct i_addr __fptr;		/* far pointer */


struct i_long {
  __u16 low;
  __u16 high;
} PACKED;

typedef struct i_long __lptr;		/* linear address */
typedef struct i_long __long;		/* long word */

#define __nptr __u16

#ifdef USE_PRAGMA_PACK
#pragma pack()
#endif
#ifdef USE_PRAGMA_ALIGN
#pragma options align=reset
#endif



/*
 * General definitions
 */
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif



/*
 * Include exit codes
 */
#include <exitcodes.h>



/*
 * Include version information
 */
#include <version.h>


#endif

