[comp.sources.amiga] v02i005: suplib - Matt's support library, Part01/02

page@swan.ulowell.edu (Bob Page) (10/22/88)

Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 5
Archive-name: util/suplib.1

[You need these library support routines and include files
to compile most of Matt's source code.		..Bob]

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	./suplib/break.c
#	./suplib/lunlink.c
#	./suplib/setfiledate.c
#	./suplib/NEW/compress.c
#	./suplib/NEW/checkmsg.a68
#	./suplib/NEW/waitmsg.a68
#	./suplib/NEW/ioctl.doc
#	./suplib/NEW/port.c
#	./suplib/NEW/putsmsg.c
#	./suplib/NEW/gethead.a68
#	./suplib/NEW/gettail.a68
#	./suplib/resource.asm
#	./suplib/dio.c
#	./suplib/asyncop.c
#	./suplib/enviroment.c
#	./suplib/typedefs.h
#	./suplib/xmisc.h
#	./suplib/dio.h
#	./suplib/conwin.c
#
if `test ! -d ./suplib`
then
  mkdir ./suplib
  echo "mkdir ./suplib"
fi
if `test ! -s ./suplib/break.c`
then
echo "writing ./suplib/break.c"
cat > ./suplib/break.c << '\Rogue\Monster\'

extern int Enable_Abort;

disablebreak()
{
    Enable_Abort = 0;
}

enablebreak()
{
    Enable_Abort = 1;
}


\Rogue\Monster\
else
  echo "will not over write ./suplib/break.c"
fi
if [ `wc -c ./suplib/break.c | awk '{printf $1}'` -ne 111 ]
then
echo `wc -c ./suplib/break.c | awk '{print "Got " $1 ", Expected " 111}'`
fi
if `test ! -s ./suplib/lunlink.c`
then
echo "writing ./suplib/lunlink.c"
cat > ./suplib/lunlink.c << '\Rogue\Monster\'

#include <local/xmisc.h>

XLIST *
lunlink(en)
register XLIST *en;
{
    if (en) {
	if (en->next)
	    en->next->prev = en->prev;
	*en->prev = en->next;
	en->next = NULL;
	en->prev = NULL;
    }
    return(en);
}



\Rogue\Monster\
else
  echo "will not over write ./suplib/lunlink.c"
fi
if [ `wc -c ./suplib/lunlink.c | awk '{printf $1}'` -ne 216 ]
then
echo `wc -c ./suplib/lunlink.c | awk '{print "Got " $1 ", Expected " 216}'`
fi
if `test ! -s ./suplib/setfiledate.c`
then
echo "writing ./suplib/setfiledate.c"
cat > ./suplib/setfiledate.c << '\Rogue\Monster\'

/*
 *  SETFILEDATE.C
 *
 *  BOOL = setfiledate(filename, date)
 */

#define BTOC(bptr)    ((long)(bptr) << 2)
#define CTOB(cptr)    ((long)(cptr) >> 2)

#ifndef ACTION_SET_DATE
#define ACTION_SET_DATE 34
#endif

typedef struct Task	      TASK;
typedef struct Process	      PROC;
typedef struct StandardPacket STDPKT;
typedef struct MsgPort	      MSGPORT;
typedef struct FileLock       LOCK;
typedef struct DateStamp      DATESTAMP;

extern TASK *FindTask();
extern void *AllocMem();

setfiledate(file, date)
char *file;
DATESTAMP *date;
{
    register STDPKT *packet;
    register char   *buf;
    register PROC   *proc;
    long	result;
    long	lock;

    {
	register long flock = Lock(file, SHARED_LOCK);
	register short i;
	register char *ptr = file;

	if (flock == NULL)
	    return(NULL);
	lock = ParentDir(flock);
	UnLock(flock);
	if (!lock)
	    return(NULL);
	for (i = strlen(ptr) - 1; i >= 0; --i) {
	    if (ptr[i] == '/' || ptr[i] == ':')
		break;
	}
	file += i + 1;
    }
    proc   = (PROC *)FindTask(NULL);
    packet = (STDPKT   *)AllocMem(sizeof(STDPKT), MEMF_CLEAR|MEMF_PUBLIC);
    buf = AllocMem(strlen(file)+2, MEMF_PUBLIC);
    strcpy(buf+1,file);
    buf[0] = strlen(file);

    packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
    packet->sp_Pkt.dp_Link = &packet->sp_Msg;
    packet->sp_Pkt.dp_Port = &proc->pr_MsgPort;
    packet->sp_Pkt.dp_Type = ACTION_SET_DATE;
    packet->sp_Pkt.dp_Arg1 = NULL;
    packet->sp_Pkt.dp_Arg2 = (long)lock;        /*  lock on parent dir of file  */
    packet->sp_Pkt.dp_Arg3 = (long)CTOB(buf);   /*  BPTR to BSTR of file name   */
    packet->sp_Pkt.dp_Arg4 = (long)date;        /*  APTR to datestamp structure */
    PutMsg(((LOCK *)BTOC(lock))->fl_Task, packet);
    WaitPort(&proc->pr_MsgPort);
    GetMsg(&proc->pr_MsgPort);
    result = packet->sp_Pkt.dp_Res1;
    FreeMem(packet, sizeof(STDPKT));
    FreeMem(buf, strlen(file)+2);
    UnLock(lock);
    return(result);
}

\Rogue\Monster\
else
  echo "will not over write ./suplib/setfiledate.c"
fi
if [ `wc -c ./suplib/setfiledate.c | awk '{printf $1}'` -ne 1951 ]
then
echo `wc -c ./suplib/setfiledate.c | awk '{print "Got " $1 ", Expected " 1951}'`
fi
if `test ! -d ./suplib/NEW`
then
  mkdir ./suplib/NEW
  echo "mkdir ./suplib/NEW"
fi
if `test ! -s ./suplib/NEW/compress.c`
then
echo "writing ./suplib/NEW/compress.c"
cat > ./suplib/NEW/compress.c << '\Rogue\Monster\'

/*
 *  Independant compress/uncompress module.  User must supply the
 *  following routines:
 *
 *  c	  = cgetchar()          (returns EOF on end/error)
 *  (void)  cputchar(c)
 *  len   = cread(buf, len)     (returns EOF on end/error)
 *  (void)  cwrite(buf, len)
 *
 *  Calls:	Compress(filesize)      (filesize used only to optimize hash table)
 *		UnCompress()
 */

#include <stdio.h>

#ifndef min
#define min(a,b)        ((a>b) ? b : a)
#endif

#define BITS		13

#if BITS == 16
#define HSIZE  69001	       /* 95% occupancy */
#endif
#if BITS == 15
#define HSIZE  35023	       /* 94% occupancy */
#endif
#if BITS == 14
#define HSIZE  18013	       /* 91% occupancy */
#endif
#if BITS == 13
#define HSIZE  9001	       /* 91% occupancy */
#endif
#if BITS <= 12
#define HSIZE  5003	       /* 80% occupancy */
#endif

typedef long		code_int;
typedef long		count_int;
typedef unsigned char	char_type;
typedef unsigned short	uword;

#define MAXCODE(n_bits)  ((1 << (n_bits)) - 1)
#define INIT_BITS 9			/* initial number of bits/code */

static int n_bits;			       /* number of bits/code		   */
static int maxbits;			       /* user settable max # bits/code    */
static code_int maxcode;		       /* maximum code, given n_bits	   */
static code_int maxmaxcode;		       /* should NEVER generate this code  */
static long  CLen;

static count_int   htab[HSIZE];
static uword	   codetab[HSIZE];

#define htabof(i)       htab[i]
#define codetabof(i)    codetab[i]

static code_int hsize = HSIZE;		       /* for dynamic table sizing */

#define tab_prefixof(i)     codetabof(i)
#define tab_suffixof(i)     ((char_type *)(htab))[i]
#define de_stack	    ((char_type *)&tab_suffixof(1<<BITS))

static code_int free_ent;		       /* first unused entry */

code_int getcode();

#define CHECK_GAP 10000 /* ratio check interval */

static int     block_compress = 1;
static int     clear_flg;
static long    ratio;
static count_int checkpoint;

#define FIRST	257	/* first free entry */
#define CLEAR	256	/* table clear output code */

static int offset;
long int in_count = 1;			/* length of input */

void
Compress(fsize)
{
    long fcode;
    code_int i = 0;
    int c;
    code_int ent;
    int disp;
    code_int hsize_reg;
    int hshift;

    bzero(htab, sizeof(htab));
    bzero(codetab, sizeof(codetab));
    CLen = 0;

    hsize = HSIZE;
    if ( fsize < (1 << 12) )
	hsize = min ( 5003, HSIZE );
    else if ( fsize < (1 << 13) )
	hsize = min ( 9001, HSIZE );
    else if ( fsize < (1 << 14) )
	hsize = min ( 18013, HSIZE );
    else if ( fsize < (1 << 15) )
	hsize = min ( 35023, HSIZE );
    else if ( fsize < 47000 )
	hsize = min ( 50021, HSIZE );

    offset = clear_flg = ratio = 0;
    in_count = 1;
    checkpoint = CHECK_GAP;
    n_bits  = INIT_BITS;		/* number of bits/code		    */
    maxbits = BITS;			/* user settable max # bits/code    */
    maxcode = MAXCODE(INIT_BITS);       /* maximum code, given n_bits       */
    maxmaxcode = 1 << BITS;		/* should NEVER generate this code  */
    free_ent = ((block_compress) ? FIRST : 256 );

    ent = ngetchar();

    hshift = 0;
    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
	hshift++;
    hshift = 8 - hshift;		/* set hash code range bound */

    hsize_reg = hsize;
    cl_hash((count_int)hsize_reg);      /* clear hash table */

    while ((c = ngetchar()) != EOF) {
	in_count++;
	fcode = (long) (((long) c << maxbits) + ent);
	i = ((c << hshift) ^ ent);      /* xor hashing */

	if (htabof (i) == fcode) {
	    ent = codetabof(i);
	    continue;
	} else if ((long)htabof (i) < 0)    /* empty slot */
	    goto nomatch;
	disp = hsize_reg - i;		/* secondary hash (after G. Knott) */
	if (i == 0)
	    disp = 1;
probe:
	if ((i -= disp) < 0)
	    i += hsize_reg;

	if (htabof (i) == fcode) {
	    ent = codetabof(i);
	    continue;
	}
	if ((long)htabof (i) > 0)
	    goto probe;
nomatch:
	output ((code_int) ent);
	ent = c;
	if (free_ent < maxmaxcode) {
	    codetabof(i) = free_ent++; /* code -> hashtable */
	    htabof(i) = fcode;
	}
	else if ((count_int)in_count >= checkpoint && block_compress)
	    cl_block ();
    }

    /*
     * Put out the final code.
     */

    output((code_int)ent);
    output((code_int)-1);
}

static char buf[BITS];

char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

output( code )
code_int  code;
{
    register int r_off = offset, bits= n_bits;
    register char * bp = buf;

    if ( code >= 0 ) {
	/*
	 * Get to the first byte.
	 */
	bp += (r_off >> 3);
	r_off &= 7;
	/*
	 * Since code is always >= 8 bits, only need to mask the first
	 * hunk on the left.
	 */
	*bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
	bp++;
	bits -= (8 - r_off);
	code >>= 8 - r_off;
	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
	if ( bits >= 8 ) {
	    *bp++ = code;
	    code >>= 8;
	    bits -= 8;
	}
	/* Last bits. */
	if(bits)
	    *bp = code;

	offset += n_bits;
	if (offset == (n_bits << 3)) {
	    bp = buf;
	    bits = n_bits;
	    cwrite(bp, bits);
	    CLen += bits;
	    bp += bits;
	    bits = 0;
	    offset = 0;
	}

	/*
	 * If the next entry is going to be too big for the code size,
	 * then increase it, if possible.
	 */

	if (free_ent > maxcode || (clear_flg > 0)) {
	    /*
	     * Write the whole buffer, because the input side won't
	     * discover the size increase until after it has read it.
	     */
	    if (offset > 0)
		cwrite(buf, n_bits);
	    offset = 0;

	    if (clear_flg) {
		n_bits = INIT_BITS;
		maxcode = MAXCODE(INIT_BITS);
		clear_flg = 0;
	    } else {
		n_bits++;
		if (n_bits == maxbits)
		    maxcode = maxmaxcode;
		else
		    maxcode = MAXCODE(n_bits);
	    }
	}
    } else {
	/*
	 * At EOF, write the rest of the buffer.
	 */
	if (offset > 0)
	    cwrite(buf, (offset + 7) / 8);
	offset = 0;
    }
}

cl_block()             /* table clear for block compress */
{
    register long int rat;

    checkpoint = in_count + CHECK_GAP;

    if (in_count > 0x007fffff) { /* shift will overflow */
	rat = CLen >> 8;
	if (rat == 0) {          /* Don't divide by zero */
	    rat = 0x7fffffff;
	} else {
	    rat = in_count / rat;
	}
    } else {
	rat = (in_count << 8) / CLen;      /* 8 fractional bits */
    }
    if (rat > ratio) {
	ratio = rat;
    } else {
	ratio = 0;
	cl_hash ( (count_int) hsize );
	free_ent = FIRST;
	clear_flg = 1;
	output ( (code_int) CLEAR );
    }
}

cl_hash(hsize)          /* reset code table */
	register count_int hsize;
{
	register count_int *htab_p = htab+hsize;
	register long i;
	register long m1 = -1;

	i = hsize - 16;
	do {				/* might use Sys V memset(3) here */
		*(htab_p-16) = m1;
		*(htab_p-15) = m1;
		*(htab_p-14) = m1;
		*(htab_p-13) = m1;
		*(htab_p-12) = m1;
		*(htab_p-11) = m1;
		*(htab_p-10) = m1;
		*(htab_p-9) = m1;
		*(htab_p-8) = m1;
		*(htab_p-7) = m1;
		*(htab_p-6) = m1;
		*(htab_p-5) = m1;
		*(htab_p-4) = m1;
		*(htab_p-3) = m1;
		*(htab_p-2) = m1;
		*(htab_p-1) = m1;
		htab_p -= 16;
	} while ((i -= 16) >= 0);
	for ( i += 16; i > 0; i-- )
		*--htab_p = m1;
}

void
UnCompress()
{
    register char_type *stackp;
    register int finchar;
    register code_int code, oldcode, incode;

    /*
     * As above, initialize the first 256 entries in the table.
     */

    bzero(htab, sizeof(htab));
    bzero(codetab, sizeof(codetab));

    offset = clear_flg = ratio = 0;
    in_count = 1;
    checkpoint = CHECK_GAP;
    n_bits  = INIT_BITS;		/* number of bits/code		    */
    maxbits = BITS;			/* user settable max # bits/code    */
    maxcode = MAXCODE(INIT_BITS);       /* maximum code, given n_bits       */
    maxmaxcode = 1 << BITS;		/* should NEVER generate this code  */

    for ( code = 255; code >= 0; code-- ) {
	tab_prefixof(code) = 0;
	tab_suffixof(code) = (char_type)code;
    }
    free_ent = ((block_compress) ? FIRST : 256 );

    finchar = oldcode = getcode();
    if (oldcode == -1)          /* EOF already? */
	return; 		/* Get out of here */
    cputchar((char)finchar);       /* first code must be 8 bits = char */
    ++CLen;
    stackp = de_stack;

    while ((code = getcode()) > -1) {
	if ((code == CLEAR) && block_compress) {
	    for (code = 255; code >= 0; code--)
		tab_prefixof(code) = 0;
	    clear_flg = 1;
	    free_ent = FIRST - 1;
	    if ((code = getcode()) == -1)   /* O, untimely death! */
		break;
	}
	incode = code;
	/*
	 * Special case for KwKwK string.
	 */
	if (code >= free_ent) {
	    *stackp++ = finchar;
	    code = oldcode;
	}

	/*
	 * Generate output characters in reverse order
	 */
	while ( code >= 256 ) {
	    *stackp++ = tab_suffixof(code);
	    code = tab_prefixof(code);
	}
	*stackp++ = finchar = tab_suffixof(code);

	/*
	 * And put them out in forward order
	 */
	do {
	    cputchar (*--stackp);
	    ++CLen;
	}
	while (stackp > de_stack);

	/*
	 * Generate the new entry.
	 */
	if ((code=free_ent) < maxmaxcode) {
	    tab_prefixof(code) = (unsigned short)oldcode;
	    tab_suffixof(code) = finchar;
	    free_ent = code+1;
	}
	/*
	 * Remember previous code.
	 */
	oldcode = incode;
    }
}

code_int
getcode()
{
    /*
     * On the VAX, it is important to have the register declarations
     * in exactly the order given, or the asm will break.
     */

    register code_int code;
    static int offset = 0, size = 0;
    static char_type buf[BITS];
    register int r_off, bits;
    register char_type *bp = buf;

    if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
	/*
	 * If the next entry will be too big for the current code
	 * size, then we must increase the size.  This implies reading
	 * a new buffer full, too.
	 */
	if ( free_ent > maxcode ) {
	    n_bits++;
	    if ( n_bits == maxbits )
		maxcode = maxmaxcode;	/* won't get any bigger now */
	    else
		maxcode = MAXCODE(n_bits);
	}
	if ( clear_flg > 0) {
	    maxcode = MAXCODE (n_bits = INIT_BITS);
	    clear_flg = 0;
	}
	size = cread(buf, n_bits);
	if (size <= 0)
	    return -1;			/* end of file */
	offset = 0;
	size = (size << 3) - (n_bits - 1);
    }
    r_off = offset;
    bits = n_bits;

	/*
	 * Get to the first byte.
	 */
	bp += (r_off >> 3);
	r_off &= 7;
	/* Get first part (low order bits) */

	code = (*bp++ >> r_off);

	bits -= (8 - r_off);
	r_off = 8 - r_off;		/* now, offset into code word */
	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
	if ( bits >= 8 ) {
	    code |= *bp++ << r_off;
	    r_off += 8;
	    bits -= 8;
	}
	/* high order bits. */
	code |= (*bp & rmask[bits]) << r_off;

    offset += n_bits;

    return code;
}


