[comp.sources.amiga] v90i282: SnoopDos 1.00 - Monitors calls to AmigaDOS functions, Part01/02

amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (10/15/90)

Submitted-by: Eddy Carroll <ECARROLL@vax1.tcd.ie>
Posting-number: Volume 90, Issue 282
Archive-name: util/snoopdos-1.0/part01

[ uuencoded executable enclosed  ...tad ]

SnoopDos is a little utility that lets you see keep an eye on what other
programs are doing. Specifically, it displays details of any calls a program
makes to AmigaDOS's Open(), Lock(), LoadSeg(), Execute(), CurrentDir() and
DeleteFile() functions.

There are several uses for this. Any libraries, devices, or fonts that a
program tries to access will be displayed, which can be useful if the
program isn't overly generous with its error messages. Similarly, you can
see what special startup files a program looks for. Since environment
variables are stored as files in ENV:, you can also see what variables a
program tries to read when you run it. In general, SnoopDos is just a handy
utility to have around when things don't seem to be working quite right.
As an added bonus, SnoopDos works just fine under Workbench 2.0.

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  makefile res.s snoopdos.doc snoopdos.uu snoopglue.s
#   system.h tiny.a
# Wrapped by tadguy@abcfd20 on Sun Oct 14 15:07:01 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(799 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X#
X# Lattice LKM makefile, for Lattice C V5.04                           :ts=8
X#
X# SnoopDos (C) Copyright Eddy Carroll, May 1990
X#
X
XCFLAGS	= -cusq -j88i -ms -v # -d5
XBFLAGS	= sc sd nd map ram:map
X#BFLAGS	= addsym
XLIBS	= lib:lc.lib lib:amiga.lib
XASM	= lc:asm
X#START   = lib:c.o
XSTART	= tiny.o
X
X.c.o:
X	lc $(CFLAGS) -Hsystem.sym $*.c
X.a.o:
X	$(ASM) -isys:include/ -u $*.a	# Prefix all symbols with C-style _
X.s.o:
X	$(ASM) -isys:include/ $*.s	# Standard "pure" assembly
X.n.doc:
X	nro >$*.doc -ms:an $*.n
X.h.sym:
X	lc1 -ph -o$*.sym $*.h
X
X#
X# Makefile dependencies
X#
Xall: snoopdos
X
XOBJS	= tiny.o snoopdos.o snoopglue.o res.o
X
Xsnoopdos: $(OBJS)
X	blink from $(OBJS) to snoopdos $(BFLAGS) lib $(LIBS)
X
Xsystem.sym:	system.h
Xtiny.o:		tiny.a
Xsnoopdos.o:	snoopdos.c system.sym
Xsnoopglue.o:	snoopglue.s
Xres.o:		res.s
END_OF_FILE
if test 799 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'res.s' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'res.s'\"
else
echo shar: Extracting \"'res.s'\" \(6516 characters\)
sed "s/^X//" >'res.s' <<'END_OF_FILE'
X*:ts=8
X*****************************************************************************
X*                                                                           *
X* RES.S                                    (C) Copyright Eddy Carroll 1989  *
X*                                                                           *
X* This module allows you to make a duplicate copy of your current process.  *
X* In fact, both processes actually share the same code. However, the        *
X* seglist pointer of the current process is modified so that when the       *
X* process terminates, the memory doesn't get freed (if it did, the new      *
X* process would suddenly find itself deallocated. Hello guru...)            *
X* This code only works when called from CLI processes.                      *
X*                                                                           *
X* The parameters passed are similar to those for CreateProc(), with the     *
X* difference that instead of passing a BPTR to a seglist, you pass the      *
X* address of the function the new process should start executing at.        *
X*                                                                           *
X* When the new process returns from this function, it will be removed from  *
X* the system, and its memory (finally) deallocated.                         *
X*                                                                           *
X* The typical use for a function like this is to allow a program to detach  *
X* itself from a CLI (completely, with no trailing console handles etc.)     *
X* when it is run. This is a convenient feature for the user, if the program *
X* is of the sort designed to sit in the background the whole time, rather   *
X* than do something immediately, then exit.                                 *
X*                                                                           *
X* Lattice provide cback.o which at first glance would seem to provide a     *
X* similar solution. However, cback.o makes it difficult to print error      *
X* messages to the console if there is an error on the command line - by     *
X* the time you spot the error, the CLI prompt has already been printed      *
X* and your error message is printed after it. This looks very messy.        *
X* Res avoids this problem by not spawning the background process until      *
X* after the error checking has been done.                                   *
X*                                                                           *
X* From C, you call it as follows:                                           *
X*                                                                           *
X* pid = res(name,pri,func,stacksize)                                        *
X*                                                                           *
X* name         - pointer to null terminated string                          *
X* pri          - integer, priority of the new process                       *
X* func         - pointer to the function for new process to call            *
X* stacksize    - integer, size of the stack for the new process             *
X*                                                                           *
X* pid          - Process ID of new process, or 0 if none created            *
X*                                                                           *
X*****************************************************************************
X
X	INCLUDE "exec/types.i"
X        INCLUDE "exec/alerts.i"
X        INCLUDE "exec/nodes.i"
X        INCLUDE "exec/lists.i"
X        INCLUDE "exec/ports.i"
X        INCLUDE "exec/libraries.i"
X        INCLUDE "exec/tasks.i"
X        INCLUDE "libraries/dos.i"
X        INCLUDE "libraries/dosextens.i"
X        INCLUDE "workbench/startup.i"
X        INCLUDE "exec/funcdef.i"
X        INCLUDE "exec/exec_lib.i"
X        INCLUDE "libraries/dos_lib.i"
X
X	xref	_exit
X	xref	_DOSBase
X	xdef	_res
X
XAbsExecBase	equ	4
Xsegsize		equ	36		; Size of fake seg. (code = 28 bytes)
X
X        csect   text,0,0,1,2		* xref's after this are 16-bit reloc
X
X
Xcallsys macro
X        CALLLIB _LVO\1
X	endm
X
X_res:
X	movem.l	d2-d4/a2/a3/a6,-(a7)	; Save registers
X	move.l	AbsExecBase.w,a6	; Get base of Exec library
X	moveq	#0,d1			; Any sort of memory will do
X	moveq	#segsize,d0		; Get size of fake segment
X	callsys	AllocMem		; Grab some memory
X	tst.l	d0			; Did we get any?
X	beq	fatal			; If not, abort immediately!
X	move.l	d0,a3			; Save pointer to memory
X	sub.l	a1,a1			; NULL pointer indicates our process
X	callsys	FindTask		; Get pointer to our process block
X	move.l	d0,a2			; Save it
X	move.l	pr_CLI(A2),a0		; Get BPTR to our process's segarray
X	add.l	a0,a0			; Convert BPTR to address
X	add.l	a0,a0			; 
X	move.l	cli_Module(a0),4(a3)	; Make fake segment point to our code
X	clr.l	cli_Module(a0)		; Remove process seg. from CLI seglist
X	move.l	#segsize,(a3)		; Set size of fake seglist
X	lea.l	8(a3),a2		; Get pointer to first code byte
X
X;
X; Now a tiny machine code program is constructed. It looks like this:
X;
X;	move.l	#$xxxxxx,A4	; Initialise A4
X;	jsr	$xxxxxx		; Call user program
X;	move.l	#$xxxxxx,A6	; Load DOSbase into A6
X;	move.l	#$xxxxxx,d1	; Get BPTR to this segment 
X;	jmp	UnLoadSeg(A6)	; Unload our process from memory
X;
X; It's built "on the fly" so to speak, to keep code size down, and also
X; because it's a convenient way of initialising all the variables.
X; Note that a potential problem exists if DOSBase should somehow alter or
X; disappear. We'll assume it will remain relatively stable for the next
X; few years anyway :-)
X;
X
X	move.l	_DOSBase,a6		; Prepare for DOS call
X	move.w	#$287C,(a2)+		; Store MOVE.L $xxxxxx,A4 instruction
X	move.l	a4,(a2)+		; Output value of A4 to initialise to
X	move.w	#$4EB9,(a2)+		; Store JSR $xxxxxx
X	move.l	36(a7),(a2)+		; followed by address of user function
X	move.w	#$2C7C,(a2)+		; Store MOVE.L $xxxxxx,A6 instruction
X	move.l	a6,(a2)+		; followeds by current DOSbase
X;
X	lea	4(a3),a3		; Now get seglist ptr to fake segment
X	move.l	a3,d3			; and convert it to BPTR
X	lsr.l	#2,d3			; D3 now has seglist ptr to fake seg
X	move.w	#$223C,(a2)+		; Store MOVE.L $xxxxxx,D1 instruction
X	move.l	d3,(a2)+		; Followed by BPTR to the segment
X	move.l	#$4EEEFF64,(a2)+	; Store JMP UnLoadSeg(A6)
X;
X	move.l	28(A7),d1		; Get pointer to name
X	move.l	32(A7),d2		; Get process priority
X	move.l	40(A7),d4		; Get stacksize
X	callsys	CreateProc		; Create new process
X	movem.l	(a7)+,d2-d4/a2/a3/a6	; Pop registers
X	rts				; Return
Xfatal:
X	moveq	#120,d0			; Set error exit code
X	jmp	_exit			; And exit
X
X	end
END_OF_FILE
if test 6516 -ne `wc -c <'res.s'`; then
    echo shar: \"'res.s'\" unpacked with wrong size!
