#ifndef __IX_H
#define __IX_H

/* This header provides prototypes for ixemul specific functions and
 * variables available in ixemul.library or libc.a.
 *
 * Each function is also documented in this header (or will be). Sometimes
 * an ixemul extension is described here, but for ease of use the original
 * prototype or macro is defined elsewhere.
 */

/* Some forward declarations... */

struct Library;
struct __res_state;
struct timeval;


/* This tells you which OS you are running on. */

extern int ix_os;

#define OS_IS_AMIGAOS   0
#define OS_IS_POS       0x704F5300      /* 'pOS\0' */


/* This is the name of the program without the path. E.g., if argv[0] is
 * "/ade/bin/cat", then __progname is "cat".
 */

extern char *__progname;


/* This macro can be ORed with the other flags you pass to open(). It will
 * make the open() function case sensitive. This macro is defined in
 * sys/fcntl.h.
 *
 * #define     O_CASE          0x1000
 */


/* Like vfork(), but the memory that the child allocates will be owned by
 * the child. vfork() uses the parent's memory list, but since ix_vfork() is
 * used as a fork() emulation, this would be undesirable, not in the least
 * because that memory wouldn't be released until the parent exits. Causing
 * a huge memory leak.
 */

int ix_vfork(void);


/* This function is used to obtain and set variables from ixemul.library.
 * In general, this is not a function you should call yourself.
 * Only the startup code should use this. If you need to call this
 * function for some reason, I recommend that the ix_get_variables()
 * function from crt0.c is used instead (see below).
 */

void ix_get_vars(int argc, char **ctype, int *_sys_nerr, 
 	         struct Library **sysbase, struct Library **dosbase,
 	         FILE ***fpp, char ***environ_out, char ***environ_in,
 	         int *real_errno, int *real_h_errno, struct __res_state *_res,
 	         int *_res_socket, int *ExecLib);


/* A wrapper function for ix_get_vars(). This is not an ixemul function,
 * but it is part of crt0.c. The single argument should be set to 0.
 */

void ix_get_variables(int from_vfork_setup_child);


/* This is a wrapper intended to make life just a little bit easier for those
 * who need to use the ix_vfork()/ix_vfork_resume() trick.  It replaces the old
 * 'ix_resident()/ix_get_vars()' pair.
 */

void ix_vfork_setup_child(void);


/* This is an implementation extension to the `real' ix_vfork(). Normally you
 * can only cause the parent to resume by calling _exit() or execve() from
 * the child. Since there is no real fork() in ixemul, this function
 * is a third possibility to make the parent resume. You have then two
 * concurrent processes sharing the same frame and global data. Please be
 * EXTREMELY careful what you may do and what not. ix_vfork() itself is a hack,
 * this is an even greater one...
 *
 * DO NOT use this function in combination with vfork(), or you'll get a big
 * memory leak. Only use it with ix_vfork().
 */

void ix_vfork_resume(void);


/* This function will show a requester with the given formatted string as
 * the body text and with one or two buttons. If button1 is NULL, then an
 * Abort button is shown. If button1 is not NULL, but button2 is, then only
 * a single button is shown. The title of the requester is passed in the
 * first argument. If that argument is NULL, then ixemul will use the program
 * name instead. Use this function to show a message in an OS independent
 * fashion.
 *
 * The function returns 0 is button1 is pressed and 1 otherwise.
 *
 * Example: ix_req(NULL, "Abort", NULL, "%s only supports AmigaOS!", __progname);
 * choice = ix_req(NULL, "Abort", "Continue", "Cannot find file %s", filename);
 */

int ix_req(char *title, char *button1, char *button2, char *fmt, ...);


/* Similar to chmod(), but obtains the original OS protection bits.
 * No translation to Unix protection bits has taken place.
 */

int ix_chmod(char *name, int mode);


/* Like select() but you can pass a pointer to an extra bitmask as the last
 * argument. In that case select() will also wait on these signal bits and
 * return if one of these signals came in. The contents of mask will be set
 * to the signals that arrived.
 */

int ix_select(int nfd, fd_set *ifd, fd_set *ofd, fd_set *efd,
              struct timeval *timeout, long *mask);


/* This function returns the internal OS filehandle for a given ixemul file
 * descriptor. Note that this function can return 0 as not every descriptor
 * is actually a file. Use this function very restrictively: it lets you
 * use OS functions on ixemul descriptors and mixing these two can be a
 * tricky thing.
 */

long ix_filehandle(int fd);


/* These two functions can be used to walk through all the segments in a
 * segmentlist. These functions are used by gdb using segment list pointers
 * obtained through the ptrace() call. They are generally used like this:
 *
 *      ix_segment *seg;
 *
 *	for (seg = ix_get_first_segment(seglist);
 *           seg;
 *           seg = ix_get_next_segment())
 *      {
 *        .....
 *      }
 */

/* These are the possible segment type values */
#define IX_SEG_TYPE_UNKNOWN 0
#define IX_SEG_TYPE_TEXT    1
#define IX_SEG_TYPE_DATA    2
#define IX_SEG_TYPE_BSS     3
#define IX_SEG_TYPE_MAX     3

/* The segment info is stored in this static (!) structure.
 * So you cannot walk through two segment lists at the same time
 * in the same program.
 */

typedef struct
{
  void *start;
  unsigned long size;
  int type;
} ix_segment;


/* The function prototypes */

ix_segment *ix_get_first_segment(long seglist);
ix_segment *ix_get_next_segment(void);


/* Clear the instruction cache from the given address with the given
 * length.
 */

void ix_clear_insn_cache(void *addr, int length);


/* Clear all caches */

void ix_clear_cache(void);


/* These two function query and set certain properties of ixemul.library.
 * Given a certain ID, ix_get_long will return the corresponding value or
 * -1 if not found. And ix_set_long will set the value of the given ID. It
 * returns -1 if it couldn't set the value and it returns the old value
 * otherwise.
 */

long ix_get_long(unsigned long id);
long ix_set_long(unsigned long id, long value);

/* Valid IDs: */

/* The version number of the library, output only */
#define IXID_VERSION      	0

/* The revision number of the library, output only */
#define IXID_REVISION     	1

/* Get/set the per-task freely usable user field, input/output */
#define IXID_USERDATA     	2

/* Get the pointer to the user struct, output only */
#define IXID_USER     		3

/* Get the number of reserved a4 pointers (for the shared ixlibraries),
 * output only.
 */
#define IXID_A4_PTRS   		4


int ix_obtain_socket(long id, int inet, int stream, int protocol);
int ix_release_socket(int fdes);

#if 0
/* TODO */
use geta4 in callbacks installed using funopen() when -resident
ix_resident
ix_geta4
ix_check_cpu
ix_tracecntl
ix_default_wb_window
SYSTEM_CALL (ix_get_gmt_offset, 473)
SYSTEM_CALL (ix_set_gmt_offset, 474)
SYSTEM_CALL (ix_get_default_settings, 475)
SYSTEM_CALL (ix_get_settings, 476)
SYSTEM_CALL (ix_set_settings, 477)
SYSTEM_CALL (__init_stk_limit, 480)
SYSTEM_CALL (__stkovf, 481)
SYSTEM_CALL (__stkext, 482)
SYSTEM_CALL (__stkext_f, 483)
SYSTEM_CALL (__stkrst, 484)
#endif

#endif