#asm
	    ;	static (to this module only) bzero... simple and
	    ;	stupid.  Non critical.

_bzero:     move.l  4(sp),A0
	    move.l  8(sp),D0
	    beq     .bz2
.bz1	    clr.b   D1
	    move.b  D1,(A0)+
	    subq.l  #1,D0
	    bne     .bz1
.bz2	    rts
#endasm

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/compress.c"
fi
if [ `wc -c ./suplib/NEW/compress.c | awk '{printf $1}'` -ne 10805 ]
then
echo `wc -c ./suplib/NEW/compress.c | awk '{print "Got " $1 ", Expected " 10805}'`
fi
if `test ! -s ./suplib/NEW/checkmsg.a68`
then
echo "writing ./suplib/NEW/checkmsg.a68"
cat > ./suplib/NEW/checkmsg.a68 << '\Rogue\Monster\'

		public	_CheckMsg

NT_MESSAGE	equ	5
NT_FREEMSG	equ	6
NT_REPLYMSG	equ	7

CheckMsg:
		move.l	4(sp),A0            ; message
		clr.l	D0
		cmp.b	#NT_MESSAGE,8(A0)   ; type
		beq	.1
		move.l	A0,D0
.1		rts

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/checkmsg.a68"
fi
if [ `wc -c ./suplib/NEW/checkmsg.a68 | awk '{printf $1}'` -ne 202 ]
then
echo `wc -c ./suplib/NEW/checkmsg.a68 | awk '{print "Got " $1 ", Expected " 202}'`
fi
if `test ! -s ./suplib/NEW/waitmsg.a68`
then
echo "writing ./suplib/NEW/waitmsg.a68"
cat > ./suplib/NEW/waitmsg.a68 << '\Rogue\Monster\'

		public	_WaitMsg
		public	_LVOWait
		public	_SysBase

