[comp.sources.amiga] v02i066: rdf - raw floppy disk handler

page@swan.ulowell.edu (Bob Page) (11/29/88)

Submitted-by: u211344@hnykun11.bitnet (Olaf 'Rhialto' Seibert)
Posting-number: Volume 2, Issue 66
Archive-name: devices/rdf.1

Raw trackdisk.device interface for DOS, based somewhat on Matthew
Dillon's excellent PIPE:.  This first version handle packets one at a
time, so we avoid problems with having several IO requests
outstanding (which must be replied to the reader/writer in order).

Implemented functions are:
   Open() Close() Read() Write() Seek()

Usage:
     RDF:/dtrackdisk.device
         /uunit #
         /fflags
         /ooffset
         /llength
         /eeof  (maintain a virtual end-of-file)
         /E     (get eof from last closed file)

[uuencoded doc because it's got escape sequences in it.  ..Bob]

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	Makefile
#	Mountlist
#	Notice
#	RCopy.c
#	include.c
#	misc.c
#	rdf.c
#	rdf.man.uu
# This archive created: Mon Nov 28 20:05:56 1988
cat << \SHAR_EOF > Makefile
#DB	 = -DDEBUG
CFLAGS	= +BCDL +Isyms $(DB)
OBJ	= rdf.o misc.o

.c.o:
	cc $(CFLAGS) $*.c

.c.asm:
	cc $(CFLAGS) -at $*.c

RDF-Handler:	$(OBJ)
	ln $(OBJ) -lcl32 -w -o RDF-Handler

syms:	include.c
	cc +BCDL +Hsyms -a -o nil: include.c

RCopy:	RCopy.c
	cc RCopy.c
	ln RCopy.o -lc
SHAR_EOF
cat << \SHAR_EOF > Mountlist
RDF:	   Handler = devs:RDF-Handler
	   Device = trackdisk.device
	   Unit = 1
	   Flags = 0
	   Stacksize = 4096
	   Priority = 4
	   GlobVec  = -1
#
SHAR_EOF
cat << \SHAR_EOF > Notice

This software is (C) Copyright 1988 by Olaf Seibert. All Rights Reserved.

This software is NOT in the public domain. It may not be sold or used for
profit without prior written consent from the author, Olaf Seibert.

Conditions for redistribution are:

- This notice must remain included at all times. It may not be modified in
  any way.

- No charge may be made for distribution above media and transportation
  costs.

- The source and documentation of the program must always be distributed
  with the binary, unless the distributor of said binary agrees to supply
  the source and documentation on request, with no expiration date on
  availability of said source and documentation.

- If any part of this program (source or binary) or its documentation is
  included in any other software package, either integrated or separately,
  these redistribution conditions automatically apply to the entire
  package, unless prior written permission is obtained from the author.

- No claim is made regarding the quality of this software or its
  documentation. It is supplied purely as-is. The author cannot be held
  responsible for any damages occurring directly or indirectly from using
  or not using this program.

The author can be reached at:

  Olaf Seibert
  p/a Beek 5
  5815 CS  Merselo
  The Netherlands
SHAR_EOF
cat << \SHAR_EOF > RCopy.c
/*
 *	RCOPY
 *
 *	Very plain copy program. No frills at all.
 *	Just Open() Read() Write() and Close().
 *
 */

long Output(), Read(), Write(), Open();
void *AllocMem();

#define MEMF_PUBLIC	(1L << 0)
#define MEMF_CHIP	(1L << 1)
#define MODE_OLDFILE	1005L
#define MODE_NEWFILE	1006L

#define BUFSIZE 	(11 * 1024L)

main(argc, argv)
int argc;
char **argv;
{
    register long from, to, size, output;
    register void *buffer;

    output = Output();

    if (argc != 3) {
	Write(output, "Usage: RCOPY source dest\n", 26L);
	exit(10);
    }

    if (buffer = AllocMem(BUFSIZE, MEMF_CHIP | MEMF_PUBLIC)) {
	if (from = Open(argv[1], MODE_OLDFILE)) {
	    if (to = Open(argv[2], MODE_NEWFILE)) {
		while ((size = Read(from, buffer, BUFSIZE)) > 0) {
		    if (size != Write(to, buffer, size)) {
			Write(output, "Write error\n", 12L);
			break;
		    }
		    if (Chk_Abort()) {
			Write(output, "^C\n", 3L);
			break;
		    }
		}
		Close(to);
	    } else
	       Write(output, "Cannot open destination\n", 24L);
	    Close(from);
	} else
	    Write(output, "Cannot open source\n", 19L);
	FreeMem(buffer, BUFSIZE);
    } else
	Write(output, "Cannot allocate copy buffer\n", 28L);
}

SHAR_EOF
cat << \SHAR_EOF > include.c
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/trackdisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
/*#include "xmisc.h"*/
SHAR_EOF
cat << \SHAR_EOF > misc.c

/*
 *  MISC.C  - support routines - Phillip Lindsay (C) Commodore 1986
 *  You may freely distribute this source and use it for Amiga Development -
 *  as long as the Copyright notice is left intact.
 *
 * 30-SEP-86
 *
 *  major modifications by Matthew Dillon for my PIPE: and other devices,
 *  but basic theorem still Phil's.
 *
 * 09-OKT-88
 *
 *  (Olaf Seibert) added provision for an external taskwait routine.
 *  Changed returnpkt and returnpktplain.
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

extern void returnpkt();
extern char *GetMsg();

void
returnpktplain(packet, myproc)
struct DosPacket *packet;
struct Process *myproc;
{
    register struct Message *mess;
    register struct MsgPort *replyport;

    replyport		     = packet->dp_Port;
    mess		     = packet->dp_Link;
    packet->dp_Port	     = &myproc->pr_MsgPort;
    mess->mn_Node.ln_Name    = (char *)packet;
    mess->mn_Node.ln_Succ    = NULL;
    mess->mn_Node.ln_Pred    = NULL;
    PutMsg(replyport, mess);
}


void
returnpkt(packet, myproc, res1, res2)
register struct DosPacket *packet;
struct Process *myproc;
long res1, res2;
{
    packet->dp_Res1	     = res1;
    packet->dp_Res2	     = res2;
    returnpktplain(packet, myproc);
}


/*
 * taskwait() ... Waits for a message to arrive at your port and
 *   extracts the packet address which is returned to you.
 */

typedef struct Message *(*funcptr)();

struct DosPacket *
taskwait(myproc)
register struct Process *myproc;
{
    register struct MsgPort *myport;
    register struct Message *mymess;

    if (myproc->pr_PktWait) {
	/* As per AmigaDOS tech. ref. man (V1.1) page 265: */
	/* ``In the same way as GetMsg, the function should */
	/*   return a message when one is available.'' */
	mymess = (*(funcptr)myproc->pr_PktWait)(myproc);
    } else {
	myport = &myproc->pr_MsgPort;
	WaitPort(myport);
	mymess = (struct Message *)GetMsg(myport);
    }
    return((struct DosPacket *)mymess->mn_Node.ln_Name);
}

taskpktrdy(myproc)
struct Process *myproc;
{
    if (myproc->pr_MsgPort.mp_MsgList.lh_Tail == NULL)
	return(0);
    return(1);
}

SHAR_EOF
cat << \SHAR_EOF > rdf.c
/*
 *      Raw trackdisk.device interface for DOS.
 *
 *      Based somewhat on Mattew Dillons excellent PIPE: (hello Matt!).
 *
 *      First version: handle packets one at a time. This way, we avoid
 *      problems with having several IO requests outstanding, which
 *      must be replied to the reader/writer in order.
 *
 *      Usage:
 *              RDF:/dtrackdisk.device
 *                  /uunit #
 *                  /fflags
 *                  /ooffset
 *                  /llength
 *                  /eeof  (maintain a virtual end-of-file)
 *                  /E     (get eof from last closed file)
 *
 *      If you open a file with /E and then read at least
 *      4 bytes from it, you will get the eof offset from the last closed
 *      file.
 *
 *      Implemented functions are:
 *
 *      Open() Close()
 *      Read() Write()
 *      Seek()
 *
 *      These are more or less just dummies:
 *
 *      Lock() UnLock() DupLock()
 *      DeleteFile()
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/trackdisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>

                                            /* Various ACTION's supported */
#define ACTION_FIND_RW      1004            /* name ??                  */
#define ACTION_FIND_INPUT   MODE_OLDFILE    /* 1005                     */
#define ACTION_FIND_OUTPUT  MODE_NEWFILE    /* 1006                     */
#define ACTION_END          1007
#define ACTION_SEEK         1008

#undef  BADDR
#define BADDR(x)   ((APTR)((long)x << 2))   /* convert BCPL->APTR       */

#define DOS_FALSE    0
#define DOS_TRUE     -1

#define TD_SECMASK  (TD_SECTOR - 1)         /* Assumes it is a power of 2 */

#define branchto    goto                    /* (-: Avoid goto's :-)     */

typedef struct DosPacket    DOSPACKET;
typedef struct Process      PROC;
typedef struct DeviceNode   DEVNODE;
typedef struct FileHandle   FH;
typedef unsigned char uchar;
typedef struct Message      MSG;

typedef struct _FILE {
    struct IOExtTD *file_IO;
    ULONG           file_MinOffset;         /* <= Offset    */
    ULONG           file_Offset;            /* <= EofOffset */
    ULONG           file_EofOffset;         /* <= MaxOffset */
    ULONG           file_MaxOffset;
} File;

/*
 * NOTE: Globals in the Bss space are not automatically initialized to
 * 0 when you don't use Aztec's startup _main, which we can't since
 * this is a packet handler.
 */

extern long AbsExecBase;            /* Absolute global address 4    */
extern DOSPACKET *taskwait();       /* wait for a message           */
extern void *AllocMem();
extern PROC *FindTask();
extern struct IOExtTD *CreateExtIO();
extern struct MsgPort *CreatePort();

ULONG PerformIO();                  /* Encapsulate DoIO()           */
long ntoi();                        /* Our own fancy atoi()         */

long SysBase;                       /* required to make Exec calls  */
uchar Buf[256];                     /* Scratch buffer               */
long DOSBase;
#ifdef DEBUG
long Fh;                            /* Debugging..                  */
#endif

exec_handler()
{
    PROC        *MyProc;        /* my process                             */
    DEVNODE     *MyNode;        /* our device node passed in parmpkt Arg3 */
    uchar       Expunge = 0;
    uchar       NotDone;
    uchar      *default_Device;
    ULONG       default_Unit;
    ULONG       default_Flags;
    ULONG       OpenCount = 0;  /* must be 4 bytes... used as temp BPTR   */
    char       *TDBuffer = NULL;
    ULONG       save_Eof = 0;
    struct MsgPort *IOPort;

    SysBase = AbsExecBase;      /* Initialize SysBase                     */
#ifdef DEBUG
    Fh = NULL;                  /* Debugging OFF                          */
#endif

    MyProc  = (PROC *)FindTask(0L);

    DOSBase = OpenLibrary("dos.library", 0);
#ifdef DEBUG
    /*  DEBUGGING
     *  Note that the debugging uses normal DOS calls, so the same
     *  MsgPort is being used that our own commands arrive on.
     *  So when debugging is enabled, please have only one open file
     *  on RDF: at a time, or face the dreaded AN_AsyncPkt guru.
     */
    Fh = Open("CON:0/0/600/150/RDF-handler", MODE_NEWFILE);
#endif

    /*
     * INITIAL STARTUP MESSAGE
     */

    {
        register DOSPACKET *MyPkt;
        /* long *environ; */

        MyPkt  = taskwait(MyProc);
        IOPort = CreatePort(0, 0);
        TDBuffer = AllocMem(TD_SECTOR, MEMF_PUBLIC | MEMF_CHIP);
        if (IOPort && TDBuffer) {
            struct FileSysStartupMsg *fssm;

            MyNode  = (DEVNODE *)BADDR(MyPkt->dp_Arg3);
            fssm = (struct FileSysStartupMsg *)BADDR(MyNode->dn_Startup);
                                    /* Same as BADDR(MyPkt->dp_Arg2) */
            default_Device = (uchar *)BADDR(fssm->fssm_Device) + 1;
            default_Unit   = fssm->fssm_Unit;
            default_Flags  = fssm->fssm_Flags;

            MyNode->dn_Task = &MyProc->pr_MsgPort;
            returnpkt(MyPkt, MyProc, DOS_TRUE, 0);
        } else {
            returnpkt(MyPkt, MyProc, DOS_FALSE, ERROR_NO_FREE_STORE);
            Alert(0x00018014, 0); /* AG_NoMemory | AO_TrackDiskDev */
            branchto exit;
        }
#ifdef DEBUG
        if (Fh) {
            sprintf(Buf, "'%s', %ld flags %ld\n",
                default_Device, default_Unit, default_Flags);
            Write(Fh, Buf, strlen(Buf));
        }
#endif
    }

top:

    /*
     * MAIN LOOP
     */

    NotDone = 1;
    while (NotDone) {
        register DOSPACKET *MyPkt;      /* dos packet received      */
        register File *file;            /* pointer to current File  */
        struct IOExtTD *iotd;
        long type;                      /* type of packet           */

        MyPkt = taskwait(MyProc);       /* wait/get next packet     */
        MyPkt->dp_Res1 = DOS_TRUE;      /* default return value     */
        MyPkt->dp_Res2 = 0;             /* default no error         */
        type = MyPkt->dp_Type;          /* packet type              */

        /*
         *  Extract File pointer.  Doesn't apply to Open()
         */

        file = (File *)MyPkt->dp_Arg1;

#ifdef DEBUG
        if (Fh) {
            sprintf(Buf, "Packet: %4ld arg3 %ld, file: %-8lx arg2: %ld\n",
                    MyPkt->dp_Type, MyPkt->dp_Arg3, file, MyPkt->dp_Arg2);
            Write(Fh, Buf, strlen(Buf));
        }
#endif

        switch(type) {
        case ACTION_FIND_INPUT:
        case ACTION_FIND_OUTPUT:
        case ACTION_FIND_RW:
            {
                uchar *this_Device = default_Device;
                long this_Unit = default_Unit;
                long these_Flags = default_Flags;
                long this_Offset = 0;
                long this_Length = 880 * 1024L;
                long this_Eof = -1;
                register uchar *name = (uchar *)BADDR(MyPkt->dp_Arg3);

                /* Parse the given filename */
                strncpy(Buf, name + 1, *name);
                Buf[*name] = '\0';
#ifdef DEBUG
                if (Fh) {
                    Write(Fh, Buf, strlen(Buf));
                    Write(Fh, "\n", 1);
                }
#endif

                for (name = Buf; *name; ) {
                    if (*name == '/') {
                        *name++ = '\0';
                        switch (*name) {
                        case 'd':
                            this_Device = ++name;
                            break;
                        case 'u':
                            this_Unit = ntoi(++name);
                            break;
                        case 'f':
                            these_Flags = ntoi(++name);
                            break;
                        case 'o':
                            this_Offset = ntoi(++name);
                            break;
                        case 'l':
                            this_Length = ntoi(++name);
                            break;
                        case 'e':
                            this_Eof = ntoi(++name);
                            break;
                        case 'E':
                            this_Offset = -1;
                        }
                    } else
                        name++;     /* Don't fail on /e/o */
                }

                file = (File *)AllocMem(sizeof(File), MEMF_CLEAR);
                    if (file == NULL) branchto openfail1;
                iotd = CreateExtIO(IOPort, sizeof(struct IOExtTD));
                    if (iotd == NULL) branchto openfail2;
                if (OpenDevice(this_Device, this_Unit, iotd, these_Flags))
                    branchto openfail3;
                iotd->iotd_Count = PerformIO(iotd, TD_CHANGENUM, 0, 0, 0);
                OpenCount++;
                file->file_IO = iotd;
                file->file_MinOffset = this_Offset;
                file->file_Offset = this_Offset;
                file->file_MaxOffset = this_Offset + this_Length;
                if (this_Eof == -1)
                    file->file_EofOffset = file->file_MaxOffset;
                else
                    file->file_EofOffset = this_Offset + this_Eof;
            }
            {
                struct FileHandle *fh;
                fh = (FH *)BADDR(MyPkt->dp_Arg1);       /* File handle  */
                fh->fh_Arg1 = (long) file;
            }
#ifdef DEBUG
            if (Fh) {
                sprintf(Buf, "Open File %08lx iotd: %08lx\n", file, iotd);
                Write(Fh, Buf, strlen(Buf));
            }
#endif
            branchto returnpkt;

openfail4:
            CloseDevice(iotd);
openfail3:
            DeleteExtIO(iotd);
openfail2:
            FreeMem(file, sizeof(*file));
openfail1:
            returnpkt(MyPkt, MyProc, DOS_FALSE, ERROR_NO_FREE_STORE);
            break;

returnpkt:
            returnpktplain(MyPkt, MyProc);
            break;

        case ACTION_END:                            /* CLOSE    */
            iotd = file->file_IO;
#ifdef DEBUG
            if (Fh) {
                sprintf(Buf, "Close File %08lx iotd: %08lx\n", file, iotd);
                Write(Fh, Buf, strlen(Buf));
            }
#endif
            PerformIO(iotd, CMD_UPDATE, 0, 0, 0);
            PerformIO(iotd, TD_MOTOR, 0, 0, 0);
            CloseDevice(iotd);
            DeleteExtIO(iotd);
            save_Eof = file->file_EofOffset - file->file_MinOffset;
            FreeMem(file, sizeof(*file));
            returnpktplain(MyPkt, MyProc);
            --OpenCount;
            break;

        case ACTION_READ:                   /* Arg2: buffer */
            iotd = file->file_IO;
            {                               /* Arg3: size   */
                char *buffer = (char *) MyPkt->dp_Arg2;
                long size = MyPkt->dp_Arg3;
                long done = 0;
                int blockoffset = 0;
#ifdef DEBUG
                if (Fh) {
                    sprintf(Buf, "Read File %08lx iotd: %08lx\n", file, iotd);
                    Write(Fh, Buf, strlen(Buf));
                    sprintf(Buf, " buffer %08lx  size %08lx offset %08lx\n",
                      buffer, size, file->file_Offset);
                    Write(Fh, Buf, strlen(Buf));
                }
#endif
                /* Is this such a special read-last-eof file? */
                if ((LONG) file->file_Offset < 0) {
                    if (size >= 4) {
                        movmem(&save_Eof, buffer, 4);
                        MyPkt->dp_Res1 = 4;
                    } else
                        MyPkt->dp_Res1 = 0;
                    file->file_Offset = 0;
                    file->file_EofOffset = 0;
                    branchto readdone;
                }

                /* Don't read past the end of the virtual file */
                done = file->file_EofOffset - file->file_Offset;
                if (size > done) size = done;
                MyPkt->dp_Res1 = size;

                blockoffset = file->file_Offset & TD_SECMASK;

                /* Can we read directly into the user buffer? */
                if ((size >= TD_SECTOR) &&
                    blockoffset == 0 &&
                    (size & 3) == 0 && (((long)buffer) & 3) == 0 &&
                    (TypeOfMem(buffer) & MEMF_CHIP)) {
                    done = PerformIO(iotd, ETD_READ, buffer,
                           file->file_Offset, size & ~TD_SECMASK);
                    if (iotd->iotd_Req.io_Error)
                        branchto readfail;
                    file->file_Offset += done;
                    buffer += done;
                    size -= done;
                }
                /* Read the rest (or all of it) via our MEMF_CHIP buffer */
                while (size > 0) {
                    /* Get one disk block: do a bit of padding at the start */
                    done = PerformIO(iotd, ETD_READ, TDBuffer,
                           file->file_Offset - blockoffset, TD_SECTOR)
                         - blockoffset;         /* and subtract the padding */
                    if (iotd->iotd_Req.io_Error || done <= 0) {
readfail:
                        MyPkt->dp_Res1 = -1;
                        MyPkt->dp_Res2 = ERROR_READ_PROTECTED; /* Silly */
                        break;
                    }
                    /* Don't copy more than the user wanted */
                    if (done > size) done = size;
                    movmem(TDBuffer + blockoffset, buffer, done);
                    file->file_Offset += done;
                    /* Normally the block offset becomes 0 now */
                    blockoffset = file->file_Offset & TD_SECMASK;
                    buffer += done;
                    size -= done;
                }
readdone: ;
#ifdef DEBUG
                if (Fh) {
                    sprintf(Buf, " Read: %ld DoIO: %ld size left: %lx\n",
                      MyPkt->dp_Res1, iotd->iotd_Req.io_Error, size);
                    Write(Fh, Buf, strlen(Buf));
                }
#endif
            }
            branchto returnpkt;

        case ACTION_WRITE:
            iotd = file->file_IO;
            {
                char *buffer = (char *) MyPkt->dp_Arg2;
                long size = MyPkt->dp_Arg3;
                long done = 0;
                int blockoffset = 0;
#ifdef DEBUG
                if (Fh) {
                    sprintf(Buf, "Write File %08lx iotd: %08lx\n", file,iotd);
                    Write(Fh, Buf, strlen(Buf));
                    sprintf(Buf, " buffer %08lx  size %08lx offset %08lx\n",
                      buffer, size, file->file_Offset);
                    Write(Fh, Buf, strlen(Buf));
                }
#endif
                /* Don't write past the end of the device */
                done = file->file_MaxOffset - file->file_Offset;
                if (size > done) {
                    size = done;
                    MyPkt->dp_Res2 = ERROR_DISK_FULL;
                }
                MyPkt->dp_Res1 = size;

                blockoffset = file->file_Offset & TD_SECMASK;

                /* Can we write directly into the user buffer? */
                if ((size >= TD_SECTOR) &&
                    blockoffset == 0 &&
                    (size & 3) == 0 && (((long)buffer) & 3) == 0 &&
                    (TypeOfMem(buffer) & MEMF_CHIP)) {
                    done = PerformIO(iotd, ETD_WRITE, buffer,
                           file->file_Offset, size & ~TD_SECMASK);
                    if (iotd->iotd_Req.io_Error)
                        branchto writefail;
                    file->file_Offset += done;
                    buffer += done;
                    size -= done;
                }

                /* Write the rest (or all of it) via our MEMF_CHIP buffer */
                while (size > 0) {
                    /* Get a partial disk block */
                    if (blockoffset || size < TD_SECTOR) {
                        PerformIO(iotd, ETD_READ, TDBuffer,
                                  file->file_Offset - blockoffset, TD_SECTOR);
                        if (iotd->iotd_Req.io_Error)
                            branchto writefail;
                    }

                    if (blockoffset + size > TD_SECTOR)
                        done = TD_SECTOR - blockoffset;
                    else
                        done = size;
                    movmem(buffer, TDBuffer + blockoffset, done);

                    /* Write the buffer (back) */
                    PerformIO(iotd, ETD_WRITE, TDBuffer,
                              file->file_Offset - blockoffset, TD_SECTOR);

                    /* On error we did not write the block */
                    if (iotd->iotd_Req.io_Error ||
                        iotd->iotd_Req.io_Actual != TD_SECTOR) {
writefail:
                        MyPkt->dp_Res1 = -1;
                        MyPkt->dp_Res2 = ERROR_WRITE_PROTECTED; /* Silly */
                        break;
                    }

                    file->file_Offset += done;
                    /* Normally the block offset becomes 0 now */
                    blockoffset = file->file_Offset & TD_SECMASK;
                    buffer += done;
                    size -= done;
                }
#ifdef DEBUG
                if (Fh) {
                    sprintf(Buf, " Write: %ld DoIO: %ld size left: %lx\n",
                      MyPkt->dp_Res1, iotd->iotd_Req.io_Error, size);
                    Write(Fh, Buf, strlen(Buf));
                }
#endif
            }

            /* Writing may adjust the end-of-file marker */
            if (file->file_Offset > file->file_EofOffset)
               file->file_EofOffset = file->file_Offset;
            branchto returnpkt;

        case ACTION_RENAME_DISK:  /* for debugging */
        case ACTION_DIE:
            Expunge = 1;
            if (OpenCount == 0) NotDone = 0;
            branchto returnpkt;

        case ACTION_SEEK:
            {
                long Offset = -1;

                switch (MyPkt->dp_Arg3) {   /* seek mode */
                case OFFSET_BEGINNING:
                    Offset = file->file_MinOffset + MyPkt->dp_Arg2;
                    break;
                case OFFSET_CURRENT:
                    Offset = file->file_Offset + MyPkt->dp_Arg2;
                    break;
                case OFFSET_END:
                    Offset = file->file_EofOffset + MyPkt->dp_Arg2;
                    break;
                }
                if (Offset >= file->file_MinOffset &&
                    Offset <= file->file_EofOffset) {
                    MyPkt->dp_Res1 = Offset - file->file_MinOffset;
                    file->file_Offset = Offset;
                } else {
                    MyPkt->dp_Res1 = -1;
                    MyPkt->dp_Res2 = ERROR_SEEK_ERROR;
                }
            }
            branchto returnpkt;

        case ACTION_LOCATE_OBJECT:  /* Just always succeed */
            {
                struct FileLock *lock;

                if (lock = AllocMem(sizeof (*lock), MEMF_PUBLIC | MEMF_CLEAR))
                {
                    lock->fl_Access = MyPkt->dp_Arg3;
                    lock->fl_Task = &MyProc->pr_MsgPort;
                    /* lock->fl_Volume remains NULL */
                    OpenCount++;
                } else
                    MyPkt->dp_Res2 = ERROR_NO_FREE_STORE;
                MyPkt->dp_Res1 = ((long) lock) >> 2;
            }
            branchto returnpkt;

        case ACTION_COPY_DIR:
            {
                struct FileLock *lock;

                if (lock = AllocMem(sizeof (*lock), MEMF_PUBLIC | MEMF_CLEAR)) {
                    *lock = *(struct FileLock *)BADDR(MyPkt->dp_Arg1);
                    OpenCount++;
                } else
                    MyPkt->dp_Res2 = ERROR_NO_FREE_STORE;
                MyPkt->dp_Res1 = ((long) lock) >> 2;
            }
            branchto returnpkt;

        case ACTION_FREE_LOCK:
            {
                if (MyPkt->dp_Arg1) {
                    FreeMem(BADDR(MyPkt->dp_Arg1), sizeof (struct FileLock));
                    OpenCount--;
                }
            }
            branchto returnpkt;

        default:
            returnpkt(MyPkt, MyProc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
            break;
        } /* end switch */
    } /* end while (NotDone) */

    /*
     *  Can only exit if no messages pending.  There might be a window
     *  here, but there is nothing that can be done about it.
     */

#ifdef DEBUG
    if (!Expunge)
        branchto top;
#endif

    Forbid();
    if (taskpktrdy(MyProc)) {
        Permit();
        branchto top;
    }

    MyNode->dn_Task = NULL;
    Permit();

exit:

    if (IOPort) DeletePort(IOPort);
    if (TDBuffer) FreeMem(TDBuffer, TD_SECTOR);

#ifdef DEBUG
    if (Fh) Close(Fh);
#endif

    /* We are a process "so we fall off the end of the world" */

    if (Expunge) {
        OpenCount = MyNode->dn_SegList;     /* Temporary */
        Forbid();
        MyNode->dn_SegList = NULL;
        UnLoadSeg(OpenCount);
        /* We execute in unallocated memory now... and Forbid()den. */
    }
    CloseLibrary(DOSBase);

    /* MUST fall through */
}

ULONG PerformIO(ioReq, cmd, buffer, offset, size)
register struct IOExtTD *ioReq;
ULONG cmd;
APTR  buffer;
ULONG offset;
ULONG size;
{
#ifdef DEBUG
    if (Fh) {
        sprintf(Buf, "PerfIO buffer %08lx  size %08lx offset %08lx\n",
        buffer, size, offset);
        Write(Fh, Buf, strlen(Buf));
    }
#endif
    ioReq->iotd_Req.io_Command = cmd;
    ioReq->iotd_Req.io_Length = size;
    ioReq->iotd_Req.io_Data = buffer;
    ioReq->iotd_Req.io_Offset = offset;
    DoIO(ioReq);
    return ioReq->iotd_Req.io_Actual;
}

int todigit(c)
register char c;
{
    if ((c -= '0') < 0 || c > ('F' - '0'))
        return 42;

    if (c >= ('A' - '0')) {
        c -= 'A' - '9' - 1;
    }

    return c;
}

long ntoi(str)
register char *str;
{
    register long total = 0;
    register long value;
    register int digit;
    register int base;

    /* First determine the base */
number:
    if (*str == '0') {
        if (*++str == 'x') {    /* 0x means hexadecimal */
            base = 16;
            str++;
        } else {
            base = 8;           /* Otherwise, 0 means octal */
        }
    } else {
        base = 10;              /* and any other digit means decimal */
    }

    value = 0;
    while ((digit = todigit(*str)) < base) {
        value *= base;
        value += digit;
        str++;
    }

suffix:
    switch (*str++) {
    case 'm':                   /* scale with megabytes */
        value *= 1024 * 1024;
        branchto suffix;
    case 'k':                   /* scale with kilobytes */
        value *= 1024;
        branchto suffix;
    case 's':                   /* scale with sectors */
        value *= TD_SECTOR;     /* or maybe even kilosectors! */
        branchto suffix;
    case 'b':                   /* scale with bytes */
        branchto suffix;
    }
    str--;

    total += value;

    if (*str >= '0' && *str <= '9')
        branchto number;        /* Allow 10k512, recursion eliminated */

    return total;
}

SHAR_EOF
cat << \SHAR_EOF > rdf.man.uu

begin 644 rdf.man
M"B`@("`@4D1&*#0I("`@("`@("`@("`@("`@($%M:6=A(%!R;V=R86UM97(G-
M<R!-86YU86P@("`@("`@("`@("`@("`@(%)$1B@T*0H*"@H@("`@()LQ;4Y!"
M344@"B`@("`@("`@("";,&UR9&8Z("T@<F%W(&EN=&5R9F%C92!T;R!D:7-K`
M<R`*"B`@("`@FS%M4UE.3U!325,@"B`@("`@("`@("";,&U-;W5N="!21$8ZS
M"B`@("`@("`@("!21$8Z+V0\<V]M92YD979I8V4^("`H<V5T($1E=FEC92!AD
M<F=U;65N="!F;W(@3W!E;D1E=FEC92D*("`@("`@("`@("`@("`O=3QU;FET^
M(",^("`@("`@("AS970@56YI="!A<F=U;65N="!F;W(@3W!E;D1E=FEC92D*T
M("`@("`@("`@("`@("`O9CQF;&%G<SX@("`@("`@("AS970@1FQA9W,@87)GW
M=6UE;G0@9F]R($]P96Y$979I8V4I"B`@("`@("`@("`@("`@+V\\;V9F<V5TF
M/B`@("`@("`H<V5T(&EN:71I86P@;V9F<V5T(&]N(&1E=FEC92D*("`@("`@#
M("`@("`@("`O;#QL96YG=&@^("`@("`@("AS970@;&5N9W1H(&]F('!H>7-I/
M8V%L(&1E=FEC92D*("`@("`@("`@("`@("`O93QE;V8^("`@("`@("`@("AS6
M970@86YD(&UA:6YT86EN(&$@=FER='5A;"!E;F0M;V8M9FEL92D*("`@("`@>
M("`@("`@("`O12`@("`@("`@("`@("`@("AG970@96]F(&9R;VT@;&%S="!C!
M;&]S960@9FEL92D*"B`@("`@("`@("!20V]P>2`\<V]U<F-E/B`\9&5S=&EN/
M871I;VX^"@H@("`@()LQ;41%4T-225!424].(`H@("`@("`@("`@FS!MFS-MG
M4D1&.B`@()LP;6ES("`@82`@(&1O<RUL979E;"`@('!A8VME="`@(&AA;F1LU
M97(@(&EN=&5R9F%C92`@9F]R"B`@("`@("`@("!T<F%C:V1I<VLN9&5V:6-EW
M+6QI:V4@97AE8R`@9&5V:6-E<RX@("`@270@(&5N86)L97,@('EO=2`@=&\*)
M("`@("`@("`@(&]P97)A=&4@;VX@82!F;&]P<'D@9&ES:R`H;W(@:68@>6]U(
M(&QI:V4L('EO=7(@:&%R9"!D:7-K*2!A<PH@("`@("`@("`@82!S97%U96YT7
M:6%L("!S=')E86T@;V8@8GET97,N("!)="!B>7!A<W-E<R!B=69F97)S('1H\
M870@87)E"B`@("`@("`@("!M86YA9V5D(&)Y('1H92!F:6QE('-Y<W1E;2`HM
M87,@861D960@8GD@("=!9&1"=69F97)S)RDL("!B=70*("`@("`@("`@(&ET,
M("!M86ME<R`@=7-E("!O9B!B=69F97)S(&UA;F%G960@8GD@82!D979I8V4@9
M8G5F9F5R(&-A8VAE+`H@("`@("`@("`@<W5C:"!A<R!&86-C(&%N9"!&86-C8
M($E)+B!9;W4@8V%N($]P96XH,BD@82!F:6QE(&]N('1H92";,VU21$8Z"B`@>
M("`@("`@("";,&UD979I8V4L(&%N9"!T:&5N(%)E860H,BD@9G)O;2!A;F0@<
M5W)I=&4H,BD@=&\@:70N("!9;W4@(&YE960*("`@("`@("`@(&YO="`@8F4@7
M(&-O;F-E<FYE9"`@86)O=70@('1H92`@<V5C=&]R("!A;&EG;FUE;G0@('1H8
M870@('1H90H@("`@("`@("`@=')A8VMD:7-K+F1E=FEC92!I;7!O<V5S.R!IB
M9B!N965D960L()LS;5)$1CH@FS!M=VEL;"!U<V4@(&ET<R`@;W=N"B`@("`@3
M("`@("!P<FEV871E("!B=69F97(@('1O("!R96%D("!O<B`@=W)I=&4@('!AQ
M<G1I86P@<V5C=&]R<R!O;B!T:&4*("`@("`@("`@(&1I<VLN("`*("`@("`@*
M("`@()LS;5)#;W!Y()LP;6ES(&$@=F5R>2!S:6UP;&4L(&YO(&9R:6QL<R`@"
M8V]P>2`@<')O9W)A;2`@=&AA="`@;VYL>0H@("`@("`@("`@=7-E<R!/<&5NB
M*"DL($-L;W-E*"DL(%)E860H*2!A;F0@5W)I=&4H*2!T;R!C;W!Y(&$@9FEL&
M92X@($ET"B`@("`@("`@("!H87,@(&)E96X@(&]P=&EM:7IE9"`@=&\@8F4@O
M=7-E9"!W:71H()LS;5)$1CH@FS!M+"!S:6YC92!I="!U<V5S(&$*("`@("`@<
M("`@(&)U9F9E<B!O9B`@,C(@("H@(%1$7U-%0U1/4B`@8GET97,@("AA("!SG
M:6YG;&4@(&-Y;&EN9&5R("!O;@H@("`@("`@("`@9FQO<'!I97,I('1H870@,
M(&ES("!L;V-A=&5D("!I;B`@0VAI<"`@;65M;W)Y+B`@("!4:&ES("!W87DL/
M"B`@("`@("`@("!U;FYE8V5S<V%R>2!M96UO<GD@8V]P>2!O<&5R871I;VYSR
M(&%R92!A=F]I9&5D+B`@"@H@("`@("`@("`@("`@("";,VU21$8Z()LP;7)EV
M8V]G;FEZ97,@<V]M92!O<'1I;VYS('1H870@>6]U("!C86X@('-P96-I9GD@U
M(&EN"B`@("`@("`@("!T:&4@9FEL92`@;F%M92`@<W5P<&QI960@('1O(&ETI
M+B`@36]S="!O<'1I;VYS(&AA=F4@9&5F875L=',*("`@("`@("`@('1H870@4
M87)E('-E="!I;B!T:&4@36]U;G1,:7-T("AS964@8F5L;W<I+B`@3W!T:6]N9
M<R`@8V]N<VES=`H@("`@("`@("`@;V8@(&$@9F]R=V%R9"!S;&%S:"P@9F]L3
M;&]W960@8GD@82!S:6YG;&4@;&5T=&5R+"!O<'1I;VYA;&QY"B`@("`@("`@*
M("!F;VQL;W=E9"!B>2!A('9A;'5E+B`@5&AE(&9O;&QO=VEN9R!O<'1I;VYS!
M(&%R92!R96-O9VYI>F5D.B`*"B`@("`@("`@("`@("`@()LS;5)$1CHO9#QS#
M;VUE($5X96,@9&5V:6-E(&YA;64^()LP;2AS970@1&5V:6-E(&%R9W5M96YTT
M("!F;W(*("`@("`@("`@($]P96Y$979I8V4I(`H@("`@("`@("`@5&AE(&YA6
M;64@>6]U('-U<'!L>2!H97)E('=I;&P@8F4@=7-E9"!I;B!T:&4@3W!E;D1EC
M=FEC92!C86QL"B`@("`@("`@("!T:&%T("!I<R`@<&%R="`@;V8@=&AE(&%C+
M=&EO;G,@;V8@;W!E;FEN9R!A(&9I;&4@;VX@=&AE()LS;5)$1CH*("`@("`@,
M("`@()LP;7!S975D;R!D979I8V4N("`@($%N>2`@17AE8R`@9&5V:6-E("!T7
M:&%T("!L;V]K<R`@;&EK92`@('1H90H@("`@("`@("`@=')A8VMD:7-K+F1EL
M=FEC92!I<R`@=F%L:60N("`@26X@<&%R=&EC=6QA<BP@FS-M4D1&.B";,&UOS
M;FQY(')E861S"B`@("`@("`@("!A;F0@('=R:71E<R`@8FQO8VMS("!O9B`@P
M(%1$7U-%0U1/4B`@(&)Y=&5S("`@;VX@("!41%]314-43U(*("`@("`@("`@\
M(&)O=6YD87)I97,N("!4:&ES(&EM<&QI97,@=&AA="`H<V5Q=65N=&EA;"D@"
M9&5V:6-E<R!L:6ME('1H90H@("`@("`@("`@<V5R:6%L+F1E=FEC92`@=VEL]
M;"`@;F]T('=O<FLL('-I;F-E(')E<&5A=&5D(')E861S('=I=&@@=&AE"B`@>
M("`@("`@("!S86UE($]F9G-E="!W:6QL('5S=6%L;'D@;F]T(')E='5R;B!TY
M:&4@<V%M92!D871A+B`@"B`@("`@("`@("!)9B!Y;W4@9&]N)W0@<W5P<&QYZ
M('1H:7,@;W!T:6]N+"!T:&4@9&5F875L="!I<R`@=&%K96X@(&9R;VT*("`@0
M("`@("`@('1H92!-;W5N=$QI<W0@96YT<GD@)T1E=FEC92`])RX@(`H*("`@_
M("`@("`@("`@("`@FS-M4D1&.B]U/'5N:70@(SX@FS!M*'-E="!5;FET(&%RQ
M9W5M96YT(&9O<B!/<&5N1&5V:6-E*2`*("`@("`@("`@(%1H:7,@56YI="!W[
M:6QL(&)E(&]P96YE9"!O;B!T:&4@<W!E8VEF:65D(&]R(&1E9F%U;'0@1&5VR
M:6-E+@H@("`@("`@("`@268@('EO=2`@9&]N)W0@<W5P<&QY('1H:7,@;W!TI
M:6]N+"!T:&4@9&5F875L="!I<R!T86ME;B!F<F]M"@H*("`@("!+;W-M;U-OD
M9G0@("`@("`@("`@("`@("`@("`@("`@("`M,2T@("`@("`@("`@("`@("`@E
M("`@("`@(%)E;&5A<V4@,2XP"@H*("`@("!21$8H-"D@("`@("`@("`@("`@/
M("`@06UI9V$@4')O9W)A;6UE<B=S($UA;G5A;"`@("`@("`@("`@("`@("`@S
M4D1&*#0I"@H*("`@("`@("`@('1H92!-;W5N=$QI<W0@96YT<GD@)U5N:70@H
M/2<N("`*"B`@("`@("`@("`@("`@()LS;5)$1CHO9CQF;&%G<SX@FS!M*'-E+
M="!&;&%G<R!A<F=U;65N="!F;W(@3W!E;D1E=FEC92D@"B`@("`@("`@("!44
M:&5S92!&;&%G<R!W:6QL(&)E('-P96-I9FEE9"!O;B!T:&4@;W!E;B!O9B`@B
M=&AE("!S<&5C:69I960*("`@("`@("`@(&]R("!D969A=6QT("!$979I8V4N[
M("!)9B`@>6]U("!D;VXG="!S=7!P;'D@=&AI<R!O<'1I;VXL('1H90H@("`@=
M("`@("`@9&5F875L="!I<R!T86ME;B!F<F]M('1H92!-;W5N=$QI<W0@96YT_
M<GD@)T9L86=S(#TG+B`@"@H@("`@("`@("`@("`@("";,VU21$8Z+V\\;V9FK
M<V5T/B";,&TH<V5T(&EN:71I86P@;V9F<V5T(&]N(&1E=FEC92D@"B`@("`@'
M("`@("!4:&ES(&]P=&EO;B!L971S('EO=2!S<&5C:69Y('=H97)E('EO=7(@C
M=FER='5A;"!F:6QE("!S=&%R=',*("`@("`@("`@(&]N('1H92`@<&AY<VEC`
M86P@(&1E=FEC92X@("`@5&AE<F4@:7,@;F\@=V%Y('EO=2!C86X@<F5A9"!OG
M<@H@("`@("`@("`@=W)I=&4@9&%T82!B969O<F4@=&AI<R!P;VEN="`@;VX@3
M('1H92`@9&ES:RX@("`@06YY("!3965K*#(I"B`@("`@("`@("!O9F9S970@>
M=VEL;"!B92!R96QA=&EV92!T;R!T:&ES('!O:6YT+B`@5&AE(&1E9F%U;'0@T
M9F]R('1H:7,*("`@("`@("`@(&]P=&EO;B!I<R`P+B`@"@H@("`@("`@("`@0
M("`@("";,VU21$8Z+VP\;&5N9W1H/B";,&TH<V5T(&QE;F=T:"!O9B!P:'ES/
M:6-A;"!D979I8V4I(`H@("`@("`@("`@5&AI<R`@;W!T:6]N("!L971S("!Y>
M;W4@('-P96-I9GD@('1H92!L96YG=&@@;V8@=&AE('!H>7-I8V%L"B`@("`@W
M("`@("!D979I8V4N("";,VU21$8Z()LP;7=O;B=T(&%T=&5M<'0@=&\@<F5A0
M9"!O<B!W<FET92!M;W)E('1H86X@('1H:7,*("`@("`@("`@(&%M;W5N="!OS
M9B`@8GET97,@('!A<W0@('1H92`@:6YI=&EA;"!O9F9S970N("!)9B!Y;W4@1
M<W!E8VEF>0H@("`@("`@("`@=&AI<R!V86QU92!T;V\@;&%R9V4@9F]R('1HR
M92!P:'ES:6-A;"`@9&5V:6-E+"`@=&AE("!$;TE/*#(I"B`@("`@("`@("!CZ
M86QL('=I;&P@<F5T=7)N(&%N(&5R<F]R+"!S;R!T:&4@4F5A9"@I(&]R(%=RP
M:71E*"D@=VEL;"!N;W0*("`@("`@("`@(')E='5R;B!T:&4@(&YU;6)E<B`@P
M;V8@(&)Y=&5S("!R97%U97-T960N("!)9B!T:&ES(&]P=&EO;B!I<PH@("`@"
M("`@("`@=7-E9"!P<F]P97)L>2P@FS-M4D1&.B";,&UW;VXG="!E=F5N("!TT
M<GD@(&1O("!A8V-E<W,@('1H92`@9&5V:6-E"B`@("`@("`@("!B97EO;F0@,
M:71S("!L:6UI="X@($]R('EO=2!C86X@;6%K92!S=7)E('1H870@;VYL>2!A^
M('!A<G0@;V8*("`@("`@("`@('1H92!D979I8V4@8V%N(&)E(&%C8V5S<V5D[
M+B`@5&AE(&1E9F%U;'0@9F]R('1H:7,@;W!T:6]N("!I<PH@("`@("`@("`@R
M.#@P:RX@(`H*("`@("`@("`@("`@("`@FS-M4D1&.B]E/&5O9CX@FS!M*'-E>
M="!A;F0@;6%I;G1A:6X@82!V:7)T=6%L(&5N9"UO9BUF:6QE*2`*("`@("`@9
M("`@(%1H:7,@(&]P=&EO;B`@<W!E8VEF:65S("!T:&%T()LS;5)$1CH@FS!MF
M<VAO=6QD(&UA:6YT86EN(&$@=FER='5A;`H@("`@("`@("`@96YD(&]F(&9I-
M;&4@;6%R:V5R+B`@5&AI<R!M86ME<R!A(&9I;&4@;VX@FS-M4D1&.B`@FS!M1
M;&]O:R`@82`@8FET"B`@("`@("`@("!M;W)E(&QI:V4@(&$@(&YO<FUA;"`@!
M9&ES:R`@9FEL92X@("!!;GD@871T96UP="!T;R!296%D*"D@;W(*("`@("`@;
M("`@(%-E96LH*2!P87-T('1H92!E;F0@;V8@9FEL92!M87)K97(@:7,@<F5J=
M96-T960N("!(;W=E=F5R+"`@80H@("`@("`@("`@5W)I=&4H*2`@<&%S="`@^
M=&AE("!E;F0@;V8@9FEL92!M87)K(&ES(&%L;&]W960L(&%N9"!I;B!T:&%T#
M"B`@("`@("`@("!C87-E('1H92!E;F0@;V8@9FEL92!I<R!U<&1A=&5D('1O9
M(')E9FQE8W0@=&AA="!T:&4@('9I<G1U86P*("`@("`@("`@(&9I;&4@:&%S$
M("!G<F]W;BX@("`@5&AI<R`@:7,@<&%R=&EC=6QA<GD@=7-E9G5L(&9O<B!P*
M<F]G<F%M<PH@("`@("`@("`@=&AA="!3965K*"D@<F5L871I=F4@=&\@=&AE/
M(&5N9"!O9B!T:&4@9FEL92X@("`@5&AE("!D969A=6QT"B`@("`@("`@("!F1
M;W(@('1H:7,@(&]P=&EO;B`@:7,@('1H92`@=F%L=64@9F]R("]L+B!)9B!YD
M;W4@<W!E8VEF>2!T:&4*("`@("`@("`@(&]P=&EO;B!W:71H;W5T(&$@=F%L3
M=64L(#`@:7,@87-S=6UE9"X@(`H*("`@("`@("`@("`@("`@FS-M4D1&.B]%+
M()LP;2AG970@96]F(&9R;VT@;&%S="!C;&]S960@9FEL92D@"B`@("`@("`@O
M("!3;VUE=&EM97,@:70@;6%Y(&)E(&YE8V5S<V%R>2!T;R!K;F]W+"!H;W<@*
M;&%R9V4@=&AE('9I<G1U86P*("`@("`@("`@(&9I;&4@:&%S(&=R;W=N+B`@4
M1F]R(&5X86UP;&4L('EO=2!M87D@;&%T97(@=V%N="!T;R!A9&0@9&%T80H@%
M("`@("`@("`@=&\@=&AE(&5N9"X@(%1H97)E9F]R92P@=&AE(&9O;&QO=VEND
M9R!H86-K('=A<R!C;VYC96EV960N("`*("`@("`@("`@($EF('EO=2!O<&5N/
M('1H92!F:6QE(%)$1CHO12!A;F0@=&AE;B!R96%D(&%T(&QE87-T(#0@(&)Y&
M=&5S+`H@("`@("`@("`@>6]U('=I;&P@9V5T('1H92!E;F0@;V8@9FEL92!V:
M86QU92!F<F]M('1H92!L87-T(&-L;W-E9"!F:6QE"B`@("`@("`@("!I;G1O.
M('EO=7(@(&)U9F9E<B`@87,@(&$@('-I9VYE9"`@;&]N9W=O<F0N("!4:&4@S
M4F5A9"@I('=I;&P*("`@("`@("`@(')E='5R;B`T(&EN('1H:7,@8V%S92X@\
M($]T:&5R=VES92!T:&4@4F5A9"@I('=I;&P@<F5T=7)N("`P+@H@("`@("`@(
M("`@26X@86YY("!C87-E+"`@<W5B<V5Q=65N="!296%D*"ES(&%L=V%Y<R!RY
M971U<FX@,"X@(%=R:71E*"ES"B`@("`@("`@("!T;R!T:&ES(&9I;&4@87)E8
M(&YO="!A;&QO=V5D+"!A;F0@=&AE(')E<W5L="!I<R!U;F1E9FEN960N("`*>
M"@H@("`@("`@("`@("`@("!4:&4@;G5M97)I8R!A<F=U;65N=',@>6]U(&-A_
M;B!S=7!P;'D@=VET:"`@=&AE("!V87)I;W5S"B`@("`@("`@("!O<'1I;VYSW
M("!C86X@(&)E("!D96-I;6%L("`H;F\@('!R969I>"DL(&]C=&%L("AP<F5F8
M:7@@,"D@;W(*("`@("`@("`@(&AE>&%D96-I;6%L("AP<F5F:7@@,'@I+B!4#
M:&4@:&5X861E8VEM86P@9&EG:71S($$@=&AR;W5G:"`@1@H@("`@("`@("`@8
M;75S="!B92`@9VEV96X@(&EN('5P<&5R8V%S92X@($9O;&QO=VEN9R!T:&4@H
M;G5M8F5R+"!A('-C86QE"B`@("`@("`@("!F86-T;W(@;6%Y(&)E(&=I=F5NN
M(&EN(&QO=V5R8V%S92X@(%1H92!C=7)R96YT;'D@(')E8V]G;FEZ960*("`@'
M("`@("`@('-C86QE<R!A<F4@FS-M;2";,&UF;W(@;65G86)Y=&5S+"";,VUKM
M()LP;69O<B!K:6QO8GET97,L()LS;7,@FS!M9F]R('1R86-K9&ES:PH@("`@8
M("`@("`@<V5C=&]R<R!A;F0@FS-M8B";,&UF;W(@8GET97,N("!-=6QT:7!L.
M92!F86-T;W)S(&%R92!A;'-O(&%L;&]W960L"B`@("`@("`@("!W:&EC:"!S"
M=&%N9"!F;W(@=&AE('!R;V1U8W0@;V8@=&AE:7(@<F5S<&5C=&EV92!F86-T9
M;W)S+B`@"@H*("`@("!+;W-M;U-O9G0@("`@("`@("`@("`@("`@("`@("`@E
M("`M,BT@("`@("`@("`@("`@("`@("`@("`@(%)E;&5A<V4@,2XP"@H*("`@:
M("!21$8H-"D@("`@("`@("`@("`@("`@06UI9V$@4')O9W)A;6UE<B=S($UAD
M;G5A;"`@("`@("`@("`@("`@("`@4D1&*#0I"@H*("`@("`@("`@($9O;&QO+
M=VEN9R`@=&AE("!S97%U96YC92`@;V8@('-C86QE("!F86-T;W)S+"`@82`@K
M;F5W("!D:6=I=`H@("`@("`@("`@<VEG;FEF:65S('1H870@86YO=&AE<B!N6
M=6UB97(@9F]L;&]W<RX@(%1H870@;G5M8F5R(&ES(&%D9&5D"B`@("`@("`@!
M("!T;R!T:&4@=F%L=64@86QR96%D>2!C86QC=6QA=&5D+B`@5&AI<R!I<R!U,
M<V5F=6P@=&\@('-P96-I9GD*("`@("`@("`@(&$@=F%L=64@;V8@,C`@2R!PO
M;'5S(#,R(&)Y=&5S.B`R,&LS,BX@(`H*("`@("`@("`@("`@("`@06YY=&AI[
M;F<@=&AA="`@:7,@;F]T('!A<G0@;V8@82!N=6UB97(L(&DN92X@(&IU;FL@W
M;&EK90H@("`@("`@("`@<W5F9FEX97,@861D960@8GD@<V]M92!P<F]G<F%M5
M<RP@:7,@:6=N;W)E9"X@($%L<V\@(&%N>71H:6YG"B`@("`@("`@("!B971W^
M965N('1H92!C;VQO;B!O9B";,VU21$8Z()LP;6%N9"!T:&4@9FER<W0@<VQA.
M<V@@:7,@:6=N;W)E9"P@:6X*("`@("`@("`@(&-A<V4@('EO=2`@=VES:"`@`
M=&\@=7-E(&9I;&4@;F%M92!S>6YT87@@8V]M<&%T:6)L92!W:71H('1H90H@_
M("`@("`@("`@<F5S="!O9B!T:&4@<WES=&5M+B`@3VYL>2!T:&4@9FER<W0@2
M;&5T=&5R(&9O;&QO=VEN9R!A('-L87-H"B`@("`@("`@("!I<R`@<VEG;FEFC
M:6-A;G0L("!A;F0@(&UU<W0@(&)E("!F;VQL;W=E9"`@9&ER96-T;'D@(&)Y5
M("!A;GD*("`@("`@("`@(')E<75I<F5D(&%R9W5M96YT+B`@"@H@("`@("`@8
M("`@("`@("!9;W4@(&UA>2`@4F5A9"@I(&%N9"!7<FET92@I(&%N>2!N=6UB:
M97(@;V8@8GET97,@;VX@86YY"B`@("`@("`@("!O9F9S970N("!)9B!T:&4@G
M22]/(&ES(&YO="!S=6ET86)L>2!A;&EG;F5D+"!D871A(&ES("!C;W!I960*5
M("`@("`@("`@('1H<F]U9V@@82`@8G5F9F5R('!R:79A=&4@=&\@4D1&+B`@$
M0F5C875S92!T:&5R92!I<R!O;FQY(&]N90H@("`@("`@("`@<V5C=&]R("`@J
M8G5F9F5R+"`@(&%L;"`@(&EN8V]M:6YG("`@<&%C:V5T<R`@(&%R92`@("!H^
M86YD;&5D"B`@("`@("`@("!S>6YC:')O;F]U<VQY+B`@(%1H:7,@(&ES("!T8
M;R`@879O:60@:&%V:6YG(&UU;'1I<&QE($E/17AT5$0*("`@("`@("`@(')E-
M<75E<W1S(&]U='-T86YD:6YG+"!W:&EC:"`@;6%Y("!B96-O;64@('%U:71EN
M("!C;VUP;&EC871E9`H@("`@("`@("`@=VAE;B`@;75L=&EP;&4@(')E<75E/
M<W1S("!A<F4@(&]U='-T86YD:6YG(&]N('1H92!S86UE(&9I;&4N"B`@("`@^
M("`@("!4:&ES(&ES(&%L<V\@=&AE(&]N;'D@*'-I;7!L92D@=V%Y('1H870@C
M(&9U;&P@('-E<FEA;&ES871I;VX*("`@("`@("`@(&]F("!)+T\@('1H<F]UB
M9V@@FS-M4D1&.B";,&UC86X@8F4@9W5A<F%N=&5E9"`H=VAI8V@@<V5E;7,@I
M=&\@8F4@80H@("`@("`@("`@9V]O9"!T:&EN9RDN("`*"B`@("`@("`@("`@#
M("`@($EF('EO=2!W<FET92!A('!A<G1I86P@9&ES:R!B;&]C:RP@(&ET("!IM
M<R`@9FER<W0@(')E860*("`@("`@("`@(&EN=&\@('1H92!P<FEV871E(&)U.
M9F9E<BP@=&AE;B!M;V1I9FEE9"!A8V-O<F1I;F<@=&\@=&AE($DO3PH@("`@>
M("`@("`@<F5Q=65S="P@86YD('1H96X@=W)I='1E;B!B86-K+B`@268@>6]U/
M("!W<FET92`@;6%N>2`@;&ET=&QE"B`@("`@("`@("!P:65C97,L('1H:7,@5
M(&=E=',@=F5R>2!I;F5F9FEC:65N="X@($ET(&-A;FYO="!B92!O<'1I;6EZ^
M960*("`@("`@("`@('1H;W5G:"P@<VEN8V4@('-O;65B;V1Y("!E;'-E("!MX
M87D@('=R:71E("!T;R`@=&AE("!D:7-K("!I;@H@("`@("`@("`@8F5T=V5EQ
M;BX@(`H*("`@("`@("`@("`@("`@1F]R("!C;VUP871I8FEL:71Y("!W:71HM
M("!P<F]G<F%M<R`@=&AA="`@3&]C:R@I(&$@9FEL90H@("`@("`@("`@8F5FN
M;W)E("!O<&5N:6YG("!I="P@(&%S("`@<F5C;VUM96YD960@("!I;B`@('1HI
M92`@($%M:6=A1$]3"B`@("`@("`@("!$979E;&]P97(G<R`@36%N=6%L("`H:
M<V5E($QO8VLH*2!A;F0@3W!E;B@I*2P@>6]U(&-A;B!,;V-K*"D*("`@("`@U
M("`@("=F:6QE<R<@;VX@FS-M4D1&.B";,&TN(%1H92!R97-U;'1I;F<@1FEL.
M94QO8VL@:7,@(&9A:V4L("!H;W=E=F5R+@H@("`@("`@("`@270@(&ES;B=T'
M("!U<V5F=6P@(&%T("!A;&PL("!S:6YC92`@;F\@(&9U;F-T:6]N<R`@<F5Q>
M=6ER:6YG"B`@("`@("`@("!&:6QE3&]C:W,@87)E('-U<'!O<G1E9"X@("A/7
M;FQY(%5N3&]C:R@I(&%N9"`@1'5P3&]C:R@I+"`@;V8*("`@("`@("`@(&-O#
M=7)S92DN("`@(%-O;64@('!R;V=R86US("!M87D@(&YO="`@;&EK92`@=&AE3
M("`H861M:71T961L>0H@("`@("`@("`@=6YU<W5A;"D@<VET=6%T:6]N('1H5
M870@=&AE>2!S=6-C97-S9G5L;'D@:&%V92`@82`@;&]C:R`@8G5T"B`@("`@W
M("`@("!C86YN;W0@17AA;6EN92@I(&ET+B`@*%-E92!T:&4@8G5G<R!S96-T,
M:6]N*2X@(`H*("`@("";,6U%6$%-4$Q%4R`*("`@("`@("`@()LP;5EO=2`@(
M8V%N("!U<V4@('1H92";,VU21$8Z()LP;6EN=&5R9F%C92!I;B!C;VYJ=6YC!
M=&EO;B!W:71H(&$@9FEL90H@("`@("`@("`@87)C:&EV92!P<F]G<F%M(&QI0
M:V4@6F]O+B!4:&ES(&AA<R!T:&4@(&%D=F%N=&%G92`@=&AA="`@>6]U"B`@.
M("`@("`@("!H879E(&UO<F4@969F96-T:79E('-P86-E(&]N('EO=7(@9FQO!
M<'!Y('1H86X@=VAE;B!Y;W4@=W)I=&4*("`@("`@("`@('1H92`@87)C:&EV&
M92`@;VX@=&AE(&1I<VL@=7-I;F<@=&AE($]&4R`H3VQD($9I;&EN9R!3>7-T0
M96TI+@H@("`@("`@("`@06QS;RP@86-C97-S('=I;&P@8F4@9F%S=&5R(&)E+
M8V%U<V4@=&AE<F4@(&ES("!N;R`@;F5E9"`@9F]R"B`@("`@("`@("!E>'1EE
M;G-I;VX@(&)L;V-K<R!T;R!T96QL('=H97)E(&5A8V@@8FQO8VL@;V8@=&AEF
M(&9I;&4@:7,@;VX*("`@("`@("`@(&1I<VLN("`*("`@("`@("`@($9O<B!E2
M>&%M<&QE+"!T;R!A<F-H:79E(&$@;G5M8F5R(&]F(&9I;&5S(&9R;VT@('1HZ
M92`@8W5R<F5N=`H@("`@("`@("`@9&ER96-T;W)Y('1O(&$@<F%W(&9L;W!PV
M>3H@"@H@("`@("`@("`@("`@($UO=6YT(%)$1CH*("`@("`@("`@("`@("!:4
M;V\@82!21$8Z+V4@*BYC"@H@("`@("`@("`@5&AE("`N>F]O("!E>'1E;G-I_
M;VX@('1H870@(%IO;R`@861D<R`@=&\@('1H92`@9FEL92!N86UE(&ES"B`@M
M("`@("`@("!I9VYO<F5D+"!S:6YC92!I="!I<R!N;W0@82!V86QI9"!N=6UBS
M97(N("!4:&4@+V4@(&]P=&EO;B`@:7,*("`@("`@("`@(&YE8V5S<V%R>2`@F
M<VEN8V4@(%IO;R`@:7,@(&]N92`@;V8@('1H;W-E('!R;V=R86US('1H870@<
M=7-E<PH*"B`@("`@2V]S;6]3;V9T("`@("`@("`@("`@("`@("`@("`@("`@C
M+3,M("`@("`@("`@("`@("`@("`@("`@("!296QE87-E(#$N,`H*"B`@("`@;
M4D1&*#0I("`@("`@("`@("`@("`@($%M:6=A(%!R;V=R86UM97(G<R!-86YU'
M86P@("`@("`@("`@("`@("`@(%)$1B@T*0H*"B`@("`@("`@("!3965K*"ESX
M(')E;&%T:79E('1O('1H92!E;F0@;V8@=&AE(&9I;&4N("`*("`@("`@("`@E
M($EF('EO=2!M:6=H="!L871E<B!W86YT('1O(&%D9"!S;VUE(&UO<F4@9FELE
M97,@=&\@('1H:7,@(')A=PH@("`@("`@("`@87)C:&EV92P@>6]U("!N965D.
M("!T;R`@:VYO=R`@=&AE("!E;F0M;V8M9FEL92`@;6%R:RX@("`@66]U"B`@)
M("`@("`@("!R971R:65V92!T:&ES('9A;'5E('5S:6YG(`H*("`@("`@("`@5
M("`@("!4>7!E(#P@4D1&.B]%(&]P="!H"@H@("`@("`@("`@5&AI<R!M:6=HT
M="!R97-U;'0@:6X@=&AE('9A;'5E(#!X,3=!0B!B96EN9R!D:7-P;&%Y960NM
M("!7:&5N"B`@("`@("`@("!Y;W4@;&%T97(@=V%N="!T;R!A9&0@<V]M92!MX
M;W)E(&9I;&5S+"!D;R`*"B`@("`@("`@("`@("`@6F]O(&$@4D1&.B]E,'@QH
M-T%"("HN:`H*("`@("`@("`@($YO=&4@=&AA="!T:&4@:&5X861E8VEM86P@K
M9&EG:71S($$@('1H<F]U9V@@($8@(&UU<W0@(&)E("!I;@H@("`@("`@("`@=
M=7!P97(@8V%S92X@(`H@("`@("`@("`@5&\@(&QI<W0@('1H92!C;VYT96YT[
M<R!O9B!T:&4@<F%W(&%R8VAI=F4L('EO=2!U;F9O<G1U;F%T96QY"B`@("`@(
M("`@("!C86YN;W0@=7-E(%IO;R!I='-E;&8L('-I;F-E(&ET("AF;W(@=6YKG
M;F]W;B!R96%S;VYS*2!A;'=A>7,*("`@("`@("`@(&EN<VES=',@;VX@9&]IG
M;F<@86X@($5X86UI;F4H,BDN("!4:&ES("!I<R`@82`@;F]N+7-U<'!O<G1E+
M9`H@("`@("`@("`@9G5N8W1I;VXN("`@26YS=&5A9"P@('EO=2`@;6%Y("!UO
M<V4@0F]O>BP@=&AE(&)A<F4M8F]N97,@>F]O"B`@("`@("`@("!E>'1R86-T:
M;W(O;&ES=&5R+B`@270@<V5E;7,@=&AA="!";V]Z('5S=6%L;'D@8V%N(&1E`
M=&5C="!T:&4*("`@("`@("`@(&QO9VEC86P@96YD(&]F(&%N(&%R8VAI=F4@3
M9G)O;2!I=',@8V]N=&5N=',N("`*"B`@("`@("`@("`@("`@($EF("!Y;W4@`
M(&AA=F4@(&$@(&1I<V%S<V5M8FQE<B`@('1H870@("!A8V-E<'1S("`@9FEL2
M97,*("`@("`@("`@(&-O;G1A:6YI;F<@(&UE;6]R>2`@9'5M<',L('EO=2!CZ
M86X@9&ES87-S96UB;&4@=&AE(&)O;W1B;&]C:PH@("`@("`@("`@;V8@82!D?
M:7-K.B`*"B`@("`@("`@("`@("`@1&ES07-S96UB;&4@4D1&.B]L,6L*"@H@L
M("`@()LQ;5-!35!,12!-3U5.5$Q)4U0@"B`@("`@("`@("";,&U21$8Z("`@"
M($AA;F1L97(@/2!L.E)$1BU(86YD;&5R"B`@("`@("`@("`@("`@("`@($1E[
M=FEC92`]('1R86-K9&ES:RYD979I8V4*("`@("`@("`@("`@("`@("`@56YIX
M="`](#$*("`@("`@("`@("`@("`@("`@1FQA9W,@/2`P"B`@("`@("`@("`@P
M("`@("`@(%-T86-K<VEZ92`](#0P.38*("`@("`@("`@("`@("`@("`@4')I6
M;W)I='D@/2`T"B`@("`@("`@("`@("`@("`@($=L;V)696,@(#T@+3$*("`@Y
M("`@("`@(",*"B`@("`@FS%M4$%#2T544R!355!03U)4140@"B`@("`@("`@+
M("";,&V;,VU!0U1)3TY?1DE.1%])3E!55*";,&V@H*!);7!L96UE;G1S("`@6
M("!/<&5N*"DN("`@("!$;V5S("`@("`@86X*("`@("`@("`@("`@("`@("`@5
M("`@("`@("`@("`@($]P96Y$979I8V4H*2X@(`H@("`@("`@("`@FS-M04-4>
M24].7T9)3D1?3U544%54H)LP;:"@26UP;&5M96YT<R`@("`@($]P96XH*2X@=
M("`@($1O97,@("`@(&%N"B`@("`@("`@("`@("`@("`@("`@("`@("`@("`@D
M("!/<&5N1&5V:6-E*"DN("`@("`@("!3>6YO;GEM("`@("`@("!F;W(*("`@/
M("`@("`@("`@("`@("`@("`@("`@("`@("`@($%#5$E/3E]&24Y$7TE.4%54M
M+B`@"B`@("`@("`@("";,VU!0U1)3TY?14Y$H)LP;:"@H*"@H*"@H*!);7!L1
M96UE;G1S("!#;&]S92@I+B!$;V5S(&$@0TU$7U501$%412P*("`@("`@("`@9
M("`@("`@("`@("`@("`@("`@("`@(&$@5$1?34]43U(L('1H96X@82!#;&]SV
M941E=FEC92@I+B`@"B`@("`@("`@("";,VU!0U1)3TY?4D5!1*";,&V@H*"@*
MH*"@H*!);7!L96UE;G1S(%)E860H*2X@1&]E<R!A;B!%5$1?4D5!1"X@(`H@#
M("`@("`@("`@FS-M04-424].7U=2251%H)LP;:"@H*"@H*"@26UP;&5M96YT&
M<R`@5W)I=&4H*2X@($1O97,@("AM87EB92`@(&%N"B`@("`@("`@("`@("`@W
M("`@("`@("`@("`@("`@("!%5$1?4D5!1"!A;F0@=&AE;BD@86X@151$7U=2W
M251%+B`@"B`@("`@("`@("";,VU!0U1)3TY?4T5%2Z";,&V@H*"@H*"@H*!);
M;7!L96UE;G1S(%-E96LH*2X@(`H@("`@("`@("`@FS-M04-424].7TQ/0T%41
M15]/0DI%0U2@FS!M26UP;&5M96YT<R`@3&]C:R@I+B`@06QW87ES('-U8V-E]
M961S(&EF"B`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("!M96UO<GD@.
M8V%N(&)E("!O8G1A:6YE9"`@9F]R("!A("!S=')U8W0*("`@("`@("`@("`@V
M("`@("`@("`@("`@("`@("`@($9I;&5,;V-K+B`@"B`@("`@("`@("";,VU!=
M0U1)3TY?0T]065]$25*@FS!MH*"@H*!);7!L96UE;G1S($1U<$QO8VLH*2X@<
M(`H@("`@("`@("`@FS-M04-424].7T92145?3$]#2Z";,&V@H*"@26UP;&5MH
M96YT<R!5;DQO8VLH*2X@(`H@("`@("`@("`@FS-M04-424].7T1%3$5415]/H
M0DI%0U2@FS!M26UP;&5M96YT<R`@("`@1&5L971E1FEL92@I+B`@("`@06QW4
M87ES"B`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("!S=6-C965D<RX@4
M($1O97,@;F]T:&EN9RX@(`H@("`@("`@("`@FS-M04-424].7T1)1:";,&V@<
MH*"@H*"@H*"@56YL;V%D<R!T:&4@:&%N9&QE<B!F<F]M("!M96UO<GD@(&%F)
M=&5R"@H*("`@("!+;W-M;U-O9G0@("`@("`@("`@("`@("`@("`@("`@("`M;
M-"T@("`@("`@("`@("`@("`@("`@("`@(%)E;&5A<V4@,2XP"@H*("`@("!2!
M1$8H-"D@("`@("`@("`@("`@("`@06UI9V$@4')O9W)A;6UE<B=S($UA;G5A6
M;"`@("`@("`@("`@("`@("`@4D1&*#0I"@H*("`@("`@("`@("`@("`@("`@+
M("`@("`@("`@("`@(&%L;"!F:6QE<R!H879E(&)E96X@8VQO<V5D+B`@"B`@<
M("`@("`@("";,VU!0U1)3TY?4D5.04U%7T1)4TN@FS!MH*!3>6YO;GEM("!F5
M;W(@($%#5$E/3E]$244N("!9;W4@(&-A;B!U<V4*("`@("`@("`@("`@("`@$
M("`@("`@("`@("`@("`@("=296QA8F5L("!21$8Z("!X>'@G("!T;R`@('5NI
M;&]A9"`@('1H90H@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@:&%NB
M9&QE<B!F<F]M(&UE;6]R>2X@(`H*("`@("";,6U$24%'3D]35$E#4R`*("`@1
M("`@("`@()LP;5!L96YT>2`@=VAE;B`@8V]M<&EL960@('=I=&@@(&1E8G5G6
M9VEN9R`@96YA8FQE9"P@(&]T:&5R=VES90H@("`@("`@("`@;F]N92X@(`H*R
M("`@("";,6U215154DX@0T]$15,@"B`@("`@("`@("";,&U/8G1A:6YE9"!VE
M:6$@26]%<G(H*2X@(`H@("`@("`@("`@FS-M15)23U)?4D5!1%]04D]414-44
M142@FS!M;W*@FS-M15)23U)?5U))5$5?4%)/5$5#5$5$H)LP;7=H96X@82!RW
M96%D(&]R"B`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(&$@=W)IH
M=&4@97)R;W(@:7,@9&5T96-T960N("!.;R`@;W1H97(*("`@("`@("`@("`@8
M("`@("`@("`@("`@("`@("`@("`@97)R;W(@8V]D92!S965M<R!T;R!C;VUE)
M(&-L;W-E+B`@"B`@("`@("`@("";,VU%4E)/4E]$25-+7T953$R@FS!MH*"@'
MH*"@H'=H96X@(&%N("!A='1E;7!T("!I<R`@;6%D92`@=&\@=W)I=&4*("`@+
M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@8F5Y;VYD('1H92!I;F1IF
M8V%T960@<&AY<VEC86P@(&1E=FEC90H@("`@("`@("`@("`@("`@("`@("`@X
M("`@("`@("`@("!L:6UI="X@(`H@("`@("`@("`@FS-M15)23U)?4T5%2U]%G
M4E)/4J";,&V@H*"@H*!F;W(@:6YV86QI9"!3965K*"ES+B`@"B`@("`@("`@/
M("";,VU%4E)/4E].3U]&4D5%7U-43U)%H)LP;:"@H&%T('-T87)T=7`@:68@]
M8G5F9F5R(&UE;6]R>2!C86YN;W0@8F4*("`@("`@("`@("`@("`@("`@("`@G
M("`@("`@("`@("`@86QL;V-A=&5D+"!O<B!W:&5N('1H97)E(&ES(&YO(&UE+
M;6]R>0H@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("!F;W(@82!&?
M:6QE3&]C:RP@86X@24]%>'141"P@971C+B`@"B`@("`@("`@("";,VU%4E)/2
M4E]!0U1)3TY?3D]47TM.3U=.H)LP;69O<B!U;FMN;W=N('!A8VME=',N("`*]
M"B`@("`@FS%M0E5'4R`*("`@("`@("`@()LP;41O:6YG("!M=6QT:7!L92`@3
M<W5C8V5S<VEV92`@5W)I=&4H*7,@;V8@82!F97<@8GET97,@:7,@=F5R>0H@W
M("`@("`@("`@:6YE9F9I8VEE;G0N("!4:&4@<V%M92!I<R!T<G5E(&9O<B!2N
M96%D*"DL('1H;W5G:"`@;&5S<R`@<V\N"B`@("`@("`@("!4:&ES("!I<R`@;
M8F5C875S92`@86QL("!D979I8V4@($DO3R`@9V]E<R`@=&AR;W5G:"`@=&AEX
M('-A;64*("`@("`@("`@(&)U9F9E<BX@(`H@("`@("`@("`@3F]T(')E86QLC
M>2!A(&)U9R!O9B";,VU21$8Z()LP;6)U="!A;FYO>6EN9R`@86YY=V%Y.B`@W
M57-I;F<@("A!<G`I"B`@("`@("`@("!465!%("!21$8Z("!/4%0@($@L("!47
M>7!E("!,;V-K*"ES("!T:&4@(&9I;&4L('1H96X@=V%N=',@=&\*("`@("`@1
M("`@($5X86UI;F4H*2!I="P@<')E<W5M86)L>2!T;R!S964@:68@:70@:7,@-
M(&YO="`@82`@9&ER96-T;W)Y+`H@("`@("`@("`@8G5T('1H870@(&ES("!N#
M;W0@(&$@<W5P<&]R=&5D(&9U;F-T:6]N+B`@5&AE;B!I="!F;W)G971S('1OG
M"B`@("`@("`@("!5;DQO8VLH*2!T:&4@(&QO8VL@(&%G86EN+"`@=VAI8V@@0
M('=A<W1E<R`@<V]M92`@;65M;W)Y("!A;F0*("`@("`@("`@('!R;VAI8FETB
M<R`@=&AE("!H86YD;&5R("!F<F]M("!B96EN9R`@=6YL;V%D960@(&9R;VT@K
M;65M;W)Y+@H@("`@("`@("`@0F5W87)E(&]F(&]T:&5R('!R;V=R86US('1HE
M870@86-T('5N<&]L:71E('=H96X@9F%C960@=VET:"!A"B`@("`@("`@("!&/
M:6QE3&]C:R!T:&%T('1H97D@8V%N;F]T($5X86UI;F4H*2X@(`H@("`@("`@A
M("`@5&AE(&UO=&]R(&]F('1H92!D<FEV92!S:&]U;&0@<&5R:6]D:6-A;&QYR
M(&)E('1U<FYE9"!O9F8N("`*("`@("`@("`@($UO<F4@('1I;64@('=A<R`@Y
M('-P96YT("`@<')O;V9R96%D:6YG("`@=&AE("`@;6%N=6%L("`@=&AA;@H@>
M("`@("`@("`@<')O;V9R96%D:6YG('1H92!P<F]G<F%M+B`@"@H@("`@()LQ'
M;5-%12!!3%-/(`H@("`@("`@("`@FS!M6F]O*#$I+"`@0F]O>B@Q*2P@($%R<
M8R@Q*2P@('1A<B@Q*2P@(&%R*#$I+"!T<F%C:V1I<VLN9&5V:6-E"B`@("`@O
M("`@("`H4F]M("!+97)N86P@(%)E9F5R96YC92`@36%N=6%L.B`@3&EB<F%R6
M:65S("`@86YD("`@1&5V:6-E<RP*("`@("`@("`@($%U=&]D;V-S*2P@("!!E
M;6EG841/4R`@(&UA;G5A;"P@("!-871T97<@("!$:6QL;VXG<R`@(%!)4$4Z$
M+`H@("`@("`@("`@8V]M<"YS;W5R8V5S+FUA='0M9&EL;&]N(&EN(&=E;F5R2
M86PN("`*"@H*"@H*"@H*"@H*"@H*("`@("!+;W-M;U-O9G0@("`@("`@("`@@
M("`@("`@("`@("`@("`M-2T@("`@("`@("`@("`@("`@("`@("`@(%)E;&5A8
(<V4@,2XP"@H@[
``
end
size 15983
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.