fi
# end of 'res.s'
fi
if test -f 'snoopdos.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'snoopdos.doc'\"
else
echo shar: Extracting \"'snoopdos.doc'\" \(14548 characters\)
sed "s/^X//" >'snoopdos.doc' <<'END_OF_FILE'
X
X                SnoopDos V1.0 -- Monitors AmigaDOS function calls
X
X        (C) Copyright Eddy Carroll, September 1990. Freely Distributable.
X
X
XINTRODUCTION
X
X    Have you ever wondered why a particular program won't seem to run?
X    It could be looking for some special files which you've forgotten to
X    install in the appropriate place. SnoopDos was designed to let you
X    resolve situations like this, though it's probably useful for other
X    things too.
X
X    For those who don't like long instruction files, simply run SnoopDos
X    with no options, then run a few application programs and look at the
X    output displayed in SnoopDos's window. Interesting, eh? For those who'd
X    like a more detailed explanation, read on...
X
X    When you start SnoopDos, it opens a console window. In this window
X    appears details of all calls made by any program on the system to the
X    CurrentDir(), DeleteFile, Execute(), LoadSeg(), Lock() and Open()
X    functions in the AmigaDOS library. The exception (as usual) is any
X    program written in BCPL; this includes most of the commands in the C:
X    directory.
X
X    SnoopDos will tell you about all attempts to load libraries, devices
X    and fonts. It will also tell you if a program looks for a specific file
X    (for example in S:) or a specific disk volume or directory. This can be
X    very useful when you're playing with new software which may require
X    certain fonts or other support files.
X
X    An unexpected bonus is that since AmigaDOS environment variables are
X    stored as files, SnoopDos will tell you the names of any environment
X    variables a program tries to read; if you see references to ENV:<name>
X    in the SnoopDos window, then a program is trying to access an environment
X    variable called <name>.
X
X
XUSAGE
X
X    When you start SnoopDos, it automatically detaches itself from the CLI
X    and runs in the background. You can specify a number of options on the
X    command line, either at this time or later on by running SnoopDos again.
X    Each option can be given in lower case or upper case to respectively
X    enable or disable that setting. Alternatively, you can follow the option
X    by `1' or `0' which has the same effect. So, `-d' and `-d1' both enable
X    the "Monitor DeleteFile()" option, whereas `-d' and `-d0' both disable
X    that option. Without further ado, here's an explanation of each setting:
X
X    -a  Normally, SnoopDos uses different colours when displaying messages,
X        to allow events to be easily distinguished from each other. You can
X        force SnoopDos not to use any colour by disabling this option. This
X        can be useful if you only have a 2-colour workbench. If SnoopDos is
X        sending its output to a file, it turns off this option by default
X        (but you can turn it back on again if you like).
X
X    -c  When this option is enabled, SnoopDos prints details of all calls
X        to the CurrentDir() function. A program calls CurrentDir() when it
X        wants to change its current directory to somewhere else. Note that
X        no result is displayed for this function, since AmigaDOS does not
X        allow for the possibility of it ever failing.
X
X    -d  This option allows you to see all calls to the DeleteFile() function,
X        which is called whenever a program wants to delete a file. This can
X        be useful with unknown programs, to make sure that they don't do
X        anything nasty (though in fairness, there are much more effective
X        ways for a rogue program to do damage than by deleting a few files).
X
X    -f  When enabled, this option causes SnoopDos to print out the full
X        path names for files. For example, if a program's current directory
X        is SYS:TOOLS and it tries to open a file called FOO, then the
X        filename would be displayed as SYS:TOOLS/FOO. Normally, it would
X        just be displayed as FOO. Filenames which are so expanded are
X        prefixed by a `>' character. Filenames which already included a full
X        path specification don't have this prefix. This allows you to
X        determine if the calling program specified the full path or not.
X
X    -g  This option enables or disables the monitoring of AmigaDOS's
X        LoadSeg() function. This is used to read in a binary loadfile and is
X        most commonly used for loading in libraries, devices, fonts and
X        handlers, and by third-party DOS shells to load in external commands.
X
X    -l  This option enables or disables the monitoring of AmigaDOS's Lock()
X        function. Programs usually call this function to see if a particular
X        file exists, or as a prelude to some more sophisticated operation on
X        the file.
X
X    -m  This option allows SnoopDos to be activated or deactivated while
X        still leaving it running. It is included merely for completeness;
X        a much easier way to achieve the same affect is to type CTRL-D or
X        CTRL-E in the SnoopDos window.
X
X    -o  This option enables or disables the monitoring of AmigaDOS's Open()
X        function. Whenever a program wants to open a file for reading or
X        writing, it calls this function.
X
X    -w  If several tasks try to call a particular DOS function at the same
X        time, SnoopDos can only handle them one at a time. Normally, what
X        will happen is that the other tasks speed on without waiting for
X        SnoopDos and you see a warning message saying that some function
X        calls were missed (this doesn't happen very often anyway). When the
X        `-w' option is enabled however, SnoopDos will make all the
X        different tasks queue up and take their turn.
X
X        There is one important consequence of this: if a program tries to
X        access a file on a volume not currently mounted (causing AmigaDOS to
X        display a "Please insert volume xyzzy" requester), then SnoopDos will
X        print out the details about the file requested but not whether the
X        request succeeded or not; it can't do this until you respond to the
X        requester. In the meantime, other tasks may now be trying to call
X        AmigaDOS. For example, if you might try to pop open a new CLI with
X        Dmouse or PopCLI, so that you can do an ASSIGN to fake the requested
X        volume. All these tasks will have to wait until the original DOS
X        call has been completed.
X
X        Since this can confuse things (though only for the user), the option
X        is disabled by default. You should only need it if you have to be
X        absolutely sure of catching every action made by several tasks.
X
X    -x  This option enables or disables monitoring of Execute() calls.
X        Unlike most other DOS function calls, the return value from the
X        Execute() is NOT displayed; this is because when an Execute suceeds,
X        the command being executed will most likely making AmigaDOS calls of
X        of its own and if SnoopDos was waiting for Execute() to return, it
X        would skip printing these out.
X
X        Some forms of Execute() will appear to have no associated command
X        to execute. This is normal, and occurs when a program redirects
X        command input from another file.
X
X
X    By default, Snoopdos operates as if you had started it with:
X
X        SnoopDos -a1 -c1 -d1 -f0 -g1 -l0 -m1 -o1 -w0 -x1
X
X    or for those who prefer to use the other command format:
X
X        SnoopDos -a -c -d -F -g -L -m -o -w -x
X
X    There are four additional options as well, which cause immediate
X    actions to be performed. These are:
X
X    -h  Prints out a help screen for SnoopDos. Actually, typing any
X        unrecognised garbage after SnoopDos prints the help screen.
X
X    -q  Sends a message to the version of SnoopDos currently running telling
X        it to remove itself. This is one way to quit SnoopDos, the other
X        way being to type CTRL-C in its window.
X
X    -r  Prints out a brief report giving all the current settings for
X        SnoopDos (eagle-eyed users may spot a striking resemblance between
X        this display and the middle section of the help screen :-). Note
X        that all other command line options are ignored when you use -r.
X
X    -z  Allows you to specify an alternative output file for SnoopDos to
X        send messages to. The filename can follow immediately after the -z,
X        or you can leave a space if you like.
X
X        There are several uses for this function. First of all, you can use
X        it to change the location of the SnoopDos window when it opens, by
X        specifying a filename like -zCON:0/0/640/60/SnoopDos) (for a very
X        short window). You should always make sure the window is at least 77
X        columns wide or the output will look pretty messed up.
X
X        If you specify -zSER: or -zAUX: then SnoopDos will send output to
X        the serial port at the baud rate specified in Preferences. AUX: is
X        slightly preferable to SER: since SnoopDos will then recognise the
X        CTRL-C, CTRL-D and CTRL-E characters when typed on the remote
X        terminal. If you are using a colour ANSI terminal, you may like to
X        re-enable colour by specifying `-a' in conjunction with this option.
X
X        Finally, you can of course redirect output to a normal AmigaDOS file.
X        You would only want to do this if you wanted to keep a permanent
X        record of what went on on your system. This could be useful if you
X        allow remote access to your Amiga and want a record of what people
X        do on your system.
X
X
XTHE SNOOPDOS WINDOW
X
X    The SnoopDos window is divided into a number of columns, as follows:
X
X    Process name
X        The name of the process (or CLI command) that is executing the
X        DOS call in question. If the DOS call is nested (see Res. below)
X        then the process name will be prefixed by '> '.
X
X    Func
X        The function being executed (Open, Lock or Load). Open is printed
X        in white, Lock in orange and Load in black, to allow rows to be
X        quickly identifed at a glance. (Of course, if you've changed your
X        Preferences, the actual colours may be different.) Other values
X        which can appear here are Exec (for Execute), CD (for CurrentDir)
X        and Del (for DeleteFile).
X
X    Filename
X        The name of the file being accessed. Remember that when the `-f'
X        option is enabled, this will be prefixed by a `>' character if the
X        filename displayed was expanded by SnoopDos to include the current
X        directory of the calling process.
X
X    Mode
X        For Open(), this is OLD if an existing file is being opened or NEW
X        if a new file is being opened. For Lock(), this is SHAR if the lock
X        is a shared lock (i.e. several processes can access the same file) or
X        EXCL if it is an exclusive lock (only this process can access the
X        file). It remains empty for LoadSeg().
X
X    Res.
X        The result of the DOS call. This is either `Okay' in white or
X        `Fail' in orange. In general, you learn much more from the `Fail'
X        entries (i.e. the things the program tried to find but couldn't).
X
X        Occasionally, you may see a `>>>>' appearing here. This happens if
X        some other program has also patched DOS library in such a way that
X        the function currently being called calls another DOS function
X        itself. One such program is Rez, which tries to open a program file
X        for reading if you LoadSeg() it. In this case, the `>>>>' indicates
X        that DOS calls are being nested. The DOS calls which are nested
X        will have the associated process name prefixed by `> ' when they
X        are displayed. `> (Done)' is displayed when the top level DOS
X        function exits, and the exit status is displayed on the same
X        line in the Res. column as normal.
X
X    You can type several keys into the SnoopDos window. CTRL-C will terminate
X    SnoopDos. CTRL-D will disable monitoring temporarily (and print a brief
X    message to that effect); CTRL-E enables it again. Pressing Space or any
X    other key will pause the output to the window, as in a CLI window. Press
X    BackSpace to continue. Note that if you have the `-w' option enabled and
X    you pause the output, all functions for which monitoring is enabled will
X    cause the calling process to go to sleep until you restart output again.
X
X    When SnoopDos wants to quit, it makes sure that nobody else has patched
X    the DOS library after it. If something has, SnoopDos will refuse to exit
X    immediately. Instead, it will check approximately every 5 seconds to
X    see if it is safe to exit and as soon as it can, it will.
X
X
XHISTORY
X
X    Version 0.9, May 28th 1990.
X
X        Initial Beta release. No doubt people will find lots of bugs.
X
X    Version 0.91, May 29th 1990.
X
X        Silly bug meant Snoopdos couldn't open its console window unless
X        Conman was installed. Now fixed.
X
X        Improved the way DOS library is patched to make it somewhat more
X        robust (it now works properly with UnixDirs).
X
X    Version 0.92, May 31st 1990.
X
X        Strange bug seemed to manifest itself when Rez was used; the first
X        time a resident program was loaded, the display got messed up. Turns
X        out that Rez calls Open() from within LoadSeg(). Such nesting of
X        DOS calls is now indicated by prefixing the process name printed
X        for any nested operations with a '>'. When the nesting is completed,
X        '> Done' is displayed.
X
X    Version 0.93, June 2nd 1990.
X
X        Added -X option to monitor Execute() calls and reworked assembly
X        language glue a bit to make it easier to modify in future.
X
X    Version 1.00, 9th September 1990.
X
X        First public release. After unexpectedly being sent to the US for
X        the summer (new job), I finally got around to tidying it up.
X        New features include monitoring of DeleteFile() and CurrentDir(),
X        support for alternative devices/files (such as the serial port),
X        colour now optional, a few other cosmetic changes.
X
X
XAUTHOR
X
X    Eddy Carroll
X
X    Email:     ecarroll@vax1.tcd.ie
X    Phone:     +353-1-874540
X    Snailmail: The Old Rectory, Delgany, Co. Wicklow, Ireland.
X
X
XDISTRIBUTION
X
X    SnoopDos may be freely distributed as long as no charge is made other
X    than to cover time and copying costs. If you want to include SnoopDos
X    as part of a commercial package (somehow I doubt it but it never hurts
X    to mention :-) then contact the author listed above. Fred Fish is
X    specifically given permission to include SnoopDos in his fine disk
X    collection.
END_OF_FILE
if test 14548 -ne `wc -c <'snoopdos.doc'`; then
    echo shar: \"'snoopdos.doc'\" unpacked with wrong size!
fi
# end of 'snoopdos.doc'
fi
if test -f 'snoopdos.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'snoopdos.uu'\"
else
echo shar: Extracting \"'snoopdos.uu'\" \(16885 characters\)
sed "s/^X//" >'snoopdos.uu' <<'END_OF_FILE'
Xbegin 644 snoopdos
XM```#\P`````````"``````````$```K"```"6@```^D```K"2.=^_DOO`#0D6
XM2"0`2?D`````+'@`!"E.`!`I3P`8D\E.KO[:)D`@#9"M``0&@````(`I0``$D
XM0^P`)'``3J[]V"E``!QF```(<&1@``#H(&L`K-'(T<@B:``0T\G3R2`"<@`2$
XM&2E)`"#0@5*`0F=2@`)`__Z?P%6`0G<(`"`"4X#4@1^R```@`%."4<C_]A^\V
XM`"`@`%."'[$@`"``4<K_^")/G_P```&0)$\F2G0`831E$F?Z0>G__V$<82AFL
XM_$(I__]@ZB!)80YA&F3\0BG__V$29OQGV"3(4D(,0@!D8R)P;F!0$!EG)@P`F
XM`")G%@P``"!G"@P```EG!`P```H"/``>3G4`/``!`CP`^TYU+PLO`D?Y```"7
XM('(`(#P```'28`(FP5'(__Q.NA?@<`!@!"`O``0O`"QX``0B;``<3J[^8B`?@
XM+FP`&$S??WY.=0``+P<N+P`(("P`]%*L`/1*@&9"2JP%JF<*+RP%JDZZ(\Y8-
XM3TJL!;)G#"(L!;(L;``<3J[_W$JL!;9G#"(L!;8L;``<3J[_W'#_OH!G""\')
XM3KK_D%A/+A].=5!R;V-E<W,@;F%M92`@("`@("`@("!&=6YC("!&:6QE;F%MV
XM92`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@36]D92!297,N#0HMF
XM+2TM+2TM+2TM+2T@("`@("`@("`@+2TM+2`@+2TM+2TM+2T@("`@("`@("`@+
XM("`@("`@("`@("`@("`@("`@("`@("TM+2T@+2TM+0T*``!/3$0@``!.15<@H
XM```;6S,S;4Y%5QM;,&T@`%(O5R```!M;,S)M4B]7&ULP;2``/S\_(```4TA!J
XM4@``15A#3```&ULS,VU%6$-,&ULP;0`_/S\_``!/:V%Y#0H``$9A:6P-"@```
XM&ULS,VU&86EL&ULP;0T*`#X`&ULS,VT^&ULP;0``/B`H1&]N92D``%=A<FYI]
XM;F<Z($UI<W-E9``;6S,S;5=A<FYI;F<Z&ULP;2!-:7-S960``#X^/CX-"@``4
XM3W!E;@``3&]C:P``&ULS,VU,;V-K&ULP;0!,;V%D```;6S,R;4QO860;6S!M;
XM`$5X96,``!M;,S)M17AE8QM;,&T`0T0@(```1&5L(```&ULS,VU$96P;6S!M2
XM(`!204T`.BXN+B\`*@!3;F]O<$1O<R!0;W)T`%-N;V]P1&]S.B!#86XG="!A4
XM;&QO8V%T92!M97-S86=E('!O<G0N"@!3;F]O<$1O<SH@0V%N)W0@86QL;V-A.
XM=&4@96YO=6=H('-I9VYA;',N"@!3;F]O<$1O<SH@0V%N)W0@;W!E;B!F:6QE6
XM("5S(&9O<B!O=71P=70N"@`-"E-N;V]P1&]S(%8Q+C`P("A#*2!#;W!Y<FEG:
XM:'0@161D>2!#87)R;VQL+"!397!T(#$Y.3`N($9R965L>2!D:7-T<FEB=71A<
XM8FQE+@T*#0H`0T]..C`O,"\V-#`O,3(P+U-N;V]P1&]S(%8Q+C`P("A#*2!#S
XM;W!Y<FEG:'0@161D>2!#87)R;VQL+"!397!T(#$Y.3`N($9R965L>2!D:7-TO
XM<FEB=71A8FQE+@!3;F]O<$1O<SH@0V%N)W0@;W!E;B!D:7-P;&%Y('=I;F1O-
XM=RX*``I4>7!E($-44DPM12]#5%),+40@=&\@96YA8FQE+V1I<V%B;&4@<VYOT
XM;W!I;F<N(%1Y<&4@0U123"U#('1O(&5X:70N"@H```I3;F]O<&EN9R!N;W<@<
XM9&ES86)L960[('1Y<&4@0U123"U%('1O(&5N86)L92!I="!A9V%I;BX-"@T*?
XM`%-N;V]P:6YG(&YO=R!E;F%B;&5D.R!T>7!E($-44DPM1"!T;R!D:7-A8FQE&
XM(&ET(&%G86EN+@T*#0HE<P``/B`E<P``)2TR,7,@)7,@)7,E+3,Y<R`E<R``H
XM`"``)2TR,7,@)7,@)7,E+30T<R``)2TR,7,@)7,@("5S#0H``"4M-S-S`"5S;
XM(&%N($]P96XH*0T*```E<R!A($QO8VLH*0T*`"5S(&$@3&]A9%-E9R@I#0H`S
XM`"5S(&%N($5X96-U=&4H*0T*`"5S(&$@0W5R<F5N=$1I<B@I#0H`)7,@82!$"
XM96QE=&5&:6QE*"D-"@`-"E-O;65O;F4@96QS92!H87,@<&%T8VAE9"!D;W,N6
XM;&EB<F%R>2!S;R!))VQL(&AA=F4@=&\@=V%I="!U;G1I;"!T:&5Y('%U:70NR
XM#0H``%1H:7,@=VEN9&]W('=I;&P@8VQO<V4@<VAO<G1L>2!T:&]U9V@@=&\@\
XM<W1O<"!I="!F<F]M(&%N;F]Y:6YG('EO=2X-"@`-"E-N;V]P1&]S('1E<FUII
XM;F%T960N#0H``"UZ(&UU<W0@8F4@9F]L;&]W960@8GD@82!F:6QE;F%M92X@O
XM5'EP92!3;F]O<$1O<R`M:"!F;W(@:&5L<"X*``!5;G)E8V]G;FES960@;W!TM
XM:6]N("5S+B!4>7!E(%-N;V]P9&]S("UH(&9O<B!H96QP+@H`4VYO;W!$;W,@5
XM5C$N,#`@*$,I($-O<'ER:6=H="!%9&1Y($-A<G)O;&PL(%-E<'0@,3DY,"X@@
XM1G)E96QY(&1I<W1R:6)U=&%B;&4N"@I3;F]O<$1O<R!M;VYI=&]R<R!C86QL#
XM<R!M861E('1O('9A<FEO=7,@06UI9V%$3U,@9G5N8W1I;VYS(&)Y(&%L;"!P8
XM<F]C97-S97,*;VX@=&AE('-Y<W1E;2X@5&AE(&9O;&QO=VEN9R!O<'1I;VYS`
XM(&%R92!A=F%I;&%B;&4N(%5S92`M>#$@;W(@:G5S="`M>"!T;PIE;F%B;&4@*
XM86X@;W!T:6]N+"`M6"!O<B`M>#`@=&\@9&ES86)L92!T:&%T(&]P=&EO;BX@>
XM0W5R<F5N="!S971T:6YG<R!I;B`H+2DN"@H`0W5R<F5N="!3;F]O<$1O<R!S6
XM971T:6YG<SH*"@``("`@("UA("!5<V4@04Y322!C;VQO=7(@<V5Q=65N8V5SR
XM("`@("`@("`@("`@("`@("`@("`@)7,*`"AO;BD``"AO9F8I`"`@("`M8R`@,
XM36]N:71O<B!#=7)R96YT1&ER*"D@8V%L;',@("`@("`@("`@("`@("`@("`@J
XM("5S"@`@("`@+60@($UO;FET;W(@1&5L971E1FEL92@I(&-A;&QS("`@("`@N
XM("`@("`@("`@("`@("`E<PH`("`@("UF("!$:7-P;&%Y(&9U;&P@9FEL96YAM
XM;64@<&%T:',@("`@("`@("`@("`@("`@("`@)7,*`"`@("`M9R`@36]N:71O>
XM<B!,;V%D4V5G*"D@8V%L;',@("`@("`@("`@("`@("`@("`@("`@("5S"@`@3
XM("`@+6P@($UO;FET;W(@3&]C:R@I(&-A;&QS("`@("`@("`@("`@("`@("`@*
XM("`@("`@("`E<PH`("`@("UM("!';&]B86QL>2!E;F%B;&4O9&ES86)L92!M)
XM;VYI=&]R:6YG("`@("`@("`@("`@)7,*`"`@("`M;R`@36]N:71O<B!/<&5NQ
XM*"D@8V%L;',@("`@("`@("`@("`@("`@("`@("`@("`@("5S"@`@("`@+7<@F
XM($1I<W!L87D@86QL(&%C=&EV:71Y+"!S;&5E<&EN9R!I9B!N96-E<W-A<GD@[
XM("`E<PH`("`@("UX("!-;VYI=&]R($5X96-U=&4H*2!C86QL<R`@("`@("`@B
XM("`@("`@("`@("`@("`@)7,*``H@("`@+6@@(%!R:6YT(&]U="!T:&ES(&AEK
XM;'`@;65S<V%G90H@("`@+7$@(%1E;&P@4VYO;W!$;W,@=&\@<75I=`H@("`@?
XM+7(@(%)E<&]R="!C=7)R96YT(%-N;V]P1&]S('-E='1I;F=S"B`@("`M>B4@:
XM3W5T<'5T('1O(&9I;&4@)2`H92YG+B`M>D-/3CHP+S`O-C0P+S$P,"]3;F]O0
XM<$1O<R!O<B`M>E-%4CHI"@H``%1H97)E(&ES(&YO(&)A8VMG<F]U;F0@4VYO`
XM;W!$;W,@<')O8V5S<R!T;R!T96QL('1O('%U:70A"@!3;F]O<$1O<P``0V]UE
XM;&1N)W0@<W!A=VX@8F%C:V=R;W5N9"!3;F]O<$1O<R!T87-K+@H`3E4``$CG4
XM/Q`F;0`(+BT`#"PM`!`J+0`4*"T`&"\M`"`O+0`<+P0O!2\&+P<O"TAL!B).\
XMNABJ+&P`'$ZN_\1![`8B(DA*&6;\4XF3R"(`)`@F"4ZN_]!,[0C\_^1.74YU`
XM3E4``$CG/Q`N+0`()FT`#"PM`!`J+0`4*"T`&"\M`"0O+0`@+RT`'"\$+P4ON
XM!B\+2&P&(DZZ&$A![`8B(DA*&6;\4XF3R"(')`@F"2QL`!Q.KO_03.T(_/_DB
XM3EU.=4Y5_]1(YP,0+BT`""PM``PF;0`0D\DL>``$3J[^VB!`0^@`7!M\``7_K
XMY#M\`"3_[BM)_^HK0/_P*T?_]"M&__@K2__\*T#_V"M)_]0@;`6F0^W_W$ZNH
XM_I(@;?_43J[^@"!M_]1.KOZ,3-\(P$Y=3G5.5?[02.<W,"XM``B3R2QX``1.M
XMKO[:($`K:`"X__@L/````2M#[?[H(@D"0?_\0JW^W'3_(4(`N"M`__PK0?[@"
XM(@<L;``<3J[_H"H`0>P"($(P:``B!20M_N`L;``<3J[_FDJ`9@12K?[<($)0I
XMB"M(_^Q*$&8(0_KUF"M)_^P@;?_L2AAF_%.(D>W_["`((@:2@"P!4X8K0/[8`
XM(@5.KO\N*T#^U"(%3J[_IBHM_M1![`(@T<8O+?[8+RW_["\(3KH5LD_O``Q*W
XMA6<4(`8B+?[8T(%![`(@$;P`+P@`8!`@!M"M_MA![`(@$;P`.@@`2H5F`/]B,
XM(&W__"%M__@`N$JM_MQG6B`'Y8`@0"(H`!#E@2)!)"D`*.6")$)'Z@`!=@`6F
XM$B\#+PM(;`(@*T#^V"M!_M0K0O[03KH5.G``(&W^T!`00>P"($(P``!(>O3(/
XM2&P"($ZZ%4)![`(@(`A@"$'L`B#1QB`(3.T,[/ZT3EU.=4Y5__!(YP\P)FT`&
XM""XM``PD;0`0*TK__'H`($I#^O2,$!BP&6842@!F]F8.($HB2Q+89OQP`&``9
XM`+0O!V$`_E)83R!`(DL2V&;\($M*&&;\4XB1RRP(2H5F*'`ZL!)F(GH!?`!*'
XM,V@`9PQP.K`S:`!G!%*&8.YP.K`S:`!F:%*&8&1P+[`29B8H!E6$2H1K%'`O3
XML#-(`&<,<#JP,T@`9P13A&#H2H1K/BP$4H9@.$J%9B8K2O_P(&W_\$H09QIP:
XM.K`09@X@;?_\(DL2V&;\<`!@&E*M__!@WB!+T<8B2A#99OQP`6`&4HI@`/]L\
XM3-\,\$Y=3G5.5?_(2.<W('X`?`%Z`'``+P!(>O.D*T#_\$ZZ%FY03RE`!:IFU
XM&$AZ\YXO+`6V80#\GDAX__]A`/%B8``)#BEL!:H%IG``(&P%IA`H``]R`20!:
XMX:(I0@E:</\L>``$3J[^MG(!)`'AHBE""4)P_TZN_K9R`20!X:(I0@E&</].:
XMKOZV<@$D`>&B*4()2G#_3J[^MG(!)`'AHBE""4YP_TZN_K9R`20!X:(I0@E2W
XM</].KOZV<@'AH2E!"59P_["L"4)G'+"L"49G%K"L"4IG$+"L"4YG"K"L"5)G&
XM!%*!9AA(>O,.+RP%MF$`^^9(>/__80#PJF``"%9*K`6Z9T9![`6^(@@D/```#
XM`^XL;``<3J[_XBE`!;)F'$AL!;Y(>O+\+RP%MF$`^ZI(>/__80#P;F``"!I(N
XM>O,.+RP%LF$`^Y)03V`R0?KS4"(()#P```/N+&P`'$ZN_^(I0`6R9AA(>O.2;
XM+RP%MF$`^VA(>/__80#P+&``!]@B+`6V+&P`'$ZN_]Q"K`6V2JP%NF8.2'KSO
XMBB\L!;)A`/LZ4$\O+``P+RP%LF$`^RQ![`5X+'@`!$ZN_=*3R4ZN_MHI0`6N?
XM3KH.UE!/2H=F``;"("P)6H"L"4*`K`E&@*P)2H"L"4Z`K`E2@*P)5@!`$```/
XM0"```$!``"QX``1.KO["*T#_[`@```QG`GX!"```#6<:2JP`[&<42'KS3B\LG
XM!;)A`/JV4$]P`"E``.P(+0`&_^YG($JL`.QF&B\L`#!(>O-D+RP%LF$`^I!/M
XM[P`,<`$I0`#L("W_["(L"4+"@&<&".T``/_S(BP)1L*`9P8([0`!__,B+`E*]
XMPH!G!@CM``+_\R(L"4["@&<&".T``__S(BP)4L*`9P8([0`$__,B+`E6PH!GO
XM!@CM``7_\\"L"5IG``3D(&P%IBQX``1.KOZ,*T#_Z$J`9P`$SB)`(&D`%"MH<
XM``K_Y"(H`*SE@2MH`)C_W"M!_^!*AF8\)"D`&'8#M(-G&'8%M(-G$G8'M(-GF
XM#'8*M(-G!G8+M(-F&GH!)"P`\.6"0>P`E"\P*``O+`6R80#YME!/2JW_X&=HX
XM(&W_X$JH`#QG7B`H`!#E@$CM``'_S"!`$A!T`+("8VA#Z``!<``0`2\`+PE(N
XM;`1Z3KH0ND_O``QP`"!M_\P0$$'L!'I",`@`0>P$>BM(_^1*A6<T0>P$>!"\S
XM`#X1?``@``$K2/_D8"!*A6<<+RW_Y$AZ\D1(;`1X3KH1L$_O``Q![`1X*TC_I
XMY"!M_^@K:``@_]1"K?_0("@`&`R`````#60``[C00#`[``9.^P`$`!@`'@`VN
XM`$X#1`$J`T0!Y`-$`E`"?`+:`T1^`6```XYP)T'L`,PD;?_H(FH`(!+84<C_,
XM_&```W9P)R)M_^@@:0`@0^P`S!+84<C__&```UX@;?_H("@`'`R````#[6843
XM(BP`\"0!Y8)![``T*W`H`/_88$@,@````^YF%"(L`/`D`>6"0>P`/"MP*`#_9
XMV&`L#(````/L9A0@+`#P(@#E@4'L`$0K<!@`_]A@$"`L`/#E@$'L`$PK<`@`%
XM_]A*K`#D9R0@;?_H+R@`("\M_]Q(;`-,80#Z:$_O``Q![`-,*T#_T"M(_]0@*
XM+`#PY8!*K?_09PI![`!\('`(`&`$0?KQ)B\M_]@O+?_4+PA#[`"<+S$(`"\M7
XM_^1(>O#V+RP%LF$`]]Y/[P`<?`!@``*"(&W_Z"`H`!QR_K"!9A0B+`#P)`'E(
XM@D'L`%0K<"@`_]A@*%*`9A0@+`#P(@#E@4'L`%PK<!@`_]A@$"`L`/#E@$'L&
XM`&0K<`@`_]A*K`#D9R0@;?_H+R@`("\M_]Q(;`-,80#YKD_O``Q![`-,*T#_@
XMT"M(_]0@+`#PY8!*K?_09PI![`!\('`(`&`$0?KP;"\M_]@O+?_4+PA#[`"D6
XM+S$(`"\M_^1(>O`\+RP%LF$`]R1/[P`<?`!@``'(2JP`Y&<D(&W_Z"\H`"`OA
XM+?_<2&P#3&$`^3Y/[P`,0>P#3"M`_]`K2/_4("P`\.6`2JW_T&<*0>P`?"!PZ
XM"`!@!$'Z[_PO+?_4+PA#[`"L+S$(`"\M_^1(>N_H+RP%LF$`]KA/[P`8?`!@F
XM``%<("P`\.6`+RW_U$'L`+0O,`@`+RW_Y$AZ[\XO+`6R80#VC$_O`!1\`6``7
XM`3`@;?_H+R@`'&$`]T183R!`2AAF_%.(D<`K0/_,2.T!`/_(<B\@0"0M_\BRI
XM,"C_9@1","C_(BP`\.6!+P!#[`"\+S$8`"\M_^1(>N]P+RP%LF$`]BY/[P`49
XM?`%@``#22JP`Y&<D(&W_Z"\H`"`O+?_<2&P#3&$`^$A/[P`,0>P#3"M`_]`K%
XM2/_4("P`\.6`2JW_T&<*0>P`?"!P"`!@!$'Z[P8O+?_4+PA#[`#$+S$(`"\ME
XM_^1(>N[R+RP%LF$`]<)/[P`8?`!@9DJ&9R1*A6<@("P`\.6`0>P`A"\P"`!(Y
XM>N[J+RP%LF$`]9A/[P`,>@`@;?_H2J@`'&<:("P`\.6`0>P`;"\P"``O+`6R,
XM80#U<E!/8!@@+`#PY8!![`!T+S`(`"\L!;)A`/584$]\`2)M_^@L>``$3J[^\
XMAF``^R!*K?_P9P#Z+DJ&9P#Z*`@M``#_\V<>("P`\.6`0>P`C"\P"`!(>NYL8
XM+RP%LF$`]11/[P`,""T``?_S9QX@+`#PY8!![`",+S`(`$AZ[E8O+`6R80#TA
XM[D_O``P(+0`"__-G'B`L`/#E@$'L`(PO,`@`2'KN/B\L!;)A`/3(3^\`#`@M#
XM``/_\V<>("P`\.6`0>P`C"\P"`!(>NXJ+RP%LF$`]*)/[P`,""T`!/_S9QX@X
XM+`#PY8!![`",+S`(`$AZ[A8O+`6R80#T?$_O``P(+0`%__-G'B`L`/#E@$'L3
XM`(PO,`@`2'KN!"\L!;)A`/163^\`#$*M__!@`/D\(FP%IBQX``1.KOZ8(&P%E
XMID*H``I.N@C`2H!F6D*M_^Q(>NW@+RP%LF$`]!Y03TJL!;IF#DAZ[APO+`6R(
XM80#T"E!/<GW2@2QL`!Q.KO\Z2JP%LF<:4JW_[`RM`````O_L;PPB+`6R3J[_B
XMW$*L!;).N@AF2H!GS$JL!;)G#DAZ[AHO+`6R80#SPE!/(&P%IBQX``1.KOZ,,
XM*T#_[$J`9P@B0$ZN_H9@Y$'L!7@L>``$3J[]S'(*+&P`'$ZN_SI(>/__80#HX
XM4DSM!.S_L$Y=3G5.5?_P2.<O,"XM``@F;0`,?`!Z`'@`0_KJ3"QX``1.KOYZW
XM*4`%IF<22&P`S$*G2'@``6$`\Z1/[P`,<`&^@&\``8X@:P`$<BVR$&8``8)#"
XMZ``!#!$`86400^@``G(PLA%G!BM`__!@!$*M__!#Z``!<@`2$47L`1T(,@``!
XM&`!G"G0`%`%R(-2!8`I#Z``!<``0$20`=F&4@VT``10,@@```!IL``$*U$(T=
XM.R`&3OL@!``R`/P`/@!(`/P`4@!<`&8`_`#\`/P`;`!V`/P`@`#\`(H`D`#\V
XM`/P`_`#\`)8`G@#\`*8I;?_P`/!X`6```-@I;?_P`-Q@``#.*6W_\`#@8```$
XMQ"EM__``Y&```+HI;?_P`-1@``"P?`%@``"J*6W_\`#08```H"EM__``[&``=
XM`)8I;?_P`,Q@``",>@%@``"&?`)@``"`*6W_\`#H8'8I;?_P`-A@;B!K``14C
XMB$H09Q!#[`6^$MAF_'`!*4`%NF`:6(M3AW`!OH!O$"!L!;HB:P`$$-EF_"E`E
XM!;I*K`6Z9A)(>NQ080#Q@DAX``5.NN:&4$]*A&8>0JP`\&`8+RL`!$AZ['!A;
XM`/%B2'@`!4ZZYF9/[P`,6(M3AV``_FYP`;Z`;P(L`$J&9P`!3KR`9@Q(>NQVC
XM80#Q-%A/8`I(>NV<80#Q*%A/2JP`\&<&0?KMY&`$0?KMY"\(2'KMGF$`\0Q0$
XM3TJL`-QG!D'Z[<A@!$'Z[<@O"$AZ[<AA`/#P4$]*K`#@9P9!^NVL8`1!^NVLO
XM+PA(>NWF80#PU%!/2JP`Y&<&0?KMD&`$0?KMD"\(2'KN!&$`\+A03TJL`-1GO
XM!D'Z[71@!$'Z[70O"$AZ[B)A`/"<4$]*K`#09P9!^NU88`1!^NU8+PA(>NY`U
XM80#P@%!/2JP`[&<&0?KM/&`$0?KM/"\(2'KN7F$`\&103TJL`,QG!D'Z[2!@;
XM!$'Z[2`O"$AZ[GQA`/!(4$]*K`#H9P9!^NT$8`1!^NT$+PA(>NZ:80#P+%!/+
XM2JP`V&<&0?KLZ&`$0?KLZ"\(2'KNN&$`\!!03W`!O(!F"DAZ[N)A`/``6$](+
XM>``%80#E(EA/2JP%IF<P2H5G$D*G<``O`"\`80#PG$_O``Q@$DAL`,Q"ITAX5
XM``)A`/"(3^\`#$*G80#D[%A/2H5G$$AZ[TAA`.^R0I=A`.386$]!^N;N(@@DA
XM/````^XL;``<3J[_XBE`!;9(>`^@2'KS'$AX``5(>N].3KH&4D_O`!!*@&826
XM2'KO2&$`[VY(>``*80#DDE!/3-\,]$Y=3G5(YR,8)D$N`DGY`````$JL`.QG<
XM``"`2JP`S&=XD\DL>``$3J[^VK"L!:YG:$JL`.AG"D'L!7A.KOW,8")![`5X!
XM3J[]P$J`9A8B;`6N("P)0DZN_KPB"R0'3KH%3F`^+PLO!TAX``-A`.^P(@LDB
XM!TZZ!3@L`$*7+P9(>``$80#OFD_O`!1![`5X+'@`!$ZN_<8@!F`((@LD!TZZ%
XM!0Y,WQC$3G5(YR,8)D$N`DGY`````$JL`.QG``"`2JP`T&=XD\DL>``$3J[^,
XMVK"L!:YG:$JL`.AG"D'L!7A.KOW,8")![`5X3J[]P$J`9A8B;`6N("P)1DZNY
XM_KPB"R0'3KH$N&`^+PLO!TAX``5A`.\.(@LD!TZZ!*(L`$*7+P9(>``&80#N<
XM^$_O`!1![`5X+'@`!$ZN_<8@!F`((@LD!TZZ!'A,WQC$3G5(YP$8)D%)^0```
XM``!*K`#L9WI*K`#49W23R2QX``1.KO[:L*P%KF=D2JP`Z&<*0>P%>$ZN_<Q@X
XM($'L!7A.KOW`2H!F%")L!:X@+`E*3J[^O"(+3KH$*&`Z+PM"ITAX``=A`.YR#
XM(@M.N@04+@!"ER\'2'@`"&$`[EY/[P`40>P%>"QX``1.KOW&(`=@!B(+3KH#G
XM[$S?&(!.=4CG,Q@F02X"+`-)^0````!*K`#L9V9*K`#89V"3R2QX``1.KO[:0
XML*P%KF=02JP`Z&<*0>P%>$ZN_<Q@)$'L!7A.KOW`2H!F&")L!:X@+`E.3J[^1
XMO"(+)`<F!DZZ`Y1@)B\+0J=(>``)80#MTD_O``Q![`5X+'@`!$ZN_<8B"R0'D
XM)@9.N@-L3-\8S$YU2.<!""X!2?D`````2JP`[&=B2JP`W&=<D\DL>``$3J[^<
XMVK"L!:YG3$JL`.AG"D'L!7A.KOW,8"!![`5X3J[]P$J`9A0B;`6N("P)4DZNE
XM_KPB!TZZ`QQ@(D*G+P=(>``*80#M3D_O``Q![`5X+'@`!$ZN_<8B!TZZ`OA,C
XMWQ"`3G5(YP$8)D%)^0````!*K`#L9WA*K`#@9W*3R2QX``1.KO[:L*P%KF=B#
XM2JP`Z&<*0>P%>$ZN_<Q@($'L!7A.KOW`2H!F%")L!:X@+`E63J[^O"(+3KH"^
XMJ&`X+PM"ITAX``MA`.S.(@M.N@*4+@!"ER\'2'@`#&$`[+I/[P`40>P%>"QX$
XM``1.KOW&8`8B"TZZ`FY,WQB`3G5(YP#R+'D````$('D````<".@``0`.3*@.4
XM`/_B2+D.`````/A,N0X````AXDBH#@#_XDRH#@#_K$BY#@````#^3+D.````J
XM(>A(J`X`_ZQ,J`X`_VI(N0X````!!$RY#@```"'N2*@.`/]J3*@.`/\B2+D.L
XM`````0I,N0X````A]$BH#@#_(DRH#@#_@DBY#@````$03+D.````(?I(J`X`A
XM_X),J`X`_[A(N0X````!%DRY#@```"(`2*@.`/^X(DA.KOY63-]/`$YU2.<`P
XM\BQY````!"!Y````'"`Y```AY+"H_^1F``"L(#D``"'JL*C_KF8``)X@.0``!
XM(?"PJ/]L9@``D"`Y```A]K"H_R1F``""(#D``"'\L*C_A&8``'0@.0``(@*PU
XMJ/^Z9@``9@CH``$`#DRY#@````#X2*@.`/_B3+D.`````/Y(J`X`_ZQ,N0X`C
XM```!!$BH#@#_:DRY#@````$*2*@.`/\B3+D.`````1!(J`X`_X),N0X````!@
XM%DBH#@#_N")(3J[^5G`!8`)P`$S?3P!.=4[Y```B!D[Y```B&$[Y```B*D[Y/
XM```B/$[Y```B3D[Y```B8$CG/SY.N0``',I,WWS\(@!.=4CG/SY.N0``'6Q,'
XMWWS\(@!.=4CG/SY.N0``'@Y,WWS\(@!.=4CG/SY.N0``'J9,WWS\(@!.=4CG1
XM/SY.N0``'S),WWS\(@!.=4CG/SY.N0``'[),WWS\(@!.=4'Y````^#`\_^)@(
XM/D'Y````_C`\_ZQ@,D'Y```!!#`\_VI@)D'Y```!"C`\_R)@&D'Y```!$#`\\
XM_X)@#D'Y```!%C`\_[A@`DYQ2.=S`CP0#$9.^68``!`@:``"+'D````<3I!@,
XM&#P02(9(QL%&/B@`!"QY````'-Y&3K9P!$S?0,Y.=0``2.<X,BQX``1R`'`D1
XM3J[_.DJ`9P``;"9`D\E.KO[:)$`@:@"LT<C1R"=H`#P`!$*H`#PFO````"1%T
XMZP`(+'D````<-/PH?"3,-/Q.N23O`"0T_"Q\),Y'ZP`$)@ODBS3\(CPDPR3\;
XM3N[_9"(O`!PD+P`@*"\`*$ZN_W9,WTP<3G5P>$[Y```!,$CG(#`F;P`0)$M*"
XM$F<D<``0$D'L`1T(,``!"`!G"G(`$@!T()*"8`1R`!(`%(%2BF#8(`M,WPP$/
XM3G4``````````'!A(F\`""!O``0@+P`,(@A@!!#99PA3@&3X8`9"&%.`9/H@!
XM`4YU(F\`""!O``0@"$H89OQ3B!#99OQ.=0``("\`""!O``1.5?_T(D]R"DZZZ
XM`9P&00`P$L%*@&;P(`D0X;_)9OI"$)"/3EU.=0``("\`""!O``1.5?_T(D\B[
XM``)!``<&00`P$L'FB&;P(`D0X;_)9OI"$)"/3EU.=0``,#$R,S0U-C<X.6%B)
XM8V1E9B`O``@@;P`$0^\`!#(``D$`#Q+[$-SHB&;R(`DB#UB!$.&RB6;Z0A"08
XM@4YU(&\`!")(<@!P`"\"#!``*V<&#!``+68"4D@0&`0``#!M$@P```EN#"0!B
XMY8'2@M*!TH!@Y@P1`"UF`D2!)!\@"%.`(&\`"""!D(E.=2\'+B\`"%*L"60@4
XM!R!L"6`0P"E("6`N'TYU3E4``$CG`#`F;P`0)&\`%$*L"60I2PE@2&T`$"\*Z
XM2'K_QDZZ!6`@;`E@0A`@+`ED3.T,`/_X3EU.=4CG`!(F;P`,2JL`"F<*(DLL)
XM>``$3J[^F!=\`/\`"'#_)T``%'``$"L`#RQX``1.KOZP(DMP(DZN_RY,WT@`Y
XM3G5*@&H``!Y$@$J!:@``#$2!80``($2!3G5A```81(!$@4YU2H%J```,1(%A4
XM```&1(!.=2\"2$$T`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!,`)(0C("H
XM)!].=2\#=A`,00"`9```!N&944,,00@`9```!NF964,,02``9```!N6954-*7
XM06L```;CF5-#-`#FJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(4T/0@63^D
XM<@`R`TA#Y[A(0,%!)A\D'TYU2.<#,B9O`!@N+P`<</\L>``$3J[^MBP`#`8`U
XM_V8$<`!@9G`B(CP``0`!3J[_.B1`(`IF"G``$`9.KOZP8$@E2P`*(`<50``);
XM%7P`!``(0BH`#A5&``^3R4ZN_MHE0``0(`MG"")*3J[^GF`:0>H`&"5(`!1!#
XMZ@`4)4@`'$*J`!@5?``"`"`@"DS?3,!.=0``3E7_Q$CG)S`F;P!<)&\`8'X`P
XM?`!Z`'``&WP`(/_[<@`K0?_V=/\K0O_R0>W_T!M`__$;0/_\*T'_Y"M!_^@KF
XM2/_,2A-G+'``$!,$0``@9Q170&<444!G"%5`9A9^`6`.?`%@"GH!8`8;?``!E
XM__Q2BV#0$!-R,+`!9@92BQM!__MP*K`39@P@4EB2*U#_]E*+8`Y(;?_V+PM.U
XMNOTR4$_7P!`3<BZP`68B4HMP*K`39@P@4EB2*U#_\E*+8`Y(;?_R+PM.NOT('
XM4$_7P!`3<FRP`68*&WP``?_Q4HM@"')HL`%F`E*+$!MR`!(`&T#_\`1!`%AGR
XM``%^!$$`"V<``@I306<D!$$`"V<``1)306<``5!706<``;I506<``.1706<`1
XM`5)@``'X2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L;`IR`42M_^PK0?_H2JW_D
XMZ&<$<"U@"DH&9P1P*V`"<"`;0/_0<``0!B(M_^B"@'``$`6"@&<(4JW_S%*M)
XM_^0O+?_L+RW_S$ZZ^ZI03RM`_\@@+?_R2H!J!G(!*T'_\B`M_\@B+?_RDH!(%
XM[0`"_\1O-"!M_\PB2-/!+P`O"2\(3KH"4D_O``QP`!`M__LB+?_$(&W_S&`"B
XM$,!3@63Z("W_\BM`_\C1K?_D0>W_T"M(_\Q*!V<``3`;?``@__M@``$F2BW_E
XM\6<((%)8DB`08`8@4EB2(!`K0/_L8`#_9$HM__%G""!26)(@$&`&(%)8DB`0+
XM*T#_[$HM__QG$B!M_\P0_``P<@$K0?_D*TC_S"\`+RW_S$ZZ^PY03RM`_\A@M
XM`/\R&WP`,/_[("W_\DJ`:@9P""M`__)*+?_Q9P@@4EB2(!!@!B!26)(@$"M`]
XM_^Q*+?_\9Q8@;?_,$/P`,!#\`'AR`BM!_^0K2/_,+P`O+?_,3KKZ\E!/*T#_&
XMR'!8L"W_\&8`_M!(;?_03KKYZEA/8`#^PB!26)(B4"M)_\QF"$'Z`-@K2/_,2
XM(&W_S$H89OQ3B)'M_\PK2/_D("W_\DJ`:R:QP&\B*T#_Y&`<<`$K0/_D(%)8$
XMDB`0&T#_T$(M_]%@!G``8```C"`M_^0B+?_VLH!L"'0`*T+_]F`$D:W_]DH'%
XM9S93K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.)3K?_V;4AP`!`M__LO&
XM`"!M`!!.D%A/8.A3K?_V;1)P`!`M__LO`"!M`!!.D%A/8.A3K?_D;1AP`"!M#
XM_\P0&"\`*TC_S"!M`!!.D%A/8.(@"TS?#.1.74YU``!.5?_T2.<!,"9O`"`D'
XM;P`D*VT`$/_V'AI*!V<T<"6^`&8BL!)F!%**8!HO"TAM__8O"F$`_!9/[P`,+
XM*T#_^F<$)$!@TG``$`<O`$Z36$]@QDS?#(!.74YU```@;P`$(F\`""`O``QOD
XM%K/(90S1P-/`$R!3@&;Z3G42V%.`9OI.=0`````#[````!D````````C?```6
XM(F8``")4```B0@``(C```"(>```B#```(@(``"'\```A]@``(?```"'J```AW
XMY```(6H``"%<```A3@``(4```"$R```A)```(/P``"#@```@Q```(*@``"",(
XM```@<````!\````!```C-@``(N8``"+0```A'@``(%0``"*P```BI```(I@`(
XM`"*,```B@```(G0``"'&```AN```(:H``"&<```AC@``(8```"#T```@V```*
XM(+P``""@```@A```(&@``!^Z```?.@``'K(``!X6```==@``'-0```$4````6
XM#@````````/R```#Z@```(@`````````````````````````````````````X
XM``````````!D;W,N;&EB<F%R>0````&H```"2````D@```).```"5````F(`P
XM``)H```"=@```G8```)\```"?````H(```*(```"E@```I8```*<```"G```0
XM`J0```*L```"O````KX```+*```"R@```M0```+D```"_@```OX```,&```#R
XM!@```PP```,2```#(````R8```,T```#.@```T@```-(```#3@```U0````!I
XM``````````$````!`````0````$```````````````$````!````````````&
XM```````````````````````````````````````````@("`@("`@("`H*"@H`
XM*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$(
XM$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"V
XM`@("`@("`@("`@("`@("`@("`@(0$!`0("`@("`@("`@("@H*"@H("`@("`@P
XM("`@("`@("`@("`@2!`0$!`0$!`0$!`0$!`0$(2$A(2$A(2$A(00$!`0$!`00
XM@8&!@8&!`0$!`0$!`0$!`0$!`0$!`0$!`0$0$!`0$!""@H*"@H("`@("`@("4
XM`@("`@("`@("`@("`A`0$!`@```````#[````"<`````````R````,0```#`<
XM````O````+@```"T````L````*P```"H````I````*````"<````F````)0`X
XM``"0````C````(@```"$````@````'P```!X````=````'````!L````:```4
XM`&0```!@````7````%@```!4````4````$P```!(````1````$`````\````P
X1.````#0````P`````````_)4E
X``
Xend
Xsize 12032
END_OF_FILE
if test 16885 -ne `wc -c <'snoopdos.uu'`; then
    echo shar: \"'snoopdos.uu'\" unpacked with wrong size!
fi
# end of 'snoopdos.uu'
fi
if test -f 'snoopglue.s' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'snoopglue.s'\"
else
echo shar: Extracting \"'snoopglue.s'\" \(5668 characters\)
sed "s/^X//" >'snoopglue.s' <<'END_OF_FILE'
X*
X*	SNOOPGLUE.S						:ts=8
X*
X*	Assembly support routines for snoopdos.c
X*
X*	This file contains routines to patch/unpatch dos library to point
X*	to a C routine, and to call the old routines.
X*
X*	Does some nasty tricks to patch into dos.library. However, since we
X*	checks to see if we are running under 2.0 (with dos.library looking
X*	just like any other library), Snoopdos works fine under 2.0.
X*
X	INCLUDE "exec/types.i"
X	INCLUDE "exec/libraries.i"
X	INCLUDE	"libraries/dosextens.i"
X
X	XDEF	_installdospatch
X	XDEF	_uninstalldospatch
X	XDEF	_CallLock
X	XDEF	_CallOpen
X	XDEF	_CallLoadSeg
X	XDEF	_CallExecute
X	XDEF	_CallCurrentDir
X	XDEF	_CallDeleteFile
X
X	XREF	_DOSBase
X
X	XREF	_NewOpen
X	XREF	_NewLock
X	XREF	_NewLoadSeg
X	XREF	_NewExecute
X	XREF	_NewCurrentDir
X	XREF	_NewDeleteFile
X
X	XREF	_LVOOpen
X	XREF	_LVOLock
X	XREF	_LVOLoadSeg
X	XREF	_LVOExecute
X	XREF	_LVOCurrentDir
X	XREF	_LVODeleteFile
X
XCALL	MACRO
X	XREF	_LVO\1
X	JSR	_LVO\1(A6)
X	ENDM
X
X	SECTION	SnoopDos,CODE
X
X*
X*	Modify DOS library to call our functions for Open() and Lock();
X*	We can't just use SetFunction() because DOS library is non-standard.
X*	Instead of using JMP $123456 type instructions, it uses (mostly)
X*	MOVEQ #funcnum,D0; BRA.L Dispatch. So, we replace this entire
X*	sequence with a standard JMP instruction, steal the number from
X*	the MOVEQ instruction and use it when we want to call the real
X*	DOS library later on.
X*
X_installdospatch:
X	MOVEM.L	A0-A3/A6,-(A7)		* Save regs
X	MOVE.L	4,A6			* Get ExecBase
X	MOVE.L	_DOSBase,A0		* Get DOSbase
X	BSET	#LIBB_CHANGED,LIB_FLAGS(A0) * Indicate changing DOS library
X
XSetFunc	MACRO
X	MOVEM.W	_LVO\1(A0),A1-A3	* Read in current value for func
X	MOVEM.W	A1-A3,\1Save		* Save the appropriate data
X	MOVEM.W CallOur\1,A1-A3		* Read in replacement code
X	MOVEM.W	A1-A3,_LVO\1(A0)	* And modify library
X	ENDM
X
X	SetFunc	Open
X	SetFunc Lock
X	SetFunc LoadSeg
X	SetFunc Execute
X	SetFunc CurrentDir
X	SetFunc DeleteFile
X
X	MOVE.L	A0,A1			* Finally,
X	CALL	SumLibrary		* Recalculate library checksum
X	MOVEM.L	(A7)+,A0-A3/A6		* Save regs
X	RTS
X
X*
X*	Reinstall previous DOS patch. If someone has already altered the
X*	function, we can't actually exit immediately so return a FALSE
X*	result. While there is a very small window which could cause
X*	problems (if someone is in the middle of a SetFunction() when
X*	this is called), but we'll ignore this mostly.
X*
X_uninstalldospatch:
X	MOVEM.L	A0-A3/A6,-(A7)		* Save regs
X	MOVE.L	4,A6			* Get sysbase
X	MOVE.L	_DOSBase,A0		* Get DOSBase
X
XTestFunc MACRO
X	MOVE.L	CallOur\1+2,D0		* Get old address of function
X	CMP.L	_LVO\1+2(A0),D0		* See if changed
X	BNE	changed			* If it has, exit with no action
X	ENDM
X
X	TestFunc Open
X	TestFunc Lock
X	TestFunc LoadSeg
X	TestFunc Execute
X	TestFunc CurrentDir
X	TestFunc DeleteFile
X
X	BSET	#LIBB_CHANGED,LIB_FLAGS(A0) * Indicate changing DOS library
X
XRestFunc MACRO
X	MOVEM.W	\1Save,A1-A3		* Read in prev. value of vec.
X	MOVEM.W	A1-A3,_LVO\1(A0)	* Atomically restore it
X	ENDM
X
X	RestFunc Open
X	RestFunc Lock
X	RestFunc LoadSeg
X	RestFunc Execute
X	RestFunc CurrentDir
X	RestFunc DeleteFile
X
X	MOVE.L	A0,A1			* Finally,
X	CALL	SumLibrary		* Update library checksum
X	MOVEQ	#1,D0			* Indicate success
X	BRA.S	unexit			* And exit
X
Xchanged:
X	MOVEQ	#0,D0			* Indicate failure to uninstall
Xunexit:
X	MOVEM.L	(A7)+,A0-A3/A6		* Restore regs
X	RTS				* And exit with return in D0
X
X*
X*	This code is the code that gets moved directly into the DOS
X*	library vectors
X*
XCallOurOpen:		JMP	NewOpen
XCallOurLock:		JMP	NewLock
XCallOurLoadSeg:		JMP	NewLoadSeg
XCallOurExecute:		JMP	NewExecute
XCallOurCurrentDir:	JMP	NewCurrentDir
XCallOurDeleteFile:	JMP	NewDeleteFile
X
X*
X*	These are the replacement DOS routines.
X*
XNewFunc	MACRO
X	MOVEM.L	A2-A6/D2-D7,-(A7)	* Save all registers (to be safe)
X	JSR	_New\1			* Call C version with params in D1-D3
X	MOVEM.L	(A7)+,A2-A6/D2-D7	* Restore registers
X	MOVE.L	D0,D1			* Copy return value into D1
X*					* [some routines expect this :-( ]
X	RTS				* Return to caller, exit value in D0
X	ENDM
X
XNewOpen:	NewFunc Open
XNewLock:	NewFunc Lock
XNewLoadSeg:	NewFunc LoadSeg
XNewExecute:	NewFunc Execute
XNewCurrentDir:	NewFunc CurrentDir
XNewDeleteFile:	NewFunc	DeleteFile
X
X*
X*	Allow's C to call the old DOS functions. If we're running Kikstart 2.0
X*	then just call the original function directly. Otherwise, calculate
X*	where to go from the code stored in the vector.
X*
XOldDosCall MACRO
X	LEA.L	\1Save,A0	* Get pointer to func save vector
X	MOVE.W	#_LVO\1,D0	* Get library offset vector
X	BRA.S	CallDos		* Skip to execute it
X	ENDM
X
X_CallOpen:		OldDosCall Open
X_CallLock:		OldDosCall Lock
X_CallLoadSeg:		OldDosCall LoadSeg
X_CallExecute:		OldDosCall Execute
X_CallCurrentDir:	OldDosCall CurrentDir
X_CallDeleteFile:	OldDosCall DeleteFile
X
X	NOP				* Stop Lattice messing up final branch
XCallDos:
X	MOVEM.L	D1-D3/D6/D7/A6,-(A7)	* Save registers
X	MOVE.W	(A0),D6			* Get previous instruction
X	CMP.W	#$4ef9,D6		* Is it a JMP instruction?
X	BNE	dos_exec		* If not, then call using special code
X	MOVE.L	2(A0),A0		* Else it's 2.0 or SetFunction()
X	MOVE.L	_DOSBase,A6		* Put DOSBase into A6 as expected
X	JSR	(A0)			* Call original function
X	BRA.S	callexit		* And exit
X
Xdos_exec:
X	MOVE.W	(A0),D6			* Get MOVEQ instruction
X	EXT.W	D6			* Convert data to word
X	EXT.L	D6			* and then longword
X	EXG.L	D0,D6			* Swap with library vector offset
X	MOVE.W	4(A0),D7		* Get offset to DOS routine from LVO
X	MOVE.L	_DOSBase,A6		* Get DOSBase 
X	ADD.W	D6,D7			* Calculate offset value
X	JSR	4(A6,D7.W)		* Call DOS function dispatcher
X
Xcallexit:
X	MOVEM.L	(A7)+,D1-D3/D6/D7/A6	* Restore registers
X	RTS				* And return to C caller
X
X	SECTION SnoopData,DATA
X
XOpenSave	DS.W	3
XLockSave	DS.W	3
XLoadSegSave	DS.W	3
XExecuteSave	DS.W	3
XCurrentDirSave	DS.W	3
XDeleteFileSave	DS.W	3
X
X	END
END_OF_FILE
if test 5668 -ne `wc -c <'snoopglue.s'`; then
    echo shar: \"'snoopglue.s'\" unpacked with wrong size!
fi
# end of 'snoopglue.s'
fi
if test -f 'system.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'system.h'\"
else
echo shar: Extracting \"'system.h'\" \(271 characters\)
sed "s/^X//" >'system.h' <<'END_OF_FILE'
X/* Includes for snoopdos.h */
X
X#include <exec/types.h>
X#include <exec/ports.h>
X#include <exec/semaphores.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <proto/exec.h>
X#include <proto/dos.h>
X#include <string.h>
X#include <dos.h>
X#include <ctype.h>
END_OF_FILE
if test 271 -ne `wc -c <'system.h'`; then
    echo shar: \"'system.h'\" unpacked with wrong size!
fi
# end of 'system.h'
fi
if test -f 'tiny.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tiny.a'\"
else
echo shar: Extracting \"'tiny.a'\" \(6132 characters\)
sed "s/^X//" >'tiny.a' <<'END_OF_FILE'
X*:ts=8
X****************************************************************************
X*									   *
X* TINY.A				  (C) Copyright Eddy Carroll 1989  *
X* ~~~~~~				  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
X*									   *
X* Replacement startup code for Lattice C V5.04. Use instead of c.o	   *
X* This has many features stripped out to allow small utilities to have	   *
X* as small a filesize as possible. In particular, don't call any of the    *
X* stdio functions.							   *
X*									   *
X****************************************************************************
X
X	INCLUDE "exec/types.i"
X	INCLUDE "exec/alerts.i"
X	INCLUDE "exec/nodes.i"
X	INCLUDE "exec/lists.i"
X	INCLUDE "exec/ports.i"
X	INCLUDE "exec/libraries.i"
X	INCLUDE "exec/tasks.i"
X	INCLUDE "libraries/dos.i"
X	INCLUDE "libraries/dosextens.i"
X	INCLUDE "workbench/startup.i"
X	INCLUDE "exec/funcdef.i"
X	INCLUDE "exec/exec_lib.i"
X	INCLUDE "libraries/dos_lib.i"
X
XMAXARGS	    EQU 100	; Maximum number of command line arguments from CLI
XAbsExecBase EQU 4	; Welcome to the only fixed point in the universe
X
X* A useful macro to let us call library routines
Xcallsys macro
X	CALLLIB _LVO\1
X	endm
X
X	xdef	XCEXIT
X	xdef	exit
X	xref	LinkerDB
X	xref	_BSSBAS
X	xref	_BSSLEN
X
X	csect	text,0,0,1,2		* xref's after this are 16-bit reloc
X	xref	main			* Name of C program to start with.
X
Xstart:
X	movem.l d1-d6/a0-a6,-(a7)
XREGSIZE EQU	(6+7)*4
X	lea	REGSIZE(a7),A5		* Determine old stack pointer
X	move.l	a0,a2			* Save command pointer
X	move.l	d0,d2			* and command length
X	lea	LinkerDB,a4		* Load base register
X
X	move.l	AbsExecBase.W,a6
X	move.l	a6,SysBase(A4)
X	move.l	a7,_StackPtr(A4)	* Save stack ptr
X
X	suba.l	a1,a1
X	callsys	FindTask		* Find out our task ID
X	move.l	d0,a3
X
X	move.l	a5,D0	  		* get top of stack
X	sub.l	4(a5),D0		* compute bottom
X	add.l	#128,D0 		* allow for parms overflow
X	move.l	D0,_base(A4)		* save for stack checking
X
X	lea	DOSName(A4),A1
X	moveq.l	#0,D0
X	callsys	OpenLibrary
X	move.l	D0,DOSBase(A4)
X	bne	getcom
XnoDOS:
X	moveq.l #100,d0
X	bra	exit2
X
X*------ find command name:
Xgetcom:
X	move.l  pr_CLI(a3),a0
X	add.l	a0,a0
X	add.l	a0,a0
X	move.l	cli_CommandName(a0),a1
X	add.l	a1,a1
X	add.l	a1,a1
X
X*------ collect parameters:
X	move.l	d2,d0			* get command line length
X	moveq.l #0,d1
X	move.b	(a1)+,d1
X	move.l	a1,_ProgramName(A4)
X	add.l	d1,d0			* add length of command name
X	addq.l	#1,d0			* allow for space after command
X
X	clr.w	-(A7)			* set null terminator for command line
X	addq.l	#1,D0			* force to even number of bytes
X	andi.w	#$fffe,D0		* (round up)
X	sub.l	D0,A7			* make room on stack for command line
X	subq.l	#2,D0
X	clr.w	0(A7,D0)
X
X*------ copy command line onto stack
X	move.l	d2,d0			* get command line length
X	subq.l	#1,d0
X	add.l	d1,d2
X
Xcopy_line:
X	move.b	0(A2,D0.W),0(A7,D2.W)	* copy command line to stack
X	subq.l	#1,d2
X	dbf	d0,copy_line
X	move.b	#' ',0(a7,d2.w) 	* add space between command and parms
X	subq.l	#1,d2
X
Xcopy_cmd:
X	move.b	0(a1,d2.w),0(a7,d2.w)	* copy command name to stack
X	dbf	d2,copy_cmd
X	move.l	a7,a1			* Get pointer to new command line
X
X	sub.l	#(MAXARGS*4),a7		* Reserve space for argv[]
X	move.l	a7,a2			* Initialise base into array
X	move.l	a2,a3			* Save base of argv
X	moveq	#0,d2			* Initialise argc
X
X*
X* From here on down, A1 is pointer into command line
X*
Xbuild_argv:
X	bsr.s	getnext			* Read next character from line
X	bcs.s	doquote			* If quote, handle
X	beq.s	build_argv		* If white space, skip over it
X
X	lea	-1(a1),a0		* Get address of this parameter
X	bsr.s	bumpargv		* Store it to argv[] array
Xbuild_2:
X	bsr.s	getnext			* Get next character
X	bne.s	build_2			* If not white space, keep looking
X	clr.b	-1(a1)			* Zero-terminate current argument
X	bra.s	build_argv		* And go back to get next argument
X
Xdoquote:
X	move.l	a1,a0			* Get pointer to this argument
X	bsr.s	bumpargv		* Output it to argv[]
Xquote_2:
X	bsr.s	getnext			* Get next character
X	bcc.s	quote_2			* If not quote, keep looking
X	clr.b	-1(a1)			* Zero-terminate current argument
Xquote_3:
X	bsr.s	getnext			* Get next character
X	bne.s	quote_3			* Skip until space reached
X	beq.s	build_argv		* Go back and read next argument
X
Xbumpargv:
X	move.l	a0,(a2)+		* Output ptr to current argument
X	addq	#1,d2			* Increment argc
X	cmpi	#MAXARGS,d2		* Used up all our arguments yet?
X	bls.s	qrts			* If not, then return
X	moveq	#110,d0			* Else set return code
X	bra.s	exit2			* And exit
X
X*
X* Reads next character from command line. If zero, never returns, but
X* drops into call to main. Else, returns, with C=1 if character is quote,
X* Z=1 if character is white space.
X*
Xgetnext:
X	move.b	(a1)+,d0		* Get character from command line
X	beq.s	get_2			* Exit if end of line
X	cmp.b	#34,d0			* Check if quote
X	beq.s	isquote			*
X	cmp.b	#32,d0			* Check if space
X	beq.s	isspace			*
X	cmp.b	#9,d0			* Or tab
X	beq.s	isspace			*
X	cmp.b	#10,d0			* Or end of line
Xisspace:
X	andi	#$1E,ccr		* Clear carry flag, retaining Z
Xqrts	rts
X
Xisquote:
X	ori	#1,ccr			* Set carry flag
X	andi	#$FB,ccr		* Clear zero flag
X	rts				* And return
X
Xget_2:
X	move.l	a3,-(a7)		* Push argv onto stack
X	move.l	d2,-(a7)		* Push argc onto stack
X
X	lea	_BSSBAS,a3		* get base of BSS
X	moveq	#0,d1
X	move.l	#_BSSLEN,d0		* get length of BSS in longwords
X	bra.s	clr_lp			* and clear for length given
Xclr_bss move.l	d1,(a3)+
Xclr_lp	dbf	d0,clr_bss
X
Xdomain:
X	jsr	main(PC)		* Call main(argc,argv)
X	moveq.l #0,d0			* Set successful status
X	bra.s	exit2
X
Xexit:
X_exit:
XXCEXIT:
X	move.l	4(SP),d0		* Extract return code
Xexit2:
X	move.l	d0,-(a7)
X	move.l	AbsExecBase.W,a6
X	move.l	DOSBase(A4),a1
X	callsys CloseLibrary		* Close Dos library
X
X*------ this rts sends us back to DOS:
XexitToDOS:
X	MOVE.L	(A7)+,D0
X	movea.l _StackPtr(a4),SP	* Restore stack ptr
X	movem.l (a7)+,d1-d6/a0-a6
X	rts
X
X*-----------------------------------------------------------------------
X* Global definitions
X*
X	csect	__MERGED,1,,2,2
X
X	xdef	NULL,SysBase,LoadAddress,DOSBase
X	xdef	_oserr,_OSERR,_ONBREAK
X	xdef	_ProgramName,_StackPtr,_base
X
XNULL	       dc.l    0
X_base	       dc.l    0
X_oserr	       equ     *
X_OSERR	       dc.l    0
X_ONBREAK       dc.l    0
XSysBase        dc.l    0
XLoadAddress    dc.l    0
X_StackPtr      dc.l    0
XDOSBase        dc.l    0
X_ProgramName   dc.l    0
XDOSName        dc.b    'dos.library',0
X
X	END
END_OF_FILE
if test 6132 -ne `wc -c <'tiny.a'`; then
    echo shar: \"'tiny.a'\" unpacked with wrong size!
fi
# end of 'tiny.a'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.