NT_MESSAGE	equ	5
NT_FREEMSG	equ	6
NT_REPLYMSG	equ	7

_WaitMsg:
		movem.l A2/A6,-(sp)
		move.l	12(sp),A2           ; A2 = message
		move.l	_SysBase,A6
.1		cmp.b	#NT_REPLYMSG,8(A2)  ; has it been replied?
		beq	.10
.2		cmp.b	#NT_FREEMSG,8(A2)   ; has it been freed?
		beq	.15
		move.l	14(A2),A1           ; reply port
		tst.l	A1
		beq	.1		    ; NULL reply port, busy wait.
		move.b	15(A1),D1           ; signal bit #
		moveq.l #1,D0
		asl.l	D1,D0		    ; D0 = signal mask
		jsr	_LVOWait(A6)        ; wait for signal
		bra	.1		    ; loop again
.10		jsr	_LVODisable(A6)
		move.l	A2,A1
		jsr	_LVORemove(A6)
		jsr	_LVOEnable(A6)
.15		movem.l (sp)+,A2/A6         ; return the message
		move.l	A2,D0
		rts

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/waitmsg.a68"
fi
if [ `wc -c ./suplib/NEW/waitmsg.a68 | awk '{printf $1}'` -ne 754 ]
then
echo `wc -c ./suplib/NEW/waitmsg.a68 | awk '{print "Got " $1 ", Expected " 754}'`
fi
if `test ! -s ./suplib/NEW/ioctl.doc`
then
echo "writing ./suplib/NEW/ioctl.doc"
cat > ./suplib/NEW/ioctl.doc << '\Rogue\Monster\'

			    IOCTL.DOC

IO control interface

		    (main routines)

	     IoOpen("device")
    result = IoCtl(fd,cmd,arg1,arg2)
    result = IoAbort(fd)
    fd2    = IoDup(fd)
	     IoClose(fd)

		    (useful macros)

	     IoRead(fd,buf,len)                 normal io
	     IoReadA(fd,buf,len)
	     IoWrite(fd,buf,len)
	     IoWriteA(fd,buf,len)
	     IoReadExt(fd,buf,len,offset)       extended io
	     IoWriteExt(fd,buf,len,offset)
	     IoReadExtA(fd,buf,len,offset)
	     IoWriteExtA(fd,buf,len,offset)

    cmd:    FEDCBA98  76543210	 FEDCBA9876543210
	    <GENFLGS> <SPECFLGS> <COMMAND NUMBER>

    General Flags:  Device Independant flags
    Specific Flags: Device Dependant flags (reused by devices)
    Command Number: Command # (unique)



		GENERAL CALLS

    IOF_ASYNC	    asynchronous flag (result will be negative or 0)

    IOC_RESET	    reset device
    IOC_READ	    read or start asynch read
    IOC_WRITE	    write or start asynch write
    IOC_UPDATE	    update device
    IOC_CLEAR	    clear device
    IOC_STOP	    stop device
    IOC_START	    start device
    IOC_FLUSH	    flush device

    IOC_FLAGS	    IoCtl flags:    IOCF_NBIO	    non-blocking IO
				    IOCF_TIMEOUT    if not IOCF_NBIO, block abort timeout
    IOC_TIMEOUT     set automatic timeout period (default 0=disabled)
    IOC_SIGNAL	    return associated signal
    IOC_SETSIG	    set associated SigNo.
    IOC_CHECK	    check pending request (-1=pulled, 0=ready, 1=pending)
    IOC_WAIT	    wait for pending request

		IOCTL DEVICE

    IOC_IOCADDDEVICE
    IOC_IOCREMDEVICE

		AUDIO DEVICE

    IOC_AUDFLAGS    set/clear ADIOF_* flags
    IOC_AUDFREE     (normal device call)
    IOC_AUDSETPREC
    IOC_AUDFINISH
    IOC_AUDPERVOL
    IOC_AUDLOCK
    IOC_AUDWAITCYC

		CLIPBOARD DEVICE

    IOC_CLPOST
    IOC_CLCREADID
    IOC_CLCWRITEID

		CONSOLE DEVICE

    IOC_CONASKKEYMAP
    IOC_CONSETKEYMAP
    IOC_CONASKDEFKM
    IOC_CONSETDEFKM

		GAMEPORT DEVICE

    IOC_GPFLAGS
    IOC_GPREADEVENT
    IOC_GPASKCTYPE
    IOC_GPSETCTYPE
    IOC_GPASKTRIGGER
    IOC_GPSETTRIGGER

		INPUT DEVICE

    IOC_IDADDHANDLER
    IOC_IDREMHANDLER
    IOC_IDWRITEEVENT
    IOC_IDSETTHRESH
    IOC_IDSETPERIOD
    IOC_IDSETMPORT
    IOC_IDSETMTYPE
    IOC_IDSETMTRIG

		KEYBOARD DEVICE

    IOC_KBREADEVENT
    IOC_KBREADMATRIX
    IOC_KBADDRESHANDLER
    IOC_KBREMRESHANDLER
    IOC_KBRESHANDLERDONE

		NARRATOR DEVICE

		PARALLEL DEVICE

    IOC_PARFLAGS
    IOC_PARQUERY
    IOC_PARPARAMS

		PRINTER DEVICE

    IOC_PRTRAWWRITE
    IOC_PRTCOMMAND
    IOC_PRTDUMPRPORT

		SERIAL DEVICE

    IOC_SERFLAGS
    IOC_SERSEXFLAGS
    IOC_SERQUERY
    IOC_SERBREAK
    IOC_SERPARAMS

		TIMER DEVICE

    IOC_TRSETUNIT
    IOC_TRADDREQUEST
    IOC_TRGETSYSTIME
    IOC_TRSETSYSTIME

		TRACKDISK DEVICE

    IOF_TDEXTCOM

    IOC_TDSETOFFSET
    IOC_TDFLAGS

    IOC_TDMOTOR
    IOC_TDSEEK
    IOC_TDFORMAT
    IOC_TDREMOVE
    IOC_TDCHANGENUM
    IOC_TDCHANGESTATE
    IOC_TDPROTSTATUS
    IOC_TDRAWREAD
    IOC_TDRAWWRITE
    IOC_TDGETDRIVETYPE
    IOC_TDGETNUMTRACKS
    IOC_TDADDCHANGEINT
    IOC_TDREMCHANGEINT



