/*
 * $RCSfile: datatrace.h,v $
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 *
 * $Log: datatrace.h,v $
 * Revision 1.2  1996/01/29 20:25:55  slm
 * Updated copyright and version.
 *
 * Revision 1.1  1995/07/28  21:29:10  slm
 * Initial revision
 *
 * Revision 1.1  1994/10/27  20:49:01  hkaram
 * Initial revision
 *
 * Revision 1.1  1994/07/22  21:08:40  hkaram
 * Initial revision
 */

/* Header file for the Data Tracing tool */

#ifndef datatrace_h
#define datatrace_h

#define TRACE_CIRCULAR
#define DT_FILE_EXT ".dt"
#define DT_VERSION  1

struct dt_object_struct;
typedef void (*dtCloseFunc)(struct dt_object_struct *, void *);

typedef struct dt_postamble_struct {
    char *buffer;
    int  size;
    struct dt_postamble_struct *next;
} dtpost;

typedef struct dt_filehdr_struct {
    int version;
    int bufferSize;
    int numberBuffers;
    int lastBufferIdx;
    int lastBufferSize;
} dthdr;

typedef struct dt_object_struct {
    char   *buffer;
    char   *current;
    char   *last;
    char   *traceName;
    int    fileSize;
    dthdr  fileHdr;
    dtpost *post;
    int    numPost;
    dtCloseFunc closeFunc;
    void   *closeArg;
    struct dt_object_struct *next;
} dt;

typedef struct dt_trace_map_struct {
    unsigned long size;
    unsigned long seek;
} dttracemapentry;

#define dtNumPostAmble(dtobj) ((dtobj)->numPost)

#ifdef TRACE_CIRCULAR

#define dtWrapBuffer(dtobj, len)                         \
	if (((dtobj)->current += len) > (dtobj)->last) { \
            dtFlushTraceObj(dtobj, 0);                   \
	    (dtobj)->current = (dtobj)->buffer;          \
	}

#else

#define dtWrapBuffer(dtobj, len) (dtobj)->current += len

#endif

#define dtTraceBuf(dtobj, buf, len) {        \
	bcopy((buf), (dtobj)->current, len); \
	dtWrapBuffer(dtobj, len);            \
}

#define dtTrace1(dtobj, item) {                         \
	bcopy(&(item), (dtobj)->current, sizeof(item)); \
	dtWrapBuffer(dtobj, sizeof(item));              \
}

#define dtTrace2(dtobj, item1, item2) {                                    \
	bcopy(&(item1), (dtobj)->current, sizeof(item1));                  \
	bcopy(&(item2), (dtobj)->current += sizeof(item1), sizeof(item2)); \
	dtWrapBuffer(dtobj, sizeof(item2));                                \
}

#define dtTrace3(dtobj, item1, item2, item3) {                             \
	bcopy(&(item1), (dtobj)->current, sizeof(item1));                  \
	bcopy(&(item2), (dtobj)->current += sizeof(item1), sizeof(item2)); \
	bcopy(&(item3), (dtobj)->current += sizeof(item2), sizeof(item3)); \
	dtWrapBuffer(dtobj, sizeof(item3));                                \
}

#define dtTrace4(dtobj, item1, item2, item3, item4) {                      \
	bcopy(&(item1), (dtobj)->current, sizeof(item1));                  \
	bcopy(&(item2), (dtobj)->current += sizeof(item1), sizeof(item2)); \
	bcopy(&(item3), (dtobj)->current += sizeof(item2), sizeof(item3)); \
	bcopy(&(item4), (dtobj)->current += sizeof(item3), sizeof(item4)); \
	dtWrapBuffer(dtobj, sizeof(item4));                                \
}

#define dtTrace5(dtobj, item1, item2, item3, item4, item5) {               \
	bcopy(&(item1), (dtobj)->current, sizeof(item1));                  \
	bcopy(&(item2), (dtobj)->current += sizeof(item1), sizeof(item2)); \
	bcopy(&(item3), (dtobj)->current += sizeof(item2), sizeof(item3)); \
	bcopy(&(item4), (dtobj)->current += sizeof(item3), sizeof(item4)); \
	bcopy(&(item5), (dtobj)->current += sizeof(item4), sizeof(item5)); \
	dtWrapBuffer(dtobj, sizeof(item5));                                \
}

#define dtTrace6(dtobj, item1, item2, item3, item4, item5, item6) {        \
	bcopy(&(item1), (dtobj)->current, sizeof(item1));                  \
	bcopy(&(item2), (dtobj)->current += sizeof(item1), sizeof(item2)); \
	bcopy(&(item3), (dtobj)->current += sizeof(item2), sizeof(item3)); \
	bcopy(&(item4), (dtobj)->current += sizeof(item3), sizeof(item4)); \
	bcopy(&(item5), (dtobj)->current += sizeof(item4), sizeof(item5)); \
	bcopy(&(item6), (dtobj)->current += sizeof(item5), sizeof(item6)); \
	dtWrapBuffer(dtobj, sizeof(item6));                                \
}

#endif /* !datatrace_h */

#ifdef __STDC__

dt              *dtCreateTraceObj(char *, char *, unsigned int, unsigned int);
void            dtFlushTraceObj(dt *, unsigned int);
void            dtLoadProtlRomOpts(Protl);
XkReturn        dtAppendPostAmble(dt *, char *, unsigned int);
XkReturn        dtInsertPostAmble(dt *, char *, unsigned int);
dt              *dtGetTraceObj(char *);
dt              *dtGetTopTraceObj(void);
dttracemapentry *dtGetTraceMap(dthdr *);
unsigned long   dtPostAmbleLocation(dthdr *);
void            dtRegisterCloseFunc(dt *, dtCloseFunc, void *);
void            dtClose(dt *);
void            dtCloseAll(void);

#else

dt              *dtCreateTraceObj();
void            dtFlushTraceObj();
void            dtLoadProtlRomOpts();
XkReturn        dtAppendPostAmble();
XkReturn        dtInsertPostAmble();
dt              *dtGetTraceObj();
dt              *dtGetTopTraceObj();
dttracemapentry *dtGetTraceMap();
unsigned long   dtPostAmbleLocation();
void            dtRegisterCloseFunc();
void            dtClose();
void            dtCloseAll();

#endif
