page%swap@Sun.COM (Bob Page) (05/09/89)
Submitted-by: jc3b21!fgd3@uunet.UU.NET (Fabbian G. Dufoe) Posting-number: Volume 89, Issue 117 Archive-name: kernel/memdiag.1 The memory diagnostic program (MD) identifies addresses which cause memory errors. The memory quarantine program (MQ) removes defective addresses from the system's memory free list. # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # ReadMe # MD.doc # MQ.doc # Memory.doc # AddAddr.c # MD.c # MQ.c # MD.uu # MQ.uu # This is archive 1 of a 1-part kit. # This archive created: Mon May 8 11:35:21 1989 echo "extracting ReadMe" sed 's/^X//' << \SHAR_EOF > ReadMe X This archive contains source code, executables, and documentation for XMD, a memory diagnostic program, and MQ, a program to quarantine defective Xmemory locations. Both programs are public domain. When you unpack the Xarchive you should have the following files: X X ReadMe--This file X AddAddr.c--Source for a function used in MD X Makefile--input for Lattice lmk to compile and link MD and MQ X MD*--Executable memory diagnostic program X MD.c--Source for memory diagnostic X MD.doc--Documentation for memory diagnostic X MD.uue*--Uuencoded executable memory diagnostic program X Memory.doc--Background information on the Amiga's memory management X MQ*--Executable memory quarantine program X MQ.c--Source for memory quarantine X MQ.doc--Documentation for memory quarantine X MQ.uue*--Uuencoded executable memory quarantine X X*Archives will contain either the executable programs or the uuencoded X executables, but not both. X X MD will run with any Amiga configuration but requires a stack size of X10000. It does not take over the machine but it does soak up any available Xmemory while it is running. It takes about 8 minutes to test a 2.5MB Xmachine. X X MQ will run with any Amiga configuration and a stack size as small as X4000. It suspends multi-tasking during its execution but only requires Xabout one second to run. SHAR_EOF echo "extracting MD.doc" sed 's/^X//' << \SHAR_EOF > MD.doc XMD--Memory Diagnostic X XSYNOPSIS: (CLI environment) X X stack 10000 X MD [>reportfile] [-qaddressfile] X X XDESCRIPTION: X X MD is a memory diagnostic program. It tests your system's memory and Xreports any addresses where errors occur. A memory error occurs when the Xvalue read from an address is not the value which was stored there. X X MD runs from the Command Line Interface (CLI). It requires a stack Xsize of 10000 bytes. It writes its report to standard output. It also Xsends status messages to standard error. If you want to save the report for Xlater review (and separate it from the status messages) redirect standard Xoutput to a file (for example, "MD >MD.rpt"). X X XCOMMAND LINE OPTIONS: X X The "-q" option builds a file of bad addresses for use by MQ, the Xmemory quarantine program. Specify the filename to which you want the Xaddresses written immediately after the q without a space. The file will Xcontain a list of addresses where MD found an error. X X If you suspect intermittent memory problems you should run MD Xrepeatedly, saving the output to different files. By comparing several Xreports you can identify addresses which fail occasionally. The quarantine Xfiles MD produces are ASCII characters so you can edit them as necessary to Xbuild a complete list of defective addresses. X X MD tests memory by comparing values read from an address with a known Xvalue previously written to that address. It does not interfere with other Xtasks in the system (except by soaking up memory which they might need). It Xsends its report to standard output so it can be redirected to a disk file Xor printer. X X XINPUT: X X MD does not read external data. X X XOUTPUT: X X The diagnostic report begins with a header identifying the program, Xauthor, and version, and the time of the test. Next it lists the blocks of Xmemory it examined. The listing gives the block's number, address (in Xhexadecimal notation), and size (in decimal). Errors are listed as they are Xencountered, one to a line. The line identifies the address where the error Xoccurred, the value found at that address, and the value MD expected to Xfind. All values are hexadecimal. For example: X X ERROR! Address: 21646C found: 20 expected: 0 X XAt the end of the report MD records the number of errors it found. X X As MD executes it displays status messages. The messages advise the Xuser MD is allocating blocks, sorting them, initializing blocks, and testing Xthem. They identify the block number and its size as well as the value used Xto initialize or test it. X X If the -q option is specified on the command line MD will list all the Xaddresses where memory errors occurred to the specified file. The addresses Xare expressed as ASCII characters representing hexadecimal values. Each Xaddress is on a separate line. The addresses are sorted in ascending order Xand there are no duplicates. X X XEXECUTION: X X MD takes about 8 minutes to test a 2.5MB machine. During that time Xthere will not be enough memory left to run other jobs. When MD finishes, Xhowever, it will release all the memory it used and other jobs can resume Xwithout rebooting. MD will not interfere with other jobs that are executing Xwhen it is invoked but it is possible to create a deadlock if there are Xother active jobs in the system. Besides that, MD cannot test memory that Xis allocated to another process. Consequently, it is best to run MD Ximmediately after booting the system. X X The recommended way to run MD is to create a special Workbench boot Xdisk with at least 200 free blocks. Deleting the Utilities directory will Xfree that much space from a standard Workbench disk. Copy MD to the disk. XChange the Startup-Sequence file in the s directory to set the stack size to X10000. After booting with this disk use the date command to set the date Xand time if necessary. Then you can execute MD as many times as you wish, Xdirecting the output to a different file each time. By examining the Xreports you can identify the addresses where memory errors occurred. X X XPROGRAM LOGIC: X X MD is quite simple. It allocates all the memory the system will give Xit. Then it writes a value into each address. It compares the value it Xreads back with the one it wrote and if they're different it records the Xerror. X X The algorithm for allocating memory is straightforward. MD begins by Xrequesting a 1MB block of memory. Each time its request is successful it Xrepeats it. When the request fails MD cuts its block size in half and tries Xagain. The iteration ends when MD can't get any 1-byte blocks. X X MD sorts the blocks into ascending order so the report it produces will Xbe a little easier to follow. That's purely a cosmetic feature to make the Xuser more comfortable. (Remember, I was the user for whom it was written Xand ordered lists make more sense to me.) X X MD tests memory with four values. They are 0, 0xff, 0x55, and 0xaa. XThe test begins by initializing all the bytes in each block to 0. Next the Xcontents of each byte are compared to 0. If the values don't match MD Xreports the error. It stores the next test value at that address and moves Xon. When all the memory has been checked for the first value and loaded Xwith the next value MD makes a second pass through all the memory. A third Xpass checks for 0x55 and loads 0xaa. The final pass looks for 0xaa in each Xbyte. X X At first glance it seems less efficient to make so many passes through Xmemory. Why not test all four values at each byte before moving on to the Xnext address? There are two reasons. Had the program been written Xsomething like this: X X char *address; X for (address = start; address < end; address++) X { X *address = 0; X if (*address != 0) X printf("ERROR! ..."); X *address = 0xff; X if (*address != 0xff) X printf("ERROR! ..."); X } X Xthe compiler might outsmart you. It could see that nothing is done with X*address so it might keep it in a register to speed up the program. It Xwould be fast, all right, but it wouldn't tell you anything. X X The second reason is to allow time for memory errors to occur. The Xapproach I used reduces the possibility that an address might hold the Xcorrect value briefly but lose it after some time has passed. I don't know Xhow probable that is. It seemed a good idea to prevent it anyway. X X After all the blocks have been tested MD returns them to the system's Xmemory free list. X X Send questions, comments, or bug reports to: X X--Fabbian Dufoe X 350 Ling-A-Mor Terrace South X St. Petersburg, Florida 33705 X 813-823-2350 X XUUCP: ...uunet!pdn!jc3b21!fgd3 SHAR_EOF echo "extracting MQ.doc" sed 's/^X//' << \SHAR_EOF > MQ.doc XMQ--Memory Quarantine X X XSYNOPSIS: (CLI environment) X X MQ [<addressfile] [>statusfile] X X XDESCRIPTION: X X MQ makes addresses which cause memory errors unavailable to the system. XIt works by removing those memory locations from the system's memory free Xlist so they appear to be allocated to another process. MQ is intended as a Xtemporary fix for memory failures until you can replace the defective RAM Xchips. X X MQ runs from the Command Line Interface (CLI). It reads data from Xstandard input and writes a status message to standard output. X X XCOMMAND LINE OPTIONS: X X MQ does not recognize any command line options. X X XINPUT: X X MQ reads a list of addresses to be quarantined from standard input. XThe addresses must be in ascending order and expressed as ASCII characters Xrepresenting hexadecimal values. There can be a maximum of 100 addresses. XMQ will ignore any addresses beyond the first 100. If necessary additional Xaddresses can be quarantined by running MQ again with a different list. XMQ's companion program, MD (a memory diagnostic), can produce a file for Xdirect input to MQ. X X XOUTPUT: X X When MQ finishes it writes a status message to standard output. The Xmessage tells the number of bytes that were quarantined. X X XEXECUTION: X X MQ's execution time is usually less than the time required to load the Xprogram. The entire process takes about a second. X X The recommended way to use MQ is to put it in your Startup-Sequence Xfile. It should appear in the Startup-Sequence as early as possible. MQ Xwill fragment memory so certain applications may have to be run before you Xcan run MQ. For example, if you want a recoverable RAM disk (RAD:) you must Xhave 880K of contiguous memory available. If MQ doesn't leave you with that Xlarge a block you can run MQ after you create your RAD: disk. You will have Xdefective memory in the RAD: disk but if it is in a location that isn't Xaccessed it will be harmless. X X Use MD to create a file of defective memory locations. Then copy that Xfile to your Workbench disk. Add a line to your Startup-Sequence file Xinvoking MQ with standard input redirected from the address list file. Then Xeach time you boot your system the defective memory locations will be Xquarantined. X X XPROGRAM LOGIC: X X MQ searches the system's memory free list to find each chunk of free Xmemory which contains one or more of the bad addresses it reads from Xstandard input. It modifies the memory free list so the bad addresses will Xbe excluded. The smallest block of memory that can be allocated is eight Xbytes. Thus the memory free list loses eight bytes for each bad address Xthat is quarantined. MQ does not keep track of the quarantined memory so Xthere is no way to recover it without rebooting the system. X X As MQ examines each block of memory it goes through its list of bad Xaddresses. If the block ends before the bad address MQ goes on to the next Xblock. If the block starts after the bad address MQ gets the next address. XIf the bad address falls within the block MQ resizes the block to exclude Xit. X X Each block of memory is described by a MemChunk structure which Xcontains a pointer to the next block and the size of the current block. The Xstructure is defined in exec/memory.h as follows: X X/****** MemChunk ****************************************************/ X Xstruct MemChunk X{ X struct MemChunk *mc_Next; /* pointer to next chunk */ X ULONG mc_Bytes; /* chunk byte size */ X}; X X MQ calculates the number of bytes between the start of the block and Xthe bad address, then rounds it down to a multiple of 8. That will be the Xnew size of the block. Let's call it Size1. Then it adds that size plus 8 Xto the beginning address of the block to get the starting address of a new Xblock. We'll call it NewChunk. To calculate the size of the new block MQ Xadds 8 to Size1 and subtracts the result from the original block size. We'll Xcall it Size2. X X Because the original block may be as small as 8 bytes and because the Xbad address may be within 8 bytes of either end of the block Size1 and Size2 Xmay be zero. If Size2 is zero MQ simply reduces the size of the original Xblock by storing Size1 in the original block's mc_Bytes field. Otherwise it Xcreates a new block at NewChunk. X X Each block of memory contains a pointer to the next block (mc_Next) and Xthe size of the current block (mc_Bytes). So MQ takes the next block Xpointer from the original block and puts it at NewChunk->mc_Next. Then it Xputs Size2 at NewChunk->mc_Bytes. X X If Size1 is zero MQ copies the address from the original block's Xmc_Next field to the mc_Next field of the previous block. If the previous Xblock pointer is NULL the original block is the first one in the list. In Xthat case MQ copies the mc_Next field from the original block to the Xmh_First field in the MemHeader structure. X X Send questions, comments, or bug reports to: X X--Fabbian Dufoe X 350 Ling-A-Mor Terrace South X St. Petersburg, Florida 33705 X 813-823-2350 X XUUCP: ...uunet!pdn!jc3b21!fgd3 SHAR_EOF echo "extracting Memory.doc" sed 's/^X//' << \SHAR_EOF > Memory.doc XMemory Management on the Amiga X by Fabbian G. Dufoe, III X X Because AmigaDOS is a multi-tasking operating system it requires a more Xcomplicated memory management scheme than most personal computer operating Xsystems have. Single-tasking systems can get by with setting the upper and Xlower limits of the free memory region. With different processes starting Xand stopping independently free memory gets fragmented. The system has to Xknow where to find each fragment if it's to use memory efficiently. X X AmigaDOS keeps a list of available memory. When a process needs RAM it Xasks the operating system to allocate some. The system searches the memory Xfree list to see if there is a big enough block available. If so it Xallocates it to the process and removes it from the memory free list. When Xthe process frees the memory the system returns it to the memory free list. XThe operating system doesn't keep track of which process allocated the Xmemory, so if a process fails to return it there is no way to recover it Xwithout rebooting the system. X X Like everything in the Amiga's operating system, the path to the memory Xfree list begins with a pointer to the exec library ExecBase structure. The XExecBase structure and all the structures and lists the system uses for Xmemory management are defined in the include files listed in the ROM Kernel XExec Manual. These same files are supplied with your C compiler or Xassembler. They are also available in the Native Developer's Kit available X>from Commodore Amiga Technical Support (CATS). X X Opening the exec library returns a pointer to the ExecBase structure: X X struct ExecBase *ExecBase; X ExecBase = (struct ExecBase *)OpenLibrary("exec.library, 0L); X X The ExecBase structure is defined in exec/execbase.h. One of the Xfields in the ExecBase structure is MemList. It's a List structure that Xcontains pointers to the list of memory regions which make up the memory Xfree list. There is a MemList structure documented in the ROM Kernel Manual Xand in exec/memory.h. It is not related to the List structure named MemList Xin the ExecBase structure. The similar names could easily confuse you. X X Exec/lists.h defines a List structure as follows: X X struct List { X struct Node *lh_Head; X struct Node *lh_Tail; X struct Node *lh_TailPred; X UBYTE lh_Type; X UBYTE l_pad; X }; X XThe Node structure is defined in exec/nodes.h as follows: X X struct Node { X struct Node *ln_Succ; X struct Node *ln_Pred; X UBYTE ln_Type; X BYTE ln_Pri; X char *ln_Name; X }; X X The memory free list is organized as a list of lists. MemList points Xto a list of memory regions. A region is a block of contiguous memory from Xwhich Exec can draw memory. Each region is described by a MemHeader Xstructure. When the system is initialized it creates a region for chip RAM Xand one for each expansion RAM board in the system. X X If the expansion RAM boards occupy contiguous memory you can combine Xtheir regions into one with a program called MergeMem. MergeMem is in the XSystem directory of the 1.3 Workbench disk. X X The MemHeader structure is documented in exec/memory.h as follows: X X struct MemHeader { X struct Node mh_Node; X UWORD mh_Attributes; /* characteristics of this region */ X struct MemChunk *mh_First; /* first free region */ X APTR mh_Lower; /* lower memory bound */ X APTR mh_Upper; /* upper memory bound+1 */ X ULONG mh_Free; /* total number of free bytes */ X }; X X So the following gives the address of the first region in the memory Xfree list: X X struct MemHeader *MemHeader; X MemHeader = (struct MemHeader *)ExecBase->MemList.lh_Head; X X The MemHeader structure begins with a Node structure (mh_Node) which Xlinks this region to the others in the system's memory free list. Within Xthe Node structure mh_Node.ln_Succ points to the next region and Xmh_Node.ln_Pred points to the preceding one. In the first node in the list Xmh_Node.ln_Pred points to the head of the list (MemHeader == MemHeader- X>mh_Node.ln_Pred). X X The MemHeader structure defines the upper (mh_Upper) and lower limits X(mh_Lower) of the region and tells how many bytes it currently has available X(mh_Free). It contains a pointer to the first chunk of free memory X(mh_First). X X Memory chunks are organized as a singly linked list. The NewChunk Xstructure (documented in exec/memory.h) contains the address of the next Xchunk in mc_Next and the number of bytes in this chunk in mc_Bytes: X X struct MemChunk { X struct MemChunk *mc_Next; /* pointer to next chunk */ X ULONG mc_Bytes; /* chunk byte size */ X }; X XA NULL pointer in mc_Next marks the end of the list. X X Before any memory is allocated from a region there will be just one Xchunk in the list. The fields mh_First and mh_Lower will be equal and Xmh_Upper will be the same as mh_Free. The smallest amount of memory that Xcan be allocated is eight bytes. That's because the smallest chunk of Xmemory that can be replaced on the memory free list is eight bytes. A XMemChunk requires four bytes for mc_Next (a 32-bit address) and four bytes Xfor mc_Bytes (an unsigned long integer). X X When the first block of memory is allocated from a region the size of Xthe block is added to mh_First and mh_Free is reduced by the size of the Xblock. In the MemChunk structure mc_Next remains NULL and mc_Bytes is Xreduced by the amount of memory allocated. X X If a second block is allocated from the same region the size of the Xsecond block will be added to mh_First and subtracted from mh_Free and Xmc_Bytes. There will still be just one chunk in the list, although it will Xbe smaller. X X The first fragmentation of the region occurs when the first block is Xfreed while the second remains allocated. Then mh_First will be restored to Xits original value (equal to mh_Lower) and mh_Free will be increased by the Xsize of the block. The address pointed to by mh_First (which is mc_Next) Xwill be loaded with the previous value of mh_First. The size of the block Xwill be loaded into mc_Bytes for the first MemChunk structure. X X Given Block1 as the size of the first block and Block2 as the size of Xthe second block, the following relationships will be true after the first Xblock is freed: X X mh_First == mh_Lower X mh_Upper == mh_Free + Block2 X &mc_Next == mh_First X mc_Next == &mc_Next + Block1 + Block2 X mc_Bytes == Block1 X mc_Next->mc_Next == NULL X mc_Next->mc_Bytes == mh_Free - (Block1 + Block2) X XWhen the last block is freed mh_Free will equal the difference between Xmh_Upper and mh_Lower, mc_Next will be set to NULL, and mc_Bytes will be the Xsame as mh_Free. In other words, the region will be restored to its Xoriginal configuration with a single chunk that contains all the memory in Xthe region. X X Chapter 6 of the Rom Kernel Manual: Exec describes the memory Xallocation routines Exec provides for programmers. There are three pairs of Xroutines. AllocMem() and FreeMem() use the system's memory free list to Xmanage one block per call. AllocEntry() and FreeEntry() process multiple Xblocks with a single call. Allocate() and Deallocate() allow you to manage Xblocks from a private memory free list. SHAR_EOF echo "extracting AddAddr.c" sed 's/^X//' << \SHAR_EOF > AddAddr.c Xvoid XAddAddr(address) Xunsigned char *address; X{ X extern unsigned char *Addr[]; X extern short int AddrCnt; X int i; X X /* If it's the first address we just add it. */ X if (AddrCnt == 0) X Addr[AddrCnt++] = address; X else X { X /* If there are already 100 addresses we can't process any more so X we'll just return. */ X if (AddrCnt == 100) X return; X X /* We'll compare the new address against each one in the list until we X find the appropriate place to insert it. */ X for (i = 0; i < AddrCnt; i++) X { X /* If the new address is smaller than the current address in the X array we'll insert the new one at this position. */ X if (address < Addr[i]) X { X /* We need a temporary loop counter so we can move all the array X entries from the current one to the end down one position to X make room for the new address. */ X int j; X X for (j = AddrCnt; j > i; j--) X Addr[j] = Addr[j-1]; X Addr[i] = address; X AddrCnt++; X break; X } X X /* If the address is already in the list we'll skip it. */ X if (address == Addr[i]) X break; X } X X /* If the new address is higher than the last one on the list we'll X add it to the end of the array. */ X if (address > Addr[AddrCnt-1]) X Addr[AddrCnt++] = address; X X return; X } X} X SHAR_EOF echo "extracting MD.c" sed 's/^X//' << \SHAR_EOF > MD.c X/* MD.c X X by Fabbian G. Dufoe, III X X This is a public domain program. Use it however you like. X X This program tests all the memory which the operating system will X allocate to it. It writes a test value to each address. Then it reads X each address and compares the result with the test value. If the value X read from memory doesn't match the test value the program writes the X address (the pointer value), the expected contents, and the actual X contents of the memory location to standard output. When all allocated X memory has been tested against one test value the program moves to the X next one. The test values are 0x00, 0xff, 0x55, and 0xaa. X X A command line option directs the program to write a list of bad X addresses to a file. The file will contain all the addresses at which an X error was detected. The addresses will be listed in ascending order and X each address will appear only once. Addresses will be separated by X newlines. The addresses will be ASCII characters representing X hexadecimal values. The program will not list more than 100 addresses. X X While the program is running it writes status messages to standard error. X X Usage: MD [>reportfile] [-qaddressfile] X*/ X X#define NULL 0L X#define SIZE 1000 X#define VERSION "Version 1.1, 10 April 1989\n\n" X#define USAGE "Usage: MD [>reportfile] [-qaddressfile]\n" X X#include <time.h> X#include <stdio.h> X Xtypedef struct X{ X unsigned char *ptr; X unsigned long int size; X} Block; X Xunsigned char *Addr[100]; Xunsigned short int AddrCnt = 0; X Xvoid Xmain(argc, argv) Xint argc; Xchar **argv; X{ X void AddAddr(unsigned char *); X FILE *AddrFile; X unsigned short int AddrList = 0; X Block block[SIZE]; X unsigned short int count = 0; X unsigned long int errct = 0; X unsigned short int high; X unsigned short int i; X unsigned long int offset; X unsigned char *ptr; X unsigned long int size; X signed long int t; X static unsigned char TestVal[] = {0, 0xff, 0x55, 0xaa}; X unsigned short int val; X X /* We need to check for command line arguments. A "-q" directs the X program to write a file of bad addresses. */ X if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'q') X { X /* If we can't open the file we'll terminate the program with an error X message. */ X if ((AddrFile = fopen(&argv[1][2], "w")) == NULL) X { X fputs(USAGE, stderr); X fputs("Cannot open output file.\n", stderr); X exit(30); X } X AddrList = 1; X } X else if (argc > 1) X { X /* If the command line arguments were incorrect we'll terminate the X program with a usage message. */ X fputs(USAGE, stderr); X exit(30); X } X X /* We want to include the time the diagnostic program was run in the X report. That requires getting the current system time. X */ X time(&t); X X /* We'll print a report heading and copyright notice at the beginning. X */ X printf("MD--Memory Diagnostic.\n"); X printf("by Fabbian G. Dufoe, III\n"); X printf(VERSION); X printf("Memory tested %s\n\n", ctime(&t)); X X /* We'll start by allocating memory in blocks of one megabyte. The plan X is to allocate as many one-megabyte blocks as we can. Then we'll X halve the block size, allocate as many blocks of that size as we can, X and repeat the process until (a) all the memory is gone or (b) we've X filled the array we allocated for keeping track of memory blocks. X */ X size = 1048576; X while (size > 0 && count < SIZE) X { X fprintf(stderr, "Allocating %ld byte blocks.\n", size); X while ((ptr = (unsigned char *)malloc(size)) != NULL) X { X block[count].ptr = ptr; X block[count++].size = size; X } X if (size == 1) X size = 0; X else X size >>= 1; X } X X /* Because we expect seldom to use the entire array we've set aside we X need to save the number of the highest element actually used. X */ X high = count; X X /* At this point we want to sort the block pointers. It makes the output X easier to follow if memory errors are reported in ascending order X by their address. We aren't guaranteed that memory will be X allocated in any particular order. We'll use an insertion sort and X we'll sort only that part of the array we used. That means we'll X keep the index values between 0 and high. X X An insertion sort works by shifting all the items left of the current X one right one position until an item is less than the current one. X Imagine the items to be sorted are laid out from left to right. Then X the sort places the current item in the position vacated by the last X item to be shifted right. The sort starts with the second item as X the current one and proceeds to the right until all the items have had X a turn as the current one. X */ X fprintf(stderr, "Sorting block list.\n"); X for (count = 1; count < high; count++) X { X short int i; X X ptr = block[count].ptr; X size = block[count].size; X i = count - 1; X while (i >=0 && ptr < block[i].ptr) X { X block[i+1].ptr = block[i].ptr; X block[i+1].size = block[i].size; X i--; X } X block[i+1].ptr = ptr; X block[i+1].size = size; X } X fprintf(stderr, "Sort complete.\n"); X X /* We'll list the block addresses and size in the report. X */ X printf("Blocks examined:\n"); X printf("Block # Address Size\n\n"); X for (count = 0; count < high; count++) X { X printf("%4d %8lX %7ld\n", count, block[count].ptr, X block[count].size); X } X printf("\n"); X X /* Now that we've sorted our list of blocks we're ready to start testing X them. The first step is to initialize all the variables to 0, the X first test value. X */ X for (count = 0; count < high; count++) X { X fprintf(stderr, "Initializing block %d, %ld bytes.\n", count, X block[count].size); X for (offset = 0; offset < block[count].size; offset++) X *(block[count].ptr+offset) = TestVal[0]; X } X X /* Next we'll go through all the blocks to see if they contain the test X value with which they were loaded. If not we'll identify the address X that failed, the value it contained, and the value it should have X contained. We'll do that for each valid test value. X */ X for (val = 1; val < 4; val++) X { X fprintf(stderr, "Testing value %X.\n", TestVal[val-1]); X for (count = 0; count < high; count++) X { X fprintf(stderr, "Testing block %d, %ld bytes with %X\n", count, X block[count].size, TestVal[val-1]); X for (offset = 0; offset < block[count].size; offset++) X { X if (*(block[count].ptr+offset) != TestVal[val-1]) X { X printf("ERROR! Address: %8lX found: %2X expected: %2X\n", X block[count].ptr+offset, *(block[count].ptr+offset), X TestVal[val-1]); X errct++; X AddAddr(block[count].ptr+offset); X } X *(block[count].ptr+offset) = TestVal[val]; X } X } X } X X /* We've tested for all values except the last one. It's time to do that X now. X */ X val--; X fprintf(stderr, "Testing value %X.\n", TestVal[val]); X for (count = 0; count < high; count++) X { X fprintf(stderr, "Testing block %d, %ld bytes with %X\n", count, X block[count].size, TestVal[val]); X for (offset = 0; offset < block[count].size; offset++) X { X if (*(block[count].ptr+offset) != TestVal[val]) X { X printf("ERROR! Address: %8lX found: %2X expected: %2X\n", X block[count].ptr+offset, *(block[count].ptr+offset), X TestVal[val]); X errct++; X AddAddr(block[count].ptr+offset); X } X } X } X X /* The testing is finished so we'll report the number of errors we found. X */ X printf("\nMD found %d errors.\n", errct); X X /* When we've completed all our tests we free all the memory we allocated X and exit. */ X for (count = 0; count < high; count++) X { X fprintf(stderr, "Freeing block %d.\n", count); X free(block[count].ptr); X } X X /* If an address list file was requested we'll write it and close the X file. */ X if (AddrList == 1) X { X for (i = 0; i < AddrCnt; i++) X fprintf(AddrFile, "%8lX\n", Addr[i]); X fclose(AddrFile); X } X X exit(0); X} SHAR_EOF echo "extracting MQ.c" sed 's/^X//' << \SHAR_EOF > MQ.c X/* MQ.c Memory Quarantine X X by Fabbian G. Dufoe, III X X This program walks the memory free list. If it finds memory on the free X list which has been identified as defective by MD (Memory Diagnostic) it X patches the memory free list so that memory will appear to be already X allocated. The memory cannot be recovered until the system is restarted. X X The program begins by getting a pointer to the system's memory free list. X For each entry in the list it compares the starting and ending addresses X of the free memory block against the addresses of the defective memory. X If a defective memory address falls within the free block MQ changes the X entry for the free block so the free block will appear to end just short X of the defective address. Then it adds a new entry to the list. The new X entry identifies a free block beginning just after the defective address X and continuing to the point where the original block ended. This process X is repeated for each defective address and for each free block. X*/ X X#include <stdio.h> X#include <exec/types.h> X#include <exec/exec.h> X#include <exec/execbase.h> X Xstruct ExecBase *ExecBase; X Xvoid Xmain() X{ X ULONG BadAddr[100]; X int bytes = 0; X int i; X int last = 0; X struct MemChunk *LastChunk = NULL; X struct MemChunk *MemChunk; X struct MemHeader *MemHeader; X X while ((scanf("%8lX\n", &BadAddr[last++]) != EOF) && (last < 100)); X last--; X X if ((ExecBase = (struct ExecBase *) X OpenLibrary("exec.library", 0L)) == NULL) X exit(20); X X Forbid(); X MemHeader = (struct MemHeader *)ExecBase->MemList.lh_Head; X X while(MemHeader->mh_Node.ln_Succ) X { X for (MemChunk = MemHeader->mh_First; MemChunk; X MemChunk = MemChunk->mc_Next) X { X for (i = 0; i < last; i++) X { X struct MemChunk *NewChunk; X ULONG Size1; X ULONG Size2; X X /* If chunk ends before bad address get next chunk. */ X if ((ULONG)MemChunk + MemChunk->mc_Bytes - 1 < BadAddr[i]) X break; X /* If chunk begins after bad address get next address. */ X if ((ULONG)MemChunk > BadAddr[i]) X continue; X /* Bad address falls within chunk. */ X Size1 = BadAddr[i] - (ULONG)MemChunk; X Size1 = Size1 - Size1 % 8; X Size2 = MemChunk->mc_Bytes - Size1 - 8; X NewChunk = (struct MemChunk *)((ULONG)MemChunk + Size1 + 8); X if (Size2 == 0) X MemChunk->mc_Bytes = Size1; X else X { X NewChunk->mc_Next = MemChunk->mc_Next; X NewChunk->mc_Bytes = Size2; X MemChunk->mc_Next = NewChunk; X MemChunk->mc_Bytes = Size1; X } X if (Size1 == 0) X { X if (LastChunk == NULL) X MemHeader->mh_First = MemChunk->mc_Next; X else X LastChunk->mc_Next = MemChunk->mc_Next; X } X MemHeader->mh_Free -= 8; X bytes += 8; X } X LastChunk = MemChunk; X } X MemHeader = (struct MemHeader *)MemHeader->mh_Node.ln_Succ; X } X Permit(); X printf("MQ: %d bytes quarantined.\n", bytes); X return; X} SHAR_EOF echo "extracting MD.uu" sed 's/^X//' << \SHAR_EOF > MD.uu X Xbegin 644 MD XM```#\P`````````#``````````(```J3`````````F\```/I```*DR1()`!)K XM^0````!'^0``!5!R`"`\```!&V`")L%1R/_\+'@`!"E.!8@I3P600JP%C"9NA XM`11P`"(\```P`$ZN_LXI:P"8!81*JP"L9P``<"`/D*\`!`:`````@"E`!51AC XM``$N(&L`K-'(T<@B:``0T\G3R2`"<@`2&2E)!9C0@5*`0F=2@`)`__Z?P%6`) XM0G<(`"`"4X#4@1^R```@`%."4<C_]A^\`"`@`%."'[$@`"``4<K_^")/+PE@Z XM``!X*6L`.@54<']2@-&L!51A``#"0>L`7$ZN_H!!ZP!<3J[^C"E`!8PO`"1`V XM("H`)&<2+&P)D"!`(B@``"E!!81.KO^"(BH`(&<:)#P```/M3J[_XBE`!91GU XM"N6(($`G:``(`*0@;`6,+PA(;`50(&@`)"EH``0%F$ZZ!M1.N@U0<`!@!"`OW XM``0O`"`L!7QG!"!`3I!.NBA<+'@`!")L"9!.KOYB3KH&JDJL!8QG&B(L!91GN XM!$ZN_]PL>``$3J[_?")L!8Q.KOZ&(!\N;`603G5P9&"T0_H`$'``3J[]V"E`I XM"9!G[$YU9&]S+FQI8G)A<GD`3E7@G+_L!51E`!'>2.<W,BXO'XPF;Q^0?`!ZI XM`'``*T#@M'("OH%F5"!K``1P+;`09DI#Z``!<'&P$69`0^@``DAL``8O"4ZZ3 XM'>Q03RM`__Q*@&8D2&P"_$AL``A.NAS&2&P"_$AL`#).NARZ2'@`'DZZ'^)/F XM[P`4?`%@'G`!OH!O&$AL`OQ(;`!,3KH<F$AX`!Y.NA_`3^\`#$AMX*!.NA(<< XM2&P`=DZZ!B!(;`".3KH&&$AL`*A.N@802&W@H$ZZ)/1/[P`4+P!(;`#&3KH&8 XM9E!/*WP`$```X*0@+>"D<@"P@6-J#$4#Z&1D+P!(;`#:2&P"_$ZZ'/Y/[P`,@ XM+RW@I$ZZ&`983RM`X*A*@&<D<@`R!>>!0>W@NB)(T\$B@"`%4D5R`#(`YX'1' XMP2%MX*0`!&#*<`&PK>"D9@AR`"M!X*1@F"`MX*3BB"M`X*1@C#M%X+)(;`#XO XM2&P"_$ZZ')A03WH!NFW@LF0``)QP`#`%YX!![>"Z(DC3P"M1X*C1P"MH``3@> XMI"`%4T`[0."<,"W@G$I`:T8B`$C!YX%![>"Z(DC3P21MX*BUT60P(@!(P>>!& XM0^W@PB1)U<$B`$C!YX$L2-W!))8D`$C"YX+3PM'!(V@`!``$4VW@G&"R,"W@0 XMG$C`YX!![>#"(DC3P"*MX*@P+>"<2,#G@-'`(6W@I``$4D5@`/]@2&P!#DALK XM`OQ.NAOF4$](;`$>3KH$L%A/2&P!,$ZZ!*983WH`NFW@LF0L<``P!7(`,@7G2 XM@4'MX+HB2-/!T<$O*``$+Q$O`$AL`5).NA3R3^\`$%)%8,Y(;`%L3KH$:%A/' XM>@"Z;>"R9%QP`#`%<@`R!>>!0>W@NM'!+R@`!"\`2&P!;DAL`OQ.NAMH3^\`K XM$$*MX*QP`#`%YX!![>"Z(DC3P"`MX*RPJ0`$9!9R`#(%YX'1P2)0T\`2K``"T XM4JW@KD5@GCM\``'@GC`MX)YR!+!!9``!)G(`,@!P`$'L``$0,!@`+P!(F XM;`&22&P"_$ZZ&P!/[P`,>@"Z;>"R9```]'``,`5R`#(%YX%![>"ZT<%R`#(M* XMX)YT`$/L``$4,1@`+P(O*``$+P!(;`&F2&P"_$ZZ&KY/[P`40JW@K'``,`7G` XM@$'MX+HB2-/`("W@K+"I``1D``"8<@`R!>>!(DC3P211U<!T`#0MX)X6$D/LZ XM``&V,2@`9U`B2-/!)%'5P-'!(E#3P'``$!%R`#("=`!![``!%#`8`"\"+P`OJ XM"DAL`<Q.NA.<4JW@M'``,`7G@$'MX+K1P")0T^W@K"Z)3KD```<X3^\`$'``S XM,`7G@$'MX+K1P")0T^W@K$'L``(P+>">$K`(`%*MX*Q@`/]24D5@`/\(4FW@@ XMGF``_M)3;>"><`!![``","W@GA`P"``O`$AL`?Y(;`+\3KH9V$_O``QZ`+IM& XMX+)D``#,<``P!7(`,@7G@4'MX+K1P7(`0^P``C(MX)X2,1@`+P$O*``$+P!(O XM;`(22&P"_$ZZ&9A/[P`40JW@K'``,`7G@$'MX+HB2-/`("W@K+"I``1D<G(`' XM,@7G@2)(T\$D4=7`%!)#[``"-BW@GK0Q.`!G3")(T\$D4=7`T<$B4-/`<``0. XM$7(`0>P``A(P.``O`2\`+PI(;`(X3KH2?E*MX+1P`#`%YX!![>"ZT<`B4-/MT XMX*PNB4ZY```'.$_O`!!2K>"L8`#_>%)%8`#_,"\MX+1(;`)J3KH"-%!/>@"Z` XM;>"R9"QP`#`%+P!(;`*`2&P"_$ZZ&-AP`#`%YX!![>"ZT<`ND$ZZ%\Y/[P`,= XM4D5@SG`!O$!F/D)MX+`P+```,BW@L+)`9"1P`#`!Y8!![`6<+S`(`$AL`I0O. XM+?_\3KH8CD_O``Q2;>"P8-`O+?_\3KH:@%A/0J=.NAK43.U,[.!\3EU.=;_L$ XM!51E``Q62.<C$"9O`!0P+```9AHB`%)!.4$``"0`2,+E@D'L!9PABR@`8```- XMG')DL$%G``"4?@`P+```2,"^@&Q<(`?E@$'L!9RW\`@`9#P\+```2,:\AV\:Q XM(`;E@"(&Y8%![`680^P%G".P&``(`%.&8.(@!^6`0>P%G"&+"``P+```4D`YV XM0```8!(@!^6`0>P%G+?P"`!G!%*'8)HP+```(@!(P>6!0>P%F+?P&`!C%B(`* XM4D$Y00``(@!(P>6!0>P%G"&+&`!,WPC$3G5.=4YU2.<',"XO`!@F;P`<+"\`7 XM("\'3KH?N%A/)$`@"F8$</]@-@@J``,``V<02'@``D*G+P=.NA+$3^\`#"\&& XM+PLO*@`$3KH:!$_O``PJ`$JL!6AG!'#_8`(@!4S?#.!.=0``````````<&%(H XMYP,0)F\`$"!+2AAF_%.(D<LL"'X`'AM*AV<R4ZP"YFT6(&P"WD/H``$I20+>N XM(`<0@'(`$@!@W"`'<@`2`$AL`MHO`4ZZ"#Y03R(`8,9(;`+:2'C__TZZ""Q0Q XM3R`&3-\(P$YU````````<&%.5?_<2.</,"9O`$1\`$'M``PK2/_R'AM*!V<`, XM`0IP);X`9@``S!X;<``0!W(874%K``"(L'L0"&;T3OL0!`!D8```4`!X8```1 XM&@!P8```%`!S8````B!M__(D6"M(__)@2B!M__(H&"M(__)%[?_L>@=*A6L6K XM(`1R#\"!0?H`P-'`%)!3BNB$4X5@YD(M_^U@&B!M__(H&"M(__(O!$AM_^5.. XMN@SX4$]%[?_E+PI.NO[D6$_<@&``_UY2AE.L`N9M&"!L`MY#Z``!*4D"WB`'K XM$(!R`!(`8`#_/G``$`=(;`+:+P!.N@<R4$\B`&``_RA2AE.L`N9M&"!L`MY#S XMZ``!*4D"WB`'$(!R`!(`8`#_"'``$`=(;`+:+P!.N@;\4$\B`&``_O)(;`+:. XM2'C__TZZ!N@@!DSM#/#_Q$Y=3G4P,3(S-#4V-S@Y04-$148```!.5?_$2.<G< XM,"9O`%PD;P!@?@!\`'H`<``;?``@__MR`"M!__9T_RM"__)![?_0&T#_\1M`P XM__PK0?_D*T'_Z"M(_\Q*$V="<``0$W(874%K.+![$`AF]D[[$`0`(V```"``> XM(&```!8`*V````P`+6````)^`6`.?`%@"GH!8`8;?``!__Q2BV"Z$!-R,+`!Q XM9@92BQM!__MP*K`39A`@4D/H``0DB2M0__92BV`.2&W_]B\+3KH+T%!/U\`0( XM$W(NL`%F)E*+<"JP$V80(%)#Z``$)(DK4/_R4HM@#DAM__(O"TZZ"Z)03]?`P XM$!-R;+`!9@H;?``!__%2BV`(<FBP`68"4HL0&W(`$@`;0/_P<#!=0&L``E2RH XM>P`(9O1.^P`$`&-@``(J`'-@``'H`%A@``%^`'A@``%X`'!@``%>`&]@``$,H XM`'5@``#B`&1@```"2BW_\6<,(%)#Z``$)(D@$&`*(%)#Z``$)(D@$"M`_^QL_ XM"G(!1*W_["M!_^A*K?_H9P1P+6`*2@9G!'`K8`)P(!M`_]!P`!`&(BW_Z(*`L XM<``0!8*`9PA2K?_,4JW_Y"\M_^PO+?_,3KH)^E!/*T#_R"`M__)*@&H&<@$K" XM0?_R("W_R"(M__*2@$CM``+_Q&\N(&W_S")(T\%@`A+84X!D^G``$"W_^R(MX XM_\0@;?_,8`(0P%.!9/H@+?_R*T#_R-&M_^1![?_0*TC_S$H'9P`!4!M\`"#_* XM^V```49*+?_Q9PP@4D/H``0DB2`08`H@4D/H``0DB2`0*T#_[&``_V)*+?_Q@ XM9PP@4D/H``0DB2`08`H@4D/H``0DB2`0*T#_[$HM__QG$B!M_\P0_``P<@$K, XM0?_D*TC_S"\`+RW_S$ZZ"5103RM`_\A@`/\H&WP`,/_[("W_\DJ`:@9P""M`1 XM__)*+?_Q9PP@4D/H``0DB2`08`H@4D/H``0DB2`0*T#_[$HM__QG%B!M_\P0> XM_``P$/P`>'("*T'_Y"M(_\PO`"\M_\Q.N@DP4$\K0/_(<%BP+?_P9@#^ODAM$ XM_]!.N@@,6$]@`/ZP(%)#Z``$)(DB4"M)_\QF"$'Z`-PK2/_,(&W_S$H89OQ31 XMB)'M_\PK2/_D("W_\DJ`:RJQP&\F*T#_Y&`@<`$K0/_D(%)#Z``$)(D@$!M`P XM_]!"+?_18`9P`&```(P@+?_D(BW_]K*`;`AT`"M"__9@!)&M__9*!V<V4ZW_$ XMY&T8<``@;?_,$!@O`"M(_\P@;0`03I!83V#B4ZW_]FU(<``0+?_[+P`@;0`0' XM3I!83V#H4ZW_]FT2<``0+?_[+P`@;0`03I!83V#H4ZW_Y&T8<``@;?_,$!@O( XM`"M(_\P@;0`03I!83V#B(`M,WPSD3EU.=0``3E7_]DCG`3`F;P`>)&\`(BMM. XM`!#_]AX:2@=G-'`EO@!F(K`29@12BF`:+PM(;?_V+PIA`/O,3^\`#"M`__IG@ XM!"1`8-)P`!`'+P!.DUA/8,9,WPR`3EU.=4Y5__!(YR$R)F\`+`RL````(`BJ" XM;```AA`3<B"P`6<,<@FP`6<&<@JP`68$4HM@Z$H39V@@+`BJY8!2K`BJ0>P(4 XMLM'`)$AP(K`39B92BR2+2A-G"G`BL!-G!%*+8/)*$V8,2'@``4ZZ&FA83V">8 XM0AM@FB2+2A-G&!`3<B"P`6<0<@FP`6<*<@JP`6<$4HM@Y$H39@)@!D(;8`#_\ XM<DJL"*IF!B!L!8Q@!$'L"+(I2`BN2JP(JF9\0?H!)$/L"'`BV"+8(M@BV#*00 XM(FP%C"!I`"1(>``H+R@`!$AL"'!.N@8B3^\`#$'L"'`B""0\```#[BQL"9!.4 XMKO_B*4`',"E`!SAR!"E!!S0I0`=`*4$'/.6`D\DL>``$*T#_\$ZN_MH@;?_PB XM(D`C:``(`*1^`"M`__1@*BQL"9!.KO_**4`',$ZN_\0I0`<X0?H`IB(()#P`G XM``/M3J[_XBE`!T!^!"`'`$"``8&L!RP@!P!`@`*!K`<T`*P``(`#!SQ*K`,@C XM9P1P`&`&(#P``(``+@!"K`+4(`<`0``!*4`"T'`!*4`"]B`'`$```BE``O)PZ XM`BE``Q@@!P!``(`I0`,40?H5\BE(!8`O+`BN+RP(JDZZ\5I"ETZZ$:A,[4R$Y XM_]Q.74YU8V]N.C$P+S$P+S,R,"\X,"\`*@``````````````````````````H XM``````````````!P82\+)F\`"$JK`!1G#`@K``,`&V8$<`!@-B\L!0!.N@R^7 XM6$\G0``$)T``$$J`9@IP#"E`"8QP_V`6)VP%```4<//!JP`8<``G0``,)T``_ XM""9?3G4``````````````````$Y5_^Q(YR\0+B\`-"9O`#@H!W`QP*L`&&<&J XM</]@``)P""L`!P`:5L!$`$B`2,`L`$JK`!1F``"$""L``@`;9GIP`"=```QRC XM_[Z!9P`"0B\+3KK_3EA/2H!G#`CK``4`&W#_8``"*@CK``$`&TH&9PX@*P`4= XM(@!$@2=!``Q@""`K`!0G0``,4ZL`#&T6(&L`!$/H``$G20`$(`<0@'(`$@!@L XM$B`'<@`2`"\++P%A`/]24$\B`"`!8``!U@@K``(`&V=8</^^@&8&<`!@``'"M XM(`<;0/__2@9G(G(*OH%F''("+P%(>@&R+RL`'"M!__!.NO8D3^\`#"H`8!IR" XM`2\!2&W__R\K`!PK0?_P3KKV"$_O``PJ`'[_8```X`CK``$`&TH&9U)P_[Z`Q XM9TQ4JP`,<@J^@68F(&L`!$/H``$G20`$$+P`#2(K``Q*@6L*+PLO`&$`_JY0L XM3U*K``P@:P`$0^@``2=)``0@!Q"`(BL`#$J!:P`!''[_("L`!)"K`!`K0/_P; XM9W((*P`&`!IG4DAX``)"IR\K`!Q.N@AT3^\`#"M`_^Q*!F<X4ZW_[&TR0J<O[ XM+?_L+RL`'$ZZ"%1(>``!2&W__2\K`!Q.N@6H3^\`&$JL!6AF"A`M__UR&K`!N XM9\@O+?_P+RL`$"\K`!Q.NO4H3^\`#"H`8`)Z`'#_NH!F"`CK``4`&V`,NJW_+ XM\&<&".L`!``;2@9G#B(K`!0D`42")T(`#&`8""L``@`;9PAR`"=!``Q@""(K' XM`!0G00`,(&L`$"=(``2^@&<N4ZL`#&T6(&L`!$/H``$G20`$(`<0@'(`$@!@` XM$B`'<@`2`"\++P%A`/V04$\B`'`PP*L`&&<$</]@#'#_N(!F!'``8`(@!$S?Q XM"/1.74YU#0H`````+FP%D$ZZ$0)(>0```!1.N@Y<``````````!P84Y5__@OL XM"R9L"&P@"V8$1_H`?!E3"409:P`!"449:P`""49"+`E'0>P)1"E("3Q!ZP`#A XM2&W_^"\(3KH"RE!/5H#7P"`M__@B/```#A!.NA%2*4`).$H39QX94PE(&6L`[ XM`0E)&6L``@E*<``90`E+<@$I00DT8`A"+`E(0JP)-$'L"4@I2`E`)E].74YU@ XM0U-4-@````````````````````````````````````````````````````!.N XM5?_R2.<'$"9O`"9(;?_X3KH)#EA/>@`0+?_Y+``&!@`*?@"^!F0B<``0!U2`- XM<@1.NA#62H%F"`:%```!;F`&!H4```%M4@=@VGX!$"W_^KX`9!1P`!`'<@!!N XM[`,C$C`(`-J!4@=@Y'``$`94@'($3KH0EDJ!9@P0+?_Z<@*P`6,"4H5P`!`M3 XM__M3@-J`(`5R&$ZZ$%0J`'``$"W__-J`(`5R/$ZZ$$(J`'``$"W__=J`(`5R? XM/$ZZ$#`J`'``$"W__MJ`3KK^@MJL"3@@"V<")H4@!4S?".!.74YU2.<@,"9OZ XM`!`D2TH29R1P`!`20>P#_0@P``$(`&<*<@`2`'0@DH)@!'(`$@`4@5**8-@@T XM"TS?#`1.=0``````````<&%.5?_X2.<#,"9O`"`D;P`D+B\`*"!*2AAF_%.(0 XMD<HL""!+2AAF_%.(D<L@"")+T\`K2?_XO(=C`BP'(`8@2F`"$MA3@&3Z(&W_\ XM^$(P:``@"TS?#,!.74YU("\`""!O``1.5?_T(D]R"DZZ#[`&00`P$L%*@&;P` XM(`D0X;_)9OI"$)"/3EU.=0``("\`""!O``1.5?_T(D\B``)!``<&00`P$L'FN XMB&;P(`D0X;_)9OI"$)"/3EU.=0``,#$R,S0U-C<X.6%B8V1E9B`O``@@;P`$+ XM0^\`!#(``D$`#Q+[$-SHB&;R(`DB#UB!$.&RB6;Z0A"0@4YU("\`""!O``1.8 XM5?_T(D]L!A#\`"U$@'(*3KH/#`9!`#`2P4J`9O`0X;_)9OI"$"`(3EV0KP`$R XM3G4@;P`$(DAR`'``+P(,$``K9P8,$``M9@)22!`8!```,&T2#```"6X,)`'E& XM@=*"TH'2@&#F#!$`+68"1($D'R`(4X`@;P`(((&0B4YU+P<N+P`(4JP)4"`'B XM(&P)3!#`*4@)3"X?3G5.50``2.<`,"9O`!`D;P`40JP)4"E+"4Q(;0`0+PI(K XM>O_&3KKV\B!L"4Q"$"`L"5!,[0P`__A.74YU3E7_Z$CG`3(N+P`T2H=N!G#_B XM8```TG`(OH!D`BX`(`=6@"X``D?__"1M``@@;0`(T<??K`*P0^P"K"91*TC_T XM\"M)__0@"V<``)`@2R`K``31P"M(_^PB;?_PM\EC$"2+)4<`!"QM__0LBG``D XM8'BWR68:+%,DCB`K``0B`-*')4$`!"QM__0LBG``8%JUR&0(GZP"L'#_8$ZUA XMR&8L2I-G#B!3L\AC")^L`K!P_V`XWZL`!$J39PZSTV8*("D`!-&K``0FD7``3 XM8!XK2__T*VW_[/_H)E-@`/]N(&W_]""*0I(E1P`$<`!,WTR`3EU.=0``````: XM````<&%(YP$0)F\`#"XO`!`O!R\+3KK^]E!/3-\(@$YU2.<',"XO`!@F;P`<L XM+"\`("\'3KH/7%A/)$`@"F8$</]@'B\&+PLO*@`$3KH*B$_O``PJ`$JL!6AG4 XM!'#_8`(@!4S?#.!.=0``+P<N+P`(4JP)5%.L`N9M%B!L`MY#Z``!*4D"WB`'% XM$(!R`!(`8!0@!W(`$@!(;`+:+P%.NO@44$\B`"X?3G5.50``+PLF;P`,0JP)- XM5$AM``PO"TAZ_ZQ.NO4H2&P"VDAX__].NO?D("P)5"9M__Q.74YU``!.5?_F_ XM2.</,"9O`#HN+P`^0BW__T*L!6@K;`F,__)Z`[JL`IQL$B`%YX!![`<L2K`(J XM`&<$4H5@Z"`L`IRPA68,<!@I0`F,</]@``$J(`7G@$'L!RS1P"1(2JT`$&<(Z XM""T``@`39PHK?````^S_[F`(*WP```/N_^X@/```@`#`K`*TL8<(!P`#9PP@& XM!P)`__PN``!'``(@!W(#P($,@`````)G#`R``````6<$2H!F!BP'4H9@#'`6$ XM*4`)C'#_8```M"`'`H````,`9P``B`@'``IG%AM\``'__R\M_^XO"TZZ":I06 XM3R@`8#P(!P`)9A9(>`/M+PM.N@E,4$\H`$J$:@0(QP`)"`<`"6<:&WP``?__X XM*6W_\@F,+RW_[B\+3KH)T%!/*`!*+?__9S8@!W)XTH'`@4J`9RI*A&LF+P1.Y XMN@H82'@#[2\+3KH(^D_O``PH`&`.2'@#[2\+3KH(Z%!/*`!*K`5H9P1P_V`(^ XM)(8E1``$(`5,WPSP3EU.=0```````````````````````'!A2.<!,"XO`!!*Y XMK`E89Q8D;`E8+Q(O+`E83KK]?E!/D<@I2`E82H=F!'``8!Y8AR\'3KH"CEA/" XM)D!*@&8$<`!@"B1+)(=!ZP`$(`A,WPR`3G5(YP\0+B\`&"PO`!PJ+P`@+P=.7 XMN@S`6$\F0"`+9@1P_V`>+P4O!B\K``1.N@=P3^\`#"@`2JP%:&<$</]@`B`$0 XM3-\(\$YU``!.5?_H2.</$"9O`#0@$R(\``%1@$ZZ"@XK0/_P+``@$R(\``%1S XM@$ZZ"?PN`2`'(CP```X03KH)[B@`(`<B/```#A!.N@G@+@$@!W(\3KH)UBM`P XM_^@@!W(\3KH)RBX!*4<)8"EM_^@)9"E$"6A(;?_P80``3"H`(`4$@```!VPIG XM0`ET*6W_\`E\+H5(;?_P80``ABE`"7`@+?_P4H`I0`EL(`98@'('3KH)?"E!! XM"7A![`E@(`A,[0CP_]1.74YU2.<#$"9O`!`N/```![(L$PR&```!;6\>(`=R@ XM!$ZZ"4A*@68(!(8```%N8`8$A@```6U2AV#:#(8```%M9A`@!W($3KH)(DJ!1 XM9P12AWP`)H8@!TS?",!.=4CG!Q`F;P`4+B\`&"`'<@1.N@C\2H%F!G`=*4`#& XM.'H`+!-P#+J`;!P@!>6`0>P#-"(P"`"RAFX,0>P#-)RP"`!2A6#>)H8@!4S?R XM".!.=4CG`S`N+P`42H=N!G``8```I'`(OH!D`BX`(`=6@"X``D?__$7L`JPFU XM4B`+9T`@*P`$L(=M,K"'9@P@4R2(GZP"L"`+8&X@*P`$D(=R"+"!918@2]''6 XM)(@D2"23)4``!)^L`K`@"V!,)$LF4V"\(`<B+`,PT(%3@$ZZ"$8B+`,P3KH(# XM'BP`4(8@!E:`+``"1O_\+P9.N@R66$\F0"`+9Q(O!B\+3KKY_BZ'80#_5%!/1 XM8`)P`$S?#,!.=0``````````<&$O!RXO``@O!TZZ_S)83RX?3G4``$Y5_^!(H XMYR\0)F\`0$'M__0B""QL"9!.KO]`("W_]"X\```'NBP`*T#_\`R&```!;6\>P XM(`=R!$ZZ![!*@68(!(8```%N8`8$A@```6U2AV#:#(8```%M9A`@!W($3KH'A XMBDJ!9P12AWP`(`8B!P2!```'O!=!``%T`!0!*T#_\"`"<@1.N@=D2H%F!'`=U XM8`)P'!E``V5X`"HM__!P#+B`;!YP`$'L`V00,$@`L(5N$'``0>P#9!`P2`":0 XM@%*$8-P@!2($4H$700`"*T#_\%*`%T```R`M__1R!TZZ!PX6@2`M__AR/$ZZW XM!P(70``$("W_^'(\3KH&]!=!``4@+?_\<C).N@;F%T``!B`M__QR,DZZ!MC26 XM@1=!``=,WPCT3EU.=2\+)F\`""`+9Q!"ITZZ^_Y83R!+68@I2`E8<``F7TYU5 XM````````<&%(YP$P)F\`$"1O`!1^`!X;2H=G$B\*+P=.N@`64$]2@&;J</]@; XM`G``3-\,@$YU``!(YP$0+B\`#"9O`!`(*P`&`!MG$G`*OH!F#"\++P=.NO'8R XM4$]@,%.K``QM%B!K``1#Z``!)TD`!"`'$(!R`!(`8!(@!W(`$@`O"R\!3KKQF XMJE!/(@`@`4S?"(!.=4CG`2`N+P`,4JP)B"!L"813J``,;18B:``$1>D``2%*5 XM``0@!Q*`<@`2`&`2(`=R`!(`+P@O`4ZZ\6103R(`3-\$@$YU3E4``$CG`#`F] XM;P`0)&\`%$*L"8@I2PF$2&T`$"\*2'K_G$ZZ[FPNBTAX__].NO$J("P)B$SM3 XM#`#_^$Y=3G4``$Y5__A(YP`P1^P"N"`+9PQ*JP`89P8D2R938/`@"V8B2'@`: XM(DZZ_6Y83R9`2H!F!'``8!PDBW`A<@`@2Q#!4<C__"\++RT`#"\M``A.N@`.@ XM3.T,`/_P3EU.=0``3E7_\$CG#S`F;P`T)&\`.$JJ`!AG""\*3KH!3EA/*BP#! XM('X!<``0,W@`#$``8F<*#$``868,>@!@!BH\``"``%*'<BNR,W@`5\!$`$B`$ XM2,`H`'``$!,,0`!W9P``B`Q``')G0@Q``&%F``"^2'@`#"\\``"!`B\M``A.9 XMNOAL3^\`#"P`</^\@&8&<`!@``#02H1G!G!`T(!@`G`"+@``1T``8```B$J$% XM9P1P`F`"<```0(``2'@`#"\`+RT`"$ZZ^"A/[P`,+`!P_[R`9@9P`&```(Q*I XMA&<&<$#0@&`"<`$N`&!(2H1G!'`"8`)P`0!`@```0`$``$`"`$AX``PO`"\MR XM``A.NO?B3^\`#"P`</^\@&8$<`!@1DJ$9P9P0-"`8`)P`BX`8`1P`&`RD<@EK XM2``0<``E0``4)48`'"5J`!``!"5```PE0``(2H5F!B`\``"``"('@H`E00`8) XM(`I,WPSP3EU.=0``2.<#,"9O`!0(*P`!`!MG$"\+2'C__TZZ[SQ03RX`8`)^H XM`"`K`!A"@&<42JL`%&<.+RL`%"\K`!!.NO9N4$\O*P`<3KH%J%A/+`!P_[Z`L XM9P9*AF8"<`!,WPS`3G5(YP,0+B\`$$?L`K@@"V<T""L``@`;9B@(*P`!`!MG% XM("`K``20JP`0+`!*AF<2+P8O*P`0+RL`'$ZZY=)/[P`,)E-@R"\'3KH'$%A/J XM3-\(P$YU``!(YS<0+B\`'"9O`"`L+P`D2JP%@&<$3KH%K$*L!6@B!R0+)@8L# XM;`F03J[_T"H`</^Z@&8.3J[_?"E`!6AP!2E`"8P@!4S?".Q.=0``2.<_`"XOI XM`!PL+P`@*B\`)$JL!8!G!$ZZ!6!"K`5H(`53@"(')`8F`"QL"9!.KO^^*`!PU XM_[B`9@Y.KO]\*4`%:'`6*4`)C"`%#(`````"9Q8,@`````%G"$J`9A@@!F`4* XM(`30AF`.(@=T`'8`+&P)D$ZN_[Y,WP#\3G4``$CG-Q`N+P`<)F\`("PO`"1*\ XMK`6`9P1.N@3D0JP%:"(')`LF!BQL"9!.KO_6*@!P_[J`9@Y.KO]\*4`%:'`%V XM*4`)C"`%3-\([$YU``!(YR,0)F\`%"XO`!A*K`6`9P1.N@2<0JP%:"(+)`<LR XM;`F03J[_XBP`2H9F$DZN_WPI0`5H<`(I0`F,</]@`B`&3-\(Q$YU``!.5?_\B XM2.<A$"9O`!A*K`6`9P1.N@140JP%:"(+=/XL;`F03J[_K"X`2H=G"B('3J[_Y XMIG#_8"8B"R0\```#[DZN_^(N`$J'9A).KO]\*4`%:'`"*4`)C'#_8`(@!TS?- XM"(1.74YU3E7__$CG(1`F;P`82JP%@&<$3KH#\$*L!6@B"W3^+&P)D$ZN_ZPN& XM`$J'9PPB!TZN_Z8B"TZN_[@B"R0\```#[DZN_^(N`$J'9A).KO]\*4`%:'`"_ XM*4`)C'#_8`(@!TS?"(1.74YU```O!RXO``A*K`6`9P1.N@..(@<L;`F03J[_* XMW'``+A].=4Y5_[`O#DJL"5QF$D/Z`(AP`"QX``1.KOW8*4`)7'``(&P%F!`H+ XM__]#[?^P8`(2V%.`9/IP`"!L!9@0*/__0C4(L$'M_[`I2`-\2'@`*$AX`/IPW XM`"\`+P!(;`.8<@`O`4AL`X0O`4ZZ`V1(>``43KH$3"QM_ZQ.74YU*BH@4W1AC XM8VL@3W9E<F9L;W<@*BH``$58250``&EN='5I=&EO;BYL:6)R87)Y````````V XM`````````$CG,``D`"8!2$)(0\3!QL#`P=1#2$)"0M""3-\`#$YU2H!J```>. XM1(!*@6H```Q$@6$``"!$@4YU80``&$2`1(%.=4J!:@``#$2!80``!D2`3G4O[ XM`DA!-`%F```B2$!(04A"-`!G```&A,$P`DA`-`"$P3`"2$(R`B0?3G4O`W80J XM#$$`@&0```;AF5%##$$(`&0```;IF5E##$$@`&0```;EF55#2D%K```&XYE3: XM0S0`YJA(0D)"YJI(0X#!-@`P`C0#2$'$P9""9```"%-#T(%D_G(`,@-(0^>XT XM2$#!028?)!].=4Y5_YY(YS,R?@`@;`68'BC__W!/OH!O`BX`(`=#[?^O8`(2I XMV%.`9/I"-7BOD\DL>``$3J[^VB9`2JL`K&=,("L`K.6`)$`L*@`X2H9F!"PK8 XM`*!*AF<T(@9!^@"R)`AV"RQL"9!.KO_0($=2AR`(&[P`"@BO(@9![?^O)`@F? XM!RQL"9!.KO_0</]@3DJL"5QF$D/Z`(9P`"QX``1.KOW8*4`)7$'M_Z\I2`/,) XM2'@`/$AX`/IP`"\`+P!(;`/H2&P#U$AL`\!"ITZZ`6Q/[P`@4X!G!'#_8`)P@ XM`$S?3,Q.74YU*BH@57-E<B!!8F]R="!297%U97-T960@*BH``$-/3E1)3E5%' XM``!!0D]25``J*BH@0G)E86LZ(`!I;G1U:71I;VXN;&EB<F%R>0```$Y5__POH XM"R9O`!!.NNQ$(!.0K`DX*T#__$AM__Q.NO/.+H!.N@$8)FW_^$Y=3G4``$CGM XM`1`N+P`,+P=.N@`\6$\F0"`+9@1P_V`H""L``@`#9P9P`":`8!HO*P`$3KK\D XMOEA/<``F@$JL!6AG!'#_8`)P`$S?"(!.=2\'+B\`"'``*4`%:$J':R*^K`*<' XM;!P@!^>`0>P'+$JP"`!G#B`'YX!![`<LT<`@"&`(<`DI0`F,<``N'TYU``!([ XMYP$"<``B/```,``L>``$3J[^SBX``H<``#``2H=F!'``8"!*K`6`9Q@@;`6`U XM3I!*@&8$<`!@#$AX`!1.N@$"6$\@!TS?0(!.=6&T3G4``$CG,#(L;`E<(&\`^ XM&")O`!PD;P`@)F\`)"`O`"@B+P`L)"\`,"8O`#1.KOZD3-],#$YU```O"R9OD XM``@@*P`8Y8`B*P`0Y8$O*P`4+Q,O*P`$+RL`""\K``Q![`4$+S`8`$'L!30OK XM,`@`2'H`9$AL"91.NNY`3^\`)$'L"90@""9?3G5*86X`1F5B`$UA<@!!<'(`J XM36%Y`$IU;@!*=6P`075G`%-E<`!/8W0`3F]V`$1E8P!3=6X`36]N`%1U90!7. XM960`5&AU`$9R:0!3870`)7,@)7,@)3`R9"`E,#)D.B4P,F0Z)3`R9"`Q.24P2 XM,F0*`$CG!P`N+P`0("P"G%.`+`!*1FLP(`9(P.>`0>P'+"HP"`!*!6<:"`4`+ XM`F84(`9(P.>`0>P'+"\P"`1.NOKH6$]31F#,+P=.NM>>6$],WP#@3G4``$CG) XM`#(F;`FP(`MG%"13(DL@*P`(+'@`!$ZN_RXF2F#HD<@I2`FT*4@)L$S?3`!.9 XM=4CG`3(N+P`4<`S>@"`'<@`L>``$3J[_.B9`(`MF!'``8#HG1P`(1>P)L"!J' XM``0G2``$D<@FB$J29@(DBTJJ``1G!B)J``0BBR5+``1*K`*@9@0I2P*@0>L`+ XM#"`(3-],@$YU``````````````````````/L`````@````````:,```%;@``D XM``(````"````#`````8````````#\@```^D````````#\@```^H```%4````N XM_U6J=P!5<V%G93H@340@6SYR97!O<G1F:6QE72!;+7%A9&1R97-S9FEL95T*M XM``!#86YN;W0@;W!E;B!O=71P=70@9FEL92X*`%5S86=E.B!-1"!;/G)E<&]R_ XM=&9I;&5=(%LM<6%D9')E<W-F:6QE70H``$U$+2U-96UO<GD@1&EA9VYO<W1I= XM8RX*`&)Y($9A8F)I86X@1RX@1'5F;V4L($E)20H`5F5R<VEO;B`Q+C$L(#$P5 XM($%P<FEL(#$Y.#D*"@``365M;W)Y('1E<W1E9"`E<PH*``!!;&QO8V%T:6YG3 XM("5L9"!B>71E(&)L;V-K<RX*``!3;W)T:6YG(&)L;V-K(&QI<W0N"@``4V]R8 XM="!C;VUP;&5T92X*`$)L;V-K<R!E>&%M:6YE9#H*`$)L;V-K(",@("`@061DI XM<F5S<R`@("`@("`@(%-I>F4*"@`E-&0@("`@("`E.&Q8("`@("`@)3=L9`H`@ XM``H`26YI=&EA;&EZ:6YG(&)L;V-K("5D+"`E;&0@8GET97,N"@``5&5S=&EN` XM9R!V86QU92`E6"X*``!497-T:6YG(&)L;V-K("5D+"`E;&0@8GET97,@=VETG XM:"`E6`H``$524D]2(2!!9&1R97-S.B`E.&Q8("!F;W5N9#H@)3)8("!E>'!ER XM8W1E9#H@)3)8"@``5&5S=&EN9R!V86QU92`E6"X*``!497-T:6YG(&)L;V-KL XM("5D+"`E;&0@8GET97,@=VET:"`E6`H``$524D]2(2!!9&1R97-S.B`E.&Q8` XM("!F;W5N9#H@)3)8("!E>'!E8W1E9#H@)3)8"@``"DU$(&9O=6YD("5D(&5R! XM<F]R<RX*`$9R965I;F<@8FQO8VL@)60N"@``)3AL6`H````````H````````= XM`````````````````````(`````"V@``````````````````````````````< XM`````````````OP`````````````````````````````````````````````^ XM`````````````````````````````````````````````(``'QP?'A\>'Q\>1 XM'QX?```$`````!\````<````'P```!X````?````'@```!\````?````'@``Q XM`!\````>````'Q\<'QX?'A\?'A\>'___````#@`.````````````````__\`A XM```$``0````````E%@```W#__P````0`!````````"4L`````/__````#@`.G XM````````)Q0`````__\````$``0``````````````ZS__P````0`!```````V XM`"<P`````/__````!``$````````)SH``````"`@("`@("`@("@H*"@H("`@& XM("`@("`@("`@("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$A(2$A(2$A(00$!`0` XM$!`0@8&!@8&!`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0$!""@H*"@H("`@("^ XM`@("`@("`@("`@("`@("`A`0$!`@("`@("`@("`@*"@H*"@@("`@("`@("`@H XM("`@("`@("!($!`0$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!4 XM@8$!`0$!`0$!`0$!`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("8 XM`@("`@("`@("$!`0$"````````(````HZ@``*.X``"CR```H]@``*/H``"C^< XM```I`@``*08``"D*```I#@``*1(``"D6```I&@``*1X``"DB```I)@``*2H`U XM`"DN```I,@```^P````8````````!4P```5(```%1```!4````4\```%.```C XM!30```4P```%+```!2@```4D```%(```!1P```48```%%```!1````4,```%< XM"```!00```/T```#X````[@```.D```#D`````0````"```#T````Y0```+:L X,```"N`````````/RO X`` Xend Xsize 12432 SHAR_EOF echo "extracting MQ.uu" sed 's/^X//' << \SHAR_EOF > MQ.uu X Xbegin 644 MQ XM```#\P`````````#``````````)```:10````$```1]```/I```&D21()`!). XM^0````!'^0```A!R`"`\````FV`")L%1R/_\+'@`!"E.`D@I3P)00JP"3"9N4 XM`11P`"(\```P`$ZN_LXI:P"8`D1*JP"L9P``<"`/D*\`!`:`````@"E``A1A= XM``$N(&L`K-'(T<@B:``0T\G3R2`"<@`2&2E)`EC0@5*`0F=2@`)`__Z?P%6`& XM0G<(`"`"4X#4@1^R```@`%."4<C_]A^\`"`@`%."'[$@`"``4<K_^")/+PE@Z XM``!X*6L`.@(4<']2@-&L`A1A``#"0>L`7$ZN_H!!ZP!<3J[^C"E``DPO`"1`M XM("H`)&<2+&P$;"!`(B@``"E!`D1.KO^"(BH`(&<:)#P```/M3J[_XBE``E1G& XM"N6(($`G:``(`*0@;`),+PA(;`(0(&@`)"EH``0"6$ZZ`:!.N@B$<`!@!"`OD XM``0O`"`L`CQG!"!`3I!.NA@<+'@`!")L!&Q.KOYB3KH!=DJL`DQG&B(L`E1GS XM!$ZN_]PL>``$3J[_?")L`DQ.KOZ&(!\N;`)03G5P9&"T0_H`$'``3J[]V"E`C XM!&QG[$YU9&]S+FQI8G)A<GD`3E7^2$CG/S!P`"X`1^W^6"M`_E`K0/Y44H<O< XM"TAL``!.N@\24$]8BU*`9P9P9+Z`;>8@!U.`0J=(;``&+T``*$ZZ&#Y03RE`H XM`EQ*@&8*2'@`%$ZZ$JA83TZZ&`8@;`)<)F@!0F```)XD:P`08```CGH`>`!@3 XM=D'M_EC1Q"9((`HB*@`$T(%3@"03L()E9"`*L()B5"`*E(`@`G8'P(.4@"P"! XMDH8N`5&'9@8E1@`$8!0@"M"&4(`@0""2(4<`!"2`)48`!"9M_DQ*AF842JW^K XM4&8((%(G2``08`8@;?Y0())1JP`<4*W^5%*%6(2ZKP`@;80K2OY0)%(F;?Y,, XM(`IF`/]P)E,K2_Y,2I-F`/]<3KH78"\M_E1(;``43KH`Y$SM#/S^*$Y=3G5.: XM=4YU2.<',"XO`!@F;P`<+"\`("\'3KH58%A/)$`@"F8$</]@-@@J``,``V<0% XM2'@``D*G+P=.NA!T3^\`#"\&+PLO*@`$3KH1X$_O``PJ`$JL`BAG!'#_8`(@L XM!4S?#.!.=0``````````<&%(YP,0)F\`$"!+2AAF_%.(D<LL"'X`'AM*AV<R2 XM4ZP`=FT6(&P`;D/H``$I20!N(`<0@'(`$@!@W"`'<@`2`$AL`&HO`4ZZ"*90T XM3R(`8,9(;`!J2'C__TZZ")103R`&3-\(P$YU````````<&%.5?_<2.</,"9OD XM`$1\`$'M``PK2/_R'AM*!V<``0IP);X`9@``S!X;<``0!W(874%K``"(L'L0U XM"&;T3OL0!`!D8```4`!X8```&@!P8```%`!S8````B!M__(D6"M(__)@2B!M3 XM__(H&"M(__)%[?_L>@=*A6L6(`1R#\"!0?H`P-'`%)!3BNB$4X5@YD(M_^U@[ XM&B!M__(H&"M(__(O!$AM_^5.N@Q84$]%[?_E+PI.NO[D6$_<@&``_UY2AE.LC XM`'9M&"!L`&Y#Z``!*4D`;B`'$(!R`!(`8`#_/G``$`=(;`!J+P!.N@>:4$\B7 XM`&``_RA2AE.L`'9M&"!L`&Y#Z``!*4D`;B`'$(!R`!(`8`#_"'``$`=(;`!JF XM+P!.N@=D4$\B`&``_O)(;`!J2'C__TZZ!U`@!DSM#/#_Q$Y=3G4P,3(S-#4V? XM-S@Y04-$148```!.5?_@2.<G,"9O`$`D;P!,<`!R`!(3*T#_\"M`_^Q![`$)E XM"#```A@`9R@@+?_L<@I.NA$"<@`2&W0/PH+0@2M`_^QP`!`30>P!"0@P``(() XM`&;8$!-R;+`!9@I2BW`!*T#_\&`(<FBP`68"4HL@;0`,3I`N`'!CL!-G%D'LE XM`0D(,``#>`!G"B!M``Q.D"X`8.IP_[Z`9@P@;0`0((=P`&```YAP`!`3<C9=# XM06L``WRP>Q`(9O1.^Q`$`'-@``,V`&-@``+B`&A@``*&`%A@``%&`'A@``%`` XM`'!@``$N`&]@``"^`&1@```,`'5@```"?`!@-GP`2JW_[&<*#*T````!_^QOH XM)'`MOH!G!G(KOH%F&+Z`9@1P_V`"<``L`"!M``Q.D"X`4ZW_[$'L`0D(,``"< XM>`!F#"!M`!`@AW``8``"^D*M_^@@+?_H<@I.N@_H(@=T#\*"T($K0/_H(&T`? XM#$Z0+@!3K?_L9PQ![`$)"#```G@`9M`@"F<``K1*AFH$1*W_Z$JM__!F#"!2\ XM("W_Z""`8``"FB!2(*W_Z&```I!P,+Z`;09P-[Z`;PP@;0`0((=P`&```H1"U XMK?_H("W_Z.>`(@=T!\*"T($K0/_H(&T`#$Z0+@!3K?_L9PQP,+Z`;09P-[Z`S XM;]0@"F<``D)*K?_P9@P@4B`M_^@@@&```C`@4B"M_^A@``(F2JW_[&8&<`@KG XM0/_L0>P!"0@P``=X`&8,(&T`$""'<`!@``(.*@<@;0`,3I`N`$JM_^QG"@RM1 XM`````O_L;SQP,+J`9C9P>+Z`9P9P6+Z`9BH@;0`,3I`N`$'L`0D(,``'>`!FP XM#"!M`!`@AW``8``!PD*M_^A3K?_L8$)![`$)"#```E@`9PH@!7(PD($K0/_HJ XM0>P!"0@P``!8`&<*(`5R-Y"!*T#_Z$'L`0D(,``!6`!G"B`%<E>0@2M`_^A3& XMK?_L9V)![`$)"#``!W@`9U8@+?_HZ8`K0/_H0>P!"0@P``)X`&<*(`=R,)"!O XM@:W_Z$'L`0D(,```>`!G"B`'<C>0@8&M_^A![`$)"#```7@`9PH@!W)7D(&!^ XMK?_H(&T`#$Z0+@!@F"`*9P``_$JM__!F#"!2("W_Z""`8```ZB!2(*W_Z&``L XM`.!![`$)"#```G@`9@P@;0`0((=P`&```-1\`"`&<@I.N@W&(@=T#\*"T($L) XM`")M``Q.D2X`4ZW_[&<,0>P!"0@P``)X`&;4(`IG``"4(%(@!C"`8```BB`*J XM9PP@4D/H``$DB2`'$(!3K?_L;R`@;0`,3I`N`'#_OH!G$B`*9^@@4D/H``$DU XMB2`'$(!@VG#_OH!F"B!M`!`@AW``8$Y!ZP`!(`A@1B`*9PP@4D/H``$DB2`'# XM$(`@;0`,3I`N`'#_OH!G$E.M_^QG#$'L`0D(,``#>`!GT"!20A!@!'``8`P@^ XM;0`0((=!ZP`!(`A,WPSD3EU.=0```````'!A2.<A$"XO`!`F;P`4</^^@&=@] XM""L````;9UAR,,*K`!A*@69.""L``@`;9Q@B!Q=!`"!!ZP`@)T@`!'0!)T(`` XM""`!8"X@:P`$(FL`$+/(9@1P_V`>4ZL`!"!K``0@!Q"`""L`!P`:9P93JP`($ XM8`12JP`(3-\(A$YU3E7_\$CG(3(F;P`L#*P````@`]IL``"&$!-R(+`!9PQRJ XM";`!9P9R"K`!9@12BV#H2A-G:"`L`]KE@%*L`]I![`/BT<`D2'`BL!-F)E*+% XM)(M*$V<*<"*P$V<$4HM@\DH39@Q(>``!3KH.]%A/8)Y"&V":)(M*$V<8$!-RB XM(+`!9Q!R";`!9PIR"K`!9P12BV#D2A-F`F`&0AM@`/]R2JP#VF8&(&P"3&`$T XM0>P#XBE(`]Y*K`/:9GQ!^@$D0^P#H"+8(M@BV"+8,I`B;`),(&D`)$AX`"@O5 XM*``$2&P#H$ZZ!;9/[P`,0>P#H"(()#P```/N+&P$;$ZN_^(I0`)D*4`";'($< XM*4$":"E``G0I00)PY8"3R2QX``0K0/_P3J[^VB!M__`B0"-H``@`I'X`*T#_C XM]&`J+&P$;$ZN_\HI0`)D3J[_Q"E``FQ!^@"F(@@D/````^U.KO_B*4`"='X$) XM(`<`0(`!@:P"8"`'`$"``H&L`F@`K```@`,"<$JL`+!G!'``8`8@/```@``N) XM`$*L`&0@!P!```$I0`!@<`$I0`"&(`<`0``"*4``@G`"*4``J"`'`$``@"E`* XM`*1!^@N>*4@"0"\L`]XO+`/:3KKV)D*73KH)'$SM3(3_W$Y=3G5C;VXZ,3`OU XM,3`O,S(P+S@P+P`J`````````````````````````````````````````'!AF XM+PLF;P`(2JL`%&<,""L``P`;9@1P`&`V+RP"#$ZZ"*I83R=```0G0``02H!FP XM"G`,*4`$:'#_8!8G;`(,`!1P\\&K`!AP`"=```PG0``()E].=0``````````V XM````````3E7_[$CG+Q`N+P`T)F\`."@'<#'`JP`89P9P_V```G`(*P`'`!I6% XMP$0`2(!(P"P`2JL`%&8``(0(*P`"`!MF>G``)T``#'+_OH%G``)"+PM.NO].P XM6$]*@&<,".L`!0`;</]@``(J".L``0`;2@9G#B`K`!0B`$2!)T$`#&`(("L`S XM%"=```Q3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO`6$`F XM_U)03R(`(`%@``'6""L``@`;9UAP_[Z`9@9P`&```<(@!QM`__]*!F<B<@J^X XM@68<<@(O`4AZ`;(O*P`<*T'_\$ZZ];Q/[P`,*@!@&G(!+P%(;?__+RL`'"M!, XM__!.NO6@3^\`#"H`?O]@``#@".L``0`;2@9G4G#_OH!G3%2K``QR"KZ!9B8@G XM:P`$0^@``2=)``00O``-(BL`#$J!:PHO"R\`80#^KE!/4JL`#"!K``1#Z``!: XM)TD`!"`'$(`B*P`,2H%K``$<?O\@*P`$D*L`$"M`__!G<@@K``8`&F=22'@`M XM`D*G+RL`'$ZZ!;Q/[P`,*T#_[$H&9SA3K?_L;3)"IR\M_^PO*P`<3KH%G$AX2 XM``%(;?_]+RL`'$ZZ!41/[P`82JP"*&8*$"W__7(:L`%GR"\M__`O*P`0+RL`3 XM'$ZZ],!/[P`,*@!@`GH`</^Z@&8(".L`!0`;8`RZK?_P9P8(ZP`$`!M*!F<.8 XM(BL`%"0!1((G0@`,8!@(*P`"`!MG"'(`)T$`#&`((BL`%"=!``P@:P`0)T@`E XM!+Z`9RY3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO`6$`V XM_9!03R(`<##`JP`89P1P_V`,</^X@&8$<`!@`B`$3-\(]$Y=3G4-"@````!(R XMYP<0)F\`%`@K``<`&E;`1`!(@$C`+@!P,,"K`!AG"D*K``AP_V```5@(*P`'^ XM`!MG%`@K``8`&V<,+PM(>/__3KK](E!/2JL`%&8V0JL`"`@K``(`&V<2<`$G6 XM0``40>L`("=(`!!@``"$+PM.NOR66$]*@&=V".L`!0`;</]@``$`2@=G9E2KE XM``@@*P`(2H!N6B!K``1#Z``!)TD`!'P`'!`@!@R`````&F<N#(`````-9C)3I XMJP`(;10@:P`$0^@``2=)``1P`!`08```M"\+80#_+EA/8```J`CK``0`&W#__ XM8```G"`&8```E@@K``$`&V9.".L````;+RL`%"\K`!`O*P`<3KH#:$_O``PJ> XM`$J%:@8(ZP`%`!M*A68&".L`!``;2H5O&DH'9PH@!42`)T``"&`$)T4`""!KT XM`!`G2``$<#+`JP`89Q9*!V<(</\G0``(8`9P`"=```AP_V`@4ZL`"&T2(&L`' XM!$/H``$G20`$<``0$&`(+PMA`/Z$6$],WPC@3G4``$Y5__A(YP,P)F\`("1OZ XM`"0N+P`H($I*&&;\4XB1RBP(($M*&&;\4XB1RR`((DO3P"M)__B\AV,"+`<@U XM!B!*8`(2V%.`9/H@;?_X0C!H`"`+3-\,P$Y=3G4@+P`((&\`!$Y5__0B3VP&^ XM$/P`+42`<@I.N@7`!D$`,!+!2H!F\!#AO\EF^D(0(`A.79"O``1.=4Y5_^A(& XMYR,P)F\`-$'M``Q^`"M(_^Q*$V<``1I\`!P;0>P!"0@P``-H`&;J<"6\@&8`, XM`+IP);`39CA3K`!0;0YP`"!L`$P0&"E(`$Q@"DAL`$A.NOV46$\L`$'L`0D(X XM,``#:`!FU'`EO(!GJB`'8```QG`JL!-G#"MM_^S_Z%BM_^Q@")'(4HLK2/_HF XM0JW_]"\M_^A(;?_T2'H`I"\+3KKS?$_O`!`D0$J`5L!$`$B`2,!*@&<")DHB/ XM+?_T=/^R@F822H!G`E*'2H=O!"`'8&8@`F!B2H%G#$AL`$@O`4ZZ]X103R`*6 XM9D8@!V!*4ZP`4&T.<``@;`!,$!@I2`!,8`I(;`!(3KK\XEA/*T#_]"!M__1#( XM[`$)(`@(,0`#"`!FS"`M__2PAF<`_NX@!V`(4H=@`/[D(`=,WPS$3EU.=5.L6 XM`%!M#G``(&P`3!`8*4@`3&`*2&P`2$ZZ_)!83TYU``!.5?_H2.<!,BXO`#1*C XMAVX&</]@``#2<`B^@&0"+@`@!U:`+@`"1__\)&T`""!M``C1Q]^L`$1#[`!`9 XM)E$K2/_P*TG_]"`+9P``D"!+("L`!-'`*TC_[")M__"WR6,0)(LE1P`$+&W_S XM]"R*<`!@>+?)9AHL4R2.("L`!"(`TH<E00`$+&W_]"R*<`!@6K7(9`B?K`!$[ XM</]@3K7(9BQ*DV<.(%.SR&,(GZP`1'#_8#C?JP`$2I-G#K/39@H@*0`$T:L`, XM!":1<`!@'BM+__0K;?_L_^@F4V``_VX@;?_T((I"DB5'``1P`$S?3(!.74YU% XM``````````!P84CG!S`N+P`8)F\`'"PO`"`O!TZZ!0!83R1`(`IF!'#_8!XO6 XM!B\++RH`!$ZZ`F!/[P`,*@!*K`(H9P1P_V`"(`5,WPS@3G4``$CG#Q`N+P`89 XM+"\`'"HO`"`O!TZZ!+A83R9`(`MF!'#_8!XO!2\&+RL`!$ZZ`9Q/[P`,*`!*A XMK`(H9P1P_V`"(`1,WPCP3G4``````````'!A2.<#,"XO`!1*AVX&<`!@``"DY XM<`B^@&0"+@`@!U:`+@`"1__\1>P`0"92(`MG0"`K``2PAVTRL(=F#"!3)(B?` XMK`!$(`M@;B`K``20AW((L(%E%B!+T<<DB"1()),E0``$GZP`1"`+8$PD2R93^ XM8+P@!R(L`+30@5.`3KH"!B(L`+1.N@'>+`!0AB`&5H`L``)&__PO!DZZ!398? XM3R9`(`MG$B\&+PM.NOW*+H=A`/]44$]@`G``3-\,P$YU``````````!P82\'R XM+B\`""\'3KK_,EA/+A].=0``2.<#$"XO`!!'[`!((`MG-`@K``(`&V8H""L`, XM`0`;9R`@*P`$D*L`$"P`2H9G$B\&+RL`$"\K`!Q.NNWV3^\`#"938,@O!TZZ; XM!"A83TS?",!.=0``2.<W$"XO`!PF;P`@+"\`)$JL`D!G!$ZZ`X!"K`(H(@<D_ XM"R8&+&P$;$ZN_]`J`'#_NH!F#DZN_WPI0`(H<`4I0`1H(`5,WPCL3G4``$CG; XM/P`N+P`<+"\`("HO`"1*K`)`9P1.N@,T0JP"*"`%4X`B!R0&)@`L;`1L3J[_> XMOB@`</^X@&8.3J[_?"E``BAP%BE`!&@@!0R``````F<6#(`````!9PA*@&88: XM(`9@%"`$T(9@#B('=`!V`"QL!&Q.KO^^3-\`_$YU``!(YS<0+B\`'"9O`"`L0 XM+P`D2JP"0&<$3KH"N$*L`B@B!R0+)@8L;`1L3J[_UBH`</^Z@&8.3J[_?"E`4 XM`BAP!2E`!&@@!4S?".Q.=0``+P<N+P`(2JP"0&<$3KH"=B('+&P$;$ZN_]QPQ XM`"X?3G5(YS``)``F`4A"2$/$P<;`P,'40TA"0D+0@DS?``Q.=4J`:@``'D2`B XM2H%J```,1(%A```@1(%.=6$``!A$@$2!3G5*@6H```Q$@6$```9$@$YU+P)(! XM030!9@``(DA`2$%(0C0`9P``!H3!,`)(0#0`A,$P`DA",@(D'TYU+P-V$`Q!M XM`(!D```&X9E10PQ!"`!D```&Z9E90PQ!(`!D```&Y9E50TI!:P``!N.94T,T$ XM`.:H2$)"0N:J2$.`P38`,`(T`TA!Q,&0@F0```A30]"!9/YR`#(#2$/GN$A`% XMP4$F'R0?3G5.5?^>2.<S,GX`(&P"6!XH__]P3[Z`;P(N`"`'0^W_KV`"$MA3) XM@&3Z0C5XKY/)+'@`!$ZN_MHF0$JK`*QG3"`K`*SE@"1`+"H`.$J&9@0L*P"@- XM2H9G-"(&0?H`LB0(=@LL;`1L3J[_T"!'4H<@"!N\``H(KR(&0>W_KR0()@<L) XM;`1L3J[_T'#_8$Y*K`1D9A)#^@"&<``L>``$3J[]V"E`!&1![?^O*4@`V$AX\ XM`#Q(>`#Z<``O`"\`2&P`]$AL`.!(;`#,0J=.N@$(3^\`(%.`9P1P_V`"<`!,C XMWTS,3EU.=2HJ(%5S97(@06)O<G0@4F5Q=65S=&5D("HJ``!#3TY424Y510``[ XM04)/4E0`*BHJ($)R96%K.B``:6YT=6ET:6]N+FQI8G)A<GD`````````````; XM```````O!RXO``AP`"E``BA*AVLBOJP`,&P<(`?G@$'L`F!*L`@`9PX@!^>`` XM0>P"8-'`(`A@"'`)*4`$:'``+A].=0``````````<&%(YP$"<``B/```,``LK XM>``$3J[^SBX``H<``#``2H=F!'``8"!*K`)`9Q@@;`)`3I!*@&8$<`!@#$AX) XM`!1.N@!&6$\@!TS?0(!.=6&T3G4``$CG,#(L;`1D(&\`&")O`!PD;P`@)F\`C XM)"`O`"@B+P`L)"\`,"8O`#1.KOZD3-],#$YU``!(YP<`+B\`$"`L`#!3@"P`F XM2D9K,"`&2,#G@$'L`F`J,`@`2@5G&@@%``)F%"`&2,#G@$'L`F`O,`@$3KK\= XMO%A/4T9@S"\'3KKGWEA/3-\`X$YU``!(YP`R)FP$<"`+9Q0D4R)+("L`""QX( XM``1.KO\N)DI@Z)'(*4@$="E(!'!,WTP`3G5(YP$R+B\`%'`,WH`@!W(`+'@`P XM!$ZN_SHF0"`+9@1P`&`Z)T<`"$7L!'`@:@`$)T@`!)'()HA*DF8")(M*J@`$, XM9P8B:@`$(HLE2P`$2JP`-&8$*4L`-$'K``P@"$S?3(!.=0``````````````T XM````+PXL>0```DA.KO]\+%].=2\.+'D```)(3J[_=BQ?3G4O#BQY```"2")O9 XM``@@+P`,3J[]V"Q?3G4```/L````!0````(``!HP```:(```&A`````,````R XM!@````````/R0``#Z0````````/R0``#Z@```(0E.&Q8"@!E>&5C+FQI8G)A5 XM<GD``$U1.B`E9"!B>71E<R!Q=6%R86YT:6YE9"X*```````H````````````/ XM``````````````````!J````````````````````````````````````````J XM````C```````````````````````````````````````````````````````, XM````````````````````````````````````@`````0`__\````.``X`````> XM```7]`````#__P````0`!```````````````N/__````!``$````````&!``W XM````__\````$``0````````8&@``````("`@("`@("`@*"@H*"@@("`@("`@` XM("`@("`@("`@("!($!`0$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!Q XM@8&!@8$!`0$!`0$!`0$!`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("5 XM`@("`@("`@("`@("$!`0$"`@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@@ XM("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!8 XM`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("< XM`@("`@(0$!`0(````````@````/L`````P````````$`````[````,0````#2 X8`````@```-P```!J````2`````````/R% X`` Xend Xsize 7404 SHAR_EOF echo "End of archive 1 (of 1)" # if you want to concatenate archives, remove anything after this line exit