\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/ioctl.doc"
fi
if [ `wc -c ./suplib/NEW/ioctl.doc | awk '{printf $1}'` -ne 3089 ]
then
echo `wc -c ./suplib/NEW/ioctl.doc | awk '{print "Got " $1 ", Expected " 3089}'`
fi
if `test ! -s ./suplib/NEW/port.c`
then
echo "writing ./suplib/NEW/port.c"
cat > ./suplib/NEW/port.c << '\Rogue\Monster\'

/*
 *  CreateUniquePort(name, pri)
 *  DeleteUniquePort(port)
 */

#include <exec/types.h>
#include <typdefs.h>

typedef struct MsgPort PORT;

PORT *
CreateUniquePort(name, priority)
char *name;
{
    register int n = 0;
    register char *ptr;
    register PORT *port;
    char buf[64];

    Forbid();
    if (ptr = name) {
	strcpy(buf, name);
	while (FindPort(buf))
	    sprintf(buf, "%s.%d\n", name, ++n);
	if (ptr = AllocMem(strlen(buf)+1, MEMF_PUBLIC)) {
	    strcpy(ptr, buf);
	} else {
	    Permit();
	    return(NULL);
	}
    }
    if (!(port = CreatePort(ptr, priority)) && ptr)
	FreeMem(ptr, strlen(ptr)+1);
    Permit();
    return(port);
}

DeleteUniquePort(port)
register PORT *port;
{
    register char *name;

    RemPort(port);
    if (name = port->mp_Node.ln_Name) {
	FreeMem(name, strlen(name)+1);
	port->mp_Node.ln_Name = NULL;
    }
    DeletePort(port);
}

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/port.c"
fi
if [ `wc -c ./suplib/NEW/port.c | awk '{printf $1}'` -ne 879 ]
then
echo `wc -c ./suplib/NEW/port.c | awk '{print "Got " $1 ", Expected " 879}'`
fi
if `test ! -s ./suplib/NEW/putsmsg.c`
then
echo "writing ./suplib/NEW/putsmsg.c"
cat > ./suplib/NEW/putsmsg.c << '\Rogue\Monster\'

#include <exec/types.h>
#include <typedefs.h>

typedef struct Port PORT;
typedef struct Message MSG;

PutSyncMsg(port, msg)
PORT *port;
MSG *msg;
{

}


PutSyncMsgSimple(port, ptr, cmd)
PORT *port;
MSG *msg;
{

}

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/putsmsg.c"
fi
if [ `wc -c ./suplib/NEW/putsmsg.c | awk '{printf $1}'` -ne 215 ]
then
echo `wc -c ./suplib/NEW/putsmsg.c | awk '{print "Got " $1 ", Expected " 215}'`
fi
if `test ! -s ./suplib/NEW/gethead.a68`
then
echo "writing ./suplib/NEW/gethead.a68"
cat > ./suplib/NEW/gethead.a68 << '\Rogue\Monster\'

;   GETHEAD(list)
;   NEXTNODE(node)
;	    4(sp)


	    public  _gethead
	    public  _nextnode

_nextnode:
_gethead:
	    move.l  4(sp),A0    ;A0 = list or node
	    move.l  (A0),A1     ;A1 = lh_Head or ln_Succ
	    move.l  A1,D0	;D0 = result
	    tst.l   (A1)        ;does it point to lh_Tail?
	    bne     .1		;no
	    clr.l   D0		;yes
.1	    rts

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/gethead.a68"
fi
if [ `wc -c ./suplib/NEW/gethead.a68 | awk '{printf $1}'` -ne 352 ]
then
echo `wc -c ./suplib/NEW/gethead.a68 | awk '{print "Got " $1 ", Expected " 352}'`
fi
if `test ! -s ./suplib/NEW/gettail.a68`
then
echo "writing ./suplib/NEW/gettail.a68"
cat > ./suplib/NEW/gettail.a68 << '\Rogue\Monster\'

;   GETTAIL(list)
;	    4(sp)


	    public  _gettail

_gettail:
	    move.l  4(sp),A0    ;A0 = list
	    move.l  8(A0),A1    ;A1 = lh_TailPred
	    move.l  A1,D0	;D0 = result
	    cmp.l   A1,A0	;is it pointing to lh_Head?
	    bne     .1		;no
	    clr.l   D0		;yes
.1	    rts

\Rogue\Monster\
else
  echo "will not over write ./suplib/NEW/gettail.a68"
fi
if [ `wc -c ./suplib/NEW/gettail.a68 | awk '{printf $1}'` -ne 279 ]
then
echo `wc -c ./suplib/NEW/gettail.a68 | awk '{print "Got " $1 ", Expected " 279}'`
fi
if `test ! -s ./suplib/resource.asm`
then
echo "writing ./suplib/resource.asm"
cat > ./suplib/resource.asm << '\Rogue\Monster\'

 ;
 ;  EXEC resource support
 ;			       4(sp)  8(sp)
 ;	AutoAllocMiscResource(resno, value)
 ;	    resno:  MR_SERIALPORT, SERIALBITS, PARALLELPORT, PARALLELBITS
 ;	    value:  -1 to allocate, 0 to check
 ;
 ;	    returns 0 on success
 ;
 ;	AutoFreeMiscResource(resno)
 ;			      4(sp)
 ;	    Free a misc resource you allocated
 ;
 ;	No need to open the misc.resource

	    public  _AutoAllocMiscResource
	    public  _AutoFreeMiscResource
	    public  _LVOOpenResource

	    FAR     DATA

_AutoAllocMiscResource:
	    move.l  A6,-(sp)
	    bsr     OpenMiscResource
	    beq     amfail
	    move.l  8(sp),D0
	    move.l  12(sp),A1
	    jsr     -6(A6)
	    bra     amret
amfail	    moveq.l #-1,D0
amret	    move.l  (sp)+,A6
	    rts

_AutoFreeMiscResource:
	    move.l  A6,-(sp)
	    bsr     OpenMiscResource
	    beq     fmret
	    move.l  8(sp),D0
	    jsr     -12(A6)
fmret	    move.l  (sp)+,A6
	    rts

OpenMiscResource:
	    move.l  4,A6
	    lea.l   MiscName,A1
	    jsr     _LVOOpenResource(A6)
	    move.l  D0,A6
	    tst.l   D0
	    rts

MiscName:   dc.b    "misc.resource",0



\Rogue\Monster\
else
  echo "will not over write ./suplib/resource.asm"
fi
if [ `wc -c ./suplib/resource.asm | awk '{printf $1}'` -ne 1089 ]
then
echo `wc -c ./suplib/resource.asm | awk '{print "Got " $1 ", Expected " 1089}'`
fi
if `test ! -s ./suplib/dio.c`
then
echo "writing ./suplib/dio.c"
cat > ./suplib/dio.c << '\Rogue\Monster\'

/*
 *  DIO.C
 *
 *  (C)Copyright 1987 by Matthew Dillon, All rights reserved
 *  Freely distributable.  Donations Welcome.  This is NOT shareware,
 *  This is NOT public domain.
 *
 *	Matthew Dillon
 *	891 Regal Rd.
 *	Berkeley, Ca. 94708
 *
 *  EXEC device driver IO support routines... makes everything easy.
 *
 *  dfd = dio_open(name, unit, flags, req/NULL)
 *
 *	open an IO device.  Note: in some cases you might have to provide
 *	a request structure with some fields initialized (example, the
 *	console device requires certain fields to be initialized).  For
 *	instance, if openning the SERIAL.DEVICE, you would want to give
 *	an IOExtSer structure which is completely blank execept for the
 *	io_SerFlags field.
 *
 *	The request structure's message and reply ports need not be
 *	initialized.  The request structure is no longer needed after
 *	the dio_open().
 *
 *	NULL = error, else descriptor (a pointer) returned.
 *
 *
 *  dio_close(dfd)
 *
 *	close an IO device.  Any pending asyncronous requests are
 *	AbortIO()'d and then Wait'ed on for completion.
 *
 *
 *  dio_closegrp(dfd)
 *
 *	close EVERY DIO DESCRIPTOR ASSOCIATED WITH THE dio_open() call
 *	that was the parent for this descriptor.  That is, you can get
 *	a descriptor using dio_open(), dio_dup() it a couple of times,
 *	then use dio_closegrp() on any ONE of the resulting descriptors
 *	to close ALL of them.
 *
 *
 *  dio_ddl(dfd,bool)
 *
 *	Disable BUF and LEN fields in dio_ctl[_to].. dummy parameters
 *	must still be passed, but they are not loaded into the io_Data
 *	and io_Length fields of the io request.  This is for devices
 *	like the AUDIO.DEVICE which has io_Data/io_Length in non-standard
 *	places.
 *
 *  dio_cact(dfd,bool)
 *
 *	If an error occurs (io_Error field), the io_Actual field is usually
 *	not modified by the device driver, and thus contains garbage.  To
 *	provide a cleaner interface, you can have DIO_CTL() and DIO_CTL_TO()
 *	calls automatically pre-clear this field so if an io_Error does
 *	occur, the field is a definate 0 instead of garbage.
 *
 *	In most cases you will want to do this.  An exception is the
 *	TIMER.DEVICE, which uses the io_Actual field for part of the
 *	timeout structure.
 *
 *	This flags the particular dio descriptor to do the pre-clear, and
 *	any new descriptors obtained by DIO_DUP()ing this one will also
 *	have the pre-clear flag set.
 *
 *
 *  dio_dup(dfd)
 *
 *	Returns a new channel descriptor referencing the same device.
 *	The new descriptor has it's own signal and IO request structure.
 *	For instance, if you openned the serial device, you might want
 *	to dup the descriptor so you can use one channel to pend an
 *	asyncronous read, and the other channel to write out to the device
 *	and do other things without disturbing the asyncronous read.
 *
 *
 *  sig = dio_signal(dfd)
 *
 *	get the signal number (0..31) used for a DIO descriptor.
 *	This allows you to Wait() for asyncronous requests.  Note that
 *	if your Wait() returns, you should double check using dio_isdone()
 *
 *	  dio_flags(dfd, or, ~and)
 *
 *	Modify the io_Flags field in the request, ORing it with the OR
 *	mask, and ANDing it with ~AND mask.  E.G., the AUDIO.DEVICE requires
 *	some flags be put in io_Flags.
 *
 *  req = dio_ctl_to(dfd, command, buf, len, to)
 *
 *	Same as DIO_CTL() below, but (A) is always syncronous, and
 *	(B) will attempt to AbortIO()+WaitIO() the request if the
 *	timeout occurs before the IO completes.
 *
 *	the 'to' argument is in microseconds.
 *
 *	If timeout occurs before request completes, and DIO aborts the
 *	request, some devices do not have the io_Actual field set
 *	properly.
 *
 *  req = dio_ctl(dfd, command, buf, len)
 *
 *	DIO_CTL() is the basis for the entire library.  It works as follows:
 *
 *	(1) If the channel isn't clear (there is an asyncronous IO request
 *	    still pending), DIO_CTL() waits for it to complete
 *
 *	(2) If the command is 0, simply return a pointer to the io
 *	    request structure.
 *
 *	(3) If the DIO_CACT() flag is TRUE, the io_Actual field of the
 *	    request is cleared.
 *
 *	(4) Set the io_Data field to 'buf', and io_Length field to 'len'
 *	    If the command is positive, use DoIO().  If the command
 *	    negative, take it's absolute value and then do a SendIO().
 *	    (The command is placed in the io_Command field, of course).
 *
 *	(5) return the IO request structure
 *
 *
 *  bool= dio_isdone(dfd)
 *
 *	return 1 if current channel is clear (done processing), else 0.
 *	e.g. if you did, say, an asyncronous read, and dio_isdone() returns
 *	true, you can now use the data buffer returned and look at the
 *	io_Actual field.
 *
 *	You need not do a dio_wait() after dio_isdone() returns 1.
 *
 *
 *  req = dio_wait(dfd)
 *
 *	Wait on the current channel for the request to complete and
 *	then return the request structure. (nop if channel is clear)
 *
 *
 *  req = dio_abort(dfd)
 *
 *	Abort the request on the current channel (nop if channel is
 *	clear).  Sends an AbortIO() if the channel is active and then
 *	WaitIO()'s the request.
 *
 *
 *  MACROS: SEE DIO.H
 *
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <devices/timer.h>
#include <local/xmisc.h>

#define MPC	    (MEMF_CLEAR|MEMF_PUBLIC)
#define CPORT	    ior.ior.io_Message.mn_ReplyPort
#define MAXREQSIZE  128     /* big enough to hold all Amiga iorequests */

typedef struct IORequest IOR;
typedef struct IOStdReq  STD;
typedef struct MsgPort	 PORT;

typedef struct {
    STD ior;
    char filler[MAXREQSIZE-sizeof(STD)];
} MAXIOR;

typedef struct {
    struct _CHAN *list;
    short refs;
} DIO;

typedef struct _CHAN {
    MAXIOR  ior;
    DIO     *base;
    XLIST   link;	/* doubly linked list */
    STD     timer;
    char    notclear;
    char    cact;	/* automatic io_Actual field clear  */
    char    ddl;
    UBYTE   flagmask;
} CHAN;

extern CHAN *dio_ctl(), *dio_ctl_to(), *dio_wait(), *dio_abort();
extern PORT *CreatePort();
extern char *AllocMem();

CHAN *
dio_open(name, unit, flags, req)
char *name;
MAXIOR *req;	 /* not really this big  */
{
    register CHAN *chan;
    register DIO *dio;
    register PORT *port;
    int ret;

    dio = (DIO *)AllocMem(sizeof(DIO), MPC);    if (!dio)   goto fail3;
    chan= (CHAN *)AllocMem(sizeof(CHAN), MPC);  if (!chan)   goto fail2;
    if (req)
	chan->ior = *req;
    chan->CPORT = CreatePort(NULL,0);           if (!chan->CPORT) goto fail1;
    chan->ior.ior.io_Message.mn_Node.ln_Type = NT_MESSAGE;
    chan->base = dio;
    chan->flagmask = 0xF0;
    dio->refs = 1;
    if (OpenDevice(name, unit, &chan->ior, flags)) {
	DeletePort(chan->CPORT);
fail1:	FreeMem(chan, sizeof(CHAN));
fail2:	FreeMem(dio, sizeof(DIO));
fail3:	return(NULL);
    }
    llink(&dio->list, &chan->link);
    chan->ior.ior.io_Flags = 0;
    return(chan);
}

void
dio_dfm(chan,mask)
CHAN *chan;
{
    chan->flagmask = mask;
}

void
dio_ddl(chan,n)
CHAN *chan;
{
    chan->ddl = n;
}

void
dio_cact(chan,n)
CHAN *chan;
{
    chan->cact = n;
}

void
dio_close(chan)
register CHAN *chan;
{
    dio_abort(chan);
    lunlink(&chan->link);
    if (--chan->base->refs == 0) {
	FreeMem(chan->base, sizeof(DIO));
	CloseDevice(&chan->ior);
    }
    if (chan->timer.io_Message.mn_ReplyPort)
	CloseDevice(&chan->timer);
    DeletePort(chan->CPORT);
    FreeMem(chan, sizeof(CHAN));
}

void
dio_closegroup(chan)
register CHAN *chan;
{
    register CHAN *nextc;

    for (chan = chan->base->list; chan; chan = nextc) {
	chan = (CHAN *)((char *)chan - ((char *)&chan->link - (char *)chan));
	nextc = (CHAN *)chan->link.next;
	dio_close(chan);
    }
}


CHAN *
dio_dup(chan)
register CHAN *chan;
{
    register CHAN *nc;

    if (chan) {
	nc = (CHAN *)AllocMem(sizeof(CHAN), MPC);   if (!nc) goto fail2;
	nc->ior = chan->ior;
	nc->base = chan->base;
	nc->CPORT = CreatePort(NULL,0);         if (!nc->CPORT) goto fail1;
	nc->ior.ior.io_Flags = NULL;
	nc->cact = chan->cact;
	nc->ddl = chan->ddl;
	nc->flagmask = chan->flagmask;
	++nc->base->refs;
	llink(&nc->base->list, &nc->link);
	return(nc);
fail1:	FreeMem(nc, sizeof(CHAN));
    }
fail2:
    return(NULL);
}

dio_signal(chan)
CHAN *chan;
{
    return(chan->CPORT->mp_SigBit);
}

dio_flags(chan,or,and)
long chan;
{
    IOR *ior = (void *)chan;

    ior->io_Flags = (ior->io_Flags | or) & ~and;
}


CHAN *
dio_ctl_to(chan, com, buf, len, to)
register CHAN *chan;
char *buf;
{
    register long mask;

    if (chan->timer.io_Message.mn_ReplyPort == NULL) {
	chan->timer.io_Message.mn_ReplyPort = chan->CPORT;
	chan->timer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
	if (OpenDevice("timer.device", UNIT_VBLANK, &chan->timer, 0)) {
	    puts("Panic: DIO_CTL_TO: No timer.device");
	}
	chan->timer.io_Command = TR_ADDREQUEST;
    }
    mask = 1 << chan->CPORT->mp_SigBit;
    dio_ctl(chan, (com>0)?-com:com, buf, len);  /* SendIO the request */
    chan->timer.io_Actual = to / 1000000;
    chan->timer.io_Length = to % 1000000;	/* setup timer	      */
    chan->timer.io_Flags = 0;
    BeginIO(&chan->timer);          /* start timer running  */
    while (Wait(mask)) {            /* Wait for something   */
	if (CheckIO(chan))          /* request done         */
	    break;
	if (CheckIO(&chan->timer)) {    /* timeout?           */
	    dio_abort(chan);
	    break;
	}
    }
    AbortIO(&chan->timer);          /*  kill the timer  */
    WaitIO(&chan->timer);           /*  remove from rp  */
    return(chan);                   /*  return ior  */
}


CHAN *
dio_ctl(chan, com, buf, len)
register CHAN *chan;
char *buf;
{
    if (chan->notclear) {   /* wait previous req to finish */
	WaitIO(chan);
	chan->notclear = 0;
    }
    if (com) {
	if (chan->cact)
	    chan->ior.ior.io_Actual = 0;    /* initialize io_Actual to 0*/
	chan->ior.ior.io_Error = 0;	    /* initialize error to 0 */
	if (!chan->ddl) {
	    chan->ior.ior.io_Data = (APTR)buf;  /* buffer   */
	    chan->ior.ior.io_Length = len;	/* length   */
	}
	if (com < 0) {                      /* asyncronous IO  */
	    chan->ior.ior.io_Command = -com;
	    chan->notclear = 1;
	    chan->ior.ior.io_Flags &= chan->flagmask;
	    BeginIO(chan);
	} else {			    /* syncronous IO  */
	    chan->ior.ior.io_Command = com;
	    chan->ior.ior.io_Flags = (chan->ior.ior.io_Flags & chan->flagmask) | IOF_QUICK;
	    BeginIO(chan);
	    if (!(chan->ior.ior.io_Flags & IOF_QUICK))
		WaitIO(chan);
	}
    }
    return(chan);
}


CHAN *
dio_isdone(chan)
register CHAN *chan;
{
    if (chan->notclear) {       /* if not clear */
	if (CheckIO(chan)) {    /* if done      */
	    WaitIO(chan);       /* clear        */
	    chan->notclear = 0;
	    return(chan);       /* done         */
	}
	return(NULL);           /* notdone      */
    }
    return(chan);               /* done         */
}


CHAN *
dio_wait(chan)
register CHAN *chan;
{
    if (chan->notclear) {
	WaitIO(chan);           /* wait and remove from rp */
	chan->notclear = 0;
    }
    return(chan);
}


CHAN *
dio_abort(chan)
register CHAN *chan;
{
    if (chan->notclear) {
	AbortIO(chan);          /* Abort it   */
	WaitIO(chan);           /* wait and remove from rp */
	chan->notclear = 0;
    }
    return(chan);
}


\Rogue\Monster\
else
  echo "will not over write ./suplib/dio.c"
fi
if [ `wc -c ./suplib/dio.c | awk '{printf $1}'` -ne 11170 ]
then
echo `wc -c ./suplib/dio.c | awk '{print "Got " $1 ", Expected " 11170}'`
fi
if `test ! -s ./suplib/asyncop.c`
then
echo "writing ./suplib/asyncop.c"
cat > ./suplib/asyncop.c << '\Rogue\Monster\'

/*
 *  ASYNCOP.C
 */

typedef unsigned char	ubyte;
typedef unsigned short	uword;
typedef unsigned long	ulong;
typedef struct Message	MSG;
typedef struct MsgPort	PORT;
typedef struct Task	TASK;
typedef struct Node	NODE;

#define ASYMSG	struct _ASYMSG
#define ASYHAN	struct _ASYHAN

ASYMSG {
    MSG msg;
    void (*func)();
    long arg1;
    long arg2;
    long arg3;
};

ASYHAN {
    PORT *rport;    /*	Reply Port	*/
    PORT *port;     /*	Send Port	*/
    long acount;    /*	Messages Sent	*/
    long ccount;    /*	Messages Replied*/
    long a4,a5;     /*	A4 and A5	*/
};

extern TASK *CreateTask();
extern TASK *FindTask();
extern PORT *CreatePort();
extern void *AllocMem();
extern void *GetMsg();

extern void asyhandler();
extern void nop();


ASYHAN *
NewAsyncOp()
{
    register TASK *task;
    register TASK *mytask = FindTask(NULL);
    register ASYHAN *as = AllocMem(sizeof(ASYHAN), MEMF_CLEAR|MEMF_PUBLIC);
    ASYMSG StartupMsg;

    as->rport = CreatePort(NULL, 0);
    PutA4A5(&as->a4);
    task = CreateTask("async.task", mytask->tc_Node.ln_Pri + 1, asyhandler, 4096);
    task->tc_UserData = (APTR)as;

    Signal(task, SIGBREAKF_CTRL_F);
    Wait(1 << as->rport->mp_SigBit);

    return(as);
}


StartAsyncOp(as, func, arg1, arg2, arg3)
register ASYHAN *as;
void (*func)();
{
    register ASYMSG *am = GetMsg(as->rport);    /*  Free Msg List   */

    if (!am) {
	am = AllocMem(sizeof(ASYMSG), MEMF_PUBLIC|MEMF_CLEAR);
	am->msg.mn_ReplyPort = as->rport;
    }
    am->func = func;
    am->arg1 = arg1;
    am->arg2 = arg2;
    am->arg3 = arg3;
    ++as->acount;
    PutMsg(as->port, am);
}

CheckAsyncOp(as, n)
register ASYHAN *as;
unsigned long n;
{
    if (n > as->acount)
	n = as->acount;
    return(n <= as->ccount);
}

/*
 *  acount = #messages sent
 *  ccount = #messages replied
 */

WaitAsyncOp(as, n)
register ASYHAN *as;
unsigned long n;
{
    if (n > as->acount)
	n = as->acount;
    while (n > as->ccount)
	Wait(1 << as->rport->mp_SigBit);
    Forbid();
    as->ccount -= n;
    Permit();
    as->acount -= n;
}

CloseAsyncOp(as)
register ASYHAN *as;
{
    ASYMSG EndMsg;
    ASYMSG *am;

    WaitAsyncOp(as, -1);                /*  Wait for all operations to complete */
    while (am = GetMsg(as->rport))      /*  Free any messages   */
	FreeMem(am, sizeof(ASYMSG));
    EndMsg.func = NULL;
    EndMsg.msg.mn_ReplyPort = as->rport;
    PutMsg(as->port, &EndMsg);
    WaitPort(as->rport);
    GetMsg(as->rport);
    DeletePort(as->rport);
    FreeMem(as, sizeof(*as));
}

static
void
asyhandler()
{
    register ASYHAN *as;
    register ASYMSG *am;

    Wait(SIGBREAKF_CTRL_F);
    as = (ASYHAN *)FindTask(NULL)->tc_UserData;
    as->port = CreatePort(NULL, 0);
    Signal(as->rport->mp_SigTask, 1 << as->rport->mp_SigBit);
    for (;;) {
	WaitPort(as->port);
	am = GetMsg(as->port);
	if (!am->func)
	    break;
	CallAMFunc(&as->a4, &am->func);
	++as->ccount;
	ReplyMsg(am);
    }
    DeletePort(as->port);
    as->port = NULL;
    Forbid();
    ReplyMsg(am);
}

#asm
	    ;
	    ;	load the lw array ptr with a4 & a5

_PutA4A5:   move.l  4(sp),A0
	    move.l  A4,(A0)+
	    move.l  A5,(A0)+
	    rts

_CallAMFunc:
	    move.l  4(sp),A0    ; &a4,a5
	    move.l  8(sp),A1    ; &func,arg1,arg2,arg3
	    movem.l D2/D3/A4/A5/A6,-(sp)
	    move.l  (A0)+,A4
	    move.l  (A0)+,A5
	    move.l  12(A1),-(sp)
	    move.l  8(A1),-(sp)
	    move.l  4(A1),-(sp)
	    move.l  (A1),A1
	    jsr     (A1)
	    add.w   #12,sp
	    movem.l (sp)+,D2/D3/A4/A5/A6
	    rts

#endasm

\Rogue\Monster\
else
  echo "will not over write ./suplib/asyncop.c"
fi
if [ `wc -c ./suplib/asyncop.c | awk '{printf $1}'` -ne 3495 ]
then
echo `wc -c ./suplib/asyncop.c | awk '{print "Got " $1 ", Expected " 3495}'`
fi
if `test ! -s ./suplib/enviroment.c`
then
echo "writing ./suplib/enviroment.c"
cat > ./suplib/enviroment.c << '\Rogue\Monster\'

/*
 *  ENVIROMENT.C
 *
 *  str = GetDEnv(name)
 *  bool= SetDEnv(name, str)    (0=failure, 1=success)
 *
 *	If the enviroment variable 'name' exists, malloc and return a copy
 *	of it.	The user program must free() it (or allow the standard C
 *	exit routine to free() it).
 */

extern void *AllocMem();
extern void *malloc();

char *
GetDEnv(name)
char *name;
{
    short nlen = strlen(name) + 5;
    char *ptr = AllocMem(nlen, MEMF_PUBLIC);
    char *res = NULL;
    long fh;
    long len;

    if (ptr) {
	strcpy(ptr, "ENV:");
	strcat(ptr, name);
	if (fh = Open(ptr, 1005)) {
	    len = (Seek(fh, 0L, 1), Seek(fh, 0L, 0));
	    if (len >= 0 && (res = malloc(len+1))) {
		Seek(fh, 0L, -1);
		if (Read(fh, res, len) != len)
		    len = 0;
		res[len] = 0;
	    }
	    Close(fh);
	}
	FreeMem(ptr, nlen);
    }
    return(res);
}

SetDEnv(name, str)
char *name, *str;
{
    short nlen = strlen(name) + 5;
    short slen = strlen(str);
    short res = 0;
    char *ptr = AllocMem(nlen, MEMF_PUBLIC);
    long fh;

    if (ptr) {
	strcpy(ptr, "ENV:");
	strcat(ptr, name);
	if (fh = Open(ptr, 1006)) {
	    if (Write(fh, str, slen) == slen)
		res = 1;
	    Close(fh);
	}
	FreeMem(ptr, nlen);
    }
    return(res);
}

\Rogue\Monster\
else
  echo "will not over write ./suplib/enviroment.c"
fi
if [ `wc -c ./suplib/enviroment.c | awk '{printf $1}'` -ne 1213 ]
then
echo `wc -c ./suplib/enviroment.c | awk '{print "Got " $1 ", Expected " 1213}'`
fi
if `test ! -s ./suplib/typedefs.h`
then
echo "writing ./suplib/typedefs.h"
cat > ./suplib/typedefs.h << '\Rogue\Monster\'

/*
 * TYPEDEFS.H
 */

typedef unsigned char	ubyte;
typedef unsigned short	uword;
typedef unsigned long	ulong;

typedef struct MsgPort		PORT;
typedef struct Message		MSG;
typedef struct List		LIST;
typedef struct Node		NODE;
typedef struct MinList		MLIST;
typedef struct MinNode		MNODE;
typedef struct Device		DEV;
typedef struct Library		LIB;
typedef struct ExecBase 	EXECBASE;

#define WINSTD	(WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE)

typedef struct BoolInfo 	BOOLINFO;
typedef struct Border		BORDER;
typedef struct Gadget		GADGET;
typedef struct Image		IMAGE;
typedef struct IntuiMessage	IMESS;
typedef struct IntuiText	ITEXT;
typedef struct Menu		MENU;
typedef struct MenuItem 	ITEM;
typedef struct NewScreen	NS;
typedef struct NewWindow	NW;
typedef struct Preferences	PREFS;
typedef struct PropInfo 	PROPINFO;
typedef struct Remember 	REMEMBER;
typedef struct Requester	REQUESTER;
typedef struct Screen		SCR;
typedef struct StringInfo	STRINGINFO;
typedef struct Window		WIN;

typedef struct GListEnv 	GLISTENV;
typedef struct GadgetInfo	GADGETINFO;
typedef struct IBox		IBOX;
typedef struct IntuitionBase	IBASE;
typedef struct PenPair		PENPAIR;
typedef struct Point		POINT;

typedef struct IOAudio		IOAUD;

typedef struct BootBlock	BOOTBLOCK;

typedef struct IOClipReq	    IOCLIPREQ;
typedef struct ClipboardUnitPartial CLIPUNIT;
typedef struct SatisfyMsg	    SATISFYMSG;

typedef struct ConUnit		CONUNIT;
typedef struct IOStdReq 	IOCON;

typedef struct InputEvent	IE;

typedef struct TextAttr 	TA;
typedef struct TextFont 	FONT;
typedef struct Layer		LAYER;
typedef struct Layer_Info	LAYERINFO;
typedef struct Region		REGION;
typedef struct ClipRect 	CLIPRECT;
typedef struct BitMap		BM;
typedef struct RastPort 	RP;
typedef struct View		VIEW;
typedef struct ViewPort 	VP;
typedef struct GfxBase		GFXBASE;

typedef struct Process		PROC;
typedef struct Task		TASK;
typedef struct FileInfoBlock	FIB;
typedef struct FileLock 	LOCK;

typedef struct timeval		TV;
typedef struct timerequest	IOTIM;

typedef struct PrinterData	PD;
typedef struct PrinterExtendedData PED;


/*
 *  Intuition
 */

extern WIN	*OpenWindow();
extern SCR	*OpenScreen();
extern void	*AllocRemember();
extern void	*ItemAddress();
extern PREFS	*GetPrefs();
extern PREFS	*GetDefPrefs();
extern VIEW	*ViewAddress();
extern VP	*ViewPortAddress();

/*
 *  Graphics
 */

extern void	*AllocRaster();

/*
 *  Exec / Exec-Support
 */

extern void	*GetMsg();
extern void	*GetHead(), *GetTail(), *GetSucc(), *GetPred();
extern void	*GetHeadOff(), *GetTailOff(), *GetSuccOff(), *GetPredOff();

extern void	*AllocMem();
extern PORT	*FindPort();
extern TASK	*CreateTask();
extern PROC	*CreateProc();
extern void	*FindTask();    /*  task or proc    */

extern void	*malloc();




\Rogue\Monster\
else
  echo "will not over write ./suplib/typedefs.h"
fi
if [ `wc -c ./suplib/typedefs.h | awk '{printf $1}'` -ne 2748 ]
then
echo `wc -c ./suplib/typedefs.h | awk '{print "Got " $1 ", Expected " 2748}'`
fi
if `test ! -s ./suplib/xmisc.h`
then
echo "writing ./suplib/xmisc.h"
cat > ./suplib/xmisc.h << '\Rogue\Monster\'

/*
 * XMISC.H
 */

#ifndef	MYLIB_XMISC_H
#define	MYLIB_XMISC_H

#define	GRAPHICS_LIB	    0x0001L
#define	INTUITION_LIB	    0x0002L
#define	EXPANSION_LIB	    0x0004L
#define	DISKFONT_LIB	    0x0008L
#define	TRANSLATOR_LIB	    0x0010L
#define	ICON_LIB	    0x0020L
#define	MATH_LIB	    0x0040L
#define	MATHTRANS_LIB	    0x0080L
#define	MATHIEEEDOUBBAS_LIB 0x0100L
#define	MATHIEEESINGBAS_LIB 0x0200L
#define	LAYERS_LIB	    0x0400L
#define	CLIST_LIB	    0x0800L
#define	POTGO_LIB	    0x1000L
#define	TIMER_LIB	    0x2000L

struct OLI {
    char *name;
    long *var;
};

typedef	struct _XLIST {
    struct _XLIST *next, **prev;
} XLIST;

#endif


\Rogue\Monster\
else
  echo "will not over write ./suplib/xmisc.h"
fi
if [ `wc -c ./suplib/xmisc.h | awk '{printf $1}'` -ne 644 ]
then
echo `wc -c ./suplib/xmisc.h | awk '{print "Got " $1 ", Expected " 644}'`
fi
if `test ! -s ./suplib/dio.h`
then
echo "writing ./suplib/dio.h"
cat > ./suplib/dio.h << '\Rogue\Monster\'

/*
 * DIO.H
 *
 *  (C)Copyright 1987 Matthew Dillon, All Rights Reserved
 *  Freely distributable.  Donations welcome, I guess.
 *
 *	Matthew Dillon
 *	891 Regal Rd.
 *	Berkeley, Ca.	94708
 *
 */

#ifndef MYLIB_DIO_H
#define MYLIB_DIO_H
#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <devices/timer.h>

typedef struct IORequest IOR;
typedef struct IOStdReq  STD;
typedef struct MsgPort	 PORT;

/*
 *	'to' is in microsections.  The IO request structure
 *  pointer is optional to dio_open().	If NULL, dio_open()
 *  initializes it's own IO request (to mostly zero).  You have
 *  to provide an IO request structure, for instance, if openning
 *  a console device since the window pointer must be passed to
 *  OpenDevice().
 *
 *	each DFD descriptor has it's own signal.
 *
 *	dio_isdone() returns 1 if the channel is clear, 0 otherwise.
 */

extern long dio_open(); 	/* dfd	  = dio_open(devname,unit,flags,req)*/
extern long dio_dup();		/* newdfd = dio_dup(dfd)    */
extern STD *dio_ctl();		/* req	= dio_ctl(dfd,com,buf,len)	    */
extern STD *dio_ctl_to();	/* req	= dio_ctl_to(dfd,com,buf,len,to)    */
extern STD *dio_wait(); 	/* req	= dio_wait(dfd)     */
extern STD *dio_abort();	/* req	= dio_abort(dfd)    */
extern STD *dio_isdone();	/* req	= dio_isdone(dfd)   */
extern int dio_signal();	/* signm= dio_signal(dfd)   */
extern void dio_close();	/*  dio_close(dfd)	    */
extern void dio_cloesgroup();	/*  dio_closegroup(dfd)     */
extern void dio_cact(); 	/*  dio_cact(dfd,bool)	    */



/*
 * dio_simple() and related macros return the !io_Error field. That
 * is, 0=ERROR, 1=OK
 *
 * dio_actual() returns the io_Actual field.
 *
 * NOTE: the io_Actual field may not be set by the device if an
 * error condition exists.  To make the io_ctl() and io_ctl_to()
 * call automatically clear the io_Actual field before doing the
 * io operation, use the DIO_CACT() call.  The reason this isn't
 * done automatically by default is that some devices require
 * parameters to be passed in the io_Actual field (like the
 * timer.device).
 *
 *  Remember, Asyncronous IO is done by sending -com instead of com.
 *
 *	CALL			    Syncronous IO   Asyncronous IO
 *
 *  dio_simple(dfd,com) 	    0=ERROR, 1=OK   undefined
 *  dio_actual(dfd,com) 	    io_Actual	    undefined
 *  dio_reset(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_update(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_clear(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_stop(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_start(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_flush(dfd)		    0=ERROR, 1=OK   n/a
 *  dio_getreq(dfd)		    returns a ptr to the IO
 *				    request structure
 *  NOTE: If you use the following, you probably want to have the
 *  device library automatically clear the io_Actual field before
 *  sending the request so you get 0 if an error occurs.  That
 *  is: dio_cact(dfd,1);
 *
 *
 *  dio_read(dfd,buf,len)	    returns actual bytes read
 *  dio_write(dfd,buf,len)	    returns actual bytes written
 *
 *	The timeout argument for dio_readto() and dio_writeto()
 *	is in MICROSECONDS, up to 2^31uS.
 *
 *  dio_readto(dfd,buf,len,to)	    returns actual bytes read
 *  dio_writeto(dfd,buf,len,to)     returns actual bytes written
 *
 *	The asyncronous dio_reada() and dio_writea() do not
 *	return anything.
 *
 *  dio_reada(dfd,buf,len)	    begin asyncronous read
 *  dio_writea(dfd,buf,len)	    begin asyncronous write
 */

#define dio_mask(dfd)		(1 << dio_signal(dfd))

#define dio_simple(dfd,com)	(!dio_ctl(dfd,com,0,0)->io_Error)
#define dio_actual(dfd,com)	( dio_ctl(dfd,com,0,0)->io_Actual)
#define dio_reset(dfd)		dio_simple(dfd,CMD_RESET)
#define dio_update(dfd) 	dio_simple(dfd,CMD_UPDATE)
#define dio_clear(dfd)		dio_simple(dfd,CMD_CLEAR)
#define dio_stop(dfd)		dio_simple(dfd,CMD_STOP)
#define dio_start(dfd)		dio_simple(dfd,CMD_START)
#define dio_flush(dfd)		dio_simple(dfd,CMD_FLUSH)
#define dio_getreq(dfd) 	dio_ctl(dfd,0,0,0)

#define dio_read(dfd,buf,len)	    (dio_ctl(dfd,CMD_READ,buf,len)->io_Actual)
#define dio_write(dfd,buf,len)	    (dio_ctl(dfd,CMD_WRITE,buf,len)->io_Actual)
#define dio_readto(dfd,buf,len,to)  (dio_ctl_to(dfd,CMD_READ,buf,len,to)->io_Actual)
#define dio_writeto(dfd,buf,len,to) (dio_ctl_to(dfd,CMD_WRITE,buf,len,to)->io_Actual)
#define dio_reada(dfd,buf,len)	    ((void)dio_ctl(dfd,-CMD_READ,buf,len))
#define dio_writea(dfd,buf,len)     ((void)dio_ctl(dfd,-CMD_WRITE,buf,len))

#endif


\Rogue\Monster\
else
  echo "will not over write ./suplib/dio.h"
fi
if [ `wc -c ./suplib/dio.h | awk '{printf $1}'` -ne 4438 ]
then
echo `wc -c ./suplib/dio.h | awk '{print "Got " $1 ", Expected " 4438}'`
fi
if `test ! -s ./suplib/conwin.c`
then
echo "writing ./suplib/conwin.c"
cat > ./suplib/conwin.c << '\Rogue\Monster\'

/*
 *  CONWIN.C
 *
 *  Win = GetConWindow()
 *
 *  Returns console window associated with the current task or NULL if
 *  no console task associated.
 *
 *  The intuition.library and graphics.library must be openned.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#define BTOC(bptr)    ((long)(bptr) << 2)
#define CTOB(cptr)    ((long)(cptr) >> 2)

typedef struct Task	      TASK;
typedef struct Process	      PROC;
typedef struct StandardPacket STDPKT;
typedef struct MsgPort	      MSGPORT;
typedef struct Window	      WIN;
typedef struct InfoData       INFODATA;

extern TASK *FindTask();
extern void *AllocMem();

/*
 *  GETCONWINDOW()
 *
 *  Return the window used by the console of the current process.  We can
 *  use our process's message port as the reply port since it is a
 *  synchronous packet (we wait for the result to come back).  WARNING:
 *  This routine does not check if the 'console' of the current process
 *  is really a console device.
 *
 *  The DISK_INFO packet is sent to the console device.  Although this
 *  packet is normally used to retrieve disk information from disk
 *  devices, the console device recognizes the packet and places a pointer
 *  to the window in id_VolumeNode of the infodata structure.  A pointer
 *  to the console unit is also placed in id_InUse of the infodata structure.
 */

WIN *
GetConWindow()
{
    PROC	*proc;
    STDPKT	*packet;
    INFODATA	*infodata;
    long	result;
    WIN 	*win;

    proc   = (PROC *)FindTask(NULL);
    if (!proc->pr_ConsoleTask)
	return(NULL);
    /*
     *	NOTE: Since DOS requires the packet and infodata structures to
     *	be longword aligned, we cannot declare them globally or on the
     *	stack (word aligned).  AllocMem() always returns longword
     *	aligned pointers.
     */

    packet   = (STDPKT   *)AllocMem(sizeof(STDPKT)  , MEMF_CLEAR|MEMF_PUBLIC);
    infodata = (INFODATA *)AllocMem(sizeof(INFODATA), MEMF_CLEAR|MEMF_PUBLIC);

    packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
    packet->sp_Pkt.dp_Link = &packet->sp_Msg;
    packet->sp_Pkt.dp_Port = &proc->pr_MsgPort;
    packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
    packet->sp_Pkt.dp_Arg1 = CTOB(infodata);
    PutMsg(proc->pr_ConsoleTask, packet);
    WaitPort(&proc->pr_MsgPort);
    GetMsg(&proc->pr_MsgPort);

    result = packet->sp_Pkt.dp_Res1;
    win = (WIN *)infodata->id_VolumeNode;
    /* note: id_InUse holds a pointer to the console unit also */
    FreeMem(packet  , sizeof(STDPKT));
    FreeMem(infodata, sizeof(INFODATA));
    if (!result)
	return(NULL);
    return(win);
}


\Rogue\Monster\
else
  echo "will not over write ./suplib/conwin.c"
fi
if [ `wc -c ./suplib/conwin.c | awk '{printf $1}'` -ne 2672 ]
then
echo `wc -c ./suplib/conwin.c | awk '{print "Got " $1 ", Expected " 2672}'`
fi
echo "Finished archive 1 of 2"
# if you want to concatenate archives, remove anything after this line
exit
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.