summaryrefslogtreecommitdiffstats
path: root/mac
diff options
context:
space:
mode:
authorrjohnson <rjohnson>1998-03-26 14:45:59 (GMT)
committerrjohnson <rjohnson>1998-03-26 14:45:59 (GMT)
commit2b5738da524e944cda39e24c0a87b745a43bd8c3 (patch)
tree6e8c9473978f6dab66c601e911721a7bd9d70b1b /mac
parentc6a259aeeca4814a97cf6694814c63e74e4e18fa (diff)
downloadtcl-2b5738da524e944cda39e24c0a87b745a43bd8c3.zip
tcl-2b5738da524e944cda39e24c0a87b745a43bd8c3.tar.gz
tcl-2b5738da524e944cda39e24c0a87b745a43bd8c3.tar.bz2
Initial revision
Diffstat (limited to 'mac')
-rw-r--r--mac/AppleScript.html298
-rw-r--r--mac/Background.doc92
-rw-r--r--mac/MW_TclAppleScriptHeader.pch46
-rw-r--r--mac/MW_TclHeader.pch112
-rw-r--r--mac/README187
-rw-r--r--mac/bugs.doc32
-rw-r--r--mac/libmoto.doc39
-rw-r--r--mac/morefiles.doc74
-rw-r--r--mac/porting.notes23
-rw-r--r--mac/tclMac.h101
-rw-r--r--mac/tclMacAETE.r58
-rw-r--r--mac/tclMacAlloc.c340
-rw-r--r--mac/tclMacAppInit.c205
-rw-r--r--mac/tclMacApplication.r75
-rw-r--r--mac/tclMacBOAAppInit.c257
-rw-r--r--mac/tclMacBOAMain.c360
-rw-r--r--mac/tclMacChan.c1356
-rw-r--r--mac/tclMacDNR.c23
-rw-r--r--mac/tclMacEnv.c536
-rw-r--r--mac/tclMacExit.c317
-rw-r--r--mac/tclMacFCmd.c1408
-rw-r--r--mac/tclMacFile.c840
-rw-r--r--mac/tclMacInit.c284
-rw-r--r--mac/tclMacInt.h79
-rw-r--r--mac/tclMacInterupt.c289
-rw-r--r--mac/tclMacLibrary.c241
-rw-r--r--mac/tclMacLibrary.r223
-rw-r--r--mac/tclMacLoad.c245
-rw-r--r--mac/tclMacMSLPrefix.h24
-rw-r--r--mac/tclMacMath.h145
-rw-r--r--mac/tclMacNotify.c416
-rw-r--r--mac/tclMacOSA.c2937
-rw-r--r--mac/tclMacOSA.exp1
-rw-r--r--mac/tclMacOSA.r76
-rw-r--r--mac/tclMacPanic.c235
-rw-r--r--mac/tclMacPort.h263
-rw-r--r--mac/tclMacProjects.sit.hqx3157
-rw-r--r--mac/tclMacResource.c2165
-rw-r--r--mac/tclMacResource.r92
-rw-r--r--mac/tclMacShLib.exp1069
-rw-r--r--mac/tclMacSock.c2615
-rw-r--r--mac/tclMacTest.c242
-rw-r--r--mac/tclMacTime.c312
-rw-r--r--mac/tclMacUnix.c464
-rw-r--r--mac/tclMacUtil.c441
45 files changed, 22794 insertions, 0 deletions
diff --git a/mac/AppleScript.html b/mac/AppleScript.html
new file mode 100644
index 0000000..4a73fbb
--- /dev/null
+++ b/mac/AppleScript.html
@@ -0,0 +1,298 @@
+<HTML>
+
+<HEAD>
+
+<TITLE>tclOSAScript -- OSA</TITLE>
+
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#FF0000" ALINK="#00FF00">
+
+<H2 ALIGN="CENTER">TclAppleScript Extension Command</H2>
+
+<H3>NAME</H3>
+<DL>
+<DT>
+AppleScript - Communicate with the AppleScript OSA component to run
+ AppleScripts from Tcl.
+</DL>
+<H3>SYNOPSIS</H3>
+<DL><DT>
+<B>AppleScript <A NAME="compile">compile</A> </B><I>?-flag value?</I> <I>scriptData1
+ ?ScriptData2 ...?</I><I>componentName</I>
+<BR>
+<B>AppleScript <A NAME="decompile">decompile</A></B> <I>scriptName</I>
+<BR>
+<B>AppleScript delete </B><I>scriptName</I>
+<BR>
+<B>AppleScript <A NAME="execute">execute</A> </B><I>?flags value?</I> <I>scriptData1
+ ?scriptData2 ...?</I>
+<BR>
+<B>AppleScript <A NAME="info">info</A> </B><I>what</I>
+<BR>
+<B>AppleScript <A NAME="load">load</A></B> <I>?flag value? fileName</I>
+<BR>
+<B>AppleScript <A NAME="run">run</A></B> <I>?flag value?</I>
+ <I>scriptName</I>
+<BR>
+<B>AppleScript <A NAME="store">store</A></B> <I>?flag value? scriptName fileName</I>
+<BR>
+</DL>
+
+<H3>DESCRIPTION</H3>
+<DL>
+<DT>
+
+
+This command is used to communicate with the AppleScript OSA component.
+You can <A HREF="#compile"><B>compile</B></A> scripts, <A
+HREF="#run"><B>run</B></A> compiled scripts, <A
+HREF="#execute"><B>execute</B></A> script data (i.e. compile and run at a
+blow). You can get script data from a compiled script (<A
+HREF="#decompile"><B>decompile</B></A> it), and you can <A
+HREF="#load"><B>load</B></A> a compiled script from the scpt resource of a
+file, or <A HREF="store"><B>store</B></A> one to a scpt resource. You can
+also get <A HREF="#info"><B>info</B></A> on the currently available scripts
+and contexts. It has the general form
+
+<DL>
+<DT>
+<P>
+<I>AppleScript option ?arg arg ...?</I>
+<P>
+</DL>
+The possible sub-commands are:
+<P>
+<DL>
+ <DT>
+ <I>AppleScript</I> <A NAME="compile"><B>compile</A> </B><I>?-flag value?</I> <I>scriptData1
+ ?ScriptData2 ...?</I>
+ <BR>
+
+ <DD>
+ The scriptData
+ elements are concatenated (with a space between each), and
+ sent to AppleScript
+ for compilation. There is no limitation on the size of
+ the scriptData, beyond the available memory of the Wish interpreter.
+ <P>
+ If the compilation is successful, then the command will return a token
+ that you can pass to the <A HREF="#run">"run"</A> subcommand. If the
+ compilation fails, then the return value will be the error message from
+ AppleScript, and the pertinent line of code, with an "_" to indicate
+ the place where it thinks the error occured.
+ <P>
+ The
+ compilation is controlled by flag value pairs. The available flags
+ are:
+ <P>
+ <DL>
+ <DT>
+ <A NAME="first compile switch"><B>-augment Boolean</B></A>
+ <DD>
+ To be used in concert with the <A HREF="#-context">-context</A> flag.
+ If augment is yes,
+ then the scriptData augments the handlers and data already in the
+ script context. If augment is no, then the scriptData replaces the
+ data and handlers already in the context. The default is yes.
+ <P>
+ <!-- I'm leaving this flag out for now, since I can't seem to get the
+ AE manager to obey it. Even when I hard code the value, applications
+ still switch to the foreground. Oh, well...
+
+ <DT>
+ <B>-canswitch Boolean </B>
+ <DD>
+ If yes, then applications activated by the code in scriptData will
+ be allowed to switch to the foreground. If no, then they will use
+ the notification manager to indicate they need attention (this
+ usually means they blink the Finder icon, and put a check in the
+ application's entry in the Finder menu).
+ -->
+
+ <DT>
+ <B><A NAME="-context">-context</A> Boolean</B>
+ <DD>
+ This flag causes the code given in the scriptData to be compiled
+ into a "context". In AppleScript, this is the equivalent of creating an Tcl
+ Namespace. The command in this case returns the name of the context as
+ the its result, rather than a compiled script name.
+ <P>
+ You can store data and procedures (aka
+ handlers) in a script context. Then later, you can
+ run other scripts in this context, and they will see all the data and
+ handlers that were set up with this command. You do this by passing the
+ name of this context to the -context flag of the run or execute subcommands.
+ <P>
+ Unlike the straight compile command, the code compiled into a
+ script context is run immediatly, when it is compiled, to set up the context.
+ <DT>
+ <P>
+ <B>-name string</B>
+ <DD>
+ Use <I>string</I> as the name of the script or script context. If there is
+ already a script
+ of this name, it will be discarded. The same is true with script
+ contexts, unless the <I>-augment</I> flag is true. If no name is provided, then a
+ unique name will be created for you.
+ <DT>
+ <P>
+ <B>-parent contextName </B>
+ <DD>
+ This flag is also to be used in conjunction with the <A HREF="#-context">-context</A> flag.
+ <I>contextName</I> must be the name of a compiled script context. Then
+ the new script context will inherit the data and handlers from the
+ parent context.
+ </DL>
+ <P>
+ <DT>
+ <I>AppleScript</I> <B><A NAME="decompile">decompile</A></B> <I>scriptName</I>
+ <BR>
+ <DD>
+ This decompiles the script data compiled into the script scriptName,
+ and returns the source code.
+ <P>
+ <DT>
+ <I>AppleScript</I> <B>delete </B><I>scriptName</I>
+ <BR>
+ <DD>
+ This deletes the script data compiled into the script scriptName,
+ and frees up all the resources associated with it.
+ <P>
+ <DT>
+ <I>AppleScript</I> <B><A NAME="execute">execute</A> </B><I>?flags value?</I> <I>scriptData1
+ ?scriptData2 ...?</I>
+ <BR>
+ <DD>
+ This compiles and runs the script in scriptData (concatenating first), and
+ returns the results of the script execution. It is the same as doing
+ <I>compile</I> and then <I>run</I>, except that the compiled script is
+ immediately discarded.
+ <P>
+ <DT>
+ <I>AppleScript</I> <B><A NAME="info">info</A> </B><I>what</I>
+ <DD>
+ This gives info on the connection. The allowed values for "what" are:
+ <P>
+ <DL>
+ <DT>
+ <P>
+ <B>contexts </B> <I>?pattern?</I>
+ <DD>
+ This gives the list of the script contexts that have been.
+ If <I>pattern</I> is given, it only reports the contexts
+ that match this pattern.
+ <DT>
+ <!-- <P>
+ <B>language</B>
+ <DD>
+ Returns the language of this OSA component
+ <DT>
+ -->
+ <P>
+ <B>scripts</B> <I>?pattern?</I>
+ <DD>
+ This returns a list of the scripts that have been compiled in the
+ current connection. If <I>pattern</I> is given, it only reports the
+ script names that match this pattern.
+ </DL>
+ <P>
+ <DT>
+ <I>AppleScript</I> <B><A NAME="load">load</A></B> <I>?flag value? fileName</I>
+ <DD>
+ This loads compiled script data from a resource of type 'scpt' in the
+ file fileName, and returns a token for the script data. As with the
+ <I>compile</I> command, the script is not actually executed. Note that all
+ scripts compiled with Apple's "Script Editor" are stored as script
+ contexts. However, unlike with the "<I>compile -context</I>" command, the <I>load</I>
+ command does not run these scripts automatically. If you want to set up
+ the handlers contained in the loaded script, you must run it manually.
+ <P>
+ <I>load</I> takes the following flags:
+ <P>
+ <DL>
+ <DT>
+ <B>-rsrcname string</B>
+ <DD>
+ load a named resource of type 'scpt' using the rsrcname
+ flag.
+ <DT>
+ <P>
+ <B>-rsrcid integer</B>
+ <DD>
+ load a resource by number with the rsrcid flag.
+ </DL>
+ <DD>
+ <P>
+ If neither the <I>rsrcname</I> nor the <I>rsrcid</I> flag is provided, then the load
+ command defaults to -rsrcid = 128. This is the resource in which
+ Apple's Script Editor puts the script data when it writes out a
+ compiled script.
+ <P>
+ <DT>
+ <I>AppleScript</I> <B><A NAME="run">run</A></B> <I>?flag value?</I> <I>scriptName</I>
+ <DD>
+ This runs the script which was previously compiled into <I>scriptName</I>. If the script
+ runs successfully, the command returns the return value for this command,
+ coerced to a text string.
+ If there is an error in
+ the script execution, then it returns the error result from the
+ scripting component. It accepts the following flag:
+
+ <DL>
+ <DT>
+ <P>
+ <B>-context contextName</B>
+ <DD>
+ <I>contextName</I> must be a context created by a previous call to <I>compile</I> with
+ the -<I>context</I> flag set. This flag causes the code given in the
+ <I>scriptData</I> to be run in this "context". It will see all the data and
+ handlers that were set up previously.
+ <!-- <DT>
+ <B>-canswitch Boolean </B>
+ <DD>
+ If yes, then applications activated by the code
+ in scriptData will be allowed to switch to the foreground. If no, then
+ they will use the notification manager to indicate they need attention
+ (this usually means they blink the Finder icon, and put a check in the
+ application's entry in the Finder menu). -->
+ </DL>
+ <P>
+ <DT>
+ <I>AppleScript </I> <B> <A NAME="store">store</A></B> <I>?flag value? scriptName fileName</I>
+ <DD>
+ This stores a compiled script or script context into a resource of type 'scpt' in the
+ file fileName.
+ <P>
+ store takes the following flags:
+ <P>
+ <DL>
+ <DT>
+ <B>-rsrcname string</B>
+ <DD>
+ store to a named resource of type 'scpt' using the rsrcname
+ flag.
+ <DT>
+ <P>
+ <B>-rsrcid integer</B>
+ <DD>
+ store to a numbered resource with the rsrcid flag.
+ </DL>
+ <P>
+ <DD>
+ If neither the rsrcname nor the rsrcid flag is provided, then the load
+ command defaults to -rsrcid = 128. Apple's Script Editor can read in files written by
+ tclOSAScript with this setting of the <I>-rsrcid</I> flag.
+</DL>
+</DL>
+<H2>Notes:</H2>
+
+The AppleScript command is a stopgap command to fill the place of exec
+ on the Mac. It is not a supported command, and will likely change
+ as we broaden it to allow communication with other OSA languages.
+<H2>See Also:</H2>
+
+
+</BODY>
+
+</HTML>
diff --git a/mac/Background.doc b/mac/Background.doc
new file mode 100644
index 0000000..8c4409d
--- /dev/null
+++ b/mac/Background.doc
@@ -0,0 +1,92 @@
+Notes about the Background Only application template
+====================================================
+
+SCCS: @(#) Background.doc 1.1 97/11/03 17:05:54
+
+We have included sample code and project files for making a Background-Only
+ application (BOA) in Tcl. This could be used for server processes (like the
+Tcl Web-Server).
+
+Files:
+------
+
+* BOA_TclShells.¼ - This is the project file.
+* tclMacBOAAppInit.c - This is the AppInit file for the BOA App.
+* tclMacBOAMain - This is a replacement for the Tcl_Main for BOA's.
+
+Caveat:
+-------
+
+This is an unsupported addition to MacTcl. The main feature that will certainly
+change is how we handle AppleEvents. Currently, all the AppleEvent handling is
+done on the Tk side, which is not really right. Also, there is no way to
+register your own AppleEvent handlers, which is obviously something that would be
+useful in a BOA App. We will address these issues in Tcl8.1. If you need to
+register your own AppleEvent Handlers in the meantime, be aware that your code
+will probably break in Tcl8.1.
+
+I will also improve the basic code here based on feedback that I recieve. This
+is to be considered a first cut only at writing a BOA in Tcl.
+
+Introduction:
+-------------
+
+This project makes a double-clickable BOA application. It obviously needs
+some Tcl code to get it started. It will look for this code first in a
+'TEXT' resource in the application shell whose name is "bgScript.tcl". If
+it does not find any such resource, it will look for a file called
+bgScript.tcl in the application's folder. Otherwise it will quit with an
+error.
+
+It creates three files in the application folder to store stdin, stdout &
+stderr. They are imaginatively called temp.in, temp.out & temp.err. They
+will be opened append, so you do not need to erase them after each use of
+the BOA.
+
+The app does understand the "quit", and the "doScript" AppleEvents, so you can
+kill it with the former, and instruct it with the latter. It also has an
+aete, so you can target it with Apple's "Script Editor".
+
+For more information on Macintosh BOA's, see the Apple TechNote: 1070.
+
+Notifications:
+--------------
+
+BOA's are not supposed to have direct contact with the outside world. They
+are, however, allowed to go through the Notification Manager to post
+alerts. To this end, I have added a Tcl command called "bgnotify" to the
+shell, that simply posts a notification through the notification manager.
+
+To use it, say:
+
+bgnotify "Hi, there little buddy"
+
+It will make the system beep, and pop up an annoying message box with the
+text of the first argument to the command. While the message is up, Tcl
+is yielding processor time, but not processing any events.
+
+Errors:
+-------
+
+Usually a Tcl background application will have some startup code, opening
+up a server socket, or whatever, and at the end of this, will use the
+vwait command to kick off the event loop. If an error occurs in the
+startup code, it will kill the application, and a notification of the error
+will be posted through the Notification Manager.
+
+If an error occurs in the event handling code after the
+vwait, the error message will be written to the file temp.err. However,
+if you would like to have these errors post a notification as well, just
+define a proc called bgerror that takes one argument, the error message,
+and passes that off to "bgnotify", thusly:
+
+proc bgerror {mssg} {
+ bgnotify "A background error has occured\n $mssg"
+}
+
+Support:
+--------
+
+If you have any questions, contact me at:
+
+jim.ingham@eng.sun.com
diff --git a/mac/MW_TclAppleScriptHeader.pch b/mac/MW_TclAppleScriptHeader.pch
new file mode 100644
index 0000000..9575a8d
--- /dev/null
+++ b/mac/MW_TclAppleScriptHeader.pch
@@ -0,0 +1,46 @@
+/*
+ * MW_TclAppleScriptHeader.pch --
+ *
+ * This file is the source for a pre-compilied header that gets used
+ * for TclAppleScript. This make compilies go a bit
+ * faster. This file is only intended to be used in the MetroWerks
+ * CodeWarrior environment. It essentially acts as a place to set
+ * compiler flags. See MetroWerks documention for more details.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) MW_TclAppleScriptHeader.pch 1.1 97/09/09 16:38:07
+ */
+
+/*
+ * To use the compilied header you need to set the "Prefix file" in
+ * the "C/C++ Language" preference panel to point to the created
+ * compilied header. The name of the header depends on the
+ * architecture we are compiling for (see the code below). For
+ * example, for a 68k app the prefix file should be: MW_TclHeader68K.
+ */
+#if __POWERPC__
+#pragma precompile_target "MW_TclAppleScriptHeaderPPC"
+#include "MW_TclHeaderPPC"
+#elif __CFM68K__
+#pragma precompile_target "MW_TclAppleScriptHeaderCFM68K"
+#include "MW_TclHeaderCFM68K"
+#else
+#pragma precompile_target "MW_TclAppleScriptHeader68K"
+#include "MW_TclHeader68K"
+#endif
+
+
+#define TCL_REGISTER_LIBRARY 1
+/*
+ * Place any includes below that will are needed by the majority of the
+ * and is OK to be in any file in the system. The pragma's are used
+ * to control what functions are exported in the Tcl shared library.
+ */
+
+#pragma export on
+#pragma export off
+
diff --git a/mac/MW_TclHeader.pch b/mac/MW_TclHeader.pch
new file mode 100644
index 0000000..6a27544
--- /dev/null
+++ b/mac/MW_TclHeader.pch
@@ -0,0 +1,112 @@
+/*
+ * MW_TclHeader.pch --
+ *
+ * This file is the source for a pre-compilied header that gets used
+ * for all files in the Tcl projects. This make compilies go a bit
+ * faster. This file is only intended to be used in the MetroWerks
+ * CodeWarrior environment. It essentially acts as a place to set
+ * compiler flags. See MetroWerks documention for more details.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) MW_TclHeader.pch 1.27 97/11/20 18:45:25
+ */
+
+/*
+ * To use the compilied header you need to set the "Prefix file" in
+ * the "C/C++ Language" preference panel to point to the created
+ * compilied header. The name of the header depends on the
+ * architecture we are compiling for (see the code below). For
+ * example, for a 68k app the prefix file should be: MW_TclHeader68K.
+ */
+#if __POWERPC__
+#pragma precompile_target "MW_TclHeaderPPC"
+#elif __CFM68K__
+#pragma precompile_target "MW_TclHeaderCFM68K"
+#else
+#pragma precompile_target "MW_TclHeader68K"
+#endif
+
+/*
+ * Macintosh Tcl must be compiled with certain compiler options to
+ * ensure that it will work correctly. The following pragmas are
+ * used to ensure that those options are set correctly. An error
+ * will occur at compile time if they are not set correctly.
+ */
+
+#if !__option(enumsalwaysint)
+#error Tcl requires the Metrowerks setting "Enums always ints".
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(far_data)
+#error Tcl requires the Metrowerks setting "Far data".
+#endif
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(fourbyteints)
+#error Tcl requires the Metrowerks setting "4 byte ints".
+#endif
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(IEEEdoubles)
+#error Tcl requires the Metrowerks setting "8 byte doubles".
+#endif
+#endif
+
+/*
+ * The define is used most everywhere to tell Tcl (or any Tcl
+ * extensions) that we are compiling for the Macintosh platform.
+ */
+
+#define MAC_TCL
+
+/*
+ * The following defines control the behavior of the Macintosh
+ * Universial Headers.
+ */
+
+#define SystemSevenOrLater 1
+#define STRICT_CONTROLS 1
+#define STRICT_WINDOWS 1
+
+/*
+ * Define the following symbol if you want
+ * comprehensive debugging turned on.
+ */
+
+/* #define TCL_DEBUG */
+
+#ifdef TCL_DEBUG
+# define TCL_MEM_DEBUG
+# define TCL_TEST
+#endif
+
+
+/*
+ * For a while, we will continue to use the old routine names, so that
+ * people with older versions of CodeWarrior will still be able to compile
+ * the source (albeit they will have to update the project files themselves).
+ *
+ * At some point, we will convert over to the new routine names.
+ */
+
+#define OLDROUTINENAMES 1
+
+/*
+ * Place any includes below that will are needed by the majority of the
+ * and is OK to be in any file in the system. The pragma's are used
+ * to control what functions are exported in the Tcl shared library.
+ */
+
+#pragma export on
+#include "tcl.h"
+#include "tclMac.h"
+#include "tclInt.h"
+#pragma export off
+
diff --git a/mac/README b/mac/README
new file mode 100644
index 0000000..81cdac6
--- /dev/null
+++ b/mac/README
@@ -0,0 +1,187 @@
+Tcl 8.0p1 for Macintosh
+
+by Ray Johnson
+Sun Microsystems Laboratories
+rjohnson@eng.sun.com
+
+SCCS: @(#) README 1.30 97/11/20 22:01:16
+
+1. Introduction
+---------------
+
+This is the README file for the Macintosh version of the Tcl
+scripting language. The file consists of information specific
+to the Macintosh version of Tcl. For more general information
+please read the README file in the main Tcl directory.
+
+2. What's new?
+--------------
+
+The main new feature is the Tcl compilier. You should certainly
+notice the speed improvements. Any problems are probably
+generic rather than Mac specific. If you have questions or
+comments about the compilier feel free to forward them to the
+author of the compilier: Brian Lewis <btlewis@eng.sun.com>.
+Several things were fixed/changed since the a1 release so be
+sure to check this out.
+
+The largest incompatible change on the Mac is the removal of the
+following commands: "rm", "rmdir", "mkdir", "mv" and "cp". These
+commands were never really supported and their functionality is
+superceded by the file command.
+
+I've also added in a new "AppleScript" command. This was contributed
+by Jim Ingham who is a new member of the Tcl group. It's very cool.
+The command isn't actually in the core - you need to do a "package
+require Tclapplescript" to get access to it. This code is officially
+unsupported and will change in the next release. However, the core
+functionality is there and is stable enough to use. Documentation
+can be found in "AppleScript.html" in the mac subdirectory.
+
+The resource command has also been rewacked. You can now read and
+write any Mac resource. Tcl now has the new (and VERY COOL) binary
+command that will allow you to pack and unpack the resources into
+useful Tcl code. We will eventually provide Tcl libraries for
+accessing the most common resources.
+
+See the main Tcl README for other features new to Tcl 8.0.
+
+3. Mac specific features
+------------------------
+
+There are several features or enhancements in Tcl that are unique to
+the Macintosh version of Tcl. Here is a list of those features and
+pointers to where you can find more information about the feature.
+
+* The "resource" command allows you manipulate Macintosh resources.
+ A complete man page is available for this command.
+
+* The Mac version of the "source" command has an option to source from
+ a Macintosh resource. Check the man page from the source command
+ for details.
+
+* The only command NOT available on the Mac is the exec command.
+ However, we include a Mac only package called Tclapplescript that
+ provides access to Mac's AppleScript system. This command is still
+ under design & construction. Documentatin can be found in the mac
+ subdirectory in a file called "AppleScript.html".
+
+* The env variable on the Macintosh works rather differently than on
+ Windows or UNIX platforms. Check out the tclvars man page for
+ details.
+
+* The command "file volumes" returns the available volumes on your
+ Macintosh. Check out the file command for details.
+
+* The command "file attributes" has the Mac specific options of
+ -creator and -type which allow you to query and set the Macintosh
+ creator and type codes for Mac files. See file man page for details.
+
+* We have added a template for creating a Background-only Tcl application.
+ So you can use Tcl as a faceless server process. For more details, see
+ the file background.doc.
+
+If you are writing cross platform code but would still like to use
+some of these Mac specific commands, please remember to use the
+tcl_platform variable to special case your code.
+
+4. The Distribution
+-------------------
+
+Macintosh Tcl is distributed in three different forms. This
+should make it easier to only download what you need. The
+packages are as follows:
+
+mactk8.0.1.sea.hqx
+
+ This distribution is a "binary" only release. It contains an
+ installer program that will install a 68k, PowerPC, or Fat
+ version of the "Tcl Shell" and "Wish" applications. In addition,
+ it installs the Tcl & Tk libraries in the Extensions folder inside
+ your System Folder.
+
+mactcltk-full-8.0.1.sea.hqx
+
+ This release contains the full release of Tcl and Tk for the
+ Macintosh plus the More Files packages which Macintosh Tcl and Tk
+ rely on.
+
+mactcl-source-8.0.1.sea.hqx
+
+ This release contains the complete source for Tcl 8.0. In
+ addition, Metrowerks CodeWarrior libraries and project files
+ are included. However, you must already have the More Files
+ package to compile this code.
+
+5. Documentation
+----------------
+
+The "html" subdirectory contains reference documentation in
+in the HTML format. You may also find these pages at:
+
+ http://sunscript.sun.com/man/tcl8.0/contents.html
+
+Other documentation and sample Tcl scripts can be found at
+the Tcl ftp site:
+
+ ftp://ftp.neosoft.com/tcl/
+
+The internet news group comp.lang.tcl is also a valuable
+source of information about Tcl. A mailing list is also
+available (see below).
+
+6. Compiling Tcl
+----------------
+
+In order to compile Macintosh Tcl you must have the
+following items:
+
+ CodeWarrior Pro 1
+ Mac Tcl 8.0 (source)
+ More Files 1.4.3
+
+There are two sets of project files included with the package. The ones
+we use for the release are for CodeWarrior Pro 1, and are not compatible
+with CodeWarrior Gold release 11 and earlier. We have included the files
+for earlier versions of CodeWarrior in the folder tcl8.0:mac:CW11 Projects,
+but they are unsupported, and a little out of date.
+
+As of Tcl8.0p2, the code will also build under CW Pro 2. The only
+change that needs to be made is that float.mac.c should be replaced by
+float.c in the MacTcl MSL project file.
+
+However, there seems to be a bug in the CFM68K Linker in CW Pro 2,
+which renders the CFM68K Version under CW Pro 2 very unstable. I am
+working with MetroWerks to resolve this issue. The PPC version is
+fine, as is the Traditional 68K Shell. But if you need to use the
+CFM68K, then you must stay with CW Pro 1 for now.
+
+The project files included with the Mac Tcl source should work
+fine. The only thing you may need to update are the access paths.
+Unfortunantly, it's somewhat common for the project files to become
+slightly corrupted. The most common problem is that the "Prefix file"
+found in the "C/C++ Preference" panel is incorrect. This should be
+set to MW_TclHeaderPPC, MW_TclHeader68K or MW_TclHeaderCFM68K.
+
+To build the fat version of TclShell, open the project file "TclShells.¼",
+select the "TclShell" target, and build. All of the associated binaries will
+be built automoatically. There are also targets for building static 68K
+and Power PC builds, for building a CFM 68K build, and for building a
+shared library Power PC only build.
+
+Special notes:
+
+* There is a small bug in More Files 1.4.3. Also you should not use
+ MoreFiles 1.4.4 - 1.4.6. Look in the file named morefiles.doc for
+ more details.
+
+* You may not have the libmoto library which will cause a compile
+ error. You don't REALLY need it - it can be removed. Look at the
+ file libmoto.doc for more details.
+
+* Check out the file bugs.doc for information about known bugs.
+
+If you have comments or Bug reports send them to:
+Jim Ingham
+jingham@eng.sun.com
+
diff --git a/mac/bugs.doc b/mac/bugs.doc
new file mode 100644
index 0000000..5f4d45e
--- /dev/null
+++ b/mac/bugs.doc
@@ -0,0 +1,32 @@
+Known bug list for Tcl 8.0 for Macintosh
+
+by Ray Johnson
+Sun Microsystems Laboratories
+rjohnson@eng.sun.com
+
+SCCS: @(#) bugs.doc 1.6 97/08/13 18:09:12
+
+This was a new feature as of Tcl7.6b1 and as such I'll started with
+a clean slate. I currently know of no reproducable bugs. I often
+get vague reports - but nothing I've been able to confirm. Let
+me know what bugs you find!
+
+The Macintosh version of Tcl passes most all tests in the Tcl
+test suite. Slower Macs may fail some tests in event.test whose
+timing constraints are too tight. If other tests fail please report
+them.
+
+Ray
+
+Known bugs in the current release.
+
+* With the socket code you can't use the "localhost" host name. This
+ is actually a known bug in Apple's MacTcp stack. However, you can
+ use [info hostname] whereever you would have used "localhost" to
+ achive the same effect.
+
+* Most socket bugs have been fixed. We do have a couple of test cases
+ that will hang the Mac, however, and we are still working on them.
+ If you find additional test cases that show crashes please let us
+ know!
+
diff --git a/mac/libmoto.doc b/mac/libmoto.doc
new file mode 100644
index 0000000..50b98e1
--- /dev/null
+++ b/mac/libmoto.doc
@@ -0,0 +1,39 @@
+Notes about the use of libmoto
+------------------------------
+
+@(#) libmoto.doc 1.1 96/07/17 14:29:48
+
+First of all, libmoto is not required! If you don't have it, you
+can simply remove the library reference from the project file and
+everything should compile just fine.
+
+The libmoto library replaces certain functions in the MathLib and
+ANSI libraries. Motorola has optimized the functions in the library
+to run very fast on the PowerPC. As I said above, you don't need
+this library, but it does make things faster.
+
+Obtaining Libmoto:
+
+ For more information about Libmoto and how to doanload
+ it, visit the following URL:
+
+ http://www.mot.com/SPS/PowerPC/library/fact_sheet/libmoto.html
+
+ You will need to register for the library. However, the
+ library is free and you can use it in any commercial product
+ you might have.
+
+Installing Libmoto:
+
+ Just follow the instructions provided by the Motorola
+ README file. You need to make sure that the Libmoto
+ library is before the ANSI and MathLib libraries in
+ link order. Also, you will get several warnings stateing
+ that certain functions have already been defined in
+ Libmoto. (These can safely be ignored.)
+
+Finally, you can thank Kate Stewart of Motorola for twisting my
+arm at the Tcl/Tk Conference to provide some support for Libmoto.
+
+Ray Johnson
+
diff --git a/mac/morefiles.doc b/mac/morefiles.doc
new file mode 100644
index 0000000..b7c7118
--- /dev/null
+++ b/mac/morefiles.doc
@@ -0,0 +1,74 @@
+Notes about MoreFiles, dnr.c & other non-Tcl source files
+---------------------------------------------------------
+
+@(#) morefiles.doc 1.4 97/08/13 12:57:08
+
+The Macintosh distribution uses several source files that don't
+actually ship with Tcl. This sometimes causes problems or confusion
+to developers. This document should help clear up a few things.
+
+dnr.c
+-----
+
+We have found a way to work around some bugs in dnr.c that
+Apple has never fixed even though we sent in numerous bug reports.
+The file tclMacDNR.c simply set's some #pragma's and the includes
+the Apple dnr.c file. This should work the problems that many of
+you have reported with dnr.c.
+
+More Files
+----------
+
+Macintosh Tcl/Tk also uses Jim Luther's very useful package called
+More Files. More Files fixes many of the broken or underfunctional
+parts of the file system.
+
+More Files can be found on the MetroWerks CD and Developer CD from
+Apple. You can also down load the latest version from:
+
+ ftp://members.aol.com/JumpLong/
+
+The package can also be found at the home of Tcl/Tk for the mac:
+
+ ftp://ftp.sunlabs.com/pub/tcl/mac/
+
+I used to just link the More Files library in the Tcl projects.
+However, this caused problems when libraries wern't matched correctly.
+I'm now including the files in the Tcl project directly. This
+solves the problem of missmatched libraries - but may not always
+compile.
+
+If you get a compiliation error in MoreFiles you need to contact
+Jim Luther. His email address:
+
+ JumpLong@aol.com
+
+The version of More Files that we use with Tcl/Tk is 1.4.3. Early
+version may work as well..
+
+Unfortunantly, there is one bug in his library (in 1.4.3). The bug is
+in the function FSpGetFullPath found in the file FullPath.c. After
+the call to PBGetCatInfoSync you need to change the line:
+
+ if ( result == noErr )
+
+ to:
+
+ if ( (result == noErr) || (result == fnfErr) )
+
+
+The latest version of More Files is 1.4.6. Unfortunantly, this
+version has a bug that keeps it from working with shared libraries
+right out of the box. If you want to use 1.4.6 you can but you will
+need to make the following fix:
+
+ In the file "Opimization.h" in the More Files package you
+ need to remove the line "#pragma internal on". And in the
+ file "OptimazationEnd.h" you need to remove the line
+ "#pragma internal reset".
+
+Note: the version of MoreFile downloaded from the Sun Tcl/Tk site
+will have the fix included. (If you want you can send email to
+Jim Luther suggesting that he use Tcl for regression testing!)
+
+Ray Johnson
diff --git a/mac/porting.notes b/mac/porting.notes
new file mode 100644
index 0000000..f1f36e5
--- /dev/null
+++ b/mac/porting.notes
@@ -0,0 +1,23 @@
+Porting Notes
+-------------
+
+@(#) porting.notes 1.5 96/07/31 14:59:28
+
+Currently, the Macintosh version Tcl only compilies with the
+CodeWarrior C compilier from MetroWerks. It should be straight
+forward to port the Tcl source to MPW.
+
+Tcl on the Mac no longer requires the use of GUSI. It should now
+be easier to port Tcl/Tk to other compiliers such as Symantic C
+and MPW C.
+
+If you attempt to port Tcl to other Macintosh compiliers please
+let me know. I would be glad to help with advice and encouragement.
+If your efforts are succesfull I wold also be interested in puting
+those changes into the core distribution. Furthermore, please feel
+free to send me any notes you might make about your porting
+experience so I may include them in this file for others to reference.
+
+Ray Johnson
+ray.johnson@eng.sun.com
+
diff --git a/mac/tclMac.h b/mac/tclMac.h
new file mode 100644
index 0000000..eec480c
--- /dev/null
+++ b/mac/tclMac.h
@@ -0,0 +1,101 @@
+/*
+ * tclMac.h --
+ *
+ * Declarations of Macintosh specific public variables and procedures.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMac.h 1.8 97/06/24 18:59:08
+ */
+
+#ifndef _TCLMAC
+#define _TCLMAC
+
+#ifndef _TCL
+# include "tcl.h"
+#endif
+#include <Types.h>
+#include <Files.h>
+#include <Events.h>
+
+/*
+ * "export" is a MetroWerks specific pragma. It flags the linker that
+ * any symbols that are defined when this pragma is on will be exported
+ * to shared libraries that link with this library.
+ */
+
+#pragma export on
+
+typedef int (*Tcl_MacConvertEventPtr) _ANSI_ARGS_((EventRecord *eventPtr));
+
+/*
+ * This is needed by the shells to handle Macintosh events.
+ */
+
+EXTERN void Tcl_MacSetEventProc _ANSI_ARGS_((Tcl_MacConvertEventPtr procPtr));
+
+/*
+ * These routines are useful for handling using scripts from resources
+ * in the application shell
+ */
+
+EXTERN char * Tcl_MacConvertTextResource _ANSI_ARGS_((Handle resource));
+EXTERN int Tcl_MacEvalResource _ANSI_ARGS_((Tcl_Interp *interp,
+ char *resourceName, int resourceNumber, char *fileName));
+EXTERN Handle Tcl_MacFindResource _ANSI_ARGS_((Tcl_Interp *interp,
+ long resourceType, char *resourceName,
+ int resourceNumber, char *resFileRef, int * releaseIt));
+
+/* These routines support the new OSType object type (i.e. the packed 4
+ * character type and creator codes).
+ */
+
+EXTERN int Tcl_GetOSTypeFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr, OSType *osTypePtr));
+EXTERN void Tcl_SetOSTypeObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+ OSType osType));
+EXTERN Tcl_Obj * Tcl_NewOSTypeObj _ANSI_ARGS_((OSType osType));
+
+
+
+/*
+ * The following routines are utility functions in Tcl. They are exported
+ * here because they are needed in Tk. They are not officially supported,
+ * however. The first set are from the MoreFiles package.
+ */
+
+EXTERN pascal OSErr FSpGetDirectoryID(const FSSpec *spec,
+ long *theDirID, Boolean *isDirectory);
+EXTERN pascal short FSpOpenResFileCompat(const FSSpec *spec,
+ SignedByte permission);
+EXTERN pascal void FSpCreateResFileCompat(const FSSpec *spec,
+ OSType creator, OSType fileType,
+ ScriptCode scriptTag);
+/*
+ * Like the MoreFiles routines these fix problems in the standard
+ * Mac calls. These routines is from tclMacUtils.h.
+ */
+
+EXTERN int FSpLocationFromPath _ANSI_ARGS_((int length, char *path,
+ FSSpecPtr theSpec));
+EXTERN OSErr FSpPathFromLocation _ANSI_ARGS_((FSSpecPtr theSpec,
+ int *length, Handle *fullPath));
+
+/*
+ * These are not in MSL 2.1.2, so we need to export them from the
+ * Tcl shared library. They are found in the compat directory
+ * except the panic routine which is found in tclMacPanic.h.
+ */
+
+EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1,
+ CONST char *s2, size_t n));
+EXTERN int strcasecmp _ANSI_ARGS_((CONST char *s1,
+ CONST char *s2));
+EXTERN void panic _ANSI_ARGS_(TCL_VARARGS(char *,format));
+
+#pragma export reset
+
+#endif /* _TCLMAC */
diff --git a/mac/tclMacAETE.r b/mac/tclMacAETE.r
new file mode 100644
index 0000000..17fb6fe
--- /dev/null
+++ b/mac/tclMacAETE.r
@@ -0,0 +1,58 @@
+/*
+ * tclMacAETE.r --
+ *
+ * This file creates the Apple Event Terminology resources
+ * for use Tcl and Tk. It is not used in the Simple Tcl shell
+ * since SIOUX does not support AppleEvents. An example of its
+ * use in Tcl is the TclBGOnly project. And it is used in all the
+ * Tk Shells.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacAETE.r 1.1 97/11/03 17:06:22
+ */
+
+#define SystemSevenOrLater 1
+
+#include <Types.r>
+#include <SysTypes.r>
+#include <AEUserTermTypes.r>
+
+/*
+ * The following resources defines the Apple Events that Tk can be
+ * sent from Apple Script.
+ */
+
+resource 'aete' (0, "Wish Suite") {
+ 0x01, 0x00, english, roman,
+ {
+ "Required Suite",
+ "Events that every application should support",
+ 'reqd', 1, 1,
+ {},
+ {},
+ {},
+ {},
+
+ "Wish Suite", "Events for the Wish application", 'WIsH', 1, 1,
+ {
+ "do script", "Execute a Tcl script", 'misc', 'dosc',
+ 'TEXT', "Result", replyOptional, singleItem,
+ notEnumerated, reserved, reserved, reserved, reserved,
+ reserved, reserved, reserved, reserved, reserved,
+ reserved, reserved, reserved, reserved,
+ 'TEXT', "Script to execute", directParamRequired,
+ singleItem, notEnumerated, changesState, reserved,
+ reserved, reserved, reserved, reserved, reserved,
+ reserved, reserved, reserved, reserved, reserved,
+ reserved,
+ {},
+ },
+ {},
+ {},
+ {},
+ }
+};
diff --git a/mac/tclMacAlloc.c b/mac/tclMacAlloc.c
new file mode 100644
index 0000000..59d1417
--- /dev/null
+++ b/mac/tclMacAlloc.c
@@ -0,0 +1,340 @@
+/*
+ * tclMacAlloc.c --
+ *
+ * This is a very fast storage allocator. It allocates blocks of a
+ * small number of different sizes, and keeps free lists of each size.
+ * Blocks that don't exactly fit are passed up to the next larger size.
+ * Blocks over a certain size are directly allocated by calling NewPtr.
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson
+ *.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacAlloc.c 1.13 97/07/24 14:42:19
+ */
+
+#include "tclMacInt.h"
+#include "tclInt.h"
+#include <Memory.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Flags that are used by ConfigureMemory to define how the allocator
+ * should work. They can be or'd together.
+ */
+#define MEMORY_ALL_SYS 1 /* All memory should come from the system
+heap. */
+
+/*
+ * Amount of space to leave in the application heap for the Toolbox to work.
+ */
+
+#define TOOLBOX_SPACE (32 * 1024)
+
+static int memoryFlags = 0;
+static Handle toolGuardHandle = NULL;
+ /* This handle must be around so that we don't
+ * have NewGWorld failures. This handle is
+ * purgeable. Before we allocate any blocks,
+ * we see if this handle is still around.
+ * If it is not, then we try to get it again.
+ * If we can get it, we lock it and try
+ * to do the normal allocation, unlocking on
+ * the way out. If we can't, we go to the
+ * system heap directly. */
+
+
+/*
+ * The following typedef and variable are used to keep track of memory
+ * blocks that are allocated directly from the System Heap. These chunks
+ * of memory must always be freed - even if we crash.
+ */
+
+typedef struct listEl {
+ Handle memoryHandle;
+ struct listEl * next;
+} ListEl;
+
+ListEl * systemMemory = NULL;
+ListEl * appMemory = NULL;
+
+/*
+ * Prototypes for functions used only in this file.
+ */
+
+static pascal void CleanUpExitProc _ANSI_ARGS_((void));
+void ConfigureMemory _ANSI_ARGS_((int flags));
+void FreeAllMemory _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpSysRealloc --
+ *
+ * This function reallocates a chunk of system memory. If the
+ * chunk is already big enough to hold the new block, then no
+ * allocation happens.
+ *
+ * Results:
+ * Returns a pointer to the newly allocated block.
+ *
+ * Side effects:
+ * May copy the contents of the original block to the new block
+ * and deallocate the original block.
+ *
+ *----------------------------------------------------------------------
+ */
+
+VOID *
+TclpSysRealloc(
+ VOID *oldPtr, /* Original block */
+ unsigned int size) /* New size of block. */
+{
+ Handle hand;
+ void *newPtr;
+ int maxsize;
+
+ hand = * (Handle *) ((Ptr) oldPtr - sizeof(Handle));
+ maxsize = GetHandleSize(hand) - sizeof(Handle);
+ if (maxsize < size) {
+ newPtr = TclpSysAlloc(size, 1);
+ memcpy(newPtr, oldPtr, maxsize);
+ TclpSysFree(oldPtr);
+ } else {
+ newPtr = oldPtr;
+ }
+ return newPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpSysAlloc --
+ *
+ * Allocate a new block of memory free from the System.
+ *
+ * Results:
+ * Returns a pointer to a new block of memory.
+ *
+ * Side effects:
+ * May obtain memory from app or sys space. Info is added to
+ * overhead lists etc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+VOID *
+TclpSysAlloc(
+ long size, /* Size of block to allocate. */
+ int isBin) /* Is this a bin allocation? */
+{
+ Handle hand = NULL;
+ ListEl * newMemoryRecord;
+
+ if (!(memoryFlags & MEMORY_ALL_SYS)) {
+
+ /*
+ * If the guard handle has been purged, throw it away and try
+ * to allocate it again.
+ */
+
+ if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {
+ DisposeHandle(toolGuardHandle);
+ toolGuardHandle = NULL;
+ }
+
+ /*
+ * If we have never allocated the guard handle, or it was purged
+ * and thrown away, then try to allocate it again.
+ */
+
+ if (toolGuardHandle == NULL) {
+ toolGuardHandle = NewHandle(TOOLBOX_SPACE);
+ if (toolGuardHandle != NULL) {
+ HPurge(toolGuardHandle);
+ }
+ }
+
+ /*
+ * If we got the handle, lock it and do our allocation.
+ */
+
+ if (toolGuardHandle != NULL) {
+ HLock(toolGuardHandle);
+ hand = NewHandle(size + sizeof(Handle));
+ HUnlock(toolGuardHandle);
+ }
+ }
+ if (hand != NULL) {
+ newMemoryRecord = (ListEl *) NewPtr(sizeof(ListEl));
+ if (newMemoryRecord == NULL) {
+ DisposeHandle(hand);
+ return NULL;
+ }
+ newMemoryRecord->memoryHandle = hand;
+ newMemoryRecord->next = appMemory;
+ appMemory = newMemoryRecord;
+ } else {
+ /*
+ * Ran out of memory in application space. Lets try to get
+ * more memory from system. Otherwise, we return NULL to
+ * denote failure.
+ */
+ isBin = 0;
+ hand = NewHandleSys(size + sizeof(Handle));
+ if (hand == NULL) {
+ return NULL;
+ }
+ if (systemMemory == NULL) {
+ /*
+ * This is the first time we've attempted to allocate memory
+ * directly from the system heap. We need to now install the
+ * exit handle to ensure the memory is cleaned up.
+ */
+ TclMacInstallExitToShellPatch(CleanUpExitProc);
+ }
+ newMemoryRecord = (ListEl *) NewPtrSys(sizeof(ListEl));
+ if (newMemoryRecord == NULL) {
+ DisposeHandle(hand);
+ return NULL;
+ }
+ newMemoryRecord->memoryHandle = hand;
+ newMemoryRecord->next = systemMemory;
+ systemMemory = newMemoryRecord;
+ }
+ if (isBin) {
+ HLockHi(hand);
+ } else {
+ HLock(hand);
+ }
+ (** (Handle **) hand) = hand;
+
+ return (*hand + sizeof(Handle));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpSysFree --
+ *
+ * Free memory that we allocated back to the system.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpSysFree(
+ void * ptr) /* Free this system memory. */
+{
+ Handle hand;
+ OSErr err;
+
+ hand = * (Handle *) ((Ptr) ptr - sizeof(Handle));
+ DisposeHandle(hand);
+ err = MemError();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanUpExitProc --
+ *
+ * This procedure is invoked as an exit handler when ExitToShell
+ * is called. It removes any memory that was allocated directly
+ * from the system heap. This must be called when the application
+ * quits or the memory will never be freed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May free memory in the system heap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal void
+CleanUpExitProc()
+{
+ ListEl * memRecord;
+
+ while (systemMemory != NULL) {
+ memRecord = systemMemory;
+ systemMemory = memRecord->next;
+ DisposeHandle(memRecord->memoryHandle);
+ DisposePtr((void *) memRecord);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeAllMemory --
+ *
+ * This procedure frees all memory blocks allocated by the memory
+ * sub-system. Make sure you don't have any code that references
+ * any malloced data!
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees all memory allocated by TclpAlloc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+FreeAllMemory()
+{
+ ListEl * memRecord;
+
+ while (systemMemory != NULL) {
+ memRecord = systemMemory;
+ systemMemory = memRecord->next;
+ DisposeHandle(memRecord->memoryHandle);
+ DisposePtr((void *) memRecord);
+ }
+ while (appMemory != NULL) {
+ memRecord = appMemory;
+ appMemory = memRecord->next;
+ DisposeHandle(memRecord->memoryHandle);
+ DisposePtr((void *) memRecord);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureMemory --
+ *
+ * This procedure sets certain flags in this file that control
+ * how memory is allocated and managed. This call must be made
+ * before any call to TclpAlloc is made.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Certain state will be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+ConfigureMemory(
+ int flags) /* Flags that control memory alloc scheme. */
+{
+ memoryFlags = flags;
+}
diff --git a/mac/tclMacAppInit.c b/mac/tclMacAppInit.c
new file mode 100644
index 0000000..8906270
--- /dev/null
+++ b/mac/tclMacAppInit.c
@@ -0,0 +1,205 @@
+/*
+ * tclMacAppInit.c --
+ *
+ * Provides a version of the Tcl_AppInit procedure for the example shell.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacAppInit.c 1.20 97/07/28 11:03:58
+ */
+
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMac.h"
+#include "tclMacInt.h"
+
+#if defined(THINK_C)
+# include <console.h>
+#elif defined(__MWERKS__)
+# include <SIOUX.h>
+short InstallConsole _ANSI_ARGS_((short fd));
+#endif
+
+#ifdef TCL_TEST
+EXTERN int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+#endif /* TCL_TEST */
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int MacintoshInit _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * Main program for tclsh. This file can be used as a prototype
+ * for other applications using the Tcl library.
+ *
+ * Results:
+ * None. This procedure never returns (it exits the process when
+ * it's done.
+ *
+ * Side effects:
+ * This procedure initializes the Macintosh world and then
+ * calls Tcl_Main. Tcl_Main will never return except to exit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+main(
+ int argc, /* Number of arguments. */
+ char **argv) /* Array of argument strings. */
+{
+ char *newArgv[2];
+
+ if (MacintoshInit() != TCL_OK) {
+ Tcl_Exit(1);
+ }
+
+ argc = 1;
+ newArgv[0] = "tclsh";
+ newArgv[1] = NULL;
+ Tcl_Main(argc, newArgv, Tcl_AppInit);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppInit --
+ *
+ * This procedure performs application-specific initialization.
+ * Most applications, especially those that incorporate additional
+ * packages, will have their own version of this procedure.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error
+ * message in interp->result if an error occurs.
+ *
+ * Side effects:
+ * Depends on the startup script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppInit(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ if (Tcl_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+#ifdef TCL_TEST
+ if (Tcltest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
+ (Tcl_PackageInitProc *) NULL);
+ if (TclObjTest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+#endif /* TCL_TEST */
+
+ /*
+ * Call the init procedures for included packages. Each call should
+ * look like this:
+ *
+ * if (Mod_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * where "Mod" is the name of the module.
+ */
+
+ /*
+ * Call Tcl_CreateCommand for application-specific commands, if
+ * they weren't already created by the init procedures called above.
+ * Each call would loo like this:
+ *
+ * Tcl_CreateCommand(interp, "tclName", CFuncCmd, NULL, NULL);
+ */
+
+ /*
+ * Specify a user-specific startup script to invoke if the application
+ * is run interactively. On the Mac we can specifiy either a TEXT resource
+ * which contains the script or the more UNIX like file location
+ * may also used. (I highly recommend using the resource method.)
+ */
+
+ Tcl_SetVar(interp, "tcl_rcRsrcName", "tclshrc", TCL_GLOBAL_ONLY);
+ /* Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); */
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacintoshInit --
+ *
+ * This procedure calls initalization routines to set up a simple
+ * console on a Macintosh. This is necessary as the Mac doesn't
+ * have a stdout & stderr by default.
+ *
+ * Results:
+ * Returns TCL_OK if everything went fine. If it didn't the
+ * application should probably fail.
+ *
+ * Side effects:
+ * Inits the appropiate console package.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MacintoshInit()
+{
+#if GENERATING68K && !GENERATINGCFM
+ SetApplLimit(GetApplLimit() - (TCL_MAC_68K_STACK_GROWTH));
+#endif
+ MaxApplZone();
+
+#if defined(THINK_C)
+
+ /* Set options for Think C console package */
+ /* The console package calls the Mac init calls */
+ console_options.pause_atexit = 0;
+ console_options.title = "\pTcl Interpreter";
+
+#elif defined(__MWERKS__)
+
+ /* Set options for CodeWarrior SIOUX package */
+ SIOUXSettings.autocloseonquit = true;
+ SIOUXSettings.showstatusline = true;
+ SIOUXSettings.asktosaveonclose = false;
+ InstallConsole(0);
+ SIOUXSetTitle("\pTcl Interpreter");
+
+#elif defined(applec)
+
+ /* Init packages used by MPW SIOW package */
+ InitGraf((Ptr)&qd.thePort);
+ InitFonts();
+ InitWindows();
+ InitMenus();
+ TEInit();
+ InitDialogs(nil);
+ InitCursor();
+
+#endif
+
+ Tcl_MacSetEventProc((Tcl_MacConvertEventPtr) SIOUXHandleOneEvent);
+
+ /* No problems with initialization */
+ return TCL_OK;
+}
diff --git a/mac/tclMacApplication.r b/mac/tclMacApplication.r
new file mode 100644
index 0000000..90d3456
--- /dev/null
+++ b/mac/tclMacApplication.r
@@ -0,0 +1,75 @@
+/*
+ * tclMacApplication.r --
+ *
+ * This file creates resources for use Tcl Shell application.
+ * It should be viewed as an example of how to create a new
+ * Tcl application using the shared Tcl libraries.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacApplication.r 1.2 97/06/20 11:27:07
+ */
+
+#include <Types.r>
+#include <SysTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include "tcl.h"
+
+#if (TCL_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TCL_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TCL_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TCL_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TCL_MINOR_VERSION * 16) + TCL_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TCL_MINOR_VERSION * 16
+#endif
+
+resource 'vers' (1) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ TCL_PATCH_LEVEL ", by Ray Johnson © Sun Microsystems"
+};
+
+resource 'vers' (2) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ "Tcl Shell " TCL_PATCH_LEVEL " © 1996"
+};
+
+#define TCL_APP_CREATOR 'Tcl '
+
+type TCL_APP_CREATOR as 'STR ';
+resource TCL_APP_CREATOR (0, purgeable) {
+ "Tcl Shell " TCL_PATCH_LEVEL " © 1996"
+};
+
+/*
+ * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open
+ * to affect the text the Finder displays in the "kind" column and
+ * file info dialog. This information will be applied to all files
+ * with the listed creator and type.
+ */
+
+resource 'kind' (128, "Tcl kind", purgeable) {
+ TCL_APP_CREATOR,
+ 0, /* region = USA */
+ {
+ 'APPL', "Tcl Shell",
+ }
+};
diff --git a/mac/tclMacBOAAppInit.c b/mac/tclMacBOAAppInit.c
new file mode 100644
index 0000000..db9890b
--- /dev/null
+++ b/mac/tclMacBOAAppInit.c
@@ -0,0 +1,257 @@
+/*
+ * tclMacBOAAppInit.c --
+ *
+ * Provides a version of the Tcl_AppInit procedure for a
+ * Macintosh Background Only Application.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacBOAAppInit.c 1.1 97/11/03 17:06:21
+ */
+
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMac.h"
+#include "tclMacInt.h"
+#include <Fonts.h>
+#include <Windows.h>
+#include <Dialogs.h>
+#include <Menus.h>
+#include <Aliases.h>
+#include <LowMem.h>
+
+#include <AppleEvents.h>
+#include <SegLoad.h>
+#include <ToolUtils.h>
+
+#if defined(THINK_C)
+# include <console.h>
+#elif defined(__MWERKS__)
+# include <SIOUX.h>
+short InstallConsole _ANSI_ARGS_((short fd));
+#endif
+
+void TkMacInitAppleEvents(Tcl_Interp *interp);
+int HandleHighLevelEvents(EventRecord *eventPtr);
+
+#ifdef TCL_TEST
+EXTERN int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+#endif /* TCL_TEST */
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int MacintoshInit _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * Main program for tclsh. This file can be used as a prototype
+ * for other applications using the Tcl library.
+ *
+ * Results:
+ * None. This procedure never returns (it exits the process when
+ * it's done.
+ *
+ * Side effects:
+ * This procedure initializes the Macintosh world and then
+ * calls Tcl_Main. Tcl_Main will never return except to exit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+main(
+ int argc, /* Number of arguments. */
+ char **argv) /* Array of argument strings. */
+{
+ char *newArgv[3];
+
+ if (MacintoshInit() != TCL_OK) {
+ Tcl_Exit(1);
+ }
+
+ argc = 2;
+ newArgv[0] = "tclsh";
+ newArgv[1] = "bgScript.tcl";
+ newArgv[2] = NULL;
+ Tcl_Main(argc, newArgv, Tcl_AppInit);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppInit --
+ *
+ * This procedure performs application-specific initialization.
+ * Most applications, especially those that incorporate additional
+ * packages, will have their own version of this procedure.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error
+ * message in interp->result if an error occurs.
+ *
+ * Side effects:
+ * Depends on the startup script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppInit(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ Tcl_Channel tempChan;
+
+ if (Tcl_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+#ifdef TCL_TEST
+ if (Tcltest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
+ (Tcl_PackageInitProc *) NULL);
+ if (TclObjTest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+#endif /* TCL_TEST */
+
+ /*
+ * Call the init procedures for included packages. Each call should
+ * look like this:
+ *
+ * if (Mod_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * where "Mod" is the name of the module.
+ */
+
+ /*
+ * Call Tcl_CreateCommand for application-specific commands, if
+ * they weren't already created by the init procedures called above.
+ * Each call would loo like this:
+ *
+ * Tcl_CreateCommand(interp, "tclName", CFuncCmd, NULL, NULL);
+ */
+
+ /*
+ * Specify a user-specific startup script to invoke if the application
+ * is run interactively. On the Mac we can specifiy either a TEXT resource
+ * which contains the script or the more UNIX like file location
+ * may also used. (I highly recommend using the resource method.)
+ */
+
+ Tcl_SetVar(interp, "tcl_rcRsrcName", "tclshrc", TCL_GLOBAL_ONLY);
+
+ /* Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); */
+
+ /*
+ * We have to support at least the quit Apple Event.
+ */
+
+ TkMacInitAppleEvents(interp);
+
+ /*
+ * Open a file channel to put stderr, stdin, stdout...
+ */
+
+ tempChan = Tcl_OpenFileChannel(interp, ":temp.in", "a+", 0);
+ Tcl_SetStdChannel(tempChan,TCL_STDIN);
+ Tcl_RegisterChannel(interp, tempChan);
+ Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
+ Tcl_SetChannelOption(NULL, tempChan, "-buffering", "line");
+
+ tempChan = Tcl_OpenFileChannel(interp, ":temp.out", "a+", 0);
+ Tcl_SetStdChannel(tempChan,TCL_STDOUT);
+ Tcl_RegisterChannel(interp, tempChan);
+ Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
+ Tcl_SetChannelOption(NULL, tempChan, "-buffering", "line");
+
+ tempChan = Tcl_OpenFileChannel(interp, ":temp.err", "a+", 0);
+ Tcl_SetStdChannel(tempChan,TCL_STDERR);
+ Tcl_RegisterChannel(interp, tempChan);
+ Tcl_SetChannelOption(NULL, tempChan, "-translation", "cr");
+ Tcl_SetChannelOption(NULL, tempChan, "-buffering", "none");
+
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacintoshInit --
+ *
+ * This procedure calls initalization routines to set up a simple
+ * console on a Macintosh. This is necessary as the Mac doesn't
+ * have a stdout & stderr by default.
+ *
+ * Results:
+ * Returns TCL_OK if everything went fine. If it didn't the
+ * application should probably fail.
+ *
+ * Side effects:
+ * Inits the appropiate console package.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MacintoshInit()
+{
+ THz theZone = GetZone();
+ SysEnvRec sys;
+
+
+ /*
+ * There is a bug in systems earlier that 7.5.5, where a second BOA will
+ * get a corrupted heap. This is the fix from TechNote 1070
+ */
+
+ SysEnvirons(1, &sys);
+
+ if (sys.systemVersion < 0x0755)
+ {
+ if ( LMGetHeapEnd() != theZone->bkLim) {
+ LMSetHeapEnd(theZone->bkLim);
+ }
+ }
+
+#if GENERATING68K && !GENERATINGCFM
+ SetApplLimit(GetApplLimit() - (TCL_MAC_68K_STACK_GROWTH));
+#endif
+ MaxApplZone();
+
+ InitGraf((Ptr)&qd.thePort);
+
+ /* No problems with initialization */
+ Tcl_MacSetEventProc(HandleHighLevelEvents);
+
+ return TCL_OK;
+}
+
+int
+HandleHighLevelEvents(
+ EventRecord *eventPtr)
+{
+ int eventFound = false;
+
+ if (eventPtr->what == kHighLevelEvent) {
+ AEProcessAppleEvent(eventPtr);
+ eventFound = true;
+ } else if (eventPtr->what == nullEvent) {
+ eventFound = true;
+ }
+ return eventFound;
+}
diff --git a/mac/tclMacBOAMain.c b/mac/tclMacBOAMain.c
new file mode 100644
index 0000000..76689de
--- /dev/null
+++ b/mac/tclMacBOAMain.c
@@ -0,0 +1,360 @@
+/*
+ * tclMacBGMain.c --
+ *
+ * Main program for Macintosh Background Only Application shells.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacBOAMain.c 1.1 97/11/03 17:06:22
+ */
+
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include <Resources.h>
+#include <Notification.h>
+#include <Strings.h>
+
+/*
+ * This variable is used to get out of the modal loop of the
+ * notification manager.
+ */
+
+int NotificationIsDone = 0;
+
+/*
+ * The following code ensures that tclLink.c is linked whenever
+ * Tcl is linked. Without this code there's no reference to the
+ * code in that file from anywhere in Tcl, so it may not be
+ * linked into the application.
+ */
+
+EXTERN int Tcl_LinkVar();
+int (*tclDummyLinkVarPtr)() = Tcl_LinkVar;
+
+/*
+ * Declarations for various library procedures and variables (don't want
+ * to include tclPort.h here, because people might copy this file out of
+ * the Tcl source directory to make their own modified versions).
+ * Note: "exit" should really be declared here, but there's no way to
+ * declare it without causing conflicts with other definitions elsewher
+ * on some systems, so it's better just to leave it out.
+ */
+
+extern int isatty _ANSI_ARGS_((int fd));
+extern char * strcpy _ANSI_ARGS_((char *dst, CONST char *src));
+
+static Tcl_Interp *interp; /* Interpreter for application. */
+
+#ifdef TCL_MEM_DEBUG
+static char dumpFile[100]; /* Records where to dump memory allocation
+ * information. */
+static int quitFlag = 0; /* 1 means "checkmem" command was called,
+ * so the application should quit and dump
+ * memory allocation information. */
+#endif
+
+/*
+ * Forward references for procedures defined later in this file:
+ */
+
+#ifdef TCL_MEM_DEBUG
+static int CheckmemCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char *argv[]));
+#endif
+void TclMacDoNotification(char *mssg);
+void TclMacNotificationResponse(NMRecPtr nmRec);
+int Tcl_MacBGNotifyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Main --
+ *
+ * Main program for tclsh and most other Tcl-based applications.
+ *
+ * Results:
+ * None. This procedure never returns (it exits the process when
+ * it's done.
+ *
+ * Side effects:
+ * This procedure initializes the Tk world and then starts
+ * interpreting commands; almost anything could happen, depending
+ * on the script being interpreted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_Main(argc, argv, appInitProc)
+ int argc; /* Number of arguments. */
+ char **argv; /* Array of argument strings. */
+ Tcl_AppInitProc *appInitProc;
+ /* Application-specific initialization
+ * procedure to call after most
+ * initialization but before starting to
+ * execute commands. */
+{
+ Tcl_Obj *prompt1NamePtr = NULL;
+ Tcl_Obj *prompt2NamePtr = NULL;
+ Tcl_Obj *commandPtr = NULL;
+ char buffer[1000], *args, *fileName;
+ int code, tty;
+ int exitCode = 0;
+
+ Tcl_FindExecutable(argv[0]);
+ interp = Tcl_CreateInterp();
+#ifdef TCL_MEM_DEBUG
+ Tcl_InitMemory(interp);
+ Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, (ClientData) 0,
+ (Tcl_CmdDeleteProc *) NULL);
+#endif
+
+ /*
+ * Make command-line arguments available in the Tcl variables "argc"
+ * and "argv". If the first argument doesn't start with a "-" then
+ * strip it off and use it as the name of a script file to process.
+ */
+
+ fileName = NULL;
+ if ((argc > 1) && (argv[1][0] != '-')) {
+ fileName = argv[1];
+ argc--;
+ argv++;
+ }
+ args = Tcl_Merge(argc-1, argv+1);
+ Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
+ ckfree(args);
+ TclFormatInt(buffer, argc-1);
+ Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
+ TCL_GLOBAL_ONLY);
+
+ /*
+ * Set the "tcl_interactive" variable.
+ */
+
+ tty = isatty(0);
+ Tcl_SetVar(interp, "tcl_interactive",
+ ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
+
+ /*
+ * Invoke application-specific initialization.
+ */
+
+ if ((*appInitProc)(interp) != TCL_OK) {
+ Tcl_DString errStr;
+ Tcl_DStringInit(&errStr);
+ Tcl_DStringAppend(&errStr,
+ "application-specific initialization failed: \n", -1);
+ Tcl_DStringAppend(&errStr, interp->result, -1);
+ Tcl_DStringAppend(&errStr, "\n", 1);
+ TclMacDoNotification(Tcl_DStringValue(&errStr));
+ goto done;
+ }
+
+ /*
+ * Install the BGNotify command:
+ */
+
+ if ( Tcl_CreateObjCommand(interp, "bgnotify", Tcl_MacBGNotifyObjCmd, NULL,
+ (Tcl_CmdDeleteProc *) NULL) == NULL) {
+ goto done;
+ }
+
+ /*
+ * If a script file was specified then just source that file
+ * and quit. In this Mac BG Application version, we will try the
+ * resource fork first, then the file system second...
+ */
+
+ if (fileName != NULL) {
+ Str255 resName;
+ Handle resource;
+
+ strcpy((char *) resName + 1, fileName);
+ resName[0] = strlen(fileName);
+ resource = GetNamedResource('TEXT',resName);
+ if (resource != NULL) {
+ code = Tcl_MacEvalResource(interp, fileName, -1, NULL);
+ } else {
+ code = Tcl_EvalFile(interp, fileName);
+ }
+
+ if (code != TCL_OK) {
+ Tcl_DString errStr;
+
+ Tcl_DStringInit(&errStr);
+ Tcl_DStringAppend(&errStr, " Error sourcing resource or file: ", -1);
+ Tcl_DStringAppend(&errStr, fileName, -1);
+ Tcl_DStringAppend(&errStr, "\n\nError was: ", -1);
+ Tcl_DStringAppend(&errStr, interp->result, -1);
+
+ TclMacDoNotification(Tcl_DStringValue(&errStr));
+
+ }
+ goto done;
+ }
+
+
+ /*
+ * Rather than calling exit, invoke the "exit" command so that
+ * users can replace "exit" with some other command to do additional
+ * cleanup on exit. The Tcl_Eval call should never return.
+ */
+
+ done:
+ if (commandPtr != NULL) {
+ Tcl_DecrRefCount(commandPtr);
+ }
+ if (prompt1NamePtr != NULL) {
+ Tcl_DecrRefCount(prompt1NamePtr);
+ }
+ if (prompt2NamePtr != NULL) {
+ Tcl_DecrRefCount(prompt2NamePtr);
+ }
+ sprintf(buffer, "exit %d", exitCode);
+ Tcl_Eval(interp, buffer);
+}
+
+/*----------------------------------------------------------------------
+ *
+ * TclMacDoNotification --
+ *
+ * This posts an error message using the Notification manager.
+ *
+ * Results:
+ * Post a Notification Manager dialog.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TclMacDoNotification(mssg)
+ char *mssg;
+{
+ NMRec errorNot;
+ EventRecord *theEvent = NULL;
+ OSErr err;
+ char *ptr;
+
+ errorNot.qType = nmType;
+ errorNot.nmMark = 0;
+ errorNot.nmIcon = 0;
+ errorNot.nmSound = (Handle) -1;
+
+ for ( ptr = mssg; *ptr != '\0'; ptr++) {
+ if (*ptr == '\n') {
+ *ptr = '\r';
+ }
+ }
+
+ c2pstr(mssg);
+ errorNot.nmStr = (StringPtr) mssg;
+
+ errorNot.nmResp = NewNMProc(TclMacNotificationResponse);
+ errorNot.nmRefCon = SetCurrentA5();
+
+ NotificationIsDone = 0;
+
+ /*
+ * Cycle while waiting for the user to click on the
+ * notification box. Don't take any events off the event queue,
+ * since we want Tcl to do this but we want to block till the notification
+ * has been handled...
+ */
+
+ err = NMInstall(&errorNot);
+ if (err == noErr) {
+ while (!NotificationIsDone) {
+ WaitNextEvent(0, theEvent, 20, NULL);
+ }
+ NMRemove(&errorNot);
+ }
+
+ p2cstr((unsigned char *) mssg);
+}
+
+void
+TclMacNotificationResponse(nmRec)
+ NMRecPtr nmRec;
+{
+ int curA5;
+
+ curA5 = SetCurrentA5();
+ SetA5(nmRec->nmRefCon);
+
+ NotificationIsDone = 1;
+
+ SetA5(curA5);
+
+}
+
+int
+Tcl_MacBGNotifyObjCmd(clientData, interp, objc, objv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int objc;
+ Tcl_Obj **objv;
+{
+ Tcl_Obj *resultPtr;
+
+ resultPtr = Tcl_GetObjResult(interp);
+
+ if ( objc != 2 ) {
+ Tcl_WrongNumArgs(interp, 1, objv, "message");
+ return TCL_ERROR;
+ }
+
+ TclMacDoNotification(Tcl_GetStringFromObj(objv[1], (int *) NULL));
+ return TCL_OK;
+
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckmemCmd --
+ *
+ * This is the command procedure for the "checkmem" command, which
+ * causes the application to exit after printing information about
+ * memory usage to the file passed to this command as its first
+ * argument.
+ *
+ * Results:
+ * Returns a standard Tcl completion code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+#ifdef TCL_MEM_DEBUG
+
+ /* ARGSUSED */
+static int
+CheckmemCmd(clientData, interp, argc, argv)
+ ClientData clientData; /* Not used. */
+ Tcl_Interp *interp; /* Interpreter for evaluation. */
+ int argc; /* Number of arguments. */
+ char *argv[]; /* String values of arguments. */
+{
+ extern char *tclMemDumpFileName;
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " fileName\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ strcpy(dumpFile, argv[1]);
+ tclMemDumpFileName = dumpFile;
+ quitFlag = 1;
+ return TCL_OK;
+}
+#endif
diff --git a/mac/tclMacChan.c b/mac/tclMacChan.c
new file mode 100644
index 0000000..b05d2f5
--- /dev/null
+++ b/mac/tclMacChan.c
@@ -0,0 +1,1356 @@
+/*
+ * tclMacChan.c
+ *
+ * Channel drivers for Macintosh channels for the
+ * console fds.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacChan.c 1.43 97/06/20 11:27:48
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMacInt.h"
+#include <Aliases.h>
+#include <Errors.h>
+#include <Files.h>
+#include <Gestalt.h>
+#include <Processes.h>
+#include <Strings.h>
+#include <FSpCompat.h>
+#include <MoreFiles.h>
+#include <MoreFilesExtras.h>
+
+/*
+ * The following variable is used to tell whether this module has been
+ * initialized.
+ */
+
+static int initialized = 0;
+
+/*
+ * The following are flags returned by GetOpenMode. They
+ * are or'd together to determine how opening and handling
+ * a file should occur.
+ */
+
+#define TCL_RDONLY (1<<0)
+#define TCL_WRONLY (1<<1)
+#define TCL_RDWR (1<<2)
+#define TCL_CREAT (1<<3)
+#define TCL_TRUNC (1<<4)
+#define TCL_APPEND (1<<5)
+#define TCL_ALWAYS_APPEND (1<<6)
+#define TCL_EXCL (1<<7)
+#define TCL_NOCTTY (1<<8)
+#define TCL_NONBLOCK (1<<9)
+#define TCL_RW_MODES (TCL_RDONLY|TCL_WRONLY|TCL_RDWR)
+
+/*
+ * This structure describes per-instance state of a
+ * macintosh file based channel.
+ */
+
+typedef struct FileState {
+ short fileRef; /* Macintosh file reference number. */
+ Tcl_Channel fileChan; /* Pointer to the channel for this file. */
+ int watchMask; /* OR'ed set of flags indicating which events
+ * are being watched. */
+ int appendMode; /* Flag to tell if in O_APPEND mode or not. */
+ int volumeRef; /* Flag to tell if in O_APPEND mode or not. */
+ int pending; /* 1 if message is pending on queue. */
+ struct FileState *nextPtr; /* Pointer to next registered file. */
+} FileState;
+
+/*
+ * The following pointer refers to the head of the list of files managed
+ * that are being watched for file events.
+ */
+
+static FileState *firstFilePtr;
+
+/*
+ * The following structure is what is added to the Tcl event queue when
+ * file events are generated.
+ */
+
+typedef struct FileEvent {
+ Tcl_Event header; /* Information that is standard for
+ * all events. */
+ FileState *infoPtr; /* Pointer to file info structure. Note
+ * that we still have to verify that the
+ * file exists before dereferencing this
+ * pointer. */
+} FileEvent;
+
+
+/*
+ * Static routines for this file:
+ */
+
+static int CommonGetHandle _ANSI_ARGS_((ClientData instanceData,
+ int direction, ClientData *handlePtr));
+static void CommonWatch _ANSI_ARGS_((ClientData instanceData,
+ int mask));
+static int FileBlockMode _ANSI_ARGS_((ClientData instanceData,
+ int mode));
+static void FileChannelExitHandler _ANSI_ARGS_((
+ ClientData clientData));
+static void FileCheckProc _ANSI_ARGS_((ClientData clientData,
+ int flags));
+static int FileClose _ANSI_ARGS_((ClientData instanceData,
+ Tcl_Interp *interp));
+static int FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
+ int flags));
+static void FileInit _ANSI_ARGS_((void));
+static int FileInput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toRead, int *errorCode));
+static int FileOutput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toWrite, int *errorCode));
+static int FileSeek _ANSI_ARGS_((ClientData instanceData,
+ long offset, int mode, int *errorCode));
+static void FileSetupProc _ANSI_ARGS_((ClientData clientData,
+ int flags));
+static int GetOpenMode _ANSI_ARGS_((Tcl_Interp *interp,
+ char *string));
+static Tcl_Channel OpenFileChannel _ANSI_ARGS_((char *fileName, int mode,
+ int permissions, int *errorCodePtr));
+static int StdIOBlockMode _ANSI_ARGS_((ClientData instanceData,
+ int mode));
+static int StdIOClose _ANSI_ARGS_((ClientData instanceData,
+ Tcl_Interp *interp));
+static int StdIOInput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toRead, int *errorCode));
+static int StdIOOutput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toWrite, int *errorCode));
+static int StdIOSeek _ANSI_ARGS_((ClientData instanceData,
+ long offset, int mode, int *errorCode));
+static int StdReady _ANSI_ARGS_((ClientData instanceData,
+ int mask));
+
+/*
+ * This structure describes the channel type structure for file based IO:
+ */
+
+static Tcl_ChannelType consoleChannelType = {
+ "file", /* Type name. */
+ StdIOBlockMode, /* Set blocking/nonblocking mode.*/
+ StdIOClose, /* Close proc. */
+ StdIOInput, /* Input proc. */
+ StdIOOutput, /* Output proc. */
+ StdIOSeek, /* Seek proc. */
+ NULL, /* Set option proc. */
+ NULL, /* Get option proc. */
+ CommonWatch, /* Initialize notifier. */
+ CommonGetHandle /* Get OS handles out of channel. */
+};
+
+/*
+ * This variable describes the channel type structure for file based IO.
+ */
+
+static Tcl_ChannelType fileChannelType = {
+ "file", /* Type name. */
+ FileBlockMode, /* Set blocking or
+ * non-blocking mode.*/
+ FileClose, /* Close proc. */
+ FileInput, /* Input proc. */
+ FileOutput, /* Output proc. */
+ FileSeek, /* Seek proc. */
+ NULL, /* Set option proc. */
+ NULL, /* Get option proc. */
+ CommonWatch, /* Initialize notifier. */
+ CommonGetHandle /* Get OS handles out of channel. */
+};
+
+
+/*
+ * Hack to allow Mac Tk to override the TclGetStdChannels function.
+ */
+
+typedef void (*TclGetStdChannelsProc) _ANSI_ARGS_((Tcl_Channel *stdinPtr,
+ Tcl_Channel *stdoutPtr, Tcl_Channel *stderrPtr));
+
+TclGetStdChannelsProc getStdChannelsProc = NULL;
+
+/*
+ * Static variables to hold channels for stdin, stdout and stderr.
+ */
+
+static Tcl_Channel stdinChannel = NULL;
+static Tcl_Channel stdoutChannel = NULL;
+static Tcl_Channel stderrChannel = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileInit --
+ *
+ * This function initializes the file channel event source.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new event source.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FileInit()
+{
+ initialized = 1;
+ firstFilePtr = NULL;
+ Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL);
+ Tcl_CreateExitHandler(FileChannelExitHandler, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileChannelExitHandler --
+ *
+ * This function is called to cleanup the channel driver before
+ * Tcl is unloaded.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Destroys the communication window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FileChannelExitHandler(
+ ClientData clientData) /* Old window proc */
+{
+ Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
+ initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileSetupProc --
+ *
+ * This procedure is invoked before Tcl_DoOneEvent blocks waiting
+ * for an event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adjusts the block time if needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+FileSetupProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
+{
+ FileState *infoPtr;
+ Tcl_Time blockTime = { 0, 0 };
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return;
+ }
+
+ /*
+ * Check to see if there is a ready file. If so, poll.
+ */
+
+ for (infoPtr = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->watchMask) {
+ Tcl_SetMaxBlockTime(&blockTime);
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileCheckProc --
+ *
+ * This procedure is called by Tcl_DoOneEvent to check the file
+ * event source for events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May queue an event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FileCheckProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
+{
+ FileEvent *evPtr;
+ FileState *infoPtr;
+ int sentMsg = 0;
+ Tcl_Time blockTime = { 0, 0 };
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return;
+ }
+
+ /*
+ * Queue events for any ready files that don't already have events
+ * queued (caused by persistent states that won't generate WinSock
+ * events).
+ */
+
+ for (infoPtr = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
+ if (infoPtr->watchMask && !infoPtr->pending) {
+ infoPtr->pending = 1;
+ evPtr = (FileEvent *) ckalloc(sizeof(FileEvent));
+ evPtr->header.proc = FileEventProc;
+ evPtr->infoPtr = infoPtr;
+ Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+ *
+ * FileEventProc --
+ *
+ * This function is invoked by Tcl_ServiceEvent when a file event
+ * reaches the front of the event queue. This procedure invokes
+ * Tcl_NotifyChannel on the file.
+ *
+ * Results:
+ * Returns 1 if the event was handled, meaning it should be removed
+ * from the queue. Returns 0 if the event was not handled, meaning
+ * it should stay on the queue. The only time the event isn't
+ * handled is if the TCL_FILE_EVENTS flag bit isn't set.
+ *
+ * Side effects:
+ * Whatever the notifier callback does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to
+ * handle, such as TCL_FILE_EVENTS. */
+{
+ FileEvent *fileEvPtr = (FileEvent *)evPtr;
+ FileState *infoPtr;
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return 0;
+ }
+
+ /*
+ * Search through the list of watched files for the one whose handle
+ * matches the event. We do this rather than simply dereferencing
+ * the handle in the event so that files can be deleted while the
+ * event is in the queue.
+ */
+
+ for (infoPtr = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
+ if (fileEvPtr->infoPtr == infoPtr) {
+ infoPtr->pending = 0;
+ Tcl_NotifyChannel(infoPtr->fileChan, infoPtr->watchMask);
+ break;
+ }
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdIOBlockMode --
+ *
+ * Set blocking or non-blocking mode on channel.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or non-blocking mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StdIOBlockMode(
+ ClientData instanceData, /* Unused. */
+ int mode) /* The mode to set. */
+{
+ /*
+ * Do not allow putting stdin, stdout or stderr into nonblocking mode.
+ */
+
+ if (mode == TCL_MODE_NONBLOCKING) {
+ return EFAULT;
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdIOClose --
+ *
+ * Closes the IO channel.
+ *
+ * Results:
+ * 0 if successful, the value of errno if failed.
+ *
+ * Side effects:
+ * Closes the physical channel
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StdIOClose(
+ ClientData instanceData, /* Unused. */
+ Tcl_Interp *interp) /* Unused. */
+{
+ int fd, errorCode = 0;
+
+ /*
+ * Invalidate the stdio cache if necessary. Note that we assume that
+ * the stdio file and channel pointers will become invalid at the same
+ * time.
+ */
+
+ fd = (int) ((FileState*)instanceData)->fileRef;
+ if (fd == 0) {
+ fd = 0;
+ stdinChannel = NULL;
+ } else if (fd == 1) {
+ stdoutChannel = NULL;
+ } else if (fd == 2) {
+ stderrChannel = NULL;
+ } else {
+ panic("recieved invalid std file");
+ }
+
+ if (close(fd) < 0) {
+ errorCode = errno;
+ }
+
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CommonGetHandle --
+ *
+ * Called from Tcl_GetChannelFile to retrieve OS handles from inside
+ * a file based channel.
+ *
+ * Results:
+ * The appropriate handle or NULL if not present.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CommonGetHandle(
+ ClientData instanceData, /* The file state. */
+ int direction, /* Which handle to retrieve? */
+ ClientData *handlePtr)
+{
+ if ((direction == TCL_READABLE) || (direction == TCL_WRITABLE)) {
+ *handlePtr = (ClientData) ((FileState*)instanceData)->fileRef;
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdIOInput --
+ *
+ * Reads input from the IO channel into the buffer given. Returns
+ * count of how many bytes were actually read, and an error indication.
+ *
+ * Results:
+ * A count of how many bytes were read is returned and an error
+ * indication is returned in an output argument.
+ *
+ * Side effects:
+ * Reads input from the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+StdIOInput(
+ ClientData instanceData, /* Unused. */
+ char *buf, /* Where to store data read. */
+ int bufSize, /* How much space is available
+ * in the buffer? */
+ int *errorCode) /* Where to store error code. */
+{
+ int fd;
+ int bytesRead; /* How many bytes were read? */
+
+ *errorCode = 0;
+ errno = 0;
+ fd = (int) ((FileState*)instanceData)->fileRef;
+ bytesRead = read(fd, buf, (size_t) bufSize);
+ if (bytesRead > -1) {
+ return bytesRead;
+ }
+ *errorCode = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdIOOutput--
+ *
+ * Writes the given output on the IO channel. Returns count of how
+ * many characters were actually written, and an error indication.
+ *
+ * Results:
+ * A count of how many characters were written is returned and an
+ * error indication is returned in an output argument.
+ *
+ * Side effects:
+ * Writes output on the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StdIOOutput(
+ ClientData instanceData, /* Unused. */
+ char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCode) /* Where to store error code. */
+{
+ int written;
+ int fd;
+
+ *errorCode = 0;
+ errno = 0;
+ fd = (int) ((FileState*)instanceData)->fileRef;
+ written = write(fd, buf, (size_t) toWrite);
+ if (written > -1) {
+ return written;
+ }
+ *errorCode = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * StdIOSeek --
+ *
+ * Seeks on an IO channel. Returns the new position.
+ *
+ * Results:
+ * -1 if failed, the new position if successful. If failed, it
+ * also sets *errorCodePtr to the error code.
+ *
+ * Side effects:
+ * Moves the location at which the channel will be accessed in
+ * future operations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StdIOSeek(
+ ClientData instanceData, /* Unused. */
+ long offset, /* Offset to seek to. */
+ int mode, /* Relative to where
+ * should we seek? */
+ int *errorCodePtr) /* To store error code. */
+{
+ int newLoc;
+ int fd;
+
+ *errorCodePtr = 0;
+ fd = (int) ((FileState*)instanceData)->fileRef;
+ newLoc = lseek(fd, offset, mode);
+ if (newLoc > -1) {
+ return newLoc;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PidObjCmd --
+ *
+ * This procedure is invoked to process the "pid" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Tcl_PidObjCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* Not used. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST *objv; /* Argument strings. */
+{
+ ProcessSerialNumber psn;
+ char buf[20];
+ Tcl_Channel chan;
+ Tcl_Obj *resultPtr;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
+ return TCL_ERROR;
+ }
+ if (objc == 1) {
+ resultPtr = Tcl_GetObjResult(interp);
+ GetCurrentProcess(&psn);
+ sprintf(buf, "0x%08x%08x", psn.highLongOfPSN, psn.lowLongOfPSN);
+ Tcl_SetStringObj(resultPtr, buf, -1);
+ } else {
+ chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL),
+ NULL);
+ if (chan == (Tcl_Channel) NULL) {
+ return TCL_ERROR;
+ }
+ /*
+ * We can't create pipelines on the Mac so
+ * this will always return an empty list.
+ */
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetDefaultStdChannel --
+ *
+ * Constructs a channel for the specified standard OS handle.
+ *
+ * Results:
+ * Returns the specified default standard channel, or NULL.
+ *
+ * Side effects:
+ * May cause the creation of a standard channel and the underlying
+ * file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+TclGetDefaultStdChannel(
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
+{
+ Tcl_Channel channel = NULL;
+ int fd = 0; /* Initializations needed to prevent */
+ int mode = 0; /* compiler warning (used before set). */
+ char *bufMode = NULL;
+ char channelName[20];
+ int channelPermissions;
+ FileState *fileState;
+
+ /*
+ * If the channels were not created yet, create them now and
+ * store them in the static variables.
+ */
+
+ switch (type) {
+ case TCL_STDIN:
+ fd = 0;
+ channelPermissions = TCL_READABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDOUT:
+ fd = 1;
+ channelPermissions = TCL_WRITABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDERR:
+ fd = 2;
+ channelPermissions = TCL_WRITABLE;
+ bufMode = "none";
+ break;
+ default:
+ panic("TclGetDefaultStdChannel: Unexpected channel type");
+ break;
+ }
+
+ sprintf(channelName, "console%d", (int) fd);
+ fileState = (FileState *) ckalloc((unsigned) sizeof(FileState));
+ channel = Tcl_CreateChannel(&consoleChannelType, channelName,
+ (ClientData) fileState, channelPermissions);
+ fileState->fileChan = channel;
+ fileState->fileRef = fd;
+
+ /*
+ * Set up the normal channel options for stdio handles.
+ */
+
+ Tcl_SetChannelOption(NULL, channel, "-translation", "cr");
+ Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode);
+
+ return channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OpenFileChannel --
+ *
+ * Open an File based channel on Unix systems.
+ *
+ * Results:
+ * The new channel or NULL. If NULL, the output argument
+ * errorCodePtr is set to a POSIX error.
+ *
+ * Side effects:
+ * May open the channel and may cause creation of a file on the
+ * file system.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_OpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting;
+ * can be NULL. */
+ char *fileName, /* Name of file to open. */
+ char *modeString, /* A list of POSIX open modes or
+ * a string such as "rw". */
+ int permissions) /* If the open involves creating a
+ * file, with what modes to create
+ * it? */
+{
+ Tcl_Channel chan;
+ int mode;
+ char *nativeName;
+ Tcl_DString buffer;
+ int errorCode;
+
+ mode = GetOpenMode(interp, modeString);
+ if (mode == -1) {
+ return NULL;
+ }
+
+ nativeName = Tcl_TranslateFileName(interp, fileName, &buffer);
+ if (nativeName == NULL) {
+ return NULL;
+ }
+
+ chan = OpenFileChannel(nativeName, mode, permissions, &errorCode);
+ Tcl_DStringFree(&buffer);
+
+ if (chan == NULL) {
+ Tcl_SetErrno(errorCode);
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "couldn't open \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ }
+ return NULL;
+ }
+
+ return chan;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OpenFileChannel--
+ *
+ * Opens a Macintosh file and creates a Tcl channel to control it.
+ *
+ * Results:
+ * A Tcl channel.
+ *
+ * Side effects:
+ * Will open a Macintosh file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Channel
+OpenFileChannel(
+ char *fileName, /* Name of file to open. */
+ int mode, /* Mode for opening file. */
+ int permissions, /* If the open involves creating a
+ * file, with what modes to create
+ * it? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ int channelPermissions;
+ Tcl_Channel chan;
+ char macPermision;
+ FSSpec fileSpec;
+ OSErr err;
+ short fileRef;
+ FileState *fileState;
+ char channelName[64];
+
+ /*
+ * Note we use fsRdWrShPerm instead of fsRdWrPerm which allows shared
+ * writes on a file. This isn't common on a mac but is common with
+ * Windows and UNIX and the feature is used by Tcl.
+ */
+
+ switch (mode & (TCL_RDONLY | TCL_WRONLY | TCL_RDWR)) {
+ case TCL_RDWR:
+ channelPermissions = (TCL_READABLE | TCL_WRITABLE);
+ macPermision = fsRdWrShPerm;
+ break;
+ case TCL_WRONLY:
+ /*
+ * Mac's fsRdPerm permission actually defaults to fsRdWrPerm because
+ * the Mac OS doesn't realy support write only access. We explicitly
+ * set the permission fsRdWrShPerm so that we can have shared write
+ * access.
+ */
+ channelPermissions = TCL_WRITABLE;
+ macPermision = fsRdWrShPerm;
+ break;
+ case TCL_RDONLY:
+ default:
+ channelPermissions = TCL_READABLE;
+ macPermision = fsRdPerm;
+ break;
+ }
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+ if ((err != noErr) && (err != fnfErr)) {
+ *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
+ Tcl_SetErrno(errno);
+ return NULL;
+ }
+
+ if ((err == fnfErr) && (mode & TCL_CREAT)) {
+ err = HCreate(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, 'MPW ', 'TEXT');
+ if (err != noErr) {
+ *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
+ Tcl_SetErrno(errno);
+ return NULL;
+ }
+ } else if ((mode & TCL_CREAT) && (mode & TCL_EXCL)) {
+ *errorCodePtr = errno = EEXIST;
+ Tcl_SetErrno(errno);
+ return NULL;
+ }
+
+ err = HOpenDF(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, macPermision, &fileRef);
+ if (err != noErr) {
+ *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
+ Tcl_SetErrno(errno);
+ return NULL;
+ }
+
+ if (mode & TCL_TRUNC) {
+ SetEOF(fileRef, 0);
+ }
+
+ sprintf(channelName, "file%d", (int) fileRef);
+ fileState = (FileState *) ckalloc((unsigned) sizeof(FileState));
+ chan = Tcl_CreateChannel(&fileChannelType, channelName,
+ (ClientData) fileState, channelPermissions);
+ if (chan == (Tcl_Channel) NULL) {
+ *errorCodePtr = errno = EFAULT;
+ Tcl_SetErrno(errno);
+ FSClose(fileRef);
+ ckfree((char *) fileState);
+ return NULL;
+ }
+
+ fileState->fileChan = chan;
+ fileState->volumeRef = fileSpec.vRefNum;
+ fileState->fileRef = fileRef;
+ fileState->pending = 0;
+ fileState->watchMask = 0;
+ if (mode & TCL_ALWAYS_APPEND) {
+ fileState->appendMode = true;
+ } else {
+ fileState->appendMode = false;
+ }
+
+ if ((mode & TCL_ALWAYS_APPEND) || (mode & TCL_APPEND)) {
+ if (Tcl_Seek(chan, 0, SEEK_END) < 0) {
+ *errorCodePtr = errno = EFAULT;
+ Tcl_SetErrno(errno);
+ Tcl_Close(NULL, chan);
+ FSClose(fileRef);
+ ckfree((char *) fileState);
+ return NULL;
+ }
+ }
+
+ return chan;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileBlockMode --
+ *
+ * Set blocking or non-blocking mode on channel. Macintosh files
+ * can never really be set to blocking or non-blocking modes.
+ * However, we don't generate an error - we just return success.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or non-blocking mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileBlockMode(
+ ClientData instanceData, /* Unused. */
+ int mode) /* The mode to set. */
+{
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileClose --
+ *
+ * Closes the IO channel.
+ *
+ * Results:
+ * 0 if successful, the value of errno if failed.
+ *
+ * Side effects:
+ * Closes the physical channel
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileClose(
+ ClientData instanceData, /* Unused. */
+ Tcl_Interp *interp) /* Unused. */
+{
+ FileState *fileState = (FileState *) instanceData;
+ int errorCode = 0;
+ OSErr err;
+
+ err = FSClose(fileState->fileRef);
+ FlushVol(NULL, fileState->volumeRef);
+ if (err != noErr) {
+ errorCode = errno = TclMacOSErrorToPosixError(err);
+ panic("error during file close");
+ }
+
+ ckfree((char *) fileState);
+ Tcl_SetErrno(errorCode);
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileInput --
+ *
+ * Reads input from the IO channel into the buffer given. Returns
+ * count of how many bytes were actually read, and an error indication.
+ *
+ * Results:
+ * A count of how many bytes were read is returned and an error
+ * indication is returned in an output argument.
+ *
+ * Side effects:
+ * Reads input from the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+FileInput(
+ ClientData instanceData, /* Unused. */
+ char *buffer, /* Where to store data read. */
+ int bufSize, /* How much space is available
+ * in the buffer? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ FileState *fileState = (FileState *) instanceData;
+ OSErr err;
+ long length = bufSize;
+
+ *errorCodePtr = 0;
+ errno = 0;
+ err = FSRead(fileState->fileRef, &length, buffer);
+ if ((err == noErr) || (err == eofErr)) {
+ return length;
+ } else {
+ switch (err) {
+ case ioErr:
+ *errorCodePtr = errno = EIO;
+ case afpAccessDenied:
+ *errorCodePtr = errno = EACCES;
+ default:
+ *errorCodePtr = errno = EINVAL;
+ }
+ return -1;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileOutput--
+ *
+ * Writes the given output on the IO channel. Returns count of how
+ * many characters were actually written, and an error indication.
+ *
+ * Results:
+ * A count of how many characters were written is returned and an
+ * error indication is returned in an output argument.
+ *
+ * Side effects:
+ * Writes output on the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileOutput(
+ ClientData instanceData, /* Unused. */
+ char *buffer, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ FileState *fileState = (FileState *) instanceData;
+ long length = toWrite;
+ OSErr err;
+
+ *errorCodePtr = 0;
+ errno = 0;
+
+ if (fileState->appendMode == true) {
+ FileSeek(instanceData, 0, SEEK_END, errorCodePtr);
+ *errorCodePtr = 0;
+ }
+
+ err = FSWrite(fileState->fileRef, &length, buffer);
+ if (err == noErr) {
+ err = FlushFile(fileState->fileRef);
+ } else {
+ *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ }
+ return length;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileSeek --
+ *
+ * Seeks on an IO channel. Returns the new position.
+ *
+ * Results:
+ * -1 if failed, the new position if successful. If failed, it
+ * also sets *errorCodePtr to the error code.
+ *
+ * Side effects:
+ * Moves the location at which the channel will be accessed in
+ * future operations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileSeek(
+ ClientData instanceData, /* Unused. */
+ long offset, /* Offset to seek to. */
+ int mode, /* Relative to where
+ * should we seek? */
+ int *errorCodePtr) /* To store error code. */
+{
+ FileState *fileState = (FileState *) instanceData;
+ IOParam pb;
+ OSErr err;
+
+ *errorCodePtr = 0;
+ pb.ioCompletion = NULL;
+ pb.ioRefNum = fileState->fileRef;
+ if (mode == SEEK_SET) {
+ pb.ioPosMode = fsFromStart;
+ } else if (mode == SEEK_END) {
+ pb.ioPosMode = fsFromLEOF;
+ } else if (mode == SEEK_CUR) {
+ err = PBGetFPosSync((ParmBlkPtr) &pb);
+ if (pb.ioResult == noErr) {
+ if (offset == 0) {
+ return pb.ioPosOffset;
+ }
+ offset += pb.ioPosOffset;
+ }
+ pb.ioPosMode = fsFromStart;
+ }
+ pb.ioPosOffset = offset;
+ err = PBSetFPosSync((ParmBlkPtr) &pb);
+ if (pb.ioResult == noErr){
+ return pb.ioPosOffset;
+ } else if (pb.ioResult == eofErr) {
+ long currentEOF, newEOF;
+ long buffer, i, length;
+
+ err = PBGetEOFSync((ParmBlkPtr) &pb);
+ currentEOF = (long) pb.ioMisc;
+ if (mode == SEEK_SET) {
+ newEOF = offset;
+ } else if (mode == SEEK_END) {
+ newEOF = offset + currentEOF;
+ } else if (mode == SEEK_CUR) {
+ err = PBGetFPosSync((ParmBlkPtr) &pb);
+ newEOF = offset + pb.ioPosOffset;
+ }
+
+ /*
+ * Write 0's to the new EOF.
+ */
+ pb.ioPosOffset = 0;
+ pb.ioPosMode = fsFromLEOF;
+ err = PBGetFPosSync((ParmBlkPtr) &pb);
+ length = 1;
+ buffer = 0;
+ for (i = 0; i < (newEOF - currentEOF); i++) {
+ err = FSWrite(fileState->fileRef, &length, &buffer);
+ }
+ err = PBGetFPosSync((ParmBlkPtr) &pb);
+ if (pb.ioResult == noErr){
+ return pb.ioPosOffset;
+ }
+ }
+ *errorCodePtr = errno = TclMacOSErrorToPosixError(err);
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CommonWatch --
+ *
+ * Initialize the notifier to watch handles from this channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CommonWatch(
+ ClientData instanceData, /* The file state. */
+ int mask) /* Events of interest; an OR-ed
+ * combination of TCL_READABLE,
+ * TCL_WRITABLE and TCL_EXCEPTION. */
+{
+ FileState **nextPtrPtr, *ptr;
+ FileState *infoPtr = (FileState *) instanceData;
+ int oldMask = infoPtr->watchMask;
+
+ if (!initialized) {
+ FileInit();
+ }
+
+ infoPtr->watchMask = mask;
+ if (infoPtr->watchMask) {
+ if (!oldMask) {
+ infoPtr->nextPtr = firstFilePtr;
+ firstFilePtr = infoPtr;
+ }
+ } else {
+ if (oldMask) {
+ /*
+ * Remove the file from the list of watched files.
+ */
+
+ for (nextPtrPtr = &firstFilePtr, ptr = *nextPtrPtr;
+ ptr != NULL;
+ nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {
+ if (infoPtr == ptr) {
+ *nextPtrPtr = ptr->nextPtr;
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOpenMode --
+ *
+ * Description:
+ * Computes a POSIX mode mask from a given string and also sets
+ * a flag to indicate whether the caller should seek to EOF during
+ * opening of the file.
+ *
+ * Results:
+ * On success, returns mode to pass to "open". If an error occurs, the
+ * returns -1 and if interp is not NULL, sets interp->result to an
+ * error message.
+ *
+ * Side effects:
+ * Sets the integer referenced by seekFlagPtr to 1 if the caller
+ * should seek to EOF during opening the file.
+ *
+ * Special note:
+ * This code is based on a prototype implementation contributed
+ * by Mark Diekhans.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetOpenMode(
+ Tcl_Interp *interp, /* Interpreter to use for error
+ * reporting - may be NULL. */
+ char *string) /* Mode string, e.g. "r+" or
+ * "RDONLY CREAT". */
+{
+ int mode, modeArgc, c, i, gotRW;
+ char **modeArgv, *flag;
+
+ /*
+ * Check for the simpler fopen-like access modes (e.g. "r"). They
+ * are distinguished from the POSIX access modes by the presence
+ * of a lower-case first letter.
+ */
+
+ mode = 0;
+ if (islower(UCHAR(string[0]))) {
+ switch (string[0]) {
+ case 'r':
+ mode = TCL_RDONLY;
+ break;
+ case 'w':
+ mode = TCL_WRONLY|TCL_CREAT|TCL_TRUNC;
+ break;
+ case 'a':
+ mode = TCL_WRONLY|TCL_CREAT|TCL_APPEND;
+ break;
+ default:
+ error:
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp,
+ "illegal access mode \"", string, "\"",
+ (char *) NULL);
+ }
+ return -1;
+ }
+ if (string[1] == '+') {
+ mode &= ~(TCL_RDONLY|TCL_WRONLY);
+ mode |= TCL_RDWR;
+ if (string[2] != 0) {
+ goto error;
+ }
+ } else if (string[1] != 0) {
+ goto error;
+ }
+ return mode;
+ }
+
+ /*
+ * The access modes are specified using a list of POSIX modes
+ * such as TCL_CREAT.
+ */
+
+ if (Tcl_SplitList(interp, string, &modeArgc, &modeArgv) != TCL_OK) {
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AddErrorInfo(interp,
+ "\n while processing open access modes \"");
+ Tcl_AddErrorInfo(interp, string);
+ Tcl_AddErrorInfo(interp, "\"");
+ }
+ return -1;
+ }
+
+ gotRW = 0;
+ for (i = 0; i < modeArgc; i++) {
+ flag = modeArgv[i];
+ c = flag[0];
+ if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) {
+ mode = (mode & ~TCL_RW_MODES) | TCL_RDONLY;
+ gotRW = 1;
+ } else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) {
+ mode = (mode & ~TCL_RW_MODES) | TCL_WRONLY;
+ gotRW = 1;
+ } else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) {
+ mode = (mode & ~TCL_RW_MODES) | TCL_RDWR;
+ gotRW = 1;
+ } else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) {
+ mode |= TCL_ALWAYS_APPEND;
+ } else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) {
+ mode |= TCL_CREAT;
+ } else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) {
+ mode |= TCL_EXCL;
+ } else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) {
+ mode |= TCL_NOCTTY;
+ } else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) {
+ mode |= TCL_NONBLOCK;
+ } else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) {
+ mode |= TCL_TRUNC;
+ } else {
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "invalid access mode \"", flag,
+ "\": must be RDONLY, WRONLY, RDWR, APPEND, CREAT",
+ " EXCL, NOCTTY, NONBLOCK, or TRUNC", (char *) NULL);
+ }
+ ckfree((char *) modeArgv);
+ return -1;
+ }
+ }
+ ckfree((char *) modeArgv);
+ if (!gotRW) {
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "access mode must include either",
+ " RDONLY, WRONLY, or RDWR", (char *) NULL);
+ }
+ return -1;
+ }
+ return mode;
+}
diff --git a/mac/tclMacDNR.c b/mac/tclMacDNR.c
new file mode 100644
index 0000000..b42b4dd
--- /dev/null
+++ b/mac/tclMacDNR.c
@@ -0,0 +1,23 @@
+/*
+ * tclMacDNR.c
+ *
+ * This file actually just includes the file "dnr.c" provided by
+ * Apple Computer and redistributed by MetroWerks (and other compiler
+ * vendors.) Unfortunantly, despite various bug reports, dnr.c uses
+ * C++ style comments and will not compile under the "ANSI Strict"
+ * mode that the rest of Tcl compiles under. Furthermore, the Apple
+ * license prohibits me from redistributing a corrected version of
+ * dnr.c. This file uses a pragma to turn off the Strict ANSI option
+ * and then includes the dnr.c file.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacDNR.c 1.2 97/01/28 10:37:21
+ */
+
+#pragma ANSI_strict off
+#include <dnr.c>
+#pragma ANSI_strict reset
diff --git a/mac/tclMacEnv.c b/mac/tclMacEnv.c
new file mode 100644
index 0000000..afb6028
--- /dev/null
+++ b/mac/tclMacEnv.c
@@ -0,0 +1,536 @@
+/*
+ * tclMacEnv.c --
+ *
+ * Implements the "environment" on a Macintosh.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacEnv.c 1.29 96/12/06 14:19:57
+ */
+
+#include <Gestalt.h>
+#include <Folders.h>
+#include <TextUtils.h>
+#include <Resources.h>
+#include <string.h>
+
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include "tclPort.h"
+
+#define kMaxEnvStringSize 255
+#define kMaxEnvVarSize 100
+#define kLoginnameTag "LOGIN="
+#define kUsernameTag "USER="
+#define kDefaultDirTag "HOME="
+
+/*
+ * The following specifies a text file where additional environment variables
+ * can be set. The file must reside in the preferences folder. If the file
+ * doesn't exist NO error will occur. Commet out the difinition if you do
+ * NOT want to use an environment variables file.
+ */
+#define kPrefsFile "Tcl Environment Variables"
+
+/*
+ * The following specifies the Name of a 'STR#' resource in the application
+ * where additional environment variables may be set. If the resource doesn't
+ * exist no errors will occur. Commet it out if you don't want it.
+ */
+#define REZ_ENV "\pTcl Environment Variables"
+
+/* Globals */
+char **environ = NULL;
+
+/*
+ * Declarations for local procedures defined in this file:
+ */
+static char ** RezRCVariables _ANSI_ARGS_((void));
+static char ** FileRCVariables _ANSI_ARGS_((void));
+static char ** PathVariables _ANSI_ARGS_((void));
+static char ** SystemVariables _ANSI_ARGS_((void));
+static char * MakeFolderEnvVar _ANSI_ARGS_((char * prefixTag,
+ long whichFolder));
+static char * GetUserName _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RezRCVariables --
+ *
+ * Creates environment variables from the applications resource fork.
+ * The function looks for the 'STR#' resource with the name defined
+ * in the #define REZ_ENV. If the define is not defined this code
+ * will not be included. If the resource doesn't exist or no strings
+ * reside in the resource nothing will happen.
+ *
+ * Results:
+ * ptr to value on success, NULL if error.
+ *
+ * Side effects:
+ * Memory is allocated and returned to the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef REZ_ENV
+static char **
+RezRCVariables()
+{
+ Handle envStrs = NULL;
+ char** rezEnv = NULL;
+ short int numStrs;
+
+ envStrs = GetNamedResource('STR#', REZ_ENV);
+ if (envStrs == NULL) return NULL;
+ numStrs = *((short *) (*envStrs));
+
+ rezEnv = (char **) ckalloc((numStrs + 1) * sizeof(char *));
+
+ if (envStrs != NULL) {
+ ResType theType;
+ Str255 theName;
+ short theID, index = 1;
+ int i = 0;
+ char* string;
+
+ GetResInfo(envStrs, &theID, &theType, theName);
+ for(;;) {
+ GetIndString(theName, theID, index++);
+ if (theName[0] == '\0') break;
+ string = (char *) ckalloc(theName[0] + 2);
+ strncpy(string, (char *) theName + 1, theName[0]);
+ string[theName[0]] = '\0';
+ rezEnv[i++] = string;
+ }
+ ReleaseResource(envStrs);
+
+ rezEnv[i] = NULL;
+ return rezEnv;
+ }
+
+ return NULL;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileRCVariables --
+ *
+ * Creates environment variables from a file in the system preferences
+ * folder. The function looks for a file in the preferences folder
+ * a name defined in the #define kPrefsFile. If the define is not
+ * defined this code will not be included. If the resource doesn't exist or
+ * no strings reside in the resource nothing will happen.
+ *
+ * Results:
+ * ptr to value on success, NULL if error.
+ *
+ * Side effects:
+ * Memory is allocated and returned to the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef kPrefsFile
+static char **
+FileRCVariables()
+{
+ char *prefsFolder = NULL;
+ char *tempPtr = NULL;
+ char **fileEnv = NULL;
+ FILE *thePrefsFile = NULL;
+ int i;
+ FSSpec prefDir;
+ OSErr err;
+ Handle theString = NULL;
+ Tcl_Channel chan;
+ int size;
+ Tcl_DString lineRead;
+
+ err = FSpFindFolder(kOnSystemDisk, kPreferencesFolderType,
+ kDontCreateFolder, &prefDir);
+ if (err != noErr) {
+ return NULL;
+ }
+ err = FSpPathFromLocation(&prefDir, &size, &theString);
+ if (err != noErr) {
+ return NULL;
+ }
+ (void) Munger(theString, size, NULL, 0, kPrefsFile, strlen(kPrefsFile));
+
+ HLock(theString);
+ chan = Tcl_OpenFileChannel(NULL, *theString, "r", 0);
+ HUnlock(theString);
+ DisposeHandle(theString);
+ if (chan == NULL) {
+ return NULL;
+ }
+
+ /*
+ * We found a env file. Let start parsing it.
+ */
+ fileEnv = (char **) ckalloc((kMaxEnvVarSize + 1) * sizeof(char *));
+
+ i = 0;
+ Tcl_DStringInit(&lineRead);
+ while (Tcl_Gets(chan, &lineRead) != -1) {
+ /*
+ * First strip off new line char
+ */
+ if (lineRead.string[lineRead.length-1] == '\n') {
+ lineRead.string[lineRead.length-1] = '\0';
+ }
+ if (lineRead.string[0] == '\0' || lineRead.string[0] == '#') {
+ /*
+ * skip empty lines or commented lines
+ */
+ Tcl_DStringSetLength(&lineRead, 0);
+ continue;
+ }
+
+ tempPtr = (char *) ckalloc(lineRead.length + 1);
+ strcpy(tempPtr, lineRead.string);
+ fileEnv[i++] = tempPtr;
+ Tcl_DStringSetLength(&lineRead, 0);
+ }
+
+ fileEnv[i] = NULL;
+ Tcl_Close(NULL, chan);
+ Tcl_DStringFree(&lineRead);
+
+ return fileEnv;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MakeFolderEnvVar --
+ *
+ * This function creates "environment" variable by taking a prefix and
+ * appending a folder path to a directory. The directory is specified
+ * by a integer value acceptable by the FindFolder function.
+ *
+ * Results:
+ * The function returns an *allocated* string. If the folder doesn't
+ * exist the return string is still allocated and just contains the
+ * given prefix.
+ *
+ * Side effects:
+ * Memory is allocated and returned to the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+MakeFolderEnvVar(
+ char * prefixTag, /* Prefix added before result. */
+ long whichFolder) /* Constant for FSpFindFolder. */
+{
+ char * thePath = NULL;
+ char * result = NULL;
+ OSErr theErr = noErr;
+ Handle theString = NULL;
+ FSSpec theFolder;
+ int size;
+ Tcl_DString pathStr;
+ Tcl_DString tagPathStr;
+
+ Tcl_DStringInit(&pathStr);
+ theErr = FSpFindFolder(kOnSystemDisk, whichFolder,
+ kDontCreateFolder, &theFolder);
+ if (theErr == noErr) {
+ theErr = FSpPathFromLocation(&theFolder, &size, &theString);
+
+ HLock(theString);
+ tclPlatform = TCL_PLATFORM_MAC;
+ Tcl_DStringAppend(&pathStr, *theString, -1);
+ HUnlock(theString);
+ DisposeHandle(theString);
+
+ Tcl_DStringInit(&tagPathStr);
+ Tcl_DStringAppend(&tagPathStr, prefixTag, strlen(prefixTag));
+ Tcl_DStringAppend(&tagPathStr, pathStr.string, pathStr.length);
+ Tcl_DStringFree(&pathStr);
+
+ /*
+ * Make sure the path ends with a ':'
+ */
+ if (tagPathStr.string[tagPathStr.length - 1] != ':') {
+ Tcl_DStringAppend(&tagPathStr, ":", 1);
+ }
+
+ /*
+ * Don't free tagPathStr - rather make sure it's allocated
+ * and return it as the result.
+ */
+ if (tagPathStr.string == tagPathStr.staticSpace) {
+ result = (char *) ckalloc(tagPathStr.length + 1);
+ strcpy(result, tagPathStr.string);
+ } else {
+ result = tagPathStr.string;
+ }
+ } else {
+ result = (char *) ckalloc(strlen(prefixTag) + 1);
+ strcpy(result, prefixTag);
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PathVariables --
+ *
+ * Creates environment variables from the system call FSpFindFolder.
+ * The function generates environment variables for many of the
+ * commonly used paths on the Macintosh.
+ *
+ * Results:
+ * ptr to value on success, NULL if error.
+ *
+ * Side effects:
+ * Memory is allocated and returned to the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char **
+PathVariables()
+{
+ int i = 0;
+ char **sysEnv;
+ char *thePath = NULL;
+
+ sysEnv = (char **) ckalloc((12) * sizeof(char *));
+
+ sysEnv[i++] = MakeFolderEnvVar("PREF_FOLDER=", kPreferencesFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("SYS_FOLDER=", kSystemFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("TEMP=", kTemporaryFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("APPLE_M_FOLDER=", kAppleMenuFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("CP_FOLDER=", kControlPanelFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("DESK_FOLDER=", kDesktopFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("EXT_FOLDER=", kExtensionFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("PRINT_MON_FOLDER=",
+ kPrintMonitorDocsFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("SHARED_TRASH_FOLDER=",
+ kWhereToEmptyTrashFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("TRASH_FOLDER=", kTrashFolderType);
+ sysEnv[i++] = MakeFolderEnvVar("START_UP_FOLDER=", kStartupFolderType);
+ sysEnv[i++] = NULL;
+
+ return sysEnv;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SystemVariables --
+ *
+ * Creates environment variables from various Mac system calls.
+ *
+ * Results:
+ * ptr to value on success, NULL if error.
+ *
+ * Side effects:
+ * Memory is allocated and returned to the caller.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char **
+SystemVariables()
+{
+ int i = 0;
+ char ** sysEnv;
+ char * thePath = NULL;
+ Handle theString = NULL;
+ FSSpec currentDir;
+ int size;
+
+ sysEnv = (char **) ckalloc((4) * sizeof(char *));
+
+ /*
+ * Get user name from chooser. It will be assigned to both
+ * the USER and LOGIN environment variables.
+ */
+ thePath = GetUserName();
+ if (thePath != NULL) {
+ sysEnv[i] = (char *) ckalloc(strlen(kLoginnameTag) + strlen(thePath) + 1);
+ strcpy(sysEnv[i], kLoginnameTag);
+ strcpy(sysEnv[i]+strlen(kLoginnameTag), thePath);
+ i++;
+ sysEnv[i] = (char *) ckalloc(strlen(kUsernameTag) + strlen(thePath) + 1);
+ strcpy(sysEnv[i], kUsernameTag);
+ strcpy(sysEnv[i]+strlen(kUsernameTag), thePath);
+ i++;
+ }
+
+ /*
+ * Get 'home' directory
+ */
+#ifdef kDefaultDirTag
+ FSpGetDefaultDir(&currentDir);
+ FSpPathFromLocation(&currentDir, &size, &theString);
+ HLock(theString);
+ sysEnv[i] = (char *) ckalloc(strlen(kDefaultDirTag) + size + 4);
+ strcpy(sysEnv[i], kDefaultDirTag);
+ strncpy(sysEnv[i]+strlen(kDefaultDirTag) , *theString, size);
+ if (sysEnv[i][strlen(kDefaultDirTag) + size - 1] != ':') {
+ sysEnv[i][strlen(kDefaultDirTag) + size] = ':';
+ sysEnv[i][strlen(kDefaultDirTag) + size + 1] = '\0';
+ } else {
+ sysEnv[i][strlen(kDefaultDirTag) + size] = '\0';
+ }
+ HUnlock(theString);
+ DisposeHandle(theString);
+ i++;
+#endif
+
+ sysEnv[i++] = NULL;
+ return sysEnv;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacCreateEnv --
+ *
+ * This function allocates and populates the global "environ"
+ * variable. Entries are in traditional Unix format but variables
+ * are, hopefully, a bit more relevant for the Macintosh.
+ *
+ * Results:
+ * The number of elements in the newly created environ array.
+ *
+ * Side effects:
+ * Memory is allocated and pointed too by the environ variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacCreateEnv()
+{
+ char ** sysEnv = NULL;
+ char ** pathEnv = NULL;
+ char ** fileEnv = NULL;
+ char ** rezEnv = NULL;
+ int count = 0;
+ int i, j;
+
+ sysEnv = SystemVariables();
+ if (sysEnv != NULL) {
+ for (i = 0; sysEnv[i] != NULL; count++, i++) {
+ /* Empty Loop */
+ }
+ }
+
+ pathEnv = PathVariables();
+ if (pathEnv != NULL) {
+ for (i = 0; pathEnv[i] != NULL; count++, i++) {
+ /* Empty Loop */
+ }
+ }
+
+#ifdef kPrefsFile
+ fileEnv = FileRCVariables();
+ if (fileEnv != NULL) {
+ for (i = 0; fileEnv[i] != NULL; count++, i++) {
+ /* Empty Loop */
+ }
+ }
+#endif
+
+#ifdef REZ_ENV
+ rezEnv = RezRCVariables();
+ if (rezEnv != NULL) {
+ for (i = 0; rezEnv[i] != NULL; count++, i++) {
+ /* Empty Loop */
+ }
+ }
+#endif
+
+ /*
+ * Create environ variable
+ */
+ environ = (char **) ckalloc((count + 1) * sizeof(char *));
+ j = 0;
+
+ if (sysEnv != NULL) {
+ for (i = 0; sysEnv[i] != NULL;)
+ environ[j++] = sysEnv[i++];
+ ckfree((char *) sysEnv);
+ }
+
+ if (pathEnv != NULL) {
+ for (i = 0; pathEnv[i] != NULL;)
+ environ[j++] = pathEnv[i++];
+ ckfree((char *) pathEnv);
+ }
+
+#ifdef kPrefsFile
+ if (fileEnv != NULL) {
+ for (i = 0; fileEnv[i] != NULL;)
+ environ[j++] = fileEnv[i++];
+ ckfree((char *) fileEnv);
+ }
+#endif
+
+#ifdef REZ_ENV
+ if (rezEnv != NULL) {
+ for (i = 0; rezEnv[i] != NULL;)
+ environ[j++] = rezEnv[i++];
+ ckfree((char *) rezEnv);
+ }
+#endif
+
+ environ[j] = NULL;
+ return j;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetUserName --
+ *
+ * Get the user login name.
+ *
+ * Results:
+ * ptr to static string, NULL if error.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+GetUserName()
+{
+ static char buf[33];
+ short refnum;
+ Handle h;
+
+ refnum = CurResFile();
+ UseResFile(0);
+ h = GetResource('STR ', -16096);
+ UseResFile(refnum);
+ if (h == NULL) {
+ return NULL;
+ }
+
+ HLock(h);
+ strncpy(buf, (*h)+1, **h);
+ buf[**h] = '\0';
+ HUnlock(h);
+ ReleaseResource(h);
+ return(buf[0] ? buf : NULL);
+}
diff --git a/mac/tclMacExit.c b/mac/tclMacExit.c
new file mode 100644
index 0000000..f5f403d
--- /dev/null
+++ b/mac/tclMacExit.c
@@ -0,0 +1,317 @@
+/*
+ * tclMacExit.c --
+ *
+ * This file contains routines that deal with cleaning up various state
+ * when Tcl/Tk applications quit. Unfortunantly, not all state is cleaned
+ * up by the process when an application quites or crashes. Also you
+ * need to do different things depending on wether you are running as
+ * 68k code, PowerPC, or a code resource. The Exit handler code was
+ * adapted from code posted on alt.sources.mac by Dave Nebinger.
+ *
+ * Copyright (c) 1995 Dave Nebinger.
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacExit.c 1.6 97/11/20 18:37:38
+ */
+
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include <SegLoad.h>
+#include <Traps.h>
+#include <Processes.h>
+
+/*
+ * Various typedefs and defines needed to patch ExitToShell.
+ */
+
+enum {
+ uppExitToShellProcInfo = kPascalStackBased
+};
+
+#if GENERATINGCFM
+typedef UniversalProcPtr ExitToShellUPP;
+
+#define CallExitToShellProc(userRoutine) \
+ CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
+#define NewExitToShellProc(userRoutine) \
+ (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
+ uppExitToShellProcInfo, GetCurrentArchitecture())
+
+#else
+typedef ExitToShellProcPtr ExitToShellUPP;
+
+#define CallExitToShellProc(userRoutine) \
+ (*(userRoutine))()
+#define NewExitToShellProc(userRoutine) \
+ (ExitToShellUPP)(userRoutine)
+#endif
+
+#define DisposeExitToShellProc(userRoutine) \
+ DisposeRoutineDescriptor(userRoutine)
+
+#if defined(powerc)||defined(__powerc)
+#pragma options align=mac68k
+#endif
+struct ExitToShellUPPList{
+ struct ExitToShellUPPList* nextProc;
+ ExitToShellUPP userProc;
+};
+#if defined(powerc)||defined(__powerc)
+#pragma options align=reset
+#endif
+
+typedef struct ExitToShellDataStruct ExitToShellDataRec,* ExitToShellDataPtr,** ExitToShellDataHdl;
+
+typedef struct ExitToShellUPPList ExitToShellUPPList,* ExitToShellUPPListPtr,** ExitToShellUPPHdl;
+
+#if defined(powerc)||defined(__powerc)
+#pragma options align=mac68k
+#endif
+struct ExitToShellDataStruct{
+ unsigned long a5;
+ ExitToShellUPPList* userProcs;
+ ExitToShellUPP oldProc;
+};
+#if defined(powerc)||defined(__powerc)
+#pragma options align=reset
+#endif
+
+/*
+ * Static globals used within this file.
+ */
+static ExitToShellDataPtr gExitToShellData = (ExitToShellDataPtr) NULL;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPlatformExit --
+ *
+ * This procedure implements the Macintosh specific exit routine.
+ * We explicitly callthe ExitHandler function to do various clean
+ * up.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * We exit the process.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPlatformExit(
+ int status) /* Ignored. */
+{
+ TclMacExitHandler();
+ ExitToShell();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacExitHandler --
+ *
+ * This procedure is invoked after Tcl at the last possible moment
+ * to clean up any state Tcl has left around that may cause other
+ * applications to crash. For example, this function can be used
+ * as the termination routine for CFM applications.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various cleanup occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclMacExitHandler()
+{
+ ExitToShellUPPListPtr curProc;
+
+ /*
+ * Loop through all installed Exit handlers
+ * and call them. Always make sure we are in
+ * a clean state in case we are recursivly called.
+ */
+ if ((gExitToShellData) != NULL && (gExitToShellData->userProcs != NULL)){
+
+ /*
+ * Call the installed exit to shell routines.
+ */
+ curProc = gExitToShellData->userProcs;
+ do {
+ gExitToShellData->userProcs = curProc->nextProc;
+ CallExitToShellProc(curProc->userProc);
+ DisposeExitToShellProc(curProc->userProc);
+ DisposePtr((Ptr) curProc);
+ curProc = gExitToShellData->userProcs;
+ } while (curProc != (ExitToShellUPPListPtr) NULL);
+ }
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacInstallExitToShellPatch --
+ *
+ * This procedure installs a way to clean up state at the latest
+ * possible moment before we exit. These are things that must
+ * be cleaned up or the system will crash. The exact way in which
+ * this is implemented depends on the architecture in which we are
+ * running. For 68k applications we patch the ExitToShell call.
+ * For PowerPC applications we just create a list of procs to call.
+ * The function ExitHandler should be installed in the Code
+ * Fragments terminiation routine.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Installs the new routine.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+TclMacInstallExitToShellPatch(
+ ExitToShellProcPtr newProc) /* Function pointer. */
+{
+ ExitToShellUPP exitHandler;
+ ExitToShellUPPListPtr listPtr;
+
+ if (gExitToShellData == (ExitToShellDataPtr) NULL){
+ TclMacInitExitToShell(true);
+ }
+
+ /*
+ * Add the passed in function pointer to the list of functions
+ * to be called when ExitToShell is called.
+ */
+ exitHandler = NewExitToShellProc(newProc);
+ listPtr = (ExitToShellUPPListPtr) NewPtrClear(sizeof(ExitToShellUPPList));
+ listPtr->userProc = exitHandler;
+ listPtr->nextProc = gExitToShellData->userProcs;
+ gExitToShellData->userProcs = listPtr;
+
+ return noErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ExitToShellPatchRoutine --
+ *
+ * This procedure is invoked when someone calls ExitToShell for
+ * this application. This function performs some last miniute
+ * clean up and then calls the real ExitToShell routine.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various cleanup occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal void
+ExitToShellPatchRoutine()
+{
+ ExitToShellUPP oldETS;
+ long oldA5;
+
+ /*
+ * Set up our A5 world. This allows us to have
+ * access to our global variables in the 68k world.
+ */
+ oldA5 = SetCurrentA5();
+ SetA5(gExitToShellData->a5);
+
+ /*
+ * Call the function that invokes all
+ * of the handlers.
+ */
+ TclMacExitHandler();
+
+ /*
+ * Call the origional ExitToShell routine.
+ */
+ oldETS = gExitToShellData->oldProc;
+ DisposePtr((Ptr) gExitToShellData);
+ SetA5(oldA5);
+ CallExitToShellProc(oldETS);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacInitExitToShell --
+ *
+ * This procedure initializes the ExitToShell clean up machanism.
+ * Generally, this is handled automatically when users make a call
+ * to InstallExitToShellPatch. However, it can be called
+ * explicitly at startup time to turn off the patching mechanism.
+ * This can be used by code resources which could be removed from
+ * the application before ExitToShell is called.
+ *
+ * Note, if we are running from CFM code we never install the
+ * patch. Instead, the function ExitHandler should be installed
+ * as the terminiation routine for the code fragment.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates global state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclMacInitExitToShell(
+ int usePatch) /* True if on 68k. */
+{
+ if (gExitToShellData == (ExitToShellDataPtr) NULL){
+#if GENERATINGCFM
+ gExitToShellData = (ExitToShellDataPtr)
+ NewPtr(sizeof(ExitToShellDataRec));
+ gExitToShellData->a5 = SetCurrentA5();
+ gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
+#else
+ ExitToShellUPP oldExitToShell, newExitToShellPatch;
+ short exitToShellTrap;
+
+ /*
+ * Initialize patch mechanism.
+ */
+
+ gExitToShellData = (ExitToShellDataPtr) NewPtr(sizeof(ExitToShellDataRec));
+ gExitToShellData->a5 = SetCurrentA5();
+ gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
+
+ /*
+ * Save state needed to call origional ExitToShell routine. Install
+ * the new ExitToShell code in it's place.
+ */
+ if (usePatch) {
+ exitToShellTrap = _ExitToShell & 0x3ff;
+ newExitToShellPatch = NewExitToShellProc(ExitToShellPatchRoutine);
+ oldExitToShell = (ExitToShellUPP)
+ NGetTrapAddress(exitToShellTrap, ToolTrap);
+ NSetTrapAddress((UniversalProcPtr) newExitToShellPatch,
+ exitToShellTrap, ToolTrap);
+ gExitToShellData->oldProc = oldExitToShell;
+ }
+#endif
+ }
+}
diff --git a/mac/tclMacFCmd.c b/mac/tclMacFCmd.c
new file mode 100644
index 0000000..0dcac1c
--- /dev/null
+++ b/mac/tclMacFCmd.c
@@ -0,0 +1,1408 @@
+/*
+ * tclMacFCmd.c --
+ *
+ * Implements the Macintosh specific portions of the file manipulation
+ * subcommands of the "file" command.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacFCmd.c 1.22 97/05/20 15:44:26
+ */
+
+#include "tclInt.h"
+#include "tclMac.h"
+#include "tclMacInt.h"
+#include "tclPort.h"
+#include <FSpCompat.h>
+#include <MoreFilesExtras.h>
+#include <Strings.h>
+#include <Errors.h>
+#include <FileCopy.h>
+#include <DirectoryCopy.h>
+#include <Script.h>
+#include <string.h>
+#include <Finder.h>
+
+/*
+ * Callback for the file attributes code.
+ */
+
+static int GetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,
+ int objIndex, char *fileName,
+ Tcl_Obj **attributePtrPtr));
+static int GetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,
+ int objIndex, char *fileName,
+ Tcl_Obj **readOnlyPtrPtr));
+static int SetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,
+ int objIndex, char *fileName,
+ Tcl_Obj *attributePtr));
+static int SetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,
+ int objIndex, char *fileName,
+ Tcl_Obj *readOnlyPtr));
+
+/*
+ * These are indeces into the tclpFileAttrsStrings table below.
+ */
+
+#define MAC_CREATOR_ATTRIBUTE 0
+#define MAC_HIDDEN_ATTRIBUTE 1
+#define MAC_READONLY_ATTRIBUTE 2
+#define MAC_TYPE_ATTRIBUTE 3
+
+/*
+ * Global variables for the file attributes code.
+ */
+
+char *tclpFileAttrStrings[] = {"-creator", "-hidden", "-readonly",
+ "-type", (char *) NULL};
+CONST TclFileAttrProcs tclpFileAttrProcs[] = {
+ {GetFileFinderAttributes, SetFileFinderAttributes},
+ {GetFileFinderAttributes, SetFileFinderAttributes},
+ {GetFileReadOnly, SetFileReadOnly},
+ {GetFileFinderAttributes, SetFileFinderAttributes}};
+
+
+/*
+ * Prototypes for procedure only used in this file
+ */
+
+static pascal Boolean CopyErrHandler _ANSI_ARGS_((OSErr error,
+ short failedOperation,
+ short srcVRefNum, long srcDirID,
+ StringPtr srcName, short dstVRefNum,
+ long dstDirID,StringPtr dstName));
+OSErr FSpGetFLockCompat _ANSI_ARGS_((const FSSpec *specPtr,
+ Boolean *lockedPtr));
+static OSErr GenerateUniqueName _ANSI_ARGS_((short vRefNum,
+ long dirID1, long dirID2, Str31 uniqueName));
+static OSErr GetFileSpecs _ANSI_ARGS_((char *path, FSSpec *pathSpecPtr,
+ FSSpec *dirSpecPtr, Boolean *pathExistsPtr,
+ Boolean *pathIsDirectoryPtr));
+static OSErr MoveRename _ANSI_ARGS_((const FSSpec *srcSpecPtr,
+ const FSSpec *dstSpecPtr, StringPtr copyName));
+static int Pstrequal _ANSI_ARGS_((ConstStr255Param stringA,
+ ConstStr255Param stringB));
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpRenameFile --
+ *
+ * Changes the name of an existing file or directory, from src to dst.
+ * If src and dst refer to the same file or directory, does nothing
+ * and returns success. Otherwise if dst already exists, it will be
+ * deleted and replaced by src subject to the following conditions:
+ * If src is a directory, dst may be an empty directory.
+ * If src is a file, dst may be a file.
+ * In any other situation where dst already exists, the rename will
+ * fail.
+ *
+ * Results:
+ * If the directory was successfully created, returns TCL_OK.
+ * Otherwise the return value is TCL_ERROR and errno is set to
+ * indicate the error. Some possible values for errno are:
+ *
+ * EACCES: src or dst parent directory can't be read and/or written.
+ * EEXIST: dst is a non-empty directory.
+ * EINVAL: src is a root directory or dst is a subdirectory of src.
+ * EISDIR: dst is a directory, but src is not.
+ * ENOENT: src doesn't exist. src or dst is "".
+ * ENOTDIR: src is a directory, but dst is not.
+ * EXDEV: src and dst are on different filesystems.
+ *
+ * Side effects:
+ * The implementation of rename may allow cross-filesystem renames,
+ * but the caller should be prepared to emulate it with copy and
+ * delete if errno is EXDEV.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpRenameFile(
+ char *src, /* Pathname of file or dir to be renamed. */
+ char *dst) /* New pathname for file or directory. */
+{
+ FSSpec srcFileSpec, dstFileSpec, dstDirSpec;
+ OSErr err;
+ long srcID, dummy;
+ Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked;
+
+ err = FSpLocationFromPath(strlen(src), src, &srcFileSpec);
+ if (err == noErr) {
+ FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory);
+ }
+ if (err == noErr) {
+ err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
+ &dstIsDirectory);
+ }
+ if (err == noErr) {
+ if (dstExists == 0) {
+ err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);
+ goto end;
+ }
+ err = FSpGetFLockCompat(&dstFileSpec, &dstLocked);
+ if (dstLocked) {
+ FSpRstFLockCompat(&dstFileSpec);
+ }
+ }
+ if (err == noErr) {
+ if (srcIsDirectory) {
+ if (dstIsDirectory) {
+ /*
+ * The following call will remove an empty directory. If it
+ * fails, it's because it wasn't empty.
+ */
+
+ if (TclpRemoveDirectory(dst, 0, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now that that empty directory is gone, we can try
+ * renaming src. If that fails, we'll put this empty
+ * directory back, for completeness.
+ */
+
+ err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);
+ if (err != noErr) {
+ FSpDirCreateCompat(&dstFileSpec, smSystemScript, &dummy);
+ if (dstLocked) {
+ FSpSetFLockCompat(&dstFileSpec);
+ }
+ }
+ } else {
+ errno = ENOTDIR;
+ return TCL_ERROR;
+ }
+ } else {
+ if (dstIsDirectory) {
+ errno = EISDIR;
+ return TCL_ERROR;
+ } else {
+ /*
+ * Overwrite existing file by:
+ *
+ * 1. Rename existing file to temp name.
+ * 2. Rename old file to new name.
+ * 3. If success, delete temp file. If failure,
+ * put temp file back to old name.
+ */
+
+ Str31 tmpName;
+ FSSpec tmpFileSpec;
+
+ err = GenerateUniqueName(dstFileSpec.vRefNum,
+ dstFileSpec.parID, dstFileSpec.parID, tmpName);
+ if (err == noErr) {
+ err = FSpRenameCompat(&dstFileSpec, tmpName);
+ }
+ if (err == noErr) {
+ err = FSMakeFSSpecCompat(dstFileSpec.vRefNum,
+ dstFileSpec.parID, tmpName, &tmpFileSpec);
+ }
+ if (err == noErr) {
+ err = MoveRename(&srcFileSpec, &dstDirSpec,
+ dstFileSpec.name);
+ }
+ if (err == noErr) {
+ FSpDeleteCompat(&tmpFileSpec);
+ } else {
+ FSpDeleteCompat(&dstFileSpec);
+ FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
+ if (dstLocked) {
+ FSpSetFLockCompat(&dstFileSpec);
+ }
+ }
+ }
+ }
+ }
+
+ end:
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpCopyFile --
+ *
+ * Copy a single file (not a directory). If dst already exists and
+ * is not a directory, it is removed.
+ *
+ * Results:
+ * If the file was successfully copied, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the
+ * error. Some possible values for errno are:
+ *
+ * EACCES: src or dst parent directory can't be read and/or written.
+ * EISDIR: src or dst is a directory.
+ * ENOENT: src doesn't exist. src or dst is "".
+ *
+ * Side effects:
+ * This procedure will also copy symbolic links, block, and
+ * character devices, and fifos. For symbolic links, the links
+ * themselves will be copied and not what they point to. For the
+ * other special file types, the directory entry will be copied and
+ * not the contents of the device that it refers to.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpCopyFile(
+ char *src, /* Pathname of file to be copied. */
+ char *dst) /* Pathname of file to copy to. */
+{
+ OSErr err, dstErr;
+ Boolean dstExists, dstIsDirectory, dstLocked;
+ FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec;
+ Str31 tmpName;
+
+ err = FSpLocationFromPath(strlen(src), src, &srcFileSpec);
+ if (err == noErr) {
+ err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
+ &dstIsDirectory);
+ }
+ if (dstExists) {
+ if (dstIsDirectory) {
+ errno = EISDIR;
+ return TCL_ERROR;
+ }
+ err = FSpGetFLockCompat(&dstFileSpec, &dstLocked);
+ if (dstLocked) {
+ FSpRstFLockCompat(&dstFileSpec);
+ }
+
+ /*
+ * Backup dest file.
+ */
+
+ dstErr = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID,
+ dstFileSpec.parID, tmpName);
+ if (dstErr == noErr) {
+ dstErr = FSpRenameCompat(&dstFileSpec, tmpName);
+ }
+ }
+ if (err == noErr) {
+ err = FSpFileCopy(&srcFileSpec, &dstDirSpec,
+ (StringPtr) dstFileSpec.name, NULL, 0, true);
+ }
+ if ((dstExists != false) && (dstErr == noErr)) {
+ FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID,
+ tmpName, &tmpFileSpec);
+ if (err == noErr) {
+ /*
+ * Delete backup file.
+ */
+
+ FSpDeleteCompat(&tmpFileSpec);
+ } else {
+
+ /*
+ * Restore backup file.
+ */
+
+ FSpDeleteCompat(&dstFileSpec);
+ FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
+ if (dstLocked) {
+ FSpSetFLockCompat(&dstFileSpec);
+ }
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpDeleteFile --
+ *
+ * Removes a single file (not a directory).
+ *
+ * Results:
+ * If the file was successfully deleted, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the
+ * error. Some possible values for errno are:
+ *
+ * EACCES: a parent directory can't be read and/or written.
+ * EISDIR: path is a directory.
+ * ENOENT: path doesn't exist or is "".
+ *
+ * Side effects:
+ * The file is deleted, even if it is read-only.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpDeleteFile(
+ char *path) /* Pathname of file to be removed. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ Boolean isDirectory;
+ long dirID;
+
+ err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+ if (err == noErr) {
+ /*
+ * Since FSpDeleteCompat will delete an empty directory, make sure
+ * that this isn't a directory first.
+ */
+
+ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ if (isDirectory == true) {
+ errno = EISDIR;
+ return TCL_ERROR;
+ }
+ }
+ err = FSpDeleteCompat(&fileSpec);
+ if (err == fLckdErr) {
+ FSpRstFLockCompat(&fileSpec);
+ err = FSpDeleteCompat(&fileSpec);
+ if (err != noErr) {
+ FSpSetFLockCompat(&fileSpec);
+ }
+ }
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpCreateDirectory --
+ *
+ * Creates the specified directory. All parent directories of the
+ * specified directory must already exist. The directory is
+ * automatically created with permissions so that user can access
+ * the new directory and create new files or subdirectories in it.
+ *
+ * Results:
+ * If the directory was successfully created, returns TCL_OK.
+ * Otherwise the return value is TCL_ERROR and errno is set to
+ * indicate the error. Some possible values for errno are:
+ *
+ * EACCES: a parent directory can't be read and/or written.
+ * EEXIST: path already exists.
+ * ENOENT: a parent directory doesn't exist.
+ *
+ * Side effects:
+ * A directory is created with the current umask, except that
+ * permission for u+rwx will always be added.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpCreateDirectory(
+ char *path) /* Pathname of directory to create. */
+{
+ OSErr err;
+ FSSpec dirSpec;
+ long outDirID;
+
+ err = FSpLocationFromPath(strlen(path), path, &dirSpec);
+ if (err == noErr) {
+ err = dupFNErr; /* EEXIST. */
+ } else if (err == fnfErr) {
+ err = FSpDirCreateCompat(&dirSpec, smSystemScript, &outDirID);
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpCopyDirectory --
+ *
+ * Recursively copies a directory. The target directory dst must
+ * not already exist. Note that this function does not merge two
+ * directory hierarchies, even if the target directory is an an
+ * empty directory.
+ *
+ * Results:
+ * If the directory was successfully copied, returns TCL_OK.
+ * Otherwise the return value is TCL_ERROR, errno is set to indicate
+ * the error, and the pathname of the file that caused the error
+ * is stored in errorPtr. See TclpCreateDirectory and TclpCopyFile
+ * for a description of possible values for errno.
+ *
+ * Side effects:
+ * An exact copy of the directory hierarchy src will be created
+ * with the name dst. If an error occurs, the error will
+ * be returned immediately, and remaining files will not be
+ * processed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpCopyDirectory(
+ char *src, /* Pathname of directory to be copied. */
+ char *dst, /* Pathname of target directory. */
+ Tcl_DString *errorPtr) /* If non-NULL, initialized DString for
+ * error reporting. */
+{
+ OSErr err, saveErr;
+ long srcID, tmpDirID;
+ FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpDirSpec, tmpFileSpec;
+ Boolean srcIsDirectory, srcLocked;
+ Boolean dstIsDirectory, dstExists;
+ Str31 tmpName;
+
+ err = FSpLocationFromPath(strlen(src), src, &srcFileSpec);
+ if (err == noErr) {
+ err = FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory);
+ }
+ if (err == noErr) {
+ if (srcIsDirectory == false) {
+ err = afpObjectTypeErr; /* ENOTDIR. */
+ }
+ }
+ if (err == noErr) {
+ err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,
+ &dstIsDirectory);
+ }
+ if (dstExists) {
+ if (dstIsDirectory == false) {
+ err = afpObjectTypeErr; /* ENOTDIR. */
+ } else {
+ err = dupFNErr; /* EEXIST. */
+ }
+ }
+ if (err != noErr) {
+ goto done;
+ }
+ if ((srcFileSpec.vRefNum == dstFileSpec.vRefNum) &&
+ (srcFileSpec.parID == dstFileSpec.parID) &&
+ (Pstrequal(srcFileSpec.name, dstFileSpec.name) != 0)) {
+ /*
+ * Copying on top of self. No-op.
+ */
+
+ goto done;
+ }
+
+ /*
+ * This algorthm will work making a copy of the source directory in
+ * the current directory with a new name, in a new directory with the
+ * same name, and in a new directory with a new name:
+ *
+ * 1. Make dstDir/tmpDir.
+ * 2. Copy srcDir/src to dstDir/tmpDir/src
+ * 3. Rename dstDir/tmpDir/src to dstDir/tmpDir/dst (if necessary).
+ * 4. CatMove dstDir/tmpDir/dst to dstDir/dst.
+ * 5. Remove dstDir/tmpDir.
+ */
+
+ err = FSpGetFLockCompat(&srcFileSpec, &srcLocked);
+ if (srcLocked) {
+ FSpRstFLockCompat(&srcFileSpec);
+ }
+ if (err == noErr) {
+ err = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID,
+ dstFileSpec.parID, tmpName);
+ }
+ if (err == noErr) {
+ FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID,
+ tmpName, &tmpDirSpec);
+ err = FSpDirCreateCompat(&tmpDirSpec, smSystemScript, &tmpDirID);
+ }
+ if (err == noErr) {
+ err = FSpDirectoryCopy(&srcFileSpec, &tmpDirSpec, NULL, 0, true,
+ CopyErrHandler);
+ }
+
+ /*
+ * Even if the Copy failed, Rename/Move whatever did get copied to the
+ * appropriate final destination, if possible.
+ */
+
+ saveErr = err;
+ err = noErr;
+ if (Pstrequal(srcFileSpec.name, dstFileSpec.name) == 0) {
+ err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID,
+ srcFileSpec.name, &tmpFileSpec);
+ if (err == noErr) {
+ err = FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);
+ }
+ }
+ if (err == noErr) {
+ err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID,
+ dstFileSpec.name, &tmpFileSpec);
+ }
+ if (err == noErr) {
+ err = FSpCatMoveCompat(&tmpFileSpec, &dstDirSpec);
+ }
+ if (err == noErr) {
+ if (srcLocked) {
+ FSpSetFLockCompat(&dstFileSpec);
+ }
+ }
+
+ FSpDeleteCompat(&tmpDirSpec);
+
+ if (saveErr != noErr) {
+ err = saveErr;
+ }
+
+ done:
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ if (errorPtr != NULL) {
+ Tcl_DStringAppend(errorPtr, dst, -1);
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CopyErrHandler --
+ *
+ * This procedure is called from the MoreFiles procedure
+ * FSpDirectoryCopy whenever an error occurs.
+ *
+ * Results:
+ * False if the condition should not be considered an error, true
+ * otherwise.
+ *
+ * Side effects:
+ * Since FSpDirectoryCopy() is called only after removing any
+ * existing target directories, there shouldn't be any errors.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal Boolean
+CopyErrHandler(
+ OSErr error, /* Error that occured */
+ short failedOperation, /* operation that caused the error */
+ short srcVRefNum, /* volume ref number of source */
+ long srcDirID, /* directory id of source */
+ StringPtr srcName, /* name of source */
+ short dstVRefNum, /* volume ref number of dst */
+ long dstDirID, /* directory id of dst */
+ StringPtr dstName) /* name of dst directory */
+{
+ return true;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpRemoveDirectory --
+ *
+ * Removes directory (and its contents, if the recursive flag is set).
+ *
+ * Results:
+ * If the directory was successfully removed, returns TCL_OK.
+ * Otherwise the return value is TCL_ERROR, errno is set to indicate
+ * the error, and the pathname of the file that caused the error
+ * is stored in errorPtr. Some possible values for errno are:
+ *
+ * EACCES: path directory can't be read and/or written.
+ * EEXIST: path is a non-empty directory.
+ * EINVAL: path is a root directory.
+ * ENOENT: path doesn't exist or is "".
+ * ENOTDIR: path is not a directory.
+ *
+ * Side effects:
+ * Directory removed. If an error occurs, the error will be returned
+ * immediately, and remaining files will not be deleted.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpRemoveDirectory(
+ char *path, /* Pathname of directory to be removed. */
+ int recursive, /* If non-zero, removes directories that
+ * are nonempty. Otherwise, will only remove
+ * empty directories. */
+ Tcl_DString *errorPtr) /* If non-NULL, initialized DString for
+ * error reporting. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ long dirID;
+ int locked;
+ Boolean isDirectory;
+ CInfoPBRec pb;
+ Str255 fileName;
+
+ locked = 0;
+ err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+ if (err != noErr) {
+ goto done;
+ }
+
+ /*
+ * Since FSpDeleteCompat will delete a file, make sure this isn't
+ * a file first.
+ */
+
+ isDirectory = 1;
+ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ if (isDirectory == 0) {
+ errno = ENOTDIR;
+ return TCL_ERROR;
+ }
+
+ err = FSpDeleteCompat(&fileSpec);
+ if (err == fLckdErr) {
+ locked = 1;
+ FSpRstFLockCompat(&fileSpec);
+ err = FSpDeleteCompat(&fileSpec);
+ }
+ if (err == noErr) {
+ return TCL_OK;
+ }
+ if (err != fBsyErr) {
+ goto done;
+ }
+
+ if (recursive == 0) {
+ /*
+ * fBsyErr means one of three things: file busy, directory not empty,
+ * or working directory control block open. Determine if directory
+ * is empty. If directory is not empty, return EEXIST.
+ */
+
+ pb.hFileInfo.ioVRefNum = fileSpec.vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ pb.hFileInfo.ioNamePtr = (StringPtr) fileName;
+ pb.hFileInfo.ioFDirIndex = 1;
+ if (PBGetCatInfoSync(&pb) == noErr) {
+ err = dupFNErr; /* EEXIST */
+ goto done;
+ }
+ }
+
+ /*
+ * DeleteDirectory removes a directory and all its contents, including
+ * any locked files. There is no interface to get the name of the
+ * file that caused the error, if an error occurs deleting this tree,
+ * unless we rewrite DeleteDirectory ourselves.
+ */
+
+ err = DeleteDirectory(fileSpec.vRefNum, dirID, NULL);
+
+ done:
+ if (err != noErr) {
+ if (errorPtr != NULL) {
+ Tcl_DStringAppend(errorPtr, path, -1);
+ }
+ if (locked) {
+ FSpSetFLockCompat(&fileSpec);
+ }
+ errno = TclMacOSErrorToPosixError(err);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------------------
+ *
+ * MoveRename --
+ *
+ * Helper function for TclpRenameFile. Renames a file or directory
+ * into the same directory or another directory. The target name
+ * must not already exist in the destination directory.
+ *
+ * Don't use FSpMoveRenameCompat because it doesn't work with
+ * directories or with locked files.
+ *
+ * Results:
+ * Returns a mac error indicating the cause of the failure.
+ *
+ * Side effects:
+ * Creates a temp file in the target directory to handle a rename
+ * between directories.
+ *
+ *--------------------------------------------------------------------------
+ */
+
+static OSErr
+MoveRename(
+ const FSSpec *srcFileSpecPtr, /* Source object. */
+ const FSSpec *dstDirSpecPtr, /* Destination directory. */
+ StringPtr copyName) /* New name for object in destination
+ * directory. */
+{
+ OSErr err;
+ long srcID, dstID;
+ Boolean srcIsDir, dstIsDir;
+ Str31 tmpName;
+ FSSpec dstFileSpec, srcDirSpec, tmpSrcFileSpec, tmpDstFileSpec;
+ Boolean locked;
+
+ if (srcFileSpecPtr->parID == 1) {
+ /*
+ * Trying to rename a volume.
+ */
+
+ return badMovErr;
+ }
+ if (srcFileSpecPtr->vRefNum != dstDirSpecPtr->vRefNum) {
+ /*
+ * Renaming across volumes.
+ */
+
+ return diffVolErr;
+ }
+ err = FSpGetFLockCompat(srcFileSpecPtr, &locked);
+ if (locked) {
+ FSpRstFLockCompat(srcFileSpecPtr);
+ }
+ if (err == noErr) {
+ err = FSpGetDirectoryID(dstDirSpecPtr, &dstID, &dstIsDir);
+ }
+ if (err == noErr) {
+ if (srcFileSpecPtr->parID == dstID) {
+ /*
+ * Renaming object within directory.
+ */
+
+ err = FSpRenameCompat(srcFileSpecPtr, copyName);
+ goto done;
+ }
+ if (Pstrequal(srcFileSpecPtr->name, copyName)) {
+ /*
+ * Moving object to another directory (under same name).
+ */
+
+ err = FSpCatMoveCompat(srcFileSpecPtr, dstDirSpecPtr);
+ goto done;
+ }
+ err = FSpGetDirectoryID(srcFileSpecPtr, &srcID, &srcIsDir);
+ }
+ if (err == noErr) {
+ /*
+ * Fullblown: rename source object to temp name, move temp to
+ * dest directory, and rename temp to target.
+ */
+
+ err = GenerateUniqueName(srcFileSpecPtr->vRefNum,
+ srcFileSpecPtr->parID, dstID, tmpName);
+ FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,
+ tmpName, &tmpSrcFileSpec);
+ FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum, dstID, tmpName,
+ &tmpDstFileSpec);
+ }
+ if (err == noErr) {
+ err = FSpRenameCompat(srcFileSpecPtr, tmpName);
+ }
+ if (err == noErr) {
+ err = FSpCatMoveCompat(&tmpSrcFileSpec, dstDirSpecPtr);
+ if (err == noErr) {
+ err = FSpRenameCompat(&tmpDstFileSpec, copyName);
+ if (err == noErr) {
+ goto done;
+ }
+ FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,
+ NULL, &srcDirSpec);
+ FSpCatMoveCompat(&tmpDstFileSpec, &srcDirSpec);
+ }
+ FSpRenameCompat(&tmpSrcFileSpec, srcFileSpecPtr->name);
+ }
+
+ done:
+ if (locked != false) {
+ if (err == noErr) {
+ FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum,
+ dstID, copyName, &dstFileSpec);
+ FSpSetFLockCompat(&dstFileSpec);
+ } else {
+ FSpSetFLockCompat(srcFileSpecPtr);
+ }
+ }
+ return err;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetFileSpecs --
+ *
+ * Generate a filename that is not in either of the two specified
+ * directories (on the same volume).
+ *
+ * Results:
+ * Standard macintosh error. On success, uniqueName is filled with
+ * the name of the temporary file.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static OSErr
+GenerateUniqueName(
+ short vRefNum, /* Volume on which the following directories
+ * are located. */
+ long dirID1, /* ID of first directory. */
+ long dirID2, /* ID of second directory. May be the same
+ * as the first. */
+ Str31 uniqueName) /* Filled with filename for a file that is
+ * not located in either of the above two
+ * directories. */
+{
+ OSErr err;
+ long i;
+ CInfoPBRec pb;
+ static unsigned char hexStr[16] = "0123456789ABCDEF";
+ static long startSeed = 248923489;
+
+ pb.hFileInfo.ioVRefNum = vRefNum;
+ pb.hFileInfo.ioFDirIndex = 0;
+ pb.hFileInfo.ioNamePtr = uniqueName;
+
+ while (1) {
+ startSeed++;
+ pb.hFileInfo.ioNamePtr[0] = 8;
+ for (i = 1; i <= 8; i++) {
+ pb.hFileInfo.ioNamePtr[i] = hexStr[((startSeed >> ((8-i)*4)) & 0xf)];
+ }
+ pb.hFileInfo.ioDirID = dirID1;
+ err = PBGetCatInfoSync(&pb);
+ if (err == fnfErr) {
+ if (dirID1 != dirID2) {
+ pb.hFileInfo.ioDirID = dirID2;
+ err = PBGetCatInfoSync(&pb);
+ }
+ if (err == fnfErr) {
+ return noErr;
+ }
+ }
+ if (err == noErr) {
+ continue;
+ }
+ return err;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetFileSpecs --
+ *
+ * Gets FSSpecs for the specified path and its parent directory.
+ *
+ * Results:
+ * The return value is noErr if there was no error getting FSSpecs,
+ * otherwise it is an error describing the problem. Fills buffers
+ * with information, as above.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static OSErr
+GetFileSpecs(
+ char *path, /* The path to query. */
+ FSSpec *pathSpecPtr, /* Filled with information about path. */
+ FSSpec *dirSpecPtr, /* Filled with information about path's
+ * parent directory. */
+ Boolean *pathExistsPtr, /* Set to true if path actually exists,
+ * false if it doesn't or there was an
+ * error reading the specified path. */
+ Boolean *pathIsDirectoryPtr)/* Set to true if path is itself a directory,
+ * otherwise false. */
+{
+ char *dirName;
+ OSErr err;
+ int argc;
+ char **argv;
+ long d;
+ Tcl_DString buffer;
+
+ *pathExistsPtr = false;
+ *pathIsDirectoryPtr = false;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_SplitPath(path, &argc, &argv);
+ if (argc == 1) {
+ dirName = ":";
+ } else {
+ dirName = Tcl_JoinPath(argc - 1, argv, &buffer);
+ }
+ err = FSpLocationFromPath(strlen(dirName), dirName, dirSpecPtr);
+ Tcl_DStringFree(&buffer);
+ ckfree((char *) argv);
+
+ if (err == noErr) {
+ err = FSpLocationFromPath(strlen(path), path, pathSpecPtr);
+ if (err == noErr) {
+ *pathExistsPtr = true;
+ err = FSpGetDirectoryID(pathSpecPtr, &d, pathIsDirectoryPtr);
+ } else if (err == fnfErr) {
+ err = noErr;
+ }
+ }
+ return err;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FSpGetFLockCompat --
+ *
+ * Determines if there exists a software lock on the specified
+ * file. The software lock could prevent the file from being
+ * renamed or moved.
+ *
+ * Results:
+ * Standard macintosh error code.
+ *
+ * Side effects:
+ * None.
+ *
+ *
+ *-------------------------------------------------------------------------
+ */
+
+OSErr
+FSpGetFLockCompat(
+ const FSSpec *specPtr, /* File to query. */
+ Boolean *lockedPtr) /* Set to true if file is locked, false
+ * if it isn't or there was an error reading
+ * specified file. */
+{
+ CInfoPBRec pb;
+ OSErr err;
+
+ pb.hFileInfo.ioVRefNum = specPtr->vRefNum;
+ pb.hFileInfo.ioDirID = specPtr->parID;
+ pb.hFileInfo.ioNamePtr = (StringPtr) specPtr->name;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if ((err == noErr) && (pb.hFileInfo.ioFlAttrib & 0x01)) {
+ *lockedPtr = true;
+ } else {
+ *lockedPtr = false;
+ }
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pstrequal --
+ *
+ * Pascal string compare.
+ *
+ * Results:
+ * Returns 1 if strings equal, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pstrequal (
+ ConstStr255Param stringA, /* Pascal string A */
+ ConstStr255Param stringB) /* Pascal string B */
+{
+ int i, len;
+
+ len = *stringA;
+ for (i = 0; i <= len; i++) {
+ if (*stringA++ != *stringB++) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFileFinderAttributes --
+ *
+ * Returns a Tcl_Obj containing the value of a file attribute
+ * which is part of the FInfo record. Which attribute is controlled
+ * by objIndex.
+ *
+ * Results:
+ * Returns a standard TCL error. If the return value is TCL_OK,
+ * the new creator or file type object is put into attributePtrPtr.
+ * The object will have ref count 0. If there is an error,
+ * attributePtrPtr is not touched.
+ *
+ * Side effects:
+ * A new object is allocated if the file is valid.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetFileFinderAttributes(
+ Tcl_Interp *interp, /* The interp to report errors with. */
+ int objIndex, /* The index of the attribute option. */
+ char *fileName, /* The name of the file. */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ FInfo finfo;
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+
+ if (err == noErr) {
+ err = FSpGetFInfo(&fileSpec, &finfo);
+ }
+
+ if (err == noErr) {
+ switch (objIndex) {
+ case MAC_CREATOR_ATTRIBUTE:
+ *attributePtrPtr = Tcl_NewOSTypeObj(finfo.fdCreator);
+ break;
+ case MAC_HIDDEN_ATTRIBUTE:
+ *attributePtrPtr = Tcl_NewBooleanObj(finfo.fdFlags
+ & kIsInvisible);
+ break;
+ case MAC_TYPE_ATTRIBUTE:
+ *attributePtrPtr = Tcl_NewOSTypeObj(finfo.fdType);
+ break;
+ }
+ } else if (err == fnfErr) {
+ long dirID;
+ Boolean isDirectory = 0;
+
+ err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ if ((err == noErr) && isDirectory) {
+ if (objIndex == MAC_HIDDEN_ATTRIBUTE) {
+ *attributePtrPtr = Tcl_NewBooleanObj(0);
+ } else {
+ *attributePtrPtr = Tcl_NewOSTypeObj('Fldr');
+ }
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "couldn't get attributes for file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFileReadOnly --
+ *
+ * Returns a Tcl_Obj containing a Boolean value indicating whether
+ * or not the file is read-only. The object will have ref count 0.
+ * This procedure just checks the Finder attributes; it does not
+ * check AppleShare sharing attributes.
+ *
+ * Results:
+ * Returns a standard TCL error. If the return value is TCL_OK,
+ * the new creator type object is put into readOnlyPtrPtr.
+ * If there is an error, readOnlyPtrPtr is not touched.
+ *
+ * Side effects:
+ * A new object is allocated if the file is valid.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetFileReadOnly(
+ Tcl_Interp *interp, /* The interp to report errors with. */
+ int objIndex, /* The index of the attribute. */
+ char *fileName, /* The name of the file. */
+ Tcl_Obj **readOnlyPtrPtr) /* A pointer to return the object with. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ CInfoPBRec paramBlock;
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+
+ if (err == noErr) {
+ if (err == noErr) {
+ paramBlock.hFileInfo.ioCompletion = NULL;
+ paramBlock.hFileInfo.ioNamePtr = fileSpec.name;
+ paramBlock.hFileInfo.ioVRefNum = fileSpec.vRefNum;
+ paramBlock.hFileInfo.ioFDirIndex = 0;
+ paramBlock.hFileInfo.ioDirID = fileSpec.parID;
+ err = PBGetCatInfo(&paramBlock, 0);
+ if (err == noErr) {
+
+ /*
+ * For some unknown reason, the Mac does not give
+ * symbols for the bits in the ioFlAttrib field.
+ * 1 -> locked.
+ */
+
+ *readOnlyPtrPtr = Tcl_NewBooleanObj(
+ paramBlock.hFileInfo.ioFlAttrib & 1);
+ }
+ }
+ }
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "couldn't get attributes for file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetFileFinderAttributes --
+ *
+ * Sets the file to the creator or file type given by attributePtr.
+ * objIndex determines whether the creator or file type is set.
+ *
+ * Results:
+ * Returns a standard TCL error.
+ *
+ * Side effects:
+ * The file's attribute is set.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetFileFinderAttributes(
+ Tcl_Interp *interp, /* The interp to report errors with. */
+ int objIndex, /* The index of the attribute. */
+ char *fileName, /* The name of the file. */
+ Tcl_Obj *attributePtr) /* The command line object. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ FInfo finfo;
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+
+ if (err == noErr) {
+ err = FSpGetFInfo(&fileSpec, &finfo);
+ }
+
+ if (err == noErr) {
+ switch (objIndex) {
+ case MAC_CREATOR_ATTRIBUTE:
+ if (Tcl_GetOSTypeFromObj(interp, attributePtr,
+ &finfo.fdCreator) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case MAC_HIDDEN_ATTRIBUTE: {
+ int hidden;
+
+ if (Tcl_GetBooleanFromObj(interp, attributePtr, &hidden)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (hidden) {
+ finfo.fdFlags |= kIsInvisible;
+ } else {
+ finfo.fdFlags &= ~kIsInvisible;
+ }
+ break;
+ }
+ case MAC_TYPE_ATTRIBUTE:
+ if (Tcl_GetOSTypeFromObj(interp, attributePtr,
+ &finfo.fdType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ }
+ err = FSpSetFInfo(&fileSpec, &finfo);
+ } else if (err == fnfErr) {
+ long dirID;
+ Boolean isDirectory = 0;
+
+ err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ if ((err == noErr) && isDirectory) {
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+ Tcl_AppendStringsToObj(resultPtr, "cannot set ",
+ tclpFileAttrStrings[objIndex], ": \"",
+ fileName, "\" is a directory", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "couldn't set attributes for file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetFileReadOnly --
+ *
+ * Sets the file to be read-only according to the Boolean value
+ * given by hiddenPtr.
+ *
+ * Results:
+ * Returns a standard TCL error.
+ *
+ * Side effects:
+ * The file's attribute is set.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetFileReadOnly(
+ Tcl_Interp *interp, /* The interp to report errors with. */
+ int objIndex, /* The index of the attribute. */
+ char *fileName, /* The name of the file. */
+ Tcl_Obj *readOnlyPtr) /* The command line object. */
+{
+ OSErr err;
+ FSSpec fileSpec;
+ HParamBlockRec paramBlock;
+ int hidden;
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+
+ if (err == noErr) {
+ if (Tcl_GetBooleanFromObj(interp, readOnlyPtr, &hidden) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ paramBlock.fileParam.ioCompletion = NULL;
+ paramBlock.fileParam.ioNamePtr = fileSpec.name;
+ paramBlock.fileParam.ioVRefNum = fileSpec.vRefNum;
+ paramBlock.fileParam.ioDirID = fileSpec.parID;
+ if (hidden) {
+ err = PBHSetFLock(&paramBlock, 0);
+ } else {
+ err = PBHRstFLock(&paramBlock, 0);
+ }
+ }
+
+ if (err == fnfErr) {
+ long dirID;
+ Boolean isDirectory = 0;
+ err = FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ if ((err == noErr) && isDirectory) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot set a directory to read-only when File Sharing is turned off",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ err = fnfErr;
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "couldn't set attributes for file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpListVolumes --
+ *
+ * Lists the currently mounted volumes
+ *
+ * Results:
+ * A standard Tcl result. Will always be TCL_OK, since there is no way
+ * that this command can fail. Also, the interpreter's result is set to
+ * the list of volumes.
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpListVolumes(
+ Tcl_Interp *interp) /* Interpreter to which to pass the volume list */
+{
+ HParamBlockRec pb;
+ Str255 name;
+ OSErr theError = noErr;
+ Tcl_Obj *resultPtr, *elemPtr;
+ short volIndex = 1;
+
+ resultPtr = Tcl_NewObj();
+
+ /*
+ * We use two facts:
+ * 1) The Mac volumes are enumerated by the ioVolIndex parameter of
+ * the HParamBlockRec. They run through the integers contiguously,
+ * starting at 1.
+ * 2) PBHGetVInfoSync returns an error when you ask for a volume index
+ * that does not exist.
+ *
+ */
+
+ while ( 1 ) {
+ pb.volumeParam.ioNamePtr = (StringPtr) & name;
+ pb.volumeParam.ioVolIndex = volIndex;
+
+ theError = PBHGetVInfoSync(&pb);
+
+ if ( theError != noErr ) {
+ break;
+ }
+
+ elemPtr = Tcl_NewStringObj((char *) name + 1, (int) name[0]);
+ Tcl_AppendToObj(elemPtr, ":", 1);
+ Tcl_ListObjAppendElement(interp, resultPtr, elemPtr);
+
+ volIndex++;
+ }
+
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c
new file mode 100644
index 0000000..3d4a22b
--- /dev/null
+++ b/mac/tclMacFile.c
@@ -0,0 +1,840 @@
+/*
+ * tclMacFile.c --
+ *
+ * This file implements the channel drivers for Macintosh
+ * files. It also comtains Macintosh version of other Tcl
+ * functions that deal with the file system.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacFile.c 1.57 97/04/23 16:23:05
+ */
+
+/*
+ * Note: This code eventually needs to support async I/O. In doing this
+ * we will need to keep track of all current async I/O. If exit to shell
+ * is called - we shouldn't exit until all asyc I/O completes.
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMacInt.h"
+#include <Aliases.h>
+#include <Errors.h>
+#include <Processes.h>
+#include <Strings.h>
+#include <Types.h>
+#include <MoreFiles.h>
+#include <MoreFilesExtras.h>
+#include <FSpCompat.h>
+
+/*
+ * Static variables used by the TclMacStat function.
+ */
+static int initalized = false;
+static long gmt_offset;
+
+/*
+ * The variable below caches the name of the current working directory
+ * in order to avoid repeated calls to getcwd. The string is malloc-ed.
+ * NULL means the cache needs to be refreshed.
+ */
+
+static char *currentDir = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclChdir --
+ *
+ * Change the current working directory.
+ *
+ * Results:
+ * The result is a standard Tcl result. If an error occurs and
+ * interp isn't NULL, an error message is left in interp->result.
+ *
+ * Side effects:
+ * The working directory for this application is changed. Also
+ * the cache maintained used by TclGetCwd is deallocated and
+ * set to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclChdir(
+ Tcl_Interp *interp, /* If non NULL, used for error reporting. */
+ char *dirName) /* Path to new working directory. */
+{
+ FSSpec spec;
+ OSErr err;
+ Boolean isFolder;
+ long dirID;
+
+ if (currentDir != NULL) {
+ ckfree(currentDir);
+ currentDir = NULL;
+ }
+
+ err = FSpLocationFromPath(strlen(dirName), dirName, &spec);
+ if (err != noErr) {
+ errno = ENOENT;
+ goto chdirError;
+ }
+
+ err = FSpGetDirectoryID(&spec, &dirID, &isFolder);
+ if (err != noErr) {
+ errno = ENOENT;
+ goto chdirError;
+ }
+
+ if (isFolder != true) {
+ errno = ENOTDIR;
+ goto chdirError;
+ }
+
+ err = FSpSetDefaultDir(&spec);
+ if (err != noErr) {
+ switch (err) {
+ case afpAccessDenied:
+ errno = EACCES;
+ break;
+ default:
+ errno = ENOENT;
+ }
+ goto chdirError;
+ }
+
+ return TCL_OK;
+ chdirError:
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "couldn't change working directory to \"",
+ dirName, "\": ", Tcl_PosixError(interp), (char *) NULL);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetCwd --
+ *
+ * Return the path name of the current working directory.
+ *
+ * Results:
+ * The result is the full path name of the current working
+ * directory, or NULL if an error occurred while figuring it
+ * out. If an error occurs and interp isn't NULL, an error
+ * message is left in interp->result.
+ *
+ * Side effects:
+ * The path name is cached to avoid having to recompute it
+ * on future calls; if it is already cached, the cached
+ * value is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclGetCwd(
+ Tcl_Interp *interp) /* If non NULL, used for error reporting. */
+{
+ FSSpec theSpec;
+ int length;
+ Handle pathHandle = NULL;
+
+ if (currentDir == NULL) {
+ if (FSpGetDefaultDir(&theSpec) != noErr) {
+ if (interp != NULL) {
+ interp->result = "error getting working directory name";
+ }
+ return NULL;
+ }
+ if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) {
+ if (interp != NULL) {
+ interp->result = "error getting working directory name";
+ }
+ return NULL;
+ }
+ HLock(pathHandle);
+ currentDir = (char *) ckalloc((unsigned) (length + 1));
+ strcpy(currentDir, *pathHandle);
+ HUnlock(pathHandle);
+ DisposeHandle(pathHandle);
+ }
+ return currentDir;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitPid --
+ *
+ * Fakes a call to wait pid.
+ *
+ * Results:
+ * Always returns -1.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Pid
+Tcl_WaitPid(
+ Tcl_Pid pid,
+ int *statPtr,
+ int options)
+{
+ return (Tcl_Pid) -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindExecutable --
+ *
+ * This procedure computes the absolute path name of the current
+ * application, given its argv[0] value. However, this
+ * implementation doesn't use of need the argv[0] value. NULL
+ * may be passed in its place.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The variable tclExecutableName gets filled in with the file
+ * name for the application, if we figured it out. If we couldn't
+ * figure it out, Tcl_FindExecutable is set to NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FindExecutable(
+ char *argv0) /* The value of the application's argv[0]. */
+{
+ ProcessSerialNumber psn;
+ ProcessInfoRec info;
+ Str63 appName;
+ FSSpec fileSpec;
+ int pathLength;
+ Handle pathName = NULL;
+ OSErr err;
+
+ GetCurrentProcess(&psn);
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = appName;
+ info.processAppSpec = &fileSpec;
+ GetProcessInformation(&psn, &info);
+
+ if (tclExecutableName != NULL) {
+ ckfree(tclExecutableName);
+ tclExecutableName = NULL;
+ }
+
+ err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName);
+
+ tclExecutableName = (char *) ckalloc((unsigned) pathLength + 1);
+ HLock(pathName);
+ strcpy(tclExecutableName, *pathName);
+ HUnlock(pathName);
+ DisposeHandle(pathName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetUserHome --
+ *
+ * This function takes the passed in user name and finds the
+ * corresponding home directory specified in the password file.
+ *
+ * Results:
+ * On a Macintosh we always return a NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TclGetUserHome(
+ char *name, /* User name to use to find home directory. */
+ Tcl_DString *bufferPtr) /* May be used to hold result. Must not hold
+ * anything at the time of the call, and need
+ * not even be initialized. */
+{
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMatchFiles --
+ *
+ * This routine is used by the globbing code to search a
+ * directory for all files which match a given pattern.
+ *
+ * Results:
+ * If the tail argument is NULL, then the matching files are
+ * added to the interp->result. Otherwise, TclDoGlob is called
+ * recursively for each matching subdirectory. The return value
+ * is a standard Tcl result indicating whether an error occurred
+ * in globbing.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------- */
+
+int
+TclMatchFiles(
+ Tcl_Interp *interp, /* Interpreter to receive results. */
+ char *separators, /* Directory separators to pass to TclDoGlob. */
+ Tcl_DString *dirPtr, /* Contains path to directory to search. */
+ char *pattern, /* Pattern to match against. */
+ char *tail) /* Pointer to end of pattern. Tail must
+ * point to a location in pattern. */
+{
+ char *dirName, *patternEnd = tail;
+ char savedChar;
+ int result = TCL_OK;
+ int baseLength = Tcl_DStringLength(dirPtr);
+ CInfoPBRec pb;
+ OSErr err;
+ FSSpec dirSpec;
+ Boolean isDirectory;
+ long dirID;
+ short itemIndex;
+ Str255 fileName;
+
+
+ /*
+ * Make sure that the directory part of the name really is a
+ * directory.
+ */
+
+ dirName = dirPtr->string;
+ FSpLocationFromPath(strlen(dirName), dirName, &dirSpec);
+ err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
+ if ((err != noErr) || !isDirectory) {
+ return TCL_OK;
+ }
+
+ /*
+ * Now open the directory for reading and iterate over the contents.
+ */
+
+ pb.hFileInfo.ioVRefNum = dirSpec.vRefNum;
+ pb.hFileInfo.ioDirID = dirID;
+ pb.hFileInfo.ioNamePtr = (StringPtr) fileName;
+ pb.hFileInfo.ioFDirIndex = itemIndex = 1;
+
+ /*
+ * Clean up the end of the pattern and the tail pointer. Leave
+ * the tail pointing to the first character after the path separator
+ * following the pattern, or NULL. Also, ensure that the pattern
+ * is null-terminated.
+ */
+
+ if (*tail == '\\') {
+ tail++;
+ }
+ if (*tail == '\0') {
+ tail = NULL;
+ } else {
+ tail++;
+ }
+ savedChar = *patternEnd;
+ *patternEnd = '\0';
+
+ while (1) {
+ pb.hFileInfo.ioFDirIndex = itemIndex;
+ pb.hFileInfo.ioDirID = dirID;
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr) {
+ break;
+ }
+
+ /*
+ * Now check to see if the file matches. If there are more
+ * characters to be processed, then ensure matching files are
+ * directories before calling TclDoGlob. Otherwise, just add
+ * the file to the result.
+ */
+
+ p2cstr(fileName);
+ if (Tcl_StringMatch((char *) fileName, pattern)) {
+ Tcl_DStringSetLength(dirPtr, baseLength);
+ Tcl_DStringAppend(dirPtr, (char *) fileName, -1);
+ if (tail == NULL) {
+ if ((dirPtr->length > 1) &&
+ (strchr(dirPtr->string+1, ':') == NULL)) {
+ Tcl_AppendElement(interp, dirPtr->string+1);
+ } else {
+ Tcl_AppendElement(interp, dirPtr->string);
+ }
+ } else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) {
+ Tcl_DStringAppend(dirPtr, ":", 1);
+ result = TclDoGlob(interp, separators, dirPtr, tail);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ }
+
+ itemIndex++;
+ }
+ *patternEnd = savedChar;
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacStat --
+ *
+ * This function replaces the library version of stat. The stat
+ * function provided by most Mac compiliers is rather broken and
+ * incomplete.
+ *
+ * Results:
+ * See stat documentation.
+ *
+ * Side effects:
+ * See stat documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacStat(
+ char *path,
+ struct stat *buf)
+{
+ HFileInfo fpb;
+ HVolumeParam vpb;
+ OSErr err;
+ FSSpec fileSpec;
+ Boolean isDirectory;
+ long dirID;
+
+ err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ }
+
+ /*
+ * Fill the fpb & vpb struct up with info about file or directory.
+ */
+
+ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
+ vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
+ if (isDirectory) {
+ fpb.ioDirID = fileSpec.parID;
+ } else {
+ fpb.ioDirID = dirID;
+ }
+
+ fpb.ioFDirIndex = 0;
+ err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
+ if (err == noErr) {
+ vpb.ioVolIndex = 0;
+ err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
+ if (err == noErr && buf != NULL) {
+ /*
+ * Files are always readable by everyone.
+ */
+
+ buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
+
+ /*
+ * Use the Volume Info & File Info to fill out stat buf.
+ */
+ if (fpb.ioFlAttrib & 0x10) {
+ buf->st_mode |= S_IFDIR;
+ buf->st_nlink = 2;
+ } else {
+ buf->st_nlink = 1;
+ if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
+ buf->st_mode |= S_IFLNK;
+ } else {
+ buf->st_mode |= S_IFREG;
+ }
+ }
+ if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) {
+ /*
+ * Directories and applications are executable by everyone.
+ */
+
+ buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
+ }
+ if ((fpb.ioFlAttrib & 0x01) == 0){
+ /*
+ * If not locked, then everyone has write acces.
+ */
+
+ buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ }
+ buf->st_ino = fpb.ioDirID;
+ buf->st_dev = fpb.ioVRefNum;
+ buf->st_uid = -1;
+ buf->st_gid = -1;
+ buf->st_rdev = 0;
+ buf->st_size = fpb.ioFlLgLen;
+ buf->st_blksize = vpb.ioVAlBlkSiz;
+ buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
+ / buf->st_blksize;
+
+ /*
+ * The times returned by the Mac file system are in the
+ * local time zone. We convert them to GMT so that the
+ * epoch starts from GMT. This is also consistant with
+ * what is returned from "clock seconds".
+ */
+ if (initalized == false) {
+ MachineLocation loc;
+
+ ReadLocation(&loc);
+ gmt_offset = loc.u.gmtDelta & 0x00ffffff;
+ if (gmt_offset & 0x00800000) {
+ gmt_offset = gmt_offset | 0xff000000;
+ }
+ initalized = true;
+ }
+ buf->st_atime = buf->st_mtime = fpb.ioFlMdDat - gmt_offset;
+ buf->st_ctime = fpb.ioFlCrDat - gmt_offset;
+
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ }
+
+ return (err == noErr ? 0 : -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacReadlink --
+ *
+ * This function replaces the library version of readlink.
+ *
+ * Results:
+ * See readlink documentation.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacReadlink(
+ char *path,
+ char *buf,
+ int size)
+{
+ HFileInfo fpb;
+ OSErr err;
+ FSSpec fileSpec;
+ Boolean isDirectory;
+ Boolean wasAlias;
+ long dirID;
+ char fileName[256];
+ char *end;
+ Handle theString = NULL;
+ int pathSize;
+
+ /*
+ * Remove ending colons if they exist.
+ */
+ while ((strlen(path) != 0) && (path[strlen(path) - 1] == ':')) {
+ path[strlen(path) - 1] = NULL;
+ }
+
+ if (strchr(path, ':') == NULL) {
+ strcpy(fileName, path);
+ path = NULL;
+ } else {
+ end = strrchr(path, ':') + 1;
+ strcpy(fileName, end);
+ *end = NULL;
+ }
+ c2pstr(fileName);
+
+ /*
+ * Create the file spec for the directory of the file
+ * we want to look at.
+ */
+ if (path != NULL) {
+ err = FSpLocationFromPath(strlen(path), path, &fileSpec);
+ if (err != noErr) {
+ errno = EINVAL;
+ return -1;
+ }
+ } else {
+ FSMakeFSSpecCompat(0, 0, NULL, &fileSpec);
+ }
+
+ /*
+ * Fill the fpb struct up with info about file or directory.
+ */
+ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ fpb.ioVRefNum = fileSpec.vRefNum;
+ fpb.ioDirID = dirID;
+ fpb.ioNamePtr = (StringPtr) fileName;
+
+ fpb.ioFDirIndex = 0;
+ err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ } else {
+ if (fpb.ioFlAttrib & 0x10) {
+ errno = EINVAL;
+ return -1;
+ } else {
+ if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
+ /*
+ * The file is a link!
+ */
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * If we are here it's really a link - now find out
+ * where it points to.
+ */
+ err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, &fileSpec);
+ if (err == noErr) {
+ err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias);
+ }
+ if ((err == fnfErr) || wasAlias) {
+ err = FSpPathFromLocation(&fileSpec, &pathSize, &theString);
+ if ((err != noErr) || (pathSize > size)) {
+ DisposeHandle(theString);
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ } else {
+ errno = EINVAL;
+ return -1;
+ }
+
+ strncpy(buf, *theString, pathSize);
+ DisposeHandle(theString);
+
+ return pathSize;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacAccess --
+ *
+ * This function replaces the library version of access. The
+ * access function provided by most Mac compiliers is rather
+ * broken or incomplete.
+ *
+ * Results:
+ * See access documentation.
+ *
+ * Side effects:
+ * See access documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacAccess(
+ const char *path,
+ int mode)
+{
+ HFileInfo fpb;
+ HVolumeParam vpb;
+ OSErr err;
+ FSSpec fileSpec;
+ Boolean isDirectory;
+ long dirID;
+ int full_mode = 0;
+
+ err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec);
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ }
+
+ /*
+ * Fill the fpb & vpb struct up with info about file or directory.
+ */
+ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
+ vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
+ vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
+ if (isDirectory) {
+ fpb.ioDirID = fileSpec.parID;
+ } else {
+ fpb.ioDirID = dirID;
+ }
+
+ fpb.ioFDirIndex = 0;
+ err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
+ if (err == noErr) {
+ vpb.ioVolIndex = 0;
+ err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
+ if (err == noErr) {
+ /*
+ * Use the Volume Info & File Info to determine
+ * access information. If we have got this far
+ * we know the directory is searchable or the file
+ * exists. (We have F_OK)
+ */
+
+ /*
+ * Check to see if the volume is hardware or
+ * software locked. If so we arn't W_OK.
+ */
+ if (mode & W_OK) {
+ if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) {
+ errno = EROFS;
+ return -1;
+ }
+ if (fpb.ioFlAttrib & 0x01) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+
+ /*
+ * Directories are always searchable and executable. But only
+ * files of type 'APPL' are executable.
+ */
+ if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK)
+ && (fpb.ioFlFndrInfo.fdType != 'APPL')) {
+ return -1;
+ }
+ }
+ }
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacFOpenHack --
+ *
+ * This function replaces fopen. It supports paths with alises.
+ * Note, remember to undefine the fopen macro!
+ *
+ * Results:
+ * See fopen documentation.
+ *
+ * Side effects:
+ * See fopen documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#undef fopen
+FILE *
+TclMacFOpenHack(
+ const char *path,
+ const char *mode)
+{
+ OSErr err;
+ FSSpec fileSpec;
+ Handle pathString = NULL;
+ int size;
+ FILE * f;
+
+ err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec);
+ if ((err != noErr) && (err != fnfErr)) {
+ return NULL;
+ }
+ err = FSpPathFromLocation(&fileSpec, &size, &pathString);
+ if ((err != noErr) && (err != fnfErr)) {
+ return NULL;
+ }
+
+ HLock(pathString);
+ f = fopen(*pathString, mode);
+ HUnlock(pathString);
+ DisposeHandle(pathString);
+ return f;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacOSErrorToPosixError --
+ *
+ * Given a Macintosh OSErr return the appropiate POSIX error.
+ *
+ * Results:
+ * A Posix error.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacOSErrorToPosixError(
+ int error) /* A Macintosh error. */
+{
+ switch (error) {
+ case noErr:
+ return 0;
+ case bdNamErr:
+ return ENAMETOOLONG;
+ case afpObjectTypeErr:
+ return ENOTDIR;
+ case fnfErr:
+ case dirNFErr:
+ return ENOENT;
+ case dupFNErr:
+ return EEXIST;
+ case dirFulErr:
+ case dskFulErr:
+ return ENOSPC;
+ case fBsyErr:
+ return EBUSY;
+ case tmfoErr:
+ return ENFILE;
+ case fLckdErr:
+ case permErr:
+ case afpAccessDenied:
+ return EACCES;
+ case wPrErr:
+ case vLckdErr:
+ return EROFS;
+ case badMovErr:
+ return EINVAL;
+ case diffVolErr:
+ return EXDEV;
+ default:
+ return EINVAL;
+ }
+}
diff --git a/mac/tclMacInit.c b/mac/tclMacInit.c
new file mode 100644
index 0000000..9dc6bd0
--- /dev/null
+++ b/mac/tclMacInit.c
@@ -0,0 +1,284 @@
+/*
+ * tclMacInit.c --
+ *
+ * Contains the Mac-specific interpreter initialization functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacInit.c 1.39 97/09/23 13:17:30
+ */
+
+#include <Files.h>
+#include <Gestalt.h>
+#include <TextUtils.h>
+#include <Resources.h>
+#include <Strings.h>
+#include "tclInt.h"
+#include "tclMacInt.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclPlatformInit --
+ *
+ * Performs Mac-specific interpreter initialization related to the
+ * tcl_platform and tcl_library variables.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets "tcl_library" & "tcl_platfrom" Tcl variable
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclPlatformInit(
+ Tcl_Interp *interp) /* Tcl interpreter to initialize. */
+{
+ char *libDir;
+ Tcl_DString path, libPath;
+ long int gestaltResult;
+ int minor, major;
+ char versStr[10];
+
+ /*
+ * Set runtime C variable that tells cross platform C functions
+ * what platform they are running on. This can change at
+ * runtime for testing purposes.
+ */
+ tclPlatform = TCL_PLATFORM_MAC;
+
+ /*
+ * Define the tcl_platfrom variable.
+ */
+ Tcl_SetVar2(interp, "tcl_platform", "platform", "macintosh",
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "os", "MacOS", TCL_GLOBAL_ONLY);
+ Gestalt(gestaltSystemVersion, &gestaltResult);
+ major = (gestaltResult & 0x0000FF00) >> 8;
+ minor = (gestaltResult & 0x000000F0) >> 4;
+ sprintf(versStr, "%d.%d", major, minor);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", versStr, TCL_GLOBAL_ONLY);
+#if GENERATINGPOWERPC
+ Tcl_SetVar2(interp, "tcl_platform", "machine", "ppc", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "tcl_platform", "machine", "68k", TCL_GLOBAL_ONLY);
+#endif
+
+ /*
+ * The tcl_library path can be found in one of two places. As an element
+ * in the env array. Or the default which is to a folder in side the
+ * Extensions folder of your system.
+ */
+
+ Tcl_DStringInit(&path);
+ libDir = Tcl_GetVar2(interp, "env", "TCL_LIBRARY", TCL_GLOBAL_ONLY);
+ if (libDir != NULL) {
+ Tcl_SetVar(interp, "tcl_library", libDir, TCL_GLOBAL_ONLY);
+ } else {
+ libDir = Tcl_GetVar2(interp, "env", "EXT_FOLDER", TCL_GLOBAL_ONLY);
+ if (libDir != NULL) {
+ Tcl_JoinPath(1, &libDir, &path);
+
+ Tcl_DStringInit(&libPath);
+ Tcl_DStringAppend(&libPath, ":Tool Command Language:tcl", -1);
+ Tcl_DStringAppend(&libPath, TCL_VERSION, -1);
+ Tcl_JoinPath(1, &libPath.string, &path);
+ Tcl_DStringFree(&libPath);
+ Tcl_SetVar(interp, "tcl_library", path.string, TCL_GLOBAL_ONLY);
+ } else {
+ Tcl_SetVar(interp, "tcl_library", "no library", TCL_GLOBAL_ONLY);
+ }
+ }
+
+ /*
+ * Now create the tcl_pkgPath variable.
+ */
+ Tcl_DStringSetLength(&path, 0);
+ libDir = Tcl_GetVar2(interp, "env", "EXT_FOLDER", TCL_GLOBAL_ONLY);
+ if (libDir != NULL) {
+ Tcl_JoinPath(1, &libDir, &path);
+ libDir = ":Tool Command Language:";
+ Tcl_JoinPath(1, &libDir, &path);
+ Tcl_SetVar(interp, "tcl_pkgPath", path.string,
+ TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT);
+ } else {
+ Tcl_SetVar(interp, "tcl_pkgPath", "no extension folder",
+ TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT);
+ }
+ Tcl_DStringFree(&path);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpCheckStackSpace --
+ *
+ * On a 68K Mac, we can detect if we are about to blow the stack.
+ * Called before an evaluation can happen when nesting depth is
+ * checked.
+ *
+ * Results:
+ * 1 if there is enough stack space to continue; 0 if not.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpCheckStackSpace()
+{
+ return StackSpace() > TCL_MAC_STACK_THRESHOLD;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Init --
+ *
+ * This procedure is typically invoked by Tcl_AppInit procedures
+ * to perform additional initialization for a Tcl interpreter,
+ * such as sourcing the "init.tcl" script.
+ *
+ * Results:
+ * Returns a standard Tcl completion code and sets interp->result
+ * if there is an error.
+ *
+ * Side effects:
+ * Depends on what's in the init.tcl script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_Init(
+ Tcl_Interp *interp) /* Interpreter to initialize. */
+{
+ static char initCmd[] =
+ "if {[catch {source -rsrc Init}] != 0} {\n\
+ if [file exists [info library]:init.tcl] {\n\
+ source [info library]:init.tcl\n\
+ } else {\n\
+ set msg \"can't find Init resource or [info library]:init.tcl;\"\n\
+ append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\
+ append msg \"TCL_LIBRARY environment variable?\"\n\
+ error $msg\n\
+ }\n}\n\
+ if {[catch {source -rsrc History}] != 0} {\n\
+ if [file exists [info library]:history.tcl] {\n\
+ source [info library]:history.tcl\n\
+ } else {\n\
+ set msg \"can't find History resource or [info library]:history.tcl;\"\n\
+ append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\
+ append msg \"TCL_LIBRARY environment variable?\"\n\
+ error $msg\n\
+ }\n}\n\
+ if {[catch {source -rsrc Word}] != 0} {\n\
+ if [file exists [info library]:word.tcl] {\n\
+ source [info library]:word.tcl\n\
+ } else {\n\
+ set msg \"can't find Word resource or [info library]:word.tcl;\"\n\
+ append msg \" perhaps you need to\\ninstall Tcl or set your \"\n\
+ append msg \"TCL_LIBRARY environment variable?\"\n\
+ error $msg\n\
+ }\n}";
+
+ /*
+ * For Macintosh applications the Init function may be contained in
+ * the application resources. If it exists we use it - otherwise we
+ * look in the tcl_library directory. Ditto for the history command.
+ */
+
+ return Tcl_Eval(interp, initCmd);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SourceRCFile --
+ *
+ * This procedure is typically invoked by Tcl_Main or Tk_Main
+ * procedure to source an application specific rc file into the
+ * interpreter at startup time. This will either source a file
+ * in the "tcl_rcFileName" variable or a TEXT resource in the
+ * "tcl_rcRsrcName" variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what's in the rc script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SourceRCFile(
+ Tcl_Interp *interp) /* Interpreter to source rc file into. */
+{
+ Tcl_DString temp;
+ char *fileName;
+ Tcl_Channel errChannel;
+ Handle h;
+
+ fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY);
+
+ if (fileName != NULL) {
+ Tcl_Channel c;
+ char *fullName;
+
+ Tcl_DStringInit(&temp);
+ fullName = Tcl_TranslateFileName(interp, fileName, &temp);
+ if (fullName == NULL) {
+ /*
+ * Couldn't translate the file name (e.g. it referred to a
+ * bogus user or there was no HOME environment variable).
+ * Just do nothing.
+ */
+ } else {
+
+ /*
+ * Test for the existence of the rc file before trying to read it.
+ */
+
+ c = Tcl_OpenFileChannel(NULL, fullName, "r", 0);
+ if (c != (Tcl_Channel) NULL) {
+ Tcl_Close(NULL, c);
+ if (Tcl_EvalFile(interp, fullName) != TCL_OK) {
+ errChannel = Tcl_GetStdChannel(TCL_STDERR);
+ if (errChannel) {
+ Tcl_Write(errChannel, interp->result, -1);
+ Tcl_Write(errChannel, "\n", 1);
+ }
+ }
+ }
+ }
+ Tcl_DStringFree(&temp);
+ }
+
+ fileName = Tcl_GetVar(interp, "tcl_rcRsrcName", TCL_GLOBAL_ONLY);
+
+ if (fileName != NULL) {
+ c2pstr(fileName);
+ h = GetNamedResource('TEXT', (StringPtr) fileName);
+ p2cstr((StringPtr) fileName);
+ if (h != NULL) {
+ if (Tcl_MacEvalResource(interp, fileName, 0, NULL) != TCL_OK) {
+ errChannel = Tcl_GetStdChannel(TCL_STDERR);
+ if (errChannel) {
+ Tcl_Write(errChannel, interp->result, -1);
+ Tcl_Write(errChannel, "\n", 1);
+ }
+ }
+ Tcl_ResetResult(interp);
+ ReleaseResource(h);
+ }
+ }
+}
diff --git a/mac/tclMacInt.h b/mac/tclMacInt.h
new file mode 100644
index 0000000..d4d43b4
--- /dev/null
+++ b/mac/tclMacInt.h
@@ -0,0 +1,79 @@
+/*
+ * tclMacInt.h --
+ *
+ * Declarations of Macintosh specific shared variables and procedures.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacInt.h 1.24 97/09/09 16:22:01
+ */
+
+#ifndef _TCLMACINT
+#define _TCLMACINT
+
+#ifndef _TCL
+# include "tcl.h"
+#endif
+#ifndef _TCLMAC
+# include "tclMac.h"
+#endif
+
+#include <Events.h>
+#include <Files.h>
+
+#pragma export on
+
+/*
+ * Defines to control stack behavior
+ */
+
+#define TCL_MAC_68K_STACK_GROWTH (256*1024)
+#define TCL_MAC_STACK_THRESHOLD 16384
+
+/*
+ * This flag is passed to TclMacRegisterResourceFork
+ * by a file (usually a library) whose resource fork
+ * should not be closed by the resource command.
+ */
+
+#define TCL_RESOURCE_DONT_CLOSE 2
+
+/*
+ * Typedefs used by Macintosh parts of Tcl.
+ */
+typedef pascal void (*ExitToShellProcPtr)(void);
+
+/*
+ * Prototypes for functions found in the tclMacUtil.c compatability library.
+ */
+
+EXTERN int FSpGetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec));
+EXTERN int FSpSetDefaultDir _ANSI_ARGS_((FSSpecPtr theSpec));
+EXTERN OSErr FSpFindFolder _ANSI_ARGS_((short vRefNum, OSType folderType,
+ Boolean createFolder, FSSpec *spec));
+EXTERN void GetGlobalMouse _ANSI_ARGS_((Point *mouse));
+
+/*
+ * Prototypes of Mac only internal functions.
+ */
+
+EXTERN void TclCreateMacEventSource _ANSI_ARGS_((void));
+EXTERN int TclMacConsoleInit _ANSI_ARGS_((void));
+EXTERN void TclMacExitHandler _ANSI_ARGS_((void));
+EXTERN void TclMacInitExitToShell _ANSI_ARGS_((int usePatch));
+EXTERN OSErr TclMacInstallExitToShellPatch _ANSI_ARGS_((
+ ExitToShellProcPtr newProc));
+EXTERN int TclMacOSErrorToPosixError _ANSI_ARGS_((int error));
+EXTERN void TclMacRemoveTimer _ANSI_ARGS_((void *timerToken));
+EXTERN void * TclMacStartTimer _ANSI_ARGS_((long ms));
+EXTERN int TclMacTimerExpired _ANSI_ARGS_((void *timerToken));
+EXTERN int TclMacRegisterResourceFork _ANSI_ARGS_((short fileRef, Tcl_Obj *tokenPtr,
+ int insert));
+EXTERN short TclMacUnRegisterResourceFork _ANSI_ARGS_((char *tokenPtr, Tcl_Obj *resultPtr));
+
+#pragma export reset
+
+#endif /* _TCLMACINT */
diff --git a/mac/tclMacInterupt.c b/mac/tclMacInterupt.c
new file mode 100644
index 0000000..97620f8
--- /dev/null
+++ b/mac/tclMacInterupt.c
@@ -0,0 +1,289 @@
+/*
+ * tclMacInterupt.c --
+ *
+ * This file contains routines that deal with the Macintosh's low level
+ * time manager. This code provides a better resolution timer than what
+ * can be provided by WaitNextEvent.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacInterupt.c 1.16 96/12/12 19:22:01
+ */
+
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include <LowMem.h>
+#include <Processes.h>
+#include <Timer.h>
+
+/*
+ * Data structure for timer tasks.
+ */
+typedef struct TMInfo {
+ TMTask tmTask;
+ ProcessSerialNumber psn;
+ Point lastPoint;
+ Point newPoint;
+ long currentA5;
+ long ourA5;
+ int installed;
+} TMInfo;
+
+/*
+ * Globals used within this file.
+ */
+
+static TimerUPP sleepTimerProc = NULL;
+static int interuptsInited = false;
+static ProcessSerialNumber applicationPSN;
+#define MAX_TIMER_ARRAY_SIZE 16
+static TMInfo timerInfoArray[MAX_TIMER_ARRAY_SIZE];
+static int topTimerElement = 0;
+
+/*
+ * Prototypes for procedures that are referenced only in this file:
+ */
+
+#if !GENERATINGCFM
+static TMInfo * GetTMInfo(void) ONEWORDINLINE(0x2E89); /* MOVE.L A1,(SP) */
+#endif
+static void SleepTimerProc _ANSI_ARGS_((void));
+static pascal void CleanUpExitProc _ANSI_ARGS_((void));
+static void InitInteruptSystem _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitInteruptSystem --
+ *
+ * Does various initialization for the functions used in this
+ * file. Sets up Universial Pricedure Pointers, installs a trap
+ * patch for ExitToShell, etc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Various initialization.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+InitInteruptSystem()
+{
+ int i;
+
+ sleepTimerProc = NewTimerProc(SleepTimerProc);
+ GetCurrentProcess(&applicationPSN);
+ for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
+ timerInfoArray[i].installed = false;
+ }
+
+ /*
+ * Install the ExitToShell patch. We use this patch instead
+ * of the Tcl exit mechanism because we need to ensure that
+ * these routines are cleaned up even if we crash or are forced
+ * to quit. There are some circumstances when the Tcl exit
+ * handlers may not fire.
+ */
+
+ TclMacInstallExitToShellPatch(CleanUpExitProc);
+ interuptsInited = true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacStartTimer --
+ *
+ * Install a Time Manager task to wake our process up in the
+ * future. The process should get a NULL event after ms
+ * milliseconds.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Schedules our process to wake up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TclMacStartTimer(
+ long ms) /* Milliseconds. */
+{
+ TMInfo *timerInfoPtr;
+
+ if (!interuptsInited) {
+ InitInteruptSystem();
+ }
+
+ /*
+ * Obtain a pointer for the timer. We only allocate up
+ * to MAX_TIMER_ARRAY_SIZE timers. If we are past that
+ * max we return NULL.
+ */
+ if (topTimerElement < MAX_TIMER_ARRAY_SIZE) {
+ timerInfoPtr = &timerInfoArray[topTimerElement];
+ topTimerElement++;
+ } else {
+ return NULL;
+ }
+
+ /*
+ * Install timer to wake process in ms milliseconds.
+ */
+ timerInfoPtr->tmTask.tmAddr = sleepTimerProc;
+ timerInfoPtr->tmTask.tmWakeUp = 0;
+ timerInfoPtr->tmTask.tmReserved = 0;
+ timerInfoPtr->psn = applicationPSN;
+ timerInfoPtr->installed = true;
+
+ InsTime((QElemPtr) timerInfoPtr);
+ PrimeTime((QElemPtr) timerInfoPtr, (long) ms);
+
+ return (void *) timerInfoPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacRemoveTimer --
+ *
+ * Remove the timer event from the Time Manager.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A scheduled timer would be removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclMacRemoveTimer(
+ void * timerToken) /* Token got from start timer. */
+{
+ TMInfo *timerInfoPtr = (TMInfo *) timerToken;
+
+ if (timerInfoPtr == NULL) {
+ return;
+ }
+
+ RmvTime((QElemPtr) timerInfoPtr);
+ timerInfoPtr->installed = false;
+ topTimerElement--;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacTimerExpired --
+ *
+ * Check to see if the installed timer has expired.
+ *
+ * Results:
+ * True if timer has expired, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacTimerExpired(
+ void * timerToken) /* Our token again. */
+{
+ TMInfo *timerInfoPtr = (TMInfo *) timerToken;
+
+ if ((timerInfoPtr == NULL) ||
+ !(timerInfoPtr->tmTask.qType & kTMTaskActive)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SleepTimerProc --
+ *
+ * Time proc is called by the is a callback routine placed in the
+ * system by Tcl_Sleep. The routine is called at interupt time
+ * and threrfor can not move or allocate memory. This call will
+ * schedule our process to wake up the next time the process gets
+ * around to consider running it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Schedules our process to wake up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SleepTimerProc()
+{
+ /*
+ * In CFM code we can access our code directly. In 68k code that
+ * isn't based on CFM we must do a glorious hack. The function
+ * GetTMInfo is an inline assembler call that moves the pointer
+ * at A1 to the top of the stack. The Time Manager keeps the TMTask
+ * info record there before calling this call back. In order for
+ * this to work the infoPtr argument must be the *last* item on the
+ * stack. If we "piggyback" our data to the TMTask info record we
+ * can get access to the information we need. While this is really
+ * ugly - it's the way Apple recomends it be done - go figure...
+ */
+
+#if GENERATINGCFM
+ WakeUpProcess(&applicationPSN);
+#else
+ TMInfo * infoPtr;
+
+ infoPtr = GetTMInfo();
+ WakeUpProcess(&infoPtr->psn);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanUpExitProc --
+ *
+ * This procedure is invoked as an exit handler when ExitToShell
+ * is called. It removes the system level timer handler if it
+ * is installed. This must be called or the Mac OS will more than
+ * likely crash.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal void
+CleanUpExitProc()
+{
+ int i;
+
+ for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
+ if (timerInfoArray[i].installed) {
+ RmvTime((QElemPtr) &timerInfoArray[i]);
+ timerInfoArray[i].installed = false;
+ }
+ }
+}
diff --git a/mac/tclMacLibrary.c b/mac/tclMacLibrary.c
new file mode 100644
index 0000000..c49aae6
--- /dev/null
+++ b/mac/tclMacLibrary.c
@@ -0,0 +1,241 @@
+/*
+ * tclMacLibrary.c --
+ *
+ * This file should be included in Tcl extensions that want to
+ * automatically oepn their resource forks when the code is linked.
+ * These routines should not be exported but should be compiled
+ * locally by each fragment. Many thanks to Jay Lieske
+ * <lieske@princeton.edu> who provide an initial version of this
+ * file.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacLibrary.c 1.6 97/11/20 19:29:42
+ */
+
+/*
+ * Here is another place that we are using the old routine names...
+ */
+
+#define OLDROUTINENAMES 1
+
+#include <CodeFragments.h>
+#include <Errors.h>
+#include <Resources.h>
+#include <Strings.h>
+#include "tclMacInt.h"
+
+/*
+ * These function are not currently defined in any header file. The
+ * only place they should be used is in the Initialization and
+ * Termination entry points for a code fragment. The prototypes
+ * are included here to avoid compile errors.
+ */
+
+OSErr TclMacInitializeFragment _ANSI_ARGS_((
+ struct CFragInitBlock* initBlkPtr));
+void TclMacTerminateFragment _ANSI_ARGS_((void));
+
+/*
+ * Static functions in this file.
+ */
+
+static OSErr OpenLibraryResource _ANSI_ARGS_((
+ struct CFragInitBlock* initBlkPtr));
+static void CloseLibraryResource _ANSI_ARGS_((void));
+
+/*
+ * The refnum of the opened resource fork.
+ */
+static short ourResFile = kResFileNotOpened;
+
+/*
+ * This is the resource token for the our resource file.
+ * It stores the name we registered with the resource facility.
+ * We only need to use this if we are actually registering ourselves.
+ */
+
+#ifdef TCL_REGISTER_LIBRARY
+static Tcl_Obj *ourResToken;
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacInitializeFragment --
+ *
+ * Called by MacOS CFM when the shared library is loaded. All this
+ * function really does is give Tcl a chance to open and register
+ * the resource fork of the library.
+ *
+ * Results:
+ * MacOS error code if loading should be canceled.
+ *
+ * Side effects:
+ * Opens the resource fork of the shared library file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+TclMacInitializeFragment(
+ struct CFragInitBlock* initBlkPtr) /* Pointer to our library. */
+{
+ OSErr err = noErr;
+
+#ifdef __MWERKS__
+ {
+ extern OSErr __initialize( CFragInitBlock* initBlkPtr);
+ err = __initialize((CFragInitBlock *) initBlkPtr);
+ }
+#endif
+ if (err == noErr)
+ err = OpenLibraryResource( initBlkPtr);
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacTerminateFragment --
+ *
+ * Called by MacOS CFM when the shared library is unloaded.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The resource fork of the code fragment is closed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclMacTerminateFragment()
+{
+ CloseLibraryResource();
+
+#ifdef __MWERKS__
+ {
+ extern void __terminate(void);
+ __terminate();
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OpenLibraryResource --
+ *
+ * This routine can be called by a MacOS fragment's initialiation
+ * function to open the resource fork of the file.
+ * Call it with the same data passed to the initialization function.
+ * If the fragment loading should fail if the resource fork can't
+ * be opened, then the initialization function can pass on this
+ * return value.
+ *
+ * If you #define TCL_REGISTER_RESOURCE before compiling this resource,
+ * then your library will register its open resource fork with the
+ * resource command.
+ *
+ * Results:
+ * It returns noErr on success and a MacOS error code on failure.
+ *
+ * Side effects:
+ * The resource fork of the code fragment is opened read-only and
+ * is installed at the head of the resource chain.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+OpenLibraryResource(
+ struct CFragInitBlock* initBlkPtr)
+{
+ /*
+ * The 3.0 version of the Universal headers changed CFragInitBlock
+ * to an opaque pointer type. CFragSystem7InitBlock is now the
+ * real pointer.
+ */
+
+#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
+ struct CFragInitBlock *realInitBlkPtr = initBlkPtr;
+#else
+ CFragSystem7InitBlock *realInitBlkPtr = (CFragSystem7InitBlock *) initBlkPtr;
+#endif
+ FSSpec* fileSpec = NULL;
+ OSErr err = noErr;
+
+
+ if (realInitBlkPtr->fragLocator.where == kOnDiskFlat) {
+ fileSpec = realInitBlkPtr->fragLocator.u.onDisk.fileSpec;
+ } else if (realInitBlkPtr->fragLocator.where == kOnDiskSegmented) {
+ fileSpec = realInitBlkPtr->fragLocator.u.inSegs.fileSpec;
+ } else {
+ err = resFNotFound;
+ }
+
+ /*
+ * Open the resource fork for this library in read-only mode.
+ * This will make it the current res file, ahead of the
+ * application's own resources.
+ */
+
+ if (fileSpec != NULL) {
+ ourResFile = FSpOpenResFile(fileSpec, fsRdPerm);
+ if (ourResFile == kResFileNotOpened) {
+ err = ResError();
+ } else {
+#ifdef TCL_REGISTER_LIBRARY
+ ourResToken = Tcl_NewObj();
+ Tcl_IncrRefCount(ourResToken);
+ p2cstr(realInitBlkPtr->libName);
+ Tcl_SetStringObj(ourResToken, (char *) realInitBlkPtr->libName, -1);
+ c2pstr((char *) realInitBlkPtr->libName);
+ TclMacRegisterResourceFork(ourResFile, ourResToken,
+ TCL_RESOURCE_DONT_CLOSE);
+#endif
+ SetResFileAttrs(ourResFile, mapReadOnly);
+ }
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CloseLibraryResource --
+ *
+ * This routine should be called by a MacOS fragment's termination
+ * function to close the resource fork of the file
+ * that was opened with OpenLibraryResource.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The resource fork of the code fragment is closed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CloseLibraryResource()
+{
+ if (ourResFile != kResFileNotOpened) {
+#ifdef TCL_REGISTER_LIBRARY
+ int length;
+ TclMacUnRegisterResourceFork(
+ Tcl_GetStringFromObj(ourResToken, &length),
+ NULL);
+ Tcl_DecrRefCount(ourResToken);
+#endif
+ CloseResFile(ourResFile);
+ ourResFile = kResFileNotOpened;
+ }
+}
diff --git a/mac/tclMacLibrary.r b/mac/tclMacLibrary.r
new file mode 100644
index 0000000..b83118d
--- /dev/null
+++ b/mac/tclMacLibrary.r
@@ -0,0 +1,223 @@
+/*
+ * tclMacLibrary.r --
+ *
+ * This file creates resources used by the Tcl shared library.
+ * Many thanks go to "Jay Lieske, Jr." <lieske@princeton.edu> who
+ * wrote the initial version of this file.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacLibrary.r 1.5 97/09/23 12:53:28
+ */
+
+#include <Types.r>
+#include <SysTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include "tcl.h"
+
+#if (TCL_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TCL_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TCL_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TCL_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TCL_MINOR_VERSION * 16) + TCL_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TCL_MINOR_VERSION * 16
+#endif
+
+resource 'vers' (1) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ TCL_PATCH_LEVEL ", by Ray Johnson © Sun Microsystems"
+};
+
+resource 'vers' (2) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ "Tcl Library " TCL_PATCH_LEVEL " © 1996"
+};
+
+/*
+ * Currently the creator for all Tcl/Tk libraries and extensions
+ * should be 'TclL'. This will allow those extension and libraries
+ * to use the common icon for Tcl extensions. However, this signature
+ * still needs to be approved by the signature police at Apple and may
+ * change.
+ */
+#define TCL_CREATOR 'TclL'
+#define TCL_LIBRARY_RESOURCES 2000
+
+/*
+ * The 'BNDL' resource is the primary link between a file's
+ * creator/type and its icon. This resource acts for all Tcl shared
+ * libraries; other libraries will not need one and ought to use
+ * custom icons rather than new file types for a different appearance.
+ */
+
+resource 'BNDL' (TCL_LIBRARY_RESOURCES, "Tcl bundle", purgeable)
+{
+ TCL_CREATOR,
+ 0,
+ { /* array TypeArray: 2 elements */
+ /* [1] */
+ 'FREF',
+ { /* array IDArray: 1 elements */
+ /* [1] */
+ 0, TCL_LIBRARY_RESOURCES
+ },
+ /* [2] */
+ 'ICN#',
+ { /* array IDArray: 1 elements */
+ /* [1] */
+ 0, TCL_LIBRARY_RESOURCES
+ }
+ }
+};
+
+resource 'FREF' (TCL_LIBRARY_RESOURCES, purgeable)
+{
+ 'shlb', 0, ""
+};
+
+type TCL_CREATOR as 'STR ';
+resource TCL_CREATOR (0, purgeable) {
+ "Tcl Library " TCL_PATCH_LEVEL " © 1996"
+};
+
+/*
+ * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open
+ * to affect the text the Finder displays in the "kind" column and
+ * file info dialog. This information will be applied to all files
+ * with the listed creator and type.
+ */
+
+resource 'kind' (TCL_LIBRARY_RESOURCES, "Tcl kind", purgeable) {
+ TCL_CREATOR,
+ 0, /* region = USA */
+ {
+ 'shlb', "Tcl Library"
+ }
+};
+
+
+/*
+ * The -16397 string will be displayed by Finder when a user
+ * tries to open the shared library. The string should
+ * give the user a little detail about the library's capabilities
+ * and enough information to install the library in the correct location.
+ * A similar string should be placed in all shared libraries.
+ */
+resource 'STR ' (-16397, purgeable) {
+ "Tcl Library\n\n"
+ "This is the core library needed to run Tool Command Language programs. "
+ "To work properly, it should be placed in the ÔTool Command LanguageÕ folder "
+ "within the Extensions folder."
+};
+
+/*
+ * The mechanisim below loads Tcl source into the resource fork of the
+ * application. The example below creates a TEXT resource named
+ * "Init" from the file "init.tcl". This allows applications to use
+ * Tcl to define the behavior of the application without having to
+ * require some predetermined file structure - all needed Tcl "files"
+ * are located within the application. To source a file for the
+ * resource fork the source command has been modified to support
+ * sourcing from resources. In the below case "source -rsrc {Init}"
+ * will load the TEXT resource named "Init".
+ */
+
+read 'TEXT' (TCL_LIBRARY_RESOURCES, "Init", purgeable) "::library:init.tcl";
+read 'TEXT' (TCL_LIBRARY_RESOURCES + 1, "History", purgeable) "::library:history.tcl";
+read 'TEXT' (TCL_LIBRARY_RESOURCES + 2, "Word", purgeable,preload) "::library:word.tcl";
+
+/*
+ * The following are icons for the shared library.
+ */
+
+data 'icl4' (2000, "Tcl Shared Library", purgeable) {
+ $"0FFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+ $"F000 0000 0000 0000 0000 0000 000C F000"
+ $"F0CC CFFF CCCC CCC6 66CC CCCC CCCC F000"
+ $"F0CC CFFF FFFF FF66 F6CC CCCC CCCC F000"
+ $"F0CC CFFF 2000 0D66 6CCC CCCC CCCC F000"
+ $"F0CC CFFF 0202 056F 6E5C CCCC CCCC F000"
+ $"F0CC CFFF 2020 C666 F66F CCCC CCCC F000"
+ $"F0CC CFFF 0200 B66F 666B FCCC CCCC F000"
+ $"F0FC CFFF B020 55F6 6F52 BFCC CCCC F000"
+ $"FF0F 0CCC FB02 5665 66D0 2FCC CCCC F0F0"
+ $"F00F 0CCC CFB0 BF55 F6CF FFCC CCCC FFCF"
+ $"000F 0CCC CCFB 06C9 66CC CCCC CCCC F0CF"
+ $"000F 0CCC CCCF 56C6 6CCC CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 6FC6 FCCC CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 65C5 65CC CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 55D6 57CC CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 65CF 6CCC CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 5AC6 6CFF CCCC CCCC CCCF"
+ $"000F 0CCC CCCC 65C5 6CF0 FCCC CCCC CCCF"
+ $"000F 0CCC CCCC CECF CCF0 0FCC CCCC CCCF"
+ $"000F 0CCC CCCC C5C6 CCCF 20FC CCCC FCCF"
+ $"F00F 0CCC CCCF FFD5 CCCC F20F CCCC FFCF"
+ $"FF0F 0CCC CCCF 20CF CCCC F020 FCCC F0F0"
+ $"F0F0 CCCC CCCF B2C2 FFFF 0002 0FFC F000"
+ $"F00C CCCC CCCC FBC0 2000 0020 2FFC F000"
+ $"F0CC CCCC CCCC CFCB 0202 0202 0FFC F000"
+ $"F0CC CCCC CCCC CCCF B020 2020 2FFC F000"
+ $"F0CC CCCC CCCC CCDC FBBB BBBB BFFC F000"
+ $"F0CC CCCC CCCC CCCC CFFF FFFF FFFC F000"
+ $"F0CC CCCC CCCC CCCC CCCC CCCC CFFC F000"
+ $"FCCC CCCC CCCC CCCC CCCC CCCC CCCC F000"
+ $"0FFF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+};
+
+data 'ICN#' (2000, "Tcl Shared Library", purgeable) {
+ $"7FFF FFF0 8000 0008 8701 C008 87FF C008"
+ $"8703 8008 8707 E008 8707 F008 870F F808"
+ $"A78F EC08 D0CF C40A 906F DC0D 1035 C009"
+ $"101D 8001 100D 8001 100D C001 100D C001"
+ $"100D 8001 100D B001 100D A801 1005 2401"
+ $"1005 1209 901D 090D D011 088A A018 F068"
+ $"800C 0068 8005 0068 8001 8068 8000 FFE8"
+ $"8000 7FE8 8000 0068 8000 0008 7FFF FFF0"
+ $"7FFF FFF0 FFFF FFF8 FFFF FFF8 FFFF FFF8"
+ $"FFFF FFF8 FFFF FFF8 FFFF FFF8 FFFF FFF8"
+ $"FFFF FFF8 DFFF FFFA 9FFF FFFF 1FFF FFFF"
+ $"1FFF FFFF 1FFF FFFF 1FFF FFFF 1FFF FFFF"
+ $"1FFF FFFF 1FFF FFFF 1FFF FFFF 1FFF FFFF"
+ $"1FFF FFFF 9FFF FFFF DFFF FFFA FFFF FFF8"
+ $"FFFF FFF8 FFFF FFF8 FFFF FFF8 FFFF FFF8"
+ $"FFFF FFF8 FFFF FFF8 FFFF FFF8 7FFF FFF0"
+};
+
+data 'ics#' (2000, "Tcl Shared Library", purgeable) {
+ $"FFFE B582 BB82 B3C2 BFA2 43C3 4381 4381"
+ $"4381 4763 4392 856E 838E 81AE 811E FFFE"
+ $"FFFE FFFE FFFE FFFE FFFE FFFF 7FFF 7FFF"
+ $"7FFF 7FFF 7FFF FFFE FFFE FFFE FFFE FFFE"
+};
+
+data 'ics4' (2000, "Tcl Shared Library", purgeable) {
+ $"FFFF FFFF FFFF FFF0 FCFF DED5 6CCC CCF0"
+ $"FCFF C0D6 ECCC CCF0 FCFF 2056 65DC CCF0"
+ $"FDFE D256 6DAC CCFF FFCC DDDE 5DDC CCEF"
+ $"0FCC CD67 5CCC CCCF 0FCC CC5D 6CCC CCCF"
+ $"0FCC CC5D 5CCC CCCF 0FCC CCD5 5CCC CCCF"
+ $"FFCC CFFD CCFF CCFF FCCC CF2D DF20 FCFC"
+ $"FCCC CCFD D202 FEF0 FCCC CC0D 2020 FEF0"
+ $"FCCC CCCD FBBB FEF0 FFFF FFFF FFFF FFE0"
+};
+
diff --git a/mac/tclMacLoad.c b/mac/tclMacLoad.c
new file mode 100644
index 0000000..060a734
--- /dev/null
+++ b/mac/tclMacLoad.c
@@ -0,0 +1,245 @@
+/*
+ * tclMacLoad.c --
+ *
+ * This procedure provides a version of the TclLoadFile for use
+ * on the Macintosh. This procedure will only work with systems
+ * that use the Code Fragment Manager.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacLoad.c 1.20 97/11/20 18:39:20
+ */
+
+#include <CodeFragments.h>
+#include <Errors.h>
+#include <Resources.h>
+#include <Strings.h>
+#include <FSpCompat.h>
+
+/*
+ * Seems that the 3.0.1 Universal headers leave this define out. So we
+ * define it here...
+ */
+
+#ifndef fragNoErr
+ #define fragNoErr noErr
+#endif
+
+#include "tclPort.h"
+#include "tclInt.h"
+#include "tclMacInt.h"
+
+#if GENERATINGPOWERPC
+ #define OUR_ARCH_TYPE kPowerPCCFragArch
+#else
+ #define OUR_ARCH_TYPE kMotorola68KCFragArch
+#endif
+
+/*
+ * The following data structure defines the structure of a code fragment
+ * resource. We can cast the resource to be of this type to access
+ * any fields we need to see.
+ */
+struct CfrgHeader {
+ long res1;
+ long res2;
+ long version;
+ long res3;
+ long res4;
+ long filler1;
+ long filler2;
+ long itemCount;
+ char arrayStart; /* Array of externalItems begins here. */
+};
+typedef struct CfrgHeader CfrgHeader, *CfrgHeaderPtr, **CfrgHeaderPtrHand;
+
+/*
+ * The below structure defines a cfrag item within the cfrag resource.
+ */
+struct CfrgItem {
+ OSType archType;
+ long updateLevel;
+ long currVersion;
+ long oldDefVersion;
+ long appStackSize;
+ short appSubFolder;
+ char usage;
+ char location;
+ long codeOffset;
+ long codeLength;
+ long res1;
+ long res2;
+ short itemSize;
+ Str255 name; /* This is actually variable sized. */
+};
+typedef struct CfrgItem CfrgItem;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclLoadFile --
+ *
+ * This procedure is called to carry out dynamic loading of binary
+ * code for the Macintosh. This implementation is based on the
+ * Code Fragment Manager & will not work on other systems.
+ *
+ * Results:
+ * The result is TCL_ERROR, and an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * New binary code is loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclLoadFile(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ char *fileName, /* Name of the file containing the desired
+ * code. */
+ char *sym1, char *sym2, /* Names of two procedures to look up in
+ * the file's symbol table. */
+ Tcl_PackageInitProc **proc1Ptr,
+ Tcl_PackageInitProc **proc2Ptr)
+ /* Where to return the addresses corresponding
+ * to sym1 and sym2. */
+{
+ CFragConnectionID connID;
+ Ptr dummy;
+ OSErr err;
+ CFragSymbolClass symClass;
+ FSSpec fileSpec;
+ short fragFileRef, saveFileRef;
+ Handle fragResource;
+ UInt32 offset = 0;
+ UInt32 length = kCFragGoesToEOF;
+ char packageName[255];
+ Str255 errName;
+
+ /*
+ * First thing we must do is infer the package name from the sym1
+ * variable. This is kind of dumb since the caller actually knows
+ * this value, it just doesn't give it to us.
+ */
+ strcpy(packageName, sym1);
+ *packageName = (char) tolower(*packageName);
+ packageName[strlen(packageName) - 5] = NULL;
+
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+ if (err != noErr) {
+ interp->result = "could not locate shared library";
+ return TCL_ERROR;
+ }
+
+ /*
+ * See if this fragment has a 'cfrg' resource. It will tell us were
+ * to look for the fragment in the file. If it doesn't exist we will
+ * assume we have a ppc frag using the whole data fork. If it does
+ * exist we find the frag that matches the one we are looking for and
+ * get the offset and size from the resource.
+ */
+ saveFileRef = CurResFile();
+ SetResLoad(false);
+ fragFileRef = FSpOpenResFile(&fileSpec, fsRdPerm);
+ SetResLoad(true);
+ if (fragFileRef != -1) {
+ UseResFile(fragFileRef);
+ fragResource = Get1Resource(kCFragResourceType, kCFragResourceID);
+ HLock(fragResource);
+ if (ResError() == noErr) {
+ CfrgItem* srcItem;
+ long itemCount, index;
+ Ptr itemStart;
+
+ itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount;
+ itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart;
+ for (index = 0; index < itemCount;
+ index++, itemStart += srcItem->itemSize) {
+ srcItem = (CfrgItem*)itemStart;
+ if (srcItem->archType != OUR_ARCH_TYPE) continue;
+ if (!strncasecmp(packageName, (char *) srcItem->name + 1,
+ srcItem->name[0])) {
+ offset = srcItem->codeOffset;
+ length = srcItem->codeLength;
+ }
+ }
+ }
+ /*
+ * Close the resource file. If the extension wants to reopen the
+ * resource fork it should use the tclMacLibrary.c file during it's
+ * construction.
+ */
+ HUnlock(fragResource);
+ ReleaseResource(fragResource);
+ CloseResFile(fragFileRef);
+ UseResFile(saveFileRef);
+ }
+
+ /*
+ * Now we can attempt to load the fragement using the offset & length
+ * obtained from the resource. We don't worry about the main entry point
+ * as we are going to search for specific entry points passed to us.
+ */
+
+ c2pstr(packageName);
+ err = GetDiskFragment(&fileSpec, offset, length, (StringPtr) packageName,
+ kLoadCFrag, &connID, &dummy, errName);
+ if (err != fragNoErr) {
+ p2cstr(errName);
+ Tcl_AppendResult(interp, "couldn't load file \"", fileName,
+ "\": ", errName, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c2pstr(sym1);
+ err = FindSymbol(connID, (StringPtr) sym1, (Ptr *) proc1Ptr, &symClass);
+ p2cstr((StringPtr) sym1);
+ if (err != fragNoErr || symClass == kDataCFragSymbol) {
+ interp->result =
+ "could not find Initialization routine in library";
+ return TCL_ERROR;
+ }
+
+ c2pstr(sym2);
+ err = FindSymbol(connID, (StringPtr) sym2, (Ptr *) proc2Ptr, &symClass);
+ p2cstr((StringPtr) sym2);
+ if (err != fragNoErr || symClass == kDataCFragSymbol) {
+ *proc2Ptr = NULL;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package
+ * name, this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a
+ * package name; generic code will then try to guess the package
+ * from the file name. A return value of 1 would have meant that
+ * we figured out the package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append
+ * package name to this if possible. */
+{
+ return 0;
+}
diff --git a/mac/tclMacMSLPrefix.h b/mac/tclMacMSLPrefix.h
new file mode 100644
index 0000000..ce569da
--- /dev/null
+++ b/mac/tclMacMSLPrefix.h
@@ -0,0 +1,24 @@
+/*
+ * tclMacMSLPrefix.h --
+ *
+ * A wrapper for the MSL ansi_prefix.mac.h file. This just turns export on
+ * after including the MSL prefix file, so we can export symbols from the MSL
+ * and through the Tcl shared libraries
+ *
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMac.h 1.2 97/03/18 10:58:49
+ */
+
+#include <ansi_prefix.mac.h>
+/*
+ * "export" is a MetroWerks specific pragma. It flags the linker that
+ * any symbols that are defined when this pragma is on will be exported
+ * to shared libraries that link with this library.
+ */
+
+#pragma export on
diff --git a/mac/tclMacMath.h b/mac/tclMacMath.h
new file mode 100644
index 0000000..7ec3257
--- /dev/null
+++ b/mac/tclMacMath.h
@@ -0,0 +1,145 @@
+/*
+ * tclMacMath.h --
+ *
+ * This file is necessary because of Metrowerks CodeWarrior Pro 1
+ * on the Macintosh. With 8-byte doubles turned on, the definitions of
+ * sin, cos, acos, etc., are screwed up. They are fine as long as
+ * they are used as function calls, but if the function pointers
+ * are passed around and used, they will crash hard on the 68K.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacMath.h 1.2 97/07/28 11:04:02
+ */
+
+#ifndef _TCLMACMATH
+#define _TCLMACMATH
+
+#include <math.h>
+
+#if defined(__MWERKS__) && !defined(__POWERPC__)
+#if __option(IEEEdoubles)
+
+# ifdef cos
+# undef cos
+# define cos cosd
+# endif
+
+# ifdef sin
+# undef sin
+# define sin sind
+# endif
+
+# ifdef tan
+# undef tan
+# define tan tand
+# endif
+
+# ifdef acos
+# undef acos
+# define acos acosd
+# endif
+
+# ifdef asin
+# undef asin
+# define asin asind
+# endif
+
+# ifdef atan
+# undef atan
+# define atan atand
+# endif
+
+# ifdef cosh
+# undef cosh
+# define cosh coshd
+# endif
+
+# ifdef sinh
+# undef sinh
+# define sinh sinhd
+# endif
+
+# ifdef tanh
+# undef tanh
+# define tanh tanhd
+# endif
+
+# ifdef exp
+# undef exp
+# define exp expd
+# endif
+
+# ifdef ldexp
+# undef ldexp
+# define ldexp ldexpd
+# endif
+
+# ifdef log
+# undef log
+# define log logd
+# endif
+
+# ifdef log10
+# undef log10
+# define log10 log10d
+# endif
+
+# ifdef fabs
+# undef fabs
+# define fabs fabsd
+# endif
+
+# ifdef sqrt
+# undef sqrt
+# define sqrt sqrtd
+# endif
+
+# ifdef fmod
+# undef fmod
+# define fmod fmodd
+# endif
+
+# ifdef atan2
+# undef atan2
+# define atan2 atan2d
+# endif
+
+# ifdef frexp
+# undef frexp
+# define frexp frexpd
+# endif
+
+# ifdef modf
+# undef modf
+# define modf modfd
+# endif
+
+# ifdef pow
+# undef pow
+# define pow powd
+# endif
+
+# ifdef ceil
+# undef ceil
+# define ceil ceild
+# endif
+
+# ifdef floor
+# undef floor
+# define floor floord
+# endif
+#endif
+#endif
+
+#if (defined(THINK_C) || defined(__MWERKS__))
+#pragma export on
+double hypotd(double x, double y);
+#define hypot hypotd
+#pragma export reset
+#endif
+
+#endif /* _TCLMACMATH */
diff --git a/mac/tclMacNotify.c b/mac/tclMacNotify.c
new file mode 100644
index 0000000..1537f0c
--- /dev/null
+++ b/mac/tclMacNotify.c
@@ -0,0 +1,416 @@
+/*
+ * tclMacNotify.c --
+ *
+ * This file contains Macintosh-specific procedures for the notifier,
+ * which is the lowest-level part of the Tcl event loop. This file
+ * works together with ../generic/tclNotify.c.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacNotify.c 1.36 97/05/07 19:09:29
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMac.h"
+#include "tclMacInt.h"
+#include <signal.h>
+#include <Events.h>
+#include <LowMem.h>
+#include <Processes.h>
+#include <Timer.h>
+
+
+/*
+ * This is necessary to work around a bug in Apple's Universal header files
+ * for the CFM68K libraries.
+ */
+
+#ifdef __CFM68K__
+#undef GetEventQueue
+extern pascal QHdrPtr GetEventQueue(void)
+ THREEWORDINLINE(0x2EBC, 0x0000, 0x014A);
+#pragma import list GetEventQueue
+#define GetEvQHdr() GetEventQueue()
+#endif
+
+/*
+ * The follwing static indicates whether this module has been initialized.
+ */
+
+static int initialized = 0;
+
+/*
+ * The following structure contains the state information for the
+ * notifier module.
+ */
+
+static struct {
+ int timerActive; /* 1 if timer is running. */
+ Tcl_Time timer; /* Time when next timer event is expected. */
+ int flags; /* OR'ed set of flags defined below. */
+ Point lastMousePosition; /* Last known mouse location. */
+ RgnHandle utilityRgn; /* Region used as the mouse region for
+ * WaitNextEvent and the update region when
+ * checking for events. */
+ Tcl_MacConvertEventPtr eventProcPtr;
+ /* This pointer holds the address of the
+ * function that will handle all incoming
+ * Macintosh events. */
+} notifier;
+
+/*
+ * The following defines are used in the flags field of the notifier struct.
+ */
+
+#define NOTIFY_IDLE (1<<1) /* Tcl_ServiceIdle should be called. */
+#define NOTIFY_TIMER (1<<2) /* Tcl_ServiceTimer should be called. */
+
+/*
+ * Prototypes for procedures that are referenced only in this file:
+ */
+
+static int HandleMacEvents _ANSI_ARGS_((void));
+static void InitNotifier _ANSI_ARGS_((void));
+static void NotifierExitHandler _ANSI_ARGS_((
+ ClientData clientData));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitNotifier --
+ *
+ * Initializes the notifier structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new exit handler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitNotifier(void)
+{
+ initialized = 1;
+ memset(&notifier, 0, sizeof(notifier));
+ Tcl_CreateExitHandler(NotifierExitHandler, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NotifierExitHandler --
+ *
+ * This function is called to cleanup the notifier state before
+ * Tcl is unloaded.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NotifierExitHandler(
+ ClientData clientData) /* Not used. */
+{
+ initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HandleMacEvents --
+ *
+ * This function checks for events from the Macintosh event queue.
+ *
+ * Results:
+ * Returns 1 if event found, 0 otherwise.
+ *
+ * Side effects:
+ * Pulls events off of the Mac event queue and then calls
+ * convertEventProc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HandleMacEvents(void)
+{
+ EventRecord theEvent;
+ int eventFound = 0, needsUpdate = 0;
+ Point currentMouse;
+ WindowRef windowRef;
+ Rect mouseRect;
+
+ /*
+ * Check for mouse moved events. These events aren't placed on the
+ * system event queue unless we call WaitNextEvent.
+ */
+
+ GetGlobalMouse(&currentMouse);
+ if ((notifier.eventProcPtr != NULL) &&
+ !EqualPt(currentMouse, notifier.lastMousePosition)) {
+ notifier.lastMousePosition = currentMouse;
+ theEvent.what = nullEvent;
+ if ((*notifier.eventProcPtr)(&theEvent) == true) {
+ eventFound = 1;
+ }
+ }
+
+ /*
+ * Check for update events. Since update events aren't generated
+ * until we call GetNextEvent, we may need to force a call to
+ * GetNextEvent, even if the queue is empty.
+ */
+
+ for (windowRef = FrontWindow(); windowRef != NULL;
+ windowRef = GetNextWindow(windowRef)) {
+ GetWindowUpdateRgn(windowRef, notifier.utilityRgn);
+ if (!EmptyRgn(notifier.utilityRgn)) {
+ needsUpdate = 1;
+ break;
+ }
+ }
+
+ /*
+ * Process events from the OS event queue.
+ */
+
+ while (needsUpdate || (GetEvQHdr()->qHead != NULL)) {
+ GetGlobalMouse(&currentMouse);
+ SetRect(&mouseRect, currentMouse.h, currentMouse.v,
+ currentMouse.h + 1, currentMouse.v + 1);
+ RectRgn(notifier.utilityRgn, &mouseRect);
+
+ WaitNextEvent(everyEvent, &theEvent, 5, notifier.utilityRgn);
+ needsUpdate = 0;
+ if ((notifier.eventProcPtr != NULL)
+ && ((*notifier.eventProcPtr)(&theEvent) == true)) {
+ eventFound = 1;
+ }
+ }
+
+ return eventFound;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetTimer --
+ *
+ * This procedure sets the current notifier timer value. The
+ * notifier will ensure that Tcl_ServiceAll() is called after
+ * the specified interval, even if no events have occurred.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Replaces any previous timer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetTimer(
+ Tcl_Time *timePtr) /* New value for interval timer. */
+{
+ if (!timePtr) {
+ notifier.timerActive = 0;
+ } else {
+ /*
+ * Compute when the timer should fire.
+ */
+
+ TclpGetTime(&notifier.timer);
+ notifier.timer.sec += timePtr->sec;
+ notifier.timer.usec += timePtr->usec;
+ if (notifier.timer.usec >= 1000000) {
+ notifier.timer.usec -= 1000000;
+ notifier.timer.sec += 1;
+ }
+ notifier.timerActive = 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitForEvent --
+ *
+ * This function is called by Tcl_DoOneEvent to wait for new
+ * events on the message queue. If the block time is 0, then
+ * Tcl_WaitForEvent just polls the event queue without blocking.
+ *
+ * Results:
+ * Always returns 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_WaitForEvent(
+ Tcl_Time *timePtr) /* Maximum block time. */
+{
+ int found;
+ EventRecord macEvent;
+ long sleepTime = 5;
+ long ms;
+ Point currentMouse;
+ void * timerToken;
+ Rect mouseRect;
+
+ /*
+ * Compute the next timeout value.
+ */
+
+ if (!timePtr) {
+ ms = INT_MAX;
+ } else {
+ ms = (timePtr->sec * 1000) + (timePtr->usec / 1000);
+ }
+ timerToken = TclMacStartTimer((long) ms);
+
+ /*
+ * Poll the Mac event sources. This loop repeats until something
+ * happens: a timeout, a socket event, mouse motion, or some other
+ * window event. Note that we don't call WaitNextEvent if another
+ * event is found to avoid context switches. This effectively gives
+ * events coming in via WaitNextEvent a slightly lower priority.
+ */
+
+ found = 0;
+ if (notifier.utilityRgn == NULL) {
+ notifier.utilityRgn = NewRgn();
+ }
+
+ while (!found) {
+ /*
+ * Check for generated and queued events.
+ */
+
+ if (HandleMacEvents()) {
+ found = 1;
+ }
+
+ /*
+ * Check for time out.
+ */
+
+ if (!found && TclMacTimerExpired(timerToken)) {
+ found = 1;
+ }
+
+ /*
+ * Check for window events. We may receive a NULL event for
+ * various reasons. 1) the timer has expired, 2) a mouse moved
+ * event is occuring or 3) the os is giving us time for idle
+ * events. Note that we aren't sharing the processor very
+ * well here. We really ought to do a better job of calling
+ * WaitNextEvent for time slicing purposes.
+ */
+
+ if (!found) {
+ /*
+ * Set up mouse region so we will wake if the mouse is moved.
+ * We do this by defining the smallest possible region around
+ * the current mouse position.
+ */
+
+ GetGlobalMouse(&currentMouse);
+ SetRect(&mouseRect, currentMouse.h, currentMouse.v,
+ currentMouse.h + 1, currentMouse.v + 1);
+ RectRgn(notifier.utilityRgn, &mouseRect);
+
+ WaitNextEvent(everyEvent, &macEvent, sleepTime,
+ notifier.utilityRgn);
+
+ if (notifier.eventProcPtr != NULL) {
+ if ((*notifier.eventProcPtr)(&macEvent) == true) {
+ found = 1;
+ }
+ }
+ }
+ }
+ TclMacRemoveTimer(timerToken);
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Sleep --
+ *
+ * Delay execution for the specified number of milliseconds. This
+ * is not a very good call to make. It will block the system -
+ * you will not even be able to switch applications.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_Sleep(
+ int ms) /* Number of milliseconds to sleep. */
+{
+ EventRecord dummy;
+ void *timerToken;
+
+ if (ms <= 0) {
+ return;
+ }
+
+ timerToken = TclMacStartTimer((long) ms);
+ while (1) {
+ WaitNextEvent(0, &dummy, (ms / 16.66) + 1, NULL);
+
+ if (TclMacTimerExpired(timerToken)) {
+ break;
+ }
+ }
+ TclMacRemoveTimer(timerToken);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MacSetEventProc --
+ *
+ * This function sets the event handling procedure for the
+ * application. This function will be passed all incoming Mac
+ * events. This function usually controls the console or some
+ * other entity like Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the event handling function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_MacSetEventProc(
+ Tcl_MacConvertEventPtr procPtr)
+{
+ notifier.eventProcPtr = procPtr;
+}
diff --git a/mac/tclMacOSA.c b/mac/tclMacOSA.c
new file mode 100644
index 0000000..110cfe2
--- /dev/null
+++ b/mac/tclMacOSA.c
@@ -0,0 +1,2937 @@
+/*
+ * tclMacOSA.c --
+ *
+ * This contains the initialization routines, and the implementation of
+ * the OSA and Component commands. These commands allow you to connect
+ * with the AppleScript or any other OSA component to compile and execute
+ * scripts.
+ *
+ * Copyright (c) 1996 Lucent Technologies and Jim Ingham
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "License Terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacOSA.c 1.7 97/06/18 14:29:58
+ */
+
+#define MAC_TCL
+
+#include <Aliases.h>
+#include <string.h>
+#include <AppleEvents.h>
+#include <AppleScript.h>
+#include <OSA.h>
+#include <OSAGeneric.h>
+#include <Script.h>
+
+#include <FullPath.h>
+#include <components.h>
+
+#include <resources.h>
+#include <FSpCompat.h>
+/*
+ * The following two Includes are from the More Files package.
+ */
+#include <MoreFiles.h>
+#include <FullPath.h>
+
+#include "tcl.h"
+#include "tclInt.h"
+
+/*
+ * I need this only for the call to FspGetFullPath,
+ * I'm really not poking my nose where it does not belong!
+ */
+#include "tclMacInt.h"
+
+/*
+ * Data structures used by the OSA code.
+ */
+typedef struct tclOSAScript {
+ OSAID scriptID;
+ OSType languageID;
+ long modeFlags;
+} tclOSAScript;
+
+typedef struct tclOSAContext {
+ OSAID contextID;
+} tclOSAContext;
+
+typedef struct tclOSAComponent {
+ char *theName;
+ ComponentInstance theComponent; /* The OSA Component represented */
+ long componentFlags;
+ OSType languageID;
+ char *languageName;
+ Tcl_HashTable contextTable; /* Hash Table linking the context names & ID's */
+ Tcl_HashTable scriptTable;
+ Tcl_Interp *theInterp;
+ OSAActiveUPP defActiveProc;
+ long defRefCon;
+} tclOSAComponent;
+
+/*
+ * Prototypes for static procedures.
+ */
+
+static pascal OSErr TclOSAActiveProc _ANSI_ARGS_((long refCon));
+static int TclOSACompileCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSADecompileCmd _ANSI_ARGS_((Tcl_Interp * Interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSADeleteCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSAExecuteCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSAInfoCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSALoadCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSARunCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc,
+ char **argv));
+static int tclOSAStoreCmd _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent, int argc, char
+ **argv));
+static void GetRawDataFromDescriptor _ANSI_ARGS_((AEDesc *theDesc,
+ Ptr destPtr, Size destMaxSize, Size *actSize));
+static OSErr GetCStringFromDescriptor _ANSI_ARGS_((
+ AEDesc *sourceDesc, char *resultStr,
+ Size resultMaxSize,Size *resultSize));
+static int Tcl_OSAComponentCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+static void getSortedHashKeys _ANSI_ARGS_((Tcl_HashTable *theTable,
+ char *pattern, Tcl_DString *theResult));
+static int ASCIICompareProc _ANSI_ARGS_((const void *first,
+ const void *second));
+static int Tcl_OSACmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+static void tclOSAClose _ANSI_ARGS_((ClientData clientData));
+static void tclOSACloseAll _ANSI_ARGS_((ClientData clientData));
+static tclOSAComponent *tclOSAMakeNewComponent _ANSI_ARGS_((Tcl_Interp *interp,
+ char *cmdName, char *languageName,
+ OSType scriptSubtype, long componentFlags));
+static int prepareScriptData _ANSI_ARGS_((int argc, char **argv,
+ Tcl_DString *scrptData ,AEDesc *scrptDesc));
+static void tclOSAResultFromID _ANSI_ARGS_((Tcl_Interp *interp,
+ ComponentInstance theComponent, OSAID resultID));
+static void tclOSAASError _ANSI_ARGS_((Tcl_Interp * interp,
+ ComponentInstance theComponent, char *scriptSource));
+static int tclOSAGetContextID _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *contextName, OSAID *theContext));
+static void tclOSAAddContext _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *contextName, const OSAID theContext));
+static int tclOSAMakeContext _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *contextName, OSAID *theContext));
+static int tclOSADeleteContext _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *contextName));
+static int tclOSALoad _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *theComponent, char *resourceName,
+ int resourceNumber, char *fileName,OSAID *resultID));
+static int tclOSAStore _ANSI_ARGS_((Tcl_Interp *interp,
+ tclOSAComponent *theComponent, char *resourceName,
+ int resourceNumber, char *fileName,char *scriptName));
+static int tclOSAAddScript _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *scriptName, long modeFlags, OSAID scriptID));
+static int tclOSAGetScriptID _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *scriptName, OSAID *scriptID));
+static tclOSAScript * tclOSAGetScript _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *scriptName));
+static int tclOSADeleteScript _ANSI_ARGS_((tclOSAComponent *theComponent,
+ char *scriptName,char *errMsg));
+
+/*
+ * "export" is a MetroWerks specific pragma. It flags the linker that
+ * any symbols that are defined when this pragma is on will be exported
+ * to shared libraries that link with this library.
+ */
+
+
+#pragma export on
+int Tclapplescript_Init( Tcl_Interp *interp );
+#pragma export reset
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tclapplescript_Init --
+ *
+ * Initializes the the OSA command which opens connections to
+ * OSA components, creates the AppleScript command, which opens an
+ * instance of the AppleScript component,and constructs the table of
+ * available languages.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side Effects:
+ * Opens one connection to the AppleScript component, if
+ * available. Also builds up a table of available OSA languages,
+ * and creates the OSA command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tclapplescript_Init(
+ Tcl_Interp *interp) /* Tcl interpreter. */
+{
+ char *errMsg = NULL;
+ OSErr myErr = noErr;
+ Boolean gotAppleScript = false;
+ Boolean GotOneOSALanguage = false;
+ ComponentDescription compDescr = {
+ kOSAComponentType,
+ (OSType) 0,
+ (OSType) 0,
+ (long) 0,
+ (long) 0
+ }, *foundComp;
+ Component curComponent = (Component) 0;
+ ComponentInstance curOpenComponent;
+ Tcl_HashTable *ComponentTable;
+ Tcl_HashTable *LanguagesTable;
+ Tcl_HashEntry *hashEntry;
+ int newPtr;
+ AEDesc componentName = { typeNull, NULL };
+ char nameStr[32];
+ Size nameLen;
+ long appleScriptFlags;
+
+ /*
+ * Here We Will Get The Available Osa Languages, Since They Can Only Be
+ * Registered At Startup... If You Dynamically Load Components, This
+ * Will Fail, But This Is Not A Common Thing To Do.
+ */
+
+ LanguagesTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+
+ if (LanguagesTable == NULL) {
+ panic("Memory Error Allocating Languages Hash Table");
+ }
+
+ Tcl_SetAssocData(interp, "OSAScript_LangTable", NULL, LanguagesTable);
+ Tcl_InitHashTable(LanguagesTable, TCL_STRING_KEYS);
+
+
+ while ((curComponent = FindNextComponent(curComponent, &compDescr)) != 0) {
+ int nbytes = sizeof(ComponentDescription);
+ foundComp = (ComponentDescription *)
+ ckalloc(sizeof(ComponentDescription));
+ myErr = GetComponentInfo(curComponent, foundComp, NULL, NULL, NULL);
+ if (foundComp->componentSubType ==
+ kOSAGenericScriptingComponentSubtype) {
+ /* Skip the generic component */
+ ckfree((char *) foundComp);
+ } else {
+ GotOneOSALanguage = true;
+
+ /*
+ * This is gross: looks like I have to open the component just
+ * to get its name!!! GetComponentInfo is supposed to return
+ * the name, but AppleScript always returns an empty string.
+ */
+
+ curOpenComponent = OpenComponent(curComponent);
+ if (curOpenComponent == NULL) {
+ Tcl_AppendResult(interp,"Error opening component",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ myErr = OSAScriptingComponentName(curOpenComponent,&componentName);
+ if (myErr == noErr) {
+ myErr = GetCStringFromDescriptor(&componentName,
+ nameStr, 31, &nameLen);
+ AEDisposeDesc(&componentName);
+ }
+ CloseComponent(curOpenComponent);
+
+ if (myErr == noErr) {
+ hashEntry = Tcl_CreateHashEntry(LanguagesTable,
+ nameStr, &newPtr);
+ Tcl_SetHashValue(hashEntry, (ClientData) foundComp);
+ } else {
+ Tcl_AppendResult(interp,"Error getting componentName.",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure AppleScript is loaded, otherwise we will
+ * not bother to make the AppleScript command.
+ */
+ if (foundComp->componentSubType == kAppleScriptSubtype) {
+ appleScriptFlags = foundComp->componentFlags;
+ gotAppleScript = true;
+ }
+ }
+ }
+
+ /*
+ * Create the OSA command.
+ */
+
+ if (!GotOneOSALanguage) {
+ Tcl_AppendResult(interp,"Could not find any OSA languages",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the Component Assoc Data & put it in the interpreter.
+ */
+
+ ComponentTable = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+
+ if (ComponentTable == NULL) {
+ panic("Memory Error Allocating Hash Table");
+ }
+
+ Tcl_SetAssocData(interp, "OSAScript_CompTable", NULL, ComponentTable);
+
+ Tcl_InitHashTable(ComponentTable, TCL_STRING_KEYS);
+
+ /*
+ * The OSA command is not currently supported.
+ Tcl_CreateCommand(interp, "OSA", Tcl_OSACmd, (ClientData) NULL,
+ (Tcl_CmdDeleteProc *) NULL);
+ */
+
+ /*
+ * Open up one AppleScript component, with a default context
+ * and tie it to the AppleScript command.
+ * If the user just wants single-threaded AppleScript execution
+ * this should be enough.
+ *
+ */
+
+ if (gotAppleScript) {
+ if (tclOSAMakeNewComponent(interp, "AppleScript",
+ "AppleScript English", kAppleScriptSubtype,
+ appleScriptFlags) == NULL ) {
+ return TCL_ERROR;
+ }
+ }
+
+ return Tcl_PkgProvide(interp, "OSAConnect", "1.0");
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OSACmd --
+ *
+ * This is the command that provides the interface to the OSA
+ * component manager. The subcommands are: close: close a component,
+ * info: get info on components open, and open: get a new connection
+ * with the Scripting Component
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the subcommand, see the user documentation
+ * for more details.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_OSACmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv)
+{
+ static unsigned short componentCmdIndex = 0;
+ char autoName[32];
+ char c;
+ int length;
+ Tcl_HashTable *ComponentTable = NULL;
+
+
+ if (argc == 1) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " option\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c = *argv[1];
+ length = strlen(argv[1]);
+
+ /*
+ * Query out the Component Table, since most of these commands use it...
+ */
+
+ ComponentTable = (Tcl_HashTable *) Tcl_GetAssocData(interp,
+ "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
+
+ if (ComponentTable == NULL) {
+ Tcl_AppendResult(interp, "Error, could not get the Component Table",
+ " from the Associated data.", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'c' && strncmp(argv[1],"close",length) == 0) {
+ Tcl_HashEntry *hashEntry;
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ",argv[1], " componentName\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if ((hashEntry = Tcl_FindHashEntry(ComponentTable,argv[2])) == NULL) {
+ Tcl_AppendResult(interp, "Component \"", argv[2], "\" not found",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ Tcl_DeleteCommand(interp,argv[2]);
+ return TCL_OK;
+ }
+ } else if (c == 'o' && strncmp(argv[1],"open",length) == 0) {
+ /*
+ * Default language is AppleScript.
+ */
+ OSType scriptSubtype = kAppleScriptSubtype;
+ char *languageName = "AppleScript English";
+ char *errMsg = NULL;
+ ComponentDescription *theCD;
+
+ argv += 2;
+ argc -= 2;
+
+ while (argc > 0 ) {
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+ if (c == 'l' && strcmp(argv[0] + 1, "language") == 0) {
+ if (argc == 1) {
+ Tcl_AppendResult(interp,
+ "Error - no language provided for the -language switch",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ Tcl_HashEntry *hashEntry;
+ Tcl_HashSearch search;
+ Boolean gotIt = false;
+ Tcl_HashTable *LanguagesTable;
+
+ /*
+ * Look up the language in the languages table
+ * Do a simple strstr match, so AppleScript
+ * will match "AppleScript English"...
+ */
+
+ LanguagesTable = Tcl_GetAssocData(interp,
+ "OSAScript_LangTable",
+ (Tcl_InterpDeleteProc **) NULL);
+
+ for (hashEntry =
+ Tcl_FirstHashEntry(LanguagesTable, &search);
+ hashEntry != NULL;
+ hashEntry = Tcl_NextHashEntry(&search)) {
+ languageName = Tcl_GetHashKey(LanguagesTable,
+ hashEntry);
+ if (strstr(languageName,argv[1]) != NULL) {
+ theCD = (ComponentDescription *)
+ Tcl_GetHashValue(hashEntry);
+ gotIt = true;
+ break;
+ }
+ }
+ if (!gotIt) {
+ Tcl_AppendResult(interp,
+ "Error, could not find the language \"",
+ argv[1],
+ "\" in the list of known languages.",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ argc -= 2;
+ argv += 2;
+ } else {
+ Tcl_AppendResult(interp, "Expected a flag, but got ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ sprintf(autoName, "OSAComponent%-d", componentCmdIndex++);
+ if (tclOSAMakeNewComponent(interp, autoName, languageName,
+ theCD->componentSubType, theCD->componentFlags) == NULL ) {
+ return TCL_ERROR;
+ } else {
+ Tcl_SetResult(interp,autoName,TCL_VOLATILE);
+ return TCL_OK;
+ }
+
+ } else if (c == 'i' && strncmp(argv[1],"info",length) == 0) {
+ if (argc == 2) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ", argv[1], " what\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c = *argv[2];
+ length = strlen(argv[2]);
+
+ if (c == 'c' && strncmp(argv[2], "components", length) == 0) {
+ Tcl_DString theResult;
+
+ Tcl_DStringInit(&theResult);
+
+ if (argc == 3) {
+ getSortedHashKeys(ComponentTable,(char *) NULL, &theResult);
+ } else if (argc == 4) {
+ getSortedHashKeys(ComponentTable, argv[3], &theResult);
+ } else {
+ Tcl_AppendResult(interp, "Error: wrong # of arguments",
+ ", should be \"", argv[0], " ", argv[1], " ",
+ argv[2], " ?pattern?\".", (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringResult(interp, &theResult);
+ return TCL_OK;
+ } else if (c == 'l' && strncmp(argv[2],"languages",length) == 0) {
+ Tcl_DString theResult;
+ Tcl_HashTable *LanguagesTable;
+
+ Tcl_DStringInit(&theResult);
+ LanguagesTable = Tcl_GetAssocData(interp,
+ "OSAScript_LangTable", (Tcl_InterpDeleteProc **) NULL);
+
+ if (argc == 3) {
+ getSortedHashKeys(LanguagesTable, (char *) NULL, &theResult);
+ } else if (argc == 4) {
+ getSortedHashKeys(LanguagesTable, argv[3], &theResult);
+ } else {
+ Tcl_AppendResult(interp, "Error: wrong # of arguments",
+ ", should be \"", argv[0], " ", argv[1], " ",
+ argv[2], " ?pattern?\".", (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringResult(interp,&theResult);
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "Unknown option: ", argv[2],
+ " for OSA info, should be one of",
+ " \"components\" or \"languages\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "Unknown option: ", argv[1],
+ ", should be one of \"open\", \"close\" or \"info\".",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OSAComponentCmd --
+ *
+ * This is the command that provides the interface with an OSA
+ * component. The sub commands are:
+ * - compile ? -context context? scriptData
+ * compiles the script data, returns the ScriptID
+ * - decompile ? -context context? scriptData
+ * decompiles the script data, source code
+ * - execute ?-context context? scriptData
+ * compiles and runs script data
+ * - info what: get component info
+ * - load ?-flags values? fileName
+ * loads & compiles script data from fileName
+ * - run scriptId ?options?
+ * executes the compiled script
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side Effects:
+ * Depends on the subcommand, see the user documentation
+ * for more details.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_OSAComponentCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv)
+{
+ int length;
+ char c;
+
+ tclOSAComponent *OSAComponent = (tclOSAComponent *) clientData;
+
+ if (argc == 1) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ argv[0], " option ?arg ...?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c = *argv[1];
+ length = strlen(argv[1]);
+ if (c == 'c' && strncmp(argv[1], "compile", length) == 0) {
+ return TclOSACompileCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'l' && strncmp(argv[1], "load", length) == 0) {
+ return tclOSALoadCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'e' && strncmp(argv[1], "execute", length) == 0) {
+ return tclOSAExecuteCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'i' && strncmp(argv[1], "info", length) == 0) {
+ return tclOSAInfoCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'd' && strncmp(argv[1], "decompile", length) == 0) {
+ return tclOSADecompileCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'd' && strncmp(argv[1], "delete", length) == 0) {
+ return tclOSADeleteCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 'r' && strncmp(argv[1], "run", length) == 0) {
+ return tclOSARunCmd(interp, OSAComponent, argc, argv);
+ } else if (c == 's' && strncmp(argv[1], "store", length) == 0) {
+ return tclOSAStoreCmd(interp, OSAComponent, argc, argv);
+ } else {
+ Tcl_AppendResult(interp,"bad option \"", argv[1],
+ "\": should be compile, decompile, delete, ",
+ "execute, info, load, run or store",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclOSACompileCmd --
+ *
+ * This is the compile subcommand for the component command.
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side Effects:
+ * Compiles the script data either into a script or a script
+ * context. Adds the script to the component's script or context
+ * table. Sets interp's result to the name of the new script or
+ * context.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TclOSACompileCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ int tclError = TCL_OK;
+ int augment = 1;
+ int makeContext = 0;
+ char c;
+ char autoName[16];
+ char buffer[32];
+ char *resultName;
+ Boolean makeNewContext = false;
+ Tcl_DString scrptData;
+ AEDesc scrptDesc = { typeNull, NULL };
+ long modeFlags = kOSAModeCanInteract;
+ OSAID resultID = kOSANullScript;
+ OSAID contextID = kOSANullScript;
+ OSAID parentID = kOSANullScript;
+ OSAError osaErr = noErr;
+
+ if (!(OSAComponent->componentFlags && kOSASupportsCompiling)) {
+ Tcl_AppendResult(interp,
+ "OSA component does not support compiling",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * This signals that we should make up a name, which is the
+ * default behavior:
+ */
+
+ autoName[0] = '\0';
+ resultName = NULL;
+
+ if (argc == 2) {
+ numArgs:
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"", argv[0], " ", argv[1],
+ " ?options? code\"",(char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+
+ /*
+ * Do the argument parsing.
+ */
+
+ while (argc > 0) {
+
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+
+ /*
+ * "--" is the only switch that has no value, stops processing
+ */
+
+ if (c == '-' && *(argv[0] + 2) == '\0') {
+ argv += 1;
+ argc--;
+ break;
+ }
+
+ /*
+ * So we can check here a switch with no value.
+ */
+
+ if (argc == 1) {
+ Tcl_AppendResult(interp,
+ "no value given for switch: ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
+ if (Tcl_GetBoolean(interp, argv[1], &makeContext) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else if (c == 'a' && strcmp(argv[0] + 1, "augment") == 0) {
+ /*
+ * Augment the current context which implies making a context.
+ */
+
+ if (Tcl_GetBoolean(interp, argv[1], &augment) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ makeContext = 1;
+ } else if (c == 'n' && strcmp(argv[0] + 1, "name") == 0) {
+ resultName = argv[1];
+ } else if (c == 'p' && strcmp(argv[0] + 1,"parent") == 0) {
+ /*
+ * Since this implies we are compiling into a context,
+ * set makeContext here
+ */
+ if (tclOSAGetContextID(OSAComponent,
+ argv[1], &parentID) != TCL_OK) {
+ Tcl_AppendResult(interp, "context not found \"",
+ argv[1], "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ makeContext = 1;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", argv[0],
+ "\": should be -augment, -context, -name or -parent",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ argv += 2;
+ argc -= 2;
+
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * Make sure we have some data left...
+ */
+ if (argc == 0) {
+ goto numArgs;
+ }
+
+ /*
+ * Now if we are making a context, see if it is a new one...
+ * There are three options here:
+ * 1) There was no name provided, so we autoName it
+ * 2) There was a name, then check and see if it already exists
+ * a) If yes, then makeNewContext is false
+ * b) Otherwise we are making a new context
+ */
+
+ if (makeContext) {
+ modeFlags |= kOSAModeCompileIntoContext;
+ if (resultName == NULL) {
+ /*
+ * Auto name the new context.
+ */
+ resultName = autoName;
+ resultID = kOSANullScript;
+ makeNewContext = true;
+ } else if (tclOSAGetContextID(OSAComponent,
+ resultName, &resultID) == TCL_OK) {
+ makeNewContext = false;
+ } else {
+ makeNewContext = true;
+ resultID = kOSANullScript;
+ }
+
+ /*
+ * Deal with the augment now...
+ */
+ if (augment && !makeNewContext) {
+ modeFlags |= kOSAModeAugmentContext;
+ }
+ }
+
+ /*
+ * Ok, now we have the options, so we can compile the script data.
+ */
+
+ if (prepareScriptData(argc, argv, &scrptData, &scrptDesc) == TCL_ERROR) {
+ Tcl_DStringResult(interp, &scrptData);
+ AEDisposeDesc(&scrptDesc);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If we want to use a parent context, we have to make the context
+ * by hand. Note, parentID is only specified when you make a new context.
+ */
+
+ if (parentID != kOSANullScript && makeNewContext) {
+ AEDesc contextDesc = { typeNull, NULL };
+
+ osaErr = OSAMakeContext(OSAComponent->theComponent,
+ &contextDesc, parentID, &resultID);
+ modeFlags |= kOSAModeAugmentContext;
+ }
+
+ osaErr = OSACompile(OSAComponent->theComponent, &scrptDesc,
+ modeFlags, &resultID);
+ if (osaErr == noErr) {
+
+ if (makeContext) {
+ /*
+ * For the compiled context to be active, you need to run
+ * the code that is in the context.
+ */
+ OSAID activateID;
+
+ osaErr = OSAExecute(OSAComponent->theComponent, resultID,
+ resultID, kOSAModeCanInteract, &activateID);
+ OSADispose(OSAComponent->theComponent, activateID);
+
+ if (osaErr == noErr) {
+ if (makeNewContext) {
+ /*
+ * If we have compiled into a context,
+ * this is added to the context table
+ */
+
+ tclOSAAddContext(OSAComponent, resultName, resultID);
+ }
+
+ Tcl_SetResult(interp, resultName, TCL_VOLATILE);
+ tclError = TCL_OK;
+ }
+ } else {
+ /*
+ * For a script, we return the script name.
+ */
+ tclOSAAddScript(OSAComponent, resultName, modeFlags, resultID);
+ Tcl_SetResult(interp, resultName, TCL_VOLATILE);
+ tclError = TCL_OK;
+ }
+ }
+
+ /*
+ * This catches the error either from the original compile,
+ * or from the execute in case makeContext == true
+ */
+
+ if (osaErr == errOSAScriptError) {
+ OSADispose(OSAComponent->theComponent, resultID);
+ tclOSAASError(interp, OSAComponent->theComponent,
+ Tcl_DStringValue(&scrptData));
+ tclError = TCL_ERROR;
+ } else if (osaErr != noErr) {
+ sprintf(buffer, "Error #%-6d compiling script", osaErr);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ tclError = TCL_ERROR;
+ }
+
+ Tcl_DStringFree(&scrptData);
+ AEDisposeDesc(&scrptDesc);
+
+ return tclError;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSADecompileCmd --
+ *
+ * This implements the Decompile subcommand of the component command
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side Effects:
+ * Decompiles the script, and sets interp's result to the
+ * decompiled script data.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSADecompileCmd(
+ Tcl_Interp * interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ AEDesc resultingSourceData = { typeChar, NULL };
+ OSAID scriptID;
+ Boolean isContext;
+ long result;
+ OSErr sysErr = noErr;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ",argv[1], " scriptName \"", (char *) NULL );
+ return TCL_ERROR;
+ }
+
+ if (!(OSAComponent->componentFlags && kOSASupportsGetSource)) {
+ Tcl_AppendResult(interp,
+ "Error, this component does not support get source",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (tclOSAGetScriptID(OSAComponent, argv[2], &scriptID) == TCL_OK) {
+ isContext = false;
+ } else if (tclOSAGetContextID(OSAComponent, argv[2], &scriptID)
+ == TCL_OK ) {
+ isContext = true;
+ } else {
+ Tcl_AppendResult(interp, "Could not find script \"",
+ argv[2], "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ OSAGetScriptInfo(OSAComponent->theComponent, scriptID,
+ kOSACanGetSource, &result);
+
+ sysErr = OSAGetSource(OSAComponent->theComponent,
+ scriptID, typeChar, &resultingSourceData);
+
+ if (sysErr == noErr) {
+ Tcl_DString theResult;
+ Tcl_DStringInit(&theResult);
+
+ Tcl_DStringAppend(&theResult, *resultingSourceData.dataHandle,
+ GetHandleSize(resultingSourceData.dataHandle));
+ Tcl_DStringResult(interp, &theResult);
+ AEDisposeDesc(&resultingSourceData);
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "Error getting source data", (char *) NULL);
+ AEDisposeDesc(&resultingSourceData);
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSADeleteCmd --
+ *
+ * This implements the Delete subcommand of the Component command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side Effects:
+ * Deletes a script from the script list of the given component.
+ * Removes all references to the script, and frees the memory
+ * associated with it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSADeleteCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ char c,*errMsg = NULL;
+ int length;
+
+ if (argc < 4) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ", argv[1], " what scriptName", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c = *argv[2];
+ length = strlen(argv[2]);
+ if (c == 'c' && strncmp(argv[2], "context", length) == 0) {
+ if (strcmp(argv[3], "global") == 0) {
+ Tcl_AppendResult(interp, "You cannot delete the global context",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else if (tclOSADeleteContext(OSAComponent, argv[3]) != TCL_OK) {
+ Tcl_AppendResult(interp, "Error deleting script \"", argv[2],
+ "\": ", errMsg, (char *) NULL);
+ ckfree(errMsg);
+ return TCL_ERROR;
+ }
+ } else if (c == 's' && strncmp(argv[2], "script", length) == 0) {
+ if (tclOSADeleteScript(OSAComponent, argv[3], errMsg) != TCL_OK) {
+ Tcl_AppendResult(interp, "Error deleting script \"", argv[3],
+ "\": ", errMsg, (char *) NULL);
+ ckfree(errMsg);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp,"Unknown value ", argv[2],
+ " should be one of ",
+ "\"context\" or \"script\".",
+ (char *) NULL );
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAExecuteCmd --
+ *
+ * This implements the execute subcommand of the component command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Executes the given script data, and sets interp's result to
+ * the OSA component's return value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAExecuteCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ int tclError = TCL_OK, resID = 128;
+ char c,buffer[32],
+ *contextName = NULL,*scriptName = NULL, *resName = NULL;
+ Boolean makeNewContext = false,makeContext = false;
+ AEDesc scrptDesc = { typeNull, NULL };
+ long modeFlags = kOSAModeCanInteract;
+ OSAID resultID = kOSANullScript,
+ contextID = kOSANullScript,
+ parentID = kOSANullScript;
+ Tcl_DString scrptData;
+ OSAError osaErr = noErr;
+ OSErr sysErr = noErr;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp,
+ "Error, no script data for \"", argv[0],
+ " run\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+
+ /*
+ * Set the context to the global context by default.
+ * Then parse the argument list for switches
+ */
+ tclOSAGetContextID(OSAComponent, "global", &contextID);
+
+ while (argc > 0) {
+
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+
+ /*
+ * "--" is the only switch that has no value.
+ */
+
+ if (c == '-' && *(argv[0] + 2) == '\0') {
+ argv += 1;
+ argc--;
+ break;
+ }
+
+ /*
+ * So we can check here for a switch with no value.
+ */
+
+ if (argc == 1) {
+ Tcl_AppendResult(interp,
+ "Error, no value given for switch ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
+ if (tclOSAGetContextID(OSAComponent,
+ argv[1], &contextID) == TCL_OK) {
+ } else {
+ Tcl_AppendResult(interp, "Script context \"",
+ argv[1], "\" not found", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
+ " should be \"-context\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+ } else {
+ break;
+ }
+ }
+
+ if (argc == 0) {
+ Tcl_AppendResult(interp, "Error, no script data", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (prepareScriptData(argc, argv, &scrptData, &scrptDesc) == TCL_ERROR) {
+ Tcl_DStringResult(interp, &scrptData);
+ AEDisposeDesc(&scrptDesc);
+ return TCL_ERROR;
+ }
+ /*
+ * Now try to compile and run, but check to make sure the
+ * component supports the one shot deal
+ */
+ if (OSAComponent->componentFlags && kOSASupportsConvenience) {
+ osaErr = OSACompileExecute(OSAComponent->theComponent,
+ &scrptDesc, contextID, modeFlags, &resultID);
+ } else {
+ /*
+ * If not, we have to do this ourselves
+ */
+ if (OSAComponent->componentFlags && kOSASupportsCompiling) {
+ OSAID compiledID = kOSANullScript;
+ osaErr = OSACompile(OSAComponent->theComponent, &scrptDesc,
+ modeFlags, &compiledID);
+ if (osaErr == noErr) {
+ osaErr = OSAExecute(OSAComponent->theComponent, compiledID,
+ contextID, modeFlags, &resultID);
+ }
+ OSADispose(OSAComponent->theComponent, compiledID);
+ } else {
+ /*
+ * The scripting component had better be able to load text data...
+ */
+ OSAID loadedID = kOSANullScript;
+
+ scrptDesc.descriptorType = OSAComponent->languageID;
+ osaErr = OSALoad(OSAComponent->theComponent, &scrptDesc,
+ modeFlags, &loadedID);
+ if (osaErr == noErr) {
+ OSAExecute(OSAComponent->theComponent, loadedID,
+ contextID, modeFlags, &resultID);
+ }
+ OSADispose(OSAComponent->theComponent, loadedID);
+ }
+ }
+ if (osaErr == errOSAScriptError) {
+ tclOSAASError(interp, OSAComponent->theComponent,
+ Tcl_DStringValue(&scrptData));
+ tclError = TCL_ERROR;
+ } else if (osaErr != noErr) {
+ sprintf(buffer, "Error #%-6d compiling script", osaErr);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ tclError = TCL_ERROR;
+ } else {
+ tclOSAResultFromID(interp, OSAComponent->theComponent, resultID);
+ osaErr = OSADispose(OSAComponent->theComponent, resultID);
+ tclError = TCL_OK;
+ }
+
+ Tcl_DStringFree(&scrptData);
+ AEDisposeDesc(&scrptDesc);
+
+ return tclError;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAInfoCmd --
+ *
+ * This implements the Info subcommand of the component command
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Info on scripts and contexts. See the user documentation for details.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+tclOSAInfoCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ char c;
+ int length;
+ Tcl_DString theResult;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ", argv[1], " what \"", (char *) NULL );
+ return TCL_ERROR;
+ }
+
+ c = *argv[2];
+ length = strlen(argv[2]);
+ if (c == 's' && strncmp(argv[2], "scripts", length) == 0) {
+ Tcl_DStringInit(&theResult);
+ if (argc == 3) {
+ getSortedHashKeys(&OSAComponent->scriptTable, (char *) NULL,
+ &theResult);
+ } else if (argc == 4) {
+ getSortedHashKeys(&OSAComponent->scriptTable, argv[3], &theResult);
+ } else {
+ Tcl_AppendResult(interp, "Error: wrong # of arguments,",
+ " should be \"", argv[0], " ", argv[1], " ",
+ argv[2], " ?pattern?", (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringResult(interp, &theResult);
+ return TCL_OK;
+ } else if (c == 'c' && strncmp(argv[2], "contexts", length) == 0) {
+ Tcl_DStringInit(&theResult);
+ if (argc == 3) {
+ getSortedHashKeys(&OSAComponent->contextTable, (char *) NULL,
+ &theResult);
+ } else if (argc == 4) {
+ getSortedHashKeys(&OSAComponent->contextTable,
+ argv[3], &theResult);
+ } else {
+ Tcl_AppendResult(interp, "Error: wrong # of arguments for ,",
+ " should be \"", argv[0], " ", argv[1], " ",
+ argv[2], " ?pattern?", (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringResult(interp, &theResult);
+ return TCL_OK;
+ } else if (c == 'l' && strncmp(argv[2], "language", length) == 0) {
+ Tcl_SetResult(interp, OSAComponent->languageName, TCL_STATIC);
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "Unknown argument \"", argv[2],
+ "\" for \"", argv[0], " info \", should be one of ",
+ "\"scripts\" \"language\", or \"contexts\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSALoadCmd --
+ *
+ * This is the load subcommand for the Component Command
+ *
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Loads script data from the given file, creates a new context
+ * for it, and sets interp's result to the name of the new context.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSALoadCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ int tclError = TCL_OK, resID = 128;
+ char c, autoName[24],
+ *contextName = NULL, *scriptName = NULL, *resName = NULL;
+ Boolean makeNewContext = false, makeContext = false;
+ AEDesc scrptDesc = { typeNull, NULL };
+ long modeFlags = kOSAModeCanInteract;
+ OSAID resultID = kOSANullScript,
+ contextID = kOSANullScript,
+ parentID = kOSANullScript;
+ OSAError osaErr = noErr;
+ OSErr sysErr = noErr;
+ long scptInfo;
+
+ autoName[0] = '\0';
+ scriptName = autoName;
+ contextName = autoName;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp,
+ "Error, no data for \"", argv[0], " ", argv[1],
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+
+ /*
+ * Do the argument parsing.
+ */
+
+ while (argc > 0) {
+
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+
+ /*
+ * "--" is the only switch that has no value.
+ */
+
+ if (c == '-' && *(argv[0] + 2) == '\0') {
+ argv += 1;
+ argc--;
+ break;
+ }
+
+ /*
+ * So we can check here a switch with no value.
+ */
+
+ if (argc == 1) {
+ Tcl_AppendResult(interp, "Error, no value given for switch ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'r' && strcmp(argv[0] + 1, "rsrcname") == 0) {
+ resName = argv[1];
+ } else if (c == 'r' && strcmp(argv[0] + 1, "rsrcid") == 0) {
+ if (Tcl_GetInt(interp, argv[1], &resID) != TCL_OK) {
+ Tcl_AppendResult(interp,
+ "Error getting resource ID", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
+ " should be \"--\", \"-rsrcname\" or \"-rsrcid\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+ } else {
+ break;
+ }
+ }
+ /*
+ * Ok, now we have the options, so we can load the resource,
+ */
+ if (argc == 0) {
+ Tcl_AppendResult(interp, "Error, no filename given", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (tclOSALoad(interp, OSAComponent, resName, resID,
+ argv[0], &resultID) != TCL_OK) {
+ Tcl_AppendResult(interp, "Error in load command", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now find out whether we have a script, or a script context.
+ */
+
+ OSAGetScriptInfo(OSAComponent->theComponent, resultID,
+ kOSAScriptIsTypeScriptContext, &scptInfo);
+
+ if (scptInfo) {
+ autoName[0] = '\0';
+ tclOSAAddContext(OSAComponent, autoName, resultID);
+
+ Tcl_SetResult(interp, autoName, TCL_VOLATILE);
+ } else {
+ /*
+ * For a script, we return the script name
+ */
+ autoName[0] = '\0';
+ tclOSAAddScript(OSAComponent, autoName, kOSAModeCanInteract, resultID);
+ Tcl_SetResult(interp, autoName, TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSARunCmd --
+ *
+ * This implements the run subcommand of the component command
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Runs the given compiled script, and returns the OSA
+ * component's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSARunCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ int tclError = TCL_OK,
+ resID = 128;
+ char c, *contextName = NULL,
+ *scriptName = NULL,
+ *resName = NULL;
+ AEDesc scrptDesc = { typeNull, NULL };
+ long modeFlags = kOSAModeCanInteract;
+ OSAID resultID = kOSANullScript,
+ contextID = kOSANullScript,
+ parentID = kOSANullScript;
+ OSAError osaErr = noErr;
+ OSErr sysErr = noErr;
+ char *componentName = argv[0];
+ OSAID scriptID;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp, "Wrong # of arguments, should be \"",
+ argv[0], " ", argv[1], " scriptName", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set the context to the global context for this component,
+ * as a default
+ */
+ if (tclOSAGetContextID(OSAComponent, "global", &contextID) != TCL_OK) {
+ Tcl_AppendResult(interp,
+ "Could not find the global context for component ",
+ OSAComponent->theName, (char *) NULL );
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now parse the argument list for switches
+ */
+ argv += 2;
+ argc -= 2;
+
+ while (argc > 0) {
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+ /*
+ * "--" is the only switch that has no value
+ */
+ if (c == '-' && *(argv[0] + 2) == '\0') {
+ argv += 1;
+ argc--;
+ break;
+ }
+
+ /*
+ * So we can check here for a switch with no value.
+ */
+ if (argc == 1) {
+ Tcl_AppendResult(interp, "Error, no value given for switch ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'c' && strcmp(argv[0] + 1, "context") == 0) {
+ if (argc == 1) {
+ Tcl_AppendResult(interp,
+ "Error - no context provided for the -context switch",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else if (tclOSAGetContextID(OSAComponent,
+ argv[1], &contextID) == TCL_OK) {
+ } else {
+ Tcl_AppendResult(interp, "Script context \"", argv[1],
+ "\" not found", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
+ " for ", componentName,
+ " should be \"-context\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ argv += 2;
+ argc -= 2;
+ } else {
+ break;
+ }
+ }
+
+ if (tclOSAGetScriptID(OSAComponent, argv[0], &scriptID) != TCL_OK) {
+ if (tclOSAGetContextID(OSAComponent, argv[0], &scriptID) != TCL_OK) {
+ Tcl_AppendResult(interp, "Could not find script \"",
+ argv[2], "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ sysErr = OSAExecute(OSAComponent->theComponent,
+ scriptID, contextID, modeFlags, &resultID);
+
+ if (sysErr == errOSAScriptError) {
+ tclOSAASError(interp, OSAComponent->theComponent, (char *) NULL);
+ tclError = TCL_ERROR;
+ } else if (sysErr != noErr) {
+ char buffer[32];
+ sprintf(buffer, "Error #%6.6d encountered in run", sysErr);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
+ tclError = TCL_ERROR;
+ } else {
+ tclOSAResultFromID(interp, OSAComponent->theComponent, resultID );
+ }
+ OSADispose(OSAComponent->theComponent, resultID);
+
+ return tclError;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAStoreCmd --
+ *
+ * This implements the store subcommand of the component command
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Runs the given compiled script, and returns the OSA
+ * component's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAStoreCmd(
+ Tcl_Interp *interp,
+ tclOSAComponent *OSAComponent,
+ int argc,
+ char **argv)
+{
+ int tclError = TCL_OK, resID = 128;
+ char c, *contextName = NULL, *scriptName = NULL, *resName = NULL;
+ Boolean makeNewContext = false, makeContext = false;
+ AEDesc scrptDesc = { typeNull, NULL };
+ long modeFlags = kOSAModeCanInteract;
+ OSAID resultID = kOSANullScript,
+ contextID = kOSANullScript,
+ parentID = kOSANullScript;
+ OSAError osaErr = noErr;
+ OSErr sysErr = noErr;
+
+ if (argc == 2) {
+ Tcl_AppendResult(interp, "Error, no data for \"", argv[0],
+ " ",argv[1], "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+
+ /*
+ * Do the argument parsing
+ */
+
+ while (argc > 0) {
+ if (*argv[0] == '-') {
+ c = *(argv[0] + 1);
+
+ /*
+ * "--" is the only switch that has no value
+ */
+ if (c == '-' && *(argv[0] + 2) == '\0') {
+ argv += 1;
+ argc--;
+ break;
+ }
+
+ /*
+ * So we can check here a switch with no value.
+ */
+ if (argc == 1) {
+ Tcl_AppendResult(interp,
+ "Error, no value given for switch ",
+ argv[0], (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (c == 'r' && strcmp(argv[0] + 1, "rsrcname") == 0) {
+ resName = argv[1];
+ } else if (c == 'r' && strcmp(argv[0] + 1, "rsrcid") == 0) {
+ if (Tcl_GetInt(interp, argv[1], &resID) != TCL_OK) {
+ Tcl_AppendResult(interp,
+ "Error getting resource ID", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "Error, invalid switch ", argv[0],
+ " should be \"--\", \"-rsrcname\" or \"-rsrcid\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ argv += 2;
+ argc -= 2;
+ } else {
+ break;
+ }
+ }
+ /*
+ * Ok, now we have the options, so we can load the resource,
+ */
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "Error, wrong # of arguments, should be ",
+ argv[0], " ", argv[1], "?option flag? scriptName fileName",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (tclOSAStore(interp, OSAComponent, resName, resID,
+ argv[0], argv[1]) != TCL_OK) {
+ Tcl_AppendResult(interp, "Error in load command", (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ Tcl_ResetResult(interp);
+ tclError = TCL_OK;
+ }
+
+ return tclError;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAMakeNewComponent --
+ *
+ * Makes a command cmdName to represent a new connection to the
+ * OSA component with componentSubType scriptSubtype.
+ *
+ * Results:
+ * Returns the tclOSAComponent structure for the connection.
+ *
+ * Side Effects:
+ * Adds a new element to the component table. If there is an
+ * error, then the result of the Tcl interpreter interp is set
+ * to an appropriate error message.
+ *
+ *----------------------------------------------------------------------
+ */
+
+tclOSAComponent *
+tclOSAMakeNewComponent(
+ Tcl_Interp *interp,
+ char *cmdName,
+ char *languageName,
+ OSType scriptSubtype,
+ long componentFlags)
+{
+ char buffer[32];
+ AEDesc resultingName = {typeNull, NULL};
+ AEDesc nullDesc = {typeNull, NULL };
+ OSAID globalContext;
+ char global[] = "global";
+ int nbytes;
+ ComponentDescription requestedComponent = {
+ kOSAComponentType,
+ (OSType) 0,
+ (OSType) 0,
+ (long int) 0,
+ (long int) 0
+ };
+ Tcl_HashTable *ComponentTable;
+ Component foundComponent = NULL;
+ OSAActiveUPP myActiveProcUPP;
+
+ tclOSAComponent *newComponent;
+ Tcl_HashEntry *hashEntry;
+ int newPtr;
+
+ requestedComponent.componentSubType = scriptSubtype;
+ nbytes = sizeof(tclOSAComponent);
+ newComponent = (tclOSAComponent *) ckalloc(sizeof(tclOSAComponent));
+ if (newComponent == NULL) {
+ goto CleanUp;
+ }
+
+ foundComponent = FindNextComponent(0, &requestedComponent);
+ if (foundComponent == 0) {
+ Tcl_AppendResult(interp,
+ "Could not find component of requested type", (char *) NULL);
+ goto CleanUp;
+ }
+
+ newComponent->theComponent = OpenComponent(foundComponent);
+
+ if (newComponent->theComponent == NULL) {
+ Tcl_AppendResult(interp,
+ "Could not open component of the requested type",
+ (char *) NULL);
+ goto CleanUp;
+ }
+
+ newComponent->languageName = (char *) ckalloc(strlen(languageName) + 1);
+ strcpy(newComponent->languageName,languageName);
+
+ newComponent->componentFlags = componentFlags;
+
+ newComponent->theInterp = interp;
+
+ Tcl_InitHashTable(&newComponent->contextTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&newComponent->scriptTable, TCL_STRING_KEYS);
+
+ if (tclOSAMakeContext(newComponent, global, &globalContext) != TCL_OK) {
+ sprintf(buffer, "%-6.6d", globalContext);
+ Tcl_AppendResult(interp, "Error ", buffer, " making ", global,
+ " context.", (char *) NULL);
+ goto CleanUp;
+ }
+
+ newComponent->languageID = scriptSubtype;
+
+ newComponent->theName = (char *) ckalloc(strlen(cmdName) + 1 );
+ strcpy(newComponent->theName, cmdName);
+
+ Tcl_CreateCommand(interp, newComponent->theName, Tcl_OSAComponentCmd,
+ (ClientData) newComponent, tclOSAClose);
+
+ /*
+ * Register the new component with the component table
+ */
+
+ ComponentTable = (Tcl_HashTable *) Tcl_GetAssocData(interp,
+ "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
+
+ if (ComponentTable == NULL) {
+ Tcl_AppendResult(interp, "Error, could not get the Component Table",
+ " from the Associated data.", (char *) NULL);
+ return (tclOSAComponent *) NULL;
+ }
+
+ hashEntry = Tcl_CreateHashEntry(ComponentTable,
+ newComponent->theName, &newPtr);
+ Tcl_SetHashValue(hashEntry, (ClientData) newComponent);
+
+ /*
+ * Set the active proc to call Tcl_DoOneEvent() while idle
+ */
+ if (OSAGetActiveProc(newComponent->theComponent,
+ &newComponent->defActiveProc, &newComponent->defRefCon) != noErr ) {
+ /* TODO -- clean up here... */
+ }
+
+ myActiveProcUPP = NewOSAActiveProc(TclOSAActiveProc);
+ OSASetActiveProc(newComponent->theComponent,
+ myActiveProcUPP, (long) newComponent);
+ return newComponent;
+
+ CleanUp:
+
+ ckfree((char *) newComponent);
+ return (tclOSAComponent *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAClose --
+ *
+ * This procedure closes the connection to an OSA component, and
+ * deletes all the script and context data associated with it.
+ * It is the command deletion callback for the component's command.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Closes the connection, and releases all the script data.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+tclOSAClose(
+ ClientData clientData)
+{
+ tclOSAComponent *theComponent = (tclOSAComponent *) clientData;
+ Tcl_HashEntry *hashEntry;
+ Tcl_HashSearch search;
+ tclOSAScript *theScript;
+ Tcl_HashTable *ComponentTable;
+
+ /*
+ * Delete the context and script tables
+ * the memory for the language name, and
+ * the hash entry.
+ */
+
+ for (hashEntry = Tcl_FirstHashEntry(&theComponent->scriptTable, &search);
+ hashEntry != NULL;
+ hashEntry = Tcl_NextHashEntry(&search)) {
+
+ theScript = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
+ OSADispose(theComponent->theComponent, theScript->scriptID);
+ ckfree((char *) theScript);
+ Tcl_DeleteHashEntry(hashEntry);
+ }
+
+ for (hashEntry = Tcl_FirstHashEntry(&theComponent->contextTable, &search);
+ hashEntry != NULL;
+ hashEntry = Tcl_NextHashEntry(&search)) {
+
+ Tcl_DeleteHashEntry(hashEntry);
+ }
+
+ ckfree(theComponent->languageName);
+ ckfree(theComponent->theName);
+
+ /*
+ * Finally close the component
+ */
+
+ CloseComponent(theComponent->theComponent);
+
+ ComponentTable = (Tcl_HashTable *)
+ Tcl_GetAssocData(theComponent->theInterp,
+ "OSAScript_CompTable", (Tcl_InterpDeleteProc **) NULL);
+
+ if (ComponentTable == NULL) {
+ panic("Error, could not get the Component Table from the Associated data.");
+ }
+
+ hashEntry = Tcl_FindHashEntry(ComponentTable, theComponent->theName);
+ if (hashEntry != NULL) {
+ Tcl_DeleteHashEntry(hashEntry);
+ }
+
+ ckfree((char *) theComponent);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAGetContextID --
+ *
+ * This returns the context ID, given the component name.
+ *
+ * Results:
+ * A context ID
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAGetContextID(
+ tclOSAComponent *theComponent,
+ char *contextName,
+ OSAID *theContext)
+{
+ Tcl_HashEntry *hashEntry;
+ tclOSAContext *contextStruct;
+
+ if ((hashEntry = Tcl_FindHashEntry(&theComponent->contextTable,
+ contextName)) == NULL ) {
+ return TCL_ERROR;
+ } else {
+ contextStruct = (tclOSAContext *) Tcl_GetHashValue(hashEntry);
+ *theContext = contextStruct->contextID;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAAddContext --
+ *
+ * This adds the context ID, with the name contextName. If the
+ * name is passed in as a NULL string, space is malloc'ed for the
+ * string and a new name is made up, if the string is empty, you
+ * must have allocated enough space ( 24 characters is fine) for
+ * the name, which is made up and passed out.
+ *
+ * Results:
+ * Nothing
+ *
+ * Side effects:
+ * Adds the script context to the component's context table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+tclOSAAddContext(
+ tclOSAComponent *theComponent,
+ char *contextName,
+ const OSAID theContext)
+{
+ static unsigned short contextIndex = 0;
+ tclOSAContext *contextStruct;
+ Tcl_HashEntry *hashEntry;
+ int newPtr;
+
+ if (contextName == NULL) {
+ contextName = ckalloc(24 * sizeof(char));
+ sprintf(contextName, "OSAContext%d", contextIndex++);
+ } else if (*contextName == '\0') {
+ sprintf(contextName, "OSAContext%d", contextIndex++);
+ }
+
+ hashEntry = Tcl_CreateHashEntry(&theComponent->contextTable,
+ contextName, &newPtr);
+
+ contextStruct = (tclOSAContext *) ckalloc(sizeof(tclOSAContext));
+ contextStruct->contextID = theContext;
+ Tcl_SetHashValue(hashEntry,(ClientData) contextStruct);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSADeleteContext --
+ *
+ * This deletes the context struct, with the name contextName.
+ *
+ * Results:
+ * A normal Tcl result
+ *
+ * Side effects:
+ * Removes the script context to the component's context table,
+ * and deletes the data associated with it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSADeleteContext(
+ tclOSAComponent *theComponent,
+ char *contextName)
+{
+ Tcl_HashEntry *hashEntry;
+ tclOSAContext *contextStruct;
+
+ hashEntry = Tcl_FindHashEntry(&theComponent->contextTable, contextName);
+ if (hashEntry == NULL) {
+ return TCL_ERROR;
+ }
+ /*
+ * Dispose of the script context data
+ */
+ contextStruct = (tclOSAContext *) Tcl_GetHashValue(hashEntry);
+ OSADispose(theComponent->theComponent,contextStruct->contextID);
+ /*
+ * Then the hash entry
+ */
+ ckfree((char *) contextStruct);
+ Tcl_DeleteHashEntry(hashEntry);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAMakeContext --
+ *
+ * This makes the context with name contextName, and returns the ID.
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side effects:
+ * Makes a new context, adds it to the context table, and returns
+ * the new contextID in the variable theContext.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAMakeContext(
+ tclOSAComponent *theComponent,
+ char *contextName,
+ OSAID *theContext)
+{
+ AEDesc contextNameDesc = {typeNull, NULL};
+ OSAError osaErr = noErr;
+
+ AECreateDesc(typeChar, contextName, strlen(contextName), &contextNameDesc);
+ osaErr = OSAMakeContext(theComponent->theComponent, &contextNameDesc,
+ kOSANullScript, theContext);
+
+ AEDisposeDesc(&contextNameDesc);
+
+ if (osaErr == noErr) {
+ tclOSAAddContext(theComponent, contextName, *theContext);
+ } else {
+ *theContext = (OSAID) osaErr;
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAStore --
+ *
+ * This stores a script resource from the file named in fileName.
+ *
+ * Most of this routine is caged from the Tcl Source, from the
+ * Tcl_MacSourceCmd routine. This is good, since it ensures this
+ * follows the same convention for looking up files as Tcl.
+ *
+ * Returns
+ * A standard Tcl result.
+ *
+ * Side Effects:
+ * The given script data is stored in the file fileName.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+tclOSAStore(
+ Tcl_Interp *interp,
+ tclOSAComponent *theComponent,
+ char *resourceName,
+ int resourceNumber,
+ char *scriptName,
+ char *fileName)
+{
+ Handle resHandle;
+ Str255 rezName;
+ int result = TCL_OK;
+ short saveRef, fileRef = -1;
+ char idStr[64];
+ FSSpec fileSpec;
+ Tcl_DString buffer;
+ char *nativeName;
+ OSErr myErr = noErr;
+ OSAID scriptID;
+ Size scriptSize;
+ AEDesc scriptData;
+
+ /*
+ * First extract the script data
+ */
+
+ if (tclOSAGetScriptID(theComponent, scriptName, &scriptID) != TCL_OK ) {
+ if (tclOSAGetContextID(theComponent, scriptName, &scriptID)
+ != TCL_OK) {
+ Tcl_AppendResult(interp, "Error getting script ",
+ scriptName, (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ myErr = OSAStore(theComponent->theComponent, scriptID,
+ typeOSAGenericStorage, kOSAModeNull, &scriptData);
+ if (myErr != noErr) {
+ sprintf(idStr, "%d", myErr);
+ Tcl_AppendResult(interp, "Error #", idStr,
+ " storing script ", scriptName, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now try to open the output file
+ */
+
+ saveRef = CurResFile();
+
+ if (fileName != NULL) {
+ OSErr err;
+
+ Tcl_DStringInit(&buffer);
+ nativeName = Tcl_TranslateFileName(interp, fileName, &buffer);
+ if (nativeName == NULL) {
+ return TCL_ERROR;
+ }
+ err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec);
+
+ Tcl_DStringFree(&buffer);
+ if ((err != noErr) && (err != fnfErr)) {
+ Tcl_AppendResult(interp,
+ "Error getting a location for the file: \"",
+ fileName, "\".", NULL);
+ return TCL_ERROR;
+ }
+
+ FSpCreateResFileCompat(&fileSpec,
+ 'WiSH', 'osas', smSystemScript);
+ myErr = ResError();
+
+ if ((myErr != noErr) && (myErr != dupFNErr)) {
+ sprintf(idStr, "%d", myErr);
+ Tcl_AppendResult(interp, "Error #", idStr,
+ " creating new resource file ", fileName, (char *) NULL);
+ result = TCL_ERROR;
+ goto rezEvalCleanUp;
+ }
+
+ fileRef = FSpOpenResFileCompat(&fileSpec, fsRdWrPerm);
+ if (fileRef == -1) {
+ Tcl_AppendResult(interp, "Error reading the file: \"",
+ fileName, "\".", NULL);
+ result = TCL_ERROR;
+ goto rezEvalCleanUp;
+ }
+ UseResFile(fileRef);
+ } else {
+ /*
+ * The default behavior will search through all open resource files.
+ * This may not be the behavior you desire. If you want the behavior
+ * of this call to *only* search the application resource fork, you
+ * must call UseResFile at this point to set it to the application
+ * file. This means you must have already obtained the application's
+ * fileRef when the application started up.
+ */
+ }
+
+ /*
+ * Load the resource by name
+ */
+ if (resourceName != NULL) {
+ strcpy((char *) rezName + 1, resourceName);
+ rezName[0] = strlen(resourceName);
+ resHandle = Get1NamedResource('scpt', rezName);
+ myErr = ResError();
+ if (resHandle == NULL) {
+ /*
+ * These signify either the resource or the resource
+ * type were not found
+ */
+ if (myErr == resNotFound || myErr == noErr) {
+ short uniqueID;
+ while ((uniqueID = Unique1ID('scpt') ) < 128) {}
+ AddResource(scriptData.dataHandle, 'scpt', uniqueID, rezName);
+ WriteResource(resHandle);
+ result = TCL_OK;
+ goto rezEvalCleanUp;
+ } else {
+ /*
+ * This means there was some other error, for now
+ * I just bag out.
+ */
+ sprintf(idStr, "%d", myErr);
+ Tcl_AppendResult(interp, "Error #", idStr,
+ " opening scpt resource named ", resourceName,
+ " in file ", fileName, (char *) NULL);
+ result = TCL_ERROR;
+ goto rezEvalCleanUp;
+ }
+ }
+ /*
+ * Or ID
+ */
+ } else {
+ resHandle = Get1Resource('scpt', resourceNumber);
+ rezName[0] = 0;
+ rezName[1] = '\0';
+ myErr = ResError();
+ if (resHandle == NULL) {
+ /*
+ * These signify either the resource or the resource
+ * type were not found
+ */
+ if (myErr == resNotFound || myErr == noErr) {
+ AddResource(scriptData.dataHandle, 'scpt',
+ resourceNumber, rezName);
+ WriteResource(resHandle);
+ result = TCL_OK;
+ goto rezEvalCleanUp;
+ } else {
+ /*
+ * This means there was some other error, for now
+ * I just bag out */
+ sprintf(idStr, "%d", myErr);
+ Tcl_AppendResult(interp, "Error #", idStr,
+ " opening scpt resource named ", resourceName,
+ " in file ", fileName,(char *) NULL);
+ result = TCL_ERROR;
+ goto rezEvalCleanUp;
+ }
+ }
+ }
+
+ /*
+ * We get to here if the resource exists
+ * we just copy into it...
+ */
+
+ scriptSize = GetHandleSize(scriptData.dataHandle);
+ SetHandleSize(resHandle, scriptSize);
+ HLock(scriptData.dataHandle);
+ HLock(resHandle);
+ BlockMove(*scriptData.dataHandle, *resHandle,scriptSize);
+ HUnlock(scriptData.dataHandle);
+ HUnlock(resHandle);
+ ChangedResource(resHandle);
+ WriteResource(resHandle);
+ result = TCL_OK;
+ goto rezEvalCleanUp;
+
+ rezEvalError:
+ sprintf(idStr, "ID=%d", resourceNumber);
+ Tcl_AppendResult(interp, "The resource \"",
+ (resourceName != NULL ? resourceName : idStr),
+ "\" could not be loaded from ",
+ (fileName != NULL ? fileName : "application"),
+ ".", NULL);
+
+ rezEvalCleanUp:
+ if (fileRef != -1) {
+ CloseResFile(fileRef);
+ }
+
+ UseResFile(saveRef);
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+ *
+ * tclOSALoad --
+ *
+ * This loads a script resource from the file named in fileName.
+ * Most of this routine is caged from the Tcl Source, from the
+ * Tcl_MacSourceCmd routine. This is good, since it ensures this
+ * follows the same convention for looking up files as Tcl.
+ *
+ * Returns
+ * A standard Tcl result.
+ *
+ * Side Effects:
+ * A new script element is created from the data in the file.
+ * The script ID is passed out in the variable resultID.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+tclOSALoad(
+ Tcl_Interp *interp,
+ tclOSAComponent *theComponent,
+ char *resourceName,
+ int resourceNumber,
+ char *fileName,
+ OSAID *resultID)
+{
+ Handle sourceData;
+ Str255 rezName;
+ int result = TCL_OK;
+ short saveRef, fileRef = -1;
+ char idStr[64];
+ FSSpec fileSpec;
+ Tcl_DString buffer;
+ char *nativeName;
+
+ saveRef = CurResFile();
+
+ if (fileName != NULL) {
+ OSErr err;
+
+ Tcl_DStringInit(&buffer);
+ nativeName = Tcl_TranslateFileName(interp, fileName, &buffer);
+ if (nativeName == NULL) {
+ return TCL_ERROR;
+ }
+ err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec);
+ Tcl_DStringFree(&buffer);
+ if (err != noErr) {
+ Tcl_AppendResult(interp, "Error finding the file: \"",
+ fileName, "\".", NULL);
+ return TCL_ERROR;
+ }
+
+ fileRef = FSpOpenResFileCompat(&fileSpec, fsRdPerm);
+ if (fileRef == -1) {
+ Tcl_AppendResult(interp, "Error reading the file: \"",
+ fileName, "\".", NULL);
+ return TCL_ERROR;
+ }
+ UseResFile(fileRef);
+ } else {
+ /*
+ * The default behavior will search through all open resource files.
+ * This may not be the behavior you desire. If you want the behavior
+ * of this call to *only* search the application resource fork, you
+ * must call UseResFile at this point to set it to the application
+ * file. This means you must have already obtained the application's
+ * fileRef when the application started up.
+ */
+ }
+
+ /*
+ * Load the resource by name or ID
+ */
+ if (resourceName != NULL) {
+ strcpy((char *) rezName + 1, resourceName);
+ rezName[0] = strlen(resourceName);
+ sourceData = GetNamedResource('scpt', rezName);
+ } else {
+ sourceData = GetResource('scpt', (short) resourceNumber);
+ }
+
+ if (sourceData == NULL) {
+ result = TCL_ERROR;
+ } else {
+ AEDesc scriptDesc;
+ OSAError osaErr;
+
+ scriptDesc.descriptorType = typeOSAGenericStorage;
+ scriptDesc.dataHandle = sourceData;
+
+ osaErr = OSALoad(theComponent->theComponent, &scriptDesc,
+ kOSAModeNull, resultID);
+
+ ReleaseResource(sourceData);
+
+ if (osaErr != noErr) {
+ result = TCL_ERROR;
+ goto rezEvalError;
+ }
+
+ goto rezEvalCleanUp;
+ }
+
+ rezEvalError:
+ sprintf(idStr, "ID=%d", resourceNumber);
+ Tcl_AppendResult(interp, "The resource \"",
+ (resourceName != NULL ? resourceName : idStr),
+ "\" could not be loaded from ",
+ (fileName != NULL ? fileName : "application"),
+ ".", NULL);
+
+ rezEvalCleanUp:
+ if (fileRef != -1) {
+ CloseResFile(fileRef);
+ }
+
+ UseResFile(saveRef);
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAGetScriptID --
+ *
+ * This returns the context ID, gibven the component name.
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side effects:
+ * Passes out the script ID in the variable scriptID.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAGetScriptID(
+ tclOSAComponent *theComponent,
+ char *scriptName,
+ OSAID *scriptID)
+{
+ tclOSAScript *theScript;
+
+ theScript = tclOSAGetScript(theComponent, scriptName);
+ if (theScript == NULL) {
+ return TCL_ERROR;
+ }
+
+ *scriptID = theScript->scriptID;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAAddScript --
+ *
+ * This adds a script to theComponent's script table, with the
+ * given name & ID.
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side effects:
+ * Adds an element to the component's script table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSAAddScript(
+ tclOSAComponent *theComponent,
+ char *scriptName,
+ long modeFlags,
+ OSAID scriptID)
+{
+ Tcl_HashEntry *hashEntry;
+ int newPtr;
+ static int scriptIndex = 0;
+ tclOSAScript *theScript;
+
+ if (*scriptName == '\0') {
+ sprintf(scriptName, "OSAScript%d", scriptIndex++);
+ }
+
+ hashEntry = Tcl_CreateHashEntry(&theComponent->scriptTable,
+ scriptName, &newPtr);
+ if (newPtr == 0) {
+ theScript = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
+ OSADispose(theComponent->theComponent, theScript->scriptID);
+ } else {
+ theScript = (tclOSAScript *) ckalloc(sizeof(tclOSAScript));
+ if (theScript == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ theScript->scriptID = scriptID;
+ theScript->languageID = theComponent->languageID;
+ theScript->modeFlags = modeFlags;
+
+ Tcl_SetHashValue(hashEntry,(ClientData) theScript);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAGetScriptID --
+ *
+ * This returns the script structure, given the component and script name.
+ *
+ * Results:
+ * A pointer to the script structure.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static tclOSAScript *
+tclOSAGetScript(
+ tclOSAComponent *theComponent,
+ char *scriptName)
+{
+ Tcl_HashEntry *hashEntry;
+
+ hashEntry = Tcl_FindHashEntry(&theComponent->scriptTable, scriptName);
+ if (hashEntry == NULL) {
+ return NULL;
+ }
+
+ return (tclOSAScript *) Tcl_GetHashValue(hashEntry);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSADeleteScript --
+ *
+ * This deletes the script given by scriptName.
+ *
+ * Results:
+ * A standard Tcl result
+ *
+ * Side effects:
+ * Deletes the script from the script table, and frees up the
+ * resources associated with it. If there is an error, then
+ * space for the error message is malloc'ed, and passed out in
+ * the variable errMsg.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+tclOSADeleteScript(
+ tclOSAComponent *theComponent,
+ char *scriptName,
+ char *errMsg)
+{
+ Tcl_HashEntry *hashEntry;
+ tclOSAScript *scriptPtr;
+
+ hashEntry = Tcl_FindHashEntry(&theComponent->scriptTable, scriptName);
+ if (hashEntry == NULL) {
+ errMsg = ckalloc(17);
+ strcpy(errMsg,"Script not found");
+ return TCL_ERROR;
+ }
+
+ scriptPtr = (tclOSAScript *) Tcl_GetHashValue(hashEntry);
+ OSADispose(theComponent->theComponent, scriptPtr->scriptID);
+ ckfree((char *) scriptPtr);
+ Tcl_DeleteHashEntry(hashEntry);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclOSAActiveProc --
+ *
+ * This is passed to each component. It is run periodically
+ * during script compilation and script execution. It in turn
+ * calls Tcl_DoOneEvent to process the event queue. We also call
+ * the default Active proc which will let the user cancel the script
+ * by hitting Command-.
+ *
+ * Results:
+ * A standard MacOS system error
+ *
+ * Side effects:
+ * Any Tcl code may run while calling Tcl_DoOneEvent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal OSErr
+TclOSAActiveProc(
+ long refCon)
+{
+ tclOSAComponent *theComponent = (tclOSAComponent *) refCon;
+
+ Tcl_DoOneEvent(TCL_DONT_WAIT);
+ CallOSAActiveProc(theComponent->defActiveProc, theComponent->defRefCon);
+
+ return noErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ASCIICompareProc --
+ *
+ * Trivial ascii compare for use with qsort.
+ *
+ * Results:
+ * strcmp of the two input strings
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+ASCIICompareProc(const void *first,const void *second)
+{
+ int order;
+
+ char *firstString = *((char **) first);
+ char *secondString = *((char **) second);
+
+ order = strcmp(firstString, secondString);
+
+ return order;
+}
+
+#define REALLOC_INCR 30
+/*
+ *----------------------------------------------------------------------
+ *
+ * getSortedHashKeys --
+ *
+ * returns an alphabetically sorted list of the keys of the hash
+ * theTable which match the string "pattern" in the DString
+ * theResult. pattern == NULL matches all.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * ReInitializes the DString theResult, then copies the names of
+ * the matching keys into the string as list elements.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+getSortedHashKeys(
+ Tcl_HashTable *theTable,
+ char *pattern,
+ Tcl_DString *theResult)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ Boolean compare = true;
+ char *keyPtr;
+ static char **resultArgv = NULL;
+ static int totSize = 0;
+ int totElem = 0, i;
+
+ if (pattern == NULL || *pattern == '\0' ||
+ (*pattern == '*' && *(pattern + 1) == '\0')) {
+ compare = false;
+ }
+
+ for (hPtr = Tcl_FirstHashEntry(theTable,&search), totElem = 0;
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+
+ keyPtr = (char *) Tcl_GetHashKey(theTable, hPtr);
+ if (!compare || Tcl_StringMatch(keyPtr, pattern)) {
+ totElem++;
+ if (totElem >= totSize) {
+ totSize += REALLOC_INCR;
+ resultArgv = (char **) ckrealloc((char *) resultArgv,
+ totSize * sizeof(char *));
+ }
+ resultArgv[totElem - 1] = keyPtr;
+ }
+ }
+
+ Tcl_DStringInit(theResult);
+ if (totElem == 1) {
+ Tcl_DStringAppendElement(theResult, resultArgv[0]);
+ } else if (totElem > 1) {
+ qsort((VOID *) resultArgv, (size_t) totElem, sizeof (char *),
+ ASCIICompareProc);
+
+ for (i = 0; i < totElem; i++) {
+ Tcl_DStringAppendElement(theResult, resultArgv[i]);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * prepareScriptData --
+ *
+ * Massages the input data in the argv array, concating the
+ * elements, with a " " between each, and replacing \n with \r,
+ * and \\n with " ". Puts the result in the the DString scrptData,
+ * and copies the result to the AEdesc scrptDesc.
+ *
+ * Results:
+ * Standard Tcl result
+ *
+ * Side effects:
+ * Creates a new Handle (with AECreateDesc) for the script data.
+ * Stores the script in scrptData, or the error message if there
+ * is an error creating the descriptor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+prepareScriptData(
+ int argc,
+ char **argv,
+ Tcl_DString *scrptData,
+ AEDesc *scrptDesc)
+{
+ char * ptr;
+ int i;
+ char buffer[7];
+ OSErr sysErr = noErr;
+
+ Tcl_DStringInit(scrptData);
+
+ for (i = 0; i < argc; i++) {
+ Tcl_DStringAppend(scrptData, argv[i], -1);
+ Tcl_DStringAppend(scrptData, " ", 1);
+ }
+
+ /*
+ * First replace the \n's with \r's in the script argument
+ * Also replace "\\n" with " ".
+ */
+
+ for (ptr = scrptData->string; *ptr != '\0'; ptr++) {
+ if (*ptr == '\n') {
+ *ptr = '\r';
+ } else if (*ptr == '\\') {
+ if (*(ptr + 1) == '\n') {
+ *ptr = ' ';
+ *(ptr + 1) = ' ';
+ }
+ }
+ }
+
+ sysErr = AECreateDesc(typeChar, Tcl_DStringValue(scrptData),
+ Tcl_DStringLength(scrptData), scrptDesc);
+
+ if (sysErr != noErr) {
+ sprintf(buffer, "%6d", sysErr);
+ Tcl_DStringFree(scrptData);
+ Tcl_DStringAppend(scrptData, "Error #", 7);
+ Tcl_DStringAppend(scrptData, buffer, -1);
+ Tcl_DStringAppend(scrptData, " creating Script Data Descriptor.", 33);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAResultFromID --
+ *
+ * Gets a human readable version of the result from the script ID
+ * and returns it in the result of the interpreter interp
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Sets the result of interp to the human readable version of resultID.
+ *
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+tclOSAResultFromID(
+ Tcl_Interp *interp,
+ ComponentInstance theComponent,
+ OSAID resultID )
+{
+ OSErr myErr = noErr;
+ AEDesc resultDesc;
+ Tcl_DString resultStr;
+
+ Tcl_DStringInit(&resultStr);
+
+ myErr = OSADisplay(theComponent, resultID, typeChar,
+ kOSAModeNull, &resultDesc);
+ Tcl_DStringAppend(&resultStr, (char *) *resultDesc.dataHandle,
+ GetHandleSize(resultDesc.dataHandle));
+ Tcl_DStringResult(interp,&resultStr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * tclOSAASError --
+ *
+ * Gets the error message from the AppleScript component, and adds
+ * it to interp's result. If the script data is known, will point
+ * out the offending bit of code. This MUST BE A NULL TERMINATED
+ * C-STRING, not a typeChar.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Sets the result of interp to error, plus the relevant portion
+ * of the script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+tclOSAASError(
+ Tcl_Interp * interp,
+ ComponentInstance theComponent,
+ char *scriptData )
+{
+ OSErr myErr = noErr;
+ AEDesc errResult,errLimits;
+ Tcl_DString errStr;
+ DescType returnType;
+ Size returnSize;
+ short srcStart,srcEnd;
+ char buffer[16];
+
+ Tcl_DStringInit(&errStr);
+ Tcl_DStringAppend(&errStr, "An AppleScript error was encountered.\n", -1);
+
+ OSAScriptError(theComponent, kOSAErrorNumber,
+ typeShortInteger, &errResult);
+
+ sprintf(buffer, "Error #%-6.6d\n", (short int) **errResult.dataHandle);
+
+ AEDisposeDesc(&errResult);
+
+ Tcl_DStringAppend(&errStr,buffer, 15);
+
+ OSAScriptError(theComponent, kOSAErrorMessage, typeChar, &errResult);
+ Tcl_DStringAppend(&errStr, (char *) *errResult.dataHandle,
+ GetHandleSize(errResult.dataHandle));
+ AEDisposeDesc(&errResult);
+
+ if (scriptData != NULL) {
+ int lowerB, upperB;
+
+ myErr = OSAScriptError(theComponent, kOSAErrorRange,
+ typeOSAErrorRange, &errResult);
+
+ myErr = AECoerceDesc(&errResult, typeAERecord, &errLimits);
+ myErr = AEGetKeyPtr(&errLimits, keyOSASourceStart,
+ typeShortInteger, &returnType, &srcStart,
+ sizeof(short int), &returnSize);
+ myErr = AEGetKeyPtr(&errLimits, keyOSASourceEnd, typeShortInteger,
+ &returnType, &srcEnd, sizeof(short int), &returnSize);
+ AEDisposeDesc(&errResult);
+ AEDisposeDesc(&errLimits);
+
+ Tcl_DStringAppend(&errStr, "\nThe offending bit of code was:\n\t", -1);
+ /*
+ * Get the full line on which the error occured:
+ */
+ for (lowerB = srcStart; lowerB > 0; lowerB--) {
+ if (*(scriptData + lowerB ) == '\r') {
+ lowerB++;
+ break;
+ }
+ }
+
+ for (upperB = srcEnd; *(scriptData + upperB) != '\0'; upperB++) {
+ if (*(scriptData + upperB) == '\r') {
+ break;
+ }
+ }
+
+ Tcl_DStringAppend(&errStr, scriptData+lowerB, srcStart - lowerB);
+ Tcl_DStringAppend(&errStr, "_", 1);
+ Tcl_DStringAppend(&errStr, scriptData+srcStart, upperB - srcStart);
+ }
+
+ Tcl_DStringResult(interp,&errStr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetRawDataFromDescriptor --
+ *
+ * Get the data from a descriptor.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetRawDataFromDescriptor(
+ AEDesc *theDesc,
+ Ptr destPtr,
+ Size destMaxSize,
+ Size *actSize)
+ {
+ Size copySize;
+
+ if (theDesc->dataHandle) {
+ HLock((Handle)theDesc->dataHandle);
+ *actSize = GetHandleSize((Handle)theDesc->dataHandle);
+ copySize = *actSize < destMaxSize ? *actSize : destMaxSize;
+ BlockMove(*theDesc->dataHandle, destPtr, copySize);
+ HUnlock((Handle)theDesc->dataHandle);
+ } else {
+ *actSize = 0;
+ }
+
+ }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetRawDataFromDescriptor --
+ *
+ * Get the data from a descriptor. Assume it's a C string.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+GetCStringFromDescriptor(
+ AEDesc *sourceDesc,
+ char *resultStr,
+ Size resultMaxSize,
+ Size *resultSize)
+{
+ OSErr err;
+ AEDesc resultDesc;
+
+ resultDesc.dataHandle = nil;
+
+ err = AECoerceDesc(sourceDesc, typeChar, &resultDesc);
+
+ if (!err) {
+ GetRawDataFromDescriptor(&resultDesc, (Ptr) resultStr,
+ resultMaxSize - 1, resultSize);
+ resultStr[*resultSize] = 0;
+ } else {
+ err = errAECoercionFail;
+ }
+
+ if (resultDesc.dataHandle) {
+ AEDisposeDesc(&resultDesc);
+ }
+
+ return err;
+}
diff --git a/mac/tclMacOSA.exp b/mac/tclMacOSA.exp
new file mode 100644
index 0000000..4cde512
--- /dev/null
+++ b/mac/tclMacOSA.exp
@@ -0,0 +1 @@
+Tclapplescript_Init
diff --git a/mac/tclMacOSA.r b/mac/tclMacOSA.r
new file mode 100644
index 0000000..7975a19
--- /dev/null
+++ b/mac/tclMacOSA.r
@@ -0,0 +1,76 @@
+/*
+ * tkMacOSA.r --
+ *
+ * This file creates resources used by the AppleScript package.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacOSA.r 1.6 97/11/20 18:40:02
+ */
+
+#include <Types.r>
+#include <SysTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define SCRIPT_MAJOR_VERSION 1 /* Major number */
+#define SCRIPT_MINOR_VERSION 0 /* Minor number */
+#define SCRIPT_RELEASE_SERIAL 2 /* Really minor number! */
+#define RELEASE_LEVEL alpha /* alpha, beta, or final */
+#define SCRIPT_VERSION "1.0"
+#define SCRIPT_PATCH_LEVEL "1.0a2"
+#define FINAL 0 /* Change to 1 if final version. */
+
+#if FINAL
+# define MINOR_VERSION (SCRIPT_MINOR_VERSION * 16) + SCRIPT_RELEASE_SERIAL
+#else
+# define MINOR_VERSION SCRIPT_MINOR_VERSION * 16
+#endif
+
+#define RELEASE_CODE 0x00
+
+resource 'vers' (1) {
+ SCRIPT_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ SCRIPT_PATCH_LEVEL,
+ SCRIPT_PATCH_LEVEL ", by Jim Ingham & Ray Johnson © Sun Microsystems"
+};
+
+resource 'vers' (2) {
+ SCRIPT_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ SCRIPT_PATCH_LEVEL,
+ "Tclapplescript " SCRIPT_PATCH_LEVEL " © 1996-1997"
+};
+
+/*
+ * The -16397 string will be displayed by Finder when a user
+ * tries to open the shared library. The string should
+ * give the user a little detail about the library's capabilities
+ * and enough information to install the library in the correct location.
+ * A similar string should be placed in all shared libraries.
+ */
+resource 'STR ' (-16397, purgeable) {
+ "TclAppleScript Library\n\n"
+ "This library provides the ability to run AppleScript "
+ " commands from Tcl/Tk programs. To work properly, it "
+ "should be placed in the ÔTool Command LanguageÕ folder "
+ "within the Extensions folder."
+};
+
+
+/*
+ * We now load the Tk library into the resource fork of the library.
+ */
+
+data 'TEXT' (4000,"pkgIndex",purgeable, preload) {
+ "# Tcl package index file, version 1.0\n"
+ "package ifneeded Tclapplescript 1.0 [list tclPkgSetup $dir Tclapplescript 1.0 {{Tclapplescript"
+ ".shlb load AppleScript}}]\n"
+};
diff --git a/mac/tclMacPanic.c b/mac/tclMacPanic.c
new file mode 100644
index 0000000..13219d8
--- /dev/null
+++ b/mac/tclMacPanic.c
@@ -0,0 +1,235 @@
+/*
+ * tclMacPanic.c --
+ *
+ * Source code for the "panic" library procedure used in "Simple Shell";
+ * other Mac applications will probably override this with a more robust
+ * application-specific panic procedure.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacPanic.c 1.14 97/11/20 18:41:06
+ */
+
+
+#include <Events.h>
+#include <Controls.h>
+#include <Windows.h>
+#include <TextEdit.h>
+#include <Fonts.h>
+#include <Dialogs.h>
+#include <Icons.h>
+#include <Sound.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tclInt.h"
+
+/*
+ * constants for panic dialog
+ */
+#define PANICHEIGHT 150 /* Height of dialog */
+#define PANICWIDTH 350 /* Width of dialog */
+#define PANIC_BUTTON_RECT {125, 260, 145, 335} /* Rect for button. */
+#define PANIC_ICON_RECT {10, 20, 42, 52} /* Rect for icon. */
+#define PANIC_TEXT_RECT {10, 65, 140, 330} /* Rect for text. */
+#define ENTERCODE (0x03)
+#define RETURNCODE (0x0D)
+
+/*
+ * The panicProc variable contains a pointer to an application
+ * specific panic procedure.
+ */
+
+void (*panicProc) _ANSI_ARGS_(TCL_VARARGS(char *,format)) = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetPanicProc --
+ *
+ * Replace the default panic behavior with the specified functiion.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the panicProc variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetPanicProc(proc)
+ void (*proc) _ANSI_ARGS_(TCL_VARARGS(char *,format));
+{
+ panicProc = proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacPanic --
+ *
+ * Displays panic info..
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the panicProc variable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MacPanic(
+ char *msg) /* Text to show in panic dialog. */
+{
+ WindowRef macWinPtr, foundWinPtr;
+ Rect macRect;
+ Rect buttonRect = PANIC_BUTTON_RECT;
+ Rect iconRect = PANIC_ICON_RECT;
+ Rect textRect = PANIC_TEXT_RECT;
+ ControlHandle okButtonHandle;
+ EventRecord event;
+ Handle stopIconHandle;
+ int part;
+ Boolean done = false;
+
+
+ /*
+ * Put up an alert without using the Resource Manager (there may
+ * be no resources to load). Use the Window and Control Managers instead.
+ * We want the window centered on the main monitor. The following
+ * should be tested with multiple monitors. Look and see if there is a way
+ * not using qd.screenBits.
+ */
+
+ macRect.top = (qd.screenBits.bounds.top + qd.screenBits.bounds.bottom)
+ / 2 - (PANICHEIGHT / 2);
+ macRect.bottom = (qd.screenBits.bounds.top + qd.screenBits.bounds.bottom)
+ / 2 + (PANICHEIGHT / 2);
+ macRect.left = (qd.screenBits.bounds.left + qd.screenBits.bounds.right)
+ / 2 - (PANICWIDTH / 2);
+ macRect.right = (qd.screenBits.bounds.left + qd.screenBits.bounds.right)
+ / 2 + (PANICWIDTH / 2);
+
+ macWinPtr = NewWindow(NULL, &macRect, "\p", true, dBoxProc, (WindowRef) -1,
+ false, 0);
+ if (macWinPtr == NULL) {
+ goto exitNow;
+ }
+
+ okButtonHandle = NewControl(macWinPtr, &buttonRect, "\pOK", true,
+ 0, 0, 1, pushButProc, 0);
+ if (okButtonHandle == NULL) {
+ CloseWindow(macWinPtr);
+ goto exitNow;
+ }
+
+ SelectWindow(macWinPtr);
+ SetCursor(&qd.arrow);
+ stopIconHandle = GetIcon(kStopIcon);
+
+ while (!done) {
+ if (WaitNextEvent(mDownMask | keyDownMask | updateMask,
+ &event, 0, NULL)) {
+ switch(event.what) {
+ case mouseDown:
+ part = FindWindow(event.where, &foundWinPtr);
+
+ if ((foundWinPtr != macWinPtr) || (part != inContent)) {
+ SysBeep(1);
+ } else {
+ SetPortWindowPort(macWinPtr);
+ GlobalToLocal(&event.where);
+ part = FindControl(event.where, macWinPtr,
+ &okButtonHandle);
+
+ if ((inButton == part) &&
+ (TrackControl(okButtonHandle,
+ event.where, NULL))) {
+ done = true;
+ }
+ }
+ break;
+ case keyDown:
+ switch (event.message & charCodeMask) {
+ case ENTERCODE:
+ case RETURNCODE:
+ HiliteControl(okButtonHandle, 1);
+ HiliteControl(okButtonHandle, 0);
+ done = true;
+ }
+ break;
+ case updateEvt:
+ SetPortWindowPort(macWinPtr);
+ TextFont(systemFont);
+
+ BeginUpdate(macWinPtr);
+ if (stopIconHandle != NULL) {
+ PlotIcon(&iconRect, stopIconHandle);
+ }
+ TextBox(msg, strlen(msg), &textRect, teFlushDefault);
+ DrawControls(macWinPtr);
+ EndUpdate(macWinPtr);
+ }
+ }
+ }
+
+ CloseWindow(macWinPtr);
+
+ exitNow:
+#ifdef TCL_DEBUG
+ Debugger();
+#else
+ abort();
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * panic --
+ *
+ * Print an error message and kill the process.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The process dies, entering the debugger if possible.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#pragma ignore_oldstyle on
+void
+panic(char * format, ...)
+{
+ va_list varg;
+ char errorText[256];
+
+ if (panicProc != NULL) {
+ va_start(varg, format);
+
+ (void) (*panicProc)(format, varg);
+
+ va_end(varg);
+ } else {
+ va_start(varg, format);
+
+ vsprintf(errorText, format, varg);
+
+ va_end(varg);
+
+ MacPanic(errorText);
+ }
+
+}
+#pragma ignore_oldstyle reset
diff --git a/mac/tclMacPort.h b/mac/tclMacPort.h
new file mode 100644
index 0000000..366b7a0
--- /dev/null
+++ b/mac/tclMacPort.h
@@ -0,0 +1,263 @@
+/*
+ * tclMacPort.h --
+ *
+ * This header file handles porting issues that occur because of
+ * differences between the Mac and Unix. It should be the only
+ * file that contains #ifdefs to handle different flavors of OS.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacPort.h 1.75 97/08/11 10:18:07
+ */
+
+#ifndef _MACPORT
+#define _MACPORT
+
+#ifndef _TCL
+#include "tcl.h"
+#endif
+
+#include "tclErrno.h"
+#include <float.h>
+
+/* Includes */
+#ifdef THINK_C
+ /*
+ * The Symantic C code has not been tested
+ * and probably will not work.
+ */
+# include <pascal.h>
+# include <posix.h>
+# include <string.h>
+# include <fcntl.h>
+# include <pwd.h>
+# include <sys/param.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <unistd.h>
+#elif defined(__MWERKS__)
+# include <time.h>
+# include <unistd.h>
+/*
+ * The following definitions are usually found if fcntl.h.
+ * However, MetroWerks has screwed that file up a couple of times
+ * and all we need are the defines.
+ */
+#define O_RDWR 0x0 /* open the file in read/write mode */
+#define O_RDONLY 0x1 /* open the file in read only mode */
+#define O_WRONLY 0x2 /* open the file in write only mode */
+#define O_APPEND 0x0100 /* open the file in append mode */
+#define O_CREAT 0x0200 /* create the file if it doesn't exist */
+#define O_EXCL 0x0400 /* if the file exists don't create it again */
+#define O_TRUNC 0x0800 /* truncate the file after opening it */
+
+/*
+ * MetroWerks stat.h file is rather weak. The defines
+ * after the include are needed to fill in the missing
+ * defines.
+ */
+# include <stat.h>
+# ifndef S_IFIFO
+# define S_IFIFO 0x0100
+# endif
+# ifndef S_IFBLK
+# define S_IFBLK 0x0600
+# endif
+# ifndef S_ISLNK
+# define S_ISLNK(m) (((m)&(S_IFMT)) == (S_IFLNK))
+# endif
+# ifndef S_ISSOCK
+# define S_ISSOCK(m) (((m)&(S_IFMT)) == (S_IFSOCK))
+# endif
+# ifndef S_IRWXU
+# define S_IRWXU 00007 /* read, write, execute: owner */
+# define S_IRUSR 00004 /* read permission: owner */
+# define S_IWUSR 00002 /* write permission: owner */
+# define S_IXUSR 00001 /* execute permission: owner */
+# define S_IRWXG 00007 /* read, write, execute: group */
+# define S_IRGRP 00004 /* read permission: group */
+# define S_IWGRP 00002 /* write permission: group */
+# define S_IXGRP 00001 /* execute permission: group */
+# define S_IRWXO 00007 /* read, write, execute: other */
+# define S_IROTH 00004 /* read permission: other */
+# define S_IWOTH 00002 /* write permission: other */
+# define S_IXOTH 00001 /* execute permission: other */
+# endif
+
+# define isatty(arg) 1
+
+/*
+ * Defines used by access function. This function is provided
+ * by Mac Tcl as the function TclMacAccess.
+ */
+
+# define F_OK 0 /* test for existence of file */
+# define X_OK 0x01 /* test for execute or search permission */
+# define W_OK 0x02 /* test for write permission */
+# define R_OK 0x04 /* test for read permission */
+
+#endif
+
+/*
+ * waitpid doesn't work on a Mac - the following makes
+ * Tcl compile without errors. These would normally
+ * be defined in sys/wait.h on UNIX systems.
+ */
+
+#define WNOHANG 1
+#define WIFSTOPPED(stat) (1)
+#define WIFSIGNALED(stat) (1)
+#define WIFEXITED(stat) (1)
+#define WIFSTOPSIG(stat) (1)
+#define WIFTERMSIG(stat) (1)
+#define WIFEXITSTATUS(stat) (1)
+#define WEXITSTATUS(stat) (1)
+#define WTERMSIG(status) (1)
+#define WSTOPSIG(status) (1)
+
+/*
+ * Define "NBBY" (number of bits per byte) if it's not already defined.
+ */
+
+#ifndef NBBY
+# define NBBY 8
+#endif
+
+/*
+ * These functions always return dummy values on Mac.
+ */
+#ifndef geteuid
+# define geteuid() 1
+#endif
+#ifndef getpid
+# define getpid() -1
+#endif
+
+#define NO_SYS_ERRLIST
+#define WAIT_STATUS_TYPE int
+
+/*
+ * Make sure that MAXPATHLEN is defined.
+ */
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# else
+# define MAXPATHLEN 2048
+# endif
+#endif
+
+/*
+ * The following functions are declared in tclInt.h but don't do anything
+ * on Macintosh systems.
+ */
+
+#define TclSetSystemEnv(a,b)
+
+/*
+ * Many signals are not supported on the Mac and are thus not defined in
+ * <signal.h>. They are defined here so that Tcl will compile with less
+ * modification.
+ */
+
+#ifndef SIGQUIT
+#define SIGQUIT 300
+#endif
+
+#ifndef SIGPIPE
+#define SIGPIPE 13
+#endif
+
+#ifndef SIGHUP
+#define SIGHUP 100
+#endif
+
+extern char **environ;
+
+/*
+ * Prototypes needed for compatability
+ */
+
+EXTERN int TclMacCreateEnv _ANSI_ARGS_((void));
+EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1,
+ CONST char *s2, size_t n));
+
+/*
+ * The following declarations belong in tclInt.h, but depend on platform
+ * specific types (e.g. struct tm).
+ */
+
+EXTERN struct tm * TclpGetDate _ANSI_ARGS_((const time_t *tp,
+ int useGMT));
+EXTERN size_t TclStrftime _ANSI_ARGS_((char *s, size_t maxsize,
+ const char *format, const struct tm *t));
+
+#define tzset()
+#define TclpGetPid(pid) ((unsigned long) (pid))
+
+/*
+ * The following prototypes and defines replace the Macintosh version
+ * of the POSIX functions "stat" and "access". The various compilier
+ * vendors don't implement this function well nor consistantly.
+ */
+EXTERN int TclMacStat _ANSI_ARGS_((char *path, struct stat *buf));
+#define stat(path, bufPtr) TclMacStat(path, bufPtr)
+#define lstat(path, bufPtr) TclMacStat(path, bufPtr)
+EXTERN int TclMacAccess _ANSI_ARGS_((const char *filename, int mode));
+#define access(path, mode) TclMacAccess(path, mode)
+EXTERN FILE * TclMacFOpenHack _ANSI_ARGS_((const char *path,
+ const char *mode));
+#define fopen(path, mode) TclMacFOpenHack(path, mode)
+EXTERN int TclMacReadlink _ANSI_ARGS_((char *path, char *buf, int size));
+#define readlink(fileName, buffer, size) TclMacReadlink(fileName, buffer, size)
+#ifdef TCL_TEST
+#define chmod(path, mode) TclMacChmod(path, mode)
+EXTERN int TclMacChmod(char *path, int mode);
+#endif
+
+/*
+ * Defines for Tcl internal commands that aren't really needed on
+ * the Macintosh. They all act as no-ops.
+ */
+#define TclCreateCommandChannel(out, in, err, num, pidPtr) NULL
+#define TclClosePipeFile(x)
+
+/*
+ * These definitions force putenv & company to use the version
+ * supplied with Tcl.
+ */
+#ifndef putenv
+# define unsetenv TclUnsetEnv
+# define putenv Tcl_PutEnv
+# define setenv TclSetEnv
+void TclSetEnv(CONST char *name, CONST char *value);
+int Tcl_PutEnv(CONST char *string);
+void TclUnsetEnv(CONST char *name);
+#endif
+
+/*
+ * The default platform eol translation on Mac is TCL_TRANSLATE_CR:
+ */
+
+#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CR
+
+/*
+ * Declare dynamic loading extension macro.
+ */
+
+#define TCL_SHLIB_EXT ".shlb"
+
+/*
+ * The following define should really be in tclInt.h, but tclInt.h does
+ * not include tclPort.h, which includes the "struct stat" definition.
+ */
+
+EXTERN int TclpSameFile _ANSI_ARGS_((char *file1, char *file2,
+ struct stat *sourceStatBufPtr,
+ struct stat *destStatBufPtr)) ;
+
+#endif /* _MACPORT */
diff --git a/mac/tclMacProjects.sit.hqx b/mac/tclMacProjects.sit.hqx
new file mode 100644
index 0000000..212d433
--- /dev/null
+++ b/mac/tclMacProjects.sit.hqx
@@ -0,0 +1,3157 @@
+(This file must be converted with BinHex 4.0)
+:%R4ME%eKBe"bEfTPBh4c,R0TG!"6594%8dP8)3#3!`*39!#3"(@,8dP8)3!"!!*
+39(*-BA8#!*!%&J!!)#!1G'0X6@&M8(*[DQ9MG(-!N"'MU!#3!p%"J!*L!hF!N!-
+(!*!2KJ!!!J$rN!3$!+df8!b`K1qP!*!&$&1Y!*!&!Nr1rpIrq`#3"Tfh!!d23Np
+"Ae4ME&0SC@aXFbkj!*!3IPF!N"%@!!![#`#3!aErN!4069"b3eG*43%!VllJ3l#
+%lG3!N!8"UPS!N!BZ&3!!BV3!N!CrmJB!kh(#A3JIG)6GpKBPYieXKYrQ8hkaMLE
+2)i``3VPN(l19QGqQFLURPpb,r$jfDiCR+Y1h[AU8HjYe2GZ%fbAKC*maF[YXB%F
+fiB4h$Q+EeE(YNAeq4RKQ6ik6jdrB(K#fb6EGK'GQN[fkMr#1l)'%Aa6Sm!Hd!Uc
+(,MplhDIbmcBMqmKY`XNQ[mNQQp`QYmPqm6`+X(jR$I)kXr20JH`FYFpciANj@0J
+qHrCjA@cKTPY[DfFPffaV(5[GCPSA[r)k[Nc-M"I2kc+rXc-[-ehXq"@rHXqV-c1
+q[#i$hR@m%H6,HjhIQBfd33-6!![JV-[VE0LJAfZcVENK)pbHl$MCj"D6,3#Fi$X
+!,pp"&AbrC)a*ihr%T$kb!IprEXa,,d6mQK31`CGT409+r&q&#hr%Q*-8VhcFQ)j
+ZM3YTI2[ZD-qhqQ2K-hFm)5TG$R*qFQTGkT!!p,P2pDBMCFE(kfPI'8ra)p3E(rP
+Hmf&MhM$1RdjK8X*Cf0Zec*pZfI@Pc%(Qd!5!+Pc(I!*cG2rd+(2)P+aIb4Im[6h
+U""C06pf@AQ22j5BUmil8pe1E$cV"c%3EEM6Q*pPNLNQM8iUK%$-+Z1KhQ+!ATkj
+2E8NrXQf#JYi8F#iGYF@fa[I3Y6Bc$ImMD6CS5G3Ph`#L9A%PAlcq&QSkq%lKE%M
+Xl(TjqVXBrqf+DCE80N@a0q)rUpM[4"fhh`Ia2dfa[m1r)*!!BMdc&&Z%`dc&(Sr
+$BBTY`Q'@BXr$BECLeq"`Z'+rUVNKp[Xic&(XicJFUGKri6"A)%L2Me,X1"b19Q`
+0$[-8Z`L(qBVp)!i,&(Xe$Pf+rCVQKGJIip#Yf0rLd#0SB6Ck&9Z-3jpLMm8KTpL
+j10"rBXr&JAZ)r4J1rBUp!BF"aAiEKd(&rKm13iVp-`l$JQ(,H@f-[La4M*PqK'*
+2aZ'4LJ&Gd&eLe(fXBY5p9,&hik"a`m3qM!1c3qaIF(K8('[Rh"k['$@IS0LT1$a
+DXA0`1&%a-1dNaDl'i@6&IPli3qbG1(bRBTUrYl8VpSmi2#D1G4"(Q#PLc!2e%L2
+RFBTY`!&X)FCm'mc8X4IKX&bakh"BSGJ[il"5XIILF*TLp'#9BTr!BE9LAm,Kp$L
+@*6DGS4Kcm%6&U"qF)FEmICGLcm,K6-9q'!I"j5cajLc&IJ@(GBVp(JkMLYf&`j-
+8q`GK0I!,"UaA$!bJrm5B@fSR4YqC4f+F0bU'EJ)Z%32rcP2XTh%!NiQ"IqFV"[i
+p4E(2i2$GF@`D-IkTLS'*Qa9McTqQ',hBSYJ1(*kZf%Y`Z%!akYkUf+rMF+&LIiE
+$-a3$KjiCakD65fa6$%aNhSR4EfD0'2A$CBKGL3-p*rB+(*kYQ1C)E4A&k,&3[1Q
+FqdX9qdmF`'hpc5!IZ%`am)jq%Q2QKEr0B"rK-X5q(iIR+rCD(%4YQR%M$PFS"Yl
+3(f+I`Z%&F@`Q1CZ`ZjQXqi@+JF9J'M&`iIX8SpI85`b-%3Bk%ebflCf+86Ic6Za
+2F2JKaIiD"qiNGMF1m$lp(8BqKTj'$&laSiU"PF`[-I!#6N'-hVe8-@Ekaa9l"`l
+J2l'2i[!baIi0Kjq)Bl2)cH"pa*LYPbX'EPfV',-(KK2M,QDCf!di[&+a2mAK*aA
+l0!k[LQ1cb@Pr5M%i'0K,$*l!M"!$"jP6BX`E256f1Kaq4V(I`S%iXBrKm,1+I4Q
+(RiYMKj02[Piaq"*mKaMi$ZFL"JE"UBNa*lqJ',cN6BVp!3krU0MIi2$Q1(B%XH'
+A&!2lhk)BFh1pBY4+,F6!bVFU"Ll!0BJa$r"VBMIK`"`4qd-F`%CLIiA$fa6lGac
+J"IUE3ll0RF6JC$FV"KplZf*J2hK1M(lrKQ,d!#`LaLb"$m6)J3m5!rY[83c1F@X
+F1j+Fqef+dA[QN4MF&Hj-$-i'Rb8'2d'[)!B@[dFa-1*h&D1rF%"LGq!!rb)'hlS
+YMXfPaS(q3!bZcQ`5!`ZC&f,8qMl&`26E&@21rNJaCJ1Z3BamF*JB@!9fkHmSFM[
+k3!apiIf+`DXrS"Lib)`3Jfr!)iL"JhFUaMbMca#MYJmTKNi$apHIN8FqSKJm!h`
+Q"SF$hiM"-p%LL-&ji+6%`1Lr8!bmq%[&k#Qi3Hc[F8#VdGmmkNG`+f,S&r!1B["
+`m)dB(2+6LX&Yi%6%`!PQK"KBJ`j$M0QJRm5B9l"#Ir1T3e%l-I$qXiSaVpa$$+k
+'cN!-r[02LS(Gk#h%`!ki*c&Qi&m9JbGp,SiYS"j!R"MDbZF9JaGq36(`liZ+`Ar
+3%iJa0r!JB[35M#9'cIm4alTB(cb8'"J2eb#'&S$f43b1+VTQ&hL4NrbkJ$G1fH`
+#"LMTIehSYC,qYa!DR0(VL'Np5%Rr@`KG3dRr@`LHV+6r,33I8p,r&Q)@PI5rKF!
+M*Ie[)AUYT2pe3ip6d[qkS8mSkArGi#K+qPmhZ,H5rYF0EUHNrh8$`j6d[fjJU*,
+qeiej9Y,rHP#cN[lA!ce!5IrV!DiSkAmpQ(8PrDm(2&P*rqX"ae25rhV!2C6d[aj
+JST,qe`-X80,rHY%l*If[&pU2N[lA#mkKT2reJJFSkAqpi$T'rb5QF89*rqX&2e(
+5rhU"+dVkAbpQ@dRrkd12P25r2Xk0k(ppd*+8p,mqD"p+qPmIZ,U5rYF(VULNrr@
+"cbMTIhh!8bAp,iFj9p,rFZL&N[kA!bG@d[pbd'Z8p,mFm&K*rmYaEN6rbi'R+HP
+r1A!'*Id["ha8d[m@BBD9p,p&a"M4raDaPk,r,B,ZSk6r,B+qS+6r,3+r9G,r&S&
+I+HPrLm!(P25raF!JSbd6dr1MT2mY4Vk5rVFBHTD5rVFBr%a*reX-IUDNrbeQ,dA
+r@mbj&2f289A5rrSa`dVkAcma4[5rIZKC5[TI2rXRqPmrCe(d[hj`5#ApVapF48R
+r'b#ZL2ihJ0P@d[m'L-'Lr`e`eNAr'i$1SU6r$8!M80,r"SL4S[m0%,G%raX%2LV
+TIi1B95ApEa#DKj,q0`K0bQMba$5290,r"SRaS[m0JPXUkAq$i$C+qYm3F&P*raX
+#lLMTId1B'5ApE`KR*Ie[#&U4N[ih"%e(5ImE)Yk,rMF%lUfNr`f"CbVTId2J5dV
+khc$l+[VI-,&Ip,pKBTMSIm2SYC,q0`bHT+6r$82R8Y,rKU(&+1Pr`p!4P25rBH+
+Ck(r$a$24rdE!6j6d[a(@,IVI#$$,H"Q)kIP8d[p'8(r$EHBlq-!,qNhYm"2`!*`
+"JjJ*CSFHd60`(Vi"$f!'dI1B$l4+F"01!1D!4q!(H!,@J!(-1l-0AX,Mi$0`+AJ
++Fi8H!Jiccr"#H!4m"Vi)Ii3AJBAJ*"J+4i3(JHp`9VJ'(!$-KNI!(q!+i$Di$pl
+$#q!5m!Ei#,`)MJXIJ4I"0H&dm%#i)p`%rL0BDc4dH"*F$ii(Gi4$J5R-0p`6[JI
+f``8J"I"DZ"ki#Hq%4m1h`94i(c`@VJQRJ#H!Sq!NQ!L1JQ0J(eS[I-(jEm"'H#R
+B!aD"1q!0A"JH$Ym&Rq(RF('`8AKGr+&MDJkDK8CL+,[Sb-926`QZ*bdK'`dKIp*
+q+I[PAC3FXM49@@P"rq[5TPa-Zlr(ieZHbj%2AV9NPhrUSAU#B0NY4Gq5+UI*N68
+lZhMTSN+Tfmd2Zl9F6M4ar"-,QIRd2-jHQ$mRRbRPJm!0@PGlBK,KYkNRjbcX1)Y
+SU1qGPR9V)kl6pmrC#HD'*Q6QphBY+Bak`lQD[f,a!&VRr&jfc&2bp-9Z3`I"`,+
+$,b$)@Eq!8-S!2i!Hi"dS"GU!DC&f2!DIUjXHZGl`d40k3mrS&IfMPr5$[SMmj%(
+iQ)@4JpN@5!B!IH`80Q3K'M5-rb(m$q*r%IiAilmIrchicq)IVEFArdIMIcVqCq0
+r&[ke69$6P`GK1E4Y&J$kQp!@fbIc-"I$LQKiYJ26"h-pVG@DZpb6aD@%PR+5XNb
+h+-FB)lrfKIG55pi0jcj'8Im[`EmH6#0dCI(IMrm"r!rLIaMr2IM[aIpdr2GC"f5
+a8EkIEr25)-cArN8,I3#IqJ1-1P0`IZ!M8Z&)%13$%J)"J@"!,"cjJ3a"1"`'qK8
+qqN4rc2R'Y3p"Iqq6PbRm()[c[(hhU4)G)SlLM3p3-L5A2J6GiTZFdRK8,&%9!Ua
+MN!"arCr#re(iRiGrc0XCr-r(rdcm(iEr,[bhilm$reRm6m2r,2`IBDE)0[Brhrm
+a)FhDeqB,RDZmX$YI'5kj%U+rrL@E%&!3Ll`jT[J(ek!m)(aj"0BHq!-@0&Kec+'
+HrCaZ-QHEEV*b3AE@E*Nl'PmXC34kKA4qkP2QUY4A8SqPYfjIjB#P$LXG&MUXFpM
+4X0aKRF-bKe81bak@2+ab@15`aQ'*``U("3lV'jBhV'jBh,#CB@R$bSD&69[lX!4
+K"F)#K28(5a'@)D`r@(k`qQ!j`P+%e3H,$pBH,$eBHE$`B0h"XS09"iX1eK`X18`
+!&KaM68,kaRk![)lXM68!'4YE!TB&V!IB%*!!bV%[B#r!QS`P'ANF1c)fC14dl!F
+!!*L$C1lNF[!&H4ej(SX$9JGNFf4ij(HX#eMZX0TKXF0DKf825al@1K%*M+92@rE
+-)1[CaMU(C3kV("BjV(&BiV$#BB($qSEP$DZEXEKKKp1f!Da#@)5`"Q%j`P+%03K
+,%&BJ,%PBMV!#B3(#qS2P"kX2&KqX29KkX2*JiF'kJf8(U`i@(@0G`P+024Tl*YC
+T,0PB$V&1BjR')STP'dXf0PJXdPK8X83M(f#"a[U-j4RE*4CRV-hB)V%bBf('XSa
+p'GXbGQ9Xb[3C134T""A8kE$B*V"E3$L3!%kJD0JVN!"8X)9J-d&D!G@a*cMC"6X
+&&JcX'PJSX%0J+A&,EV"bB09)C"Xi)VCGl,VBG,(R`Yq`p@,2aAD,(4GV*lCIl,K
+B9V()BV[&KSR0&RXYYPVXY0KSXFpLQm8ZLde@fiHa(@)ha'D)[4$E)VC%l)AB#V%
+6BQ[%YSLG%"XKpN&XJpJ&X3PL$m3@L"d3'b$f2farf2f`q4Rl)lB8l"hB9E$RS$5
+$S9KbX1eJTm(ZSZmfpKGp[eN6J)9@ef&@!m"jG)h'QS1G"SX-eKKX--j5!b(%iS+
+0"RX0PL(X,9KCX1KJ)mFqMQdFHc%fG'cQf&La8@-2akD1$4el1&CG,-rB`,&rBr(
+'lSh0'hXhYQlXh0LiX@pMfmEZKqd31aff6@b"@#UaMfQ1J!d-qaFf0'aQf,q`I@(
+h`ZD&[3YE&hBZE&cBYl"YBGI#TS8p#eZ@XDYK0B,*B6Z#Bf(Y`DD$&3QE&0BJV$i
+)j9KkX"Za6S%e#Q!Y+a5`$X2XX%KKMF*bK8d+1a(f+#aAf++`,f'C`MU&93PVNl-
+ZlIN15Z3H")&'UM3R`j&eDd!+3p6G'!4H$6F233+$F4kZl$eBE0Y0KVdKj1,lqUe
+["Cm19"mPQ1TeX#pUKkp'-p@cGH5!9kk@A!G55'jHAmF*F*!!L2RBIYrM"FABa-@
+5Nc38#+-db6)'Vm'RQRD[De2hT9-(4Afj#GaQRT0)X9l00p%4ej8CrAep-K,EVlf
+VIl$ZMP5(F1VA&pd5"CVXJTlH6[TTj,a%jhkG"h8HdIN42'0XbPH8QTVe3lrQPr*
+1VcG8bpHS"U4i%8+XA(K8mm,diGR&ZZSLPr*1TkUEVXZ1eZ@cG$j#qEh+0hNkhU2
+il'CaQCH`[fHlJ6p@+d69TA9E6QIAmq(QVGR$H'[B[S`U-a9$++36-a9IR"MLPEb
+2MR,AD1cjmX(BUZDfC2VQGlBi,I-l&RAJ10U6@D69$Vk8Va1DQ5@5QN-#Rb1aSKj
+6b9fI[[A-1Y(d!p$,23J)QBdFBaJipE&,%#K@bq"6+@dqd[R'P"VHipBZ5N*i$`,
+UmMhh"-A"@[6ae!2h)+$11(!2)LZQdpBpL,Cc*[UG[`F"m6`U+dB5+Y3MZmJN9`Y
+[B6ee-U'c%"r0`V[GG5-!BDTYhB-)1Zh!2BLTPqqj*qS2BZZ1!rF!mYX1h)-)qm`
+$pi#AfrIGil(q[ZP`a)ZifDYiSCF[HDZe+qHqc`2JbYiFZV@b9mQ(rbMr`%II-@m
+P6N8NHX6q*!p1MX'VQ(GTYA"P,$PSj3$e3)6-NJ!C#iajD5m(df9H(,`mFQ-ZVeC
+l-)K,#ia[F!0&G'BB*,*ZD!@#flfK-XTG1ZcE@&Y2"C2dM(c"4CPY!cepJdYDSDN
+[CA4Y2La'jifCrV&+k*AG+'hj'3-p6XEHSPYd,'1k)#RG0@PTc36&CY0(#hkjkT8
+mGpL*EBbQ[hB-)JdcE(,NH9aD,44jc5QYEDe"X93[9Nr!GUq3!!mp[i*kG64UeGV
+&LK)FVEP20-$9QM[HQ69le-Ri`kjT@Ja')P&)CaCRPh[dP@'RQ!*pMCN#hC9e!e(
+%cT1Z)4LFeIN66[0QcKiq-@26C-ad1'Hc6H+bEBd`4JHGPHXT9reDk#$H0LpI+[P
+q"FhFAL9ZV*bCQ6%MbY6"dAa3b*HLk0RZDS2cmU"XPQ6k&LcB9X0SjrC`A211iXQ
+!V5@QhF*9$Y0AZ---5,i[1Yk@c5hH(RDGND"dKQLqHT1m[KI)%Nc#j[SNf$a3jV6
+HhLKDQ+``hd@,5+Bc%QM3+4)[iPfpI,NVUMKr2@fa%Q)H+'41BRfad!QE&438`C9
+0&F#6H`cX-B`@-b[P9DIAPN#Ac2e`!jfZkeek%h-$XU($BDi&!dK,rMil*-%9p'F
+C@jkr!Y6M9SIPG#ZJ"q"SR1J3NaY0@`hX&4Y'K8Pb-K!"+6")C6%j`HF#VE,Pk-!
+@%)J,Jd,0UiEa3136`TUM@ebKq4c6MiYhhK4eUC!!DDDVP&,N06#l&9hJEIUL&9h
+ac%IBZk)VCJ8Aq*A!,lQY36Jf&*!!mef-qmrSl6c(VB44R1[AjVd+BZlq&9f2Jd4
+!e&Cd%EUN"kX@GB*8*AF@1C'p85ia`4#2BNb-5JXDiX)aNb9MAFIZ&,Ndl*D4lm-
+1VH[B`9b5a+4hmIf*'D$3[8+TX3'0!9hA8AFQeEq1jldU2T@[!d2Krp#5[!*[kbL
+A*QYF[6kI,f)$e1'4+J5YeMcdNY'rE8r"jHFiaJ@PhIHlaE9qYip0)#bk#%hS1Q&
+QhH#qci3H*"6YeJ'TcRrN&Hc@-*ecNarXeKi!Y*fp3f(`e+'Y6q,c8k`AD$YU3T5
+6,h,3KUXD0L4(F!GX!2r0(Bjm8MD-krI!F3FmBPZHA&$RQrRFZMlqCfIGX1D[G'Z
+MJF-YIlQ"BrUG%e0Y'kp*Y5fI1pMRp(FAcE(1!%mV@UE2`6Bc[HCTd4e6Tbmd)mj
+Jr,)"B8QTkGr50SR8T[5F$IHBLbkkU2k[lVpkQGQbCF[frpGJHfX8[hlpqPeh(2b
+[pV4f9e+lrq(rPTY[6NLSdhhqL,k$$meF,`%qh&-l1f(dM%cYJ0$h&(C!G$bp!d,
+I`ik&drEF%a5Rlf((!RYQ@[H``'fe[5Ilp#i'I3p'KkRG$V*NDfTRJlk((3Y61a[
+d25bMQpVCS1pK&m28cJCp$cX@TRBLk([`"drYBY$hS%e-lAD3!0A[8lXLj*k,%Va
+h0[J+2NF#f!MK#"8,6aeCJi-iEaV,1TeIK"eNEP8K#h$GqmaBU1[HCmELA2Fq-aC
+91SfCjE$ZJ3`XIR@2H'#CUlc2aLc`G&XU@0BTll-a5e6PI6CQ'DUmcmBX)CEhfCJ
+PZZjpC[44hQGMhQ-Mll-alk@4ppQBKF$b2K[cIKKjRiejIiZmcmDmI8AHCf2HK5,
+[Xc([,C(hf5JZjT6hf5JZYCAhf5JZ+CAhf5JZ(49MRf)[jAdfLXZ8jAdfLJZ6jAd
+fLXYrjAdf+IC5hQH6BLrNI6BT,P59*9iT,JD9r4-T1Rj%FdpaNE'mcbE&jFEb2TX
+8Ppl+qfc-BQTjadH+#ilPI6EQE@Vb2TX8&kc+qfa5l+@mcbE&aEEb2TX8&4ajRdf
++LjrPI6BT,MU@ppQNL4(b2TXdje$HCj0QIq9p0ZRkQdU)X5K9a2-dPbI,qfc5A0i
+Xll0*FqQX[-mQ6Bb4ppQNZ5aB92mdHbC,6p0FZL[[XdPcXE@mcbE0KG6b1SN-F8h
+HCj2Kh-VlE$,XPlc2*X1PVI)qQ`bG9[)qQ`aa3YjRNq'LBAQIMAN(Qkc`cR!"XVc
+2*N2mNrICC,Lm9YjRNq%LBAQI6BD,J'ArAiBi)HqcbI"p4r)qQhELYEc2TTeB+@X
+9fiP0mMkEGQ+"[-qQRA-Pll0TCarPI6EYh(dLll0Tjh*XHCp01aIkb[YXfVRF@Gj
+RdmjHb[YXfSN6mMkEGZ+h[-qQR8Z1jAdflF4XHCq0S4,b2TX1iVLmckD$IC,hfCJ
+hYiP4Yi0pN[ICG,!AmMkE$Z+"[-qQJrjDHCp0"r&-hQI6`BA5mMkE$Li6&Sp'"rX
+Nll2TB*rNI6BGA(iZ'pilb#e%Zmq5fmMlE,,N$')AbE*RmMkE,2&)$+KCcVDmcbE
+,1C(hf@4jP[ICC,NB@pE`C,N!@pjRPL8Hb2[-XX3$m3kE0lV9hp@bji022!qNch%
+k5r5H[h(YMp$0Br4D+NrEp`+Tbb%UA!P8d$chU)Bklf2lAXKh5m5Sm,dEcpq!0H4
+RL8Ali$k0%+L)Bki+jcE4pm!qae`DqAX!QM(h4IiH@#c2f'RGBjlVdp`iQVm(rM1
+e19AIJ`S`YX%dI`mUja&ll[Q"jMhQf3TIl52Uk'2fE8ie,`M45YKAld%aRA,Ak(Y
+38*ZZP+JH&0@Qbb@k"q@Nk9k*lN(aE,TVSRY3CTXE6$haPKG2`QII4S6M*3X#1bX
+4c[P[elHVp[B4Yq,@[%*L'b!BB89[E9R@AXiRYf'!`3(lR$L0!m[#85`apEI"JD,
+!2E1*!eGJ,DkA$3J-$Kc@a!&[QdaJheIIPQk2Gj'Y(kYb4rSbEDhhUD'"+[(0BL8
+F#$DCqp13!%"aAB&qlFkbjXD`p5&H",'P0Par0m1bk"8%bqCjPAEcaa[mA6LJp3(
+$#kG``*bH8bllPIEFf"$H5*(VU44+Bm-*BD6"i%$f,cLJfD1A$!3F$ZMA,#eVjp0
+'YS6*E9B5G64`3$m98Z['DrfDZm$$Uc*bTl5HeRTUdKSL'$i`23&U[h#ZQmp4*',
+h#hpP2(iC[6kErF,jH2#Ia&YjZr1V2CfUZ4U2[XNqY(V9V+@9Pp4eS)llqrH0qTV
+phhYIYHlQ2II2cB'C(Dr$,rGU1V[0`$ab@l2-f5pk(lBCq14Fl&kiV4Ek-fj&lpX
+fJlX5ilBCJ!2hE$0`lQAlTVpPjXqhq,0`J-1d&l82@bfZ6icEDR&AY0A#[VLBEHV
+6AJ3[q)qeBK"SL2Q3!(QipFCmVHEjYEql6raC1)"qb'XVr(0EpAec2[4(RC+i"J5
+bPq*KqmC@IIefGAR6ZAl3qE*Fc9rK&N)Rk`8&mhMU4Ur5Rk&+F#N!il)Gb9I-RK@
+Cd%jh+lXcjF(Tj83TYjJjQJm+qG*%UC+Yl@kAH*@4B%IfUQ%[p(GHZGU[l+c4,-0
+[P#mcX'T9@-[[V'rP@"$kCHH0lPYAqVAKRGR,#`8h#*aF2LcZ6&dajT@'Rkk*0lR
+AKiI-dl`J(`4ZHHL*8FJrjVfF@'rZbTQC'6-Q4XXQ0bE,[[mpQC943N+eG@41Y)l
+d@ZY)(1eFm'4@I9T(-ae"'50hL9[DNAUfZhULda[bY4%hG!EF-0cGDLL4eN%ZV8D
+j1iS6!"PR&[%acShJXC3SBe$+FrdZe&r%aQTb--"aXL"MR'1!-Fk)FE(@HB'`1$G
+"a6Jj"X8i-mE%1$1#a&*L$#ZPl1Si4AKBD&`"$LZjp@%5-#`-5"i,5iRM2FXMB5N
+2)#`ReDBcJX%i-dE"1$-"`3)da"LS-pBAhG)1r!ZbLYJAj%@i&bG*`q-FepH`eL,
+@*BR"D!D*JR&"h1"E%)faVG44JD%J,m'd)$('Xb!VaV)J+m+a1#R'JcJc'Bd)Zm,
+Q&(#VQ&FH$-'VX1PjV)U6kRh*Be5F!ci9%NV6&H&5N!!9Be+3!*AJ86M'-4DG0(Y
+dJT!!&9+,U&4)MU#TR#R0,LHk"KHE8%5U@RB`PB9X`Da#NJ'Z3NU-A[8C%23T*#F
+i9XL1`Db3!"SM@L%eJV9bCS`KjI6DE%8S9qaI!HUUbBh*%Y!VcNSHqFUC%kh,Bf!
+j%5#XC0@R0B,%3QU-LiA8""b,H"%MT--$Nh@Q&qc86*lBlr493krXVGiPM"L8@6F
+@9XHH8Xc1bHl)XPl$Y5kD8b@IFD9PS8%+,5IU1Z1NFTN"1BK,,(!p+Dq3!+4,#a,
++C4A'+UkY!XG5B#969eR)+TGUi@N#U8XAa'"GbNi3SR4"!54+k6(HPl)Mb+mPap"
+CZd(3XjEVS,)m&!AiEq3($+#FEdP!+5mHl9*f00hej,''ZI%[*Ai9!4)HfEaJ[0d
+4[DNPlaV62-QTjF*ckSR0FBMC6LNl*MbPl#+",q9((,k@h'aP8@jDdI9lbFHP*U+
+2bkYS&LkeT+#ja%3UFRP&X5K+5f5C+$F8CU+XDRY,SP%K-j+0JXa!1()C#GpbH8A
+'&DG9QT(RBLkP4[*FFN8-,+C@feI8ZD+djNJ9Y+iS5p5Z1+AFf%6aFRPe(AC&ek4
+qEY2V#VV0(40aEAV$bQ#6krUlcDdTm'&UAFm1ma0&1m`XbGFb!JdP2XSZDr'5A96
+ME9CGHl#j0I8KRpTS8NQEX'N6)SLpB-be%DFhfeXc&S5TNk0B04H%QE'p)*p@Ehl
+GBQ"c'm*9(Gf5r)B'@FHh*,qT$9F3,NQZUjJ0M+YH8*)$bbKAQS@QQPR$Z9*kSQK
+@N!!Z5Di,94@XUbA(1PB6lC)EaZA`1Yk9mQXDE32aUKFd"V1Xe*C"Vj*E9@XVX"H
+V$(ANUe`aVZR9mDpbaB5Z9d("5[kBYYI!`XBG9E@PM)M9-CR3q'Ui@,fKS[09d,'
+52kEe96#bQCrSI8fNV&bb8r1VifAeLUEZed$0aKhM)ea6rmV`@8p[+)!9%!ejjEU
+1Cj84Qpq3!%CXmVJfB[1EiSM0EUJM0VNZMi5j$9)HAP"Lj@&UQAr,,$3PNLLp)L*
+)HL+5f,5'5Q+6kc**2VICUV*3B[-QP4*l`lK8%ZH2YENZPS5j1`Hc*TH%U3@p**r
+AQ)+'BQ+6Qj**(IG+&c4&NcVbP5iBNddUf&I+EJJR$I5Vh9"Qk'Am+`r&Q(K53m"
+bINNqU@"J+EXKS&43X*jGN!"3QMKBZQ*#4+NMBIQ#ZSc5`-,D$FdaV5JTC6LX*YH
+dP!SJ&RKL(41VGdc)+A9NV0ia+DK8m,&k`ELNdN$*jL8e4Pl'bYUm6-SU0F5XA9%
+99LUi@EeJA&UTS1IB"59aTBQKe9Yfb5Ye*+hG-5D`02#dHFR%30FePM+`0[+E+NX
+&AR@#6KYh2ERFNZh**9Cp6bkhE(abQ5ARNdY-V%p4AXQS%bARR6T4@Z6,#ITFYMm
+98Q-$8C!!'KUJA%V*!H85%`Y8R&GY5@5#FMPe&j6,VYUJLVQe0LC'U#K[E-#+9UJ
+ScAQKiTa+KdYZ+*FB`j(Iq8ZC`kE'R#-2pm@[Ub1AkhfKd+IKIhQe@NS'U'0YYRI
+H[R[dDXYF6jNlN!$TE2f1YERH"3N"G@c-c%m'k1[C!rel+Vb[MJfG5aDe$K90)3M
+D61UhDmhKrF2fJXlZpr1i)PmUqAl&kAC,pN@ekTF24c&ea5@AmfcUZ1$CHYFZGQ,
+q2$BGVSj(cNJ+U'0A3ljHakk(j2lr1RB@XVq1#eG9cFc9Fq0j[H(Hi[L[jkBCRhX
+hhRY`j3B$bQcRpr4SPVF%S`lblEaqGM1@q8NGfricViIAkpJe(Y3KLX0iBfdG@Zc
+a"04a`@4R@hfpUPR(*",YVf1hEZ('GI)cGH``aEdiE5@8YJLSA@U#dqGQq[Ec'1j
+Br4b6fHSAa[BhEIF(rlJXU$h('ZkTBdHa0,6[(Le&6I'c(H&B3N!GI%Xa*0rUkbM
+qKA(R&FcLjrpJh'LQYHmJiak[`a[!Z0I0@qMXZfGYE[(qIRJqQ2YB9`mbpkNkpM(
+hU6Vf-IFpGGc$h&YeY*LlHd1e2i#j0rVa)(-IEqapc,e9aclQhLMM!HEHUQ-hFpG
+e6*&hbp`[((PKlVdIM&Zlq1Th('6FBhA`H3)BYeiQGF,VR1C@U1)hlDq-5GHa%aR
+ZC8a6GHaM1R[UZ)ITY1Ui&mNEG6b!j+dkGS1HVX-X%@XKa&)mR@Bb2kp)6%b)VZ-
+j3b[feV&ZD-Aq1UCP*f`BmR9QXjRZjq&[l2XDiQRI'*1iTilYch*&AFGff-bDTUp
+JSVHkba-#qRU)-`4FHMFRhep(#cPhceN`(jG2MYRA[KQ4lh!#BfC&kZ10apm&9@P
+-KDTqS3VefXZYqZJ&U'0P+3J-)%B$b&JG'Z[TDpYHRGbSKPk!IKLec`Y3Ke2l*Z[
+BVrCY#mXPdlXZVZ2&Qf$YbUDA)(ld@pV5dpkdbI`i2HZ#hr6HQRBfhiXVj`1E2SA
+mGkGRREFf2HfGEED1Ch'+a[ZaGmj%CEQSqXbm)V%B)*USBe02cM'YUbIVf0X2Sl*
+i!HE9U#aHJ$Vi,*berEZ[TJip(QhrRBqcr)Sl54P80TY,!2$TkRITf)QIT,G(*%m
+i(eEf[IXCEFTqEXBQ2m0K[!"eV&P4@pk+rfre&9EUVr!X6Rj9,T4m)4IkpRb%A1M
+EmqS2m)SC,R3)2d$J69je[`0REerp%mSeRh#UrqfVU301G@Jq@KD[YU16hcaHNpp
+qTZ0AmRJGqMa,(Up,Uj2XY09A(i(,@h[&$RdH%+pB!d!Hm)U0)E8[`#Z@Am&8[b5
+E2-(F24A-e!Z!R(i&T0VlY4EPH%!d(Br,TTc*cd1JaIL"0Z8FqMa,Qh,fDc(e3V`
+%'hGfIV*aCqIRhpUidl,rYde0U[$rlf0`rSdp![FbVdBG$c+[mBEFalaDGAJRpL2
+XCele3[`#HaCX(4G1cKP&k0F)@P)`FBmIJ"'B1V`5HarmDCXiec5!VA0p&+Xjr&p
+e@446!j[AmHaKdKI[Z'(0YVe1L[&S%fF[hQ8ZHjh8TKZR)[r'e+DEPU8Z1H)d@iI
+RDa0R'DGVQcL,11dhhm6T4@$ZIL#ApL4cja2QVLiiFPN#!(2h5fhL2$6h$fXC0R&
+ZUG`#9@P-KDTqS3VeLA9@II3#e&(Ha&QZSlCaX+L+'GA3#p!2SrCj!HS)0R&1e,&
+Il62Ejpk@DfcL9"HQ[SfihX5TeYe@0HY6epjpifIAT#irR@#L0h(1VL$rUY5eAjq
+I@[G$h"GYRa[[apij+frL,0G4fm4CV+1mLI1KIKL9a3X`VdCPm3,8`9IBa2P3Add
+Gm5E1KqTiH+@cLI2KD-qE1!r@mA#)C"1Rf3F6IACjM1rRfl`d#216@1*"q*6j2jb
+fl2-8qQ!q(+jV1XlUi2rXV"[@r*9ZE65)V*DjJ@2kR406E4Z[5E8YRc[Bjr4h&mf
+acJ"2+eUQcc'T-fibjY9h6*fqd)`iJhfD221PR1k0LYb4RV2K(M-q2Kk&p9RGIr@
+bEI(J2iQhmRER9hXk9A-e(Rf6I@MeUPP,+bqTkd!GprI['r8eqlrh[QVGcA[ZRjX
+$-cYH4dIb#dHSI5N3HU@Ipq@Efj,TQprCiV6-leM8JH0S6fC45k*+rc0Ecm),&fr
+rZ6%RQA)30RAHc0BPf(R6IU`a,f0QhPf9fAVf*i`jrQH%9jejbDkLMXIr#$)[fRE
+RfDMJFDeBXb*eTKqdeGaXc*ZrUQVd,IP-,DM03`G5UY0P5Rih$Y1V0@c!5Yhf'X3
+#0&1[af%JcVb&cS58[I3,M6Z2(83XEHp%fESZcVck+TBAC0k0`jSimq6I)GCZ1i!
+fG9bFq9+D+6TY*[Y'j-iE[S6BY(TQ1mABZA(QJL-4Qe(26&-,PGjm%P2C0Yefl5@
+0ITji-Q+K2hp6imjVIS$BSRTLkSj'2ppr&f+,lCeX@T6HA2)BBXb1l3!#T[6cQQX
+3'l+C+!*bjafh)"D!C2U44Mq[B'a*K"hDY6Bi"p(jj6!JGXJ%kTR@[6`*GAE-,BH
+4Cbr)h)4SpmF4dTRErHe65ciGQ)8l3C8i8h&@C!D1Z3qa8fdUfheNEYjq2Q,JJUe
+Q9Z21mcq'f12VQFG44jDjH384K58JpXlE'M2`[LX3@fjRMETNEYl)rJ5H[4648Hl
+md0X3@f8cIl-a0fqP%RbklGT)ScGhpL"fIMeaN!#EGD5IXlL*k#Pf#N&ZZI-kS'c
+EQf`rhpASjq9%SUIDDXL8hR36"cEEL6)Afm`q6RZJqJj4Qj-lAd5m#A6PSHmfq[R
+aKBKT-l"Q&hT2ePCLqqTb1,)Gfmr&QqB!Up4*j@U!QFPRDPar&"3TjH9kJp#NMq"
+dA9Q[F`(iJ'-AHDC`0FbN60$VJ4"SjJ'UR!1d1r8"K-i3%JPkDlc4H([ZfLB5"CR
+RI4(9I,TC6B$iI0h[DL*4F1G'90*,4[*SS9Gmjp!0GR,6Fbj'6$-SQ8*d,CRF'i'
+GE9I@-dGjMjhFp0R%0&L*qFiJcj!!+A`('FfEkjR([SFA2cYi!L@ANQHic(!'G#@
+pC$S1Td8ad91SqF2&Vi"jZe26%@5H"hNi4pIZcCU1@'AT[V3j(F'GQfj&qipTBRY
+mTpkk&[DQ8!dBda9eZR2DKi!*X#Ich3"eZ(Y0R(N5J%40UfHZ[3bYhaTPCMrj+$,
+Re$1r#*jl`XAaRCRr4qD4&YY"Z8amjqI14LE-c(B!C*`IhrRNcb06hfZr(NEXj(D
+q%M1NAQicB@kciX`Rh)c-HIA-iiRkYm9eI[$6b03F@qk%ejd5hrR)Eb"cJFh%9Mm
+c[[2,$b066k@&kHXZ`H'MmChU8iJYY(FqYh(RYH$MLXKN[Rj1iG,icUGr"TNpp@T
+H#6c-a+L5hB)T9+qbdr'HaR6FfSr-J*RfRdGfB+[C#)44PTRfIkr4cp@()M0JTMh
+N3BI&QG213@E!6)I1Y"`Lqm#Gb!bBD3qCTFcD@8!Q44CJ[Y2*YGiECmi!qe2(eI[
+jkZXiNlDDflq-@-"QRm4TH'HFH42BRl*XpKLS'M)Gf8I"i4@jQ+RQ0EF$9Ha%GID
+FL`5`fRbjecB`UK2)ULclZ`bGl9S9Cji#VUBXqh[5jJC'I36SUZVZ5,8851)`UKH
+9+-X,-m3+QF+2JD)TZp@dRbU!aDMXJjJZ4GCS-d0Hf(NbBSV-c(`$4#["U&AX@V!
+PiX3[@)cU2!SST+a$IiK)*$0p-QGJV@8al%18k9Mf8@5HCEN+H'%a+[Y"SV(e'R$
+RKJC'h3NqVHSfSlEMhY[!U$QS@4%Ac(FeX&d`U[0dSTHZ6UB$eFNKZ'DrDX"b)K$
+1BP6fDq"8LR@Ell&J*DkI@iNh+%+fdkpVB03MhSI-Ff`eGeQ-kP`$VU-@fcZ[Emc
+DQ8"-YF6@q5@,8GRV`"i9')Ep9S1V#dCeRJN'V6M*PK1aGG*L9'F*h%CC&H#%YcH
+QihLS0-UU!#qr[i&4XmNl!K9J!@IBBP6f6XbhXLV!GH"%`U1b[`*l9&B&@!1Q)"M
+9H43QAGAAKUNCd,S%Sl+hI`i*`@S[44b3!#Rmm%05e@`(8-3%Sfkp(TQ"FT!!CLp
+NEVDKYmVZC&c!6JY'c5FV#aD-,!$IGaLe"Ja0fIeqA83%QHNP`&YPpmKNL2mb(DH
+#Mb[V2H`&mML-HJZkV+abf881,KMeQ@mL-r#YGAfJ`46H"!9+fDf('pSE21Vc[d"
+QS*fQbCEXG(3H6FBBZ+DlS*%i(RAq6j%CU+Spl)$YCrC5GKVfE,k&l+I&U1`Q6+5
+bIUQ&TcCie"Y3Xb)EY0A!j'6@MZ-8"SV[!,XN'28"U+,+1JqA!RNF4Qe$Pj@eKhd
+(ka)HGIGhN!!CZ#GlU$l+G,`-+Sd#ca2ddUcABG4dG&QY01Cr!*!$)#!03eFa-5"
+3FQpUC@0dF`#3%[IA!*!$i3'3!!*b!iF!N!-4!*!$KJ!"U18!N!-@!!![H`!!!J$
+rN!3$!,#$ZID`JlX)!*!&!r1h!*!&!APUrr$rq!#3"[bX$C!$0MKVT8aTBR*KFRN
+ZZ5kj!*!3G0B!N"![#`!!3hN!!#m,rj!%68e38N0A588"!+YZchk`'-Mj!!""!J!
+!)e`!!!ZT!!!(jCKeMGB!N!D&K3l!VCPCfU#Adq`k(mr0SZAPZP"1[iZfF[HTVFc
+M0$Q98cFG*-pc%hTikXNmfDe[I,AMjaA,h#c+Ml$ERN8jZAhQGA3IXb+FE!Ql1LP
+2XXNqNr"1`[B4(YYNRfQAq8Qf%8iii4hKQE&Y%Nliff3&[VUqHZXm0l0EQDeXRad
+l`Vrc#+IEc&mNr!$)"ZJ%!Y"[3J!B!(ciL`#cmCqKa'*6XUlr#6l"%iYCXqk`al%
+Tr*ilXh,*jI@qMV!FAQDreS3[A#jhSl0eIMA$',(B(r%GCf2`jK8!4b`%U$*9dS2
+$!6j*F3ia!Sb1a5SY$cr$X3c%XZkkJ'-fa+#pPQ1()'CGG4r(LLP'f`-F'dA[6LM
+M@!(&qfSAamBJaR)QF'`XaEMQ&a`EKhm6@2!f!X`$)NhQY[M,XB!*!f8JdS1h[mG
+-(41b'#%!B"%rGD4)TQaASj%p8HE3KBZ2&q2H`RTBYZN6fm-8c%Bf$()3BQ`T+J@
+CYI0QP*EZ*,AKSV1HR$Z2BT8rQZd0KAh"b#+ljfdG@IPMk`qr[U5jqZ4QPlY*-[,
++b1HMC'KK*-M!5TcaIc0U0)j,j'K528Z8L!-$1**DC--9F)@m+"63Sd-ac)+2343
+q#eqbZEYN6C(+T&28S2+L)Q-Dj@95RGS9e06Jcc6**AZ3!*5UkFN'6mSD131a$aM
+!b+1-RIkDll+#5X6EmBlVL-2Mkh-IZ@lBGm8[q#kZK3M&G@&PUH,jVqZfAIDpqRX
+&!Dk,Db(QF0drDJbVaN9rehDXr)Pefcjkb,$VaVlJZU3@BJlIVAM0GhQ'ePV%ke2
+rj6j@rQ6IjL-['2EGa&fq5fJKjR$ImYIFCc-8MhK#rmjmV2bTGG[UcaPfhrKGlM1
+d%+Ki,qTpahY2L`HmCfJK32&HEPc[L-rrP[PBq60p0lN1(IEHK%([k9S)85VYCCT
+IlIcr5MYf@GA8kD+!5MZKK3$&GpPB@(AkSmUlAG3+k,ZZV&F3d%90DL&#m9ddk&[
+UplhE4f89$20GK5$!GdNY4"bq+`8,cB3NAc%k"%h3Vh3Z[46Jq"Kpr!P0-'4EA'T
+3pUJTLPDB!L2B*Y2+a(f(#HP#ibS!-m'frG&"&q-ref#3!(J6J8`qB('Q,r4fFK#
+QR&2QZk@kUJ99p-ph+C'`HSB5AU**GI,TXY3dU9%kLTAfAm&+&meTDC!!'QZlB,,
+84,Hj*40al15NDh&+k-F&%qZJ8fTT3$U&D-FfNpP8R6'Hf&Rk!3)6%4K(ScL83J$
+1jSPQqbhc-"aX#G#)$GX+,0[4U359X-rMZ09,#96@PNKi2bcKlDh04@aVLaRrL6F
+!kbG"hZ1##SG4@E&+Rq8Cd+qhN!$dLfZSiqYUmEkD,35@k3M)(NIl3PEfK4#-(Vf
+3!!mIBD*MCEdp-'V93c"qkS0GXFIQi2Z9-,V!#N8rH!SHDUp%["p'AGR0bYC2jVc
++HLp1m#lVVHI[-3i8MD5D)K[a'iK2l,C2pm,$V)dldR69R8Cmc+'ShqEIqM(1rAV
+mhS*D-*QK+(FeXL"1"9b2S[aZeJ8MEPi1Rb,m&Rb*SIR-8ZbQMEq%"fjGE@K!4V$
+"eXG@`pC(!EBq83Zr(iYCBM+1RI(hI9K!hF#k`66'JH923j28&!f&e($%8D[)AL@
+X15"hA3AVRN"m'0[8A-V12`)p8V13!&eidKc%h@a6'fPRaEm*mAE)[E5(G8X5BRI
+L2k6M8apK&jli)1%82hEEQXq`YAqi"2&%JF)fY4b0H!m(4khGM2KXa2XS[Skh68D
+mAqG6I)N4r`ELJhH+4r%IdZ1[Z4raj4cRmFqrciLI`(8p@l#B36iKp()hX&%1KdX
+0+c8q[k**apJVl181dBS(-"GD(4ie%*)M$Q&,,X3jbK["8U!R`jQ9*dVe[Z!5*Eb
+Mc-Jd)VMGcMp(5*pa9@jhr3I96M[qUd)K[aL!KmY92cFG*`p(AUAj!DS352UABVM
+Fp6@#!"kY6QSp#3"dE@aUh%R`G4l8Z-U`Gh4j0+d8f,CZX08PadQY'cKQQb[lrDS
+DP'S9Il`9`Llq2)GBdqdmXa-2dliZQXh9+MRrccPYfU!lG"jQZfID0#%!M`blCkm
+JVr,Bf`&k9GG3LXJV2*5PS5hIA+RlpDTlH19#H1&G5',CPG#SR-REEYB6U2X"E-Z
+h#["p2pYbE6ZlF(4&dUq*TZ"EHK3NH!`eb(+4Ke[@2,*rYl#kVL&C%`A`m+586HY
++T5[aX"#22CRS)!q6IDL1XL!2XQcUk$bd[ARDJM*8D3'HTq02Gq6TNjd0qqZB!JT
+5-e6*H&920-dMIDMq#221Z!L!KpEPldM(bA0Ale-9H85LJJ!HG-afG-PlZVV*LqQ
+D2Ad%)"8j5[p5M$FUmN%H`S#+['&Z(I@BKr4`Z9[6HSJq+[YGUVj4f3raH+@bhmr
+M3'@rApF$PAfDall+RSj4fE0c#pY&!*Ap6Mf'+rY"B9q[l0-m$P6f1fQm@GN2m4!
+(92CQZkCd[Zplm8G&MVZ(ASVa4N@qL`FG38"&hZS,PTG*5bYR[Pf4CrqcSN+LHc2
+(`BTUL-FVPG"q23j83QNH"c2p6Kj[C[SK(KRfSDaS44kB'2DAlQBl6RLQ-YP!af+
+h3iL(fV%iaD1KBh'D4lEV2f-H#G&G6RePer[RjBaS4E@i8rIa`!cN6p@D)iQ(ApB
+dbBNc36J9pEckFFGMVD!X%J,SqN(0NDc&KfVkJcc5Q6AYXf4'M+4XpVH6`dG%hmY
+"HEbl+3HrJefV`5lALbICjEUh*p(G&!,`F2Se$6!$BAiCj*'&Y3)AINqIRRFPK3"
+km'kL%)"([*ZBiR'`QjKTliS%r&HlG4lREF(Ajl%l%#mkVC6eE!V"*,BKY2RUPDc
+[1%Sfa3$j3AbrNQh`hXCkISAaiM`@SiYfkr'bci`ZMLqdakmCf-**mk!CD+"4mIG
+pclXi3J#rmLk1%)!((BX3)*r4-3X"r%&ba%Il6DIrGFKrH+A"FiDJ(ej-c2&@K5)
+31@3%mBX(%UF)-VNIk%mhRSKi-X+jB[dP4r-J5`q4H(mM[XM)DIEiTf1MFPmcD2!
+FEaaaJ*c2FJQ`ZpRGTPX)ZJBE4f0f6E98iQ5a,QZqUl80&G@RkhG21!`F'be8*C2
+Sbd(BAFmZD)hR'`(3D@[6)R)iY4p@J($)aS@dZB1RaHIH8Uj-*X[[Jf@6%%4a9X4
+A$SYTcVFTbkGA&P-YSXmX-Zcqd*m@Rjb-1`c%"mBGU),qY#)Cl(a"N!$Tq69"Hil
+*KV'`bf9m`TG6@1*XQ&GG)TA-UfUZ`UYl[V1j4,4L!CZq!54qRP[1ETVLKU-Sfah
+'ESH-d!,H%Cm8#Z-3`J5`ec490f2%bjUD'ir!qpHfmc$hmqBqVcUFa8"EN`S*#ed
+#4q0e0Q'0,9L[!r#*fEDI!ifTi'JCCQ-[I"aR)[K!3+J+F&r!b&l#ZXcJ3ia[A6P
+V)bc$e5Y6HHbeX!Dai`JEQ3Qi$@Ad0B5&li(,%IX4BE11K'mJpKZ1M3)XkXCQ%hE
+5lq#(!-ImP,!9Tm,YL0e0@&5&H`!U@JNEf`%2)RBDB611JDF41j[crLl$6639&a'
+fH$P$I@HF5YLCKc2d`ic2%AEfPfP,bSb[%2DKm@`@`,(R%MDpL&8MKLj$99D`"BK
+Y*'cQVjQ-E3`qaA$FeaRU2@XYB92'-*bNFr!faV((Xe@)RF@0YTN@R-hQ-6jb$Z#
+Z+XEhjKqkNYk0j%[UmpeKGE(LL8MSAmfR"Qeah1A62(Pm3LJaGj*$-f41eDZFS!4
+(*1I*q$-MV,%,FhVBT`6NS+ADkiZSBA10'ScN'r15F6*a[&81"hh"6Xh'1kN'MEb
+i#Y9,)f&CbhG'YBJDN!"19*DGSBDpQUh+ie&`)-BY4lSd5l-FlP3LYVP4RppV"-a
+Hi-3P5NSN'XUK5A4$X`,#j[Ndl!dVJ3l8B%4b6*h(LE2A"kcL5KP`A#L,XmD&`A*
+Sk8bF''(2%NYZT-NL#-IpH$b$S%eII)$k"4@r$E[e#Dlr!`!!$3$VX9lc'QeDjQh
+fDGmCjE5hD#FrQqQeCJ2#k8$#2(j'f%@1%caI6rTiTQm%Rr6)bXL)(4R`)jb-'6P
+1MK01KS`FLa`R$"mCm#182#I(Rl!MM($##6pbP$$b,)m`bI(c#2H58-)*Hm+12#1
+-X#2(J!!DZ'D%%NkHPRLf!P$m@FF*NMJ!%`qm!JdkMm9908N)#H([1N)fh54Nmf,
+-B[Ml"2lqL+qA5*M8emBd1DkQ-NT5N40eRE+8N!!emMSK(hr3mJPj!dM1#`12N!$
+kK6e5['iJRL5K#kICEaIChpA6F$CH6BHFPMA&`R6HF[Yla5`Hp&MGSfTbAEZ5P,2
+EkL)34Y,VYJ!mXip8QBcX&`UEQY36X[i,U"`LBH0mD2JQeCHqUQRP(2f)UK2bQk*
+fN3@%e$D3!(EmS`kK(Q'8)%l2rJmKPQ@&aNamq'mUpR[CrVCB@1#8U-PRL4j2GUY
+5SPG0biha4a6`9JN@-&aV-UR'jeQm`PNXYPK%KUAd2!QbDBj&b'*4Bl&SkphRN5#
+YA!ZE463pjV1Sj9VBLVC(8JQ2aZk+,qLbm9KJJ`BXZY++lV&iKV0BlV$3C@dd8f+
+bTD*&0#HdD1!XPPSXHP9G'6c-H@bSl+kBP&DmhI9La4Ilj+`kUX9,2RfYiSYq06l
+LqH+&#SX"*HA[LfFV,0j0+cQ2KA-GcE23PD6(iRmc,($j&&P8DI+3!*c,q+[B4#k
+aU)B@VGR$DFrQ&'k1KEh664E"SB-A&9VXPE,qbX&cF1HdS&I+AL8YDI2V$fm[ei*
+k0$)LP69elQ&Ad3JSq*X,Kh$!)T9Sl43XD$SJ@(4e#aC29PMd("!XRJVFC5BArMC
+'Q['B"Ee5+)YS,U20dpM$@5`#LcC*piA!fmaC9)&&q6$'@bEF&4f6dri&5%LcF&F
+d*mG(KDK14Z6kSRbNildU2%U2p&l*2lc@#(Geb)%V#&NS&1f8XX-"$5H"FYh9U@4
+e94`B6V,QqU)VRC!!FhdI(CURdF*Cd&[(M"h%'EL5XeK)@I59c8Aq,hCA9epPBD`
+0&1dVRmEN1H(dEL8GR&dXpA5GhJfR#iZ50`-YN!!Q"PSm,9Md5)SI!Z)K9IAF9Bk
+'m&E2XCLqX1NqciUYdmDeS$XpF"CpEiQY%j1dE(#qe3JYBL0$C5hU1!Zkdf0U9XR
+ekpipqRc!3T1cXMEQLET4l)ZB9JjN#'d@Z#aSQJJaPI53!1r8YrQqS"kP`CYR#Vb
+)8,4b&m"!`ZR[5B%5N!"qKS@6V$J88fJk$0+L3f0#j94f2@4K1cfVDqQiP*AM+@q
+6ETeMBEYV@CZ#'JJp4b0UKZreE9b,DRUNq`6-YjfcU'R[ceM&$jp'SkI&D"*,A3m
+1p4fFaA,D4QQ6Xb1kQZNC+MRHDDBm9*5b-#XY[KK0rhM8r+b'd`Ie)(Zfd&fRVf"
+D4(1k*Me@C+H$Dk@f)LNfMRep+A4d)2Vq!*d!dd39b6#`,M28bpLc$*9RZ2R`cYm
+Y9$U"`Jb9*jc!QQ5SNdJSLkKZSTPI-2UYMBS*%XNLUTYJ'RrqX-I@&4-N5TD(r!6
++1(laTSf+#4)N%e8N6R$1GHDKkdL-6&54-)(K,FEe&M)-aT9R(Q$SS'+#HjLjJGr
+2B(LEFEf0Dj&ajGHPFHlF1cBU*VM)'#Uri)al8adf+LDi`*Mcq-8'EjpL,Mq&I*@
+KmMc@q2,XpcCA6*!!iM2RmG3IcVR#2(3&,3rcZK5Y%12Bq(i(GA`r@KdcU)m-N3m
+hMcNlVhN-R5S69A5``2!JihS3ZCqTUmJ*iEFmFeiH594KSj55+qcL+ED9Tp#'-e&
+&Hmii2KPb0XTN#-fUSK[F*KBmN!"JENJJRf+kmMc,Q1KU#"daZ@+#M*NTa$0Tk,,
+%4X8%UDH*+P*5E*pa#j91N!"bX[h+8e%ijbmE&41deBTZF0YYaVPIepS+BB,f51'
+b+E90M&pqEV94-8(6UFM9E8BC&cipDD0LJYkBL5TkCXC%kSEM[030j'CX+r1F$Aj
+EbTbh&!NAmbY2a)aMhfb`86&"%l+SUpZFa%DBB,YK!Zd1Y[0i'`3-9c'ZUj!!3KI
+fDbQe"YC'KVS4q9p"ee*H#+ae$(8GfS1QVU*YL,drk+#1$k)99h5$fk,$9Y@F2G5
+X)89QEZ#T-h4Cca4DMcDJb9@d"k(,!DE3!I3CL`Ujr8GJ(@+SKmM@&M-G%4NDX0B
+`e$9N@i[*9@4Q*mr@G&LSG%+f@kJL)jY&EE4345BfLlV$iHTPB,1S,eQS)[1D4@f
+b&I)cVPR8R4DU5+0Q8AICZm&26Sd6AqQfAc&"ciPG0V`ACC`iFYj"2A)Hl@lE$9i
+E2"rHIFICHE[[S)GGh&jZR4(l8@@E8N9,HHCLHh6T'5H1jKf&MZE4Q@,lPAHXN!#
+jh(2ZSB[hd*-YAJ"ZVpDiIqN2'a86G1J+f8DTFiIlmbkl41qL'mC3HCF-@0FBkM8
+dB4JUEmiB2ehrcPB)%c3mf(A)H`E)icTY9%c316"448F"ZYaR#Ye(&j!!h9km1`K
+GcM#&cU#&a9"jD`YA8"1lKjV3TLpQ0Qll(TG*MYdS1I45f8h*Hkcjm#lLk)UD3D5
+`+ARA![[a+YZ89p(3+H3ST8D2-IAC'cBU*QMa&K,L8N-@ZS5C3Q(56Lqfe1IrCZ%
+@+Tf%kf-*c0(+VQf)G@Ia[d#B[m%UApN*ljq1Y5HcdlLdl4q1pFY$$ak`(q%h)8*
+r3j[3r`%!!!d0$cBiDk96D@e`E'98Bf`ZZ3#3%!E$!*!3,hX!!&&h!!![#rq3"%e
+08&*$9dP&!3#VEXprX!1PB!!!-k-!!!I`!!!+Y3!!!YN"qhUm!*!'L-m0`+hAQEh
+-NjQYl19'`fq@C02M0&[CZQQhfDClhB`FmeUCPmQTR%US9alKCi5H'Cl6NpfDcr&
+Aj@qfbDCF3VH%pHPHb@h@a3CZBj&pNLhKX51FFX)PYpRAJ"&+'1'a66E,cCj`XMh
+###HFF,,2kpKQ(D'FENBifICNNld#Ar8eF,000VZYlmPAYXq,59MN0M[#pT-Y18k
+HK5FEH$f"!23kH`!'!*CQJ*RiVl9&)S9Thpq26c!L%AhD#qBB9XLrXqH8,R[-kHd
+)qN5AafIHUF%h$VF8FLjbI8,*G!Vp5r41U,)Sb+a[PY)RCVSRJYrMS`R'45+PZQ0
+riTJ@XE6$AqDB!6&SVZ,BH-6dDelPf%6+dA58BcRdEQ%*aib8EeXlabBJaM,c16D
+*FMcp%XIbm&m$1[c+J"5UK'K-ifAapp#""K0T%3RMecpc$SF'@@5S!,#)468TNZS
+f"cT$&l+8d8G+p#2kAFr#,&hcqC0jc+#2)U-k'iBb@8$(X*2%i%L%84#8Vha5E0`
+)-#p#2rk%0%cAf30qYbF`c&82KC!!`ISdAI([SH"XU&d"#d%UViY9hU#+3+fTP-4
+YLaa#GIRLF[V2YSXK+A#h+#f6K@VhFVIJR&SRh-`X[BmcbjePpE9#A98l6"1Fp$@
+rB-TFB,IZa1DqccLP'YU%qPUNNiY&Z%T6`3jUJl!+Y$GX`$H6m$q21LM92F!AHAF
+imD8[a(iNB)C8Z!-BXmkHaZTbYc,TU`13!2I,PhLra0*QdN0'',pT0daqjR[YNEI
+,Q,3HHIeL,BcIfS2jeL*Z!92RGLCYr"E[!G*$TRKRN!$@lk2hP!GbIdfUT#0H4R`
+LchqP"ika*Uk'jXNASrQaIf$rf[Zk$r1d4r1(Ud#6!VQ[l8!@a#R-pFMpeAE@$KR
+eqf!0i6rZBP+Xh8DHqml,V1JR[+YL[Yh8-CRjf#[-XVq4@CiVCM0cd#P0H6LUP`$
+Ta@@X(eLkY8hdLj,ABch8LNqeERQCJ0q6ihVfZdbX[ci&rq0[!"kG#PQr8kRS-K'
+-0BS01DlI*KIT&p03`4pjLrAhk0N5B+R@$VI(fV#DP@`1`VKa5q*pS+3R$$PV"Z$
+'SMGi(bMCh!AMM(S`rHL2-0$3L(J[j'cYCL@26Z1m5RTiI8@a'[iHmi"T,$R(G-4
+h%jr6I8$*2pJ(5MBI8I,h'(NI-)eCLbb)Nj(VBFVZTMl`dp9`2q%(mH@*2J"($f(
+Ai2QS%!c3rrCDr#q'rYm#[$QT&bhTNZMl,C!!$VYC0fJQ@1eZ6ke6F(B'J`%TC+d
+5hDfL*&YKc$GQXqjmiX0BRm[#(VJ*Dk4b#9YhDaRL$YEA40T4hp%JhJaM0SCCYb!
+JpL,q"a@mk#ffEY(MK&2qb22hV@F2rQB$iR&RaIVULa%2Fc$R`Ef)cd9m#q9Am+C
+TL2FUI#CZL1EI6Ac`Qr*4rJ%Prhe(%&r0FClrJ9HMqH1iSQFpF$l"jP+UJ8P$09$
+MEC(FNPH8V@SU0C!!0e3$L-CDJ9T+$D![e&XpJBkJ1f49Er'&hF"bV&Cl3")V[6j
+4&MjPRQfH&EF%+LPp!%H"ci,1U$6$1D@h#$9Hrc+4bZTNT%Bc1"bf[f9)4Pkj`e(
+cXH[&F5Z8"i-qG3!HGR[0r'5H,,4'`U)1FJJNrCNFGNG0T8S!M`EE!R8!AHZFG@F
+*AZ(KUQKdDFdYl4jCYJ$lI6FBUJFRS[SR1'DBlrEj!J'r8#AkBQ0"p[!Q$M(RchK
+A)aiDXfH%Vm(H)0KQfUC22eFG#Sm8XfIkG&8!(PUcCd53!!piM%a$2p!e1%cN-Jp
+a4I$!GlZ8HRhb&HlH#-mpM#4@EZ@*D'kXAdK6-'!(GKMaI5mlX,1CV4XhHl"HP4@
+!$r8`aRNNKX9MN!#(`belh,lc`LUk"Yfb@J!2cl#b59h*YK%2(I'id)P'H@M-#4q
+P3ajeiUU4(!S2HD42ke#'FVQ$pqRBdcrhk8CEl88IBk3NP3NRdaV`G#Cj*)2mKb4
+,#G0`LBIFlQY*jXPb9,bV+[))GDS%m+")-@19I+5VJfSakGQ6S3,Lb&(k-cQZ1[*
+c2&3$((RYr'VD08MSBAFd*293qh$flkKkeGNRH&afpKGjA(,f&h@pj1b62#ilHrD
+Ph'Be!'Gr9Spr1rYc`PjapNNHPjcp@4VAR(f#4p,CDj1f2UkV,,CGVh[e$dH1kl0
+RFPaej1r`S&!*F130A[qX%Q&&kCcr1I,dIcNU*$V518BG9B,(C5Gd8Bp,6LM*Bl6
+6Rq9aVG-RH'M0LDkS4alB'#jDpa5ccc[FcNj-,-jA#2%)Y#`GjP(EXM6*)phqiCT
+(A(5l6GNk[al[G83pUX8Vp9dHf)&m`ejc,2(`Z@9CX1&H&'i%$DNIUhMd#Z+GUJ#
+kIZ`j"Vei`Y12mNKfeQ5G$AE%d(#C[4qCI&hkSak8aDHEE[m2F'TeEXVeeaLFF[d
+m(*pZUJ,`X2PN'E!$BAmjab-0[3)ArX+FRNmP93(di00%93!HX@RL-)r4D@+UZ6h
+8iA[+SI#ip`#q[THpJ,MT,JX,p`@KL'dV+(fULfhj($@ELAKE`ir[ZpLfr$dXr"V
+QLr&BLP9dASrhkL`kaI%',p3V6A'521JH!0$CK1YeckFiUJ$ebUFiUJ!m+(5U!2f
+-)N89S$j)MYMY$-hbIpcEb+acVa5U!qeq1H$rMm0!KS`q0-ckAiHL)K*8#1S[04!
+2%k6bHU"rqZ+0L$FMh+e@AR)d#p)31Ci$RS8dp1,+R5!"$`8*K6KL[[N+IFUVl29
+NlQJmIFrP@Xc$L0Gj'1V`B-mA#(XD"dF6q&D,pXMTT+9iE8'40G[Hd)55+#[9jcF
+FMSF"Y,`SP-)!GPMClalU0bT!dG3NKr$SP,U$"&6'ZA6&KPIlUEI8+`HEj4l3pDQ
+#+-j-r'U@1NhXSLkI[,T&AN6a0JbG$Ih6!Ca'Z[@JHP#iaeh3f5YIG#0,`lrH$id
+"Fq'8+rT6IBRF!P[YJSS#S@""ZDXF2af,E+i#YC85-2#T36a1h4GNU`H#-mKP6fC
+pS!NZjK2a[+#%5`Mjm%QRUqiQc,MT"*f8AMl8jfjM@6IF5%9'Q2dJ&12RA-)qZ`9
+p1J$IP(@*31XTZ&+'bf4@`,YMM*mZ$1d([0E#EL0Xc'1!aq3BAbeCkS6PL$e#@1S
+m`'l)MK&feal!LbPDRX2iGIJDBQX)#ab&Eb1fKE#UJl!GTa2l#2-e`$0iTBPICCP
+q#2BLaR1BASG$!!9dD4#Nfq&Pa2JQ@r8Gm#CLI%YibJ$m!6%AB@0h-G5kN!$I+Ta
+Db[!UBL(A,(mZ`bXYK9b26rq3!1(L3K(I5PPi$rX-BRb-fANr`cG&I!4B8mHFU!4
+ILTQhLpd18%b,AC!!pJ4V!jL44CLY&QrK`3cPp0CHZX`hNqHiSBX`pJCKf3iTX&6
+dK!5X9GNEm"YLZ0dVHl,i0P"mab56pX9XJ9CaSHM2'0`GimqLDE1M'j!!XC3a[-%
+YqEhq0PPAdHS0"D58bS!rC1"cdQMLV"M[LK8Kb5eRfcVP8+"$Z%9FHAG!DT80j4k
+2L1XZ$RHSAGDjh&+E'$,-lr6k@U-*daIEm%55'1S-CY+HH93P)f%,[$*1IX@1&Y3
+MBh!*RHH*X9I@Tf+U4H'iD,C+1bE,T*-b-@+%R53fH'mQM5"FjZ2jSJ30bPN$e-m
+[qJ`iLipcr6m!#J!plGD6HZb-8-+HV13CH6alFSbXl!R&Xb1-8%)**60kC'9+EL9
+XPATNY50--Q2V5I'%VE,$8ra&9LpfK"%DBB3H18CSj"JC8h+-c0L6!C-F*EFQqC@
+`)d0fC-D1(#1h4ZD-M#Jj4LKj4SiG'6"bM"`ME!9Zd"&+D**RbXM+E'@2ChEN'8%
+1!b$i!`lV5J$0YNf%%!II)`L&EX2h2Xbbm1f$lcdNS,1)4h%aVjQ5@YC0m`-`f1(
+C[q$I3$a2H3Fa,f&2kp)*+DFlGUfUk3jBpVAJaq05"m+,+KHPY&'U&UZ'lV6'lR!
+29Pq-,5C[[@*RdrN[MfZ@%6VpNM(rm*Ef!qqjad-Ifp5Cmr,qG)1,FK`rq$DfN4i
+lcF*!bR*02fJCh$qIjF9R6mQ@d510`Fid#q'*DlVPIX&pT4jPe,4pAG&RrP'28@T
+r`VEFUQefEEHSabNeT1K@E5FJ5J@5%%B4P#40iM[`C#+kQTRA(9I@ZJlXp,2rMN@
+8@@4+9hk+L)'&8Y4fipMEXaLJ&Z195XSbHL+i3BQ&m"SFr0DM&K&Sb+'4dDZbDC4
+ql)A(T9PX@4bJ@AM0)eHl&RXfXr!EQqU)S*!!8AmR3Gm*faENhMieP5P-b51M&f5
+SfZm@(VGMFAKm8NdPLr&KimcSp-R%MNkSCa&6LQiCX%#AI*PYMh$(JU-@JiUDPR)
+ebc9QG,bUhf+0H&cFQV[l9&prr*kE9l,T**l!%T)e$"UK)FcHT93m33*e$EDZVKS
+*jJS6k#655N'(0IKKMC[26dcPm36DJe#$YPPTT9Dj18c&%fK43JeDGf9TITP4BB*
+#00HJ"qUUZ-$0d9c&"45Qe'$[kqY2+S`+%hJY%'V`ZPKjG1S35`JQm&+K@rlVCG2
+Jcke4+TkJ#%dSk*6kQiFePK#Hc-E@S01Jqi9`0ZfiT'4Z[VX%K6i*ph,CT1PX2"A
+1ijqXUPpZYre,m+lRirJ1EZrr!!d!#8*eD@aN)&4ME'98Bf`ZZ3#3%#8F!*!33hN
+!!)3!N!-[#rq3"%&38%aKF'ad)3#[M5YCVkGYX!!!BLm!N!Bb'3#3"0ZT!*!)9Z`
+1`)qRR'Ei#i"qD&MCjqARf6IbXh0NqINHGj!!Smj@jRGHCckRJ`C0[0lY`!BfY*R
+A'h,-CQPR#,#hJBeYCZm"(""!VPpfCCqRQh8,Ej!!4@BJHC!!c##CE!,a"-#"66`
+m%424JFZ)*Z2PKA2QAIc4R"j,DH"JH$Yl42f1T%L2!iN(NpGMrL&8Zhp98A&qG(4
+HX5"[EUbmFY53!0'Yi8TqIikTqDj[0,LEmdcT#S`(`K((fGKLYlKYM--X$mjR'ML
+D-RXG1Sqb1VJmdIQ`1b02[b1SrU1YU8FL*qcYVArH3er1kE'FKbIL$Xe[0QGqc0A
+8BNaLZY#@S@RIRdYP[cQKPEBPb1#$Z3[HlDdr@NST5bCEDfQ(*@e(9!dBA4SYVbU
+*9KB@983VmXU,bLUMXE+biU+m@'94D8RRk0c5UZM-USV+k05LFPK&*4@9XH,LD$r
+N+"J9jXXLNPNMUdSU!++mY'TDB63@V5JS,bUSL*C1MHBAaBT,Tb'f0&T3NKqY+S[
+1,UUd+DD%l9P@(#Z*6LdYYhfD&Bf1,L`SL4E-+FLVUN6kbX+#-%'@8L1bqQG&ak-
+@HE'5NY,+RfSfYEadCTM2e55DR9p8#95E5JPd0RpB5jZpD&25388Pq3APJ!RmdG)
+bQkiL'LX[k+@Lbk*M#f198E4*1%pk48F9&K3A9h51$LZD8Kjc95k2pLqY,,5jqTA
+R&4C9&Z499L&j0,GdGN&jlS$1dGekc+M*-US3f2*Ya+K+e#D[1KEIL0,+JQLAk1b
+#D(jTe*BkVkUm[+#NXRKZ['8'$"Uq@ippE'P4KBV5**S5C!MVE6ZR0!(HiKf%!J,
+LL0+5,R$9S"b3!-$@fI8"%XdU++p!r@h[SLHMD,&B!NZd`N'0T`M4frN`Zl4NKmV
+SY),+X#9$I$@IDkKS98Pa389&Q$#[X,5d!VdD`SNhCU`BD!TMX`TXm9bPE8PXU8Y
+3Z+NS6B9Y24Z1cV")-AQSBEJ@%+@66jQ`)mR4CmFq8@1m(H)4GMC'kC)q[BQ[@!I
+IahKja(jQI9G[&RAeZ[9HHXePJpUhkM,B4R6VIIQ&eK[0-ZY[@$iYfY@,pXiV+kR
+XpkRCd'E`dQ[D(0ZqeG#q8p1'AQXf6*0CR1Qecc*IM6KJ40@)rBLk4XB[kYTl4-l
+S)8!lrr*@(5C()e26bV`qG-@M"hES'VRLe1MSD0T6Pe2MeRfTFGcA(,lQBaCeV4q
+G[15![HD2cZP3BMC8)aTaTaNpP+CeXXKLCF@9AAYAj*99PV@q[*0&0kdZiL*GHpZ
+DPY(PRDliDP`1-PBQ-##ZZFeUi`H0c"i8GX6m)30'Y!dpCpSikkM9,cGh@"J#Yif
+3!2P%+GJmjN5*&Q355aU*T&"+LP"D'P0QICSIE80pqrDMk,Vjmc12SljT4e-dC3&
+&T5pPFT3b*C-b8p)S-bf&STP#ID0-mr[+%63rj8LQY)(!-6L&dXDP88Tq*RNVJ*2
+YTJ2F&Vm(ZpCbSRPVX-kX)cEVb6-EU*E4P)(PTT8amrXBXhbH-@Z`l+c$Zal["V`
+D-3Da'MNf)0Ik@SMhN!#(N3rfI2L"`H,BJ(FpeAT[(AN2!#F$Vm8I(b,i-RlFYYE
+C!9,pC@a1N!#"1Y'Q"1Y@[P'$))-L+fX5V+196m#C5'$$N5qC)"kH5"#'Kr%ZJ3h
+Iq&Sb34MqQJ0J%aL$m0A,N`MdkJd)Md35#6DZA)A`jFN%'eCQ2)&`LQad#6*Sq8U
+%NdXB@8AV)[L)(%,8%3PXH"L2F+5diF[$H&YQQ`$K6fb)KiG93IM+H(KB-S5[6)6
+6aR8fI(Nbr,80@m*AVkS*Ya@X#EF9I'0$G6KP,&qe,Q0P-YbfK%hbB`0AKbHk,[R
+ejIRTIHY%@fIf6eZEX[M)Nr[eE4eYNcQ`mE(Y-YY(@r5Pq6`rBhQV0Ah@c9Z2ZD1
+0Q@Ikk&BE@Uh[Xkl2QKE,`d&Lh`b(bD#RV$H5%B*FYhb9lFZ-5#5F#@EGUR"BE(a
+MBcJN0QDXYUA,X'f'(JhlliPeb*@"&N4US(TLJdfpF9ASTJfV3MH'8,+Qm9UDq(*
+XPrIi9Uc8Ie,Ch"p$#p5YRZKB,P)TYGjam2MMeT!!KlA$[N6eZB3fb#hH&D'pfV[
+#TGZ[cD"B4IkBIU1LhE1kGl0[1U*5l!l#319KU5"5m2'-1%"X5#Q)h)j5&3bC(JE
+9`Ej4+i$4Z"[jPE&bV-h&44@9#Gm`q"69)YiRc*C*DDRB@cfcN@U6(m$dZe&UFG%
+8R"3XfYV%-m05#J84#UJH+@c-bpaaBQl@(EEFU9L0lFB8)4A!c(3!bXVb3MXA0`+
+%KM!me#XpJPdD-"$r"aJ+-(l!h-N-B0E[4QN9KA%Jm#"A##A$38(4U8k%kP"p5VG
+3-#9'f4`*,&Mdc2GSahS"c'Jh5XGG#DH3!($&Yl@0qm0V#r`+U8*FYG!0p50!eB!
+bE+9(&Fh%*FV1S$L`HJ$f(D)E"M"r"'C,93-X,&J$"`cY4BdLe-J#X`Al#9K$!&Z
+2Hd+6!'B),$aIE!)@qUZ"0AE!!R4A8cbf%bS+riLV#A"p5mh-0`&-fe8iGB5J3Nm
+)4e%cKd@K0jY(U$RDa`ml#X&a(1BEZkfQiQe",48-+ADccRaY[Q,c0BD%qFUQD)Q
+h&889M(!NeD8'jNYU(F#`9FdV,-LE89CDK+Z3!"e,cTpVr@idY5BH'QDYEli3mi9
+&&-AEKYSU'#'LKY6BI%lE"c#DGk-)'UkmXUbmG$VZBR&[V[-U(#A$ZMDN4RBcahB
+[e"CSfP&l"81+%0X%jGk"1LJBhT!!H%Nr-jqD6hcc'6A1LKA-ULc&YP"5KBi*ekb
+6U4-q0TqL0ZB6fc3G%M-jPcS+G35)6V5MJL(PBCL2)fdA"3-pXeei+-Sb(b[+5J"
+1-ap49r1K$l0a9XAFLY,LdPLq"CPB*@,S&89G5HbK&B2II%$GI"JTrY5LiJ*&h9b
+CX593p`Ke4rG%HVRlp*M+SZ)+#e,-KlC&FC05e)@i0,kb[4qBpkPf0pUZ+Nb%6$[
+LhFQmTfJRNTa`[Z65cV5,JK&@1B0bD&HKAC&Q0pTG`8LC%)CeT4l8dlaVeLSiC%r
+8)J-cUKIYS@")-@iY'@M%hZBG4Ee*5X+F$@P2fN["i1jf-k+'jQhI[)fk&KH86&1
+dPbY8"SE"@i&jkem$K-dlYX*l92IpQjjjdiEdG0hB$!AZ3hd9$(5IpEFcDkLIH51
+!fDBEC4a899!q&iYRI0Z,"``U,Fpa!8,p82VqjR9&r9ejQP0VmeTJAYZfFSPjhEB
+J0Qp&IDZlEh9J9[qVU',HYEfleVERlRJ(d%!&)kaR0c460Je5--*kGU0HjPADfl`
+5`,6M-9bRA58UiYl4cLZd0m!-0LmV%!E#QR5RhFa,JARThc9jf9Ed&9[43G89I6%
+`,e,$EP3Efh0j!Hl8*D&VC1J5'JM!3m`,LSDiUE%RKXP3fXFmEjj6F-KHQ"*lSN1
+'dA!&)i5&#@'H$Fbc@f%T'ZlDI5rUBjlac$1f*[ZipKJ!a`M+86$#[@)!CCZRa6a
+Y8q48PqfT`$celk)rEa[a19[j&bb%A4`%l'"Q9@"@ECkNjMhEVqhajTSR&DCSFQ0
+k`UaNmi4&JL19Q#IYH4Q4'9KDb6H2dlidNNDChp0S'Q-H-iqD4aK"f-RfaDE`X(R
+)2'JH-#[-r@DjZ5m`$fmE1i&jk&p9$Fb$[be5[RPJfbS8Q"8eK3r-r9YEP3dZRfc
+ZXi[T5#bQpk*epJYJeT`G8QNrK0k$TKJE`2cM35'9aL,"hGMqa`8`rh)U5+9a5()
+APSVa!FarhJ"5D6`5hSN9I8)!mjqlI5T03-)lX(T2$'$qFfG2TBP)H$Xe0lF&-2q
+bM+HDfq`m'%@5BQieYhMQ9YXaYq"kJSR!k4J+Y6,0cG6"h'4ZT%Qd[lR"KrZA4I8
+Q1f4ZY!0NNMAfaa5jRVUEkmbejKTcYER+A1NM`1f5[VPZf`iDQ'YV1Ydhem4AYF"
+FrHrP+6"ArED8"1E+VG1MMVQ"pZfdjXfZdb-NfFrQ2&#AqNqa&l&h1Nr(4D*"*qZ
+N'6[5GYPj0JcpA*J6"M'#8V0Ic(PN1VFJ0Ae@GIbBM(3DBmpX9p!"'-+6'3i-pJ1
+Ucf`(#Kf)b"K086$#Qi%pCH94[S)4,PefU&p1"HDb!'E,EU5Ub[*MP3@*@DV'K1l
+i-"8U!*bTjP*&8kXhN!"PJ9N@6S6#dTN&CE(+3ZI*K8I-TED$,l0eb8r8TC!!TJP
+0!j!!3LT5-1+R"SqQ%kjCdpe#C#I(*CkjK&M4M'UX&`IQiV$*A)I0LK8RA2[&3'F
+V!UTLQUPJK"H!&"5XK%S9$'rIm(b46f9d%*8VQ')C(`%1,4@%HdZ&+ir#PD9+U!T
+!CY&X"51mG#LXiaI4(,28KaQI@2QPHG86+c0qkCMM,Kf+kTNP00H(NH+lb,RZKT+
+"%mI"jN*&"j2NK4H#ZR3)(DTJa#m'QHD#`&c`eij5G+KVN!"-h%[2pmhj`*GA13I
+A!a$Ka#beLpYX[)I4i3T'@,c'e-+FCmiejrMQ2"4[q2$FNF0M-`UbbmZ(ii52Srp
+mXS9NFkk&F)k&F$MHHHCX4I-FK*E8eL`fCjNcIE-i$Q&!F8@ZUlrP$53JR'8KJ$)
+MjQcE"CA*5jmjSjBj!`h*Ndp@k%"[C,bM6kIjjM3I*VS+Kqq#m[*SpHafHi"#Kb8
+R`+Q"169FV*!!D@E&Y0!HAM&0c'N@ElRViXlSmb1%MN$PMU5M&)b`LTeTQ$Q&&Y$
+[I*KZ9mM(*6p@-F10)(`1l`+5+5'-2HKS1NE"L2YldV&dR))4pqp1#qPi"52Zhj9
+1S"-9M,KrCcU*&LNBFAphP238"52ZldURdQN+4YJQZ,A4k4%kh9jDlGRHm3R!1!#
+0#&ZfSY0F(h6"&HlN`*bmG8DFi["da8hPM!LGB8qXED,PXD)+F03X13!p8eVHbei
+R!@T4iS+bNeRNQd8B+*LSZ)+Hk1*`36-R"HDN2c@GSZ0GMPeaI6R40bFQFarRiRD
+R(ZB%hjb3!)`laJl"fQLMAR5Q3H1Fk3TPr@G&k#`-ijDM#NZV828Ki-)P9[q`CQ%
+cp,%PBh1mAE9rKleb)5fQXhfB+Ik8bK*-fFAZ@0)EFqdFSA13!1jF1Nr"#((faNR
+Qr!LGMa*ii`[FGC(1`hZ"39GIi*,JDN-A4ZK#E!XbSM6-BF#&5+@c!IKB@Q+1m@'
+Qq2P6Ll%h,(&*"q#8Y$4#5cFK5cA(@(K(iEh)(+hS)RFi'SlCG$&GBRj(ba3FiEP
+a1$Eq5qNb"5-m0`l(VRbj@D$SFRGZY2iVk%S&)c`hjY*SFj4[MV*P"ke5dC@*[,P
+dP6P5d98Z$rcQ#0mFBIZ[SKK,`T'fHaEBVVr-e@dd$K*A4qMU6A96G)REb5CLPlb
+'VP8``P`6DC+Clf(8)m@ee40jAQ$Qr@dR3jf4ETP$&%2YVk2V&B`3%6C6FlKR$MG
+'dIA9L!i,c'(E%"eY%C8k"#PBU@l)S"ZNC9TL'5&q`fjNra(J'c"f5$Ci+H&U&`*
+EE[[$mJZkMTi4lC%9*d&[qUiE'JcU2p#HbP1[Ec#J0,pJE+bm[!LXR5%$Xm'1f6h
+,RF(rcjIkqE8I"DQ@GQJV%@FXerXa5F2K"CAPPSBkSb+k#6'Z"'"eTPk2&pX*pDm
+Z@UrUK*YF0EPlrD9bY6'1,Sp0,A2lZBHpXLF16eAB,bk)j"E'`&[G+6UKY+6Jck9
+-(eSdFiF+ajFG(V1,ljE[PkEbN6XkT'4DBF`KrhIVN!#I0@T!eb%j`l2hlQIl4QJ
+QhKX00ZdEL5f2FbTZ$cFTZXR0RDNdc4`5Q%1fcCe$,BSTH'qQ@a5-j&AdB$1AcF&
+fY-ke+@l"Hb[GTQ#%0jF8F(0ZTcX8M160CBkCE@B&CNji8l,ASj!!ij9I9"jk(H0
+VB&'jQ0PfrCKP*alB,2DQB8pXGp*G#NBi8e-3HMIGBih``*!!JQhlAP1Pk&kh%eM
+rI3Bl`ReZPl$qjA5rJK'Rp`5Q`MF9i5'K"*H4qa0jDp-+!rq+"+lDp)!j50%$ETQ
+'hj64JkE8KpNiUb"@AM&eDRjjpI)HT4MmLKkdc491DM(S0$B(@31PBi-,$"X3F"A
+G8chp5`*6XR@c[5Yj(U+(-ZJKI[dr%ScpiId'M0SmpZIE2UmeT+*`CUc!BIh$f+p
+Bm36'[XfeIkTMh[eIr(,q0Dfqk$YSa-#4YK,aX9rRab4Ue0b+bS+Cd8'Pa5&D4S-
+"25V92&kSATXcp)UAj6mE$2&I@Z6r(q*ZE0q'pf&k4-&)$YbC"UFQi'!$V%+2i(f
+8(P-``S'EKK(hHhTF`8J1h"QddN`2B2kG@E)5B*i`Z%`q86f5#J06q#Y("UM&J1'
+Pk2(U-qH63Nm#c#Tk5X%!ppap6`XpM@c6c06!62Z0[L!'Se2S+Ec2d,-+4[aD@TZ
+HSqF9M$JaUaDpB%#RHX%G&Dhr4AT*`BJh`(BQhq5C+B(*rmI'!3"LF*j5p&+5X@K
+L[SNP6idB$SUHVfk2!`0ci-mAB(S@YAZCAP%``YVjb2dUVEC'#-$(rM%CccmBFDZ
+V!4m3Q!0#`$J-jC9@P95'RJ(@)r3+!,p')$QpjJ#Rim$q"Ue4--)&+"h-U6IT,3A
+$fjdC&pGQCRpkQplaBD,%T91Q+lK$X29!!C`8Q%Rr+-ilVK%EiY5feNa8Y0BY8GE
+rVTQJk&f(hIVISrF9M2"!djLDQ['q'CrNMEh[F&ZL)"JLilB0(6Di*V'CD([a,CF
+e(G4Q%%r'rXUJA92G4Z#[l%G0Ze&33l'"XjSe4+qMQ6kJ$a8-EaabYX60jL-cKN!
+#r-K0ZLa`-ci4qJ5*2UA2&)b`kl*!T9Y(RbXBi3M+`SP`0(eK4J8`rdNdq!*`[M3
+M&AhT6U9G3HVlLVj@--,biE4TpJh-[PXAaDpGRQkJLq3'*MI"c(#G%,VFa"H$5l3
+B,(b+2UpZMCc!j'aMJhf'mRaM4LMkaKheHU)*[UAep"epVq!)MhSpF@lmJ6BS'1%
+XX%I1M3EXX)d1*[aQ@'#'ED-Fi6k[D)1E`U!MQRdm!rDc!Y#`pIU!1UH&0)TK''(
+'Y9iIkXr-SM$E3U!J$CUKJ4RkeiQT3#e0eRe)B)EmI5G",B8p-eLajbiTS+CaLQ)
+FppdTG+$Cfc0lflD#A)qJ+B5hie6&S(VEaKK-qh!Y6P---VI&24M%ZN'"'I3hQKb
+R1@K$D+M*pJa1BF)Jp(*Y-e!aQ0kf'8E3D2D&IB3&(&%FZ'BB3IZbiR3&(NN)!C3
+k-m!c!d!X!58T@IIqJHRrMlU$Zm-CTTpL8,PYh8F#FUCL5(pBC*EjeYFcI9%Fdmm
+@(`F"4Gql-SbP59b(kbUZ3i+4$Im%VXIe&GGc04K,idbI`26CfU2e(FKa00lXj4R
+35a@$q*dShjk"fI2RKFL-X-bf-9XRS),F5`LN0E8a[326qlH9i%0d330ZU,L"+qd
+8+Z"'h&Ka)eHL+C4Rp[!-L+b+`I41P+KAB(VpSm-D!PX6de0aNq50MTXUEZU3!0N
+EA3r2p!!Cf[5dNq8aT'['c48hUli0l'jfBl1lABefXh1U1Gi@h&+"24AH"L+8`Dd
+iUVK9p@eJ9fjYGJR-V[r,SZA@J06'l+bi6A9eG`V-6Z(D"3fSa'("qK*R"E1cR3L
+irLVS[VJ,JGc,EB9"kZEYZChLlDY,f0edBi2eN!!0MU(#S(YcHpj"-4LCa8k,aR6
+P$Q`J[KAK$U#V0iRfUjJ4M8dTVDU-cVED$JQP)0#A,B)Gm(EN6SSl*SMEbQ6aMYc
+C0eQr%'%BP'V,ed!TZ)[TSKMmkrMjME-LR!A'H0Y35b,H`"9@J#J82STCeNDm#((
+54KGFCENc1"5GZ5Z$"0ij3GTJd-1,F3F3UXAGcBi+Qh&)iV$qRB6"jZDGH4I&S((
+(ZH+mDi4h45ZR1XdT9q4Gm1l'Zb[H,DRC`$dLh!-,IZfN*T9,"5Sbpc5SEmmNLi"
+l4EJALT!!B[@Q`L`'Gd`f1pUUG8291[)HTS0[1LDB(aaRDUG4EHiGiGieZ9-0P*@
+%3D2R2AN[aAXQ,K(eZ!rh9Bb1X"YK1YAKIJD0$9kfZdc8iIim3$(SfIBkN!!"MPG
+lhl42d$`B@iZ0XhYq1pqd5p)kGV"cC4-l'`S$fiG6h!k$bY+`#jecG'R)VKIH#l8
+Cb0Q+3@bfFkFqQ1TY64Xf8$eLdmD@,a[[)0jEm5!hGfb+eMbB$B6K)P"fDdh00Xd
+Gbp'*E9,jFTd'RMB2iD'+KlM*8aq-mbM[`m0m%reemS!&E5F2j#aiZ'QP1%k8Y[i
+4%4k"Hd+(F2*JNFL$HKD)#RmH29D(*6jq@YP'(SC'EXNjR1ZEPXRaNq2'6d0Ua[Z
+D&SVhGH2(qNF+Md3&4r&SaD15c(`H%q%af1eUaH@rA+P(ipf2abVHcb9U4)ejA)6
+(@@U0*Hf'5FEL(@q`XBah5D#D`4-L2'(,j'PZ#pE#&L`A"@['%de6hc4,6Tk*,RG
+cDX'6)MaTbq4TDQ'#N!$1qr-"bKk%E@1eS4ei-KqSH,+E2'fS(FG-%m@JKGV*Bre
+61%ma++Gf`V5&YN"Mhc416Kk`6QdFa#a-)pmd5NkH*REb31F[-ANJ,Y+3!0+k8BS
+G"EB5S+Cb2KFScRGcTJ2i[`e-I6B0E)hVfa3B&6b9TbQHkZD-69'2#pQ!kK,K`Kr
+RM'-b@pNf4e&fI38q+4IaG-9&lL$6JBlM'9aXk[*-KA9,F)e!6%mZi9)&pCV`$Y'
+"ZR!C(k4`Q3hVei%kQMU"UE1TISS2FVh@N6TcHB6,IqakKF3KPQkd+eF`'J8mdX6
+G#@S`8+RCK#A1KZa1Zh"9K+YUqPCaX5YFEcU#Cr&XNm&c&-pbi(T62jl,"bZHkm#
+"aQE5!j2qkiKAI(##cpDA$iR`)6rY3BTRZe9d)-Ai81&$d81(mH'+ilc4J664+*l
+(mhh3XhkCeI2FV"j)Hr-4"UFAm#i6rL00S2K)9`MV2bV#4d&iSp[!2`rVDY'rZ(4
+IXPca'4jB!aTDUD"NH-ER"3`U*lSS2XK"fl5$I$#0iU00EF9(Zd&ZrFF)Jh[)ar*
+aLSpejE"RU)84AKMZN5&b0dU1`hXmRk!Bj%DE"c)-I'+%6h6lC[A)!FQ66c)iBjf
+8Z#cYbiXL['M,+!F*L`dfk&5fI-9DI,**p8fYj#Jr18R$ie-LI-U@8CjUBB++bkH
+Dl45IkNEj*$6VDAbkiY2F+*m%j[FC"ZHh-p`SYricq5c&i&EDNEdr66DHEl!0adI
+j@5l1%[$&0b$ba%Fjq#1+6kmHj4cJU'K[5[QPm8N,MfX!-H!FL)%iPq)jESD!F-Z
+,K4HM@QIc1BT"PV3c**m1J3V8ZAbH$c,(,c2NA$FcmQNDRkmaGXk[pPqJYH)i1G2
+k,ic`K6KUp[crCNLdI9bLdJd6VDf"UU6bHH6TMEb%PrTkBh+B,(($T*!!+[JL[8(
+a4@kB@2r&`L"ZmL@m6$%BkVBZK65$,ih`TAmB*L!qmQ9mZH)ihh)'PI!9%ElL$m-
+%4%qq8[qJq%UATi31iUXLI0AQBD*rX#@$A&`U,dA*[ZHVpAHqrMij6+jfZ5YT0Pm
+6i@Xf$a2pRB8*3LaIUpFV[YB0Nd24YGIapBU[Fm2N8*V(0qK[&GrJKSRehmJh+3C
+RcJk0`fLHrXEAZ(V(K`RBFcEZ8$T-IqhVVa2$4(pV4d-eT90r&HL[IKiQHVdG*R9
+Y4R$dE&N@B(ZlQ@p4I,1Vk!)kKQq0m+eEZN[a,G8![`cdPcm$j1NSqfemZf+3!)R
+X%VU3!"EU,r6RV+(5a2TcfaQhilf$le3-QTeG3Qf+GA`ADdM%4ILZ(ipX@i4$A3Z
+$MmGhmcf+lhDEh%*kMqrPqr4R[&`ab(K@@()KhFIhm`V&)0NjrfAm!$qSq!%hE4E
+5)Rj)IkVi)FFRXIk(p5H+3AkbQk$e2m+2+Rl%94lXFreaS$rH['BqkTVQH$U*(i[
+`Bc9MJ$9NReK$!%VaJ`lbUA3arejrT2Mh$V,e2kir92bifjUYIb8rS4M%+&Z#8qN
+XIT*A+Al5P3!%G[e"S$riE4N&!FS@j63kNjq+m&0EMRH+Rh$JcU%,q@Pq4[(6$Y`
+jG+jq2p$[r`EZ'3IZA,U!Rih`XeXUEY@Mp%F@C*c*H#AGaFrTpa5$2@8VE2h2m`Z
++RhG&Z*+ZiaIj*F8[ZL*F59ITG`2plPr(Lq)i6qSUZTCIM[$,@fDlBT!!XLbX'qN
+fIS9I9Ib+Jh8MhD6A"RVY9PJJ5&PB0p'Y[$V#UlG8&4)pLZpcZpF+HS0I%`EIL9r
+R0a5rlRD[&I5bISIAm*ZqIZIAh@Z0fl9@J%rjPRjE-HK%&VMe[ahKYlIZkjY8F80
+Ka&#XX'E&HYZZ+U"CkEIi(9lVklH5feA)Pr,"kAZDhp9[+RlAE9I@rjl`HkMNqrb
+"BY#KE#8HTXIi``KrD%pTbARl!Gk2q'2&)#,C*)r45[iN`TrB%mhQ`I`ahNre'X@
+IZN3VD49r&Z(2YZa@9Ya83fmVPGHLB'r`1[fkVpp)lPC3B,1jRk(RqI-)IljPYl)
+5@3ak'AqKAe--lT*YX&I3P9rb9iT"BE+le5[d'RqY9b[qfZe@e[m0BpIkaZe3Vp*
+VqP9I[jVFVEjeFDr3UrS9Alq5h+e@fpD2mk$Xk[0bS&qQG)MEj*G#LXHD+,hSefa
+92l1j3&Zh"AN,#mPkrNiak%1fPQr4@[iq`Yrrf$#+[k['pP+JArSM0Vi(YIk"X49
+EEK15[Nr[kaIe#kaIY&d%J5RK$AJh-MEhMG8TRYI2XEC#90S+86')5i`$K',M"YE
+lA+bI&4EapE1r$#``N!"#8YMl2&%m59(L*IcMC6Y*93+LNI12N9U5TU4@`Vq[e"C
+I5Hf%IlJ%%P%#VT!!m`m4*HP+9-+I,4Q5U53MiHmRGD5Z%T!!H*ar6kNRpCA85rK
+l5J0TU!6-'1II94T*Bb@0%[lZdN5D+QQ5m(H4CY*F#HJVcYp4@NK,*H#U12m1dNU
+L5L")k2aYTE@d83)'L[1hNVDb[4+3!%LF[jQdNrC+`"KarLDbJh43![k(mcH3!)k
+#rS(3Rr2AN4fPXa,32*aI54I*JT(`"p*9ZLN"3F2jDdPhf8P*pi6INjeP&b8lare
+NC&IC63NNpTcr"pPGHLJ"hm,j[j@HdNX*&1fFrd[C3hSVf52KrdcfP,d8eU9`3,e
+2(dQIL23"BE2"b)*BrYcUeD1USUKNQK-`NEM@hNIdUAl'emmNa%B%@RefarL-[T!
+![[TT"G(P-!rmqLPI2aA2`pT+UNN["rP,qNEk4D5I&IUd%Yd*BNY)T&%#kT%GbGr
+5phU9VeF"3Q9X#U##FQ,MIL#YRr6eNmNiU+cC1-1LRr$e%mQiRF)ipMK9Vr6ebQ3
+Fj""YA#hfpH0iNR&CBHNXX8hr2Y#rrqpe@%+j4KrdUdcTVap6iY6qV&mrkZY(Ni@
+(lUZ56Q(K38kV,`-L-J#-K,Ufm#!m9A-ViY@(@U5Y6J0ZV"rap52*kV4hq*T`8re
+`S"qZ18C)5'[b`G*U+32e3dS'ZPc`k`Gpr@#b&JrCC#"8f9UdiMD5(C(X4#f'&CA
+-X1dq%l)8aI&DJ%9PDp'@fqX(I2e!XKBY(EiGZ)0H%HJ92brA!PkBV8Y(lLb$p2d
++ejJ`,rakZDqA*qYb[`AVq'IFKE[*hK(F$0)T,Hb4@'@m'Z#jf@TdjehdIEkq,eN
+0L,$EZ&fjKllAerFQim$QXh%pZEHqapIh*10!kE0aHh*IIEH[F8L+ai&LD12km8"
+pPkr[5XD"`@MMXRQ`[Y2AGbEM)&YViiE`-(f(Vqp)a[NZEMMRkYYpIAXb$[a+'lF
+[MpDhqIUfC&bULa[$ir5Y[Vie'3IeAYXpihQ#$0Dh+(%UM0D[E`ldc6pYM+`K!jF
+US'lTQf5)$2Ae6BP6J'$cXeJQFElXSfp8XNpi#JMp`d5'390pZ)a3iJK!#*XX14%
+SBH$)-L"@NJHe!EZqb`LmZIS'*ENZcf5H)[Y'"-+$N!$0!*R),X-hf-d6FR+T-K5
+&Z&j'kZYmEIAM`K9I4VV-"9`SSb)bUMTcUVl13V6[D"QMC(4ii11CI,MX*f2eYIS
+D*IZ&4al%9-Si'DpNA,Md`emQ%r695LD%5hrSRbL6&%LJB@H9F*QqbYGA*CCqQH6
+LCR+*[Y,A9bDArU[YQ('N)C!!9LTNriMX[k8(P)`05C-mQ`q@!j4!#-lfd@bHUkm
+3$@didGID"VM'eR%-hXPbS"*,#-)D2SrRkF[eCD`[YbNJf#B#k6L*b43Pi!KCJBP
+jI*6N#8BRZ%!@f$`q3PmU'JT[5L$ZPVJB,![dXT!!DcTcES))#9H#"iNp6k4!TLS
+"k`Gh9P!i&ZK,C"VV5h"RP@R3YQd9(BA*#e9YHdk+#bdR&+bcXV,#T8m%A#%TP#)
+PKDiC&q"Z-&eQk)[e43TDZrD`"faR5,(-9,E#YMNAm(&5)U8+R4L1+p"(p0*!,re
+YRA*53r`l2PE+)P,f4ak0i'aYmCh!TmK"8Ui%T#',l`3q85m*p*,Im%'Vaq)lN8q
+@LSL!0lU*&L33[m1*MaIc4UN850D*9-NX*9@ZkS[j$TNYFr5&qJ)Pd(fc99r-9mK
+F19J*&1GX94EcqA+)(+V%+Fc"IlBq2p$REel6R+SFU"[Rb@%41H`20#H"@Th&XS5
+AbH%b6mRK$JXi%rUm3*qh'FXmKf8TAb,c)rK*JXheK%#H(5CAmbebK"bTm,-$G[@
+(rbBj5KBS1FS"ZjU[dHF'qYbYNd3*f$jfSPl$0mV[j'JP[h1CVq8Ep6Q"2ZI2FYi
+#4T!!cA%05""R"rVXEBaG*@!Y*@EDiN![rYY-dj!!hQ0pJCe+)'c*-A+XNQ0FIpl
+*VmTaXP#ITFp8!Q+4lFmlqA%jANj3FVcVU6[j2MP46P,L"0IJ[dZI%HJc0[H8iaL
+"Mh#[,)V)SNfF3L8J)PNF+rJ419P183*1NF@aJKr3T`Ikp-diR$)F1!F2bkN41A9
+,Ed)Sb[EQNrbLR#DR+`($b2EQNrbmR#%Si"N1'+lrqV4!RlDY0mpd[EQ+Rj1cC,%
+5F)jXjUG`Gcmed)"GSp8Z%'fcdD[i+Ae+S#(0YkdVU`P+qZ4!RlbY+b&&b0T+%3V
+NqZ4X[8M*fDiV9f1BRL2RkT2dL8T!LE&GZCSrNI2NI#@3!)1chE5Dhj3,j%)P)"l
+CiUcQer3*J6jKkd(K3YGCVr%D@4+4*6q5!!4m*J[V(Ij!PJT@P+81&XlLq[K!(lm
+9&QK(&YCDIPmZMXM&@aS@T#REX1[i1lP%PLQ"F*YYf(AmV9`UPbQje)&FajrVKB&
+HZ+eK,h-0qcPr)jI,&8SZGjQri'rdFB%qlQG4Hi%JRFhc15lIa`Ekf&pEGePekai
+6k'1fYHj*YR92Y"[V)QYFE0dAf8k'`+GF+9FTXB*hN!!"`+H2PUYC3a-Z)PH(,*e
+0ff0)4SM'LIYZEl`+lc9bV4))`')@!-!GFTeFVhqRXAb!"@9P+`4Ah4X%T`L`S0#
+dm0H5Qq4Q*8iV$(j2(aASShlEkaaj#4IU9,NP)VIm5(Q4'adi(bIQ@q8f*EFkF,i
+%qNJm[i'lcB%,*&eZMmMY@qB#L&FBV0*3EN&e"B`QZ92Z8S,lN!!YH8-FCHq@Hr3
+4HVi5U)ECNMI%SIKHZ8m*L%Uf+JeaQ&iZZ)Y"*Fa@TD%dd[-#2@rc-R'rUd%MD5S
+V)J)Tj8e,#G6',)k@1&!r)!mUHF$KD#QYp1'"2R`cMJFGMPE54Kk+b%0EDJQU!@D
+FG-+Pq@&j4!QB8*Kam(HA4`A(6E#G,,"1XU-q,0"10r![-`jU%CKaZ(KhNpr,idS
+J5Q`cGjCZqY"!(rSr2eXJN!"hXMPa0GH("2U3!&rRACbMCHIG`B%qH0Zm1m)11+L
+ALGb&Gk8mS34X+e`YT)Idd(2e(0C3PQ102jN4!99+RY5cPH$-E0Zj"lTmP6bPCqN
+U*DYF1rI!NHeTH8B*P+CX'rE!AIeCH8l*Xkjq2D5RVJ`dC%)fYH&cVJel5Qpj2L,
+2rh3$J2L8aG*AXZ8&H9(*#`j,AqQR+`*GX4N,U&-@5cmC+#p&j+8Y,If8'dr$-'4
+I&S%ZP,`LVbS"`mA@FjM-P0AbQLlA"bPClHSj62DAeq80*G!MXM8B*[[+'RP6L9-
+cJRqi,JYdfGBekNeAMq'5+fp&j+drE'IJlPKBSf@m[#h[+((b6r#2dD@",Yd+kad
+(D`aZIQXMXRC,QChqP"`S4I+Z[+F%'P"fFKdSdq4pq8#*dhU#2kC,!PfbEA+"kQ3
+R9dbQbSIbNC)2AHBT-PA2$26-rrRT"J&,bZE%48mA"lViemN&GDV%j*S4k"RE*TG
+G2c8%r84HaIZaI+,NBpI'*E*)2TA2p(50)ae%S@`EPmJm@5HI+eRRqUe%+Z3,q9,
+*&kii1-lT`N!AEZfh,efrP8UjI"@4VhlNJmVR$YBXh,ZqPQq81"%Sq'IVDB'HYK8
+@'&J@eQ`j@,k0b,GEfKKD6lD0Mm64CVemTf5pDq-MFGMjARj3mVd$HD3FTDF'HZU
+f0JCCbVEa8A+XE*!!M8UJl'3c,j!!Bh9"S![qjkFXa)P(!F-#R4rSr&rEH"12+br
+3HG[D'0*eV+f)R8$(5l6'e9Hl0MiC3aVNF4h61"C$B-UfmFQbe!2e4hRJBGPq1eR
+1m$`[4AR3Jl,&`49+6`ldj*pS!-Tc'P&bLTcZE4IaYYY%k&1H1$5,jA`[eDZP2*!
+!$bbDaEMG("$S!rk%"J*5&XhCFTkA&[(50[FYIM!Tl0Y,j"U[YZFVcj'qi,r+#lb
+)mJ)($iF6[AqJprpEhhV3IE*pZdbZp*5AVMa)5GR-PmU9HP+J*rhmEaUHdjG#hN[
+ea%"2r+9A26!c%Vdk)G!6Y[9Uc2BUrSP*Y#fRKMBSDfKSLVC5S4TbZkbKm#X#LVH
+Ai@8U$q`eZdVH+AIUmASFkr%f"F6Fa-[%@mHVUl`k)A-!+HlfkLR2D9,"HjFH'qL
+aIkZ&Klp'mHVVrC4Ahf'm"fH&-ASdkc%@ifKE%2bKMc"qVF0VS%FT$mbiZ-U4(UR
+hC3ha0GD3!'BA$3@f6*S-VN@Zep"Vj$AfQRK0@HFLbQY)+6T(Mp$$pE"!jra$25l
+3)hi613cdm,q,qHYKreD$5[FDiDm'p$k8ViIU)9icVlNH(-$ppaUPDdLdT1Lp[4D
+HhKXr4q#e!1GF$`VdS*q&&$A8UM+pCL#ZC1Z"HN#JXrqD+G!$YiVB"RV!Rh5m-lh
+Q8+Zj3IIArA4Ih8I[TII8[I8H%#)r3d1B@rH%B[D&ZJFYeE[VhI5ZHKHkZTEZlm6
+FIGd[,R([kljaK8KIppNQNZrV[EDTd2Ykcfd#mi(ZrDIk#@T&2NVP5&Xq#ZE)46k
++jYJpRYiG(VhE0PUTVhH0Xfem90MaFHVS`93d)rZ'R$9ekB$ke2,0NNj[,AQl[If
+0Jj5F6V#f#kh8dV(8Cjcp"CF2PV6lX0hMl5l#qhLlMpYpmZPRaE0LP"QM1M'U'k&
+k1C1TIS`DG)j"4kJ&T8h2[Q%mE9H8IF1BR+8C'HPHBcY-GUBlp%kkZpI5Dk@l"A$
+rTYLTGl,c%kbK6!rX0pded&hr1KSb2DLHd8-k5hIaY9AqqPQeepGGiRV!G65Q)+S
+IG%5GqDh1fGIM[a1m*VC1RHPa[D2Zj%@peVTM!2GrMp4d$CTTLZlJYI%dQ)6T(YK
+qT(F)p!kr5+YUe#86[jq6UY[VGRTlh9DhdDd$hAjEcN#hfcSDYrqV5PkJfriUHaI
+S0PX&p!,GHUYdBDEAQY*d9,I5,A8,h9`hddeeNd"(IqYTAlH+cp*!Yrcl,flS&R(
+C8PmhM`Z*qYUU4FdScF-mEBSqcbXY,mJVU5bSl[0-p`-FZXNr9T8kZL-9GCS1)E3
+hff-5VXLq-@I*a,FR6Cb`BY+%*HpdhLRlTTa'e2rLL@[I,XBNR&%)j*f@AY)1rbe
+4+rZ@R'AfrbD#Ll+IbCQH-CiD,LZblKP`&m&Gkk)C,E0[R*JchUc-X6%cl!aXDQG
+,BilU4VUKepEEAMF)G12rAFBdL0BTZVlAcY0J@+CllHb%U4ISHVp)mqQ'GX+daB5
+TUq[S6*fKdl8+G0eY130GjpIcI+"VK*m#MGq!qDr,8k$6IlTU"&TYAEJc[HdTPl-
+de1qi"rI5!ILM[UkYdh3Y(Q&CQM`""-PbVY+TI!JIa3Y"+P[%Tr#&I#PI`9H"ph3
+V2`B@cV2m-JJYEr1(r!Pr"[,'pp*(EiFcESS-`(&hEmR"HA886UjPZ-mG*[1eKe[
+HU9TNL9bX'HIQff@&2!6fr[2bNV`PDcFDq8UqhDLplEbdM4YpMH8S[Ri&bIA,UM6
+TfVqZArM0VIMkCI@4l2VPke6V+5h&')-#HAbl`bpfK6683(Yr)RN&8%5YS4F&fUN
+BrC'p%N!"k*mhrf#MqGGp0GLSrh@q#cCZr1ZaU)jZ)2HYHI1YYpqC1@[YZqp&+#h
+RX3mlBpaqp1E(Rhb+Q-q5-6IQA)50dZSQ`iC+1G9Yhi+',Sf"XYk#fX5SrTYB-,&
+IaUJ4mXDSF6,c6H1T9BbD),jTM*V&U(NBhk)Q[PD-@Q+J!eNVh1BD!9A8)SAG1N4
+UAm4G()-8(1*JYdh'KHLh"lTf-8,!$L'k$NPd0iIS1QEIR"1M6T0TahEfM9&Rf&e
+qHTI'Sl0#ld9aEpI3Hh(Ffqfr-[rj[D3GUY)p4MX9fj,XR#K*$(p"BjI`@9K&m,m
+Pq,Q5@h*3k9hM&GmYhP[6d3flarZY4c`QIGQ5'2AXh#llPM!e)UeiT-f`4df'hXN
+-k*3piafc9df'2SN-B4DJlKY(hbqHj4*JkKr(0U!Qmm!Dp0Ra$)-50321[H0i"pG
+N(9*6ND(a$2[8C"L@c("*$(m3J3b`4p4Nb+QT@CKT@8C1ESCR(J1KecaU&FmH`95
+hrr1""8aprrVVi"a[q8P"r&G'MdEi'`PU$PpQ49i&ITq!&YVIJS0pT[ep0pJAMFi
+H0aU*VkfSR'[23!pAP&9JRk*R"Z3-c%EFkre($,3UXGqihhGMFEr[aZRZjpfiD9&
+H-54AZ6dQX[A["0[kpbV%L32fd&&$*Z!((hLrXEQP82U(q''S14rrjK[)4N2`1Zk
+$j[SmcQrH2+8`c)(I*)%mq((@PaEqID#,`b%dU9h[fGq`#he4mYb22q"AZ1U6Pm[
+jM3Bk62Eri4,j8Zb2$XDaTMJ"rM0$Re11$hhEfEk)qfV036ekaheh`lI,"m[$1Je
+`L%)IMVh*qNfcV[m($3!,3R9TE'3J9A4TE(0ME#kj!*!3Uq8!N""4G`!!XKN!!#m
+,rj!%39"36'&`E(3K!+q0'8#[Thr$!!"AC!#3"LfT!*!%6+X!N!M[k3l!6ir6j+X
+"d'qBSj9pARkH@@rRCqI)FZ4cch,8fFVmcZ[-jr6lE1*P0[#b0j[Bc-[[c-j"0V1
+*fG6,%1"eCK1EfFcH!cJJJ&`rlXQcKr*cBCXYE1&3XT!!#5JjN!!m*#KB#-36!!G
+fGSBRBL)Dr#940PkH0'r(*%5-AA&H[fYKeeNalkHVB6GE-HrRJf!I[-,V2V'J-$F
+dZ,bJX%b3!$NVA&SqU%pfBlJLhpmM+Vq9YAZhFjiKZ3jY&1A&L!P3A0[T4&8q*4*
+E'9,P1B9Ca@8&T`iU,dh0q5HJ3%rI(,lL[,ir`CkpV-[bEi!QIpPYlei1ZcAmhm&
+1AGCPa81`TklB9@0mGE[q@5VlRHTELC9""Kr-)r!HE2fKBSUI2mTD#eV-EjSaX8G
+fFDKdBP'S2,qJ,&5@8eT38Ki+Pj38&Z5%b`Z+LeU(TK42$%fB@&BH'P03#UZJU+`
+mA&JBkSBFHB2mI+P%!j*kKFYb"hFE&'UAfLl0[NR!'Tm-l%a#F@b,S1$MmC'ka![
+&)r)!5P!`T-!2LU-UP+KJa2@*9%r6J@DR"l0K'UQ**ERKmVb5dZ*aH6RPT!EllLc
+R&MS3F!*QKd*MFR%Nr5qHqB9UT&&LI['%[**`HElcC-%MCJFDeqbdG8Q-eL@I2#%
+23)+N&!`TMG3PLC)9$*lJqpRm('Gq*PD8A)(e*mrm4,A5k-$5[2+*T8@6`S94e`R
+K3J&+S45UUQ")TQd!bU0U9&h"L$[HlpYFUN%eUCD#+H@)m0#aYDQ1JZ'A4e&61NM
+S)!#T5r88$,5*"9EEE+IkjXF!c$UTiEa*jF@ja6P&%`X,LDBKE`U&#`[+&08RX65
+JU,VjJ4S%B-3(A'3$NN*dB6*UdG"mVkJKLH8[kfp%)3A$Vh)bTCM[222G(afP+13
+D"'8fh`E-Ym#A8hjU1C[[EDIp#)2Ui@e-643-[hKeU)(jaRaYYJA-0bMHJ!&C!`H
+%aqHPPjB1)1S+pTT'YT!!E,kf%,CC#%h`0M9If@l`)65%pd[cKINmB,k-31K4@*E
+PkQm*-!VK#`[KFfYmCEZJMLZ@4d(c@4Ac'4U54me4k-#iJC'1rT310Tm%B++V3)e
+jTD@K9[KFp"bb2S8HM6(!9XpXTC3d5N#Q#@9MIAY!f9JaReLmY9`AYdDI0a0UKXS
+eTd-8$,q+VDQrqCKD8-X!c$UTC92+LR-,LmH'bmBl#X,Rm,BJ'Hh$1*TDdD%+4X6
+I%@mE"52L2iT5UDf#%I'hTc4UTf"%r)I6BA5iJK(aYm13!0"H`BMifp+4G*5#iEF
+*X&'()(9!Ib4RjqH&4[[$9I'B8-Mf)mTlP1Z$0T4U2[,-4hXiSVh$daD&k"K%dHT
+5M5DKdR""@9iZKT!![""kTVLd8mL"1Yb"DNH(Q3m$jN-3#KJ9K061a4e14jJ2222
+"2jT1!D'IScdGDGi2Q2GMZGZiZ+1SJpN5-&YLFBGD%M`3&HP%RFal#UCI+1Xr1SK
+Z1jJD$XS[RSLUp`RPj1IPM#mT,LJUpf[Q0d-A@c)fla%P8%Z+-jZT-ad6J"NI'&e
+H"*EY60`AJ$U$eii91KETZP"A"F2(L@68,8MG8)+iBAPP&S`JNe"hmkkLlLl*-8M
+E)dJp-#e)4V'I`laV!4m$`1p36l-T!$-qN!!lTV"F88qAY!IeS[3JTIq+,-&XX[!
+1`G[,E&4)%$mFQ3D!QikMhZCYkU2J%+"#c&$U5rd8$#R%R$Z!XN&9EbRU6e,Njmc
+'Qk&JX*f@XbME["N`EpUbjaHJ#KR4[&Q8DGj3P1Rb`'pH$jMAEIq9&@*)H-0fceZ
+fkrZjZQA6%-S+)Qe&h46eGM2C#$U*MUH"#SDID`500+r&QGGXLS%9M2bUCelppjN
+-G8BkX+p&&%EY"e'fJZ%M#Y0SmdUFHF8BK8V%%,hXQCIh)YVSceF136a'UX(*0&J
+D*ND(%H*hTpQ4-f&Pc4l&ZAP$`U@P"F@PS6ipdc%i(j9k"'CAM%qFrFM*rKJejq@
+j2$MTD,VKb8[p5DA$#a[KEmf$JpIe'0)RRDLU2pVj`0EBrJKNja5fc4iIkT!!Q[E
+lHQ"&AkpApjkSbEqMrrqqK+qAIqBPG-[+kQmV%GNb92mY5Dd"HH@PaC2c5XHAKAj
+&M$d!YK3*+r(1XJ4A8E41&3PrGHh+hHRI+RFJ,D%Pi6%PEMk2`h$ANBE44,U#EJK
+QjBI,mN+(KBBA&qApXj4*I3XQ(&)@bV*J"i6r[VMj9e-&N!!le+GSE(lB)Ir[eU&
+!kU!HEIYN$NJrVT[Y'd%I#jeJAP*d!R&rT"L$6F33"IlcH@F-M68[HZE&[EccNN@
+4J(FS$9-`--VBR4HC&m`'0LpBDYeJ8`c$1ja'+"MqcL8HbjD4G++#%GZj2'r@Qh@
+HHClUTe&`E&kjf`VP&T6kAVIck9P3+QDp(6r@@FBl-ET!D83R#DKCD"5GV'"`5D6
+SB3'MLRR121ZCjrcKF%aaD8kH4H8m2U*REBe1aMZDFK3-P0&IVCPR+*GKB#@6L`'
+L6kKA*'8)@kY`+$qF-cj89SaC,&`HQPL@9eTQ*e0rT99B-,SdA$SPP"-Z#[NirB%
+0X,%c+LkGiXDX(,aj0%E"L#&qQXBb$#!HLe'S@kLm1$3k$b!Rj!&AdGK3-A#8@X4
+fGiE!heGRS*3Bc048M1%@k4Lmq95JB2KE(m[bifLmH8V"p([)lX#`,V,p1i'+&!b
+fV"@(9Le@91`B!9lcT'HHr,14U!MT5m`6LNSFS4`!9+FS1X@PapE021kCarIdi41
+fUFGAE%)H-f[0S`(cf0j0#*ZePJiHY96cP#ee!Gj5XdC4U9Yi938jP"%'3NabGZ#
+ULFh04*UNB2METjTB8%dfMbLDl!C'kcr92+b`er3(6HZI3UFT'2ji94FlViF#jL&
+rbe48UZLdD0kkG,Tj80(T89aek3ccJ+)ch+B&IV1DcM6h"f$@5Fd,PjD0'C0E@P(
+2%)AK9h5QC9k,TjDBqfeC(l$'JpCif"U2f#E"IMBk'YlRQI[fV$h+AG'UBU9f9M+
+GaHp8cS5B![M%K&i&4EPjTFhiqe%c#)XHqr,J!qHEap1f1$qq+lG13mb$j[(MCN@
+S0C%cFckali"Z23EYRJQR@G+TdUFXId)icf(pfdaBYRBpCN+E+iVqr`b"[hebrE*
+'hh6YPG&cS+e%C#DXqPX50@K+@ARH"$"iSBq@3@a!MdV9Ma5Udqi-R5*PqCm0*Va
+rYFMrRI$mQFkXX53i!Zp8QUCJa%DbHmdpE1ke$(+26@'Ep'bDVQ$i)eNL"[ecD)D
+#%4[*lUCcc9dH6$Z5qGZQmR#T(FdLhQcR&6SAB-icGbSkVi+A9RPQ&G9*Si$,#A)
+SMrVk`bIQ6PZZZbbEcDKBK*m[G$l!A%!c&BcB($G,#$1lZF1Xp-`GIMQJ"bJYMbl
+PR6HkNcFBmB9QiVf3!'BV'*&pqS&d%9fXB2J%MIkM5m`+4CHiYE2eck&,&Ba)!aa
+JPTYPjRE2,2pV*PeQDhQlVH@PMR(YV(0E`0`@@dD[X-%A9l6(8XmXr9-M3,04ZlP
+dQB,Kebk!h*I6&GE`!36)-lILfGm*#M39!lc%-dYm`*JEFiSR&TAlRKl@)h3C!&p
+*9bNB2Z!N,1IRdG8+KMm&*@'&IJeGUf$%(F@-RA`pF`YG4pF(B+,%aD2(+EKpX0@
+TTVRC-cIr9CcVA52@`U4dJeQXk!Bh59RrM@D4SKXGGZZI6`X8$(q&9`H6e-+!@3M
+FKAP&@,NZF,KV84ecNfGZfNXkE"CC!PaXHa(b(CX9%JZc`$-,pQC9"2&0Y)hQHfB
+qe8dM,l+*pC2"Q@@G2V(49@LQQfLKJK%h&$NEBJHab0a)+2%Lah5T@(cF,(3c%Ye
+#5a3-[qY5XHLqPCBU'$i&T@+*I!2GCUlhB2j[+FTYJ(1lZ8l4l@kChKCEpQ@dA-(
+`biIPYlR@-pIZQ4DAZcaBf*YV2(10[rJ"4lK1m&f1mF9FCrRZHYY'5bYDifV2A"h
+0kCC%[QZJla)-8N)Vc$a&+pcDYb1DB#AG3DX)Jm0+YrEYL)AdAA5hJZ&cJ9f$hf2
+!5rFiQ2#E+cecj4kBE+kb9EREX6"fk1D+1(1&$ER$Y9iAE+6[&ESAaEL2lPF`r0E
+VJPhhDX+i[YS"aBlFA1kCbrpJ6%82906p-XpFpTmc#Gd2`!qDZBSHG+Z4(UM$3iS
+JZ(,,mTlQdML$IDZBZACk@BAhBF*DiQ(A',faRPj$MbSB2ZlHe-I-mFbF2BfJk&%
+(V3re0CI%Q8Z-%AS%U0BDc%"VA60NB-ImQ0"M#(ZFX,Cjh$9$"[EE6a+@3dmk#"P
+BS9m8CbkbdU1R+ZSqfc1crkVl%m$fY,P3dG1ZlJ-"q4P&ccKN!fQ3!*N9CfDK11C
+#@ha)h"6GkFS`"!6a,$fRB-J)hcqFeY&k"F1[`4!DDQCkCZDH(Ph[3')jD5k)-aJ
+R&6eA8Elc2A2qR`14QBI&0bMl6`C8Y0J"JDV)R1HCmrD2"![4"Fr6"JA$,qeSl2a
+HS"F9$,p%@$bDFq2-ZEC%,eD8D)CRC[c9B4Z!l59cMU+A+VDi,bYkf5'c@pcTF@B
+kXCKc,,0-arX+[DTJa(B$CjYTE-kfSa'8@d+[iRf0APF`r0e!%22H'r5QJK(E$8b
+PYmaC(X`QDC4mbX5mdLRBia@Af"9N@53!fp*-&b$d&L#pEFj8p(C&GFr`c"Rqf!9
+PAh5aB(h4YB,"+Nc-@CB4hSaX#14KfLLd%@!fd6X+4Ub%Tj[6f*aZ5hLD,H%lH0q
+Pc3T'E,FkKGjM'#MRHeJ+(K6U9MBq&"jG2,%m00PZF1fUe@ie1VQGk@Dm@qKp"F0
+Ii+%-jP6kJ+!)1R@I91S$TqLa1kD2c'4&(mAdHr4aN!!qKNURk4#,0p,!f0F@qh,
+(b@'VkiN8)5,VQ@chpKp#C61*YK*%BC0LXTkY&Q8!@DV3TfDLSNqGc-Ik2a2k$)l
+2k3X&``F2-54p'D3[8IZ%3IPjKB84TFmAH,qLE3U'RmIZHlm1dYGSq!2lqc[XJUJ
+SD"[HE`bB$pV4U-lNfb"pLb,%GmGDfXpLS#"N-p&@l408VBbq-k8"Q&&Y%(5Q0RF
+LqZ2l)(fr+hH#34m*[Brh"rT4`BKX)UV6G[T*`I!R`L5XpRif@#Vr(0e-9+9I#2V
+,Apaf)"NU`*+!+BN*JADi1$[R&`F-&+J4iFmTPPGqUQ#M)Xm8q5aZbD#mf1p#jm`
+ZpM@p3MqL0MY*+aJqlp5J'QD#JFB20@@$2Ck3!-CV'-L-iafEBM`c'p"A%)Z6aP6
+[9pka+ra`D3lU"#+B@!SGJ&2e#J[(+8EA@ZDT3Bh01)lR!`*Qh,qBKb&YYF`$25F
+RQ!,&#DlEV,p+N!#VB*r3`QFH$")jH@9PN!#br*0kV'!K3MmJr`3q!)fFciPmB-$
+N4qQ(S35cp&1,kR(!M&8-pDZP(q[hK+&Pj5!Va8&AJ9T8Qj1#R)5qU1+[3l0kZ&*
+$RXV*R+)BLPDE#-*6VKVNUPCmG@5(m5i*T+YFcBa4A-dPU8-(FI8J9kpN(Lc0fBb
+e"80ZNmFe6'l!j%@CKfZih2@T!GF-FXe+jXQe-12`eZ,DLQXjjQP#Kh!G2NKa(FF
+m6DJCec8jLZXkjV(qHPaIF6h(-%fTQ4NG-+1Mc-2eA9`6+%A$!411-3qfMBUK&Sm
+bcmQH1CN5dbMH8S'Y4'fm$ELKBPmK+pM"Yc#Mc%PX4YNDRf463#[,M6LNZ*(M'C[
+L4'l-jN6,-ieriaN-M18&15%dI&PqZ$3[er89e)lFK*XUEZ)@-LeS*Kr-cFa)EUl
+iB*,Mr*L1I!Lh8!c4RYe$Y+!fh*,"05eGr5!G05-m-q,AqLPZjAUY*EAQ3i0mk'p
+GVaKL8SXPMGTcDfkMZ(A&hQQiCiE[aJ,GT-8#Q5LR"MPe9pmUEZB+ejR1jVDFCSC
+a1m9Y(EM1e)d2im-9(qE!3HKSKRTQk$k+9`cTTe-mGZ8MJRc%lh13!1)d0iVfT$#
+h&fk2(MU5Me*mT12URM6#$1%1h$&JKZcMkJk1Uh[5FGc*R+!B8fI8Il3CV2KS9`M
+VlacNcK$%T[Am*eN2LVAf),qe3l&b46KmX$91X,cB%EbBcFI`X3'6(52bBab4pkC
+"h-8-8JaGU#9bkqmU$#8SGq2ZLVZjFQ!0a6f#h-1I)hhNMNUkiqh*kBSMiXpqP-'
+pJYc,cCX9P*11pcJc82&adFh5mG`lb,dVU4ck(cE3P#6`X5MCmGc(C!A-m6%Ula-
+6DR,I)+UeQmUc,-bMm2BcQBVl15SIL@EYc`-8pL-qPBqN8CaK-K4$*@UTh2Sc18Y
+a4#9k)Sdb!`*Q3)c+Xe`F0'ZQIm$dMe&jKQ8%5&#M90l2-rhmR9*ZFB4TiA%0)!C
+b*$($E%B)L5f(j)+hMKFq(Y8Db1LpJBj$FL%NkX[C2$KJqZlMN!"XaaQjd)bGB2S
+S2U(#2m6d9J`KRfd8kamDj+&BDREmrcNNe"`KGPd3)C2HeX!++)%(Sc12if%m2'#
+1Lj%*G(k@62+TM%HBAST(1$+arT(#)e(R%rNN"GQ0AjGm'XqMJMcUEf3#)4qIc'(
+&*lXmikQ)4`Gjp0r)"-SqcM%JR4bATiK1iG`JjeD5#I5UE(VCNJe(bATbRZN4-$e
+MC*,RFTI6C"i6j$'9C0,$`Kb%Gk`""ijeC()'ZMDI-9iML5@6-fJUMc2G&)pcC',
+pilP3SF9pdML6TTUZ!G-e4LDBefcF'9#$G3QB,M%bk@DTSD##6)lec,&lb+5lVHe
+)Ql'j+mX-6'm6Z%LKR(j&Cp$jA"`%Q0hGTELS!Z!aRMRQ6i$F&'8[i9-80$Mq%$U
+,CTR1jQJfR@e$(@dlia5mTBbqKpE1$U%f45G'*6[C)E6mYb9E,f`H3$%Ca89Yi()
+YM*Q+*r)Na42G*$H,2ZE*I+VTb&-83j'([NA-)h`DRkiB5M[R[iA2i$-9Rq(BCKC
+G`QHC$SV2FRS5kjpU-**"r'3R3HZIaQFVk0,mbXqL#mf4RMPbpjKjYQZD#qPLRKl
+NkEYSJ-e4eZKJdjcT)-qPKAb1DDri(!ICqQHB)a62F&1cpCr,jbQ'--U@B#jGaHI
+c"BV2Gb@!YXFFlTR$p`qMf&MESPa'9r,-)-qXA0iT2Xq"ZiCZj&PmSH*C$Kad1ZB
+`cabf(pb&$YbeG!22$[,XbST$P-fQ[38CN6-ZT3Ii)S2a'ZST@f(V[jJ[8Aba+m*
+5@X&cq&,&Fe`4PN+fNZDCY$rS4A&%*h8E,HHj3CjEbHf+)FUbX&E4[A`CAkli-JF
+,@K(6eM0Ypm##3-V#ZT2Zi5Z#I%9P9F'kLNpeXpGDHTH[&)EHLDrLHBU[FV2A@RV
+6T2,9I%h!T1kE[DjfXpCDHS+[0GKK3%jNJ9[rG8'qEXqmEPP`%U6#GLhZj-*jP50
+@'cZU3'CP@[2eI%2!Y)j09ljH+J"4aSYmScP8mBeZZV,qqF,c8FN&I*0Lb+&X*Ck
+NChKKN!!AfP9DM'p[`VZ)&bZ'%-NQHBE@mFe"[YQZD(B6mf+mYaM8q4DAD"eYi#9
+"AP)j@d'kbZC3@l!E8,#@I+YT%6!YBl29V5lh5r3U,`hbdXVC#X*5BFM,q$CcL'*
+SPfb$[B@Z[*fA+BD%bFj@Ep%QAQk`MPVZCL[VAm%V&Dp`-p6EY-Nd#aMXJ5+ce8S
+ApaE%"JF(c-'afDUjEIf)$XU12Ndpdj55dZL!h1)aU$P-P&l-)EDU(@dZD,4Y3EC
+J),Q$9bQ'I-M@FJYpb(F'qFlI'NEaUJTX66c6j1rBH"*UI4IIVGKUQj!!G#YY0Be
+0L!dZ3E%*fADi'qmpI+rLHbT50$)0f65b+4VD&"!ZmAem[q,l('&Yj8,6J&Ic!`(
+6B"pKVADLX+dmJKrNKa3r'282iiIj%F83'MRrB&l$MbTlfF(jMqHer*MLY9(r!(k
+FRe!-VC!!mrIK*rNTa8p'rHRm0$qMq1QS[aXrbmmTKSM(qBrKGEaHmEUS[b-rcaX
+83aRMr1hj"Aj4m3Y4IcYqL9p@r&,8hiCIi9F93llLr#hj0AjG-E3UcRm)[m&[+Ri
+MkQr+Er(ELU&!FIj'[*%h+BD)a2RVm6[mVQ)S4Tcr)0l-lbQ'rX2jDr)@IPraPUL
+r+Rr!(bU'c-2j&Ar%(m1)qMhHbTmSKN$$qD[`TrbCiNqMrMMqR,p3r(R%$lR!Prb
+9iLqMrPpi'hqY'(S,jrq4[q&[&Am6pAr,hr(hLVq,qVrL(rK(a6miJYT+Rr(f)'q
+(B,2Q`,a`lT5+d@0LQEdJi1MU4dGARp'ATRl!e)qHSq([hBca&Ah$2jPkLL-##IK
+0hB#T'mR$TTi&mDf$r#hp`$m(q@FS093)Ae6BiJYT&(rY+2P(b$B1#TL$!+%m2"T
+3)6QaFEq3!$Ce!UC1,1i,&fFJ@+SG-,9MFCrjF@LI"&-VB'V&iMjaF98J4+L**aE
+hX9mkY'23e2"-MIhMm)GqiG(-+Ib,UDiBFK+E(Aj6,@#Ua3U2Bb1+hrF,$bDS`6Z
+#[!1+K'Ufm"!m9@JV)Y9rce@R*YFa931QDU`klcTm"d&5N!$LQC6Gb`KIeK3!-6A
+NR5CCm8kA#hk6&$"*X9SNff3390PD0-)UA`GC4f[4[k"S['hh#6KF8KLT"948YKC
+0ZEP4!4bBLGELGBF2Hhi6p%a`ch!0ACLY5dYXlBha&12-QXd,[`N%$+Dl5&dm#pE
+Tcm$@DEKV"[K*P1Mh5,Jm8JhSh'`ef[%4"Y+5!f29f1$LfR-(NaJ`LE%iU2PXA%I
+ZE+S%6*9B(#4p0ZiBlQS5!LBK&JH*SBhVaMd0P$-(a1+JB,4akGcEa!G-I#cZ#4I
+AKrZEZ)#"%LS5pjL,'m"C4J)388EMS+qdFFGcYJ(ei+"!*1i4&cHBKaTFKS03+K,
+hN!$V(Ua-KE94d2Rih31reTl@[dq-5')Rk`FS6Zm8NEL!hKPG"BJi,#-j9q,e$L@
+i)SC9J1mr3!5Al54"ULKa!L#%MC,%S#6D*8Z2F&%16JlBm9fUi$e3rk,N3*GR&)q
+@3&!#pXj6*PERb+&r3Cc'cES%L8-KIKC2ra632dG(I2&FjMc1Pf"3JK@C%c4Z$3T
+$pLT+NT5!EE$J`iEb,%Q@&,eGrkJNf9rb)+CFUNSe*EK(Jk%IrK+TVRp38YdIqRe
+r$DQT""SHfeP&A++r$qM[Sd1re(4af(lUl`,kZqM3Vhm!cBJ6$@'9@5DeJP+VXJH
+8T2LL55`G6j2D5R$cc[E4C*kL[aApV@f!lEB"l"8j5F*E4`j5BJ9"U1e8RUUrd9q
+crXDQX+IL"&IbT+l88`+0N!#p-M'9cj(kdN!*Y%!@f&3q@fm6MBYb5KV%0JEk+dp
+rj@Y0*db*#L(KLZSJ"HIVT+%d8J,9$rDX2)0Rk#mPa"SA+B-5`P@h4U&"B0k**Ii
+kb@h[Ti3LDNaFJI'(2K&SKD5a0&(5f$AM$1M-QXV"qJ[pZ4,XHl(B!lBVT*Nd9i*
+6FEBjCr"-184D+$R%dG8-2PGrjZR2rQ1F%T`3X9eh,PmJ,B25mZmk'X(DfZ+EcCG
+++cP8#84$&YpX[NKrkZP2pq-le1'lL1G)kk#dhLd,%Kc(`iU2jr&1D525"P92PEC
++8Ph9jr(pNLEYp#GkUa,FTE09RmHhbQ&bZ",FTE09QFIAba(5AZ&dS9q9HAberYM
+6(qmDdm6GP-1bm$Sj-LK(rNhQ*)Fl,20jX4`P(C5i@hA`,p!IHIUMh9Jk1#`,H*&
+d$%V(bRUfFf4b1pmYRH4S*4LJ-2V$IkGdPQ18i-5E"BE&QIl3darZB4+&H[L-ZSa
+AbE(54FQa,[0bAU8rm,5lD)IE458P1EkGPG9$#44"0XFbAUlIpr6lHa@l5U"DLR,
+D&Np[qAG1dcK1b(UVC58)YU5VG&-#KB6YcpAmYR5A([Sp[9N*K%@f2eIcFp*6dTA
+dG$feQKq4AR+FJL$!,`lfArTG6lqlZkHFaSJIi)HPGe"krkST9!)KNX@aPTq52Y*
+A#64&&JFfAISG6lqc'dGIKq-aIP,k"D9IC@qLefe[2Xq[5hmCS!3+)pZEcr1VNL'
+C5M)F-+bip#C2EpVEQjQZ0cI`+j)PabZ"jXKQIS&Id4Xp[C%#VMGY#B%E&qKXp!C
+q3ErYkEIhG@@&3%QrjHQhpRBPcJLbhQblXK[HJIT0*30G9fi%Q3k5E2f'IPd**$'
+f+cIb&c*B6P!bf(A64Rj2KXK3*Hk#'2bEp'ZHIZh2KB)-GCfeL6I,X+!-qdd%)0!
+c@9JIm#FbA%BS'HjJBIfQArAdUhYJ3ACNBAh)@f9N8%C@0La%8lCKYr&2FU+FT!3
+hJ'c$EZ-ICC5FV!6A`ba)l1$d+jjqC@r$iQ+BEGL[q3F*bfJPBCIj'rj"[qcTPrh
+bP19(k"3H$%!qSBjfHElQEr4,RRjTAqZH90'k,hVDh@,lYpDeK`cekhCLIG-D1$[
++fTiG&9c+P"a"@d!!K1N4U`64,dJHDpaR#dUHVp,jGAVda3LKL($IcBeS4aNMBj@
+-mEN!!1kAI#R3'r6c5Y"@i!,%9*Ga-Pi*9&"S@[LV5+&-8"Bb+JKrR&l[kIAljcS
+RAT)il#q+JQL[5XQ,J,dYZ!"f#-95SX3G*S2Idq[`l!H(Uf3@R#G*FNT36URN"3L
+[3+a55qk@8J&&L*3*GJ[3VYZ5em))0e%QkHIdXdT`1Xb@["B'imPbUK))P@a9DNN
+pQ5+R+F'T-&Z9@P*E2q2TChB2%kHj'Y6'QZ$dS*bqHbM"b6',Sb''mM2N6#9R1"`
+BrIA6RRjk0iic(Bj'dN61#XTCPE@%e-#+k9[*i6*9TLQ"%JSF"hml19ZQ+i(Db3,
+$h+fIm[46HcN1eb,!FA)S*ZCcC)D5FecQeT+QRr6dNa4+Sb5R,LkcE@T,'I(lE3Z
+r%TahXMN2PGEk#8mrXBr[)KSYbhH2HrVa[AchR#8iHlN29iY&cTAcP%"YKEf-G*!
+!$[Sa[CEeBcD&[3mRN!"+bIRk85ARZhEZJ#kr3'EU0IS4*4HiGZk!5A#@A+J%PkC
+X'hD3!'0NYPbNC,DVA`ITU"rfp-1lfa!h8@`EGX3JIR&3,[jp"i$M8aC,9dQA5f5
+1NNXF&XblqL&22l3E#k46&NXh6,UA"ZA5bTDHkHLT[p`KFd9`&dSZNmZ9A1EUf9m
+Qb"9bTAj32k$N#PI2rTK[VT*j5R#2b0DJ[a`[9mXe5Y`e)cZZkY@HAVeRM,V'e@-
+!aY&VJh,YhkBcD(FXV'`C*YI*p8VFq5Ii"q[l2Ahr(PMA1eL$CDMF%*3E+X[XlNr
+*b9)J0mTm*EJ"CCRVC"NV#q3Q*Hl@%raKICqRlp[,A*!!1PRQ#Q0b@5L,P#adQ8I
+,'(f[Tqpec1@Aa'FZ1k0&r$jcqC-D9&)f*kBlIBqRlpR(A,K1&@@ZZceppelQXVI
+m0+lkL9b1Gl(FV'5aDq-LN!$%,E*%hkA[9)+M8,D0Ld$KYmT5*EHkIL[#A(+Eh+l
+N0PHF)LR@UcbpDNqrhHlkV4KMcE+J,2Y0$bT,(Da*FVSXPa9+h"%Sq#IV1capaaj
+B8'"C@*2P0&NCP*@9EBaE6lD0TmZ&i+Y95Zj`E6aGCXUGFTH51ah)kA+1AZRTPA[
+E'')TfmERJ+l[PRZ8i,+6c6a$,Y!V2,hLE`1)Dq1+!F4[BhFmbJi`HVQRPqpVi`S
+GPelQk@9lfaLRkeME)hD#1ejbVdC,hZ[DH!k+ITrFVfr6D&XFQ,*Y2!ImY9V!cY"
+KfAkE!ljq8"j5JRY3YMKcj&*pUkG[r9d'S-6GL**,jA*j1)J,1"@#2L821$6cj(T
+j40BSJIM!STNR9qXPRPlb$c3i)'A4A!h5IM3SMeEf,GEeYQmAb6*C+imTFD)[q'q
+6aq8**BmlH)YNXEl&dlIXl9[FIE*pZeL@bT2bP"+FNV+CEjDPqQC2hqaZJ)E,rDE
+e2Akl+R(hT5`VkX@HAVb[9k(-L2EU)Nm[fYZVYpPHA@Vh)MM5*aT(%PRMN!#QD"`
+1&BdEYDbIYjd-LEFm,FmSJAV0MT+VCE9HU'pL[G#QZ-QQH!E[Xr+FNQGpj3"52#M
+VP,LE9,E&p3*2,pLlcAm1!0CVc$EV(FD(j#&pSlk"pBd@i`ff)20Kd1Z)I9jMX))
+b,R,P5&qRVf@0ifZXm@F'SR'"$D)%(,e*J9Bf39mM'q3&H9&HNTGCAi-MVl+"i[A
+9HTkq5PrTkD[rZL(RkARl6aekqUVpeb!pIH9rhi4+NKHS5SUqJK,ejISbH89HeA-
+pZ2qc4NND8e1m[P4HLp-3%5I*De#HkcQHR[2R189pQ@f&9b"IZ84IV#rbp#9rC2,
+daAZ1(A[kSRrFHdq49h'cCV#HV5r8Xr4-IB%qAjqRcm8G[ijk"KfYcm&Pp4jk1UA
+VXr8d29@I49P9p'ahp$qJ,icm#N&!ciVFL3cSQAYrTL#J,pMlY`)"IIlH(a(`p(R
+rU*qJ9K4!UCad+i##1BP4!%9c'TmiI6BmHYTHF@P!6ieSEJ+SX&2P909cU@"mqKf
+CQk[456@SiAY&VEE-Ilpjfh&"LXpX"HX!hdSS(N*GKYSIF2KNIV02QchAl#DmccA
+l[0NAAhj91#P-+@'U'UCU3DUH1BTUK+PQkc#Z#6@Ja((TG`bM!`V5laLFZ5!j18P
+HY'4b*TfScp#Rbq[bKMl0Jh[rh8jpKQ94A!e,%@MJp"426rQ$'P,N$4$XUAUbRN4
+RkBND9(RU(hH-@H0UPb!2'Q[LhP1r!9dH15*F9Cp'S4Tdi*V-0FP$+"&EFC,mc2H
+VNGI5YXZ(VG0A$ND*Al)P,U-CZP5I)Qr+@lV%JrXrf$K*Bj-CVi[Pl6L0C@Q53#j
+)ZXM64IqkcDTa(#Y&hN6&*qK#29k2d`8Dl$KKEdj2&qjKeI&rR0Rcp,KpGr-mAE$
+R!TqRmrIF2Nb4Yc"9M09MG*l1e6PkY!lVNcdpGMmG"$6ffci0HcT[rpQpJ-k0h$d
+0k*c)*G+!YVHIaKIRJ)V$D2bFBYcK,LV2UfMm&*mZ2AhbAe0199e#"Dh'39[rAR1
+3!1MDp&@CmdHm2h,%m,8MKmrrS29KkAGQeUEZ#dGmq(iK5(4mIMf+El9J8E2aKe+
+9p,Xc&im$4AShTEq815jj'09DA'$Giq%ZJ,[+6H-ETUmDN6R-V-Zd-H-YIEjXZ@8
+8[DP2dLI+4YQN4hT`rrFFTh'[*9k2N!"hiM5%&dRbMQ@BiCiHrUrEIKThUP*N)aK
+QQ"kUKqJ6p'#GlHPKHh0kqMq10hNDh"PEThVkK$p@9jiHr2YDa02CHbEf&0Q%[d(
+i@!r#qEb[k9XpN!#qemIV,*fT-b!k6S)+Z$VN[BGbUKl!4h"RlX'pZ$IhjD&@6mQ
+j2)D,H6V2K,*Y,Pr"er&#[TQAm&+qNlIVr[bclXFl@%23Q3JC!`5+dK,Ep51aDqi
+V[D@IlS2ekNMG'fZq8l#K1dXI*aGM%h5Yh+"lB8Qc8UI,`r+SlKP!HD+6'a3lNFR
+0hNc5@IXQYmcBj*B4QG`#fVpl9&`-'[-[(IQ$BEq)MYA6IIqK%[0dRphk*%rhrN2
+qiZRMrNXdi1PHrl@JpA6kIqhr20hcMfe696e5(YRmhTEh2jJ`kF12F*`a-I1C6eZ
+$EMpllr-[[N6-9l'B9CNhB4LeKjGKipBj9@[HJ2SZ#%2chS#DK+R'HjK0-CU'U6E
+bJ[eMQHmF4Sh#G"$LkiDTATMUqr%0GX9A#90$%$U3!$A#FUmf8)8X8YL0ID6f4Gc
+#-'l*)3jfdeLFMrjJS'X@*J3FiU0V%80hPiqZCITGQ@&U0BS1E@EI-,@'hHEhGd%
+N1YAhhK6aY[@p#b2HY2q9qCr[SQDS5VX`(9CS5h*iY#4Kr1Z(RGmRB45*bmmF0`R
+c#LVG2P,a)b1p03lGF&5NhcT%BT)@c`p6apE0dZrf8b1b8b6$dEXbG)jP3+FF%qQ
+BBhGPk",0i'F"kUi4p0dL@4B"8rF)YKkl-[IFK6ipNU&AY'E!H9`%EqpG@I[XUSJ
+p@'Bcp0Z9SAmX`k)`IP)$'@"Rl-U3!,QVCRkQaFQC@FRfa`J`F!9rIZFG(#'R,IE
+(F`V+lHNZc'bqS#[b(a(Z[h6FX&ZQfV3*99bB$ah4p[#dYKf28UTEdC4)LYKI,C6
+YrNNErjpXF[2'&"6KFU8pGP#59eTZrh1KX""h`hC0b!l!j!+)bI!(#lB3*B9Kqb-
+-a5k01dU"%`@U`2h,3Q33aVmcP*@RKN+$lDqCf"VkIchLl`53!-cqdS+p*qPIG-A
+b-`"5YKGGSemGrbDKqq`rkB4S84I)Bfq&iKUh8,%ic6M"E'mE0iRDaU9eAV$XPPl
+0'lATE5251LqjdAT$U@El(@['KYV'K6VRP"59Gr[5l'M5Hm'b*KFdEp5hkjM%[X[
+0MV%bL92LQUHDlc*1bTLBJH0kEB2$,QRE15-cZ`r36P[5U-@S8("-BNPF&lVekC0
+EY!hH1MH8(8TmB3R9DGb9kN4mpH'V2rL5YM9#SqDIG1bdl-`@4@C("D+-e5Dl,ie
+YCC'&5`V,fhBZbbNT,fQmT*9&0lBDiS*YFBc,AXPIdZV@liCQ)Q0j&!2LkYZX0Vl
+A`(4l1!ZVa$ip-TVkRLYYR(98X6r6%6P2kdG!JNAaq11I8h'4CJE8m6JE),J[%)p
+IjdP-C%UT3G2`mbeGZhDMd,CTde*Q8YI%mbJ82i0#%2#Qi+KN#M6e+I'*P*)B6k%
+8r%e+L'PD9fM1TX92abpip!51h[(BFZ'b3blfeQZ"%hF'r6fRa4m(Z`S@p&-K3m@
+[ec"q,bF12me6"ArMBhrXTa%@QPf-@629Q-hieB0YH,IMhB&A)mBJ9L2($Z6DAJA
+aFFL$Da9VB%q$(aJXMKeiYe19MlG4h'2!L@-hEXrUEpRYKp-DZlpYPN!U[Z6G#C*
+4*pc(V8Lf$Rr(8T%JQB,VGLAB4Z[@`aP0B-14,jBJ%Kj0i)Ilm5k"$Gqj+CE!$pr
+N!0J%aL"mijSB!Vea"m+$`@L#RHXf)(a0,-'1GFRV%8j"r"q+6C!!6'[@)CaF`Z!
+'fKE%K`03[Kpe4!)ElXFM(#PYq"SrhTEC*N$iHYb-m-2pUL!FIqcKKrXP3rLkD$M
+Yh'E$em6#0qfS$0qiB9HiVH#ZF&["GhG8K&2bQJhENYI&`Yf2-Hb)K8H59)4(Zbl
+fGH9T59fVKKURG%rm-(lHp$RGZMB108RT@HH#CLR03`fkdM5HPVbQdHBZfkCZ"qp
+SBkDD,VV4MNEEZfcVXVR"'Tp)l*[X-"RdP28'Nhf3!0[@E,"pQ4`-qTaJYQh`b@,
+RZcYpNYLC[0'@,YQf'AV8llrefj!!+aNYL04!YAk(6EecJqqQ(4Ym0dJS9Y0),Aq
+)6(,fTjNLI`HLe2q3!$)I9UXJFX`8#C43I5BmJD'E+3l6KRhY9H3"Z$TI$U82cY(
++6XKbSP23VhplaAhlAe!I4bqT2Xjh*CIPP1'i1%fhFalXLqdm"[ZDl25Kq&FEZVQ
+XI)V9A$cF)l0R1[c2GXrSD8HV,C%jl-[)(2DcQm)iS5#Rd"lDUiEGPI8hK'hpVI+
+K$S"pj+!q`qhebZj$m(pAGR4e9!C2hb(A%IlH!lG1'm,hZIAC1X#A%Tp[I30Zjll
+$lUXqdrS'hBHiG5iZBbjmq!F'JhYM'FJa"1ScJpY)'8r$YphKb%5qBGLJqVih%2G
+#*'i6I,hT5Yqh&6PQ1er@jiMEl(`$Ym'ha2N'(3(I+jqXXElX9I"PZArcb,CBlh+
+BXPq$Vrcr!3!!$3!-3fKKEQGP)&"KG'KcE#kj!*!3p2J!N"#%!*!$lF)!!#m,rj!
+%39"36'&`E(3K!+qR+)f[TbcC!!"a+`#3"MXj!*!%*c`!N!JT"`i!Cj66$(m"d1p
+bNU19I9jq$Z`kFj!!RF2mI+p*CPjR+r0l1r1+ITp0[0lH$`8fmr1DfF"VC"1cUCd
+K`0l,lqaXB(2a(P"iekp"hhN,bmdk`MZb#IMN3$)!b81#JS@!H),A2,2c!)53!%+
+)i[P#&1%[jaJKDQ3*,eCB@"BV'CYI9KV'KVLB9XG(ZSq,&Bh0MqE%bXD94JQjFf)
+PCB2l$+Q282Mp%[rPZleklcBZFXbq@TdLk"!KU)LQUjRU0+eQ#MT)+-4,eHRU$+e
+1&l)i[&mFE2'$,D*+PNM,+biG&b[*cq2)i$#Le4P#6N5HBLT4Xb*UPSL)e-&PXE+
+#A!'-Y$V0P6@&MPHce4bYCVZbTM#!0E[m!49raiDRY"fA,$iFpmGrEij(LdA+[&&
+mQYpNAX-"NlX2+Bk@6#k+PSdV+)f@jTB86#U,aLC0+Lc)"56&4FfMdiSR4bG1,Lf
+,MLNS`DQJU,3-E4EYLKcjJm0m,G'0H`r+,md[LrGDLaDkEm(%D*qLXH0L%k-YSQe
+EYFPUeD'GeN1f&9PBPPp5LVVc89PKIR45Q,T*,,GX-ZUE&LdZ`U'!JFQ2PNiV,FZ
+I'%maTVJN@P3mY@QdH!b++!`6$-NYE$9N3R455I(ir0bbdTCk--$)$IXrcf&59Kb
+043X,J#$5PZ6R&TINP8CcLi[+BJ9&"89M`bU+#r2#'U1aSVc`3P(qe2"#bfLdcaL
+1FLe4B0LJ3I0S39PdDJ(U(jdIcFX[c#r,cd1DE+3YQ9T3QVrYHK`)p)QS&T+B%1R
+#%jNi4j+0b[d04X1r5I`'Gh*8,1cF5FJE0b2f#Ijb`'(fqeCULQLPXMV0AhapVmE
+e@[6Q'eQGEVL'Sp'@p[XlPSq0YP,46VQ6LXUkIQDh01JpIh'$@BhVpHdb*Uh[VAE
+,@*SL-eAMP[EV!8F0Q$cJ-#&D4BDIfkV6J1`KI9$YM"[U04N9MBa*Qk3kLaZI1VT
+*UmL0&d5(400HZ%(8U0p&e)M(DL0@HqLjVDT%4mdlkZ!C3l+E&0NYj480@'D(p"9
+MQh&PX8Q&CDdkPHC1+TY8riCQA0hBbVJADG@*-CdNEQKfipH(Cb0M@D)'h+[0@IP
+qVd%pHi8G-D02p`%0`mJPI)m$&EVQj23,Vb$-0fL'%#RJb@1M3Xc-&*,5"&'+5%N
+KNCBQ4@B9-52D3(6TdP9%0mqBN6PEG%NlA846CSSSG4'C-LSb+90NTU5*c,38%Fd
+Nd58UaB`ZG,+BNA++&'Np8%I[&*&fH*T)bFX8DJAUP-c,U*[V9cKA@#l%p$8Jhme
+#fZq&XPY%"@Y%"ULiRV8c1PZlI,UeDd$0Qr(r([mYq"[FXEKVN!"M#h*pA`(h&I*
+)j-0j"Z+SJH[BJ[rhSX+(Qi9k&(9+e-[eadN%AmE2Xm&Q*T!!mLpMHi)-i#5f*YL
+mmVeY&@5)b-TY#6D,PFmKQ%M!ej%[Q5"q2C%J["lHG`RiH["1-N&ir4eA!#H`&YG
+A,dp@B&C[`I9)**%J@,N+ejFR%faCQI%FVSY)i"*NL18VF9fiK*&9BR-%Ra#Z3Z#
+)"(`p[)rV5-RAPiIh'@C1J1[2EBPI$e("pCAakb&NZ,ibF9d%QrRkmZ6eGlEXZ,j
+keEEVM1#fkicJHe[+ViZ-jDXfCka-AZH@i#3r0h$jp86A*EmZFNCkPdV4qTRGdMD
+Nc$hP[+jGkNFEC2DS-DY4CZ0SR5jLKTb4XEcHQXkEThm2hM(@6VHG6EdYpEl[[,R
+cQMV,3b,KIiDVbD+R1"V*#)[F[(`9pf9'*"*bJYfm+L5,i,dJ*)NJBc9$Pm&YKKi
+0qqqjcFL9J4C%DP6eh"C1(D`+`f,,UM!-%NTL'XI5Z[%b($AMikM@rj[+R2Nd@U"
+b1D0MZ%J9UA[14X3lI)e3'$[i,d39X83XT5I8HH)NR!1F`fr-T&kadVbKA3G(@lG
+XRFArG0a+i4P%SLU&S3,V"X6NK(L"Q*!!8R"c$j'UFD$ai58ImdB&2Y60%VSX0lj
+VBB$$X&Zhp%0BL`T#pJecHL)03a*+U5JmM32[1d)!rBM`aCj#(p$qd%Ap#NDAa%U
+QYEb2)5EN*!c$@Z-3TQ1-dL1BNj&ZdU6FAp*Tr$0%TXBK6!G!4D@)U)4Z51GdD06
+"ij!!-j%[%rr+BNq03jK2!HSU%@5V+M)BMF%&%l(230C%`MhaVbUUD4c#K#PSLHS
+48Cd6FS'r*Ub'I`faPmBK6)Jf%M8MSLBM8MVZ(rRf`Vq@U+ea#21PSRrU4%3G31@
+&k18A*R29aVqZ$E5Skh*93(I9LiKkZ&L0`GLkM0Q'ZX9-4#L-X%DSVh%)HaUBB(j
+Xi1031dY%bLCXE@P%Yh9d!pI4%B$9N!"%3a5bYfLNF3K43,Z+aK(410&$3bEmh+5
+0m0p(00%iK!NefVPT4$40p0#[#C[JhdcXUh%)%kDM[CY(42-%#3bCX,fTpm@rK@L
+TF3M6J4#`Ga#YZ1@f0[@%4,k@q'H*eKU(-&mQq+*04,4*N!$',rPDilqIf&rM%1D
+V"2CS'a&Y'BlbPNkQfarr!qa2@KcJdP8'cZdLSKe[q)B9P)j,G192R+`qrZe&"ie
+$f*@e4%[lSqMSim"G'CmT`NNN'3dR$#dkZUkX"GJ2*(%J#ZPNIp!#Dk*$`f[lLS0
+5"AD)f"!F,$Vl1&E1%K8`G"6&*ZD(J3%)D&`1BDS,,,T%"2BkSR,(M[f,5r*lB8i
+UaGL`ImX$1M*NUD)cU[P1G,AIqMKb0CK4A$8)Z'UkZQVf4V0hLiKZ[e@cRk['IXY
+Gm!0h33ImZiXH'JFUG,11rFCq,HdhQ!$XejbL"rip45q0!aAJIL[dkb'LYmC"pBQ
+Rr-TqDEr`l&HL4XYBrT5bBL``LbBA&VSapMc4$*qdAh,9Ac!,p8l-2$(4K`3Ad9F
+FUR'JN[MmdNrdecJ!Nch#4G`!ZeQ,!BQ#dqcR)YYqjZ&BSb9QaZ,#iPJH&jNBe@)
+J8bfb"I(D&E1$r96NH$LNH$b#DT&62V3-M)L"B)T)afk6#c!@$LdV+#ae02%CY`"
+'B5hkKb[J%1P2I2Z*U*JPpTJF*N+Q3r%I*!CV(#LECbc-+%2%8)e$#'F'*T2$a$#
+0!q$MH"@lbAjX2r,YTT!!DRKG(Si1H38PBG30%Md+5XKqc%"ma"J-+mGJSfmhLX`
+XNCSlZB4cmKRCY"MUF[JLBMrdlBFlF"U-rq&LZ-C"(4jZ1Jm84pJ2a!JYMR$)0!G
+lEK!MlASI4elYPr#XlbM3a8)#*$%5T4aTefPaT+$450`#P(#8'+9a#$Zf"3MqD2Z
+q&NF,bJh[Ck(94fXF3S!`-pLe[Phl1iLMA@qf&+hX'XqZ3FrQPKeE*Zhlh!@MA!%
+B)Zal[Rd[T%)-m0c9BB#jMZ`klTVe2$Yrm(X',8Di1QU*U(hAYqrqClJQ-4bBjpT
+hY-KelG-*B1ECe3,&j,Rfb8(V[#h'f,Gm(2pXRc%SCDap8iZaVRd'SLA(L3+03ca
+qQ"J[*QJF`RBD##STY'pS!BEQGZ,i4&'NF3K4(#J'fGGpqrV[l96NfJN-C9rcl'[
+*GRU$ffQ#Z`bk%X848B`E&6U@6@MI-LXF&,3SF!@#[ZbV[ReeClZpbHhf&VIEkTh
+YPZrUk#akf&GmqmVIFbrCGjL`HZ%r54bMF8M1*LrEPk4pQBRj*8ja$2iP!P4IiQD
+6r6$kPBR*'SH`*6RPLf++IF((mFq@R)*#TYT9@N`YTpRRIIYm+#*K--0K+ic`Y%8
+@Uc+b,h#26'EDjqmK#%#QD4c#i5C&2#L1)h%F#MYHR+"a#)HA&($cFq*%Zp,$-6i
+Yj4ARPNp,QI(Kj83h['$4ECm9*hNiT%"H`cG2FK"KAf'ImHdcZb$#`T6%#IK2&c-
+d$Z%d`LZ-Nm8T'JFU#Z1eaDPLTXC"YNDmTUKYRrEXdkJfTf[@IPT!CF-FT((c02Z
+8&UFj("'h6pSRa1QHI4)ipZqI-qL3!*,m-Ea`Fb[6'B)aP8J"T%l(q2Ui1%2-mR"
+%CB2bFcA#i4L0H8M-*M%E4FfaMfNaa`'4)5VE4chlD"`)XSpa)E03b!TaTRh%`a%
+hJE3@CcS@`lC)R"84Cr%dec8h0lqde+dThFcl#*2'8`ci+H8Y[Ybhbm2q`8`q#I#
+9KT%FMK#kNF6CiKb03pJkpE"219HFTh%)DEJH&M,RL`Xd$L'3!29%IIX`fBHjaJX
+F*29&!rZ3!'FI!P4-FaUcF,,f"hhlB&Jl*[KilBM%Dcm(Y9pS(p$L3MGY0!DEA'6
+[&aGVFC(MP`2%[H)5JJk$a+9LVXBK6(3!-PjQPiR,YEK-T"b"'he4c"AL5RZIZ%S
+M3$h$1`2&eH)DM3-93M64&b2Z2(Z[&[-F+h"m[PLJF3LEm9$4hplMfAZ!ib63M"B
+,()iBfqhG[VdlT(e-()aM''!BTEfA@q%D4b$p-4pGDqr5iPTA)XFALN8DKl#8!5,
+(hZRE1hIZ5KDj,2fa#9MUfk@L@TDSL2(#,@E#N!"6QdPl&aGpTF0q#1MV1R'pA@,
+[d!M3`F"k#)Dr'm50'SF3Q#%BV@qbYfYaN`1'icH,@c31BFP$-IcFjY[EGUjGER&
+C-%,C@helkfjJEQGJER6%-!`cpq+)@!a+#d8M@Pc[f[SSd-kY*'l&TGX%3,R0FFp
+4'#[Z%%Xd$J#Y)Z*6a&+l@)ZPEZR%m6Y6aCfJae[%AH*Z$mG%VplPF"k&bISHHl-
+@pcLF1Ak[Z%rM%#*iY"KYEr,Y66Ya[XpP'BA"rNEIhVJEjjZCU1m'%MH)CH*q$mF
+8$i52U@bC3b)IJqd$pRSY(R$X`r%(lA8D("FL`r'(a--DKj!!IFD)mAD4CaFPkhM
+BBC'2BAZKEaIZC*rVQ2'[Cc$Z"aMALZ9fJBGMLTGG8M"@3f35JM%4Xq-MGVi@McJ
+`1,l#cY0LK31$iim+c#@21M#+4)QpaV2A*1Yic)'3!paHlGZVGi)aMm'!E$,9,Z$
+)BQlj*HA$`&@q[5V4H#jcI"BJF6ZSi(&lT4D21bUB"SCi3MbTF3Lh"G-`%$iPRYB
+iK19-%mIC+halaFlC3SZRhEKb(%E-CdJmJr+HY4JARRATMa2(fmYmHpRrS'%[Cq#
+H,!GZVQrRrM(&f#Yj5&l#H0r"NIXipe81a6-`PD`8cfNF3K62`0cf[-!!rVbV$E1
+L[G5hPqj#FC9$F4DQ[aG)[!!8Al5AD2'L5cp,c,BAqrELhlZ4,04V@MaAMZ*&[Ve
+SCk8qKUNrZ%k,bed0(F6"pN,IA[MhkTM%A1$dNRKCia#1d4GK*VV!RLpHmH`&m6'
+DUhEVJ'eMp2R-Bkq!ami6V`SXFXj,6Vq[ZSRL%XalVdI%klp2[q)eC$jA['(2mA"
+-$1"[Z0RKFSaSEkD+0j(LE2'@2F[$-6(p[q@kl!TaP6f6l*R-AfIai4bH@Pl'rff
+a@Z-3JVP3,,&cl'caMQIRr!8Q0$5TiKh81dZm+plcF%b!qDi$mcV-5@XLBXhrJ2N
+H-TmKePVX(Xj)JVR@JAN64UIh8mAl5('D@'GRHMJQ`&cRQKA$R6h9YkIZE2K81j-
+42Td4AShrHSYYbAU(m&*aVchCcV$62AYb(1&"qEebrS%`0MPNTr2K&0k,hIml$fP
+aX81NU@KQ6r,Y5AqX)Z`$c&I6bR8m'c,%"UUEPUKEb2GiGI5r!RcGKrA"IU"5Z)-
++#m18K(emA(D&aH#['@rVkrIUeS2Ap+Qh9qeHR*Fr,&C58J$T9TmH25%kD0I5VH$
+rRbreLeXhqDNX+@8NiYVT2Ap18UerIPP*mG6mNJQPdDd9SbqJf%h&Q*dk"kKe+`H
+YBhR#VD&YZ6[q$h)9X55i)6CQNZXlKCej"bb#*k0[VilNM)Y"CG`QHN4a8Ij[8+C
+$'VF2H)Z,l4rMKG'1lmqQmXTPGIp[k`L[jH$ZVITNpqpj5&IZ'a,-ParB%lAiS(b
+$HS)pAYS6H#BlRZRT4"Eji'B'P,4B64iR2K3Ea8ILBl%*FZG2a@GfQMh@6T@iL-h
+NKm+c8qaN@fC,EBNpaNkbaEE)6[6YP2mXd(dlqHqYVfr,rKkI2&Zk@f$Lfj,G+el
+I(V00$Z(E5IrFPNX,0TB@BlqdD,adY!+Pf%,aZF)K,9emcJ6Mial,h+TM)eT(e%Y
+(Yb$*"!'Pm!44)4hLb3UmVfX+139,CGU+GZPS*k3B,lj31-Kdm38,PEp-&9pL5LQ
+!m1FV(mIIpPkTiLZN'#HkfE%qMVpYCP,Y@%CUNkL3!'R(L0ifhqD*Vm8h0YG$q%m
+j$NL,N!!,EIdei"lYfp'r,qmca6IJKCJBD)qfSqa4pNJldSk`4pMKpR"4l1'Ldp4
+ipZMG@KcIMYV4I8IpVAcalC(rl%r2MN5j%iTc#cdl!T(FiY(M2AX%#SI--cqhU#b
+r[2$-%'E2$SmV(RcJp5pkU'4caHKQDpDf'Kr"K[6Pl%FVLiV0aZmV8RUq1M5lZQJ
+!8BS3)cliX$!LdLD-Ub9%XmFrDMb[dB4pK6FLHlMGM"alF`lj5ij0MFUcI*D4$P*
+&R`i6NqeKGUMi9RaRKrJ)r`ZBG(XBFmGJmEh#!Gca2DUdJh`lD0IHIbL$rbe'f)%
+fafEE!EDrlHIEJ6[cq6CRjpMTfqaG1j%"[`qd[ZfrDeILfhkrVj3baAFBUcEB3fe
+IfmIfYSH)Xf`[fp2fX0eY0p[9GS%Lrf#af"jN1pN$aHZfSeKM1hMfd,JF`V0pGmX
+S20XR[L$`E1ri(X"$L@lGS'`[4'c2hIS&crD)lqipfch*2Gf5h02e,qlT%Yr"qVE
+clr6Z!pRI10fc"m9hRClY&&md+U#IkJ(qIbe@20YKpe+LNKdL(Pj6@GcIE1fmN!$
+QXTZYDlDqqB3T'cli%)be[RR21l,(6rQSFFmP),0,jSriH"1),-*%TUU,N8aZY29
+1bV@I0Pri@I1d1U,Y`XqEaf$F8%IXmfNBUR3YrMKAaVNbcRZQpl`VHm'L#9-Dp9`
+bA+Ka`dA&"GH'85E&Zl1EEBL*+Z[@Mjp5Q!iJUSEaDZ[@,dL%J99ecR6X82!R0(`
+CYVhi!62VMa)"l%9q+&G3rd6L*pcF)L$9hH)N36bf'f%e$NP*8$Y3k!'qE4G1VC-
+RjFA+mZ1+FU'(KZ%F&bD`2NPTffS*ENpX#rIhlIiK-iiVRTM2M1dLc0GNfr*BG3$
+M!Tfh`f@F**+%3T4-d9)P9)j+lL&6YG`MZGDaqbN,TDZ@UH@eY[&YQj!!8d[bbbD
+A&%f*BI[[3SI&#NP#,biVb$3Y+cJ98SV)Pa@PTf9&S3D'bXNmkFZ)e&VkJYM-`aG
+lbh5CS6&+K2"Sd9"QNS3q@eD5PE@XP0$h9,HYjCifbl1Yrp3T5HLdHF1MaCkfPDc
+Lf9B*RC+XiKEX%2,)UVDPPP@GE)EMe@4e,@(&`LK$0'aEq,E&cSl5XRT5,'bEHlC
+j8X%'1aHbf*f3!)4+ApD3!(YT@F1"9d28XI[DCVDTCrH0-f,rf)6mRL8PrH(1X(9
+0"liQfj4,J"TFeV40Y+cT5UJV'YTpE'2Eb,2la%[SAPMkcdeIBbkK%4pJ'k0PA!l
+2%Xbp+pLpdC!!FY4j@ND%'K6[k)DbPQhJfBEF9CKqmdY+SZ@6Ja[1YB3Q2F%!pAe
+E2jb&N@PLkGM`h,pd,0N'A#m-",L,Qk22Dj1%6Ph@NA8eb$K%XERSCk1bRSak0KS
+Icr-+LmI'5LFi#X,RkUhRY[$0aB'b[QbJ*G64,Yj"0T4lD`RTZBZhNieNBbfK,(I
+aYR)ILDlC*a(I6cD9U+GT)YjDlLZED`QPZ)ZhNLdNZ#!Z''mZ@XK@%GQ+"HP$i--
+`1Y6J`VJ"$M'XLT%Yb`@MpAaEEaG(0(IeY"*C-LXLXeMehb"D%S-2N!!cH%$2B-N
+(!6iA"A%l&p9DY,&e29XAK!*'M@VCa0f$iYc@m5f-!(jY1LdEZaaY)C@YlGRDbGb
+3!16c[ADL[DhP@Fa(mA[!NI8k(84(fGV@e*!!N!#%3('m685fJ9bllZ"aaC1"HKr
+i@16R6TK8A&"8&Q)@0N0RKNcDQYM[`4T(fEhNIR*rcqk&!NHA&B&P-6$`KVi6A%I
+DNQ`,!MK!YY-b,S([*!k5l51b25"3`r1GX&Qf`lq$VD&P"jIN)('`l"L4(GNbBN"
+aQ-2#"bP9lSq#UmX$E6A29NI"H@-+bl3md#AY,RV*6K(CD@YPUEBDPeFAri0X95d
+aa,))Ucqik@$Cf9D4AE3m1(6A`Th$C9IC6FZZ6RA6A`b4hHfH@N+(lY4K3f32f92
+,(NjeNb1'f-UHVFb`MbX!#K#MZl`jXTHYT'8[P`GaQqRC61krdN)-#C@iHl"!eV*
+E3ZXk6"i5NBGXa8e,G"N6iJKaP1`YqfJ*J6VR'J&&EiDbF&[4XNmj)kIl0[eI-jQ
+Y`ZQkZ)UJ%CCpjD%D24T@""@deFTUDcAN#XQ+)Vk0l+kS+PINPIYJE##*9TApV+p
+P2i%IDk6'bIjDaTAUBk![pRcVlDl*j`9aJ#S'b'`Y"j3[L#[D0'NVFYYJf8N5)RU
+C)`GUQH2Qk44433k5Jl8F9$j29l#TGJrI9[L2R"eU0l+3!!TS#6@k8mfQbb&bU*C
+aXA`+VKiQKq(JKXF8iF[$,DEQ`efrFhbi99T#MXdm`I%Mj!JYMh$G84'l4I)XG,B
+B%SY+Y"b4b&Y4MV3BV5&GGh99P%GD&(YN3TCEd9KjP$'HX4L8mQ-PT@2'j*@8$fC
+4%80Fbk1iZF)Z*!-$2-Rk"'P4SE5+$bN-EVP@h`5q#AC0,G$VadGr15T$MT,[rUm
+%LSlqAEX2hUlSB&QVU0#RG0c%@,kVpHI[YY)9cd(4`EQ161e98*5ARa`@rmp(9bf
+Zpf@AAJ0k$')NiSS1X2,f6`pfaMqpX"MMDL8D$08$UGTaS$TZcp!a$X[rEU$2q,0
+&rSmq)e4Nb)(i(beM@X)C)8kiCS[j54UiA8R$aL3bK[pSQD[PD%HiDD#i2*Q[CGa
+QJ&2q+-HB(hcMV%V#16&K`HLLF40'NV!DN!"McIGDMLfRT1pmJj8V0XjEP4Ma@+L
+q0pm$"J0l%#fKfdqXX-D4K$f",*!!il@%,F!N9ibF3-K!jP[cM@qq$H'!2@&*@@+
+GjU+*ECU"U`K*Z"V)3MP45c5!BjD+XNJ@DeQ8m2ZS)#HCVc9U$"G'($p'JRZ2566
+!(ZBVmkAj`MGIrA[L-'`kBYKd4%)I&,F&-TXpXcQa4M)`1G(SM@4lI1kEcrrBlU%
+#NU85mbF'4mE13ql*FJS1VJ"2q1Bcr2lZ"#fRP"ImU@mq$3[QYARaj++b-0+G)b6
+,82"8HDb@8eh"kD+1R#D2dh+D'i$545ej[$a"5rJ,Y-15-N28-Tr)%q9*R[NN[UA
+@mN4Al*kLUYRN'qFkmLFi*lP'V#CUbZRQBbhK(F"$&-GRQ)mdMa"F1mG2PUGSHE)
+E[QZ)QQDMCcEbaMbr#-Z5Z0+qQUKK2[60KlY*4aUBR%J$Za-Y6h"Ci6eN2[$0"lZ
+cDRPFH4YYm-d'860,q2%G5TJ-`4`1KX3QMd8cR5TRDRQU%m[A&6&jQPN[6pIb0-G
+d,F9)H3E*-j!!D*DFVH8Xeh8Y4AXj4jkTj4a(35h&!@DG2-ZmljYeredLRi9bcMC
+VYB56!+r"S!Z5jmKcY6c(`BHeP9RMQc@l"X9cNlBRjMhI[*F3@EK1#%11mFQXCEj
+MUa3*9i4%DlcVQhF61Gd+)!`0#N-NBEdJcc2[D!P4+5pX1U!*cTFAb![P49UHlaB
+f(83RHE'm4-Z,(4I`!ZY5XeV,5a-+f)lQEGqm[DY-D9Bc+TFi&ZiS$M4[+326%#h
+KPF#YeeRdP(0*3L%V,j1ADhQCDlh1STZm3PkTj48*$j%ZjNhI[,Q6-E@mXKch0hc
+caVpR%RNj#Vl+[+lP9@k6dKdiA+hPeBNe9`rcQM+[F9ZpcY2,KIKI)qGT#9m$ESc
+HiP!jAbl3%PB*A(G[dFHmkTYAGc@#PM"2i0,kL,lQ&@9HXCBNI"INYHCP,Dpec6!
+!qkq&*"ILfL*jRCD,A$--%!2PpI)',H%@`#8-%0RQ*@9HBY(!$H@i[qLE&rq$1q`
+3j)hQ"5eK5F#i$d,*0fPj8p)[aUa5CKA!-E!j)326&5d[FM!-!d(F,'r4mQCS3X,
+i%A+a[&A,a3k$BH*`mla[R([+EcekUbX5GN6Q1@8Ja0BblU2!m+hdcFSr"L)$DaM
+IV0r&J&Sk'f#fhM$2qZEC[dF#f*[)fq6Y@XD0&NC$3('(A+,P(3kLd5,A2+2--`a
+4Z9lI21fETrr6B9$ZbkAQ+5eKdT!!f0(GUH@GVM,Xk-b6bN",6`Dq*#6K2bc[NRG
+V'4SfZ0h!%qCaD@#K)XhMR1*Zr1q4pfS*$`IH$84%KVa2,Y2b[[,G`'2bI[1SEai
+6$E*%aM'6mdZQ`8LaH"+l0jE',r3U,XPf&dMHMj)H-#ZdI+!Fh8GmmmKZEfFb+jJ
+4(Q9'@"EI%0"$mN'5-(#3!!r*Kl9mU"c#jHCKDH#2+JfF88JqM2pbqBKQCA'KXj!
+!03r*&G)m"$MP#VLSl"AY@MSK'KYG2"N1[Z0L@)BAZeeiD%T%%NB0mP(jQ*D2*[c
+!Y(P32LkIm-b$IiNFB+$!ZhKHYceT(Y!5VCGB[cd9N8p"XYP`'0FEEq$5D&jak,i
+m0FBEq6J)EL&[S-K1P8m)CHkA6mYR2(0rFL(r0&I*ESS9j,-'V3PI"9l3Fh`P5GJ
+Gb1INmeU#p1)@C(*94+i+ADMCFM#qShmHraINLeUqN!$d5j3[4H4,'2!V1Y1qJX3
+krdAmAcEhDIPbFN-XAiR)9`"#5VGL$*+FaF"m3CTPM0Sc31eHqDUjac2h*VIkF4H
+"01aLAS[)elEP6MAhF*Q2iIqkI%2,ea1EL$hPQr)Y,Gpd%b&8XI*Y!rTk1l'CU#4
+A5db9Ua1'2TA-ACkj+lR#ImIGicRr6XrFQ9MCQlZC9f!mN!"JSk@q@4Ub1*0"@A(
+BK5iiT$JdE52j"V"j9lkRjEZ1GkU)+QD*Z8-D0Tm`E$iKhm0rMF3-[XEa$UHiAEi
+[$I6L%INqjS9D@hQ(p4HaNPcJ"#+BA*,[1QdYrZ[NHLhA1HDT)ZUEfq3'qB&RE[Z
+,H6BijS(ETIc3B%lkd(8EacG'j%EX%jU%c)0"JXd1S%(rMAVB%6912lGb)hq!4Pi
+X2j)IHfCaNRkJ4QEkUBDpd#D$%@f6Saq1Id,b%b$iUIa-bdmG!Y9%GIPj4(l1cPr
+K*M3(!Jb'qM2m0mX[Y)5$-LHU,QV),b2b5jC0(0!H+cp1mJAqAjQEYIc+*B(pT[`
+k)VrH`6c`Jj(Q&JEXB`"fNrc'h1LCQj,-mih,A4Z,V@mMmYXGc(-MPlNHrqmNPTM
+I1HCT)2D42mJIYB3+N!#CTi&S*(mbQ)UKr@2QiIJ@'@Lja6&-3p()A1qCkj2-%lK
+l$84$FjeRVNXbc`h-2$q@-mmLhb`5D9NLKDQ!NIJHIb1Kh6#1CjU)*QDKZ9DDKBc
+aYCc#`ZdD4mh3-mp`LJA3raRi[N4`G3I2B'#%mA`8$4rhUHHd8"d5+8V4"0ERK8`
+6''6Y3DPQ2PA3"'GBf1$M6JG+SiUDlE9j$p&%Y##2I%h3L6"q6846-mmhmlELTmP
+h[3CY1N8La2kKflTH8d9A5jCS5jV508&GPYJlAH1EDlEA![dJep*Dl%mC%FVBeVH
+D8Ke`RF6*P%Q9c098@F291bbZNqK+He)96AZkiL"4-PIjjUUr+&j6PB4@U3Y9M4$
+dBMr23CSUZ9'dKiK405,B`9*eUU'TZZ2U(Q+%ZC,fSTUHZI*2VLBS!CQVHiK$U*D
+j3P1YmRKYFlQQfJi)MYH*8"diEQAeq)fXhCX#Z,AG``1L5EML(!iV(@QZ!-X40)I
+Q-UT,p6`$dbj(j!3C&40jEc'BSQDZTUJMFSlA*i*!MaT33df`L'8iX)DL[51dpil
+A$"""Z%H0U,'Q4Ll2S@)!l41KIGbm@8ijMI&[BLl9""'Ffb`0T+B4DVU$bLpPb1B
+bC28!f5A8c&cXQ8X59%jaeeK)V'MI#%(e[Sh+,qBbDq$Ih&bNUEQMmT&SeKE88P-
+,4q8Ma5KUC5l8e-T41FHcU,8Q1-BbC4mT4TN,2(0"JXS*HMUq0e)FDFlhc2P*+Vq
+3!"NKVKjN+Mr20qIYI"%#QBXBfkXj)pb*Q82b`&YYL0S!VIeSIdhl13l*%mHEFkN
+Y(H#CFrrL%-M`Q$2ba&KUCml4"-9G)YlHR+fT[@X8MRH)8!FX06[mIa`5EB`V[#k
+)NmRCI)!V6bSGJ-imLcV5JCij+dNQ@*d`QB`6TG6*R+N*AV9-*K`rL%$,4!G6Cde
+a4pTaBJ*eLF#1rfFb3Dh8PETTLR[06K"&e$e#hAmKNflipc"c0%'pahQ+a$(8-`,
+RZHeN-SFKBdXK1K#3!-fQAQD@CfBRb35+2XjG*UE5)4'-20[*C"DA#EpIkQh1d06
+ENFN*k0Sqe&F6HTA*j!3aR3ieTfZ#45Z6#FIl8Ap0d-`aDC`STT[62--'3Bj-S*l
+MHbH)%me-cma-NJQmJ$4"`CFJNe0pipb$IL16-aKE1(eTJLDEBCQ*k@d!C@XDi"#
+G+FkJR!MPl1JZcHDaL3*2mFdTIa5)Ya33$D4"QL!QiL&dMTKM6MBcT$QC'iUGK`K
+@Y$5BKQL#c)k(8%iaRBC+!dZL#!hpHFR@#jX(8-b!iU)@#,N@KKk2$U0KQJjcNp`
+Fm5%G6X205A5%*SMaq$d)Fm6$0)*'DZb!ir(Vk8Jk5K1%@m`fFm5j0-UFU'Q8dj0
+`r'KcJLD)RhJ5j(L-4QZ+fm,1%@HDihecr2Ba-fi(HkBiKh)Md!0YT3&Tf-I'`-*
+'8qJmkm&hm9V+-mGT!K0ab4c20p-dBB2$8c2(ap"B64"'-33AL%YT("9S'ZFJZ%"
+FD)lecE&r$k-33$%S&m+"FA`%pY(EPhHDi1[+aF&BLbC3S5EBV(*aPiXVc&6I62f
+l1$3X&hH&Z*SQ4QML$X5Rm3&Q2*VL5XDEa2e8C+CS-&b)--H,DC)Q#(NCK*[%EA3
+-P@JkaS&`NlMC62E0j$qHa`(+#XZr'6D%T4'#SQ`EYfZ#+)[,@L,ZS6+DV1%T%*B
+&#ha6jTZbA@9")-9P,49hdj3)6GQ"kK5ZE,LE[9D)pfJU%I41G#bKFipeXpF+mDB
+TTH2SH-q`#p#rCLmiV[+XY8)m6LFBi!ij%4I1m4-MG1+ZHCeCF!TH+X"VFCDJm`T
+`qiL&1P-*-LYc$*e%dcec6(+k#[95(JcjAU3C"Udh`deA($qCm(!*SP2S9%f3!%-
+a%Nq)TfPQK'Eb+Lh*YkILIaTK9S%3LC-m,9E5'4%kJeFdfiRjG2aRQ@*0XebLP@)
+9cBl3l"fc&IXB'@Md8QNk!#ZL1@DLCiU5Xa8m9MRh5q*91M0#CqkBVA#6#2)b1XZ
+!Zk"GiJCl#eej0Q'8KB5*CkZha$YdVTQJ#@DS2&Yar$`kAa-F6RQ'HPZmBmClCRa
+bYS**+Ypl5laY#Ma6N!#FVG$bQZ)k+"jpa[PQR%L(9e"Hm4KJML1J*`-C*TQ610F
+4$T!!pc'3!&a!f"6%V9EIKbVkSJKGp(2$D,U`[,Da[KRlMpTS',#qQ#l4a0SQ*0d
+S0TSa*PmD+(fPBCmNJXdUA8VB`PaDRL,2j%S$!b9TS&)NJR#*,L-XL#jcK,94&TV
+4G!9GkCR4Ia%@2&PC&,C4MU#Vk'T0F%KdmH&d$Fh6"+'4L`qPqE4!dra%I#"G5`X
+e`9$9aI[6)VT1%l4#,Yk(VUFE0&fIL2HN'qNQ66FQiPhTCVT&%d3m,Ri3,DCE05e
+1a$[3EA5l*LKMA,`Yh8&,0-'#e-9Ede+k8p254,`&h89hDi*maF@EdMedVbCS99a
+m(lU2PQQ##lq,0k6lk3&08+#iH$ekN!!HdJ34LB[ASSGTZ5BS4Pam,hU%9QL#rX2
+&Up+Mp*LQ4a2a5[3i2D%*-JmAer3N2B9$)Zl6dr5-*JJdA,`#28XV06fEL#YkMTl
+Ap&`m,LbYSKFdV8V%Ik)Ak590d&Ziq(Id-VfL#6D),[i9[8U[DASe%IqFAUFh0,h
+Z#'UMf%4[4ZK0Q)jA(C3IbjY@2RT-,Z@A56LkJLNMdp8QmCQ*HBEYY8)M#AV0c4L
+ILbrT,A1dTVK!!R%cbM1MiRQN1CU,H-@9r*AiPYk1d0[mAS)S[S5`aEPl%f4M6-R
+IL4r08Cij#L@8a8DM9%K1q0j2`TJM2A0NmKkX1IQHK@"TT'IBLX[G@aRHJlY0UKR
+K'6EQF[FJQZ*l&D4RMX![HFmCPE)[M4RZQq&rMm1`13A`N!"ICG*UFlJQb%Ni1q*
+QQ'H'*B'(S&-6c&J"2*aXUY!l%AU((d(!`%2`9+kYL+1r`U&69GB`KhN'Diii1XY
+GIA[*QQDSEiCZAdD%XLC2eT*ek9f$p3VX+MNAiQD`C`BRX4M#b5#SBLcUb3EdAS6
+H5f$4Vk"S!VIl4$J1&XDaJ)U+X@JS'jY"RKQ8a-*Cml,&LKRS'fIKpGY`$9dBip*
+80UFe*NI6'TFAFC2YQH`N,MPFV01I`BFPLpC'D#d%1'PKMm6+iQK!jmCSY*ElQ`'
+H'C!!410fGkqYE'rkHkCrmKl8I(b[JqaNqRQQAr)H*(emlb$Ca4cU'AEXF[FJ-H4
+lA@82dpFcIC2hS'$NHcePEp2(-qcFjHjGjqleNIe-Emq`MjHl"qGS[YGIjTK$2-1
+ZAZiHp*9mEk!FBRTjKMfqh,ejlYj3HEMTkCQHbAYXJShZ'5k2S2G0$dh[Zqj"h(6
+h6IGI*dCTi)k3!%TABV,Z4ZYS[@IB%-bY!YDj@NE+20TJZQVD%+i#`[J(42"KT!p
+TSbBR!-+e8I44K$lL*8[h@&%Zh!E#)4qqJr5akD,TBjGRP"a0Qb+dL4eDX[R"#4L
+'mH3CDESb%$!R0ChT%h1`CcSR4ra2A1Cm#2FrMG#RjCP6cF&F)Q5[p"PpVZQcF-%
+R*mU6D$0pB3ibR64Y$TFmZ&0'Ap*AQVi-Khl%*p(AjN"0AiG$IaMrKVl9"!d2GeB
+4G2XG2G-a1I4rkqj0P%@QJfFk*)Iq!jPQR'K)6T+Pp&f%[Y[4!jTJNJM4*-6[ap(
+hQQ"lahdd98iclFR!pi[-3G`!H,m1dHIird!rDQ*"%-3hdb&EEfF1N!#Q(DH!'4I
+4MrMr4&Xd352%"K26jDN8N!$4"#d3&cCGRQcDNS&lPbC6[M(BhcIlKeV6LG-53NL
+%%MT)JXFB`IG$%e3r@0[*QA+Qf8p*DIE$RP9*'-EALr),95C2#YG*mGGf410Uc*B
+Y@iC$(f3qq*05@X'*K*Ya*Vc#8Y3HTSeTV4Af[9MXSED,9DUUS"AH%m,019219QQ
+USPCTMUjQ3XUHj4Yi(rdj6LRh'K4jQTbP[)MbrU'M89KEFheRbI19Vb*D366%pCd
+&#AXVhl6kZclhI"4jYMa2kBM5ff9"#PjRf2I)Z6*3kD4J2+Sb9+C@'3leZI)q98P
+90Le0#kdU1G6RbK[9RUU+9[!CBe6QbUY89990+c`,K9'C+bmccAh6I0ZBTZ!XaKK
+F*Up8e50`VrYCjU6J6-Dec*1,9!fePeCi-3VA-Nr10r[kCYrYYHcPDTN[&kUD%99
+c"ji`(Q-bZ8AHT@UTfPT"+i64(r'PUSkUUe8G9pJYFV&TjTYQZjK%+kKpQ&%Abb@
+URSTU9FpP[P8Z-8epdc6dSLSX')eANS6RR*cZ'Uq2#A0!H@fDq+E*AkqaJQST`@R
+lq'DIIh'DiGG%Q4E-5""XUIUUJ9EeAAmZNfqVKQT[dpJddJV#)Zl2CI*Ce8JeeJU
+1B0a6bq6$DKr94#Xm1BA"@3BemYkqfAYl6cQ0NEaI2U5D4P66VCT#V5"%iMT@b#G
+9-i9AAcQc,X3I03epdh"l(IZk1Kk96kMQ%G9m4frZlAVcHIQkDU&DDJ@&%IIQmr*
+9KGFkDGA+&IDmA'8Dq+E"lYl-FVfj5VkL@UXf@N&ca*PIN!#[Q2UqU5mmejX-)HT
+Zifk[NLqBU'pJZlDl+lF+P1VjTYlZVS60R$4X-kIJ++Ef-b#Ar9aAVJDClUrDQMS
+'"!4*$(IPD[QT1N#edqS!edfVj9V9ARA3#X)M"JHkA&2,0l9f[C(,1B2*Gq3De6'
+L1[iX!P$3-h&Ckq9(kN$955YiJR&Ckq8'8p-h-&rE@4CN4ec@"VP4(444"qeS@)L
+QZ'%hbar8`DUc9V!+iiEG,,p6A94AVEUi)U&+0A[jCUrG$3Y6-@lB,q5hUTX#8F,
+kLc0r+Eme0Aa6)i5RG&bF6K("!"35DRHAj`[jTDRZ'dKHGlGZjr,@VHDEDVYEY`k
+hEQfH@1[b!5mDN`C6-HBpr(ZSRPVKL5fB(JQIUDTk531rViMU&DTdYNk2S4JK'KI
+ZZlN4,QMU%09E+b`r`!8Si$l94r8e9FbHQTI3i!,Ff9-GU[TTKHNI6BYi"G9I$G$
++HB8KVNaPhe6qHkjciL@-UDNU1k+bIjDm+,c9KB[c+%2PU)&DiB8YA"`8UDB5IRm
+A0p!9je1k'K5"8q*fAS$`#X3+6HGGDM!T+*V8%$98Ub%1mQV86KfQKTP-Nk%9A--
+BmQUdMcTF$GF`H3P4U8Dee"&UK&C`#@08UP&eNqiE,,kf$K0i%JTM8*eUUT%40A,
+l8!+h-DkM,M984kUMY$V5e3(&TY'qdG[V1-V98BmDU&%40@S(PT!!'S$MU"RYTij
+@-DfJK!,()GjDM9Dj@N(Ya)8eShe0a$I1%qjr1!kL-A!Fl8YC+NrPDjAR-MHR,12
+laKI4,$al+&5APA+E-T6aH0LfL'[PRQ@#'TSEccIHAh`AefJaheAd6FAGI)GRP8N
+$cca53r%ISmCU"E89pM,8(ZV(0&0"'MM,531EE&+3!%UTF5C9Uh'ZRGZMb`[8H,1
+(5G'U`,9cHqUM*UK#VG#0h)EYk5!e849TjGkrJRJ(ShbMYVHKHrF+GD"1UMLL`UH
+YE0m"!!qZT3[e9*28-9T0FV9dSDi'R)AR-ffY"G)TVU8Vp9!P%9@bSkAKk-hde)r
+Z8+@N3)HU6%h@UXcKfBmQULPUUS&LA129D#'HrHK)GDbDTKAmL"L$IM43(DH1emU
+j'5(H2l"qB(H08FFl22T6MMSKSNliC6U$GSI,'N,$eBRU*+fFr42L3`2M"fCA@AK
+B#TFeP!jAdb0UqJkBRIm8(8d&DSBk@H19C5&c(8eMe5RU9(kGA9MNd43,!Mm)GM-
+AT%l-A$%DNhM(ACKj0)eallB,Q5Z%*'3ZRY(LmC!!ZF**$5STcJReB2#6(rcd&h2
+"R5V1A-'2I[$MEZCL'cqBqU'&mDLAa+2b`MBZSR29,$8lq#(iAZ2*H-Q(k-e4CfU
+&e`BN(U*hPMTEUl2+(k,hR4pmYk[IcLjrL0ij%AA1,`r41l2m)AVRU[1dFLC3L%m
+0[[@$EhH9"38@Pc@9MP2R4p6j1pSBANrFaUI3QHS#GD&@&lJf2S9QUi[8a9VKG5P
+F*24U`6Gqm-hZ0SCBLY[i9*UP,P'ADJ9R*mimNfB&Ar["elm-)+k0b`H3!,#0RAN
+8DTJCI18(H$l5lMBZeh%&ArV"PrpUi`$@G6*J%cXmpBr8h1!,VHDk0Mi2*(fCZMc
+B((bZ&3bQZ)h2SrRU#R@P9Y"KFEqG4aHVUp69@X%2LX'"ULhic!mqqe8'S*AcL+,
+ck5*e684GXeA3Tp@9VTUjG*@DTqCV"I%"9c1A,JXqpB02reN0$+5iQX[S5V8JSKE
+Xk&ZXklP[&p*LGDeDU*86I5&qXeUNVY2+[Bm&m8A"*hl`bHkqKHm6pqdLZNPGVfl
+3#PC5R2NkZLRBj!HER%emV#aXfM!5YUY@cPm+HDm,2[D$MrrUeILEAVKA2r+$MhE
+h+YlA*)2289F!NcibF2q6"Yk2C0JUe-"+94UiYj+#a&[GU'l5#ZSe(L@AdE*JBr#
+K$$Cb!4pb#VcI4GfXEY%+$hH"FJ!T(P#,YA+H9)MH(hcJ"arm#`Ye#`Ui0GLJ&9l
+I`M8q5!m'ki0e-X"6NQ6!MdS+0Z!Jld@Hfi,hYB)b,Zjb&+`0eXJ!jQXb`(2`+)!
+$@kEi8D3'lkREe4eUL9UUlT3"(ZU@U@iA+F'l`6["kZ"Y2h![6rV62Fi2h[Rh@`Q
+#eArl32V"frqA'e5kZJ22%`MH%MCi-hK$hDAZ$Plh%Iih4ZN"2)"5JYI825Ti$Bm
+882G!FakmkJH[rQ'N'1$j5CRU,U'#9i+AJjImi*@GQIcJj9dQYRl`dMmpQM29hA#
+Vf4#m',`3V!UH$ji,9JE2"Xr)9M)VH&Uf#Ck5l@A(i%RC+AJLH$ai,(K8(P)KH0%
+CGA["#iPh"35ViJk4A[$mRbm-#2JC4hmiM(["bYhQiAl`l$raSq!Cq%J'r!)M&Qe
+j`90aFC%A2"PApkMJ#85#ahI,5VhJXEMDaJ[i$8@XakN8[#i+*X$Q(km!1+U+U,Z
+fU0RlmpBejXF!T)3fqhZ%Tp6LBD,ciIc'YBrQ0IUidE10&Z$rE+02'RhkfHH&8f$
+e$hYr12Y(a*lCSd59Q+J+MrpUH!T&f[LHG``AHa6d['0Sp[b-M(5eK-PNK4`F2")
+X9rHUqi+(r@$&[adl!cc8L!,iK@8UU0q#KrcJSCh8N!#Ti(SQ4`82"Jpi!6YrrH(
+Dk`82a2f!+`82L`bJlcF&c[,pjMe[ajX#e&,'kAkC(b`,lP2,e2h"[Aj`rpq8QKl
+J-6XT`6hU!4@!lG)9e(iLZ0X2l[l6@M@!#eHQ@SDji+lJcQ"TX#5i)lMG$qlDRG-
+2lYa&M8YhZZ6j`C+rE1rmi)jG"RTqF2XZkm*-GEp)#fi,EJd@"lF%0`Fh"6F'0rM
+"EArhY"IFQRL%4E$iEpFm,q#(#i@2D`KZMKZ*HJ'l4B92E`KZh2hJ"Mqii6qM5UA
+JAP(!,lX3DaZ$#9IJY3[c4U`E1H+)&512Q,HqHCZH5r(kK@lAMYL`$LpG5!eIZY"
+XrN*q`N8&['*KdAM`R,qJjd[Cic1'LfU,#MJm!H%#K#XXQ&$A[@PKC6EIQF!FH#G
+cbr9b@A"GX%JpU"i+&[V"pIrh-"CJ8Nm*VP82U`#ZN!$T#UmH%X%#2eM`Tc9IX)J
+CjN%`c2aJAR"0F(9`9A#P(mcIRG-2j[feR[H$EFC2IR$ecXf6(ecekeE$$klF0A"
+RUSIJh[j8F!@d-Lr*9i,,j@["CF(Fi0,J%VP4IJkjaYIb@i+e9(!a9D8kY$IY3df
+aV1k!*@ehkNQ(8!lPdRLD5+9BLTf)cG-C0*[1T)[ScH!LHMZiN!$HSIGS,Ae%QqK
+6qNjjd0G99c@$#e46e6`iAh98"`ARU@`e5)e8Si*c9E%U85HSkF%jkKaeIR#fZNB
+Y#-lbJLZ5ipIPbI',ACU#ZAq0AjFQabrf4q,ab`XZjNKa-@MXSZ4dGf&FKZS(&ra
+6j18(f0pYP4IjJA-aqSGka3r1rHr1h`r1qHpqe3r1rZrkcJr1fVNXUK3XT)IAV(e
+rhIU*mGGPC$rp-Em[Bp2D6clp$(Fq6pjCNVd!%bAl*Z--Ph*4ZA%GdAFqASd"DQf
+!Kf'XaB#*q6)QUL0[604)CPikA05,LEe`[fC-e)U*fZ(p1Y[Z9iL*ZL"d9&B2ZlR
+UU#V+PH*F2kb8rlL(GfSdi(Xi0dcH#k[I'p8eLJPFf#HXVNQbZM[$kTVf[$-l*TU
+0%[XfiRp-0-HjaDrrqI(E,F2SJRLd94Lp0Kl0qMhcErq&MB"+kjKS8mL3!1bAJ#5
+'p`rb%$i&SiJDKkGmB&i"dQhML"m3lkhak)CfmAjV(lq6[QKH6(4ShUMRA@&Uh1`
+Bch$JYJbGNKR3+5cHiSijH&Z'cSN-B4C8h59HIGGiPS@SU9ZmYZlE-[IB9MdE4A'
+'AJR-8#FE3('p[EGPlE-0NEla$)GZbp![Q@&K$+p$3!DF"fc,N!#p$E-`dk+-l"`
+m0H3c)DZSjHPUZB"+p*(J6,8LA6h#X8H$1HUaG!Ald4VUm@#fHL*G`A1L+PB4Xlb
+!hl*8QPFk`3[BbLTh6(&K4$d"C[0lj%r*,bbH0$%INcUrU5LBNlcr''[`%frDG*I
+26&jH`ES![+@(h`N8[J@#,B!XhTSVl93m+!%c0qE#b)r[[SXhCHeiS#qH-Y'q'Xa
+M4@h%-NYc5q%E*1E`)f0a[S3I!i[cJL%p$aq#a,H@PNhMlG36TC0+-HD*PlTRpqL
+*Hqpf'p#$c@ZrGBq"PH3H!b[6h90JCFf#h%)m!%3faU$!m6BiFrcJFGLmi0ahF*m
+Mm+3NHGL`R')m3!#ZpU%9I[bEBI(m'2K`af-`)'dKahHTR6)Zc!'(2,L@cqCB+Pj
+M#'[6m"jFBT1@qR!AMFHJKXA@&4mHeJQc3#2((cM%e35*Hc)I4-I*@U%TjZq5-1B
+`#'-TH&P()TED'(KdLXI')lEr4mXj9J(VkX6MIY1JC%VL"qfH%2mr$3d@F("MT8&
+`F'aP8f0bDA"d8fK-D@)ZZ3#3#4DG!*!3XKN!!2[B!!![#rq3"%e08&*$9dP&!3#
+Y,$I#X!1PI3!!-Tm!!!I`!!!+Y3!!![&bjHld!*!'*a%0`09PJeCQCLEhj1EKYlU
+P$G`VNe0ZENC@`XKQALXl1Ee1Q@jkPXI2+hCiDRK16hEV`)fr+Rr6IFb18,+2pB6
+YSi6(kYLPC'[NpKZjcFKa5TjYFPZ6E%)j*C[`Fa2Z&8[##0X5IK&11$QfcpKqYQQ
+hIA)mYXNqXJ*IA9Hff@D%RlIerGEfXD)4&VQYK'ebQffb*Fr#N`e-m!,KJHfm(S!
+"`,3P!!lm@Pc4+&LAlm9I!(j(f)T8JU+c1IC*J'a&mAfR@&%#FT92p5Z4UXCbIjh
+MU8B"XhJN0D+rUXUmRq!FhSQ1QdS,GD6`-E$L%c1YLq*lY2jARTfi"T!!#@,$1ED
+4X"E'X8l#MRXiGSJRG")@[)9MAq6BE*ilK@2e(%[Pf'UH)m5alEbZVq"$!"ZqdX"
++R@"%,Qq,[iF0"%aN3D30Arr-f4F#XNJc!@""3E@B6kmNb4&ZiYhdYbLL"c8L2Ba
+h0@YMUF)A6ZCa3-S*ETI#ILT6!GJBB2FC%Bdb#S,'kdq+,9X!CU2Jc)lbAkL'U6C
+h1#6j`ReF8f!5T,%ZS5AqIUFKX,m)L8!5liXeIX8NS0G-61+H-Smi[hK4-Ae(Z1@
+)'VjI9PGSiRaTT54@h9ST6QB&(GpM"IF999H)PD@0N!!V9Y&V6Yk%@F!@2SAL[LG
+M`RaS%+XVN!"1&MEK-qa0BBc&#@[!F[0Qr'FXIR0)3DR[!GCbGHKp*HHL(Uh#$&D
+i&aKc6XpP"3r[BZVAMd(1kcrRHSQYcG4(-Q$dSjd`lZPGMG'hLjLk#ANGfJ#MYlG
+M[Xf)&d"fd`kQE[Nfe`$eNHbi-ULEpY$rP!HbINe958@mL2K%$hbY(GjJ5hNeK#G
+I-[+MIU"qlIjY!2-d'[RE5N'`3YB[IiJXL&-EVdI@VhD`4NLVhJ2V#Ip*#e0MFK[
+GqreAfC6RZDTL2R)fGPD`YjN9l-0D[,#-6FXX!*M`$D0H)U6Q&l&ZB+R1"MNNUhk
+IFcqj'iZNV4$a25jHcfj[0ZZZYZ)hrJr!ilG#qKp-+P3QLQ(BN!!6p@[I4I@,e9$
+(f`rJGcGE!Lc*'C4mcYVYV(#V!U0',BRV3'&l'f5Z2`Dh6$R#GD"`D`Z-bNL"l1I
+q"%GV0b$H!CRE@eRKilQF9f%llbm$+qIrBal)(YR)GD"`DbIa1Dd$H[iH(5MFHPM
+2hjl"G5"lq!CN3C`bH$fb4l55$[bd'4iNr%AmXeF(i$Il-4[24ieJKqkh0m#aJp1
+KqhJq("hEJCB8r6RrIaZN3LGV"H%QTe[b995*98f+%PBMcP*CUTG9c3R$(j[1@XF
+6(mDk[!AXSBRB)b9,f&FA&L(ZB9e,UADN1`,Lbf$iPME@+SU)[B4I4FHR[-@8CIQ
+%8rlSJ3FfXBfrhiaih&QaVQVk[if$Q4Yh)ci,m@f8AmHAjL,HSI-CXpR)hdPmm%h
+j+2ma2Im$Ka&[jMM2rp![M2aaA+pR0A!qbV+Ce!0M6r8!6L085IA,QY-dT3G3#e1
+F[R"3N5*1-aFYC*P1TcZXbLAqJ+b*YcZQ1qj`QUcS!-#BCm'@SBZKaq-5brfK&6*
+CcC140*JK%6R&(Nrjaij['AjTL'J1`-2Y,Tq6b*11YN!X#j*$S0+IbH(fP*HB"2#
+SFFde"kKVC9AP@B)Im[$1Ur9D((@02NhV!(Dm&Ha12K2PND+m48rl(#N3#)G$BUN
+FL)h%f!pqa0@)q4E6G)(c%"bqIVjfGihSQZDD1[9FGqJmV!lIe+QQ!$`X$Ppr36l
+Jd6m*r+#Z5Kq4+ccN9FUd089k[clj'VNhJI#XPj(%kZe3+DrK-p18ZhJ[ilrlm+X
+)djT&GZ3JGe*k[j*aqemp-Z)m"JDP`j'(4p*m8Z"mBI@k+T*Q&X$$eeIC4&h*YK%
+2'r'iS%5AH3L1!4pPSAkp'$S2V9qRE9L'BLh)G6VfkepeZYC9-HKM-LK*bB#6U3r
+lQK)m%N(q3pA8!G-`a%0V$03PmU4ljPfX+[+)0*N%m+#`1V",2UUVKhT4Gq3cCLi
+`Eh(N@2Sc1DikmR-m6!-FHF@Fq9aKqq[KpY3NkQ(fiHcIUqT9Ccr!iiUc(q3aj1`
+(kcVNl"-m,MTl#X2CXd-r+c!$F2CRkr&[ChqZX"mkq`52)@GrPXBeCcr!)q(XEFJ
+MBHleZQTb`ifq0rp`j$0QVML6ikSMIim(K8Q!)kraKqiS&&I0R((GNDIqbe%KdAl
+PZ1bS"RKFF8+$p4Kb3JNHPjAq,)pV5Mr!`q)B8-88j)(#-'MGVBk![dr1HLF@jcZ
+%H)6VP[IaU+KERZ#4k[l[QNHmk'jAkIAFTcXqSBJT@#hHU4GjS!)&qVcQ51)4N!!
+d6A6KAK4Z"*fUIUcMd5[)pjN#e29Mcp(Ma3Fmr@8H#@90p&Q2)NEkfZcp'-CAK6r
+5S(3qh96HA)K6Uh06VRHMCmV9)-DRQkB!2&`"6308)05AFcb5d5[``PqBdr1TT#P
+!2IJdd45!4fbDf-IMmM3abG%B#3E+fh3HApk('bV*3LhLfCm[%%EHZ`pbK$YIQ96
+H+BJ(Am18Be#lAXIr1i8lAp`KM&b(@mma(XZaLmlAie+I'9-F[h+KAfNr)m'$GZ'
+"6JEFk(Xqa6%&k&Fqa6%&i%&K-`A3-`UV+8"r8$PLGb1%PCGZ694VXKU5J[*eLi)
+-'6d%jVc1`$3NU"(-AhSJ(YQ3!"56RKi*iJMZ9[01dG&d5%D%IicrRiANIeaGZ4L
+c-I5p(YC5HrU@bAria-&hVlXJcp0*Cq*fY9&@A&)bcJX-$5RXB1((AB`$,qaPIEr
+lP0kB!-A5T9U%RedbF`KUibb`#)BXRZaUdXSHXI`af,V!k`ZJQ*5&r"'r&2#[N8Y
+8U5%SKkk8m%E&GIjH@3hk3e,N'RfXCRD23qf0N4&Ii-4TV0XGI)jKXK)l8HAC+'`
+aLIT!ihf!1kf"1ScH$LbrY$YL3K$XK!XkHq'+lN-*r29q#(E-jH(M!m-1QVY%9Tk
+VBZkm2$&[EV'h'*qH-TFhcfbP"Hck&C4Br1@f(Q[ZpRcU-2ibMR@"S#cL%r%F4F8
+PK2&`@j@hFL*QI,3h[l@$$rAT2KeBR`#kFCG&@0+$N!#2ceQ%TI`CI6S!hj49fS$
+@8h#P$1",D`&[EV&*K$AA!&jVBIF39[KG`%0UM+q@&$d(+a(l&Q(H-N!eC'm3GTX
+#H$(&`R2-q!Tm%l(e2-IRi!R%Y[&ZI`&fS-(E6GLB)$`0-2&K`Zj1!raRBMYK#jk
+(rFL'ApT+fJQ[)XBpdH3S(%AX-i60fJ"r4)`@Vf$#@SDecXXKV(3R`iZ!HBYi@ae
+NH+8PMbpVI2Bi`m@&bAbM9eh(2SdB[`D6XirKTXTNAV19M&8"61&h"Y@lf@+!UAa
+$H[%cV!%JRerBbfc'1h#3!-pl#(E6"5S(ch&c#f(X#'%M2'TiZHb,L0LVQMmFXXG
+`YercTI0YS2L1b6$D&h1&kq@lj&"DcqiBrme)1m,BJ)bPM1%eNKVbKaSdflakIb5
+X@N[#SBLGcdQ0a1Nah[0@494*'q&UdL,KS,K!ARer@+hAl-8qRicV,KiTdUMC[*,
+D)%IXFjVmJASMBHSL&jj)NL00bM$D-cHUP%(BA,q'Nemj@)Ie51YC3ZGjBZcepDP
+Be3`iAM4AL4Z6$D16-M&LK*dNeR0[*TNJA1EMq3b#G[fX!GB[*!IX1)Z2Frdr#X"
+ep*@YdXjV3#LC82)VB8H1NT@4CbYCbB345KLK%EBH1HD4Sq6`-I&-I15BC,LH$-p
+12#0iHTSIS4HK&lQ9N@2NQ'6%*-q1M#QC8d*PC,D5#5-d-Q,Nf40'MT%"*30'MT&
+Mj#PKj"QC-A+-(*-F"6km9eeQK*'M(D%RSB6L'@%%4B``!!)F8%ib+a8(!"M1IS$
+%!ja,L1Ni1h"qJ8l)JJ4TGAM@VAK"5V2pB(0pU2q**&9a$q$L-`eNr%G2iRapaU4
+QPe0QjDD9'NKjPPqTHDEP!r49Xpri*-'R&Nd(aC@pNRIh(EjY4GqIi1XZh""dYZA
+rjHX+6'I-b#q#p2`&,P9$rlU%IiNG2iJc6CP!PMEIT6F!2HH)MLAC)jD8(*cc11m
+a&6%9-F9IjDVB)R`qY3"*1)0JRVh&$D@kb*5!VjpGb0*qVf&2ZBk9SLJJpr[cZeC
+H`CIAG3hCkha#$Q"#D2bR`@1NA'"CDC3Yb808')-R!5jm3!$c,#ZJ`NMB*,6+Xa3
+Lac&jKC+*iFYBXfjEC9,mZ3S+eVD+(Uj#0%6'h&I4'DQ3!0G44DYTZ!TUQF&-0Z0
+21Z9$airYU+!Qh&Ca)ZpL6!h6Xpd!$6P3%IA+RSVHXI)Gb`b-QN[&fYDKr&B4rVT
+(T`2,Ze8bV8-RH-2[Hj%SP!,Ukcp0%+AbPk0KjirATJ0lbXUdj85mHbU`fB@%)d1
+LE21qL(,240+h@ZHJ+qK4Trp8%IA&PJV[8)8DUFq&VX5TA,Rq1XIZqd'Y6!K)R$9
+1i5kV,,3Hj@APBl2*kY4iK%!(CifcLP`09LrSfJJKQ)X`TA%,0aihUkaH(*iS%S,
+C#PRM,$CH[I`U@"'""(FSEYRPZB&9lLXKS!KIMeTefEmFX5+#24mf@R`A2*8IVR&
+@3["5#Af0,aYdFk2Pk`Cfa)mdl(8+*QHQPD%C0RGk!GX)fdP@G-d2$dBfrfN0$je
+VZ$HZMcKi9,GDkbTpG-1k[ERC@X+lANV6$Yd!r`%!!!f3!h"`Bk9-D@*bBA*j,VP
+`G&0S6'PL,VN!N!QCLJ#3%1h#!!%0rJ!!,`[rN!4069"53eG*43%!V5`hTE!Bb43
+!!$#J!!!MA!!!#H%!!!I9lB`j4J#3"TI&$F$9*A0J!dk6dfkccm0[YHJJ@cIPY#-
+X5PCZK2NbMp02QA)kb-JqYSmHRKUHkAAQEr`92q@a66MG6lH%ZaPKYqNQq`L2AG&
+Y,2+mJG&0119N5flV2R+F8%)**fc66BiIf5`*)ca'H-r)*V`Ra`R[fAGNNp[(pNP
+Z"EjUX0PY@K(ZE@Qh*P[EANH2X-KY*E`4fB`m2ccC`1X*"+$Af3-`!&Me3B"Lr$I
+BJN%`GMq&6`"q49K2#N("p4aE!C!!l[Fl(kahGbL5dQmj)1"EZph4D'ZYV@)3a2J
+6IMDq8Ac6J`$,Y`+8l!FM2RJ[`-FSclADqh`cFI8%1*E1XGf%$6#1M4&fbX'aRr+
+%9X*kVq2B4cQfRZG1jPJRae)ieXpcH$Nf`RAp)Ai)B-+[9+j&12*i@I`P6#"J)J-
+L3rMeYjba%*!!4DS1!)Y`e*%L5C,&emHVkFp46KpFI2`)IEH`)CBLI14-RK)`88f
+(i@#3!&%3Y$3Ur,jp!1ZaAD`2mMHN3)V*l[0+6Pp-+5-83#SE&`BLhj2"f9#l!9J
+,jY12CS0bTBFB40i%))NAb*eZ[ij!dHQ8a2YV(@*GaHB+qXqdb`(&GiHXp+KLRA5
+l*$CGhbJ@XT,4Vl+5EH8Y$@*MM3[ba#EkUXaIYJlBTJ2BjCr-@PB(A@*,!p,*`A*
+8f10#R[!5X610![3Z3f!4Y9*U)3"hm8CcqLYT#EB*"l9)GKaBLV9,pXU+ffNp6#h
+H)+Np)Ri[LG6fmHCFGVc&L2q40`!2A!mC[p@TU,#cCNR6lri*dLqXSBEIrbMq2m'
+f!NZbpNT1DiZ(PAl"$r2REqAQ!4XG+adHJZb2Ri6VLRlT#[kQ(0m2`2bXC-MplXY
+`SU8'm9()(KPNT3rNF9kP`rG'H*F1er2hQ!GbVh(KNa6%aiK2m-LRKq%PeXBV8RM
+iD#JrpP$8Eq)AT-2c@[lKV"S3M*!!Qhi2XL"1@9b2h-a"jS,8lqq!6a(q0,l%e0a
+c"*rkqM&iiI!p)3h)P*MKj0'pF2a8!Ik2`BRhB*I)3p[)hqq(&"KMJb!XX0SPCd1
+6f06RprZ8J,9'PMTP4E9#qTI@X-'Pa)HamHB5YQXjeNMe9VCR8cRL$MEH4YSPilq
+!H$ZNlaYLJk+)f&(mpfYidDrCRSd[%dljJdGfISlYIR%[iK'$`XCELK%IiQ$flJR
+%eb'qRr*VH&XHiU-DRi9l3rR(L!pq8cl+Ie,,[r0ja(G`R1IIpE03rJLZkGQ#CJE
+jq0[,U!mN@jfqAVm8X1Ujp!'@EEADIBTFlIE)URLMCBePY99RT3m!,$`)TLbY'6S
+F0V(HlHf4PE-f)fNQ3b)@96JFpHqkRAEmVr$l2IS!21cfqXT%RJ`F@BQe[H3352T
+c1Hb1qQUG!"kYYJhk!,Sf0M@H*rJ@MqDU,Fd'5iI,UDSP`%i0JVNZ1Jj+ISKMjNV
+*ir(j['+0l!Q23YLpph')06h$ZaVa%#c1DEjQHkYSHjpYjFUTkY"i'#h1P5Ye!AJ
+B,-jT3GlN-6d"HP0AIic)C4lbG[qKE`eSpIV`6lKl)ccR@5642`+0mTeml*Cm+ap
+`XN12CH(l8AES3$[E-hp0Y&l*Z2e2Mk`)MrL!,"ej1#69+ANZ#+[TkTG8[3!HcTL
+b#9h*YK%2%r'if)RQH!L@Z)mb)3mUf9KS206T2Qe#'5V8AYkR`dr2pZNYYSBC(j0
+&5DVM6UE6jqa,m%J%q3p&9H+QBCD(k[*d*2*N1+SZUBSm!Rdk!6`SM"DXNUZk1UJ
+@08HqYQbMISXM4qR2jEMLb+Gik!BimSE+1TSaar@`1eS6HZKp12[A9,hLl1-m,M[
+l'4kccRj'eePRRq"abGP6K*`pqf41Zak!Xcq[acqFrC5`EcRl")pCChqHaY[12Xj
+$2m$C'bfUh291hHYr12+eC6hRFPaaj+raS0!*F15YEZrU8R&lfGVr12+8[cXU*$V
+G1HBF9Cc(C5FdSmHX%dV`Q1[djhQmhHRM2!b@H&G-4KlB''DXZp(LFFIDfHQ*aB8
++)4kqMZiBMiD1lJ52&2Yrec`LSYYYZ,QM"a"[G-4N9)YAkL8Hf)%m-Dpj$I(`5+S
+UfR![#MH#*Y829cak"AQE,S#ZlhU1U"H2HrSj(SR1QULcD%F-a-VXVj('9d5[pU!
+-2Yf8[)rMe'TUb[9U4+GFc`e&TTZk!$aX(P8&l%$BAkCic%1[`)@r1+IR8dPG!$h
+i0&%AJ%GiQKMM-6G06,+i!VfH4a`DMlX2iHZlf3m3cre`#4XDpi19MI6A2$,!pYp
+-c@BK3+BAh`q`%Hm40[4cc"IQdBe9G%'20qSX0-9aqbr@U`&(1!NHY!-0Y#Vq6Yh
+c+BiZ3,hb+BiZ!!m+Nbj!2k-`kJ,8"mN4AZdAERppb6qY8HSAkh`ZVqVcrY0K)%0
+'(`+crXZKk)J%&B,q5`e%)KH5`UdRfS)iJV[9[&)d0!2Q)F,r3Zm2`VcAcfjFL[8
+BfPi2'pMbbMQ-Ir1*J+qHpd#HVb3Y`qeU6GC-HfYEXp1MEGI(0U)LBDD$+,`ZH&'
+`CmmF@*QX+cfID'Y6!j*bYG(S!359F3iBK&"E2&29e#ZMcI)*-)hVJLM1F[R*)(f
+Dq$CfH8-D1S99D"*S%&k!hi@65FL,R2%M1JU&q`I@LP$1RM1X*ZLE1$aI3*Yp&Ri
+J5*Jm%h3a"$2Q`LPAk+Il%MRjYSB09IPLrSD+jJVmG06DQ[2e9NV!V&e"#FFIMkX
+*"EI9&*,,AX,'3I"[jK2a4Ai&Pa#@`Je0cBh,-H0pTr-E4rP3RlZ06C9!4mjb#0Y
+@"FAiZBi`ef2Sd`(iTUaT*j!!0FH9-Y`$E`5mYF3+#-Yq'MBMaUqQp0`&(d!-VkM
+Je5@%%AZ"X-`A!5F#l2H%hA`-m'++J8rr&hm#2SrB,X*@ZH%VL(f0X-+$m#J1pVj
+(f2)I`AI`aY0R#8Yq%LB3qb*Kk4)FaQXY#lKQAiCML0e)Q,X!6L$'Hr%Y4q&hL0h
+'H43ae(V&BX)bFKLHK&[45TMXCALPC88AB6A$$"FAmUZiPM[B6BKKGH%@fBmCEUV
+Nmp@`['GB%d!"lqkf$c(8Zp"1f!fIBFLK+)hA9LhHri+L@hLK6G$eT@+HBr%!BH`
+KAK-1aGFY1`-LeUVUpRR0BGcZ9TdCI"XSXQ154[YL0PqRI+[X6BhZM[&RSE5QUNj
+h`+FBUhhH3'CS'c+F2Sbh5SVAlHe5cAa1'NUF%HCGY6fJ5'UQV8m0q(V&MA,r(6k
+P8c9A1*dbVVXiT)",069,5TFF-&IfZ6fGSB3TQfei)NN1p2R6D-mmT&)@B4[F+Nj
+qjGi1e#!eZS61mi6CDqY6BD9#F&JSNkhDMXR5k+4-Q"KKCiK&lmh-)`LAqALq%%'
+cGYB!pI2+(M21iL0Fr`m0!&6@1I#bXlbm6%[lcLLR[CfGr1cYG@)$`ZQPl$aq4YL
+4jq,jHY,(-hdMq+G(9NB'R,!M!hk%Nc%MamNa-QEN@13BBIM)J"pKj$NjrS4&'1'
+%%hlN+1(N@8rBNHFHi9j('''%2@&(RK&'f*&M3!#GZE)e6[Q4ij36KQFV!&AAC`4
+*()!T-"jSd(NXUZYa3NJ&rYB5XZB')@[RBaE"hbI`pc[mfNa#T(j*a&#MHL+Pa68
+e9YHY+M(9-(H&$J,MVaF#(L(eFrU8D0eJ0'k1e!fNe+JfT%8*QFF`+Kr!-EbU,M@
+T'TU$b6pHbRi[Qm+$(X[kG%2Ye1+UZD'Z(ESS9YdkB+FqUQhjQ'c+iP@%(%h+H"p
+H*@6f83V(hba#&MH3!%lmS`kK(Z'8#+RTfr-qa(+Yd*L+M[aM"IDDf@qA"5FBF[K
+8@p%iV0)DMq[44PM%Ibp2XkK`@Fah@E52+-NC%Q50d+,+C4&1MKG)N!$&3J['SQ2
+RlS"&5eR4c[C%V%$MPFFXi2X##qbq4lkSF9Rd*#h9'%YCMjLX+f[4Np6b$(*EEeS
+,aL+FPLbf#"B,A"BlG8XE1LKiV#V[VSL5e!UlUd(iJVPVYfVUBdBdlp0AbqiDd+1
+M"9qm@(EAS*B)pXA+XKE[*,9dJF@Lab`X,9jJm95C4DqZ"([dT8N@Z(ab[TKVU-0
+U1K8XG!IjAaC-LdTS86Tdm-*##iH&H6"CC1%j`GHL66'$aBARi8kcS,G1QjC8M*N
+PLYFU&+8HE4p95XkSNBUfJd+`r`KjVXJL%@[YPLaS1L"Cp24+&Nq@@I6YP5aQ&ph
+P*"I"6Rp0X+#h$Q846UH-'4T[#4Ec`+*$X3)Km0B+&R2"SR5Nibf8lJU2UmRJMXb
+Q,p-XU,[#D68k*N9pAE#J[LLGqRME"![U8AVUle5#mffjG&HA@R3&)A1NdlX9Fk4
+)BklFAGfDDHRb`2#50GmA2FQBQZlri-!-M4f#"EeeR!K%RS&,")XjP%9rb9cN@H%
+,4i[qdQP-RTFEX+Hr[(C@5+IhDXRLfF966prT[A#kY#MCAY5LH1VM25eCp#PD%#A
+LeFYp36Ha+IG&Zh4k+DE#HdCS3AGkd9Rd[5'dS2XLSKKQmAbV%LbS&T(4iC)@GB)
+&hHQ)j%h9'#r)X9Sk2@+8!KP#1`%&,A465`pBKG[i"F'#CT)JS#@(!kHq+Ca128V
+MZi)3H'h5&qAV!Y*,TlqV&*@!p*-X['5&T@R9#63AKQKcS6'Q#bTETeN`AbcXd&$
+JS)GNZji5Zl4*X+LNjh9!`(Qddq'cU1SF5,NGM)$'q[pmi@Na&XFkYSSRpSBC,AJ
+[*+#a8E#SS5`k9(28dP0p`hR(G`J@LlJ@iE4P+)m8D43XUNh,5%B98idQ#THAej,
+jQiAcXa)XKUaL$ZkLZl[+!CC*XAhNm`X9K`I$l`h5#6!G9*RT!ZXL4lf)2FY44BD
+E#@hjc8@P%bM-88A##Dcc(28m%XSFUTpSCQD0IFP3-8%LQ82e%dclMfpf-&da3D,
+NHLK)S1aMjfi`9%b3!#!jU$*aJR1ZF3pG3f,NS-U%#3a[FUihN@&`VL,c!%-2&42
+F`p`0iRi'`eZFkbhFR*bVZ&(YXfIICULBi#,MU1+#XqpHk@+SQ1!#imi6&aZmICU
+lr$6b9BiUmPMlXjqqCP`a3BV2R5G5IcMR%[I3*A4&R1Y5GN[X)kIfH+LRpU!E-SR
+kd"#C821iYr1Dap([FP"P(``-ph'Zqj!!qcQkbT`3IXY`jf@3!%4P0dSqZF)Z[X+
+hmK9dT(+kqTdUU"RMZXD3!'6c2555Er[iS9mU$MN+BB*NLHXUNLKlSUH"S@+#M0P
+"PCQdIHam082&"+QRJbT68QbI8biUR5#Ij,U+2"21ZFT3-8(R,HFK[b0RRrej"9-
+)%c5IFUKq8mVqpC16$"86G%kbpe#qSf,rq%-V3m8%l61(UfbVf41*kjlc%YH4Qr'
+Y,()fq'd"Gpi#j'6FVb*AXipmXBUKBS)qCFi0I[m5'f'#liB*Y$[icK0Y%$"FbVN
+Z4CDGhDrjl"YBUcRUDQ4Z@9hc'4f`DMPU,CU-MUkbqBLp2q5KRKT#YblR"Vq,Kee
+XH(ZSf8#+c0dJ8QISXT)VY"*pY4aArh5!,[Zj3[[44(43CA-4@(XjkPkb[X9*4f4
+ZGI+RULiAP8l)"KG9jP46U"XCeb#AQN*YG&&PJM5&ZUR&G813!"M"!mZj'jD6cCk
+ZK5a`LQZ6LbTcb#R8,C-ZpeZ[d18!9qJ!NP"Aeb!jYBqIX,`lli5&RVDlmi*HGbD
+dlEDh[EEG4LmlYe(mHL-fRFjhRSl@mZ6YpI"QXimIcRJ+(FkJrF3hT@K,)6fjked
+fjqkL0j[EjAl2eVjhiAH'LJRDF0Q8)YqH`b9jKpq8Gp$biULL&3DX2cRURqLdF&6
+4JE'r[rB98`J6G$AiR5FD!dM@ZKNU*QJ21+LbE3"GlR'&lU(9akmSd3+%,QHi3QI
+3Tq+SSRq&HkD*AcC0k-ARdKHr4ip0PqBl,if'+Em145-e%pT+2&e4''M,hZ@L0B%
+Fj$*24#kMXC0042)0(r[+TpXC+LDN`ld!C&BqG3'%(b6%qBBXe!aaA81NNeifLD1
+28f`AP8j#pE[3D+T!2hCa3k6AY0Jhk!mXkFE'q$E5'6FIi0,r-b!8'9#(lprR(q'
+E#N+rSGf0r`%!!!d0$h"`Bk96D@e`E'98Bf`ZZ90S6'PL,VN!N!Qq+!#3%2[B!!%
+FA!!!,`[rN!4069"53eG*43%!V5`h`V!$TDd!!$+I!!!)k!!!#V%!!!-pe*!!&38
+!N!EC*!h!VCp0C(j[0XAc8klAbeIQTYc00Y[VCQ3cVlAR0&01*G3ZfmBfSBHRKZI
+dV$@IikmkZmdfiA3c3VH%j4&fHph'ZYK!`Xr)IX)M2"EK0,)CZFeZ+pQ%%NSfiHF
+QQh@a*)c`''&E`XNq"ahEccElMQabqpJHN!!9q1TkpTYZYNp[kjZYE5efK%9Z+q%
+0M'c*mm16$EbH3!"kR6d!!i$TL`#Xq'qdKm0JDRN+R`$mNV$&b35&jh$X*S$d3-$
+p9CHR0H#9UYeHkdi$[RD+FY!eVrS'RV82rA0dMb`V8*'#"m'%RjMTXf(m(U'qbV%
+39fq3!'0$1,D@X!l'X4l#MMXjpL*2D#1XG6c(2X1a16ah%XFD1CE-X@8mKipM@lQ
+Z2m32!jMa+`9-9!PDC21bq&ZB`B#*M)L%m1[[1I[$J#a5G!"B8*!!&ZAdP5"Dr@f
+mQ[iDKI4"K8JIfRF0#l&N`kG2jE&#dJPZPm25PbNIc!b`qV3)KaN&34286iU0'`(
+QB-1C%qC25-0NXm2[%phqIUj*N!!,+DcAd"(prNY"B(d4%S3%AKI,23'GJ&V6-BR
+EjcQ&mU)&4I5IlT!!JV*rU53[9S4bFBNSZ'kX%UD`r1k[XI`l#QXUKDUbCXJ@A23
+e0fILE'#hlF6Q[LGMBMNd#6@95#F6Lr!ZpQ2fV$%APS0al!Cm-aVrae!(TES(Z)Y
+hKj0ILGRBMpSaJ`Nq"BcCCQ5cr(Yh-IQ,af$-6jlMr4*,QmRhCF#)66d`l[&GcH&
+I&c*j2I*kF4@-f0U&q6BJRJpCEGZC[2%V[!I)pf9&1i1mIJqpTcb3!2Nc8L8Cm8,
+L%plrq5jiPG9a03b2(G$bBrr!rVAl&el-dkcP$j@"`35C,qp!&X3Ta2A)r1PfeJ`
+T0AYJ*H(Il@"bT0f'RrVkmfcUphKAaAcNE#`XrqPZPVmAYALkRNdIPJm`mAj0,`'
+5m`VC%@$*YLE**mNHYfdIZ4ZMU#`@m(YF9-mMe9RX5)d*rk0[!"kk%G*qSe24CF)
+BQJdjS9rA,Y)[SU'+Gqh(rpeX%E!%@k[SYMANXB,0!4JqI&'d$a4dK@$BbQ-`IZT
+KhJF+0RI!m)`Nb(Vbph#d)3RaEKLfYC-92*60H49dmIV5X!Vq([0!eY"QhJF+0[F
+3Rp0p3-dIk`-&Q`qTqEXbH"r)'V)+@4#R$+j(9RSRpB([Vi$9K$q$,drf!IMj[P@
+D"P3)&MKfB!-F1Ck,rce`G(3h@P,djrcp&NL'(YB*KT%fKqLZG!QZYN$!,`GYCC,
+B+-Q+$BBm1)0e6L!qM29@jl-eNl"'5KHaGEF9)ZjN[A@N(I8G!q,e-'4ML(8+!Q)
+(m$qJiP0raGE0$a&1qF2lleR2eVkb!I'SXf+p0AQ)KcJiE1eZa'FM[SAbUhKG0Z,
+G+Tp4'l6m2F3([bNIj6qQjVrR%1)V1-lcVhP*bar&96eVJ2-*e-qL'KMG9`-9RJC
+CP$f5BY00U3(XK8NfYlme)!CYHLkpN!!0XpNFIPNUpAJP4IL3!(@'p4DEcNSI!"M
+e"*Jce'ESG0U&#Sp[X84@me3N$'D)ajJLTl2L!mGAMrp&JB"A(i#(`e%a0jiR$@f
+"-+q9(!**IbD(`eP4UK2!SpCHV!qJDj@VkLc"YhP8PbbX0PSEQYf+NJrXH#GBbQ2
+6`+4(1'DC+hUpIVp2+*1mNC%BZhm6KjMV@Gl9L)I"kVl)eq+S&Hc6lG1QRDX1PBI
+*kTif64H!Kp(U[LM)@c`Z6J,IdMA36q3D$kNpX2HE(@Up2[BMlYi)ccb)**CYK5T
+T1CqC*Yh+jpYXlii-I0r0pZkXCqZ'ciM9+aQhrqQ4%H8a-#JGJMbFSZ)@[HH&9A8
+0L)TH!!ph[l*aAFQf%3mcmEM3LDlb-&J(I*54k[95U$b8LhhDM$)8+Dfm6dHHrUP
+2,l4A$[UB$%T51Z"N'[hZYML2H*!!rj!!&AR!0&cKS64l'q*jdT`PPe4&(X%fR3!
+H&#BV9XPlZMUT&P9(2R2@I2d@4il5RmPahC'Iik%Ei-JVjjE6R(e!$iHc0Uk(hSH
+cIeh9kmjqJ-FeCcr)iiUc(p6eLV12mlMNl#NdCmmqPeQ["q$XcqVa6fGr6YLhRAf
+Faa9RIjE'1mjqJ%IFfCZ44pcFUlSU8Y2lGDrriFKRcPTm*XGe4rik$`UG!%GHkr(
+G8L#dcjVjVL02rSHM3U)A1mG94cA!ijS6'Y6MLK1+mlMDkFrbH+I6$r!`@JHkBK,
+b`-B`D0e09UqR[jfGR&LFVa$Li@pSkHG4fG!5jj(Xq1qD4e4dKlhXhGbR+clH%C0
+3,9kTPhKJ"r,fHmfKa--V+STJaldSh!MU8cp5mHJ9T$Yd!A6p`(2%[2L!Tlr+)pj
+Cih8@kiM"rM*l-e,jU["l25L06cG&hlGaDR9Zb[9Da+CF,i5LddeG!"jfVk)!GL$
+X,qGi*+*Ai-*IQ02cUD3ZJ"jmQUJ,`#-b6HcRFA@DQ'"Y$VCkYcP9(RI[aGGhXam
+JRR9R2J[e"Z!4pZM"(GXkf*D28E-CKAFPI2LqJchk6$%,[Bcj)MaDX)V1kh'jcV3
+TMLG`S9jT2b21JhEKJ8i'[&rhI)UM#e#[I)UM#m#$`U`,d-mS6,S!p8&b41j''*D
+mF@XLY8TF*T6lQhf+hrF[Ki%-'AdBQ1hI$N9(*+J3p&pU)"TCN!!3D6fa&X34h+h
+QPD+LDC!!L!Mrdpir!BP[A&fj&(-`e,dHeV(`p#f6rr#*JUpGGd'HTj21`ZeU9GC
+d4fdGh[Y4,`cdEd4&``*'IYa&1r$#$UVlhAhp4JFSkZU8)"jFdRH3!)$+1"1-"V8
+,aJlj8&#[M$A,li#j9`G#F@aMZ(&AdZi*PSQqaY2$`FZ#Cr',8ISdm5hUmKRUI6!
+"+dh)4E-`T5r*8Sr5V(UEe"diHcQ%6p"l,15A[A31JTe`39pJ,aLBN8[c$4bHMk6
+02LZr$fAJAfq'`B+jF-UPrA4I)M2(APPFNL2N&"G9&q'RFjkp1NG[T33XXDN"a4p
+[kl%9Vp6I60eZ(1X&3f!"YajM!M)Z)8b!bDlUUNQBFG0*1UCZ2Y6REX2d-0#0Zdc
+#%PC$(Rl1*LcT$qM6!ILQE#!%C-eaT3cJ%`m!hYaLZB50V3HmeX*Z*qcQMB#(e"K
+I,5Pl#CBJpJ"K`Gm"6J6BUi5eZ`![TKKj$[N`I!QaPB40fJB2)lD&X,BeX"d0hQl
+#XTq%ar(e[B3PMJ0m-kQ,X')4pJ&-jTHf@Zk%ja($LeB!0lA#8F3q6YMXjq#hL0(
+L&8ci-N1YFmB3YR3e`iZ!13X)beh1m%T,$Pr@8-BcA&bB`MGkE82C4a$Mef$FfaP
+ZUNcKQJADQ!YJ+Vmcq1'2XNm#61-EdJ@6@40!(Vq`*pIK(6M)ic8%ZqN#PCAR'0Y
+"'$Y-@,T6pVG)lU#!YDTir$j,"(Gi&(FDh`D+lTLNdVkBhGmSh5Vj8Q+lBrbCPMC
+Gfi#-T)cJYD,XmrLD&(0*SbISPdfPIPr3`ZHN@Z+d#1q5pU!X+ZRf0LASEaAQ5mZ
+@qZ9'a9,NGNZilZ)8Jmf+Z9U8Qk5JC@kEapZS*8aHB-F659+`,C!!5R[QQNSCK"9
+l&*cm5Ud0U%G+E!QGjiQ`9pHR)UTTF&3dHkN$NkA55CN)-F*1%B[GQdNN#*IjH$k
+0S%8pDi$kq55["@Ia8Dlr"`#3!`[!hGUPNlU9(@%R18D1(EQ9-$+K(6PU4aKKj0Q
+4Ba*kNTAG5QiPYai66`mI)e3bA%q+CbHH(CjkR4iPc`KE'EReb$&bp-JcFNc###A
+2b$2b0$*K4ii4YMiC-FQ%%AEN'''%NQH%%RD%(AP''$P+D16B%AD%N@IN'"P3mZc
+)J!+AYaicb8TSK0Q!($e2*N%5)`b!!11"dRUmNXRS!%#`lJ0`jV"H4dh#fS4e$Vq
+kJ%+l+klSIRPBeIA2Pl'22bUq(G81S*6lq@)C-j20k%Pr9%YPNpN,V(QTkVKLb2f
+mX8(KT+R'`T!$QNr0Ebr,3k$jNqNKri"UC-DcLQUXqE(D$V$r"RcTQ3&DHJQ2Mce
+LVH6&a(HmUYqp((3rH3Idi4cYR["C[@0A2[f)K,M*9H+Q1YBFeN[%JjS(0DIa3$K
+-`G+Z5A$$EK5$j$Pf1-HQL02Nl3FQZeLr6pC'4RA9ck*&lpF(Dj`pq)+5&%Ah2+r
+3#j!!%)cr0(L%N3ZYLdE)M1-i@aK(G`*d[1(cljL'9JKEQi5emPQbP"fQSXH55R"
+d0*,@c)$bKh+Eq&kRF#&&A$8fr2RcVP-36Z(P@@b"Y'jN`5JB3PrUA*h#XdVaGIG
+C&"jG5ihJNJ`-CHUCZLX8M[II+(J@,B,Ll`bl9LQU'j[MH#0T8mfH55SUVY606I#
+,`ZTVP50pTa-"53S&kKM0'a3YXD3jh)M"HKAIGBVYXF(3`(MDe%E8HKL9HIT*%6`
+P4rbKV8LGUa6XFPUKm1"#lf!)1+ZEL9CmqEkS8IMilUVF1B(XEiU@bUcf@QRDXeh
+XRqmP"F-F6c%&+(HejkIiBIBD+F5ND*JTi1#ZpZc@@*[ip0Rc8AEN5Tb9+G$-@He
+Y8j5eIT%3+RKG@20NAb0PHN3KKIM*4*`T1%Z@UcelTDH4Cb62A*N#6M&$MHe4P$X
+A5CiRe,N),M&$MBeqpqCm'mNR3ReKTZ"eB#9NAa1PkGRc)L&8m$,KZk&abC4Z(GS
+MA&("fmTbY@qa-MhmPVXb"@mT+b(lpLVG,Y`4V%c*I5cMjX00k*L@SSCe+*1,EHa
+iH)9ppk@`[R,Tda2X3j,9Xm[,e5EmRd(E@3ql@[i$!*!$$3d1F("MT94ME&0S6'P
+L,VQj8fK-D@)ZZ3#3#@#V!*!2!3hq!!%UFJ!!,`[rN!4069"53eG*43%!V5`h`V!
+$TF%!!$+I!!!)E!!!#Ud!!!,jPjp3V!#3"L0r$F$9CB2@,M16HhCjH*CZCT1pXRA
+6,MIG+f&N-epfFYT&C8VS)#2m2-)16`h2k9RV`)fr+Xp0pdQjK**0@%pB5[Da1RB
+Tf4Ujr4kjcFKa5Qkc6EDA4cDKK1iMr0c25T-``Q1%2q'%Nf2l22HccAkEj2DaHV)
+#AeeA[pPQTEIerGEfXD)4&VQYK'ebQffb*Fr#N`e-m!,KJEh1(S!"`-aP!!lm@Yc
+4+&LERX9I!(j0f+T8JU,c12BaJ!a&mAfpfKHSDLchecQHD"6`EkqN4US@9NrN@8q
+LEdIA$@@cG+6J)E$L%c2G(FAh+2f[I$Ya$83iPXka$B5e-Bje%hE8bl(p2+',X1#
+0(2XFaqEah#NFUqGB+XI@mK`KMQhRZVk%$`&Xq%S$+e@#%AQm,2iH0K!`N3@4$Rc
+p-fGI#-JLc35!"39TXBKH5C)Mh-bVk@p44!mU4(SBlaV@`9+&cjl)ii#8Bp`ZK[e
+N*LIB''$e'4'0-JU#aZY2LLeE!1CK`jNAjEq3!)DT0Nmi*2R#I9a6B!UNX4kK,Il
+qDd&JI4%5J54H&beqa55JeNa-iVD&AR&4mC*LqJlhb"%eI+HXVY,%4G*U5DbkU9+
+FbTaGMc,R(88e&@*P@52NL9Ad+XQI-"IBiLH`ZHr+R,!)'X5D#U56M8Ai)q&E`N6
+,@p!#PV'EmCmaq-fP$NTe$h!Al`l(AmPjf)r@B!BV,!I'A,2cQ,1MPDPI1J+jVlh
+-qb@@0P-Ib)44$hE$Z#HIDScqVSLTQj!!erle-'Tl*qCELVJ6FTTh-(A,ehJ28"r
+)LAF'GG-ZqTrb32B[5*98a)Z)6h6[aNjiJkhJDJL2l62bBrr!rVAc9`(-dfMNlbJ
+$`3VC2hmF@4#R$Uj(pZXl@#1NeHb#GB6rX)fTXABEIIDEVl"T2qCG&I14Xl%cjdp
+@-ZGZe1+j+@aQPK0J`TF0[84)R9(%$J&,G6A))9Reqealb0eB*'f9L1paF6d29HH
+`3c9@r-Er!AMi*XMi[8P&PiPL'$ENQ(kG6j&q-3ee[(-[IRHbCF#5A%(*jkTkQ49
+X9@$Nb'Aa2P$3f3&Ckil!MG-1mMj3X,804QDQ3-icIi6$9BmMhJ9CfpYC`F0jR&G
+"*km[!b[Rrf-Hb"R4b2Y!`GCZiR1U$qMjHrY!`GB$H[l160i(FY,A)`[LP-Reb"R
+H6RhJZ9DiPr$RmFrMI3"qZ@HpS3%9JKf1l#[$lfBiG,3E$SrT3NZ+rTcr[`e5SCZ
+eJh#$bb2j+UV%UQC&#DX49jNXeFZUjS,dKfDcp[(%Kl'HDLHlEa,@51NbG[rL)X5
+pV'F&D8Gp4d"m*D4[k@$YSSMB2[`U1MlY6ACrf4(#+ApdlcfEf)EIE%BmlUaB6md
+-a$XiQ,9K*q*c%Gp'qA9m44lLA6UIdCZ0r0h%"pq8Mr)IdI2IF`$a9Slcr2Ipc-J
+Iah8pDi$c89B@8Jf-19N$1*93*G8[Dbl6P"V!ATMLmS@$LK4aQERd3TEPFRR#UPc
+U$mLDq!R(E-FXPmP+(`!Br66B-[9Qk2@kaA*rD*9-9[0%*!eQ5%4ZXGGErT(M@iR
+IBN8*Q!2`m(M+5a*j-Y!@L!Z$j"")qY-j20lb8T-!(VAZqHB!ZPC@9CiKq!'2kJ9
+,Ubf1ZNDITR8"1pS1GKHILI*)8GkNTle%#J6#iC!!@#B(BL-apZh[m@l%I,I6G)(
+c%"bqIVjf6khSRZQH2[eXGHJmV!lIp1QQ!$`X$Pqr)1rck*m%[UqVdNIN-JpjM6+
+cT8L[emGH*IFQ%*lp)T*BZadUj4Bq-dfjKGFbrVXE[iS`Xe9N"erJ6NU[9c*Zrp-
+M-mjMB&#DMMbmNZD6!ZH%eA99*-dXJ)H[6pQ%VQ6EL)H0H*c[4*Gi#)i"(f@KHVd
+31JqY[drE8)CL,FMlG1cA[r6TTHk+34q658P+"ja-IGMAR1#4#2)IUUB1Q)BK(PT
+MS#k4*m1li)+Ub#25E",!Jm,U`#Vj8&F[eD,Zb1F8hQVHiXK4qY-jVMMbXca-!aa
+j4FNLhQ(lpI"iDa0kQ(diqhG9[H,X"hKFG[D$2)DFrD#Z3miq`H1#XkF`R$hEre1
+R'B#c2k2([jhp@@%rF2B*(N21rJb0UmjqJ%I#fGZ3!%I#h1ZkDR,$pEShrh$NF`T
+ARFjaaC'rbi2#*-#4erT$X`V%0B9cVMRbe(mj+L6DhcNZ1DS"(THGd+!H3diS`H0
+5Tcr$ifUR(q"KF3ada46NJBeKd,TE(3&rAcXl2V%i9b(%)ecAe-HMSUiT`529mpm
+eMlMS(RICYGbR+Ml4%903,9kT&hKJ"`VdHFd4a#-JDCVSaVdSh!JkUAkXiY%Vb(H
+B!ZMkNHISpH)$R[i5Md4R6G4CEdH-p*ACHc'-V`Trf)-bq(46qHeLR&UGRA+p%le
+6VJBa2Ydd"H$K$QJDB!I#rR+@4c*k"5lmq6NpRdUD!ZM"TiQQ!$aLdm3q(THQL8Q
+1aNJ`80kKmrM#EYa354D@)Tlc'DF`B[PZb"9ZIQP+HEFJ[[!UTKb0[HXer,pEZ2R
+j(F+)Zh(V1FDM#D[SR"iAkmbBi[L9mr9+qaN*(V3,$h3bi(VGmbQ1+8#pmLQ1+3!
+2#TXT3$qMX*S#e!I*%EXE)DbqH'ZL4T29N!!8P+pC&'6)k#%`ec8'TL&"K@$q8J2
+ab)'N@1[TE8%F`GeUALNkQJ(*L2#2mIr6N!$mMkXV&f)HKVlA`pU@RVTPmKmqFI#
+Gkbl)me653YbZ0Q6&*5AM[-$3N!$#$KCqh-8im-*He2Hl6rBE%k"BX8+,i-%PF`F
+*U)bc`5)BEI&%991[l'f@2`"E$q$a+'`Q#d2qL&m+q&[N8P9U#-UKba*H9ecRAbf
+V3Ap)LPbPMfVQp$V8if',q!+&$Mkm-'q*lf+ACm1`a,!1F*Fe8$F&ebHR[Pf"j4G
+h4d`)JKec3@FZA0&p+)'rhJ["MVQmI(aJf%&cPmM1GeI-Aj!!,qE2,kiZaUGhSEX
+khfbP"1ck&C4Br2Qf(QXp[2RM"r#AFD`("'8*RiMR+LSZ)Bb(b9A9PC-`ii2(meZ
+lq&#IlY1"p4'J'hICK#AG#c2`1CH`P$qK6`IJQl*+"p"k#Uk8!Acq,X#E@f`+BDf
+eJ0GDf'f%&A`$m*!!'Z1V*8A2`'V%[NTBmdV!EXMHi$)k!5qQ@(L1U6[J+iLY)fc
+j1RJ%X@f%TEm11p$Jl56-p`Gi%Q$5&`QE'!EmCe)RB@)&l!'Bc#pYP86J&F5i24V
+lI6L-f+F*@hd6[)8B,9l"a$D'@ZIR%KBqc2!LB2i5`LCR-Ec5NXqA09SU'#iZ618
+E[FNEf5F4ipGJJX8-0e@QFXfD[X1U!+E494QBi'Hh!dcR'p+IfXJD!'E`#hXjMq)
+G1*M"D`KfdJ8U"mmaYSd`GT!!X1&H0G`Nqb)LeUVQ$iIX-GcMeh`CI"XS[Q-bM2E
+&h1&kq4BjP0Dl1mCr-p)10cBJBbPMH+fNK[bK"XffS0iI#D[@dR!SBZGc8L0a4Sc
+hJM849G+'ZjZe5$JShLU[[61XeQ[fBTp2aR8AVa4Te'c9NYSJ4q`PcIj![C%`GBN
+E6b6*N@CP'1fC'bTP%MEIVq(N9`l@S4jT[8[S2%q-[Eiq&920J11LZ8XpQ'`BRC5
+*%52X",(HHc2*"1%b(mpR%,6VC`e3[j!!(,$M,$l1pIm!N!-,`(Ad2ECHRFFPR+a
+N`XMM#502#Hh)8GP+RT&Rj#NjTS5Qj&Cbkh9i'Tj'f%S'M2ak8M`lmB6KkH%lRj+
+M%@ENeXJaFN`bSNHHNMNl-UGfC%E*M*%j)j3-'*Nb`Ti`mS``-QINf*%*"EkqSjR
+A5GK+ISh32$b6))N4"N!!!JlVJ-r`TZXk!-$`[J53!-62*(k$MRFAhPqJ'h+J`'"
+kE+(ZHS&@X[d!3(R2Q5V!cME81#NmLZ"PM*Q5AG0-GpV5"M62mYejcl4mJ%`M4p`
+)*hRT+G0"ZCTAp4kp`I20D2p)AJ*CXflJ![[k&0BK$p$h#P,8PBNe5"rbHXYhTCj
+Yq5GqG*raf-!U`2!+,kAB#NXT$Yk,H$pKDDbPXCEdAdVB+RbqZ)cpq4q,HIBDAb3
+EUbb*Sd6RmR+1h[FEpQcGX63D"@5rZh+JI"02AYG,5'q+'dB!+Y,aV`D(NEQXjC3
+LHki18f$Fq!pJk!-@F*l9FHL&!Nm&HXUT#Urd"DC6VTSm$l,@3VeMf5ZrK3A0iD'
+&6)LXfE%)ChrI!YS@AXH#NS4EU"p&cZeC8&B0kITSeV&V[qFQj!U,+#@&43,T2-(
+L3k'mfp(GV"@pN!!@f@RhD#ESR2[HLqlpAPc)MaY&E64,6FAK1,))lGX@jihLa*h
++Q86%r@%KBU!i&eMHrDTTR8K%1G2Z4D*F$5KarNaAQ""YLhkH@VIRj`*leMTZDZ,
+B!RF*UA$DN!#HX,-M2$RL5@K0ESq`*6qBVe%&&%'01hp!9F8%a*QfU5jZX+@bALT
+3"EU%Dj`E,H2D@pBN+P@J@e$MR'JCpQ4)Y5HK4dl$k45e2QeYXDBrip5S!JP"M5F
+B@4[5&5Z3!*3cG*V0kbqf-kaC'CdS8!@cPHGLR-8EDeX2@A0UV$*&&G`a1$AH5C!
+!9BqSGGa[IP&rqL+V%9%EZ&[Y86Zlf+EkE&03HHAH93dc$2F1G9`[dGk2dI3iFad
+$I!hI,HX&"aIk+1YZdBGZ@!pfGU*(q#p"'D3hP0Er!*!$$3d@8N9"4%e&,QpXC#"
+$9b"`FQpUC@0dF`#3#4-H!*!2!4aF!!%[f!!!,`[rN!4849K838a'33%!V6CC3V#
+$Z[`!!!'D!!!)h3!!!58!!!24cTJFa!#3"USQ%3!)(03FJKJ31)9R4#2T%CD+3bR
+TZ$mA@+C4l#FT[VLi0T(LAC-5%[e*2TiHaUeli+MJ!fL+c-cdk!)VHcSGN!$9G'U
+6J%!jMpQ56kaeF[e0@`(NIY"TIBYZaPSZ#Jh%Q6a,T&"-4%TDC"$eBGaHiK6#F$r
+UE,#$K6'4MH2L[2ePY((0QJiVbFa)MrLFX4C&XrV9P%k*E55PCMmU5Cp"9'4'1-Z
+-Lf[I(`peHXRTR!r8LlC+CmbYQ6M-8l)b+*0iU$1*`cN"2!)9[(l15!V2AXTrX0k
+2IkXDVJbafq3iprDLfarSC$QJ-RJmccPl4rQGfdfBlQaj86C'lbPj8raYH`fTHV#
+M8'J$b0qMPE-r&2B(JPdGlSZC1ZG+q#P'FmIFrq"C&J!!#diTH3##$'"#b9-bSBI
+R4`Nr`JJPP%cibZNASCa`)j6`p5+FF$)$k)'TbJ6)L`0mp2K+d-F*1MK"1P"Pe1[
+NbSmFIm+0m#2SiRLb(S#H2IR@*kE8kB3r6(I'FL6Mm'JLY5C`NhcBN!!1Z2@",Rc
+,hqX3$0kqmVDPdp0MHZa-dbRSe@cFQPSH)+X6Ya@YRMap8,m*RNkcVqb@YfD9Gdb
+@(pL5V[f$d)%h(&9dR3K2-3A[eRC$%24pcklPGN+im510NG9[4XAqhCK'q!eX@8H
+1&G%ekCkF*`Xr(+MAaLAm#N8JL8`U`c['UarA(D35p@268DFM0Cf'DJ[UkC(Cd9R
+e+9JlEBp*ZeDHKp0+UC8A*"NaZmEk#-NKq2H!(61`k%F%UCp)Fdr*Cl%"fA"*TFD
++XDGdJ0S2%(dd&['`dC0MSHr*ei)Z5lrcJGrQe*e@ReHIU8%hphS0Hji3Q-&B-r'
+!mp$N))LP#-B!)B`&f'`LHhLMDN4DcNc+m%'`YYc2QFGPLb"(dc,j1eJ"[*DXUB-
+1"Jl95M)mFbK1DmPq60TDD*8#LVTr#Rr-&km"3+6fj@33Ul%&lGaJhPVr+%cQN!#
+G+hA`jZcqjfmbM8hebm%*,9!L#+N1,H'dJ0VNPPJe9Kd-3r1AhXh0a4pkH&Kf%#f
+#S[15JjfFi&LDIV#-jfH$L,5dRc$"*5dlYXAG2h*LG5FAZeHe&i@T+a(C+6&bY`H
+P$M*,5%%qklpGV,EkjjR2$X!aJ9$a-0&D$,#rE))C8XN%c4LZINU-S[#S+LmCIC!
+!cK!11deUqPDTKG4E#6HFSVUI*E5mS8,K!P#'dQb6&3RCYY``3[+#19G%q2Pb0#J
+ISIRVG`)P&)Z1ppJB(MhdimJaJ93H!'Mi@T5Rd"MAQVaaB1MMKa)()M6L(,6@B,f
+BHK4EN!#q(9UB3)UXA%[2l9N8ah+I0m'm'dV4rqeSET!!ClSCr)6[ZI3NaM(h`Qa
+[Df2ZM6pYS!15DA,kLjYTqqaZXl1YS@d*(H%rQQ&[D0Y6m!1*dN[C42ALBTH99bc
+,bIS$"qQCTrb*Z50"rfpQi4b*Qd1"l6*AaQdb0RkSM+88"F*R6F)JpAKak0@bKl,
+Y2',&a88HM(5M8lHhF9*1#le06*L"L`EY&BZD,)Hj"+6$2Ri5Rb0DhFpTR[Dhf-I
+XGEF$AHi+SpLrp2"q'$L2d"SE9NEE)@cJ*[*N!9d'%SFBi[m"%%kr&p8R32,F9C9
+DmY6@hedY,YpG65D,AUqEhF!6qMhQ++lae#2F)Uqq0MeGZh@RHrAHp"8f(jkqB,H
+ZiZJUl!(e2`d0$R0ST90TEA"XC94ME#kjF(*[DQ9MG(-!N!N1MJ#3$`%UFJ!"2CB
+!!#m,rj!%68e38N0A588"!+dX0m+`!k9%!!!bR`!!"h3!!!Ua!!!#REUK4DF!N!B
+@d3h!e@86QCrCbJDCKprUCMD3!+rGTYfQR*+9-,+C,cXjlD*b+U'$[1dCSH'Ti6R
+ef+f6MEmU6qiQQh)*h4,@5GKYZSh9XB&NDj&pK%GZ-l+PQh$*E9C+RK*+0Z(R*T[
+PCTX44KMKK1fAF-+[-pDlf@p'1,R0,X)M+r$9GI@EEEC2EqZEVHhcBNGBj,B5(YR
+(pNZH(jjXB))A#!rXGIB!$!!+&J$Bm@Yb4U0JA[3XrJ,`'m)@Ta)8RF@a6`*NU0j
+[eIS#BEpFjr(ERj3&r0XY+C(DZA@Ii&P2SAq+RP'9dc@Nk"%`ia-ch4I&pdMYVc`
+VFI9(1$D-BkX*kf!FkbAXQ*YM,r'%$X)#0h,XmabEaA1RF+b&BkNF@mCc"$QfQH[
+k-h`)B-&A'TLT%[6)j@Aael#!J)P-L(6Kkqmj"d*!&QN'!#`S5)Yjp%U5l+%fANe
+rL9*k8#(53hrAXbk@+Yal-SmG8SjcHbHXTc)9JS8"9TmHd5LM)'LmpU4B[ajJ&MD
+F@9(q#fQBDR'&JT)R0-!e"5C$'ZX61Z,[2aF%eKFK%8MLGG(Z#aX%e*U"5G`aebh
+1+jYI4Yp-Paa43[I)bQ*9R#FYNF6DQfV%+Db`jpZXm1l5qQUaTY),Z@)Y[FVc*X`
+%G[Z6f0ahC%fB"keLI6A5bF%L[*mp`AiK[!(YB,TK(Iic"VpMUB05h30mJAH(%kr
+NA1a(5c'$'Hi#aK`cFPRK3pZBmTA$-2EPRr0qLDA0P)HcB15'AKMhe$C[p(HP6&Q
+,[&jD#5-hGf1qGBJAJUeY#e2@Ij2h!19K@l`c+'Yhd2q8"h*H)995%5mP2Y%pAqU
+')kb*Ub%mrTbH(rX(pUrYVrNaMeI2he8*JKPbIV89@4#R,Uj(cUqh-#qNeHq!&B6
+rU)-TXABEIIBlcl1T2qCG&I14Xl'b`Th,@H%Ze',R3PD3!&d)-1'VZPiLT1DAXS2
+!8KfYFP"@I"l(ER)h*NPG,1*lA&c2Jh8fGV$HM0ri2`#2hJ3C4`dUZN`83lFKarA
+VhNEka668m1ipq0h1&J",FJ3NMk0K!5[D')B4)aE%qd"4GaGNVcJ-0dip`2Y!dFB
+1'*'9!VCRhS4$$5@)pd$fjNj@p'JZjeA8cHY,akVirjJ(E-1p[!m8EH`P2UIlJ*D
+r[`m8EGb[jHr1iRh!0Q`PXL"1@9`2@fBRpB'I,)F(#ImTrRQL$m#VZeIU'P!K@1(
+JXA`i[(F'((`c"3k0k8&,L[kFrlm*8U'AGB)`bZ'520@eBQeE1"a5)Sj+@@U4&G8
+"`akC`6V(%ar'qZS+fDU*@#-9#pLDfdX4Gl1q*Y+1qSk!q%)BYVk,GBSLBXrK0kc
+K8epRDqE52f(+(phc`&UfqVIV%)ml+pCARipi&`Hc9fp(I#ELQbLrKMIP)YkMm4Q
+p6XrI5hc`6INSrf%Yr`2l%9r1FCjre5rer(&Fdl-H1*r``K+UJ6'RDU$+eka)LNp
+@(BBT0B#p--AK#3A#8X4Kj0),@EE$i3STFSA2,k[LTq`cl0-G"LYp!'$ddf$*dTU
+Kfqd8Uhc"a6*CcC140*3K%@2,h1kUMahI3[b@KF0qB`!H,PG9H5*2"YS#F@k!(!*
+*IbD(bee9B4$!Sm%jfaK!ejVDQV-%hqG40kHacQ4[pRT8Y4$BX8k`e[#C+)q85Kb
+6B)XYPrcq8#JS9XVqf%L-[Ak%3q`EDcE4QhJ)GXp&[PCAJqJXF%kEGUik0"jQZfI
+D0%-!(LDljk)Jlr'i1!Pm6pI`!*'V215PiB,f8UeH(hq"h*Y!H-iq*,&X-p6)l9V
+phXTVQ5C!q,p@V`IfFLHPe5XCYrrTN4AR-6JS(BBmh*,UNIcRKG9d$8ZU83!2ci#
+b#9h*YK%2#r'id)QZm"$XJcl+&+[A#k(a8#rfD3[+8+B'H*q1rIV(2YhSV"lb-9Q
+8T',3bE5%2'd*(SNJrk'SbU"TZ-a$pIUE%hNbh(-ZUBSm)Qd'!6`Sc(DXNJpeG9-
+YDSkmZ13fiaC(MY+IbA(0NCrMB4MJb+[,jp'FI9!2PlXKSBI4Kl0r@p9VcRk3!-G
+9Ccr%il+c(p,eXV02m,MNl'2E93B#c[kX([pdpZH%IGrC*hKFG[CRDAcJl!Gj**b
+p"ANNc,fQUbUhIP6haKq1[,KNmCNFeacjfc`S$!)FHB-[1,e)A&T5I0f4Trl$85(
+4LjhMLU-Dj((9#3hTFGN**AKFkI4RHAc3k3GjQ1b$A6%&H@"M',,ZCV[I0p$16N`
+XcPF)m3Je,aVJ8Gfm+-%MeI@I0Bqik#jRjIAFTbXqd4&68#eHUCGiB!Ib$hM0iF6
+$,kQUk-5p+0`)1U9qV1,4+mKh'`,SqV(Rk2ILJjlq#Sp%Cdh8@Ap(M!b8fEZ4cPH
+&2qa"'Abkf60T*dkYcNfjhSVq+GH'6I(TTL%!$kGI93%l%2DAFcb5d5Y`i5r-kIP
+8dK"!$cj00!6J%CXQ$[#i-Ne-XRXM!Ap9PmEMrPfiA*FX0#*ZqebK-2bZAI#U82c
+&Se@pJVMh"8`j'R[AbrKrVe#m[&-BIKpZ2FGi,-)U1Ur(1h@Q6h&mi3[e5[XC#4k
+d#`pd-Z#MZZG6(%1!HZ96(%-!(K3@3i"q4Q%f"+J2NL0f0d*BmXkYLAT99S*53,j
+Z8C!!)D1(`"cA'4L'""@#m8X0a--'5E(@dpq#1)+leEa50$3$NK(K(rhrTb(jEeG
+A,X8X$'f[Kh8dRVjPmQmqFI#Ykbl)mh65%YbZeQ60G$8diF%IlF,!`%C82+aJiXG
+Gp!-[E*qfhhfUhaJ!4916'X'$5mB1%P!Cji"*d0[LbDUQAYRI,(m)PMk8c"Id4Ab
+5hpIq,mGQ!+"i8d4@!VkJ&2Q[BE6aLe('02%$k[)MY!0K)KS'FE,U[6NFpN`jNB6
+qdla0qPDF[HcA@NJM[qaPF"$XZ![k-RY4B#DZba-i2"p&QhefIKp+i+ph3l"L,MF
+I(qKfd0JPF[+FeE2Rj)PjXm[Ub[$TRZZXbc0D+3'VGJ8P&RqiVFIZY4fp'EXGM'0
+p))6RmiRif,##5`MMB9*YAFe%c,MK4(jc$arUFlGKIJcSaPd1B8N23MiqCa+@mR[
+dk3"m8cEF"@60FD8-1DF$hYaLN`PVh!TiVBAG3GM)l`-H8Q0mYF6r'La"l1Z%YGm
+*1"&J4`JVAJ9i-FA%FpLq"ep$E!9K`@ai$$%qT`ZBB!XD[1f%M5k!T`!Q2N5BHJ6
+`RiRGK*9e`@k!5Ic59R-c2)mBRqf@[`L(%2X-BER$i3h%D2%+4MBae$T[,''Z()B
+A!I2Q%rET@aKHDFRMbaS6[XY`F@%+hqLGEQ+h)-D[`FamKZ'QbK5Z@F&X9JX`PDl
++32dVl%k!DAa$fJQX&5#IApMll$km!`Ij[)CJ1efJX[-F0h33aJi3PZP@3SYN6d6
+%@P9pSD!eKVYmULH$E`2&Gdc5D9r-'@U4Ej@$DIflBr`h2@fQ[J%C5aR$'b3Pk!Z
+fUTBj,Ej)5$&AK))4+jq6kSNcBVcR,)dSNTVTE&-MSB"iQlcXRT!!dU*Dbc`H'GG
+Gh&,%UeVU*+99MPM,fhcq&MeKkR`RRNL5)fhKG0SceeA+)Qbf6mA*VaaS4Mh5qTI
+3HCiBHfep+UDD$XG&FeDi-&NkRC5*%52X*,(qHc2*"1%b(mqR%l4UC`e3[k$XYq)
+X2Xler`#3!`V!hGVlRB5GMFL%NPm**i``3MYb$%p@`JNP6mNcFQ`p`RiPE#@h(Q&
+iTNH15BEiC(KfUicJUFr`(hP'+$P'eL2(b$(*-r+-c"Pj4Tk4BdH1ND-HQ9%bBi5
+5#5-64KJj4JD-$"Jj4SiG1IEN'"NbmSa-+2$ea9E#EL8$YK*'f"(k!K"'RK(N8-)
+!#("!!%#@!(DMi3%!`cN(%%rJ2)DDLA-#jc1mCB$$I+*LHq@DihRXbfem*`pApeM
+r"A!Zr@E3,eedUllPhhb0jk[$m#Lrj*)60&Uql36TiqQcM5X1KC*L`1jrq[$$,e@
+kV2"F*pMPSlNRJGr%3lc3l[ceBlPCJ!Xc3RU*-h(M(NZ%mZerDaRiI("YYZbZ0$d
+R6D[$%X'E%d1%-hKbTPP%plDFN!!&@(lk+mZp!`iMFU9PH)%pL*fQ`PJm!($UVGa
+r[JR6N!!A68*2j9S)*4RDAX8*3X-H8dBYmTf#5BU8SVKB[Ei,-UdT5TEp*iliL%)
+PZPp5j*V03YhG"U%'&45apmJ3YD@LS)CF0$*'821U1hZ4r*C&[fXPaD&q&TjV@k(
+EU"[qL!+EIC!!4C5-SYL(rNZYHZLZ1!Dff1mX*VFTX!-9a!i$`042#R&,&HUKieq
+eE%d4EH8SLhM*#QYMJ!%ddQ6&CQRkp8[2Xk`6K+dU+F#PUkBGZXEN&ZYQl2(rhl&
+1jIabK44-@'5XfkI(&qc)GF''5CQ3!0l`pBmEYeLlC"EcT-#8fSEa4U2A"QY6Jj'
+#V5N5dLhEIGaj`YU8%#RB6-*90eRh4H'9FN8&@e&XVQl4AZ`1ZY*V8["h)(-GrbD
+kMdiH8DbNV"l&MaV(rZ@ECM%3RcDfH[JZeL'f+Tmcmei`+*4cG$(,cV@YVIiMr&[
+cHAT$VI82!!!0$3T8Bfa6D'9XE#kjBf`ZZA"bEfTPBh4c!*!*k0X!N!m",pJ!!8X
+m!!![#rq3"%e08&*$9dP&!3#Y,$I#X!1P*J!!-Tm!!!I`!!!+F3!!!X8d$l-C!*!
+'Jc!0`08PmeZChjX0mK+rfFQeb9k6f4&fNT8``[9DQ8@lU*Zkk5$EaSVGQZ%jpGL
+Yq4Yre56h56[#pV20)SaXZNhhX8[*2PCNNq0(EM1bTH3f)lGCHH3TB@36(YYNXbk
+ffCD`,H'ac3M[f$jMQffff@mMccr#)a6imGI9*2ITEIfeDfdI+hD%4@iViC(EE*-
+YHAjiXS%*AL!mX0IC!`J!+&`!i-#[aGhC#GE&6q-[!,mRE%N'3Cdc',X0),2'(kS
+1++'3!12aJ)4rHReUV(T1cBFi)mGIrMJGlB2,*qY)dGI!LNr-Y,S6hi2d[`VXa$8
+8Bk`IBaX)Da'-G4$fUTHaJjc349M6#-BqaGJ-cTh1@!0M'BbYi"aKaVDaVMr$K`3
+fI'@#P5V"L(`ZLlq($54-C%'N&9rrc*N-#9PNQJ#`S#!YjY)VcHH)0(-er5e+k%'
+&5!rMA5YD4BCdlkNm$NJr`He+f-pNFS*0!&DI%CfGJS+J@r8RaHE0!$1`iFcSj&p
+)``bE*a,fq50*VZN`&M,&6UNPmIjV3@"p%4+$0+k,PF'S58#YQCM%AA1mmYc5HDA
+dcIBS-6@b6&'AD2*Fhe+IA$fU5KiRR1f2#ZFp*E@9FP9j!2,PDRV0,"Jj(F4((XI
+Q[MYRj&aSP'XVN8iZ&Z&piKGLRf8XSTCE0Z&V+(k(83HPZJHiMl[$b9HII1a(bc'
+$&Hi')9a6mSAcJIe#rG*a'2ELIZkA@0T#hCJ$JalUJ1&22"RSI,P%U!mLVi2VB0#
+f0Xbh!h%Rj$9[&qVQEh!28$IQ*6U$qZ"ZqTrb31j[5C8-a%Z)6qHcAfL$Pm4#9N0
+kl$NM2rB2l&qlIKI#2!%MIfXj5&E)rI81C%'F@PQ2h0pX&`()V0d0D`Mr3BY3iqf
+fmqP[(K$MImKG&I14Xl%,jc-9`VN(YAKQN5JFi!3Bq@9$,aNb*TD)Sb!bA)e+@&'
+$IYGHFMF@RlC%a[I`K*j(Dr,%d9SVIK2r!$`m#V*H-DRS-TdBKJdjS9rENk4IA%-
+GEhX@[l[%!K"TVLDIhe@p@a4YLF,!J3X5ID#SV48'V$N1)mBIi6j3Y+8&"ZDN3pl
+hAi0MeBmLhJi$YUd943rR-kqL0Ui[!k[Jrc%2j282F"mSfY*"I-lf!6er9amSfR*
+)cpq@`hdJVpmkC%'FFPL2[1bee!GqY!V@%rjMr20N(i$$HpFC'P!Kf1(SDqP`I0m
+812lF9MJfY"dY+ITcrRmVC%!(5Ld0GRPmrXTUZESj'SfS-9HjiQY39-f9V$@aXmC
+l"Pm%r6DhRNVb1RikAm*CLCfe%a(AF`hBX![akBK[jIb-,ma([*e`XAE)*V(K$jX
+3la$hMilLQr*4rZ0krXmI3R`9ijcrrPmCq4-i8FBFV)q),LUQ'KKkTJBUJ[@U6`d
+Ub5S`'DN"l)AT,RqN+HU,ZFaFHU%Bi(*j)USb1aK50(Q5BiTMXXYNT3m!$(N+E$P
+k-r4khA*&-,a%)DYj+Y*k-k4L@+RA@r'"ieZ%hp*S0'31`-2MUCLCbT1&YN#Hdd3
+1JD3rPm2MVCKY%X#McMh,(%$AUZUUm`6Ii9&60Vr'iUJ2q$A0#H,9Y@#[iTNS4hS
+jMNQ`aFldK8+45&JZ9d,aNCK8Z*)KmI-ml,Jk$mRKlqCVpp6*lN,hK!NAUN2RBAA
+i*d``"H"KFILl"AQE4rFNm'eGSdNLehNSbk1&+d[dHRhX"A*[@)mPN!$l2**BX3f
+UP*8m-dfrJfXCrpe$p5S9VT,&NAhXT24k*H2f2ceb%Mak"UApN!#(ekIjID',`ZU
+k4RfD@3!2Ie,CP+jNfiL(MAKFkN6AH%L1(KpPSAUp($S2VEY2fe#'8Uf*qh6mepI
+lp(ahCDq2bD%NXhZF6%2%hjcLN3Vb(kUQpTL'Ucbd3+JqP5I,@hCC9H34DcB*i%&
+KG@#9[+FVM4m-4ckeq%lc&NH1dTr,FF14Aq"K'Z$)+fI1T6PlMaiHEee+$l-2Crq
+QUMHFI3q2kmkqPmG9CpqVke9RRq*afGP6'-jH(2bTd`c!fCrAipr1rS+`lcMl&)q
+Vc[imMAHGI3q2P,1h)Bq8ZGGeeC6'pq[Hr-146beHFLl($8Iq*Jm+N`"(AKF-6bk
+5PaG2[HR)-rlPU*!!D(IRZ1DSHRKFGd+pHPae3LNHecVpH4l[G[SH(KC(6eG-4al
+B'(UYZp84#LEEfFQ*aF8+)4k4qX9*(TAeLe-m-McrAI0)L1jaPpr-IEEL8ada(GA
+L5Vh-!cY3+1Neqa12N!"2df3hlNAK4Y!CpH-9Mej"ZFF830F22%HA&qrap0GiT$T
+VUXkk1Q)X@@C[49pH&Ak["fAaG22`Y`kJ'li`jASMZUCFSpS6dde6!"lZN!#Q!AB
+Jl#mAH24"Vm$#AjV6me65&%!2RLDD![#)6a162+j0%p-FJ9K6U+*9jr(C2CLPMc3
+ImEa21UAqGqq"`p+d5Dp8G%Mb[KF`j4$XA5rLrah5Y,&VTIkVFHXjcQ-a9Y&&2Dl
+8Q6(&#8B[e5[YCk4id#imd-Q!pqZHTcLQ!2A+8aa6!"i80P1!INCK03@S$j)MIMG
+#@RVPeN5YTUKKAj0bdk)J3d%25A4[6TZK""@#q8X0*#)2dZ+YTkX&-B+le9`T1TS
+&I4$KMr(r8p$R(eGA,XF-$(f[4l6-2h[,j$pm%Z!Eeef3!1ICT-@iADh,QZfT@iL
+AIr3,!mQ0U%6B`F,(AB`$,q*jIErl6,ma!BU&#l8B(P`bGj!!J-Si&bb5d4C296A
+ebUjQq6f`l63&89cNmF8SFjVi,RAjIZJ8C$i5*KFlR2@6aTe*XLbS"A4[daF[j9J
+1k5eN2Prf-MXSh"-Zk)[LPj+`X$6IaZ(jB0VXFr"p+)PIEi9NaeaH(KmBGY$F*A)
+,h*@cbJVNJPQP0DAip-jaea5BVC5!AEq#%Sr6YrA%[B0AI4Ll(3`A1d'+cZ1*q,#
+SLNX)Ym+BkTUUdCMaSC2jVHdme'HhBAd%k-CG,Q&Tkf%L2UF6P[jRp1N![#NEE3@
+bjVK5K[qe!YlF%R4T#qSP`'XYiLl#bVi1H%K0m'V*lDYK+@*I*@ckB-#*J(L*-28
+@`!XX&XkamQ2`&F6@%&Eb'AJ%XDf%6IS*E%H$YiX`*2N%`1J('2X1i$qMf`JEXJ2
+f!ScK5eZC)q!!BMcE(I-b(-2AlDc(2[J6BRb**AZp3+d,KM(A-3)[!KE-)qbMIa4
+iBDD!Pc8qFC[!aB9a[0'lE+LBKKKIJaRDAq#QbMM@l0-E46A!H,SU!pTqmA'!#E`
+KAEKD0!*-j!Yldcq(Gq"J)YF3l+),9!l1F8X,BH))kq&9)iX9Idc'@Y@#NE!pMRZ
+#QMq,Yi%51bCpD9r-(@P3lP$#Q9flBrbEN6EEf)#-TicMG6ie(!`hDVDbKQ!XSPT
+R4m)a1mp*MF4CFGjPbf1U6mYf0fZa5*0mTl*L@84Yd1bPIVq#kbjHAbbJf@TmDU-
+5XmpX$SBDM)3Cmpai)NQ*08IldTkjS9)1BE1#'NjqPDCke#1cD`QGmm6CkqY6FG8
+-1#'DHlB(Nr@PNc*aBS5G)YCeEkB23EM-arN-JREpV!(U&eC#GTc&*lMq(`V!GFa
+@'a!fm$TbM$`M[a*'RT'9(6QfNT8`3JNP+hP'MUe(f+rN9X,@BiGRkj0MNZ&k-J"
+fUq`!U-p@,r+-d1[)HZ3B15BC-3ND+"Qa)mI)8Br-+*NamS`m)a0''$P'"S`-'$P
+'MKdj4KLC-I+-($XbSF#(ppDV@pR+b'!PM$"b9,C+f"%88F)!#("!1FQUe`8!-*a
+(!3,hFDiMCZ,FJr-jrK+J35aBXN5d@19#I%81p66ee`FES'Q5,dam1E[5,$I[[-'
+hc6"kLLq5[kVSE1lmijXVF+IHDPSmHMbkN!#m&6eA[mEK)$Q*rX`1q@MZFX$(3Z`
+K#fN#j`V1Zbb-@"Ja`hNU5GJDI*jGK4!F3M$0AZ''FAZ0'DjF2lDDS2d$4AZT)AL
+8SS2FEdq-V$q,,ffD1@4[b`NTJ%@PF9H$adLj`K*DPUhVCkJ`NTL(8qpNrR8$`T!
+!mCU%9Q8d2'5rDiPmf8Sh'YQDlFDYhbUTEqL093444BNl1r`rZQLX)L+pq#YNCUb
+#EDXJ#CFV0rqS#2G9k"p33lmYP4I8N!$*H#,Z9%9PiQKSU',3Y9*1*&YcHI0kfH,
+BRT--re,Kl3AbCEFk&6"Xr,'+ICMa3U[QfNXm2K%6f&'"Pi!5-6A%'+VSYiG5mEe
+,B`[*LcqlG2$f$T-q8M%hk#jK@fAAVYILcE'+B$pP+Fp02j8E9ekN@-Ga@a9#3*1
+XIJT(V,T-MYq-2HhdHpBTA9JX%B)1HallVGc6jUdqklb&IHLaq[hCIGaj`YV%5JK
+QbqX,2iXpIINCDp0P3`J%C"Vm0YRiZ(Q2YI0Q,N-)'#TjdrC!VNh@TXiP"(2VqHV
+R[2XbqeVjLJJfXZHVhq!pr3'bdMBKH!e)KkEA3rI4bF0++b(,4ljJ'f%lkBDCFlb
+$NDem`MYbjK,Z&Fb-F,l9mhRkQ%9qBfYVX)4h[4DM(ES"rJ-0!!j9F'4KG'8J0MK
+V)&4ME("bEfTPBh4c!*!*I`B!N!m"2CB!!9A4!!![#rq3"%&38%aKF'ad)3#Y,$L
+SVkM%6J!!%4!!N!B+*3#3"1iL!*!),Vm-`2MVQ#GEcq[CbjrbTd8"k(946[[dqF3
+S0mV91Tr62N*rUedQfB6rbMa,QABH@8pDjbDFE,CZRh$#R`ciN5hC%NifqDfh#Ip
+Sj&Q%4fi6hNYZNeZh(GR(HRUFmM2G6KaBEjHAH5XIC*6r@X#'[lj00b2l*-I*E3Q
+2(#Hc6G#cm34!"jdGRNJMSX#G4(kmfMhki1-2%c%6'3rTJdrm5M"&aL2!dU3aqcF
+RqX*@4+eU(&3p[E&'(HVGiD5eDAe2&D"rSepqMjr9FDQ$,!Jqm6!p)&iAV)5rdAF
+b0[DZ2[M,PaNId8)#laH8YM%rX2ZSiYE&dk(3E@3dhN683D5ZqmhdpcFb(lcr%D,
+'#(NfmX`"8!NF)kh4eXBUkVl9ihVdpK1FZrfh2(hl2[kN-dhU9Srqk2dR)(41k$q
+YNZm@Zr+F*MRG)HRM8X&9R0alEj4UAqhH*CdMkhVL+MNbV+b"D%UPHT24K+A#L83
+XfKZfS[(K#pAZq)JD'NPCUMqD4"8G6PRK@%be3#1bbGDVJqQ+pR#UEh2,*R94h88
+0m[VKe4f!GiedFQ%FL8aJfQ#q,fkGh'$1Sa)6KEl6*XhM8e6U3h&Q!mdIfQf&NcX
+L9NUJ(JFbUC5d$Bi"mZKSYNlcb@ZLd)CXQNBqJhbdL-a9M4XIZ5Dk24P1lUll0A6
+`H2%D2'15iFK*Ed`$M6Q$!L+h+6U%VL)XmS)m)kSPH2d8-&(S-H&KUR,mKFBj11!
+[4#+!0dJ,6"4f+d[)`jr63Kq+LJBb-$**+j'-licd@RQdfd&0")IGLK)UjFpFr"P
+T1Lf!Qd98CU+`hF`R(dr6'9)XE+$5@(4lIc3@XB&f!0)qf`-QJFidk%`Bm+dGLFE
+ke'BV'NXj[5r$HaD9QbM34BP5iVr6f4S+M-2Cp"hDU$B2pmD(KL,$&Z)JSQ*Kc,Y
+eFec&SX14P,,L$L[Z*)1+ppXiTNAeaf0pND5+pYYTFA0if()mPq-pKmie843pIdS
+9'JTiVU!VkE)j8E(iVbb+#K`TS*'qU"92eMRZcX@lQ-ic846GrBdU044`9dNYG+A
+#d#8L5@Xh@T6XME4'NfUeUPkI'KJ+4f+V@b1l)V&i3KUq1MqGUG8@9S@kKYA9MXI
+cm#UU-P%82Aj#e4S+H+bQ@UT@UBL&%E&(86TBG&T6B$P@U[!ZSD8QLQ+-I-`IDIb
+aa-K()V%8lrP8Bk,3Sq!E#*B,U0C%i9UIPrb3!,2mJCFrT2+kF'5A&8GB$ir%BN4
+TX1qMjIJdcNTiI5#4@eZ)h(TDTY-bQ&K1+d`8HY+QqHP#@QQL3%rQfCEVq(f6kJU
+'$IiVeI0lAT6PGDRGUAJX(Zi6Ni8&)ab,)TEV5AG@*3rrK4Um+0aH#5Q6'NL,JkF
+MhplemEYI*CM1lmN-[#m0@qRS5D[ImI%l0,q"jShB-3B2+r"H4"HE+23ZM'-!FhN
+*A@ULX2Zj#'0r'Ddb8D"rJLrQ2p2Pr,B2T56aGSR&`PlKS2R93UI,BDk4hc+Td@P
+"'Ch0*hemmZYY41HhC-lHPVDYQQhEQcjqNi)09*+-@,[#-E[H%SkC@-*XM3!&q3d
+I[h'kY4IM[B*I0qN+FQq$5K9QDM9Gb5GibJ5JVd(i9#%KQZJU%iAYT)UUqEL2Mhr
+PpLTR+DLQ*Ac-aFG)-j'hVQY"ZB"@m&&D`dHm+"%M#0G)-UPQTpU*%C2@1"D@)5k
+D$@V'PV$)f5Z3!2f5qqeK$'qIXbSGN3*,UXC6JV`Z2Dh"'k)@%d8amPlM9c9q6A4
+H&BN@['[j&C2@cNUmc#pTr,*)[#4@AT'8!M-3*"H9m*pS(EAb*0DF0JdJ9Ujej1E
+$r#)IiKGmI2MVFIAaLppZBciqp&8qHIQ&Eq,@6kfNZrPjDRHKd2h8,YhbNHP#Pc3
+rY9&TN!!RU*DIih'kQMTic![i[r(pR,4pA&TlY43Gk2Ucr!`rc3IjMp6Xj@IckHV
+PClj*C4mr24Fa2MliE36ki1l,*&R!Bp5`I'UlE-[e1l%jYahUHQSKqCF,J`CAN!#
+VlI$QVYm2DSYTrV+G*mqiRP`$!C*3!Grmr0La!h*lb"pMC*H6J``'5aCc&4lZXj-
+N04#4)F"3fcX@"Yk,aXXk8[MXD-"'59KTR%mZ(BSHENBBlXI#3pJK51[F`Y2eVPe
+8lfTSfRIJCqdeP5XlK0(302U3!+#UMUGrRYQKkPfUU6FaE,@mclRUMRd(UZqUUG`
+3k[GXH)ac1r4G@Y"98iIVb`fG)jeEX$`CeppEhp6CeE-HEY1MPE8h+U2INh!edrk
+$0pA@'rYrU(U8jrP4+Um+8ANHU`"@XIRHqM*eipiEeU4lZQU(16IVU20*lYP!1jD
+,Xh!LCY8hTAS69U*UG,Qifl%32+1q5AUDS0(PqcrCfJ9&Uq!"[!T4&AllY@hYpN5
+NekrVA')M$`K2J0+@lZjVmTF4Qk%MD0bi)pfLL1i)iYb!'iVZ*MF1-Kk24X%b5UY
+U#S9D5'A6kH$G&2,F5FTp"bNp4%&089!28Y$YSD$(65U)J&FDT82k$bMY[NdM6bY
+mG1!iXp9$lMiNpP2`UFRG#Vl&[`YeDBCS$pB%l+NDMKSZA&*+FI@4Fe%PFlUC1E1
+(H3URUbcHDE`j[+I!BA"235-(VHP5m&h3`A8TJcS0("l%4`l[0*@qR5AAlq"6Jem
+lB*d3XAH`dep@!Q6f#ra6)#$lp$m%XQ2(ja`%b"LE%mM5f$M!JS$3S9F8b0-,!ME
+GjMX#3Tmj@K5`k8FG!b,!$2U460("U5-jd!fM)$!c0J&kTLL3!"X,M)01"NjC)K#
+Jc"MSj!JD%j3em"%j$Y&(#!MGjS-15D&RE,kd@34!(mIabkEEA3&p,%qh@`Ek@)&
+1-eQKCiVdSlR6p#-6Fh6Ti"aG1RJm0dZR3'BL'aJVdTd6F+j)ci[-dJY69ra#@YS
+I@U#UJQXp*pd2hRCI5kK+93GEbqmk2eLM&SFSVD8$QFUTjZbHDH61+HBph(bU-PF
+jhCaYRPUFXB0%hS$ML6&6JKS"ff3f-b&c'6!-1a-i1f'(aFca'6XNCJ*(T(8"'62
+-U$eriePS"6##N!#'Ur'F5-p-f$$P*Q`B)96XDEkAMFlje6l&jXqeT[Qr23[RkZ)
+mD$JqPLbk'iKhka5jN!$AmXVpidI8U*r35qcDTIqN)$GhKGFQ@dFVCGZSd1kKB+S
+hp6eJpmLQ*&Z)E$5SIpV6YV8(`SqPV0hLrJqT4'S!pD&eADeYi"eEfpNU5mURcND
+MkFj'SrQGI8Bl*pSE`hP*UiRfTJ5r',AJD`Ekqh$fd6CX@VqY$I@@klVMf(5el8i
+S!*RFeL-hq@kLmi!e1[GjqV%fHFf$lJ("2%pUNqe0Lqi@c1q(4PQHplSf'FD8feJ
+12'bHmRr"I"hBGqArJM+D,jk8imNVfMMQfeJG2#Ab[%[JpARRh`(['Qfb,HGJ[VA
+3f1YJCMZ`MMb'LGUfe2Qr`,m"@+ec`III"1a#aj0r@*YFGrMr$3!49A"NBA4P)'&
+XE#"8Bf`i,M"UC@0dF`#3#3i-!*!2!8Xm!!')DJ!!,`[rN!4"8&"-BA"XG#%!V5`
+iU,!DCEd!!&q3!!#3"M)T!*!%Sb-!N!JD3Jl!MkIji5m!qJecY,,23BkX0`IC1E+
+F@3jbe0R+r-lVc1IdqfcLp6DaL8eciR9HFd1#fG61FQjqCcQe3Ckp"h"!!,Pq$FU
+qiqGQhF+lML`GQ8(bN!#-)"NY"1)*`*PfGKkHL)RSN!"8SS0amX*SV+#b)1Z)dT+
+#D$k1SPKakE4C"G4Up)+QZR!"FBdaCIQabS*SV,Ji1MU[Z&[(E#'K2L0'$)f9&9F
+ffaicq!"ZqpG[qBhYZehMBT-AE4NrqY#8rGX35HrM+,YEM,S0T-+Rj[HKf[-HqHV
+`)@E,V$BH8CrMU2CmTQj(HG5lpl'8[ZmkSRR[rR!ihScVeSa'(*AZAAAmHV2jq)I
+0TZ(c+AT8ZPbeL#Rph'CQaAb28VSY*J*'Kb128JC5D[9$%6qUS1(KZ0U6+(e(RH+
+efa[RlMBH,D@8aC2YE8QEa5f'cqShZM4D2UXN@PPB9"'Yb#X[+UZ-aXV+LS[bBT9
+&T5AYSh0,Cd9RcUUSM%iY+XHYU+5Ld[C-(q3S'"AQk`KB$AVrT8'fI8fh0P[T9'!
+YX$dA,5X[R9k3!&GCB3(8$IZA+)0mbX)pNN`ZiDdq6P[l4)QMY,4A6q*V0b,f#8i
+HIT!!fG6*QdfG[1bH5fkmHN#VTKd'fKIC2Dqjh%DM(FfQj5ZQ46YjdCjjC5@9I6i
+cQjX2A(*Mmj0E04hFHfVki*[-jQNbQl1m9Kh0em-2'6jVq%&%R5,Mcqc8FhMZk%&
+!1rqDTQdQ4b06dmZmAR6YNiHfk45jpZcSk'MkmpG3r@DpUAimeJLa4Q21l&3l1RR
+a)I[2(jhETX4XVN)dr&icHM"0DfZ4@B,Te,-LVkbbV0NeE5fkD6Aa,Y+TTkeT'9h
+6pYU[aq8LBf8#!pieXPRYq`%MF`D%(6&r8,rK,F,)qIDG$D4CrJUI)'aIb(bL&,6
+Ti9'L"9R%NNiL+C55)T5HcT49QqC(Qi1BqP"dircj@DG3lr36+CUbJ+,5Ql)i5PQ
+549NTkC59RN,4,+(H8DEj[H9BQTpb(&LU2h!-6+(dFHQ8NTp&hNVJC%X,`'haHlL
+RV3$MJIA-4Q+cL6bcQG+-TNa`9&0Mj[FbCX8mBpD"XcELh)4c-dk00`C[0A*X4Uj
+0DAM[)3mM(qlc%3F'Lf-ccNf8p[j'mKi"6JCHLcp1)[JbIk5QMCC!UVl-l3Nb85I
+DQQ$MUVAE%'45C0@f""YTeE-)*K,BjmLA6""rRNJ32JrIZ`6fqCBeb36Kmc81J%e
+J$*krY5+*3,qe'FmMN85#,DY@irQ+C),0Uc+IaA1+E(%*-QR&+M`RPc#bQMC'm"%
+jK+JM%YMRiAXm4dVlI%AihTEC*X$cCcI(RiG9`I09mHGKbI"m9H)jEGPSRkp)2Pq
+cHFIcYeC[HfiVZ1fjVH$Dc9A2+A2&kSfCUj,2E8[B*$mfF0Ac40FP[pim2k0hM@L
+cV,lTlk9FH0bL2VfE4CYRpDprFXZX9Y('[@NqcmpFdA4GVihc0S&hY$(c6#rGG(2
+66EdfpPVAH%9)*2E-G*J-HXT')jNKb)dV9YZqc)a%3Ni`'eH(C,&PlCD3!#5fC,j
+P5jGTf``p'[EIXaZ4+a-YL04!pHaQQhV,kM"-QeH(BC!!8,+Qm9VZjHDZF!D,cfP
++rHH)9E1+"8()UC4Dka4%r((Vb!09fj1S0Kh1IH4N,a,H@hYAZh3(A68J9T%rTXq
+SD1H1RE2YQB&A+CDh'DJm%$'43SaRa!&LUNM"bfU8UR#4kH%M(abG&Z"50jZUcja
+E'5ZI9P"CB81MA8K4'[(J-&Ge5XG!!3M9b9Him-aiiB))"95,e$lGKL`E@M5P2&B
+qYq-pYV5#d9%`1#U&La6ER)KRQ#d+8f@BhXBc)qJiT#mVbpZ4RJfB8P"&`3"D3q%
+5BN"eUDECV0!q)3BEVa8"JMU8D8X`UQJQ*Q(d@J)&q&'S"XlD9%IK%U,!p%jec3r
++cVN@KBhALe!pLm*@iLF82eJ8GA$@Tpd8,L'+&,45!r1pSJB1KBdhM&"$S-b`+*!
+!Ie3KLTS!mEd&X4[14Y4Bi4+#3%Y5%r1GSLB1K)dhM9"6&0`2!438*k[`R3A3''I
+8E&+BZ8-!U@M5CZCE4FdF!"Y[(U(QYJS9KAmYjEF!JD%-`95F,@KhK3Z3!)4XC,i
+aIfEcMFhcCjYLGj`YUCA#*550J*6jQPS(Z$6+TJL@$q@9F9+,4dHiU+,@VK`"4Fa
+AR[N+%bke!TSfY)I#*85639RQ5fSEi&)cQp++LkC-,5SZ#!-$%&$8eQ()!%HdLe!
+lp((3GeC4FAjd6'94FB9MQ6e`YUF1#KG8-4bfc4I8NA%"mA5N!fP)G%a*AZR-Q38
+PP5%6&mH`1DQF8aSY,LSTU)K@PVTATBklYr(ee0,Lr),bD0(8F1mb*eC5k6"h`0Q
+*XK8Z5F`EU62E!69#R@PIkV)YUBAiPke1N3dA*+)&q8@9TH8G(ETXR([5AJUA*,V
+2D@r'"HMfTMkdVjdNbJV++qHL419j"If,bU-pSXd(9461M"88pqKI-,ZJZ,6-&Va
+(BZ6S84QZeASdGaMh`YQ&pP'i*$&q4PdC&f$XLJjY(UdSU%5,K+eS+jK%fLVabN(
+C"fFhkUj`5G,)TqB60TpD'X%f5+JlcKkdVm*&L[#q"XLT*qfRF2%'a90qE$ib(rV
+QBkVI-9B`Zl)8Dkq5@FA&EXCE4'haXIR)NYH(GVMC,c(FG+,pKIB(L&l8@q%LjI(
+094rUUh""6DU&'kaqjJ0&r4+!)qCpkQrqj10D[f2&h)V5iY*B[J@CQ-PLa88BJ2U
+6f'8GYPcQ2FVaF8Ra,8NTbL%Z$3H3!$5c)6!ErSh"a2c*pX!(YQ"pA6jEkRF$mbj
+9ckCUXd)D!iEH1!I3!3SAb88lCS,G"p)JK8YBceSB#!E6%)8,kQIMMFdl005X$h#
+e6$c&dQ*LJR24q"!R0"6JKTPeLSDj%Y5QhFcD`+cG1IH*`E*'c(TEYL&9CAXl-'p
+69MDPPKG8cSi9KrH$BX@+"VNFQD$c0B&CXk1d"q!FEYj50*a5*L",-h4X,Sd`EjS
+h&!+b2mLR'3D0!fQN`L9%dSbDQpF$mrUrS4hTKS,Qe-+mjTRAL"@0)'mNRV5QGZC
+9'Q9HmA%&MB"F#mV,Se9Gl@K%d5J(B3m-'+-M0"T$@5dh9i$l,Hm2L+&jmd0k-kr
+BbjZfMGq`NEGX6II&1FDmV'K-&H@pC&jNmj,0mk,0ml+P),c-a1i0NrB,G"#00Ar
+%$$11aT[Rc@Vc(1-4TVb$3#h2QPAQ'I1dHFSmDCi`M`IQfCfp'CK9[ipHJARQhmM
+)0dr[iYE!2,@YE`2cj0qDMmd6YX#2fpU1*8NaMp%%$jHd$*U!X42$RKhQkf%%ENV
+02C5E-e$[Y#cc+1eR(M%VD5*0-Jrl#2p+mSrBrPPTHf1L[8bL9,2#2'3H0!qBqfQ
+dEeE%1GJh$qhLlX!mZ+1J$ra1P!(3rEAN0Fc$P0efh45lVHJd28+Fmd,ZbTU8dGD
+qS"RYb-YjD8cZSc1i-9AIBrTlGFD69jLC3H2Y1ZBq1KJ8F!JM!#BpZ'SG-ePS-Pi
+H5M'&5cJ5f5A%&-T6Z)3-EbRPAXShp`5i0XNQ05[F+#8k2VjJLVHmN!!PU`*cYk+
+#+Vkq+c"h8HeX5LmXR9P3&UXXG*%4L)LjfcEC2EBZHBQk&0*8SDN!-Sd+&5la5FU
+M)TUZF%RXI-bGRVR6dZld+Uah"1D1N!#cd$@cbNYX!m9$k#%"0+%C"2+HBHFEZbS
+TS*P8SR$a$J`e"2P85Q9dQ-*9l$Bp`%K36TM!bPejl*B#GEB$q#bDVA!*"cP&pFc
+Y0-IFjZ-D*jAmdV`U8XQ+$h*ch##RU*DjP3lhF8RahF[$hBLBLCA5A,0Fd9b5[(#
+DU8P(d*%+Pq4dFdYJE[QjSa3Gk4S%fbTcXfpZ"VkmbX-Vf5bhRADE(4YQicb+MPD
+iK-@VMbRZ*R1MZF%h0k&i`iD0'$NX0U-JTlam'0DM@+M1*eY)0MGD#$GB#%IM2-C
+FVqJB"k%*TU$Vc,AQ'YpF&iI3VlKLK+ZrhFNQ)&aV)8!K)qCkf`899GZCUp2-e@K
+)RVa)S32$3FTQ[SVQQ@8qVVm18[1U''"TB*D'r)P--bZQKIGK&G2%,,0i$h0Gh"j
+p2Pr3Q%,(dR%+Pl#+l6(+ANR(d`)I9dITq9!)a5TQ1!V#jr!H6c)PK,%[R8!R+Pc
+LmHjd%TfXF)R(Zp)TY&$K%SphS92T0)9,2,iAR8jR+&cLmFjd*U(qCbELRHJX1P[
+K%VB*pNYd6S61XI["dGMDK'1$(4BKdF#-TqKXe`FGU+1j)M"Al15)43i2GNGdES6
+1aHD`G[0SHDbSSL!rA!HKCdV,Hf#cCd'Gi8"eTMh0%YmX!D'!8D1+6R2[pU+pcH,
+!,2jEdbPDk(*Ja@-ZpmhPbG`RZhGGUCZjc$HA*GqGk*D*hE'K1FpFUZJm9bJE2cm
+#'F[Ze'48BHNX9(e30+q`)'p'@@P4I*d@0J2f,RBbZ06Z(aG!5A)*A8!AqVLQq&-
+U5m#b&lK0FNr`fN9#&b(G(qKLK8Z)%mXJZL4#PpMGl2L#q'E[BTbA'L5je#AC$fZ
+Hbb*dQGe$$mHBB-RXBJ[i3J$q!eeZ,[*a6I(cTaCMrhLj5pS2+jA&%9Um&9QUZFM
+#1`lR%R1K)R5@A8`-!cGG39HD#fLT3N$f`q3c$12V-VT+i5,&Q2H'B9P`Y6PIdG8
+N*@(1dA30ADY`iFk)Mk$4jMcIR'I,APL%+PbEb$Z#VM2R+VV1j8(FR11EFfcr944
+M5$MAGJr83SUZFR8EM3(lqJKG[l9ZLUjd-pP%1S4ZS"X9,Q%Z1e@IlCQcEBSEUaM
+jV-#FpBqC$(9'ZU8183be[iPZ9VL%L')da5cbc#*M&0eFKHM-`*bj#p'&&P&*e6,
+mPNbk4CUN*iB4iV9f)[XI!EjqB`IPf#fL(H"#B#YXIpKpHDI4-k*BFrk8mHE"`B#
+qrHdQ-2@@1[e+m`['aXV,LdV,Si2kjd"&dE@Mfr,plbreLjXq$P+YT-Y@)LlUUr9
+MNVV$#LV,5qF8P-qSL'j&M,8"&(1TYq"FL+VeV5TDMkU%@d2EF[IipmT9"reF%jY
+DjZCc$h0PGb`JCS(%,iZ-+)a9&%6hM%k!p[,[TF`BA$5cG89dK!8l,'B(hahIVdh
+P)hGd8-Qd`TK$rYqY3hl(8Idk$FSGPR0!(pXh3RD$YYaJ'PY1E$9b8l%ZZ&A4VBj
+hTY)dFhTJ6Yr&1fGB&$'FYp(Y#TIN6ZidFbUEdbbeRQT6h)lc$VT6i4,ZA&+`XlU
+,X$5jUfVRXY#FBNi1c-*`@@6A3Z'#2VqS2)`kU3q@i'+JeK&cXQ@mZa-,P+CdMj!
+!P9RF5rFTA+!BG0rp3[FMfdRQa-#F&!k(i6,GSR+4%0'*YNEhiAb!(P5i*"Ic*p"
+$M!Yff!pKBcSS1L#H-JSj35aD'-ZE%Df`)SCBCA4@48&jKC-`i$%fIeC4%mf,PEM
+eI6L`!6Cf4UAP@(4Ba!rLA%%2+eb5L"I35XB&L&GLJG[(V[qR3+b!14Di5UC&5i'
+Mh#,HVQ,BUP3&T54KGZ`B&cBmM2-4HP6K%Qjpl,,N-AVF(+p`$A[)3dFq)I3%%Me
+*6bPFf,+@eHFmVHKTa`L)QZ-#!pRY[cF52BAdcjKM&6hM#+8D8+e5Y-UPKm,'c!q
+`'2QP$iqe6Ieie5CNRMR'(1fEHEXf)@b1XA4`Y+@DiffT(mAjV$P+dE0Zi98$j2!
+FV9DiK!0A(@aZRUFr+Pc#l9-Gk)&H-0Jf[H!'4KYrd4bKk%8hD0Vi5i50mdYZ['T
+!MFaFhm`0Yd`PjBTH6Z4Y3+qB`a@pNX$9J&ieFa5pkMBYL*[Cp*UCjH0D[f0"V,a
+LkY6mmUTk4LQ'Z+,A,20D2(A&31A+CSkp306-jJKl1G)f#4DmLG%3DqI+R@Z2eDj
+S0E"5Hcf6AZHhrdH#QA"BRhkMYXq%GXP%DA&0c0mchPbamPR-K$EA`DN$LNSJpIP
+rm,R$i6HpYHq+!F2lMl59L-q%0Al-SNE0VDJXQ!N'Ym)LC!@a!6dUe5JKhYQHS8H
+m,2qc`B6hDi[mh`N[R1R-8CB%lm6j"VfTF%Q1C"@QR!dDP!h+,r3QcVGSMF)P(-R
+5XC*mQpBUA*)Mf@'dcT3&Z2j6k,)1B0DE8NAVUhLT*$!P9$qEI*F6j&#CL!e&6!`
+5LF'JTQKYe5,m(D&h!1CGfU"`5Fjal`QpKf`c6A&JC[iZ`a#$MK,DJ202p,l#*Ej
+2VdiId)F+PlJb+Bdq-M-8IH6@cMEq-AfLF)Nh3$8ch45C`X"-rpG-LJi58fKVq8P
+56@LQq@CDFKQ0!L[kX+SpTJCQkLmD!ASIYIZ82P1iK,AcNIYcfQJ[)3!IUSS#(2r
+5!N*IRJ#F(jMm%$$QaVc5@9$8f8Jr'a(k$)#rS#m9,L(J$+JG[k+[&5lK&*3"CFQ
+Ik4Z&LpH9V8bUSFQMEfQ6MbY+A$S&3S9[(9K)3Xf8`%cj9h%fZ8DXLdRT1`0"aRG
+ZNV,almfKLVjhf'hm"i,bp!Hh`UZ25@UbEbB$Gh&"#9DZQahZZP6I("+B3hD4$K[
+i4,#*f9lmaQ@&a0%F(*L$Gf99p(99'dd+c#4UN!"03A`6'bC$F)30KX4'Ak+CYT!
+!9VKiij!!X`P@*-C-C)#'6YJbA8HDa#cS)m(08e"SKPhANETa#PG6R1)SU#1@b"-
+ieB`2c)6rP+)`C+@FCXBT6R2,p%kd*kGcGFATVRaBITZaJ4Rlbl6)8!VE20R8f4`
+8Q)2#a3mi`R9#'(+-,`CP&6-HEF69UPTM6'$'*(+k*9%B'KQ'8'H8acHM&IYZlGX
+G64"`K"9R+!lFfVFlpH4-cP+FkEJ!Dh#ZB8BTVZ&J)Qj'"QEN6TKX-)XUKUq$C@&
+)(mf"RX(+3c%84,EeHP%1ea5'#*aVF@h&Y9cVpD+qA)IV+UlMJ%,6D%B%CX62M+N
+B!ZC%hA-$Nr[2QB3KJ1CkCVMLHQiedJpeU+qiIQ*ChYm-m`c8*f+'i`+0Mr"Zh%!
+aC-Zf-3E5%'l)M43hG,LK864$!c0dCb-SEZ5J$D,"CSKRKKJMh!#S'T["#TUTX"Q
+'dfKZ)Y`%cjTb9(&6e`c$k8"ZaXd9ajA0`bRA$2)-e)D+QeI9I@"J"[kVlT!!9(!
+,Fi$L&UlZ)`&jGm@l1f3M)4SFi*N"+)ij`"BI8JA`J5[$@""%5fkP'"TS#0)3Rm#
+YZBeL+*aY$FE51*-6Q*bG2GV'JE6#[rkHk@r,ekUUI2d#dqqAJFL-YX+eL6XC8&N
+cNB4JXQpJq[iq%QKd`4lF9M&%dlDd8kL!fh&laHeFL5"!-hdmdmH@U(e9LAS("KB
+U[hGB@f$VB(STlT!!h1*b4m8G(6+laGhI-rY$"QjkfEPi$G*eiQc&SB6Dl3Ef-ch
+Cl'G()rLY#%-(cCej6i9a+p`0`#U!pq+p&Hp9Y4[BPlZB(S(CPjTR8qCKX`V+jf+
+29eTQ9j!!&I%(f*EQZJI#8$[c2UDliRfUUYXY-0h#X3YQ$BR&JSdPaE$G,52dX)b
+`Gha$)!pb9q'Z!010!@DVm,QVfBG09e[#I@`*)AcQ(Vb[BJLI%l[9,S`UGd%jZ5H
+@JVY&qe6-L-DQP-kUM-ka'eblDV9E$@5d##!ejIeiIm@JAkGF9QC[lX@pIE2hVe)
+TKL,(+RT3#ZjMpP+-TSlVplK[K2Y#r0TLV-8EEf$XDdZh#pDhbAVf`YiHjM'HfC2
+lFArIl*Q3!29`2i[5'MfNFBlTV"LUD#[cXI%"`P!cm`%m82%"5EF'(K6K3@MPe0$
+C`#Pp'#TR(Xa$&()Rr"KiD!3dNNR9R5Y%89`8a%0`$M2J$BLCicS6(KlKi5K#5Pq
+XTF-X"PS&0TM58lNrUYD*Fde(hh4+D)-B%QZE1jfUmiJ)MpL@1pA!R%-BJR)qN!"
+(+Mi`XBQSaD-B8q-S0a&Q8!dHBcSSKJ,BE5CUm%%m9[&"EMZ3!!N9B([IY%m)JAL
+XHfIRr(DqDCF8rR5`[$+kLSdJa'dEXVJPJmV5X!YGF(4TU&%@(SRDM12aLXFjhUP
+0YFdHTJfE2@c9VHd9MmFjJ5FURZ"iakCScC2BY,Dm-`Rc3X1Y['0Aq,(b203*4$#
+Vh1RkH5,1JrN3KI9Nb$beB624LLIcSEjTp4[c30TUQ3H''a`c,4A(A,ICq*3)6m%
+qS8h)2"JNmJSU+L"Pq6[e@-&#R(jDfNBq&)fm1qGa[Qpf6p*2RU1IZY53!!Y-#`@
+a3%Jr0Mj9'&T@RXEB+%ac&DK,pEJS`NABJ+5&kp!4S#pEDR3q6qFCLU&SYBRU8Ad
+ZMV#YSVG20fK@E4*FHDE"1$V6*B%9#*G%Z'3(mc5h"B2j8bVRSf$0Z04%IG-Xb6b
+P,MFF3,JXJVhLGZD"ji[`)6J2ih,&KcRQD8kYZB+4'J4SQDFjYH4CTURL@BjjE(`
+fce%mfc&-#fTTQ[LQ5C*jjVKh9LrIf$H0Nmc6e$*2C4Ac0!T-)dV2TK4,"EB5j6J
+2jlQ+3i@XYHjSBaUD"Q`DfKShX#NJ)H%Mq%M&4cLHX5Pfik2Bl'CjjUJIH3B$Bf9
+4AK30Ae%B+im,l2P)R%Ic-BU2GJZC0R3+cq2jTMiIUhJH#3Cb[1R1ar(aLL(DXhZ
+)0Y5"&r!*LZ%GCqX(9a&6,c$eYYC2m3N*PApl2M(#*rlBpBSK*V9BXUN,Rm3R+ck
+TDZp80c"eYf1"EY*Lk3`EMP-LI-Uf[P93'S5&kdR(mN)qeG6Kda4$ffA"pD3qI$U
+ISIKd"`j#4e-l-,9rShM&N!"q1X9MEcic`QIq0!FT2Y@0S[dTaSZ%&k'(cZ+c&Cr
+PZ,Sr665eq"`qecHeIZ2UFaaApkF$q$a68r&j9I(c63h&jlY#f2J&%Ei!CKrCrIp
+1eU15V6dUE1eSXPaa$SF5JNe0bi[RJKHcq%+'@M-V5H3A1L)I5+2i$bC6-A5KPXK
+Yr'*K+%(j%Vj8m5@Z((B0G9Q%,`[Rb"#jSj*,F9l1LaA(aCp$D$J[LI!50fp@8Fj
+LR&FBl2ZZ5'b@$Z3V)hcP$LU(U4)EH%LPmN8SQH+P*Z*$$jQJmU9*S5B[Lr#b(93
+1VblKXh&HC3,&9cNURi4Q[CU[83ceU+Ab565CVc@qBUK%,CAEq(9m[H+i5[4JQQb
+Uq`C13h%U[pkpQd3(Qh6I`0NY6Z@qC34)8"08$PHRY(#RP&mDCeT%A!1)#@aYkpL
+-%"*E$XN(EpdJI!1UG52IT2K'ab(jG+4*jC[j&YqNrXBK0c[1b+GT[0aJEEbm+Rk
+V59%-)CpY&"Zr,F+hBDRCrIp`##aRh,SJ6LC@0'1XPT0[3@GkI$[Ii4XX$H*N!Tf
+I*C0#UZ!lM5L'@B%P%aZr5rJZe2PZ[NFaG(Zf,S8dJqq0m,er)4-)qIJq[PraI5l
+2$#VK"b,m`&r)"-SqIY"JBrDJbe0#Kr&$%AjS"jRB6Cfae-"hS'43V'VM3bQ6)*-
+9,RFPcH'()rc`GM,4b#0m%mk9@LYHkFMN+(6Y)rbSiNFFQ4a&mrJa[8AaBij-E2a
+aIN,aiiidMUCjHV1[0bI*j!Rh$SB%qJGIrj!!)"-0hbh&MbE*4(mIk1pr)41YE@h
+K"URi@&H@"CMHRZ5R&%1kCbZkJ%lLTb2mp)lZ8[a8&F$[![hG,`$j'*6p'9kPq"N
+hK#kNKAU6rTBe,+aB@c-VASAc@Aj1-E4fGJLe+ElKeDcKBaAKe6mZf3CJm`#+'9j
+DdJ%Kem)3jI(cr%I&clY*EL'pcbr`LrV2r**L+2+XVH0#L$"IjPF83fRRiPIcUrb
+DiPFGfbbN-rPerEALejfHa-EId&mTK[M*6S)frLDrTIK09rQ&G+Vq-Y"IEKmchh*
+0FbUG`@XL['BE$E$qbPkqYQPHFj!!ckBVq@hpKH+h(@3EAkXh+PlVTQBEAmIV&8-
+BC8Y`0Ph!lr#lLYpa*6LEcY'I"rVchiG4#+"X8FkKmhP$K$IX@0iTAZr!3B$2lr'
+I&,rR`%(HVcm,p'HrJrZ6!hFaAFE[4rMp(4@(R4CVq(JTMXXCVk2lq!2pU@+STfb
+&EIa$rNMaKki)ep(0r$&rS[KM9i6Vk(Vp5D!rqCPH&-Ge8YI66IaTK$rG`Hf+)FU
+bX'kPZrJcrPcaC`l@VA5ErMM3(qq%"B'8KA8EhFNE)laa4eAKLkAi46GlVD5er)8
+`p%lm*B-X[R5cedTkAAr%Ar1IIIh4El2Aefl@@NQ2m6Ik3m@3!"0Ci$EqEB5rh6Q
+[@aDF$DQ`ABXR(-qfM9JD*PZT$*Q9rS!hmAHqrL!jAB9k+4m#f6rbprTpaGqlkFV
+'Ia$q!CAFc"K$))HbPALFRQ)GB@eAD8QqhB)6`j!!BJa#0XP6Y%Si)PDDP,D0Q-0
+6p*m8)Q'L9E4D[)M!8@RVE+@YbCCqhaEX1a6X28R4'haYREV#f3UZUQ(Z&qKPU4D
+4DMYQU`ff(T!!PdQUIPF*Y%Zf`GkJYC)Qk8SJBE+ce4Zd4UVVGj6!J0$19MEZ5k$
+%Gc28Ql4'VrIeqX4X*B&l"r'MAZIVGFRCkKfd2TaHNk22fN#[T3bi&1@A6NA0F8A
+T4EpVU`S$2X8[ZB+m3qp,4*35b)GX,Gq"&$%M)KNr0S`5Z$iQX,dGk,IrLShrL&T
+R5TB5Ufe#dJrS!le'[m9kMHdLDfm&BeQ4'P*6#A`6%bRHe'q`YMCBfYTJ#B4,8NY
+U+kRP#1X$,YD[5afTkq[AIb8XJBQL&B9p`"1PRY4A8Lm4(bql53-P%"Ujq"KT+)f
+80%c%$j6'dN3*l!pGI*JdPDJ5D)9FI*!!0*2Q5Z!9lH)jdN*f9`*[3aI[)bfPP4+
+)H&am2fNYEC5d6X5lbak#qN!Ciq*GT*fd9p)Z%HmX(D5M%PMrZAJ(k56C5L"IFI%
+pT,2XU34D&4G[,A[*hNTJY1IL,D5,l+-%#K3AEbTGTCX5L%KF[+&dPaj+S"KamGe
+NAqQT"2S2&kmMqmRq#Z0)2&j$HNP[*D"V&eI54rVLNSJ(dNrk+m'ZdmA6*%F'+-P
+*a$dj3!BU6&%Z6NB'b@!PD'BArd''b&!Pd&Ziq,Fb6)BV'CD)Ib@j-N*"h"k2Ibi
+(bNJPF(#c"28"I5bM)M)+JXdk)`YLqA1V4SpC&GC"`0%9[0`XAAe-RqRAI2eD`Sj
+'4VJCih2k8NEV9jA%"4+)keGmr8Sm$qYA,BMK$[*Ap)f-LFJBDbFDaCF3YS4#'L9
+$(59r5prVPhhp-L"8aUB!+L3RpYd2T29,[RiTq@kJHfGBp)ZqIM(jEN$iMMe1e5r
+iqSAN1qLkl,Xdp[8IF56I1Gmr+c(8c`IkqImBKq(YE!Z2C9+@(+4A+i'Fa'C(A$r
+RkqH5KBF(V4+SU9"iVX'eC@a%aN+480-@(S+R+Qe&[2S`jlE9UF2epE1qIMCCR4i
+1(c4qHP@J9feE4NJSDr+KpfXLir3c5XDjA)MVThhpG,)@cpKN%&6C@M6PjM)q)Z-
+6Y4KD9$,$Y[Y-'*F8afX"&C@Y43YZTCrbp92*@ZcTm%&ETjm-p*1r$0F#ACLYbal
+FALES*j4-F(N4eirlq[&NAH"9Tm6TclJ$Cm[%#24l'C3HpNLX-Pi0k0aX06Vch[S
+aAcq@V!Dm4qfl,Ya02qVV4j2[S1DcllTc6rf)Vap*[S1NcllEMh[VPEjHQA`(LD&
+peiIlkiGprA$b(45-pPd1$p3VI'dplGblU(XhL)IUKhcp82)Gr'(YZf%m3MrSk`H
+6lk#[Y1m1j0(k!9mrN!"m"e0Dqfi-Mp2hqrVqj,[3[0ERm6a"*ZRlP%abhB1i[MI
+3prid-E+'HefUe-9NIBmF,)IiqTl%+N"JA'#a61*mQDc[9M)jA!@%m80&i'`R-CQ
+La!Q!m'bbj%@JFXH5T9qX*!q@!q'!2`9R[Vj,5El,-jQR5%&%#Uc28blQ$cX-hf8
+R6hM@TFSK+-5G-PAIiHXlNb2q9*HjJ!YP@N5Q9@91eAGBL*!![8UK&#NT$"Gm2*1
+2NHNb3pqZEe1`SV9,(VbTP'+CUHc)Lk%Im6)TdEFU62afk!rMT9+Q""SHfeNPA+D
+AqhTjFZJ[FqpQFSQqaGHh*)Iq@bh010%3Ph'&("D4`hEdJ*)CS@L5jr!48Ui`mSG
+p0)IRkTY&hf`Ei(EE!0C&$P*)N3S"ALX)`[*L(Xr60qNE@GpN8eLV1"MSLFb5f8U
+J%E)Z%r2iH*NMKbZ"&XJ#QmI(kKY%`e&1bH&9'i2V!hhp2da""ICe-PH18!,9$rD
+X%1!Xd0I*NDb[`jj9MS4(F02S+$$[V,*`R45hFil'eCK`J3Q(2K&SKH3S19V*8Di
+C&d"qISc-dpIUDj4Jhi[&(V#G*r2P@!@Er,!j&r!TFT`FVq3i4eF3rqLV!hhelq2
+8mDlV6Z#6C8&%&[a94`1rr"$IDAb@R#!R+S&Sb1)lM8rA9`AkUYraRHM`R3i0cNN
+41@Ql,%KJMSF9(j3Z@q4NNC04p90NSC*6A08[j([N9$P0,p0,PF#AcPEp3Vj@6TF
+cP-#AcPEP3Vj8cT4&5Xjd9B&S4PmCk#ZhMfR18ii[iN[NV)LFp4HCNjcKX#cQCA+
+fR+2%HG8K[N4I%HJVYQ-jaf&C`N[Ph)LFZk1HTcNbZB([N!$cj(`Pd!TKp%Im0VP
+!,P3#LcF,l!Dq85m*p**rf)S,e$k@8@rN@q8LqB15LecQQrK@[6M3cY%1hN8`d3l
+[)dEd8`*&N!$0!B@+[Mc3Pqp5l#U"DLR"DCF&qV*rF*U'15(VTCD9)0L5Lq85*4H
+lrVbAhj4,j6*pUFBE#)YXIpl,cmMPXPM*jDkRlZ@(C)PFS@5*+mkpI*qq10!AEqm
+TTc'#P14"Z6)L9fl9&#U"%-RL@-P2b&*CTJ5D)SYM*6qLra$S2fc(XFcKH)3IPkX
+LFY@1hVc-pHCcr+TF,D"4+)aXEcl(,mZeFTf5Daf`jhLe[LM3&qhUcHYFEklQPq4
+kZ8%*0%Ffmr2mNVi`d"H5lhV6PK#ii8"RAkrQjr8&JElJYkkX%LMTm`0prUkZK)d
+JkdYX9ek#mdCpRT)EA9Hq"6+p5@l@jfS`'53aYL[IiNrP&PQZj"EA6@raHVP9-0J
+j"c(%eqLc!hhfcSA#EDkce[!kZ6dLYrmS!K$SQ5bX$IbKh#&h+VR$`GV!lqQc!Rh
+@6PL3!"eC@1ra"h*A41lDdE!36GQ'hFMIbGebMj+lAF0Zj'rPAX&B$[F`#h)MIk%
+A"AV4VSD&BjKYf#ri'lPI(P"b[m[m*33"C`Ekc,!m&B9a1N8%!e")U!qi2&r`PrU
+-3*ra@q[H8p@kT`IDHE(pHqYD)d0pMTeBcl-Af)kbYVDM!ZG5H9!H8J+r-8b2f1Z
+,2Ne@X)Br@d4@K#UGVG0M+%D)aSAlEQjm#1I$XP)*PLMJ!J#i4ak44r@T'P-99&$
+@ZF&ZT4q6aj9!"B@Q46a0RT!!*j9!lB3+)ZlT8`*pbZpcR4-[L5HTmP4%R[T4mL+
+21h!q&ZP2#cCMcTJ-m8#IM10hF(!PXq!#bC!!94&CYB-A),`#X8TG8-fc)P!dbA1
+#25!fIlENGE%dIPlqU%r5'&9K(@C,AKH,l"IN4583+YQUe-ALr#9j@3QX`Qa9kNS
+pI8+J6pJq6,cXDP"2'XJV%APPqe!#bc',S`N@k+r+DdTHG6LD5&1p)0!,YZ1!rEE
+&d95DbqX4HAe(,5%eX#C2EE%*Id2H9!)P&$J1mFlbPUa4!V@6"GC@fZRM!hhm,Sk
+$@`3i$K[jE(PEeLTjff9Z,pRkZ%!I4p&Xr1a!U#kVX'eU5aQ2Kff,Z",B1pQFf1V
+VB`0pl'pm&pGS@EkE(qMjZrMZ*%Y`eVP29Z0F*qZ93'f&[BadNfjkRMk'p6bE`[V
+$#D45mSl'jZ-GemlGd1A[bJCpP$j5bEZZREYK$rqH32)#TbREKYf`phpI2P$b[UY
+I0qQZM`Md%G[Em!2AKYfPTh`BN3prfJ(!I-TLk3d0`%IbXC+2(*EHdNI2$I6Fl9J
+JRE*BqNKrq53LRqaSk3f1RSE+F[P8",j3mTPmVZ3c9mqK-P-fbKIkF$e(b8CAck&
+B'RiTAbQ"(j'Y`9$S",k@2bYaEND)$p1c!celjaMeCeH2B6*#[SR)0hqCcU$GXE"
+'bhMj9MBTFIC2L)r4X`)pDbHX63l@'"NRhdANZaePG[j6@')@bIIbJa*i3&RQ1P5
+Qb@ECSX4j25%Hdj@"VYc&A*!!1PRQLXP8d@+8D*Gj#MDB&B'ZF-`9PL4N,MZMaH-
+KFi@6'P450LGfUESmd1@r-4IFU4,-G9LJ$p[&A0E,6m296q4c6$SBF"9qLLCXia)
+jda22df@k9(N`KE*YA#,c["5[Q[,`(aQfhdUN`N[edT5AkST6)U@k*0!P[r5EKer
+*X2e@+Z9HHX4,re%2kZ'[0#bXfA+N9phcPHG-S"#ISfF'HZC1@&"J@9Kcj!J[L(M
+"pMEfi29NfrJi1G@,H%VK2cV#0Mj16[%b[%cPi8Fd,%JX&R9aS)[rdFBHa&+fMBr
+(chKNH6@8"fFRQhQ"R+aR"(V'A`B3emC9!iKYBmqC4`($!Mdpd00rE@0[UikV+0"
+&ZpSBhR5X,5i22PjH69fS[*UZM4I*FUq@9eY2de19"i-TfmD,C)PAakZV21L`E,m
+YN[1mHPjpjF%2bS*B*'ITJN!Ar#3$8*lcL*+cj&a[YiLhfeC"Rr,U1M3AbU9H!kq
+KmL!qX'JZP)YdIU$criB'"P)@c89bLGFSiMADdEGBepZqA5ShHSfp*XTcSLr%VrH
+DHP(P0AA`X$,6HB(1fp@h@$RE[PdQehR0[1E+Jj@8cAb9A+HR"(U+m`#09BC0'dE
+#GP@HmjG#hUYd,0#ahhS9bSa%VaiDk%0hpHSdfkZ`e44Y$6Bd6"*C`dK60)a$4F1
+MP[9#5mL3!(Kl,EcGPHIqc!-ESA[eC(d)kmNfa5'ffI&R(Pj,VjAb@SE+!D5ihfZ
+Y21G*KHKpqZ"!(rb2@RMi'3q[MCkN22b-KmAiJ$bJ*qS*V1&aaGVbKjk%#q-R0,`
+pp(MP34NAGcR5ir4BeM"IBch@jS%$@aBXU92e39jEVjhAhZ[JG@50[q[*mYT5LKk
+M4qY4HQ5Jarc,25l3Shmh13cdU(rqai%HqGpZ8"PH1rbDJMk3!2,d#*hViGq%p2!
+!iAr@+%0$RCDLKhQG23d6SJb[-c6RHQLJKrjLT+MK!*[PGB*`CBJHV!F&HXM2Q3)
+pH+I0FD!(rFhT2F[,KP[0,AUJ2N!2d$Qk[qkRqqSq%'ZIUh[6qESA208[dr[6BVf
+IlURhe6hSqM3pd0RpqrU!q%m3q(T!h#(5ecQlIU2!erehrDH!Vr[YqJ@"32Ip@rd
+%Y5)ITA+L,4m&Fq)L(d9ckKj2liH)lVP,9ZVVIH0U'am9GRUF'RSi&Fh)@CklVLB
+G8TZDV#pTqmlLGe[CIhK)b@f,@lA`PPSkPRVK(b8SrF2&,6pUq8c,+h!qdr+6PTp
+qpRRal"KPaDK'M'VL&f0b*e2Y'09T(i128'0+RjkcI$a9+mTC2LCh5@CQKYIHNNP
+hZPYhdefp2Efpp$i"`VmlGZTZPMrK&jEP3IfQZ`5kbmr8N!$Pl3@#h9[[TIH%0Vb
+ccJldhMml',1'AjFJ$aUVmbk6AepMka2D"pI3qe#d0P9INEXLFbcq'FRql%4KlVX
+e+GM$YXYllA0Z'B-5Gl!PlN4VG8IG`G[Ekk,E"`Mr"aYRD*JrTqKfhMkHKXYFKJH
+K)1QfJ@llUbZVKLe@PVFh+Vk(EU0EkeDkTGipd([XbKRS0MYCYIA2"RZ"E[@EBek
+J@qldhJ[dlMYG$l1m,T5Z@qMQZTQ1kUDkL@kX'`@kaHpdi1[QF4S1G,2I$IGm(Bd
+lR[UkDGb$e0I@p@P'D4kSZ$%D2km8$Y`PP399MCrPr[9$0rVAP&0$YkHLYY2E%De
+["4*GQA0VlZ+*ldkD1'(PT!Q,0l6I-qHfh(V8pmU*lleE$"+G8GL3!&,D,PRD%Mr
+%NCCc4qkbkD$)i!Vm+mIdc2&8GeQ4$Fp!Z!MKY#YQ0-QjG@,ZH,-UelkCBHQcSq@
+@KK"K0Y#lH9fpEVTqS"[qVcP1`dmb4GIcZRXD@i`-VlYPQ,U"KK2V2ecp0"bUXVb
+ZB*JkZVDZT@[U'MSVd(9fj3cdIpJf"EV@eN9US'[q[,3+G)fI&L+"cYSjUfGjh@J
+%pp@C9K6+`h8'*+"+4h5JICl#49aXTBKm)TqLUr1CI!&I"[h@PEb-Ei-Hk3&qL"r
+QTk&YfF$[mkG@Am)DHMY2UN&q-%URBdfD*Q1a2*dSH9+!rHCK@'UGC,Fm1P@Za2U
+MQY`ZGqN8H8T@b5[bZ[EN3rP%[T([Y(MTAU$CfmeVT$&UC#BRYicNj'EGNR6NYmN
+Y5%jZ@!'&NjZ[3mHMdP,3@1Ka&!k'DA%&Dk"6rkB2#c4m(EBUN`+GmV2`*G$HImN
+&!Sfr,2VADKE9rkr0A`#6R(rI-pA3pH@KGH[IHAI$c0R[rHRp#+AR2[94Hp$YaqX
+rqI3c[2NmqHE@h#X`M&V,CGcKFNie@c@Q`8YLpPG`U(Q-DUr(E)V40%EeN!!A#kY
+NjY['8p-BlBEh$@,8-%D0`[H0Yle2Le%6%$U3!$A&@UmH8%8Y8YbEK8MYLAGAaZ!
+LKhHiYdLq#p([$R3YBi3(V80dEC,SEJr4lC&cHfk-fNkQGLhY'D2fZ(Iik9`5Ipd
+aM&i4MhB+SeI'SpRrP[R[jp+@U%VR'1eCE%Zb9k)N-Ia#NChICf-8m3TcTmr'[)*
++GiPAI*piEde(0h50peZhq*Z-CBYMe,epbj`l`Y4if51HBGpY'ASQ-k"6pSYhc2l
+E-[4+C!Lc!(A[12Sqm5a,JDP[(&ZrECRlEd1I%mm`)&%ci$`JMRIJYUb$YP9NF$c
+$N!"Y'BBQ-bb0iIFdN!!"pq(E-Z4ZUeQBD9PQlSK-cc`2,E#")3'Ejr$R'*KY-Ap
+&[RrlE8L4Gr`&RT311,QaGBYS"(Zm,2XEEiJYV-LV`"m&d2RfYpY`[f*dcMMB2G"
+0&C9cl3,TmBUb#Sa6p%+rh2j`&k@hq`l[EreP[h'rhFELIVZ0-pa2Yh'$SVaLr-`
+&Y`)KfrLHZ0[irS9BHH!qH05J#IKj$$jSl)K5kd-rKHBE'#a[Xkq(*jEpm!i#FLa
+")BXS$0rp`FCUR@*Me@#3!*0mpm$@h,#NF$'i1Dk4dV1aDM2`qi1YH")6h)U5q@!
+TNh`(2aIlR4r'-*mQBYKr*f29QQf0KAlr(ki)ka6q-*MllB"8H-mQkaIqi-$r"`!
+!$3!19A"NBA4P)&"33b"8Bf`i,M"UC@0dF`#3#9Z8!*!2!9A4!!'5l`!!,`[rN!4
+"8&"-BA"XG#%!V5`iU+qS`VB!!"%@!*!'#K8!N!36(3#3#"+i$-$ikjKR[Y4M,cI
++RaB&S0G&1Ffkp9NMSjabY4`3CY[SEqPeQh@%%rjiDRLDXP[cbAV5iqFQa`PEYi4
+hK&pN`)pXmTaXXXPJXilX)jY'RNIfNprNpT(*5RK(0YRRdH18jbR[I!IbJ9d1BUe
+m&1@r&J"3eEFTGlrN1,NYiC(Mj$C"e!BJ!(Tjf4%LMBJ#0P%YIZf4M)LP*Y2a4$b
+jAic%%Q)mP4(fK#@qEXC#KY%AVpf6(M0Y5``0G60r5%Ih)60M$rH20!(k0rVCqrR
+jZkjbN!#e'eJC9)4($STXDLS6Xi5CL8h%Tkf3!"$pYSLC56&U`B1Tj*J`lAE$U"Q
+hdqhK-+T3GLUC-%Hc)IJ96Nq0KQhSQ$4MBF2S(aH(S%BN8UQ$l+0T`m*i9SbPBP1
+69Y*QYTJ`Tbf4cX#'#k2rXBVIADVbR#0*2*6XifE'4BVF4flRkZ(@)jX'TVT(8L)
+cPA4NCf1CH0S@CMUGL-G-1jj+AUBFQ*c+fQ)mRN%96fCY-j%3AHKK$DYq)FMblPZ
+N+VMM%Lcb8l4kUFr-MZhT'KEE3YXLr0H#j3l!&iedFQPXN!!"6$YBmXbYNa[-094
+PS0!2+0)DHCDUI5Jf4+KQmT!!E@Ef@hD@S4%(-ULDY0f1!2,S'!5GDXKVS0!Q&8d
+MRjpmY*k-G$VfNa[MSaNcFbMdDr6"jmA[PmX'qCefl)hKKc(R8B$E$FFRi6JLS04
+3,R2A+[be&$"3k!RQBH++mK00&U&!IX)Y![L$Y0C!SDbX)SrmQ0Ej8$4%b)pabYM
+T61U!&E0,k*!!JaUdcV'LLUVP4blj%@NkVB@Dp94RS&"UDXJRPqJm,YC&U$S4(af
+2*b`&p!&Jqj3'6!*Ym0-'#2$YR)SRaX3H1jl)1YlAi6qIkJd8F*&MPZ6Ik3)0"FE
+K![S'I8hX55+q9#Ca&#C-C)&pCdSJIUfXX&-1+q@NKNL0+pb*jF5BP4&aPA6L6M0
+T1jVVm9p)&aNS+TSrT!B0"63hd29dp@T6P[L[R)ScE*94DbaZTc)K4pe&q$I5a3D
++LVS2U&&$!A@0e%AA)e*6D5YM(q,0)@Eea$1LA66hCbFQ65[4hQ00@iP8QJe[,de
+RYKh"[6d8D@pf0&k-Ae#6JD+LmAeUeP"!Bc1e8V2)@MC'4)dL1eK4fP*Q19+Dm'q
+Lc3D+5Sbm*pr9j(XF)qpbLmhi,k%@!i8H"pq2B,Q8@Jd8V[j5bhGN3ElYPHp3IFL
+dTZd8JM`jP8J3jF"qN!$Dm$4Ci2"kQb1hY4bjBGULdaD)D+1Y"JUGP`hX@A3CA@k
+JJ#GVP153!$aM8+JXf#rr4Q(jPKGPI5Kl+*Y+T-`a&PPH2Xa%(,%F*YeCSccb6BT
+i8ELp(&)'48K,JDFMhpl`b6Fq6c"G[X8cF)B0ZpcTaeDrlT1[8df%eNbT')1'VIL
+hd48'#Rd3iaM!A&j*9aNSP*rV-ICAdc8'#[M(q%Ej9lT@[ZC$b8NmbV&BhLXFY,4
+Dk(3Ya'fAVaUdhE'JMLk3!+Gpm[3AfiJZAq8jHieYZfE&YPGmmK8+4UJUBpR6CN,
+9Hmf%J390p3K38,lXNbqIXrB+r0I*P`bkMYbhS%X6CUUGVTF[bN8$J,i$iG1%K1L
+J'``85NN60FY62RRUFl8h1%Y"-ff5*ehb*'N'mYCe%bLAdPCjJRE)iek8L"'%UjA
+*L*@TGQ,%S"f1K#f)LdirG@*,@1rX&FKqc[dq%m-ljUa+alPiNFGiNC'Af0-@r&(
+jJN(4PFKlAMkRbHHjch2Fj`@1)$!$3A*4PI`,8RZRr$0fQ'i0)2DT,R,,Cq@#2#D
+ImFPR[jK&ReciDYAbb@1IKipA2[0PPYE56Y,GmQRUFD(3DkQ(hI+4iB*,@Lee8h9
+3rSPDj90bRRUT6clT"IcIE(k+ECpRDhZjk)2VFh*@2L%IPhqN6UqF+d@R9mjq'EN
+qqF4UI[MNierPQ`rU2SZ*YI**LV3YM[)U($k!YEMhkF((eP&Y'c2Si&Cbp4lE-rL
+lJpT'UYPbi24j0j0V)X#"!EVrij-R(i8GMD8M$1pT`cD@`eMj(L1'*bbf(q1X9LH
+-ZKH@mjC4ILS8X#J50KARmA&$d)mlNA&(XFF39J25"[E+TE"VQX+Z5-I$MrkdVkA
+amPh-L(6-r)K4%C*,[mM[&f'Ak)LPNhEA'9PXh[A`SmhhY66ZMSjlG[p-&[IVdeV
+3e4+5l`rF0M!eX"FlNIrQ"m)G!i-Mr9#EQfPX[9hiaceT9bFGrF-GV@(rdHq,%H&
+jDSEUQk*8Am)DJ$AXH5"F*firFYZ1h-KJDe)@9a30r%D1l+EpEDc-6#IXF%FfPVE
+6660YV'lr1[$mi3lf0%dcE8IIhcH)MRCC!hJ0h*AjI6IepUQ*b29h$fa5b%2-Bk#
+kDfMSaY,"3c&d4)`EjjLlF)kj0iJV!NiMZT[FZ,0i2"S&kbJRQLNDl5*4b1@#pe2
+8med5lRY*k&%+DS+#HT!!JQi2"6eZ%N(NYY!S&p@r66Rh24TjHU"M&fiZqccN(N0
+@2`DG'TqUS*[eZe"AjiN1)rfaIQUi9EK`)+R'-BH[3)e5jMUPc"q@FK(AUJ,q*Ia
+&r'I"NH#H4BmLHLe9Jqp#(ab0mUKc`+'"G46a,e(eD`9br4Bk0HK9dHU%L&UYcVd
+#"mM+#hcD)-"VmMmD&'C2V5S)N!"rGV9"J@ER!*BE-"hp+Je+p()$49GmT`(6Pdp
+8'LMk#8F!0j!!%[6MqBU#XmH,S2[pj3E,Xr1JjbX0LV1"1G$*M`X90`K3IKCdFKV
+kjkRJab0b&-*(0'#kiS11PNc2+clEc!e!Rm005p'9+k$2PZM+-Y"Rbh4D,M!pAk'
+I+*kM(jpITE1$Uh4fm&4aK8k"r(`K-&ZKmdK`Nhm1m!Up2(@9&p9bYG'eSLQidh2
+DrB0l(Zb+0SRQB%rpICF%@m6'+1@dA#$IZ0KC1,b%h$NVj@(CHEDaf,M8@HKFh*K
+A3F*r`0%N-91-qJ0+C#%rch-Cm2Y9*XM#[!U,j92,+L5@!mICZJ#2'@C8cGpF!Ed
+#'%'dKUUj)VGHRPF`&HF9M"#UH&VbmNVRiUUZVk8,V@(mEm9DYj+##13UUPTrIqP
++baGDjfCE4hI6Gr4p1*fJeNlUEjEEVGlFYB@HQ8CH0"Ud4bLBM@@r"Hal[#6a!M,
+FIdX[P$l#5`h`hirdlKZ"J+HcpL&fiBeX1MZ"qX2Z`CjHdM4pjd!2pK6Y3QHTd9U
+FT8Dl`PPTY"ha@!+()feh2*CPI#pUaNFRaXG`d0'5haa+BEh9i)'kFC1fF-YPP*0
+bL1KLB$K[+Gi2JD'[`QD!EAGZiV8$`$cF$laI!G[XRQ$-mdYJNIAhUakDYY"G+2%
+@`-0@Sl#hJ@&4Ne+3!1F$B,YBDah9V!9fUk2*blf21Ifm6H"Kc9*BLlCJjZJKK@d
+$Ejq$qDi'liL$'GH"GdF*ZaYB`qYjjFGfB(j(4qfY`)Eq$`#3!`d!'&9`C'&dC5"
+8Bf`J8fKPE'`J*L"6D%aTBJ#3"hL-!*!2!BKU!!'GS!!!,`[rN!4"8&"-BA"XG#%
+!V5`iU+qS`d3!!"&B!*!'#N%!N!42``#3#2IC$-$9-Fpmq`EF+$GD&)"H(H@HT9q
+$2%fZPJ01Vil3jdH[fk`MR2"If4UHTUbemrCkdMUkb5E(eLhKC"2qC-#2F2+m)jX
+-q%HfC0-f1AjN(aPXF[[)C#@m)rYB6i[b-fmlL!hN!lH$2&YjAKlP[aB!80@hf@E
+lb#E(b'd*Ma`RU0J%&4Y2!(63fH'*""%&RbF+i"82f0CBLab`TA@hE8f0TD8pBFR
+akDQS(8Y-4H)aZhClFLaL@h)d'TFM%eBm,TY3ha$E*3hi')l`Ql*("NBE!*rlIR&
+qrj818VP6aUDd`ejfQiE&Y"a2a-HXP%b-bjR$Date$U1c+4YDe,fD9B,89PZpP%V498
+HY+h#f10L(d*3&GIMSRUNfY%cKREYX5UMpSeL1PCT@kl0CRFL191CLSRG%j@fG-h
++MCXfA9%YZb"lYfk'jfbA&$k8h+Q,'CF*FMpf1eH2VheXcH"dpfK#TUDjHl'd6%G
+6XD3Y)mPN2"D0m+KFaYf6Np0T@il(8UKL8fNlJQRTJSBeS[A369S9rXqBF%Z'qb,
+TXHeG)h*MbmBfIJ0JZB2SM##$A)*EC!)6GaB8h3Dj`9a"C5B+BimQPDR691j$XE+
+0+LCRl%KUYf@R'4Te)*2+5@c6@L[)Bf!8$+SJViP#6'UD)*qII&4$J@3bqJ4QAip
+mbkmKK-H,edqQLF+)XbM`J&Sb+H$S-ald8j!!3Z69fSJ04eZS*6CJiJfT[!N"E3#
+pT8VeT8Q9MJ('Ur`BFM3J2I(%5'`53`3R440I3N,P@DF-EcA9Q#MJK#1*e"IUFk'
+qB*h2@D)'lhQddN5K"k5F+Y3LRHp$8GG'ISaTbNkQ%RZXU&e!Kah8T21GGT564hh
+Q8Tq4-'JPh065"5B+lFC,I[8TVI+KU'UMmRKXehJXEQQJ$i"*Ua`2ASc6KAkk%#h
+fECf1aFINGMX@6cX$G3(H1PTYSN!A1D"*rBdZ%LJ`BaI4MA5ph$i968a1@P1f$Y"
+i""PMhj@3!2(BP)A86MLXK*0'R+D-FfJAmM@QmeAH&CQb(FqVmGD60&'82(p#$3)
+&2$I3CVVUM#KEr&Iq&F+mJ&TM-6Z"b0EZ*0j'@Q1L+,RlQ#i@+1$ZBZULc4*$Pl4
+5pJaDP)TD2E'8E*H0!qQ*bBJ9EqqapPVa4*)EhPkBcR5l(BeIdp,@$NrXF3hH5kM
+*4&(bq&Hk9+#!adYT,6A+Y'9M423SFJG,6TZ+,-G+%pkeY-j%8BU4Me41U)mi4R)
+XX3j[-kdh84Jam$Qm,U-0*JVA3%(b3h9+IH"9(e*Y5m6DDbH`)%a0aq0%'E!ISQC
+m3ThLm2U!$@`S"RNVY4M%Np0+E5B+)k9T!GT)PjXSd*-9`2edKAVIT#Z+K[hU,h5
+PHXq,XVBP2C01a"14-6CCA#L``#(XVb6$@F!mkPfkbS[#lH@3!$,T+K)*(EIPkKf
+IHZGFJKRU2Ck"plPKPcYkh1UhIHTYUQLM&G-kaZ#K$Hqhk'S6K6'%F3`L"+kK65B
++hFpU*%dlE6C4S(q-VeCrTJjedSH5NhJAaf*a@h(3`X*L8!I-AD[H-ZPDT`8eG)&
+kdkIHr'V(-G4E2'FRZ@fEPp[fKNqp3D%f+NYCpYj)A0Fl)R'60MNDf&R8kcleqYR
+@ASehLeS`D3ZjEi&+!fDdNm,UK$TZ!M#f)(`DG+TY09&S*`h8U)lje,&cEVFk5`%
+58KeeUD-N6!U6kbC3,UAekNr8V9lcSN5-)&bY9%SZ6l86)bCe1aE@)Bpkr05$(D,
+Df5Z3!2fFqhd4$1qBMMIe'KFRH)b2-l,!29f2YeHpDP,[FZ5pSPi@kKA@HCPeAZ8
+)!M-B`Mj@T[j)IA5G1S)GTPm!42leN9XG9LqT3qT&RcVme5cke%[IV&SqGHKFq(M
+9LepRDB#Z)m1YAU!"&`TAJ!E3*qaC3DTbS8mL32e8(P,cY%%pV`l50VTHcAN"rcH
+GF43aS)AQBN%1dIASqh2U@I@-1U$q3$eHp9`K2,hUfDp$ekHH1C-J2RAJQi6c`Gf
+rJk*5c9&Emm)ZhUKEprK*p"iDHVU+!Xh-S$[ANk[hm2DKhpdT9P2&ZMdRclZCA"0
+"MJc3r9mF2riNfY&511$S6@dLNV,'j&iVaEHAiTBi20bY%b20HcS89cUl&'EIL`R
+JYD2ikC6!jN[BNjb2VbL5IYVC3@)reL6#QN"LF)GDE(AYT9CA@mIM6rkXVkPq3cm
+cfMTQ(f98YUM&AfChbeDAl)JQTqbZ8bVIf2riNihh0G9[#iplYMfPmVZ0[5,NDQT
+4R`cH0MJpZ!0,N[rQ"eXl"SG'"q!f-eZrpRET(rFNACfdrm!GDe[pqaq@Sp,c`Lc
+90S5TYS$9!D[ErQ"VMEcpXGZfC%D(eNkTr,+M`GqSd@fdZjQG4C*aZl8M(8hDbBE
+CCRDhZ`SmIfX(pc4*Xmhl2pNj"%@lk!'m1PCPIYp0[Aek)M)$hB0V02))maJSlaS
+H[U&`9p%-!iRMaLASENPdE`KR"9aJ$$HjFFlai0!9UU'-E+4`Z)YN,T-*h8pKc`p
+)ZZmPDB3T*#5&M"#&h"i+HG`N3`D&TD"-f2JqCGch#2,d`%HrQc`l2H3H3hJr$Cq
+#,dr`cIjGU-Zc42Z`#@#l&6L&Z("2+FI0L)p0p8TP1TA+lP0U!@Ha(0j&[(QmTm&
+4i*k'4KjDLqAJZk#$fe3@G3Bi2,#220j&+Rml4klI`UH!Ajfd6SMSAH[XPq-!@Ik
+#ra!)mKEqGi(F(2DCCB%JqHI1#14SlL$!SJ$6S9F5+0#,!TUZqBi!djH1P33drCK
+MJ!@8![eSYZ6Jp0%mk(jr8@"TEKldE%NJ2aFm#$VjFIaLJ5"Pjd!R4p!r6cNr2L,
+()IS)!DCV2ZL3!'4k9[1jc5`!qN'F`$4GG`AdZ3*GY`cdZ5+GPR*-cjESar*Rk8I
+Rcp#jJfISh-%6q@8k"E2cZH"FLFiM`5,r(1"PHR(U5PpBC!,K5YN3fZSjkIl423p
+eK4YNBkLRpVj,3NebGCJb)K2-eLpdj[BY)RG1+l92GCkZcpF[GZBk&eCRGC!!m"Y
+d2#R-&+2qS$DCbmlcA!EpITd*+MH[`f,Ta*)1LDAJ8@jGN!$($$1UjqpJ$PT"M##
+NiHTJRU@AjM9-qAN0)i4+25hdFUYcfY9RhX)Tf$6rYh&9,BFLmVQ-bUV["q,GZ8!
+Z*$HrI2&ST6A'$mA(A)ZI'ka3@$#@VrRL5-pX2HmGGH)"#['Z"1b"G$6pAGj(H,G
+"rC24hTfM%(iUEFq`qpqRNqN*e)HkKhTk`6ZqGE#(ej92RGe''-jZ)`,1CL0@aD*
+a(*4%8bbDC[abe)a[Q4JI`k&(E"XCZ+8ApBj[$bH`r)TGP&&UQ(Yej"EXM[V1rMe
+JNRR!ILb1p(@i*aMcR!*[Y2TqaJ)h!+YcH"85'#*3Bqh!B%FT549KF555`3+MDUM
+L9[#`1E''&pVGKadpEabm@`Zml`$VTdFdaMhSF$"I"PMB`FalSCdVB!I!DhXhUr[
+a-$#2mjp!B"EB0BkR`+q!hI&r!!d!$99`C'&dC5"8Bf`i,M"PE'`J*L"6D%aTBJ#
+3"lG*!*!2!C,[!!'SG3!!,`[rN!4"8&"-BA"XG#%!V5`iU+qS`r-!!"(%!*!'#Q8
+!N!3Z@3#3#&'+$-$ikjKR[MelZ9&ZY#LHAKIP4NZYFQ!dZGTPF[TGp2PTYeP(11'
+8Vfc0ARCVjj(eT(9ZXXQaG8XifB3rf4*qC*0RK*00"TX9f8Hi4jj&pT%C2r+EV)6
+RN!!@V8[+"qP!2SXe@[Pb2+2me`lBUQqcl$TbR0b@m-Ka-Yd%04Y2!(63fH'*0#)
++0"2jm@Th,eUT2j+ZTJ2-4)Y'J&@HcJT@YJSba'aX6`k&VDJj%)Q[Efc5`HN2Tka
+Yh31e`TI['rbElrIRGPeQ)iXIdqM`3A1`ELalB'8A"8c85Di08D8JlBHSUP"A5hh
+`jUlXL&XK0He(XJGkEqkGq-93BR!mBF@'"`Flpm*4l`kL(R"(P)13!ehCiDm9ldP
+&alk5*,T09DkcA@*m++96U[0QJT`("k9kB2A"PEd6Q`B5CQTLh,4'BfNc(8R&NTB
+C6LEMX8MBLLA',c(h*5E-XBQdC3l(8UKLifNV()qEEG#)EP0kME#e226[-C'@r,%
+cR"lDhVE0A0HiVNPH(eK12cUMN8i169TN!02f&"5G1MR"A%4P"JTpYb+9mcb9He!
+XDk++XAe@1$85YG)#$GL3!%(PT28SV6*bk4J&R5V)ED$3aK40)iqA2,58M#[@ErR
+GeYLZ9$LeVr&Kk1"air@5BD$3ik)*h-Gc"[PXHF(pA[+,I$)C15Z[mCai-2!'D,'
+"3RP!GfN*j`eDBRX3I+NA$XiK[l4J@f`-Fi33+VV)LmCL[*AmT8'9YJX(TZ%FrX+
+!UR)Kq$)[,4-AdSPrZ[J#,[K,X9+'pebU-P$!LZ3FmHFmUr(RSM-V%P9ick2P"JS
+eD5jbmprTI!q+kLEbBYj69M+9f"f0@!@dhdB01YrZKiXUq$-(IdDD6X[KTTT@'#L
+8'`mCr$Hk`)0L5419af1lKQ2aU!)k!4KdJHh"Jl'V`B2QHpSRB[%KFlX9LkIYd9b
+"ek4D!`@k+%P2r#R9D5JJ@dIAd4CcqhJN-6B@(EH3!'94-aj'@&Qh*XaiE$bD0Uf
+%c8VBX@BQKK@1N6'(%r'KD-U-$DZSZc8mEYQHDr'ZT&8'LT,RrkF,046`I#&YS-[
+2L)V&Ei)d*R#dL%D(BPBLe@Ll@i@hRLib8*6Fr4qYeP$!h@TUS`dQKLiC69Rld+*
+8*0S45jR0CPehHR3X()dhGd6h4Z1*T$5mZ6#Gk@C,E620GEE(Lr"H6!d'LT,(6fL
+0KJ)Hem"PRCQ1@KJ40BV5`C,6qL,,YY+!pa*DDk!Sa8L12pBi*c(bX8LXaGY)331
+&(J2IKdPZSR8'#NGh3I)MrT!!2h$c4e69')lZY4,B0-BRiR'L$0Mh83-qM6q8m2T
+!0S*eaBdJ5*IUG#P-r)JZ-e$S+8AcdH9dKB%#29N%h%YAm[X'A9Ndl1AhD$fIGU1
+XDNc[5bILLI#3!*JXELEKH!aE`hV5l8h1aAqPUp`SR'i*+B1Z)LfK8VZFhrA`Zpm
+QQ-kRC3EHPiCGBHY*Upram$Y8d85,*P5-`F0PH*YTJi&#lm-iqT&Q,A5eJ8,eFbR
+#Eb1e'LM32m&Am0X8iVFm+#@*GdNX&YFH'beX2MU&B+k0hc33(+S&PA3H[q(K0lj
+EPR4q8qEX,@PEkd,EA[I`ka4SSV*8e0SEMUYk4cKZd0@fKTm#212KQE1YhB#hR8m
+Ce%l1'k&5LiRG4"emNNmB!250#*pDC0jQkM43+#He9-I(2Acm@lHGpP*34b[j03H
+r4TT"(H5i(T5,D!hrKDlK9pdS%5-)efJUC5j-Y4dM"PeM@d!!8THAZV$G,,Ah#Q5
+rj(jR'--lT1+0AjALT)ca#8&158q$H,ZTad"4LVaAq'@0Aa'GPd@L"qm@IXQJ,3X
+5drbLaY-LmD*BH8P5#Nar!&YE'IqCYY+er!)Q[9F$L$9a+cRjH6l'8rbFKjrrEP`
+pI1b(EFc$8prQNjZIqcjZIA3Yk8iq5Rd1&%iIp@'ha$)Q@qib"cUPqDLAbJ-m5H[
+i@Ak'qZNkIYS0q$m4rUbdrKPTElm8ek(c6r'6r!3rcSp4PjZI+L5XQjrm2TNpr-5
+CQ2(`icr%S!IZrT8QLrPTDQUBf58,I(#hPl60,r3pZS4m$F+J2@[)XIR&lAf2lG&
+@8-A&Zpmqj`CbM2SP9d$hIR(bj"'dBfhKA#6VA(rr*M-m2Q4LIcGa!dJVF*Z&a6*
+LTNHMFHN9GR1eEf(ih4J!@8f+RiS*,0f%rF[qj'4MdQpE@dJlM(f+X2Z3!0DlJfH
+$MVd8G$5e2($N`FlkQV9G`QKU1I4V3Fe'R[e$GX3-1Xb@5(,FD[Z)mh9G$abTZl1
+qTLFdl1TjL2-MqPiYi+K[j%rPC#4(TD$hKRZ$,Eep!pe`QcP8XhV3p!klNSj@1[c
+8,DZ$hX1r0!G-ec'FV(#qULTJeF#UYpmEV$3($pkm-623YhUFm`Z1HKrKJ4iDD4"
+Ri@6F#VDN)dNV@AZS3Gb0,!(2'fb4RLET8-2K6hIf3G%UHJ#[@P5&hhRpjNie%CR
+Z6EdV&A*!H!+8YrAhEbdFF44$4q!iFADkc55k)i$6!mipZT1FZ"fjA"S&+LPMeP%
+Se%CQ,T-*h%8Kemr*G0j"TKkLJ'C53!p3`1QLJ-Y*CJ!VP+P4*U6rM$,1fc9bGF"
+(Pj0F1ehN(%*k2`UIQTbji&[m1e#ACiRfcmJZV)iT$Ta[j%SPPkdDjN`VFhBrm`a
+ZF$QmXhMcH1I"BA$RSC'(eQ`jq!lSi"#@4Cd"$JrL)iphPXVIcC(M6r#T`Dm+@MY
+%e$jfpXY*J#amrUm%r,+Zrd-J0iP0Cd(!6pl*-`)jQM`+X#JJG1L9"!VdSS#L+li
+Y)25j%b8"46pK'a!"CY#2CdX1jSrR3IGkL`*cNe1JCdX#q8Rr8G$*LcZE#2JT1`N
+kfB,H+FTjm4(C$Y&(#!KGm8'(T0#cLLpY&J(3Mq,LTZLU+k"2&ZLUCD"2&ZNdPa0
+kYN3rN6p,2cjeKLiG2%1A$Tl+,p$*Rjh+q5G,G"N*%IPkJ"ISaDNVI5%Yi`XY0QX
+$lDkhRIIIIPpEU0DX#h48hAPKS0jF%D+-P[&RDfCDFrYRN6[cc2ZjGEiQAc2EQQZ
+G@C&935+[hrE%Q#P"[AjP-THGNVRdHldU%cJhTF*LlY5F#SNjrh&TR9r'$$1UjZp
+S$PTqM##NiHTSAU6RTK4-q5N&)i4+25hdXXfq)kZEFZ(ZE"6[mrpGZ*BXC#,LZBc
++PYi&a,ecKK`)ERRP+$*+&qM[kEe5Dh2k(8@j-hm1D0-GKfTNlDM@lUD!V%V!lNj
+(dMq4G84@'p5r'GLmF`$#$k@YIGKpkBPd-Mf+qS90I4fiEp$*pYi1f9BqXeFE6EG
+A'meR,cEDmPJNMTZ69Kq,T!@r&,AJ'dH(Kh!,dRUfGGqi'I@1(rFRd&eY&f@BX8Z
+60RdMGK"edrmTX&A#!rBVEAVVrFj4`5TZ!QrpdVX%mcd-E+$!ZdHElX3DTV!(`F-
++bQa5a4&Y1Tc"rX+992%dH&LF4--0l8fiB5MX9I"Z+["1`ZYppTm9lY2J0GQBjd2
+Sj@c-q!4HNcEQZa`DYpKrArMQSAh-rLI"A`QHDA[be`(crJm!)5%1G'0X6@&M8(*
+[DQ9MG(-!N"E4!B!#BJ0h!*!$!3!"RD!!N!B[#`#3!iB!!!)!rj!%!`#Y0P!-X)6
+[T3#3"3@H%3#3"3'RIrrArrX!N!D6%3d0$%eKBe4ME#"08d`ZZ6"PE'`J*L"6D%a
+TBJ#3"`M!!*!3,`X!!F`h!*!$&[q3"%e08(*$9dP&!3#[Pr(PX)6YiJ!!!4i!!6%
+D!*!$G3!!)QfB5M6Q!*!'TA)4!!LbdAJqT3$Ldi`fC,5RjQK+Ai"mIT)55NR(rQ!
+RhrRBieJEr!(4ZNIl*!6+H@RGIKmki-8R!-9[k,6f!G5lBNkrLTCcYI[RD%XEcYA
+ZQU-YUc9A1cT(1l[bA%fISeALZGUYfCUp2jR1V['eF45UEf%5!!!1q+X'1FM2@@C
+*qAQG[4hPGVfac3TZce[V1Qmc1cHcbkm"fbYEXmkLlqhef55ihq[YK0Z%qq'Hj+"
+1(Y`2ph8La@YL)kqa$5(C6q"qi6j)i1f$Qq`MQ`&M!35-[miZZpCQH1EK+EGhX`d
+*lmJq-YRNf(kfm4X#j$Rb1h`bR@kc,#XQppQ@[@LZh*GCeS5[L6eKbm-lBbaEcdh
+@10XkF-"e2(!!*f0k3#(LLepX@9YIc#FqYM9KA%1k)j&-qaP96N`U-0'q0ADGpqi
+m*K2H0V@SH'rEPXXRX[NJ`q%M26!f8CIHI5L&-6`ZNq42F'VKP-@YcH5'42++9+)
+jPFh9lHa0`*E)AP66Gc8chf&091q*ic1*j0@*(DRqr#HTIeeZIh[9rm5QrEPmUMh
+HPXMP8VPZrh%VGRFdY`fN*p9`RY2N1c"bU"p0LXepGrSER`*5H$CEEA5"EaZM0YV
+-YrA(LlPek-a[Q[1mpX$UY4ZfUGqdX*l4"BGD+CMjYA04`'#!eRNX,9TSaZmj%HE
+qXfA09hX988"%+bChMGaMj"iVYi#d04kJNRZ#h"2PRJ4'bAfLh&2NRLVh0,P2NRZ
+kh$2NRLRh,,PRbce(lVPbRbch2,P2NAZqh+I+$GLI*RHYh+I,IBEF#q4H+2HCFTm
+Ppb+jcjEl(,R2PAZah1I*IElFGA*I)2F5Z5q8qb)T*AH$S,YM@5rhik5S8R8$ZpK
+lbUrdTA)Z**XBcJpdZX1K*F"#j`Y[HJKQS5"6"-1*hhL9f-XIh9A%FFmL(@ISL@-
+AU*mQP+"fI90YBf1m0Rj"I2(LZVIGcdSZPE1mXA%Y',+PLa,pkC!!MfIFC$r(RK$
+lpjd0j@Ij2`U8`(%Z%Lm$ZXAbAaKED,fQCT'K5HGCpKBhVKYaHM(QJQ*Hp,TTF$Q
+V&33jX"3A$*p!EkRYfA)l*-UbrPAZ#@Vl-,fUYKr!P64pFTkXYJI!NG4fX6bQU+e
+"(P29eP`J%2BqHCbNY[qN0F6f+RR-80Ylj6&6ECq6abber8JHXl99U1NFY3(PFpA
+f3(QFV,CemTLRYU3m6P(EIRNBq"IEFq9aUYTH)`rULBdDR+Df,mQM9QdrPFITbZc
+ST628KJmpL)dq@+Lf+q4aTYSH+iqce,CE(UDcaAC6!@eVrTXmcP%E06KAEG4JXGV
+ZNXGjMXfdqIPUSkCeDJ-$,P"E[6b@U#fK1)i0R#)1YKI*Jpl"pKCj2%KYRjE(JpA
+fIAP3@b#&a"qL0[*HUMCL294YMj6(-V9"VLp4fj2Pm6#e[93HrdjYEjA(`pAf'D"
+9EE!d%9%iim#Hj@UM2eHSMAcLDYXN$fU1$FUq8Qh2P-FUYGdXMm[9pLjjd+IB2Uq
+BLHdRmPMMf-D$LBp3'cd[r-(BU#pBKke*(Q!10[*@IMAq1I*S90XEj8&IB+2''p3
+'YK%I+!DA0kS0A+#Hf+M[P@VE*Sr0DRZ52,DSl6r,Bk[Dk+HVe2CCH6a+EG6edBj
+Y![Mq',949c!+'re$MYM!Eq'0aRDp2-!3E263GVAG)Jm`&Y[Aj8&-E2pEH3G8!Jl
+3SMB`DiIDk$&9GbDfbS-Efp2NX8YYj(UefX"&4$CXhj!!K`Sh%hmPM`l(0JP-8R9
+X%VL684ZpmALelC&(9QhJRmSlNqJE&DdQd6GJ0EDIbB1BFLE$BIDU$Eb'ef!$8q!
+Af1L"Dp6f&(NS,j`-jX'rX,eI(Np8flIN35r,-C6U@VA"6j4$RJJQJTrBk'Ib`ND
+pRUSfH"9pLZd0mU#2X)(P6eFE'(#$BjX#"[`(YF&2RU%fm1C'YG'hi#FfFS#cB)-
+[rNHeI8)Hce)E2"GH+@FUf!N'BU2[U3mfm"6qKBdqIjlDb1hjDRZp2&kJYY[Nm8+
+er9!Hrq6BTS'Ap#mf1*A4*-3'0hL*fX!DqJiE048&b0KH*`m`%pZRj2&Ie!E2qaI
+(GK+F&[c"4Uqr6'e`K[qU0[$Vj@UMPekKYRq6ab[9pR&j`1q``DIK[(+Q`b0IV6D
+i)Mf&$Cj$I'cJ,r`8'hMa@V94DfU)$GbLAl"p34ld2MEi)Va$cJakm8eUSeIHV$B
+i%V`2'lK#,YM!1"9BCY#VEeFEHEj$E4q4ac[9"NH%6mQC#8GrYpVJ`qp4'aJ'KQ1
+$Bla2EH!QH)J0[2L!fUMl"pAf-AR!0E$"#fpeE!KXeSI8"[DMA@#$Ve)IE2#ZMkS
+02N!Zf-!EX!8EZG+Rf2!"dl$pGhPm8QdSA'#&R0P`8(!9'l`A6SF0rRDlfZ!BGkL
+0ZX)TX)%&k"[BU#2F%aZFK[l&pNYjI0'acB%rS30JJm0r@@e`bkqS$Flc9E@"F``
+HB!0(lP3E[3&(`iB2q@,lZ6bqkGMQSX[!4l#K+AaEEI$HlkJ062fZfZ!N2@TUa0!
+C9&`,DUZVhTf86lD*9YV3Y,BaQfTTh9HhNcYCRD23+4!["AZK5NH4,JFL#i%&X#'
+XJ#P%&a)%8B@J3T3K$a"8L#Q%&#*+Ld)m)C`363JQa"*##C'%3%)F)G53!%E))L3
+43J#aJp""X#"`%%0)#331iJCKJcJ#k"!fL"S%$@)')B1)3F!JAK!ZL"B%#f)&SB*
+)36!K8C!!$NJ6K!"#K$!#@8%)3@#"6#!X))!JI#$!),"!#K%m)'`)(!JE#"S38`3
+-K!X%#dJ"!JA#"))%3JeL"!)#iJ0%'B)&XB*33D3JD"!`L"3%#Z)%JB1-3C`J6"!
+P#",%#%)%%B)!3A`J2*!!'JJ1a!C#!p'$c%"L)#q3!"D%084Ma'*%BK@@MDL-8!b
+*4(K"I!BI%@)4(e&Q%$%3"5"'#,&!,L)+!MQLGfAk")%#`4b4(B%CdSLJM'L-k)C
+`$%''r#0m)m*!cK%E)(f)64!b"(+%@84@L#d#,-)Z`Ld#,!3834,d4YK&q%)B4@"
+&@)9i)k3L,##1)2!Jp%(q%8B4Va!e)*H)S!KcL$53!$l%Cm4+4%V),D)NBLHN'P%
+5-4)4$RCSfile$83SV3K[L)Q)$BL-L)Z!MK4ma!4%3m4$4%+%-N4'4#0)9B3P-3!P8!M&S
+i3TTUih8bBQ)YApHdZMCHZlCeHcD4h@pYkQMG9pZd1j0*bf4FBVZmYUAfYHEVNPD
+LV5fGj0f4Dph@dYU@bQ(-YZChmTEKX5a4YZG5L@`5Pqfl@eT5f@fYDE%PNqRfpN4
+(-kDG#GFThC&,Yk8`YLI),#R*Y#B6EGZbU4fYiZbkjIGR8[*ZEXfQNRNRGLUElH"
+0(4`2eq,%00C-QK+eY+86HGF0flEf4(lRYKeYZe-dJ(K*A40YC0Lq2CI2YREX`*4
+UGelE@RCh*-QM[6@AG&,052b,@R)iC@3DFT[E'8@MNfj'NXQhL1(a1@NNH@HG(XJ
+P%afij9ThG#6D-,KT1`BR6E(PdfdQ(TEG*Y$qA+TMMaMbVHe8c$beYXQ1I*[DC,$
+4,IRZMYCF[VPJh1HDLU&hjh-G#C22-JmBkJ34,,PV9lH$"B`M@5XSEVUMpST8@mC
+Uf1b-*aP2-6BQT+aYaVSKGBdPlq@jGQY,I2fU9Ai1M5Y,jQ80qf[,16GX,6KB(X9
+Aqc+aENbf98*f1PP0UpG[fL,P01r,fp,E%fedUc%hT$TfHmC'1M59GFfE@cZDdh[
+a,UCdmG*(e'@bZdUjip0@cPaFr(l"h0#iZ@4f1dD0fM&BLef"H9NQNhaP)EG+N8d
+R5"`r"0A)TI+lfM0e&%G(&8D11fJ&Yh-(VH#,lU!92-dGY)+$ZB0@m#jhd!Sqj3j
+D`B[F35[iN5[98!ehd!V1VB0@KP[VS*AKccTSCI3'(E3bHS%1@KNY3!HY$-rA35[
+$RAA3b["R(E3bI&J(V5`'8(63b[T&J3rEj+b$9MBq1QKP`eeed-U'UqUJP8dIk+#
+9$Hr835ZE2Y""+a[ZU)0@0Ta2"keXDUq$9MBDJ`jDf@J+1QKPSahSS*@02U1$9MD
+kL`jDfHJT1QKPSk2SS*@00U+$9MEkK`jDfI5($PVCD!XkD'@M'HLJPFe!J`jDfI5
+($PV&`!99bf,dT!jDaHJ6(E5+NEm1@XAJl6TS&B0rkk"9$'c33DXB2&N(V@*`C"f
+dLX'(GG!U"MESS&8-(8S(V@*S6MTS&8-ldN'V',AA3DXBfSS1@X@SX3jDa4K+d%'
+V''+`$PV9J(FkD&8$MZLJP4Pkdd'V'ZUSJeCQk%d(V@V3"A63USCHed%V-`#RJeB
+eD%3kD&@$hUD$9MASC6TS9B2@TB0@0HK@1QKP"Z0k"eQM2JkeTVISAc#&AUF[A'd
+*EZ,V5q!,h-,ASZ!1i$Hi"%H!'i"c[Ti%rS2lp#Yi"FE6ar3iH%(rJIqq9UEpE(S
+C,+12kAm`#1bRPm%T9d-$bhcG#j`$1qKKF,fU6B("[LlQDQ*J'aJ1GS20i#qi$"k
+$`iU9%3#(['4dZM#8DiMHfMGHrhe4UXl5-C+)YV0+)+'-#Z[HH2e2[RRJ`+H8VdD
+d(AJCA-bm"3pNaL#Q3hH&8jl`Mf`lih5KKDljF@p(*63ZcUU,QZRG'LEhd84C69&
+D6h(mh,hU`MR&98)6Y,cG`fLFRQ%dFrTAC!M#6Pf6f*23I6aeel6UB(IKA,@kXAE
+0mL[4%56ZK)C8GNHUG[h`&U,KQTYe)44K62hDblFNVfjYEXbQGfeZ%TQj"1Je-He
+VeXEia606GG%6TA-&j+l&6ch(LF,,Uh+j,Ipq)J$@6Ihpr,NIJ!#c&1I)Z5FrGJi
+j)"*eN!"G0%MIMT'&AceM,i8628#%IYH0aDbl#C0"d`hVeqZZ$qI8A,jKNbi,XH`
+TRH0R)S'Z@VefTF#"VHqB[Q[d28EIBr8p6YrMpAf#[LISHk+q*qPlXVj2e2F8I8r
+9pc4pRk6[kEbPN!!ce$j6hl2d29[IFr3p9pmRkhZH[Nr4phapRkV["qMl0(hAk[Y
+dICqKl`AkAUM[-r9pPViA&GXU0VNdaPGSNV2eIBkqcpAhBRfITqrcLmR8R0#4fQZ
+QSm6SGPfG[Lr3pa*pAkK[(3BC@&H'&(#2Q&m9mK(`+i+p2p!D$U#k3VXVXM-`J"L
+2f1i,l3`Pk)",9-)jfP[X%V1GIT+(,&TFYN`'qA4!*TVY'+ilaSSYDdMPXqQpUHc
+9ZGUQ[!bE*V,0,VGb4MZMcN$#E+i60B9499NKU!4`Q@iBAFC+`DC-+YRDdKTeaKC
+X*XhX!4`3G@#2['Aff2@),X1"Q`8(Z[P!BHP`C*TQB+m8(+LaDYJYUkYPelCfA*h
+5jB"(cj6b%J)CXUJN'ZNQ3MR(A4IKRI['6D*Z6J6%$!TY(!N`5a0*FQ3kChVhYTE
+YrRa1C-9dMX`04!"N'"0@k5jfL35Seq(YjfCpKb%CC[6"[(XQMb)$-[PGk6UY"eI
+-L`X+,5Y9C-M3'L2h@,RCq6aHlK2NRL$h4,NRb6eClK2PRL,h9,QRbAf5h02PRLR
+h,,PRbce(lVPbRbch2,P2NAZqh+I+r3#j6j1l9Zl6j6j$lJ9b,j6l6,R2NRZ4h'I
+,IBlFjmUp@1lcj$jIlMUj,j!!HiRF&jVKNjKXqA'AfNHqR*Q,iZ[V9bkUA95rI10
+bH6DZMQr896a4+FF9P'511`T!8(,hE*914*fJT#Zd)Re1a*@J&$dKbd3c(+-Z4!P
+)1,qAHCb*Eef'&l8c`qaY+&Lf3JC4C5PXd@0PFfXql6ZX5RINLqD'eBe0YI&dFqV
+b9%I&c9%AC'9Q4kUYiX['$pN-klYPiir+C"j6Hp$PB(lUZ6Q4lC!!jDXjhc@aSc9
+C'dpNDXe5%`RHRT(0XRi0#b&8!+Qk$PDS8Y$9'fVACf3eDqXeT96BUe,0)Kl[bN"
+fQ'i3Z1bZe,kP&aqX2PjGPF1T1e[eU&fj,jp0q'd5hjh,TpYV(j(D[cHGEIBpPbH
+6+HQE4YQBklZYf0hDeYbG"c*5I@Z1p6(Yfm[&+bT-CDIZ-MNl9JmfJ10iX-hMUaV
+-5YC#TCh0V!Gc8-q$54L5dY9HH2@9Y$L&9AD5CE!9MqjH01YeZjTI0Zp@UpD8hTe
+0TTS5,5P**GA5f8,G9GZBN!$&22RDTP3qheRP9C*CE8-LNc&q,L)BVl@bD,L%ILL
+$cSUI5TN-R-RHRibXrZRdZV+KY!'i'eYmjc+mq*jG&I5Gbd8XZCD4bIFXG8V&XGc
+L&@qhbbYqAPZA#Yi*Apfq"I!Tq5U)q6jP0Z&lPMU`bl'R-$hYHE$,IIFZ)$hSh&[
+1%Ta@(!IEc3I9LTr"e5kRDUR,k1TlPJ(@pkc`,Yqh4,dUMY9bq35XF`Gf&b*@r%Z
+J@('Zi',&[`b0&Hm51PDFIB#XqTDDYKT!'k(U1Y!,CE$XGIF!TX[GJFb+@`Ne+mi
+qF2EipTI+KFq+AcH#9L*83,62Ik$-2T4@I3meCK&3UkjJDSpIAaH8N!#eiP`#eiT
+c*lj@h(f)VIVfeE#NG(3ZfHVQRT8!CIjCmHlLS*8!R6bdiPlQSKA[%KqY1TG*8M@
+#bcbU[S00dFP2Hrd,T+l,AhPUaDr-95[H*ElDica3-)qh9K`2FYG+L#lqfKGJX0`
+P(PYe(Qj6Rmp@I3fRlA(XEiFbYkeiPrPYaE[#F5[q*CjEGHi[C4m-kdKB!-4ZL(i
+SG[f(`0J0-3$(ES"q3(Epqb$CGqr[GMp'Gj2ihN'E$%"c18)9VE`)AI$XH[B$Y1[
+I"p%Ppk(L(B4Ter838,Y"KU#k-d43rMkipYh$&Zk&E0ql%l4,VS-0dJrFVRmrG,[
+qJq$Y4ZL$EpppX,#$%$i#h`&dMm$f)FJ1i(S)UN1B(S6S)AJHKZCK@1k&j!#1Kk!
+iJ1%q#"k&ha(S(B(G)FJ0iAB3D[YJGJKL!hJ0S(8B9SFJG4"1qk&d4*)+"+N41HU
+3!"J95&&$3P3S3`f+8%-5e,!!05`rpBT2JI3d*$`&XP1Ik$3U1Bd)6L0bdj!!f"4
++6B0#8jr-0#3b"4*6)$!0bdY$iY+JY&34PL+5Ml1Ef-a)bl$d1"Ci4-,Y*KiEJEH
+E'-%R-QdhXGR$%9fhQpKKK+fTk,69a!iI-2T!40b1DVBU*DVr$K-eFp`rUH'H@P6
+@Q$Z4rpZ5RcqV[m@kr[1eeK2[@$L6IcfG(pYMcGRCh-D["plDY(($!ZQecc5XA,I
+*rG-ATrpLcrqCqi0RGm5Hrk[5TVhBm`ki2`85FA"kDaTGFS`Z0[L["P%qrq`3+EH
+SPXA,mQ6K-NIrYlY`D[Ml@5F1)9M+(-Ba[m&e1!iE!eRZ(-CKBSB&d'%F0Jqb*$U
+-!ipQNA3BK`f',*X1il$PN!#&e'%F0L'bY$U-`lC%&PZ(FGLSb2,V-!jE&eQ3!"h
+'B6-M5l6$1'a[C0&f')F0Mc-1af%,*%Zl`cKXLQ5aGaL(6C)XrJlMX'f5jH"K($C
+5XN!mM-2@5TD-Kh(BE-NLmM!1fbpC9Kl'B8-Q#mh$1'c4C1Pj')G0Qba'$q1`MC2
+Pk@%F0RDbB$f-`eC2PV#(F9"H@03HaQ%l+-[F`cKX%'AKHaL(,D-XK3rMX)Q8aI&
+K(,D9XP`qM-0'8aE3Kh'JV5bT$q1`'C9&pQ%FmjZ&Kq1`BC@&q'%FYV#b0$q-`kC
+@&ZZ(FGMQb[,p-!iEAbrYMq-Hm@FVl'@(ik!#,MmFKqfb+`l(iBqJiSIMm,Z0km-
+irb!pR(mN%#E"12b5qFD9@cE@EHrr*8rRP2jaZqqB2(EQfrQ&q$mIjNC-(VZ'-8h
+q%hX8p8`H)lrH`MpjK`FU%FB)km%[@9c9QY'rBrjEAC[65IkL13+Jll1jl(hr`cf
+5"kFZbCp!r+fZ*Sm4BRY[(T%Q[h"NeNJ0MZcClZL$rX&brmLH(bFBfI2M"#0lITa
+JC-q2%icXqA'#N6dr6M#bjmF*4[Em1-()RKmR'0Rci`3MHhkFB'62Ma1-l2PaJT%
+p2di`XZI(#8Efr$M"b*iIKap!iAqG`MM"D*mI*aMYmq-%SheqR'#dcim6M2EjFB,
+42Mp1-0VRa`P'qr`i`@LI(bFBlI2M"+0pITaJY-q2%icfqA'#d6ir6M$DjmF*4[[
+m1-&SRamR'1hci`5MIAkFB,62Ma1-p[PaJY%q2di`fZI(#8Elr$M"D*mI*aMYmq2
+F1pSRA[H1pSRA[D0piRA[D*pih6[D&q&rBYD8dGq@R'Gq!r[i3H&GRXRm4G6hmQK
+S@-XrrKmkXZQZGR8l)aj8YMG'3q2D85AphM`faqZM!HUkS@P$AiDrcm1Ga%MQFMq
+el&mh@p-qdZ`&'$[Ef+U6'2B0kme38Zc(Yj1'NmH)YLp+ZV-8IU!lh$`@`r!M!I)
+B,XM[mKLHI2YrHB56"[IPNGVRj1%5I2Zbkfjarh+aaRkLYG#qBFeYP[fMqCGGpj+
+*pR@aci[p*fimq`B[Mq%"R0&kH*-c)i1"NSHZbamXV*1(r00!4%!Hb819$HYkA6'
+2!)Q1jT'ek-1Q'ppVqR(VdJrC'kFHm*!!G#X63IBkHpeEfZb'@jE3T1,r'iPcUlA
+4rZJCCPc)j*'cGJBil@clY`a3HpPei[5@q2T4(N1-950-*RTL)LLhXfhdGrAPh`P
+'q9NZ[cXL)!p1R66*AqV+C1ISIae'Ic"ZU@a[M$m`lX%m)J-BprS9DqkHb@[F2&U
+2L!rQ2P$92c$hd6b1-2I42)i`pl[cZ)qjKhNBj[lcQq3@c+jjKB`*1-cGr+#p`p`
+IqI3LFfm5Zq(V6ZGkHIb@ZII9idr-IE#`[fIZB4j(Q(YI'RpNlQ%HRFcpdPRh-IG
+,CeDBHfU(0B66$!@E(aATBHjh'Tb1r'$F&bqpZMI'(aMh3"kFL!$',6mrmX#,DSY
+r-Y*j6VbI-@eCHR&rM2XCdfJH4jM1hARFah6#2$*@1YPfmh1Xf$[1YQCYIk1iEE2
+hLRh@[*[&GRf"%8LMLF1UpB*iHfrqS2(IpGTA&r)3CK%4N!$(%@E49pFr-SX`Ma%
+3PMc-6lJ%-C`m8MPVmH)"CN%5UCb#TpL"XiS#i#(R8"iqKF0FcZ21alPE51VDL[p
+EI2!8&4ZRBIZ42,fpm`GNbfIppPfMH8`bP'VSGfLR'1eX`cP6l"[@$9Eqi2%VlfP
+RN3"ja0YNSi'cf'!J$hFI3D$b'XdV%U!H4UZ+"-M$eDU#2)jU9@EIab!MN!!TjUH
+GGB8bJ*PEAe&Q"1pK*V5ilf1`([IdQ@S%VCQKIN8M'16f6KjQh`H,+)lh[G%))J(
+ke@J%N3"j'#4hpR6mYDiQ$rCd(1q2#3dMrpXq2Ejf8j13!+&8bl(+XeE$U1#3!+U
+K2+VUG4H5Si*(!Z4Ke'YTaGa3(KAeZXS99IXBcU06A4[-3jKd4%!H3PdM![*Sbaf
+UKka4+IppDMN2MpZ,&K-98!r4BU)"mK!i#r))mDb3!)GS"-Ibm&6RR9EZ,rMUe50
+M)FB%r9&5R3Ik!idT)L!2dCL1p@ZRaK3&N!"(2QIp[FmQ&ArkYLIJ4'8%GpNr[[(
+E9ZbY@kaCGel[HFpqbPY,&5-EXI1`Ira--dm6Zf3Z[,h!##)#mK"'%"'3!)FJH94
+!(TQ)J,VZY$+CBhN8jMi%UBlPdBP8Imf$8jFBaSq9rN5LjP,)BrXGAKlT+)!m*K9
+r$Dd(mFBEeE$K-kq[HGQfbi`+0Ir"$r+mjhppi2r'**iTe*L9@r+HDKJ*N!#(8HN
+L!I*`9ESJMkT+9mKM0@XYA9AX8$fU@r!UH4J9+K+JVQC5jAJH[+GZf*R)j0,0qr[
+jd&`('@jrH&3!-N3"j1'T8%0j9,F@9$V48k(qRJHkG#4!A4h%L`,)`d8m)6&(%Br
+5pL"H8LCHKZT4R4E[c8-B984!(X+")`,b%!iF&C!!4bBLS+l-8"j(FSp,(kY(L8X
+Ibk165dF"j*%eUYJKjL9V!Ja3(qUch(!HZQhJ8"jQfi#-1J9j9,F092)`F`ddrR'
+m0i`b%L!2`bLGKKhXMi0E!LTe0E12N3"jF)`kHkbZ6(#Y5hIdDKlZX4XD'NIffpj
+pc(c%b&S$kj6SYld'`6Qk'cTLDDr"hdl%dPk$61E3,S'`VN@YiG#jCpHjYarKq)N
+!fBr3"b"rh)m`J044!IX4`[%)RBq)"1LJk!$Q(P("6#-"N!!c@J'TlMRKFXJ)%%d
+R`Q8lC(!L#,5Bk+$YN!$(6X65GXLM@Na[)P%%@Xa`$*hl1(5LYlC-KLZ[V'Rh-lL
+Kc6lh-lM42)i`Z0%mMM#iZr1iMm'&HIb@HIAPm5IQ09L3!0mcVc#2)mbV,idr-Ur
+42(l,[(S6L5MBj69d+VZmqNmd!#-`H84+l2)+9hPC*d92D)[ap6F0E5VdN!"Kp0p
+Lc%k`5)!meZc+YY6*rCHk`L`L6M6+D-Kr#IU(bI!r'mEFYI8*-SPlQJcZ@ZfjI"%
+"aYbe@9lM(Q0CNr%X!Y@BZlE)eTiC(a8,RKf9R'TH+SqcaE29MhQPc!l2F@0+RM8
+rp#SJQiP2`I-k*mq#jjDjPP8V1'$M+AQkRRV1PRYb*L[lTUEGqQDaZAmSB&R-)bp
+a2"mp4fba!L$)[FEaA2)0LZ9j[PlZ%ac2Lcp$qTlRf`&)ar2"+m8feR@d*mVMBXG
+crjYS&mm6%+Yc2+qG,EEaRLIpSRQqCbBfch02`E2Pkf+Ei(NqLASiRX[ALBfm(Fq
+R&$cIqN+a6I)mRbk2'ah2P9qL8ec2Q"!(qjQ1jbAI%SF6AFqaTmTMRZ0j)eJ!a6"
+Rh'Tjc(3mEB"XPZXjrF1568clKL%Yk8VTGQ%"mB9LRGZHci%GfT[5dmqaV1F,JCT
+m3R[HF&r2mbVTK*S2LHQfpRaEZY62q$p6(P-N*UMLaG`U(A3kf,'N2EqMM"fbMIA
+-RdZecf[2j#4QdI24dTULk0LrEPbEbe[6fUQkfG4Sr&pF3+p#c#X&mGEq5')q5#S
+!GRX9f#!B21D@BU89D`3rC9[N%pj@V,6RZ98%P5@,LYQiRJZq*6,2Q+m@+qh&[2+
+edP%2%p1(Y6X+Q%BA#NjVjpDIqJbaQ9fdR&f#lC-[-jla2C[%i9pGce@##,&Qar0
+5UBEeEklRc9,6q%l(mdA-r,r'kiiIH(J6ra@bN!"84F(i$(V!mIcZR@*lR9HE[5#
+@irNcYL5"Y%l-C96DmG`26Vr"mla#(KpekRR4Xm8Q[H5FFkE)BkN6mbD`%0ae2''
+-$Kq)[ffEf1!%jP`KpE5rjRMH$SkmaBZjS4$c&qm4QpRFC$`Ikb&ir&U`9$VC1AX
+NYc%1KiLrJ$qGJ"miq%N0RHkSA`!lHBHAM@aKYlBlRX[SlhHkRS[I9DMRZbi5'hB
+RjPeJXq2j[(m4flXpcepjD"brjFGLSh,QR$Zed'[ASCbmer8mMhlmX&1"'RM(qec
+20@ZN1fBl-4ZH*3l[Gch2IcaC1jk[HkMB2Z"9l@FH`iVrXm5h2ZKkAL2i%Y11qKC
++(0MS91"dH5ad2,ra'l(GkRR#UV4Uc9[%"JX`ja&`MHFkRMqJ!X)fR,2LP4k6LjX
+YFKra-%T`fXA#HI2!%GIc`UG+QNk[e9mU0ZYMVZFPdN'+KI82T2khZClIqdS"#jm
+%@RcFkhCiS',KEA#G6hLH$r'`X(iP+24*ca01je5k[RDTf$lPHFVQ@"F,hrNraIC
+Tca0XGl!`rJA3$REU)1Z62HbSEi6*hHlaY38&A2Zr+&phZ*i2&ckJ@&Kr&5cZXel
+-#`SaVbIQjca81EQ!K@m'p6r[HYiN(-A&`TDALm-A[+V0+(6(8q%GAr5bZGc$`RL
++[S'G1Tj`%mA#&"cRbejY,LPJiD[TI1P+MING$`[V,`)G3&HR1d"5lE@PF2#[H6(
+rMiH&m64L(Rc&R%Yrk@&KrCAJ#$cFR18JUf,KFd%me!-([HKFaF,pF*e[ZTi!X)Z
+&Yp$Yp+J6mpS#&MiG$H,ERLGGT&9VqPpLSlj1"8!HaF)XUYCh25am9!%,hrN#3-Z
+brMm!$3d28N9"4%e&,R"bEfTPBh4cE#!Q)&0S6'PL!*!(1mB!N!m"U18!!G(0!*!
+$&[q3"&4&@&4"6%C"!3#[f%,pX)6`$!!!!CS!!!YU!*!$T3!!")%fNF*0!*!'CE%
+4!!JFe"b#'($`eCIG05NKdCrNL`SqJ+E)6!pi)*68-j63U8d#!UAH950UIVlBrG4
+l@Vd0N!"hJ02kPZrDRLEK1C`6`#03`H[RM+4`Z1Aj6J#9Vp$lmDqrI9S&L0dfabQ
+YLkVT6TB$UN%jcd32RXA[h(jUIS$FZfBMU@,Z+AP6r-hpHPDq`P'SFer%hk09+dH
+6r)&J9iIlBUE1Z4*qLY(F-IHFNQB"#djAmJ!%'F#FF(+EE8U1KSmI'A$###-66PX
+*Tq3S2qAd#&rMK&eN`JR!#V!#V+Idm1I&!3Edq%V3a`Nk1%%k8&hIGFDTK*2M*q'
+%45DF(#I(bA%bi8H3!-!T@F-,p(CpTH@be9ARhE9@-G"c)F5C$G%R&BfcJ9E1Nh*
+YCaTMeh5PQ[`LeTV1TDU%1$8q4()VNNec6"ZAU*8E@KQl*"0*bf!dj"aG*mJXhCe
+YR&`1qXC'&fTaUhf!@AE"$f&bHR9$`5@[0%Q[DR1V+k+c5%TD@QK%N!$J6mDA3Na
+@XAXjRH+r+L6Eb%@S%0Hd5iYTK)p@ULN5AA%bRKVREMK''@(8"15K8UYYc,R9mPB
+63&M)4E0"R"jSE#MC+,eH#Ji'KPj8(ih")))%90*UT6P4q1Na3Ml0%V%MdQal6,S
+5hm$SR@&8%,E#ik#2i68iXTTGZ$dMb-Ci26L1AQIEST8hH*6`NN@8@fU#Ha#B%GT
+dB1LcYeHJX`326rCCT"[VlUM'EhB*D@#3!2-*ZPR4mbfLi+6i&f0bp-KS534p!FU
+I"@U6UR[Bi9TFe6S`Z5@IN3V63*(VBiE%hNM[$EjGHNFIJfjSEXKBe55NbE*#,P!
+kFF0a,C*T!$c06XmrHI(&I4JSL`qb1!b2,DDrlpJ`#i--5jPH9-%!*YU$@bNr`R0
+iB+l,ib%+TV53!0NeNR((CrCK22YFSKm$@pXlUbV%2h-f!Yb!GJ)rA*RRmpI9Mf#
+&V3(8R#Cir3NUb0"VXr$5'i#5q855cV06r!VSlrr#TPfi*P!+h'TXiF21bh8VUG@
+UPYD%&R&bj`cY8N$+C58QNdPfXH)+,l%6bQkYi4AX[K`&j"&A@"mNA9l1%#@Ej5q
+2%Cjm16qM'Id[Zm[Uml1,Vpp5-m4DMDi@$kiBkq,U%I#rA%dQ!Qj'J$*aQEHKJ"6
+!"1p!UdqCZiLjlPI(&VlU`0V2G%`BMDj62a6Kc@!B2faT(Q8d+Q05NYS88552N!"
+r&f8+(N49F6U[)BXipU+KjT&bF,SX6Yq,2MR94`c$S-Pr@ee*TbGAJh+[LZSJG$j
+,kUCKlVD5!hTpjGf#,TI`Iq%ll#BICI8$H1qjQjZfDiVm8l`lqJ*E'pN,GDrEbci
+*Ef(D#B1rXMlZ6Em$DLFm-2KE9'(,r%jii"!2YMMmJQ+@,5e)iYA&bEIh1$kb+1Q
+99$GVcb2kqBA&f2dA[j%LZ2dE*"$i!0+Jr`G,J""D82b(#JM,$Rk$mUD,"bckLZV
+Vk)5PjPN+)`alM[[UQ"I$B4S3AdMDC)d#aKKLGbE@CEIX6&c-6eLQFaEEX-rN9lc
+bj0VRa4#9R-[ZfPI`1eRQCj!!lFIcRmUPri[bSI2j5N5c0aM[jHM$KjNmPS11UD1
+PlM3fYP8mC'AVqRAD*pe[6E&A`E@!YaJ-81U1F@()m`ac,8UVF#8ajCEKS$P!1MD
+Fk#(',39AQA`HZCISMH0e2rDmrLlKX$,%bIlchKFj3a`0Z!`LrErF)iCa[3GN@`Y
+('2fIQjE1l,U@VEJfE39*I2T8fc@ITIJNp4m!N!-0%&4ME'&`F'aPFf0bDA"d,VN
+J*L"6D%aTBJ#3"`Gm!*!2!F`h!!(TaJ#3!aErN!4069"b3eG*43%!VpP[Pl#%ldN
+!N!EYrJ#3"KH*!*!$DJ#3"T1b$Z[RpGR%Dl+`cXfZGAXjmPGqpJXrSpZ,EGV+*Pl
++UCaqClR2@#YENrh+EThXpGZH,FHAiiZaC5*K1hk4ECe2GPlfjN8@[KMEK*-G@6a
+bLjIQ)YQphj(&b('bm'AL'GQ56IDjX*EMC,'"f6'J!cMaecIT(16CfHFeb(fakmN
+Yj"Bl4YM#!0J#3!$1L9pH1*Q-14`1&qjV()jRrXAKq*VAiDMk'pMh12(S2TE,C4+
+6jl@ibm5f&EGEE2IKpSMYREM,aIC4h"9Lqa,Z5V&p!rFd5C2j9)RYeAK-&pXU2'D
+)E4-H-mAfCMaQL@dr(V2&pK%mUXAfD6aUa2B921D)l4!HFlA0Y352H@+l$BrjBVX
+EM`9Lbq$a3f*l'ai,aIBK2#i4ffI`Z&4XIih()QdV)hjH*EE,m9JXYR9i-(IDGJQ
+qD2Xj2)"(CIX02)J&fSJEaUIYlr#i3Y[Fa-0Va(B$(PH+V3@2Um5@`10UX6fXFDp
+X[ih(Y@,l8cbZ%pYcH#c90JmaXdaXYq#aA'c%[8pX$q"a[GJqJ!IV30ZRm&JKYUI
+aZ&&Xhm(M*QdV*djZ&Y[YH2b`f%*i-&rDIK+2@m9'I+m8farM3Fc54Nc8DPX&HB%
+F44YcBekdYH*aKpJkm(LGf0k$"hQ'YYr$ir9Lq`XmkX6fEhLXeVC+iYN[0ZD`4Qa
+[`'1Yf0k+"c&1fiIa@#qf,q#a3@bX@Eff65-I0BL0f0JSYL!HM@)Mj`A%4Rkp8f`
+Iak0*E%rK`CLdr4-HGfPE&6QV@@c%$rQ"YMBmL![DL!Pb,'h[aQ1cf*JIip$fC6b
+fL1dIm5"2NUl*Qq3%fXJ,a!*YV0FEaEB(Mh[%4KjpNpKq$BpYB[Xm([H+lCYiN!!
+(+!'S!ED,M6`9&K[cDaIEEM`LBYZ(a`kar3SH1m9'RLEIdNC0%"8YBUBja!Re((8
+Fp4Ye'r8-p4je'r@Dk$5P"iP4kK(b,r8BG4Me&c8%qBdkLca"A88p48kLIU+Z*)q
+6[mREPJiJ6j'[bE(NCh)jG3$jQEa-2LB2Nhr*Zq4EmLcjPEa+2L@2NMr*%p36j$h
+b(AQ1r%EH*#q5hmKVj$2b+RQ6I%BH)hq4YmKAj#Rb%hQ*I%3H)[q3!(I)0q3CmLr
+e((8Fp4Ye'h81p4je'r8DG4Ve)[8JG4Ve'A8Cp4MjMIU,ZSYkLha+I89G46e&(8@
+0),V5B($)M3m"eLq)T1lRbYC`,*4+a5+CF$UDbMV@4G1CV,FPXM-H5@3GY5&IXL2
+VD)aZppE(8mPdeR[,bSf13,#YB&iGLX@5bB4h3b5@FJ6D[2lVr8ZAkN"YhQ!S%`l
+&P,8jmS!MZ(CG)A4Y)*,H'I%f)FHZ1V6X3XlG2[jeJ9Y@lZPf#JEpMQ`i&JL&%6!
+G5ZreKFAHe&,AD8XlkKLf4B9PG[@*E#5p)a51d"J)C9A+JCC'Eh0()KZ04j!!QQp
+0Bk0b8I832emq(SVSA4HkjZESYTAYefT(4!Zd55JiU+S"#Ye*D$F9-BmZ9Y0'N!!
+B"8'diUl,a"eEr%hVE"JT[abUD!C#0"LLNBc[%ij8+[`K!BHM&Vl,@GJB%JHDZKc
+KS"`C%AB03RUZp0h!S*PG-8EGf1XXe96qfN2Ea$eRl%*Z[emK&d'CGZN'fY(-lEa
+3bAJbQqaMN9c!bB,daI+f*$[5iBLMC@mQ'iPlEEJaM%C'S'dEE(R+f4!*Y8I5[P4
+Bj+XjiP!48X%G9L28K&iR!eKG3DZE5(9SG41TJ+aZ)T@4e8fN`V(L8ZPCh83U0UZ
+E5'9QG41TrU@Ek'$(5lU*MJIc+[9R4DAb[%r8+Xr(4,AbI&EU`m0ZKh36(AmVDTE
+R@k*UHGM0NQkLNh@4EU+618Jhd8N&+0e%*a@XG"1G9)V56A4518ShdFRZNA36RHm
+3p8MEqh-iFciQf+(YF9'AY$dTkT-feNqkLFjR4)h5GP"8+@hXE%NhdFAk56I4a6T
++0p(&Z0*0G&'"5MI44@8Zh83A&E0d%ee8bp*0G"'AdNedXDl56A6p%Kl56A4p!Jr
+T*VVBeC0ZSSYG3qNQZPJrk5Dk[SZ(G"2,L$hT*TDa&Y*0,'0YT*YB4Xk3!'jL'9@
+qG"-0#iGi)iE)Hq3QBSki)QD)*f+0059@L"eb$IQ2R%QZ)8H5(iJ0eTam3Lb4,mN
+R9RH&I%+Z*(m3cq31eTlF5)iJ(a$Mj"&b*r&#h&LG"SYlbC2%(MQ5Z#1(NPF+h4h
+L5cKSiNMRTL`V&(m8Jmc6kb*-UPRc(fHhr[#,+"T@(TDhUH(NXLIqL(9,Sa#A9Y@
+)C`+"',GdLhQJ$00acm3p#rGX)JVh$0b9Z#Y`9q&f1j`S#@kqG'!A2FV+q(+2BG"
+5CIQMNXMP9)'AZT6R0-Pa"VSU@Y&QI&1#eP+)1VFFYT(rl)E3@d,q@#L63E[LJ@L
+U*r6@qU#hS@ic1iB@p[+PmV$),(Had%H,h&9DJ0bMqedr1+Y`kS*"0#bG$fe"kqh
+#B6kfFC2c%HFdeipdel%R5i",9jAFj!4Bb%f+X+e@TUh+V9kQl8!*Sf5IjD#kQZ3
+KMiBXHC!!r'laA4mA@YeQmUDPeFd"Kpq-AUSR3PC*qH`ZVBkJZFcTZ(5`9m0H@Mq
+A+3,6+4@iV-"-MR*KPKbrp"+VCFi6Up1aH,!BdNGmX4KRL,@cG%#-VP`2CkZkj5a
+P,UPQ2ZeCZ5S$GjZ#pEj81V)MH[mJRZ9PSd2J3MjC)6@"4d%mX+0Y"bF2,,8D6X8
+iK(Y0,Kq6Jl3dj*p+KrZ5i8m,a`r#0jk1GZ`FDd6SNeG@e,5jlcdrb&Ue8e3RDdh
+MqLhK2G(fB$UjZkd&fVcm#30!AEGYbf4$kIrYq&`i&+@U@AVm[0`Y-aiJm,r9rTQ
+Ukck59hAiDR#lFAY`6mGGKEXFG`AZ5YbcF&IMRXeB1HYJNm4ZPNPRPjiZ0,R4f*!
+!cmJ'Yb0p1CF*MJHJ"p$VR+kqNAU9RSSQpN65Cr1BfrI"Y604ma[6J'8mGbB6-J(
+KD)a!)2J5pI3HIX"R'`(r9SHCV%CrC$Prq0@HAaR-!(RiQrCc!XAS`ApT&RBdKMq
+@i83B!d!H$E[61hbicp@9Rr!#EAkC3()H(mdYc32r9FlQdETf5kY[HqP69qHIrm'
+MmYL9MCm$2r'KmYKG3Z-8AP8HBpc*'3AMKaff#ra""YiD6FQ%QI0eE8q'1IR&!)$
+lG#BY8eR1jm(MJpJGBGQTZUSmMR3iAmT$#hF1%"L81i[-%dSR%'L8@8A$ThXQad$
+PJid6$(-m$f1!3QPDhA#-1EZ'Lr3I3iA5'H21cX%SShNXPGrf&r)S&H4d(U-%r2d
+maTRm4"k4qdX&Q6aDQCl(Uke-akV4031R@)p8D,3VF6U2dS#4mEVbfk59a`J6RFi
+M0DT1aqYUjf%%81iUMda%CSRpcc&2+1kTRelGNjIk6bEEB3M)JmF(N!#FUbY(Uq4
+ElJ0"+X`6bYe3S8b0!-aT9Q#UUD1C!4rdc58pRD1c"elUk3cRB6ET1TrUa3bKif`
+[CL+2NlfBL6a1pQ+1jA'L&c1HKhQK&c0BMeGk-F1&2G1,'FrMC#pQ-)fAHc%6HCc
+Ua3`NBL,SaC4Lb,c$dF0KL11jpJj-2(+-(cfG)5)kfp-T-ViTS+GM$"QcC!qGX51
+B!-TJJ$N'L'N-HJD!XrZ[l[IQEZKM6pm`$8a0+-eP-S0-``#VMQZ$![F,,q-chCE
+I0b%`3eiPp'N%$TrL&!Re2V$[H8b`R[PX6a+G%kT-ENG0@bp3ZC+60aeBq1jl$ah
+k-fXbVCRYF0UR24G(XF+b!rX1AR[Sd'1RTq@Bb!lR'(9TKD@D&6iTNkZ0E+HXHZ)
+691R8(0kNS1XBi#E5U1R5Q&jZ6djeGID[E%8#I`kcA6JCKa1%,jQ-`bQrQ#)ZITa
+M2&!I6KPH2TN2TaEl"LI+rN3q$LI0cCh-Ke291C&EmKRSrX1IdpBR*Xr#Ra2CEjf
+-`kp1R!)q'XFJI-TGr-X"R9fIL'DMS9MdJFLkG%M[4R,Ur0qI#TerDb3GMbC#f9I
+59hm5A'S#YKXI*6"Qh"JhfG*C@lXcNSLNSf&M'b%S(LJcb%diGGAUIR*,4iSrJ@Y
+PZ`Z6'MXi$i%(U!F#N@`kH9mN[5IMEFQ'%ZfKG,YXZ,1hPRX-qI8V'BmR%lA"MZf
+aD0KER`M(1YSMCM#k8(V!r5)23$8Bb8M!iJ%2qd5eJ@3kXLk+Rd,H&EkEI6HCeMS
+'LJFUlIpQa8'UT61[Ijf[3U)'Z!RSDPZK`R&LhDAZIiSVI,*4P$RP'%"qS"$'eXC
+I4VF6D+PI@k1@VNY%XYkepkGLk#UF&C(eQ$M(X*Jm9pU6`'"fMZabCB3j*Sr"55j
+-K90$Yd``%p6QAHe[@V2fDZr9DqTDkr!-e[YEC9-lBp-aQ8hjZiK!k%GKrF)&JhZ
+%@XFmX)cALfGmC19raH9#K@TIZkkUerSl-YPNh,XaX[HqC,TGE8*DF+m,Kb1C$1C
+,ChIeqVD'X1%"Yil0CU1*REhZr(Q'EiDT9*rckSjSV"hXR8eMCRHh,lmUqC2YNI@
+44*rVQQL'Dh6&YmG!qdImjCI6%8q1FSf%HjD@VG9$Z2%a0S@+p3E@hQfKG++[MV,
+IAlGAIE1h+B9pBI(YScFIYF%20[Y+p@j2Ued(Lk4m0`Gkh2+l0J#NL8LX*i"-"Mp
+DAA%r@Pj1+4Z%)Pe(S*JIF(E%%l1Vqpd'LUmRLJm8'&2,MeCAEHXdaR!k4T(QG)!
+5eqNB)i5R)a4C6`FBTVkFIa&dZ5$pb-Zj$q"-m$*#Ki83Jk3K)IU)8EX@f9%('+E
+)[2p)#3I)8[Z1-kD18U,0cKLM-"JQd*cr"+#(U$6RITK2mlj&T"5C93FSdU[q#MV
+'Va+N5,!5SF5`%Q5%BL9%N@-P`M$*jJ-83CQ2dSr+[2m!p#cJM""YCia"LV&Lp&'
+Yq"Dj9L)-NfdK`'JK"qK@R-Ij9X+8#,FV5!N1`j5E$h!-hN1NQrFrc,S&ja()&(P
+A)K5*&m((@*F4LT4,pa,I-X))fG+rb,4d(kCCblX)3LY%2`)Yj`'%+A5-8'XZ`##
+4U!"pT%V()U25ICK1EHrKXJd3+6h(@C3a5K5DMe!Xqc"j@YjMS"fL6F[j-'IDRN1
+i+,)Ph6ZT8V,`+[CUM'B-$cp@c*5R['qG"I2,Y)E1$kekqhLSLMABlb+"K6f0%lZ
+I'`q1qH9$+qLaDhjfepaTqc-T[$LI06GhHMJ1[lr2Qic$rihc*q0`([H#b6M(jh%
+M$ZGaAmGLUTL$FlEKaARF0dcQVEB9(jphM6LFRcdaCaYa1$plBXkffKeeFXifiR!
+1q)hMG65i(M*J@A068f["U@apmbDe#4"Ye5el-pP)A1B+4L2F#+PbAAhM@QSRHA[
+NA5l[#RQV10`p30k@[5UIS1Y5p#-NZleH$$(dYZb+B6dZYLEKVP*$b1Q58T@m,IX
+XH8r,Tq5FLC5D@ZUmQ@4(1QaRJ9UA5E6CmUk4GlAiikpS(b$Fa`'"+LP!i$h$f!!
+)q-f8pb3J%-99H&X!J9h"LS!31rEc9CP`crh1"G32Vk#ZpZh2a6Lc56!ci,lm24[
+R-cjhi9HlS4H3!$Q`#j!!%H0clhrLi[M'5aFp#K1mZYCdU,VSI9M6SIbLG@&0KfR
+iUX922dHrVKDqeTUR[LCcpE!9NhQEEVmFQi,143A#CdrccB`SimXa`L`p`4BHQjK
+US-@VF9p1Jc8#i`VFVbNiA)Rl+S5XXLCLU"%CK3K(aQLB8Q"ahIGJBCEMB+I$FfF
+b8@T41!1"i%XV6r8HI0&`U0QX)aY8eHJeAFiIlT!!AJH0E3E)`pqd[h04Ulk$hH&
+Cf0%BrPKQE12h%hNdl%l[m1%q9eF1JJZdqGHB!I$4h0*Fh*VpG"jU*rVYT4Q4Ud1
+a@$+Cm'k)a)Dfh9Gjl-V'ci(IhUPrG`Q08hJe"qb-[l8qk,h!(f6JVG(8a-li8h8
+e6qb-cq0$Dff%CDIUU[*i)$V%,kIbQ&JBEC&j3ZN%!SfVaq2JEkfe,6p+1eMjB1-
+%`ac2`aLJ8*T@0aaMcQ$E4$d-&8TRM$["9(T)qe"9V6b@,M8&j&%Ub1Nm4JRiqhQ
+--rQ*22#Ci`,fY6)pMeGEQBj9!hR)Q2VK`ZSmX(@!)5#2m'KPaq[+JAY@(L0-G$U
+2e+Jk(DqVRBF43,QV2$+4R4Ii`cbKZ+FQ2f*2J3PGPFPf'!,bi2%"*1IUbV'Hq5d
+4"S*8Q#H8Zk&#Q4S"Q01X`&46Cf,TG20(6qI`(Za@jFrdG)Ec-*YdR8reBSE3FEB
+A-j((b9l-4"iRHc((mMM4LaR2`lc3LaQXabZpQ1(#RZR&M1GaXKFcQ-E,[CL*2%l
+eBJB5-4(dBNSap*iNT4KEr%d6HSJal+l&)%D-(cfG)5)kfp-T-ViTS+GcXG6bbme
+pX'fH`j&p'eNlRXRQQF4pX*AIBM!5X*bHHGAY2VMP)r##TiZHLCkm+Z(TZ!DHd8,
+-Zc&![a)TZbA2XQpBRP[r(Y2Fh`)2b62RH4F@[jS06kINQI2FXK,6lTrKE-*i9R8
+%C#SKUSBFUq(TH!LHC,5F*hilc'$4&mDcQAa-I@C3'ma#6&E0MYRf2Nccj`Mj'I&
+X,0N6XaUeX5UGVmdMk&2m!Y#a,*l+G(VH$86jR`"feX@c1r19eQF1jlTHQNT(GMJ
+mdcKLIj(PHGPQ42FU6rH$C'"l)kXV8!&AZijCa9f$&eZH9ci0K$bV24qm(3j,l$`
+E@!cYZIGjTQGlhNPdk$`r1`Ffqhr)(2kVUp)alrN(f$KK8RY5jFh5-ErpUl#TZC-
+mYh0CpXrTQ*Fraf,C-Am-MjADFqX"f04S5ZAj1m5D92V0,+2PHFG2!ha2kjM,bBT
+Af6'"+)RTZBDY5AXBij`[N5Ce0Qpr@,1C2SrF$`M85ma(iF!pZA6-lpVSF,rpJl#
+T'CJmUbJ%YQ[2Vrd(E,B'A-8+k(Ukrq"MX#fc21Ib-90l2R`*E-[YQ0r"BjkZ`1f
+XY-rbI$eA*G"BFhrU0f'lh[CFL-H61ZE1$m"Q6`*qp$0!a`)GFarie,(#M[PAH(a
+5aec)2HeZY$`ICTiD(Ck9hi,Y*X[cm3eJ&8(8M9q%!lB!!drr,RTCB#fEFf@V!M!
+Hd&fc1mqj1Fq[)%qbc`h#ZChl*P5r2mqjGXc0B*fDEbTQeCcE&I1a(%YH83FE0a&
+6TaPSQ,9"B`#PdK0-eENAD,GBFP8!$VGDRPr!eKF@5eD`3`PG)APq,XH5'cm2fff
+@jr`2jeMbd9q%cGiFBrkRFmKpjlGKHkhYqBFjPRcq5C+MjEQ)@N9B%UZ"JZMXQ%r
+P@1@&CYKHChNZi*)-JXr,eT*-,-rY3,[&NNZq62ME-DNQK&QIqeIBL"hY5Ei8P[a
+hVK&KGdEE`FB@5bCB@eZ0cU%#%A5i@&ZlHrNUD%0K58mGP42VSr-NfU@Hcaf%cHi
+8,0KNXk6Rj[I!YYlfT&S@PNcq%@aJ*['NpK*&XTRBV,Fm&h0e#Ff5lJ0N"qSGGAC
+")3P,HVDbD[D2LGhcFbbjr8f`fGhUa6N0iDRiCGM)(cVQRpJXkGj2MSCk!Z1"jAi
+'('@cT%cd"RpL*G*jE-9B,'PlEJ*kUPPG5jPf6J&ImN+H*HfBV@!l*Gb@#8YfaTa
+,VD&Cd[e4lUV@C(Qq#k`L,1RC6+4BHmNj'S"pB8RheeQ&Zbc2Md1(@b`C)Zl)4ZV
+8%*qLPTj#*m(4BPH!DN*BmJRU3RZ*ZcP8PX+5qqP&p1ZBa+0Q58mCe5*dVhMHR@2
+*4ZU`0TXPL@l4N[G#G6Zff*j[cE&N`cYJB`lUm"1dX+6lFHV2VAE-Rmr&[1eCf0j
+Jm`"eSI$!Ma*4El3mNq!aB8RhVfq$`cdf1ULDK58Vf4BPXfK-8e@+P[`YmL,MDXr
+p1CEmi!++&lXflmeTbEpNM[C(f`ASh`K,ZVp+E@2hQ1D4)S3P2G6YGXIS,L*FY+6
+cA54lbh-IXV'dj"HCLIhG*d-0V9R5rG@[`fErYPp#65-DiVdF3fhrk[STF+E&NRp
+12B3q#rSUL,FI,1QX#6CL99Mh2l1[B[H,jK%G`ALQS![&NkVCmZaN[$RX995M&m0
+qK(4TrKm!!!d19'0X6'PLFQ&bD@9c,VNZZ5!Q)&0S6'PL!*!(Sa3!N!m"dFd!!L#
+6!*!$&[q3"%e08(*$9dP&!3#[[Z!5X)6Ze`#3"3)rGJ#3"MCG!!#E#!#3"KXA"[L
+,4EB,ImP#D-ZaKHdMLi36MPri`XP#Dq&&ZqAi*@'%,8S@HR[YZ)00C4kK!ql9@Gb
+9VH'C*kG1q1V4SPf4ff`Ii3XRYlaNajBM[h[*FXCflm8**i`XaeV)[[KLC$Qfm+X
+M#eQ1h,CM,@HXKI!MYf0pTRX3DcRI,SrF3PDXm!HmfRAYBpZ"hF+Z@eJ,!&R)E#'
+hb5E$K@bb@cGCEG5NXipb-kmc,bFfciP0SRCpY-kADj1m,Xqm"RC1mVYd[jQ,ATq
+Gk6A*5HIRjA9mmIh&3AlRZr$&FcPR,QpRGKjCI2+lb#Blb5DhMba(&V+3!0X#!!'
+FGEVDpAD&2`E!SYGY9Zbl#'[KYr$&10Q3!*qh!GL#2q#"jGQJ9+pA2-r,)HZph-$
+&b'QHYfSBqpdqL[qPZpC2)Zrh["mDplc9EA[(9i$Ipb'U9!+8rKqm4lqNYm+lZ!G
+!&1Ep-X@"qN*m&Z2mp1Q83[TUri"r8HlfjAG4%LqFpEe@UqhiF-[A"p239-AhPYr
+d[*pVk4FZRRI4U`Ve@V&82rG@&@4[PIr4h2j-lhK-crZ`Ib+hFX8kEah2F+rRIEl
+JrH"5VPC0MfmCD$6$hHA&Pr2#5el6re,TNb@mYbF2Dc6af+9D)#eiDb'&PN163RU
+QX-!Uc3')6#a(5%ej,YmS4j`1&H4BeUZ-TSI4NKlamY`&ZC%9PhD,N!#T"VSi8-&
+5Q%(k9lL5h2-Yj'XF(amP[*IY12h)[iM(0hD8IVaN+FT+5iRD`[DETdU9c@&a*Qb
+1MqI2KkV51djr(qLrdcrYdMq9@dTVp@@ADm,rI*II(-A&j[qPp+qqY,IL%[*`)LN
+iU9,HY4Cpl$0CAXKdGm,RGD2HP4[d(eYaY8`IZYEcAKeJ@)cFR061#l[%Tj!!P*l
+Ap)rNVXKpX90bGcC+(aJYlfS@QhXhMMIVYi5P1#L8Sj+hj,LfA*[)"rPkY9'ZK-e
+PejXhA)[MjR"6@$[YGe'j0[m-()9Cm&Xd8ilVTk!@efZR-&U,8DPBHIiCb(GYX9N
+VefDMCGqPa6h&ji,@lleS-@i@6f%f,84a[4Um+Gal@ldjFmUhX93+SbJB,mCcTac
+c#qA+c,24c0c`TZH5"(l0jDJB4@&eecHI&-kG'35hmQ-fVFYIGGAcbD&FZh+MkIS
+#!B9CdDT8lhJXq%@2"HI1ai*EkmMehr)TCf0VILLUNPEE`mUbimT`hr2[ZUVBR!h
+MB$+-ip-2ZaLdBB9LSj&icY``rhb9BmGLP@0AVR)P2hVfNTYqB[DM+XFZXXS9RUG
+Bj6Tpr8aQhd+9+lmhe59f,98jpLe81ABX9$Pfj#TAmLX8MT*cC`CaP5Zm@&MP1Pb
+lFS1UA#%V6*8Vq8@2CDTFb3e9VYfRR)eFjGLa81ABX96P#Y@M8193r`4lEC[$[B2
+-qCkGE-lh,G'jJU-Tm!8rVZC"r*eXVH4FS#5qXq'#[Sp2"Rf2GPEAr[+'L2QqC9l
+R1lF61pqcRGRjRL9U9h"XTdX&lh)kPGKGm(!Gp+lSfje-KZ!&#9*NH!A(q-f+(+r
+JTdPHk059R5@DjhZfmccIXdcdJY*3U)%kqDAA4HAS&-GXQ3M''R'j@Ylh$5STUmQ
++KEK"3l(GEdeKf@GCX63f'44#hU6mM1daKLA,""Nk8T5q8dHBA2N,8EEc3!Ubh8r
+%b$lP%#rmcf*CF#lb3q2C39L-FiQA'pFLX65H)E-X1KEC@Y(ETfY&[i#EmB1Af'@
+lVk'Al+[jTI%T*UMa$$1dj0Me-%(b'UHHl1eS*(3iGcpRb)f,MR'k&GKad8r4ij*
+6qDQ,"0Pi&KQbm@c[h"MIX(96G#`r&c0Di64lB2e!0&Ij9M9Nhd)aC-G5,@6IX"5
+bCk%5XL-A`T*I)6&,c[63*EHZG`k,B)HVAc3+VUS%XNZK!V)M&m"f[r+6k2,(2Kh
+9Mle,aDr6YqXCZI59r+)%-i@[j)Dkeql6qF+&UXH1KD,(MX@DakjFmNTqRHp8,(M
+Gh+qEpd@FEarIkqCkA6`[jRKPIYI&l4lKGBp`ZK+IkqCbA6bZQm1emlIph#hLE4&
+Rkq*V-9FVml4fMYE&clUj@6F[FhCpHScVc1l)d(P)-GSR2c%Nj`rIE8*Qc)B"Ykc
+CIJXTarE%p`kN'0'6hjmL+mhf0D5HSI`KXYV#KejMYM%SIFb'U9UDP24Z4+Nef`d
+SrFb'Z2ZElIG4"TJ0XmLRQHdI815!XV$p#1Ade*E8f`ddfe#8-m`f&f@3!0P@@Pl
+!GMA+B,1p&'@)fAiEj5bcLEQUa+9Qqb)+iS,YZbMRQ!eMHaMD3SSKRZ&Q%a2ALF[
+0eS)b`Q`E88DD$I0aSmaf"mTSXld,"EN$'pkqhQarMd*6E+Pr3aQAfY,+XI&Q3``
+6c)BKXiPQ@iXbb@b)@mb05GY[S%`aflY4TTVY8bKi3pLqML*(e)6YqeC28$T34fD
+B$HmZ"YLNE6E+,,1KhX!1ffD81@Dl"DA"E'p#3Cl#pXFSmmb'R*Y[0Z6FJY3Qja0
+TJ#kV[*86fm+'0fSd'q,1Qfd,#NeLCZp%`53mE'p&@@5fpk0Jm!kf"e'@Q1dl+"H
+B$EQ1A%Cj4"eCDME%ID(C%$FNE0HK,$2EVk%X0p[E8&DBl8p3a-bpY2dYbX9QqaF
+8e#YGIY[-KKUdbQc)Yp9Q3raVc)Bm3ll$KYUfcQa[4N(YKHdM+1[0pK$+"V2K[5m
+efhqLA*ED+P9rAf!fe+E,cBEmZF*Xm%&pJ`hMceHDl6A'0@"$RZ&pB2XXbP9QqbB
++DM*XU'hAT,BUmB4VcBDkKPb'$EQ+r))0X9e[0V`hYKr!K[IHCVEl8,DEl5XS0$P
+ET6cEQGSNK3%IJ3dFJ%K`YHVAEV-KYfQZY9V[GD2CEN@jb@`BSAkKf6k)3U2Je3q
+Jl$AEpe"HP0TUa,9S`,K'A1)PCN1p3jf%$EQ0Yi80EieiBEXGK3ClDpk(FT[C2SD
+#QJ2E9e&HEVCr43'Qq2U)qi&h`)DkJYS)'qVb+mf'Z[-UXb&RIYeXd&pYYYp$!Bq
+!l4-S[fNfF%6N2Q`r3!'r%epIFEAAQJfmi8kcSHlIC6E8apHC$IRrHV2KVGpJ0Z6
+C'mhf!46`#0LqJ!)H"a[b'h9!I,AL`-#%$E`"p4mfj$GU-Qb)qqeQ3ehj(E-K2j&
+IX#&qm',B%2FlcICA+1"ZX(d,"AN"flqMJ&Z*VjrUfA[-"Pi(RJXEF[fpCN2YITr
+C8,2q`'c)fcmd'plaEV0p#1@2c2DA++LaX(d$"Hm$fip48)[%eermr"kcSFk"jm)
+'[SFk#4[i$lJBE1!!L"%f[-H(cBBD!"i"'plkSfC$R`#m"MC`#p3Lf&$c2QkfRk#
+J9SK[J()#Q,#"'rqCf9#(Z[H3!(4ri!IJZq#ji,IJaq$&i,IJYAKIm'G`FI"0a)S
+F"am"T`%A38d(*`H2"Um$e`A("GF#Td@Y30kLAS,,iSh3#d$G4Ld$j`Ir!1p!VU"
+QSRkKCS0RJ&q!9i$IJ,q!9i"2J%H!2i!hJ#q!*i!IS1k!$i!(S2kMlU-'JJHKeU2
+'SlDM0U#rJPa#2`9p&13jHJ2SSi#rS@m#NS1kMli'kM"i(rJHqMV)Fh!mm"'3!%l
+d9Y"635m&244`A[3iG0m(046e3bpe3(e&6`#m'(`8A!Rm&r`C["Rm&r89I"Ie"C`
+FI"4m(0`42"*m%K`5h"&F(K`HR"KF'&`%h"HF&h`)("#F!I85("Hp!Y44p!E3%`#
+r"8F"0`%R!4F"ad(G!KF""`(h!!F#a`(h!1F!ed#0"lF!T`#A!)G!c39R!&F!4`!
+h!#F!9`)I!!p!r8FY4-e'V8D04Qe'c8G04fe'68BY"LG!c8FY4Je'l8A04De&M89
+Y48e&,8804He%c85Y4)dNlZ"rX[H@8KULQL(EYPkJK0alGV&(X+L$&JmNPFSYYV"
+&IB@&,L+8*$+&c##cb%VND'39FK5b$MQ!Y39GLem5[Vf2l%iLrHi5E-ELeIQR'T2
+(GkZS#"$P)dYUp*U1"'elYD0Mpi"e&`jmj68CDJ23d9dCM#cUEUd'#CSUDZV[(YK
+AYJj%m+hI-KjX(ET"&6")(9kPSpDUq#plH#P1A!4-UUTAeK'V@)-P&(U65l`3TX+
+lB&8kNk*Q,q4NbK-F$L9q8fAd1kMaGfLG5kP@q(9L`0)k&r@J&jiV',r-mR!2Mep
+ZLU&4#8AbEh`f)0I-Tp-,XVB3aXhkE@&c2JU5)CkfbbH#+rheKqrbeqmHR"i,*ME
+2H9F%Np,brCHp`I1h3EH'Ikc[XUhHE$"Yl9Vl643Vk9Z0'k,QKASm(l+Ar0&U2%Y
+M)(9LZ65*PP(bGG9'"'ESf8M$aPXa2XVFFr,%JcM3`)&Ja'JRe6rlTQNebIHqGlq
+hpkQNTHCGpAYprNHfU6AaS(K6)[F(lrIfINlM'ZVl2(*fk[NPN@ArPG-U4c@Tjjd
+D"D!@YHJpL*VM2CakALp563eVJ3Qb9TGklK9PTIDei1)J`e@Tjai4AQTQ#dr3hFq
+NRPp@ki&Dfk+[)CS)hTV8Fil)1M@k4EF$EB*2T*iE4DHTl5eb"Jd8b4!6ZGH+5&)
+6A(4(40XLDHrj*G&fDSQ,IJ!D29HQRTp8Ji3Dj-*6Y!3'[5VeR#G+6Zeb`IRa(MG
+AidL0(MeB)lph825pip5!GXp'03#Q911+'N+K*pUcZQi82'@MLI,Qlp4!S5Dpq0$
++'TPkpPAEJ9VfP!hdDUp6)i`Dq)4aTfAKTl%Khi)pA25j!,DVZ@!q"m6f+k5a(ZC
+bcAc(QcC*H!mB0rA(h#jIAApqE(LN2qJI(TSD3QhGNTqb'69AbLHB'IA(#Krk`i+
+!96"M)-FHD3DPq$hCm4-0+$94,)D5Ir&DrNT%[&PkH(66MY*mH8Cc`'XRf8Vibpj
+Pf5GS6ENQYR058p)CX2'eDm@MD!J+FI!CU*XUApHIjqc+T6!RQa0-Y'9+Q+QqG2,
+Fc)!IrkUlQh#km$dEch5jIDk3!0@Xf3Xd85#UC8ZY(*H,&ABr,'i@CkXKLmL1ILF
+E1LVq9@'c@Ui9iqq%$ek&GDCkdiF3lHY-h306%mFqAQIkb*lXacI+DL6`(XbNkCN
+bM!1KTD9Rdm!3+a+P-cJcX1)5i(qZU+',20RHK'aQ6r,$[4GNq8hG$1rJf*!!q*l
+"I!EhfALI`hdU$XPMNJQM`3S0d9GUf$JEeX*QZG5cVHALTG26SJjX+rCZU`'b$XK
+Tfd61YSUe,63Dp@Dmd5D9A@U&`@[4NK)M!`dE0aEUc9#VphB(2ce`cF$9[GE)JGH
+L2j!!%am)HNjYFE%f8fc1-29"ZhrE4S0mUZfS9ZZeRQ3P!S09LKFq9JF%Hh59m34
+C"c,LKCYBdlNalYh@+T+mX)*I(6NL0X(Mb*&R)R%2(%&bG0H+qF5T*XAAe3XeR6k
+I+f)&`31p30l49E0'!65dCkU1*cq9a*cG1Qk-FKjmMmiM(Tr%IhErQ-YXVBTMEL8
+)l@!`j`XFrkUl0h`ikhB`Z""f`6J3)K3aGRC4*(hUAUU$9@IBHBXGZ&MMK[fU@'L
+(REPB@SEGZYL0Llfh@15'KA"i16"fE$h&cPMXHF9q@Hb@4Am4bpZ`Z"&lCV'b$U[
+K-(@*[J6f[Q,[,[E"JYTM[4Y@V@'r,PEFBEm,GU1#e@-r,IB&B(mY&VDKHi!p[pM
+$Lrfmf1q,RElBdiY9EpMaLhff@)D((F$SdQ)P'kCrpFjI,)ZMhHGbcbpfjQ)R-IE
+@BTFZdJ-lH,'V'$2a@15'0A@J#pK4Lrfk@0#(AEISG@!&R0jTLefhf'A,qhZa+eM
+[lX8HB1`baRT"l#p'ka8lM,%M'IZ4p5jN%$[XS-(D#EeA@HpEaUjPV*VM2F[BrD[
+h0@#2!hBfS*Z#P3hB8iZpa&LBT2IjBXm`lbl'LN$H@iaGa)rXBmBZClf,'EYMX41
+BG`&MlbrYQIrTPreQ2eSkl8QfElJfZ)0Ei(-Km"$4,ACrl'Pj&[Hr-V(h#jMGiAJ
+%V3(l#IBa`k$[`T!!qjJ&`ZKN3E1VTME'@HU`f)NQ1@eTTjMHi9lbdcYi5Rl`!Fm
+Vq6QUeK2cYf`lTlr)'f6L%`9AMHbB'QL8AYU1,Z*3PpHdKe&qdfIL8"qD02)pGRR
+edQZH(24@c*c`9QrDQ6[@HX$(lUfK*4-`Nlh[D9pN-XcEGh[IdUimq$lGTke0TQT
+EYqFR&QTFMq05kY-@pjk9ccKd9H`p`j8%m+2GC(3pJ3'R@bN%$ZV@QM-iAKF(M(a
+P"kG!a"N(AEGe,Kjdj6DFLBII"lcc8KFhZR@lAX!aHB&ZhKk(JmlM5mrJd*8M%JI
+GbE8Z(R3`Ap["k9j**h$3%EhKI$a&UeYZ+LLS$A`64fPr)DU[lSAV1ce+phZ8qYr
+P@cc+IAbq4H6RIAap0`Rhm4rTZHYq1hV[TAiljL2dl4jk"S2Zl(%eI)9a6&fKNA@
+D"#"EG+&(CQK![,VZK')U3mqak#Y*m'&k3er)K)N9I5%6*M"dc`iY9EU3!%PH$%)
+A-XR,31K#*RR4KjihrCa9!RbiqSJZC%SmBC8"(kjIdKFbiEhdK8c`eaFbS5,3K8b
+H-TdZC2+8`A3KNkI-T!ZC2%h2d)9-mNSRZT!!bG-d#Ph)j+QV4aFbHCT@S3ZC2%f
+Ed)9-RUB`k'!&6qp0r4K2&j(3K8b51G+&60jI@k@#lFY@X@$$"6Pd)C1Rbi6S3LE
+[+DYNX2f(965N-h+5'J4*j3aGb*681p+&6%RKdS9-5H8hAFL89-@L#jQ5QN#L#jQ
+5QNkKjRC5NdCd)905Nced)905rA1kN!!T+@j+&c)P0F&$&c,*bk,S3UDN,MqK#jQ
+51Q'",Q4+kQ`'ZT!!+DP*D@SV*C86G#&68KG3dB9-mK)TZT!!+IQd9@"GbUJhN9)
+0SJZC8US4G#&65RP)&c+Pp+E8H8XT0VU3!#QPb5+Uh#P0j0#&6#P08G'&6#R9!lU
+3!#QP+5LkN!!TT9%#ZT!!+D9V@@K,GNUAVY#&6#R91EU3!#QPA+F,Q9+I4U'HCNV
+R5Y$j%@RP0adFNGCEdSN4DG8Q1LSLV9T!Cd5NP9Gd1%4DEd5R3U3e08E(3D49fqJ
+FL,6HNJk!5'Z#Ldjq5'Z#L)j[51X#'$Uh)De,AqM!KV41K+!,QG,+AEU3!#QYUir
+S3UDd,[+K2QMkXbM8Y8Tr"B8ZC**A9G'&6"Ra#TTFbSJ2d*4B4[@8,Q6+U%j4PcD
+Mh+8,Q6,+0lU3!#QMGk3,Q6,#T3ZC-TT!S`ZC-TS+S`ZC-Z)VG#&64TI08#FrS`Y
+Pk%+QM%k)S%CSjZp4k%+Qc--S02U58CfQ#jNbfSa*&c*P9C[T3UDXkMX0e'G9lqK
+#TUcbQ5jNbLTrU,Z@9Cad)90@18SA-Q8eU8)A-Q9e'3eGb*39Vk+Gd&R9'1SGC4p
+&S3ZCXVTdLLjNbUQZd)9-1A%5ZT!!59jj44Fbj94Ek8+QR1SAAFL88pfK#jPbbP@
+kN!!TTabJ#jPbHJZkN!!T*jj%&c,PG!81AFL8dmNGG#&66YFXdB9-1H8@AFL8dd9
+0G#&6lMp3k%+Q#[%rZT!!U8+mKbjNUP#HG9mRi%cie"lm4-k@-f0*F`D*@fh%K6Q
+*(d"@)UZ3!0A)'Q3IC&pN,E)IXMpb!2)dC"hbG14!j"R)3FJcNB143j!!Cb(24Z+
+)iR13!-13!-14jb*()%FL4b&()mFJkj&MNH13!114%j!!%j'6N!#6N913!&14dj!
+!dj(R)@FJCb*R)@FMjb!EN!"cNI13!214#j!!#j(R)aZ4H@36XKQj*$hbeph4jAB
+EI1Bm!A%,k&9DH,@P8JjR!YZ'L40qKT%@#BlP`qTFDI1h*8j)$YRE'!FrJGp1"Nb
+#N`hN8)XB@42iMC9+[643-Q[6A,'@'4I9pQ5fjQd6Q@ea[MV6-BT3I@0,,3kE#if
+ikl#PBebdf$8ZVmIPhAXcXcM$Ed[R'9D'8AfK@HS%ePB[c@I'9BbIq-E9YI*LalL
+RA-Q-&p@,HUCGi@bif%Lp'U1p0BXbAicD!HHC@0aP6p%dAq`N4"-@#PXmHH2Qc03
+bQTQ@[GP--MRTA@"FY0KSTYCQjL'9aFqS4AZBM566c@&TS3d3T"EbDRQarG",3N1
+lS"M0Q8AFJlUMr@`YYCP`F@cA,@fV5%0kmTDaYKiN4mYB&LCf0QM,lML,J(*(*Y)
+@U`KiMGd@&@H[$pTDE%EfAUhcXfEB&8CKFdrEE9FlY9VV8APa-VB-%3Ca"D)I#"+
+F2)0(@e18bcDUfp@UET0QkL9[Z%a94"Bde4Yk$5500V8ed[)(fid9(QH2%XH[MQ4
+V$U2jZ0iSc#SiheRGmLJmGXI0@UNBKD@U(YkXULMABiN[Mh8Ye9l+U1AeQK+",f0
+08#E%IPYehD[d'&ELqN@"+a*(eN"j'k2HF*KJapQfHPcAZ*Kbf3)!e8LJ6k,@kIU
+R))0k5(Cj+D1q#PX(*01TFG[NPL!r)&Fm64XeBeeQP8APkQ)TP(%Cf53KS0&%Q%4
+CYYfX-$BX"BUREDNQMbeF%Qp8RGe4)h@fLTZBiEG`-NmFj*K)6h9-l-L2AArp8Jc
+Lb%Ffbh$e)MJ6,Ul6%*0V"E-1Q)`8-+`Q+*J4P'DPL@5rT*m4X)Bj%[JhMiiQ9XS
+'lG)@cq3ck&,ZE+VASMS8BRHmX#ZT6hZ$E`4m5H*3M&N3)P%JLNL"8iM'ek(UYq8
+VT6L&J"8%)Pe3ZSb,INV1HK90q`Y6N!$d1#XQNh#SM#MIB@Z[+GqmBHE+EP6+NA1
+%RJc2UGq,d0@6FVBZ,MFMRI'T"Y%EdQ9GA8pHM'MBC&*jJaT[5RcKa4BAPpjXcra
+bP69jm['PK*5PUTa)!B3X2*hTjfFZZ#ca9%&4VNl5JjUR6[&2M'CK4R-4XJ@C4)U
+cb14P@KNNMX$-)5Z3!*A)+Q3eXJEC"pNA@B[XKqb2()!m$9Q(2"dj%(N'FK$b614
+Jj"$N@FLcN814jb#()BFMcd@13)j%MN+14Sj"eL2()XFKab-R)#FL*b%R)kFJTb+
+R)DFMcd213-j%cN,14Xj"0L$R)ZFKjb-A)"FLcdFf)S1l0a`!Ppr8,29JA(9Eap3
+%T0c6``k*Q`rIFC+6cDlA6++ll9XU&PDS#YG5&F5GPU"1$VG[Z@fS#+V#GUV#Rd0
+Sk9*54p[hSZ4q#Di+,kBUI+R9HYUQ3PeXhrrZai[hUVJIEV05@plF!9G'iCda+9c
+DUBE0%jL),ZpD`c4ab8ppHJ-*Q"P#,QhNG$YX)-&Z"SbjPMD3!'$A!QEDH31*hMk
+#[3VP$55Pl52BDi!p"pKTJ*PiC*8$BJZ*mq$VZU2"rE+Ed3&bqGN[6JG!R8qPZiC
+%fDrT&EG(A03$9pbP@I+#'#IFT9RCRR#ACU&G*UlD+0B"Ilf#1kd5b$SJlR6mkB9
+4BQ0-JrII#1kZ1L$kKC)Ar[cLX0D&A48f-,A85T@&Q4jKT%(@JFF[6m2&B5kb)U$
+V3%92Z)[$8!HUHX*G*)JkJ)P"c*UT+51KLjRHVl9DRp!@fm,R$i5lhMlhbpjlE-h
+'YQaXS+EYf()H#l86mcMk2J"XbmE@CQc(TUhBMSE2JC@MiM(f)Qp'6N9Z3fj(lN$
+Z40k!h)AFMGb$["(CM&b%A)aFJV`!fB*FLV`3H4&b'A)jFJ@b&ANaFL@b$EN+Z4U
+j"VN@Z3jj#A)pFJ2b8Z4Pb"FJ,dGHJGb)["+j#ENCH4AbDZ3eb'Z4@j!!eb'[4fj
+&6N014jk(R)'FLCb&R)fFJfa!cNA13mj(,N!Z4*k2E%6QN8PN#MNC139j%h)d%V@
+Nb&QrHefVGIcdA8M11-lUk[KF&,F'*Ee,AYPA0cLp%r$%Ka-"'KX0ZfcJ4"c,#U0
+f'82m&9IkGRh,aNIYBSD6FDc0fd81*pjejH6%Q3L2ab&[mEPbcLY&d@%1X,MG@lR
+4,PB3AdAMbe),1ije3IM)%9hcN!$`5fp*,X+3!((dV'lY[3dSL'1mAAMaUcJHIC!
+!aq0ip2bP*q)i%-La1,!FHr+q`64IlcNqerVUB%lf1Sj+U0Pl+&Nf2C5ji)T055i
+,hiH3!$Yckpi@q&miPLbXNA%FZ!MTd(ZJJ56MH$3pRVK4DD0G(['V1*kpG8PprSe
++)JjELCkiGHR!Kh6Yr@3FZlfjFh@DpS[,3UeG5h8DbmGlBfeI80ljL6hV$S#pAq!
+IZk*Q$i#&ciMMm%80a6hVA4q@PVX"iX!RPp(rr`qRNKbm5p(p`EM&bhCM2-QiicL
+F!Bala4Zh[R,-E(%pIpIRq'$ZdDXqbG`2aR'%Z4q-i`Kc2a6(cjKlEabpc"dI-AI
+[mBI@p`"Jl[[HifRQ(MrXFHEH'mF4jVi[M+HBHfmF2FaGa('3!,`VjRl9l2rR[I1
+$FBYV(,SaRQ6F84ci(!'-HffjG[A2")XEVMh$Z#[rPc'*1!j8KU1-k@!F4jM1S6K
+qaR4kicKDbII&m93PlifMTqL*1%6H(f,Q[GGCQil%rJ`4FHcBC4FGGArLL*5$F93
+@rZYXJ)T#)@rh2*hi(UYi6@NQ(STMkmYF8F5"LilPk5PL1,hdZ(j'E`lEPjDHH0H
+6R-(RdMfFr&JF[C@c*mrmr0Mc8TSppP8R"bcZVc&pNqlMcLpYSkX8GD(+Ap#&ZLE
+)ZSp1J$LD+P(N8@*%!BRL%,8HljSiebHAA8-R`([)ETm6)!lGlE0a(1[fA4YA+pl
+SJ6519ac9Y@A*(GJ(hVSqYqUY4lQJBXBMDdI[b`A(MJ-TjS$lI3Erqh1[Ir"$Z9A
+[5&E3bMLZ8aE&lh%ickM,XU9a0Pr4BT'&D(mFZ-!bS8-e6qDpl,)i!I*9GPQF!((
+J8q8XmGehPA')p%Km,cp`qmm"bZ!9#Z2I2Q1MrF0SGbre5+cU26(jd$6fVV1p+IA
+T(,1Ij$"1J$L@hY,F2B"mlPh"5Yd9-i[f+h1KdKG`S42j%A#K%rRU$TJ9NecSC2e
+!"9jIEV`bJA2iAGd6R@Yma+QHIeFC4mpYY)IM1(Kkq*!!hQmcA[BlaR6F5M0H*cr
+(dScAcXC,l,6hA9d%8pjL9ZcNj`#C&GYA3*kD&BXUY5YJ9N`aGhP-H6G)V[F%FhG
+8-&-R319d+e5U`pr"`klF(cdGKmZQ(2Xj#(SaEU"015Frap+QR'1pQ1j!R!3EG`j
+mY((R`1IHfVM61rkIk1Y9-IprK-'j0rB)('9Hqq*iQRR&$h+FHIA'iCcBMh#-HA8
+(iKEBXk$L%!HKl[m3K0KEVdM"IK`h!#13!(%i*IBqq(FMlKmCHr5V@EUIe&9h0b+
+f['mm2phSJ[N`DlYdk)BKbGVZK4ebHVhYmSRJ5RrpiE[mpEX(TmH#LFechKA"T,4
+mrf9[i%MhMl0#rBYpPfheCS0TZj,mk1G#k2'9hr5C104RHR-l5UpjFY"E-A2#@le
+TCqjBk`%IZlH'QH2JlV'pll&*c&6JlEZpEqP@6[JqcAPUNqY'@VIRl3jEKa,R58+
+LF9FGIZI,9pHI(aXHk3rkKiHQKP"EYq5Rl2Kp9mU(#P!c-6CQ9pfVVf,6a(5lcq+
+YIZj#F1'iH-[S#2"H&bajBIYbF((&![NR68qCRMBpBhV@p*cT&DCAQPjPHVAT0DE
+h-Ef[kE@Qpc1p[qRb(A$PV(QRe#9,Pif,LaJ)kc66PjKHCrVTTJmdr3c6"jPqTZQ
+$64pLqPQQRfhk8022-AfBkF002pId%DD20(f8kD00(f0k[HPM6GI[10ld#DC20(f
+5kC00Rf,k901RQ6lGp20-Rf(k600RQ6lEp$QQ0jJqYjYVk9HrF$PkN!$EmdbIErS
+#daHDIVlTMDER6@mbr8,6QlYa9k`jFrBfP53FY%"kUJYEUA2KrE1iUF`*&MbkLe&
+e)IlbA'k+3IM,FLEdE"HRHZAb1GhdhJ*%jV-)A1DTX'Xr@DZ%,ZZ1m(qKk6,[K5l
+c9HJhQBkV,4lrF*p$-ZNMCHab26IFaA+TRR%Abk9l`PdXph$lBMNRh'9DQCja&mX
+pIUNDA5cR,,Y-Um,9!Ap8`*m8F)a9!eN(+R[#A5chF)qjLqAFChFS68RhNbrYV(@
+SZ$ZaGHfhIp0l%jXhHHb!G!I6GUf(lYfrG0@)*hYiKa)'21@ZHHrSRrEKIkprp#-
+lrAIrX1jpFdcGSI6i05[b$U@S6RIGS95Xdilb1j4F#XcG$E5Mh$*hI-6F[9pB[E-
+(!(0h5pfKG$,[6fNClP$D@$Y#9bRU3T@rS![eR30Cpp%*%)Hj3bQ+Sq[HRQ*A6(B
+0R3$[)EYp6S!ir$Z8pXGaV0XREkqjMqe`qJiPldlr)HcL$LA[`%FEhNErd0l0pqc
+h$rkXLSQi3kQfK[r,r%1e6rS(RJ#2Ekq*hq0`RTNlP+)iZZj3+XCKlP"krMeNPm8
+*N!#[XX[L")J$(pe-mrblbMM8(8V2ah'+D(1(NRYl%kHm,elQk+Qh`bC1bGbGE*X
+i$q6p+4A%*XjcrEXEIr[-*XklCljIe0R%L9[,8mQYj9QlYIbj*hD$IELafqXCGh0
+lTUImcHfBijFhYaIUJ,UUHN[[X)[DMp5"C-qiQpZchlkjh89fK[q6YpF,pZJN+`+
+k$P6dK,Zj(AA!)AGcZj!!Q#0B,88kbADb3IPSUJZF&1UD-cKH&fFdkLdC6PD`rRG
+Efb"`--Qfi3b1(jc!QBakUm1CJ[SbKc-90C[Kj%kpYm'CKTTl)5m-cR68#SH$cGk
+9$QF'DTA$`F4BYF1CK9VMF'DMpR%iFe$l1Kc3L9U(-aHeRm1CKpVIiFa((H"`&U#
+HjR!@SYBj(+c41phK0+)1G$MBd(''`m(QM%%1Ca(UQ3i(%qb$(Fi5e#%1"eZTch)
+i,DKR1jbPU%-G$[B"RH0`X*PPQ-0CKMVFi5a(2GIKV%!GiA!`PMV5i9b-1XVKV%3
+GlA$D8-FiR&@Sp3jR0HTBKl-'GCc$@BXkhZ'X3jhJF#j"RHK`eU01FMJE8#FlR%Y
+4TcLFbe#R1T`AS%jc1*HM6RFi@!"aRX2"iXXC$JHce6-G$QDjCcNFh$dcfq&JEGF
+FKi-GZJd1"j[EjMSFc2l2FcKE81Fl(-b8,h!if%qmd1&JSp6j$JHl6aSGcRE8[-2
+CJGVNF,$0SGRKh)#kb1&JbmGLKi1G"%XF$PB5A1"`X(1KaH(FK2SDemGk)HTV-ac
+GUHU)jfE80lTqeel80jh(199(q(Uk`XbUE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK
+aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK
+aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK
+aE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jKaE&HBF@aAQ(&X9jK
+aE&HBF@aAQ(&X9jKaE&HBFG`!A@'1ahD&'FGfK4R(GS8CahD&'FGfK4R(GS8CahD
+&'HF83k%V,&J-L%``"Ej[kPei!5+D!MFi)'64&,M"%C3URJ)h1"R8D!VFi'!rD$3
+&ER#`365D!MFi&DM4&,M"U850TX!06K9U0!9ZF+T4SbP`Je1$'Nf"'j`qU0%8Z-(
+TLaT0J4ZF@Y4S#YcJB!Pa0!9ZF2UM4P2J"QF!DM3&ER"13ifQ`!e1(@Sd"@j`6NH
+0TX!0cN$8D!VFi*b"'Nf"'aaaJ93m"@j`cN50TX!0cQ$8D!VFi!a"MDE!$FjCU0%
+8Z-%j'c@D!MFi3e'M+A#$F`jU0!9ZF($66$3&ER#'SdC6i!ERA04S#YcJM%#0TX!
+0cNM8D!VFi)a#MDE!$3kfM846i!CR$'Sd"@j`kP'M+A#$-aBeQJ)h1103SbP`Ji0
+Y+0%8Z-'CJ"T0J4ZFLDM4&,M"QB3D6B%E('aKLDE!$3kfX%46i!B(@eLL+A#$Jbd
+Xd45i`F%@PQJ+h1"J#dXd"@j`X)8PQJ)h10M#%Nf"'aaXBBQQ`!d1YV"%8q!'"eY
+BSLP`Ji-Y,0%8Z-("&TCS#YcJB!Y,e1mh1*LhLkE!$3lQlD)TF)1$HEYS#YcJB0i
+ZQJ)h1*LhLkE!$3lQlD)TF)1$,II4&,M"`9aH0!9ZF$"(&r6Rpme9##r-X`ApqAd
+iTpi)Rq!cMrARK6mJPQ8ib4Gad*m2q[Ja$[Vc34mraJRlmc%1q[0"[cr'3Amqk12
+(11M2"hhm'#IXcmFik-m(rIiB"rhjS)mIik!r(r6aBacdji-qISb$rRc3aipad*m
+2q[Ja$[Vc34mraN&r2ZMMacMSc`Gpr"JRl-qRAX3*qr-a6YLIMh(#rRb-%rERBjb
+`2arMK2hj'#IXcmFiBAmqaJRlmc&1f*q2FF,qI)`6pZGMR,!r(q1%rINB*qc2acK
+KIcl'#I[c-8lBRipa`[jmM"2fjf1FX$mIii6pq4J(rIQJlalMS$mIp2&MR,!r(q1
+%rINB*qc2acKKIcl'3Amqk,[(11M2"hhm'#IXcmFiBAmqaJRlmc%1q[0"2ch'3Am
+qk12(11M2"hhm'#IXcmFiBAmqaJRlmc&1f*q2FF,qI2T&(26RJcjdM)2qI0$(Mh(
+3R`rkq$%1q[0"(cr'3Amqk12(1'&r2XC"IclSpmFik-m(II`B"hYc$[ERK6rfejb
+#*26Rpkqm1M)#bcKf"*Cal!JXipJ4@-Da)l#-BdGJ'FH1`$+1(B&P($X#bcKf"*C
+al!JXipJ4@-Da)l#-BdGJ'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@-Da)l#-BdG
+J'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@-Da)l#-BdGJ'FH1`$+1'f!%PZ1a)l#
+-BdGJ'FH1`$+1(B&P($X#bcKf"*Cal!JXipJ4@0pikT)`!ZZ5qC,XZK@d6[l1Pkq
+Z2cmf20)Ip!m263fKYQl*6kQVje$jX&"XqGLfSF,)`-J1MH"dIQKrb$&Z++5[pJr
+i&q9ZAiiNqrfKcAhccS"0crlDN!#H6Fq-BcFp-iiEB0-caf-h2611hI6-1(E6-q2
+B6Fq-BcFp-ilGp-`iGY-cipK0ciaM0cdcMYhdc$Kfdc2Mf%h2M'-h2611hI6-1(E
+6-q1i!6BpFcafdc2Mf%h2M'-h2611hI6-1(E6-q2B6Fq-BcFp-ilGp-`iGY-cipK
+0ciaM0cdcMYhdc$Kfdc2Mf%h2M'-h2611hI6-1(E6-q2B6Fq-BcFp-ilGp-`iGY-
+cipK0ciaM0cdcMYhdc$Kfdc2MZ!%f2A-mGY-cipK0ciaM0cdcMYhdc$Kfdc2Mf%h
+2M1-'f26-mGK0cicM"YMdc2(B6Fq-BcFp-ilGp-`iGY-cipK0ciaM0cdcMYhdc$L
+RHJQERT2H*AhR"i!(pqkDrpd84BFprfYhH#XhkPj'p98d[Lbe22rVIIM)[bEkTVF
+NZf8F621rNrF0T[Pkcr'jePF(Fl,A2F`XaYj$b5$S80S1&CZ5A"Dq$b&hjYDp,I#
+rF#aCK1GBQ[pe#FcYARZZ6Y2FVLc8fV98TpeEFl[%Z1-eDZi2aZd!fU,Q@'$ZEU!
+YDTDjib2QlMhqd2SH!-cGrE0&VBHjLcJ1NRGrqpR*[(H!E$rEYdAiUHeRqlF41`)
+BGqqUM-TH&CXbR"-E,Y`6Qb#F!"XFC)9a5Qa-U#bmZ)G0I4@&3PlAG6X![XFUAP1
+DLBILf2Sb9a4aB)[aX(bpfLKA6MqZRp'E`qrZ!2IIib4Rm,Pd$bFr&NG[jHc*-cm
+rpVbbE[hJ9heqAAhIT2Zimd[Ek#T&ADMb&h5KVJQblU-6)!kjC9kY`BlLd0ZVECp
+FGJfG!1mKZhe1J$KdYmr'FDcE*lI$Ah3JMH-94jN3bH9fB"pikrVFUVFHCFI$RCSfile$I
+@MYkA#iiG"e*XIqMh'Ic[clhq`3rP9Ve$dq4Q1hcm(SIcM,SX@aTRma8Y&PQ)pXF
+KYm0MEIR*[*GG&LG![XSZLa-J$RbdeIhjGj9aL24)I#mr6JeY,Q9)Rp`q4@[jhh3
+i`,BSlM+8p-Nhdc-EJQHP2%eI-(hbaMYBp#im8r,FIMSSl25Zah2,%ZBkL0l0Ik-
+$$e5FU41CTl$XB$)mYcq0dhLqb[0Z1X*-16a&R0U6r0q08Y9SXVXKq5GrJ5eBMV`
+H16,e[&HA-G!#CI'pY)-jr#PXZ1Y"I5,@a+qPRVGTC&&ZbX(RkFD!TDRRK0r!KYX
+Gj*Hj"f9+kVRL8pK`VB2br(B(-h85'ej"4I-6P0QTjkfkeJ!A1FJ[U4cYNhUqjdC
+XZ-&"IZ1**Qh4l&80`Y80mXXpKP+AH[Ej3fbiXd&&JlSi12@m6l2%Z+a"IMrqFmj
+1@*Gk[[*h&E2r0TMM6UHHVIq1$GFcU'JZ3aQ8HVEm(6EFbk!m8HXTSpi[&0!NjAQ
+V)P#H(p5qHYc%S$,h!bJ2@ZCLFcqZB&"jJdT0f6&EliQl&e3dVp%E+Xp2UHiKGq3
+h"FlL2Cak[PYlYA(EJ[bbBM18(Hp8R,KQ38AcPXkV9DXhM2X9&#BfNAmQpC6A)1"
+L"9A@40jlDe,2pp9a`)d++JY446k4HRj$HBD+)ErTZMYK8Z,TIH@Gf'"ARQ+cGp,
+HFm#ri)"Bj6IVdhKZ6MfrrcXii0B%QCijhRck,aNQ,NX38P4MNDQc9*F'9H0)GCV
+UB2VNp%(2Icm9VrCJ08ikqllR1ZB&EJ,6!h1VhP*lM[M82r'HU+Cp`83&,k`F6rj
+q*fqqrK!fh+fJ2*'Y9(2(XJG#AUUJ22qQJhRlRGK`Qi,br%DRjMji+cCFSb#rqFS
+LURLE$Q,$r3Rb5reaTqC@UX,JiJ6PL9T)Q!rSrJ$FQ+!m`9'SUYbZ14jFPD$H'rF
+@8-hpV%CVrF-Rjpr3UERI8[5i(%&K)PqSUQclE@bi&8&jBQXreGbl&61Z3j!!Ab0
+[f(Gck[PQe8kICkFqf+Qj@m8Im#)UQVC1cEeHH+LKb[2PRBaU8)A!P3I+%e@5DZi
+hYf,$A3H+$B)l8Fepp5mUKrak)ejDCmI[L[NJGq3hPPUJDqlR9*R"l16A5VC6cI@
+H[NhP6([1Q1jNafIr%KXZ-T!!hcK99Pdl(K#8pP`TlN8epkh`5RPeJIcDU&1kj[l
+MK"j,Hki5KkDDHkGfLq#b![R0HeG@Fj0hX440hP)J[l8hG@VZ2hd4"ea2),p,k+$
+SQVY*Y46h%XLDfr#q6Xh0I8$KbCVl-EUSU("A@-dPKLPBmal2[iHkl0GFhh-YZpP
+ZK`(l09GlMRL8&k[AQqZD'r"9I+JmQV-L8h"lJFV2(h9UlYe#`E8&LT&mSB-TZjc
+)2IR09,ZDDZiV9AZ3!2'U$TLDqfQGbBXE#Y3$I,j6)3DU&[V62EPrl062&k["iAG
+M2(A*U%jr8CMq")kRHNjapPI$a6qjFc1Y(eechrPC(2aZYrHj6PA*+4+mMhSEF%H
+UZIrmG@cqPLUF69#hdqSdpZ,KPJ)9$ITP9(0R+pY4+99')I0dc88PmkIqkP@A+D0
+Z8FAd*klUpHj8FpqZGeR@pQc3@e$04F&,E-[L"%1NM,T$V(Y&&JdB%Y@S+e4[GGX
+S-3ere$ahZjMfa9NdU)b8(9[d,V#VD&lAHE@r8%F$R%*qFmAYUHC18Sd@I5$eA8i
+9d69hM5*"(LK--$QUZIe8Ej%(kJ@`'B4UlJ1U!@[ERYI6kp%eplir`f&Gfr-11LD
+kjNj9[`05IKqQ(ZUDqcP9-Y(2%C99G*!!CRfXbh1TGb-UkfFmVda2bMYZ0GIhA)1
+erZH9#&4cYHH)IbD[aSKVk*VVBlBYdJ`5&DlLTQSmHkSI*AEEh!h[5,kZfSM!$$`
+[)4Yq#1Y0h6Fq'XAdI&#M0f5F#2d+kSJ&Q1[K%0YJjpi"AJ$XbQIRPhb5%LfbeII
+d183EQ218492--qKI)8484XUepiU9#Vj$,i!k32RCmMJfe!p9#j%[9!Y[&!0!YLM
+-qe'Z6$frXNH&`Frf0f4aTLj9"dQ[`NKFUGUZiNaGr-[Br(89+I8(+-kr&Zr`Hk#
+ALVe5R'rq"faqPh@QDTq+-h[Ked33r&U)ESQ+-hY-HH-2cDEZcZ,-hLJQkqqXfD$
+DSH,-rYKGf-4XY+J3)QIZSL1@f'a9KITqkC06'ccrRI#YIZfUiRZZT3[brRH61rG
+D&QV2%Bp41qTPe9A&aea(R2I3SI#ZX8VNpaFP0dEr5E'Br2eLTEUMlpAJGF4LmVm
+LVZ*h9ImIh5bURrQ@UVIZ"RYIjh@TIZE[9EI1hb@8PN9P4rk$RmIQphA(+EF8mfR
+kUAZaqE0)BcqHFBMmNlq+cHriMU964F`Rrq[L%hKA&Fe,-ZD6Ie39`TqC'#rZU*K
+2df[&9G$h8CM)9TAYHE99%PNhq[A8D@)qqI[9$I2lqH2&CJRcfkU5IJ0r[(L8UK$
+j2k+H*V+CK1q"55bcDD9k-DKY+M[HPQ9(dhAU6U#c)EmVP&qUGZ5I8!GAj$P9)R"
+(pClj4p3hfjZp`)FcETcrZ2LG2bJfr[k-Vc80r"BfriEFmH,6P'XIK0%NP%IU"A!
+lL1*VqCDLZDAYH5AXL2KDdiq,UD2(,EpVC99mV@P!A"6p-P9Cd@P6fG'd9P8&3aI
+bq`&FL[KDrV"Bc'eCR1K8Ufj$rK2+&23cj6GI&9Lp@Y12L'QM2b@r694*kMBdr55
+pMi6H9(jh+EY9&ZB2kYA[D(YZ9#GGaGPm5081R%*9#2!"&@Icfm9[hYAfr*!!Q,q
++XrQ[e*G"cC'em#[UUe#fIeAE%$!eS0J5-Qp509TLIr65i2VD-kc6Q#bSJXQKRK(
+Qr`%!N!30#e4ME&0SC@aXFbkjFbkj,VNJ*L"6D%aTBJ#3"lp+!*!2!HR'!!*2j!#
+3!aErN!4069"b3eG*43%!VllJ3l#%l`d!N!8#51`!N!BZi3!!Dri!N!C92!B!a6)
+h)e[bY+hEMK`R@r&E`JQRA@jTYYN4IQl+*EHCVAeH8GPkQpTah8mfi4422CR+$Tq
+rm8rjq4djlLE(1X,)*M`**EH2E(,mb)6Y)rX)2m)fZdeSqmMam`JRa`NMV)[m*YY
+1k`NlFTa`)r`*[`JRqb4d(pPN$qb08+$$(c!eZmlbY[6i18Jj*CcmIX,*FE,*FI,
+lb*lJ1F&IepQSXdPfAV'ADefXcR0l0SKYZZf-RGcVBJZlcGakRGFeB!YVd,1Yfqp
+BREQFpMD`JEf$cP"JAZIeIZGhC*m0NLa(GRiDBC[FcSrX1&Nmblad1A+,PjfpQF"
+B!!&hkhQGAAEjf@NmZYRPKQbch-m)Jl`MqpN#`"D!J2(!Pqph&9cA9NUPB'HVe,*
+[`(jHU3rUm'r3m101AGAl+GL[+hAa68V0(r&A$MQjNeAUlV[TH0l`a"rhN!"G0XS
+`5AVMi3jZ$H%3bpr@@qZ01VFr2(h(Sk*5kirqRk)0D(06Ye4[bBfNQdrEH,)DMP6
+%1!XPcGI*h2f6U1bFR`cc4K-h2IlPd#M($r16N!#SLr,G0eVTZVGZfA)bD0RQ")!
+XE-9m!VhA`!BcR8p5fC5!3,jlj)b&26cUYdR!R5Q`8pP(-rl4ID'DHf('GBb#HkE
+#MF$1CZeJDP[P[p)#SET0HdBl2'ZK@S)bh+c8,c+*&(fDB,B@*impp*8,E1l+YG9
+j[VR"f[ak2[b&k)plZRri()mc2jGV4d,2lcl4Ah[bFFi+bP#i0%Yk)h1X3cDIP02
+i(E$R8ZflfY(8(k[B%pIaJ('b%R-UbmfLdb4BhTCCIf0R`@ieMD,Tjh,Tmjf3!2Y
+Edr5Ie6F'SH(r#d#NA%Z03[0Q+f`eR+*YqZmN-%KJkBP0dDkKI!lp,f4UA0iUHlD
+TS`rD&k*P$ceqbi9@8)VaY@8Ib[QGZ+bV$L3")1h`#DY)I+AfE%UE&CAQPQZ8qT!
+!6[kVb!3+YF+1)C88#`FA,KM-K@f$(3XlRSa[J*dA@,Mjma338RkHV(GP6r'pmlh
+#0q-fP#lXc2RZ4V-3kKNV++KMS5XYTb1YTpfbCa'TLX(2AR%03XmbejM1bFJPPV2
+T,eGUZUA)EL-S'2C8UKUpd[!GbqN,MNF[,&UK1h(P)YHCb('aFC-aPElf`-,0S@p
+-j0I9(i4Z@ErHh(+ckaFRSZFA#QB3k$NM,%f%,ZLhl1+V14fli[V*jL(b"#X`JX!
+Xpll5#S6hpKD"IFAY@T*H[(LUYD,JMCh9eC*"@QQ[G"-5UU8MFP2T#1mY(B(Gc5f
+RS[UkY6[G'*64FZHDp[(3NmfY8j9HBIKpCUMRc6!m@HT&Z,%pBhKH&,Zq0!@3!%P
+N#4q6f"JHbi(D"Z8i@qpLrL9XV!Dl"Nk#&4Q6'!1-585#Llf99`K,BP086))68%`
+L%da-)Q0),!FQX&+1VVC6M)I&`KAKX#HfVjN8$)X08X$#FZ"Jc3T)@)i$##Y"[Gd
+C`f!5QD"J%TQ#B"%D%Jb8L18Pdck1IbkUK(dZ,XDp*%J,RX6BZZCc,@&G'ZKDd`8
+UaMQr`6IR6E#YA&'&)4HABTS,62$-459BjU*L(%Z#%Ma))Y2@L,%VAj`LETAL+Sf
+KH*8[HJ'VNU#qZK3`+SN"RiS"jHk+FFP&*CMNSP)mbVGaJNA(VYJd4FL+S598+JE
+(d&5*e'*A!Qf"5d8S)99[Y1[+BV4L9M()!&Fa*%'[[Kj3p#N'TcK@M%l!V"LD)&S
+a0)De5Q5#)CA`hYk+8Dj8[b,89B-hGTD#AUPA#XKALGa8ZJ)'9J)"`TkS[Qk0)E%
+BQZ"L-63&aa*H*!KTmF"%,E'##FhNd4ekeJZYXVAeK$"L8'CCIqK"K1b*2$9c2%V
+dkf9j2@1L1&AbQ@4D%4Sdd8UJj*N%9G*dj#"*XFMe0,eLN!#NjJ)UD4AE+XQY"ii
+e`Cj)bE)B98NeJUG05&fq)!(VFR5+%18,LL"4$Nr`[K`G3hj[F!+G[6FSH[E'@UL
+X0%84rMI'1`C3LBp)3$NZDHebG0cGIF%$"E2YA`lm+3+N2,,rJX&bar5Q0hK,QaC
+)6QmX2+F[X,mG%VC6MNi)6cQk41$,m6'(l`hZ,f9*EPU`jMA*aiDQSSq0kp%XE'K
+C3E1"U94NidTL84b@bM*aE&kBLD1Uj5f,4XA)@$CbN8iiXK%Thl*a*FD9K288Sm$
+&E%J[bE2"2@*J+E4D[T,1&BIeYe44kiUM91e+3LU&648['jG!R@IL2!9f,Ha6BFq
+"I4,XNf'C`AiDl,Q`Cm1ZJEd3pJcB&m0H#RXQl%YJA`Ul'[D2B4N01arfkE#8HMd
+X)deR`Ci1qdaBQG)12J[lH0JR`$i4pP@`Pm0H!AXPl-YKA`Pl&HbVB9m$qc,B9m"
+H$IYDf0I"[Kk@1EFh`Vi*pXf`Ei&p+qcEB0m1q`lBGm*H"RX0l,YJVi@p$TB*dME
+BFE$MB9YKam"1J*d)bcKj#f`$l,4SZLe3@f$r",B*PX'Vjm$@`qCJpi1G$,Xrl!'
+`8f#R`YU*f!0K(b#6@3`KbTbHQH4LC28`f-0Kjm$+M&C`&Hb$BBq!24*f,LbcD!I
+$2Kcf%0L,BCm,qd$Bjm%bEGF"1`[f+0LMBBq"PHQei&VBHE#cBDI$2Jbf%eE'N!!
+$cYFI"$X6pRf`liHp%IBQf2I![KG@CXD#[E!IK(dhl!f`Ym$H#RXEl)GJ2``VmhV
+"IYL2`Yi1qc(BMm0q![D6X-c`A3ql'2D2B'A',mM!RJ6lD0M(`#k$lBBp%CCacY0
+J6i#p"2B&X!YKA`Ml)YMjX!YJ(`Yl-Zabf"@`Tm#H#VX)pMMBPE#VB"m"qdKBT[c
+-5*hAi9![qSmk8A2kJ&kRYm%!X*IDJJ(8P4T63fT*IF&1F"GFTXjJ'Ed2jY$Rp!D
+B$SD"(q!%@!4fdH[d'[e(,i*lB!Zp!6D"(r30r@Ha!lbJ$fh[d%[J#(J%eS"2B"U
+B!hk"Vf!HH!LHJN2J'lh0S8r"26!4I!8l`6c`&i`#%m!!-!eX"UIJ%H!XZ!Q1JJe
+J&aJ1jS)0i!Mm!Pi#Gi&R`%(!'l!DlJ)f`hr!II!GV)HAJ12J2$`)22BB('QbDE!
+0X2["6SHG$0X-f`Bl&[BJf*Q`(E$d06dk1aVkRSAbKl!Cf#cX40Kkf"aX!f`EE#Y
+X#bbG3IFFHJ'EKMU6"bIP)CE(d!rd!$J"AS!IC1"h114[XBYkf2kh0H034qT*lDL
+KAq&3NpQc@Bj$B0YK'f!lB'I"(Laadf#R`cE$cSKUQ"`I`!)'(mcjhpPm,m"a@eI
+-%A4USqM9C90f@PqheD*'NTc6fh,kfXBEb0IZhfT4(2bqIcG#[$1QZXdN[cpJjrk
+*3JllNm@"I-fc#0Jc+ZMYQcNdFD5)LV5k*`@hTB6QUfYUAp0Gf'39U9bZc!-+2#&
+l80`+KHKB0QXC,GKLV@@%pLk3!0EL&mS"Gh*3-5`c3l'!BA*3,5a@SEVBI&"2BC`
+F9&)B+JGebLTr+*X`4!kUT@A6+*'@MD1Q@I4(1820iA`1&Jl2q4YB&![1Yf"45MM
+r$S[#3RQTSeQ%*6i8&G35I#K0q2'KXU$+i%1YSIli8*&34[#K6U%Ni80&3XR"KiU
+,BS-203lP"Kq+,+S02K4$mX@(!JMQik1@U$AirJirU&$ilXB2+JqqIm-2DJIY55e
+4TI"4#j3aI+K6U&Ri8(a3Zr#K+1NbN3b9(e3SI#MCe"`ILLfU%cl34&@H$09Xe#P
+mp#J+($l86K3iI035K3lIAq%(93hIRILK*[Mq#6qSBIKqK"rk#hJ")m!6I23KUKS
+qkSZkKXmUD[K3Ue$Fm+&JSE,K3kP(QF1(!XbGq-!Be$Ym+0f+T&R@6*A1l'2iJ@A
+LZ`XrU)[irK8r5JlVL'ZSI2MS@rS,(r8#(r#KX+(-i81C4+R$"di3L`q9('84(qS
+ppF5(HSrUL!rm3rA%Kj+-)SR[-rK"%FAh&F&HI1!%+LLq(q)(M!+L`@[UJ!qX"!I
+`J8dSTIM!!T4@I239+LSqkSLULJpe%884(`SJIRbSkkL$q*K-3&h%4bhT6AcJ")S
+X2[!Ep4(I"Z%,q-"XF-P5#C4EI1!iUL3qkS4DLBmq4`A'4jhS,hc8J[VJ!`p3-[(
+"PTMSm08F0MqYYK`VY!`E8dbl8r!!U%ZV3p-[@ii4[TZq2d&0fVBYdDP"i6mc(Ge
+HD(9UCARZ'!CZEV!E`Z#pk5f&623@@%&kbhdl(`[VQr)k@D&,9BY6m5b@+(kVc88
+CPmVM%eJGp4Y&,pR5jKAB%MCaE%[BqY,9'%"2&S9*h*)NLLeKIIh0,1A`fGPrNGT
+6h$5CQ8haCbVUJBU6)ZM`-9[#VY-He[kF'KVI#PRT63r3m86-+1aNNS-NX*rV&0Q
+C4F8*BkLS3mE$KA,lmX!mJdGQf%m#@QF,rYQT2bI@)[SB)FF'f2Nr%j!!V,+!4l4
+(SlT"aX9'P[0X!h2!CrL'[d9PeSYVV4Q0&p[!GUaYE1m`!lIIahKi%%El(1GlAK[
+%K6N&qPHBJAJN-Zr%Xkah)jcVV0ibdTe6G#ZqS-f"1[!NSf!Lc5$IPZhUVJ-aR%2
+[8JbJQrq9kBjq"f2BCdGKmpIPfr4dj4BTdH(d58+DZLh5R'0V1)*F)4T*AQX@pEJ
+AmfYhiN)(Sd@1'hH19bMaQRPepA9"b4j*9MTJR98`3XYeN!#[H105,9d[ATcG[[P
++!@bZl9IUf+&KjVH$-3iS@((SXHdDTP6F)eIQ+d8Ab$@Q#maXZI&%r53jZ-CCC#a
+FELeC89b8VS4TQiQl[4*Y!MY2V+b8U2DfXZIkS8lf[X#`EGGe8-ae(R%M'UdR8T`
+kUBjAaX'$H&3mk%jR@eV'FT!!3I2BRH4X#A"R"DlDdAh&1db$&1S#Z#l0V4phfmU
+S8bZ$Yj!![3PHhJjNFCf`HU36SMK3jS6fpXKEl+am[2@@N!"-)P*SN!!3pCI`VLp
+p[5[1Z(!pC8Nh2pJq-@d5"4pk["*4P%XSKU[m-J4T1Eh(`"l0''&Q6hV9lSe5S%V
+QIVL"K%ZqFrBceT%0FHGM)c#!Y"6ZLjV%A8&pf2m3A`(UFD[&FUVPk!%iQJ4Da14
+'8eB$Hk@#N@%DR$D%)`8'U5*-6['j5+ZLG-3K5c2@Q8("Yl``ESK#3$lRq"DED#(
+'e11FLC[L+K8M6AH93dUm"QDhB!ei@hkc3i+p#pE%V1"-e`PFfk`,`[lHJ*c[(0a
+r8R[c6DB64Rk6d,*m)h`qTj2"4%QN@hYJj+a*YHPX8h1YAY[8f0Q)hqkfG+H-9[P
+5cQpRGB[lkDd+(X9UN!"FBHGGhBS+TdReU9CbjI34A5Y4VFK(%Q&@D&-q%PSrF[d
+@&H`h-aXp%`pj29$+ab4IL!bClYY4qA+Pa$NMUU82B4V@Kj!!B65C*E-118`DQS(
+4`8NYkCSaicV2'8[Ih*(1R)F(B[V"9c20hDq4jqH)I"5[Er"09#6+jKF65S+b9Tl
+lriMZ*Sck%Cd"CHDLImpbE)$N`[bdQ80RN!$8$*!!mVS!$K1NCR,8AXhSU*'3!!L
+!FHlNVNaRV$PeKfrQf)l"YQA-d(G[0[e0JFj'DmpIhU%[dZS(lp2U0kcUbZSGV59
+eKClRhi,D"5Z9YJkEX!jkY'E"f[J9"ST+"XTQr&5QhM+(8LYh2kPfl0JaBX2RlZe
+44imH(EG[`240l,pKeki6GpaRUcAY[5[0hIpJEhr``B5%21ha4p3GI1L2p4,J`pE
+FJeNemIl'`[l%R@I-q$K@crfKV%(`Z4hr%eYYEqAq4c`4@rf*["e&rJeE,ILG6If
+eZ1(iAVCDblRUMmp3(@UekXqP&TIQY512AIAER9prr8I[UqEGImqZ[YR4Xd0jf$e
+-jXe1BY(Zd0ckYark'6BIqN,H+*3lQ!#3!,ArB9*Hhcc&PXl)AGUr%A,[EA32'0)
+iF`pidc4c$hM%0Y$U2@(e(M#VCI3HZmDXI!qieMTj6j`hZ-Ifd9Sqi1,ibAXZUGj
+M0LVrY)j-)cem+Zq#JleSamhF`jkd4mlF`eD"*D2hp)dAQ,Imj0q190R$X[8H2p$
+b$&rcmFY06(X!*MjDaeE491rh`8emL!+D[",0E&6CHH,pF(k!ZHKB!3d(9-FXTA(
+rUTemPQ1QX12M"9&!T42$$jcFEZ12k-3q,6VUa1,U1l-96rE6jV@jC,QG8kr0#`e
+PTqe2lf(fGd3le,RH*mcF`mlN+C1DCC`hfZ[8mjUUh)0@1[qm"LT4l-apa-`pD+8
+$@[1ZHb3H6AUNMK*[jM"UfVA%Sb'2e&[LkBZ4HNXmZl0(kmJqj`(0[(!2QdF(Y2$
+#2H$&D4`!-2Y$L[R`#Jjl$kaM"(mNLThE!l-*KA[Bf$%`ke#iK`dI!c--KA[Bicf
+LQGplMiIqH-hHcq&&f-B8R@4,FS&i9ULdjf`6XTIQh,mGVR#'-AMRaL+6'Jpb5&I
+hdlk!Fr9j!$b8SA+I$q!&X(k5JmKURml$%,"pAJmRILD3!%m#,Rd)0,(kZ!0YM6c
+)H*ifNr#i,11*0T0`G11$fdcbZqdMXGqHdFdNkIfe[(IA*kj(rlhhjVeh1m[Q[[%
+(p0rZHr`(GUJ(Ulfk%81#iD5j#GZ@kT[iGNrBZXfAr41k2ZLGDJFYNeF"&ADU$5N
+AIJ$fA2*[9Lj'eBEdIcGlV[VlmpjElpr8`hq3!2IZI@C$2GPrAfdA@jT2pC6c3"5
+ZE5Z,Yj&&eXZ`VEckjKdIh9D6`Y0+Gjiaidp6mG4T,Z`$mAqm3!ZQe0U4cFSEbl5
+`*hCdM6cV-T`lqU)HQDPCe0EHc1F[k[mXqHq3!2q$UcGRDNkm`%H#Z%L5VZFr1aN
++&fB['RqKM`bYD9E0FYPNr[-35[e[P@6-2I,I*[rM*AkFh$pGlVIj6"1rZ8rZDC!
+!rlCU-HUL*c[NRlQLTC2Efq@rSATE`r[(RYNM(D3Cf6+E#XLG-k4#TR,LRmPr9SS
+8FQQHce`+Vqq*hXkM"C!!bkE)rp468kck1$Z[cr&'c%a[d6!m!Lm&NcJb(GQ*+[G
+`aFLZ8lRRClY6!8Ijj8@Nd6hQHB$ZZ*fMFJmML[Np+jPApmS!ir,,kdUMHl+[lT@
+"2XM[[-PlA(,3#rRYR,Q(r62(cpc$ATj(cGc$Qe"'pX$)2HcP'GQcSUp%AC[![ir
+&4h!J2(!jmhrcpPpLPr4U[NSj1EkDp3hHPE2e[B$Y543[jK(dbX,@`EE#MS'YKmh
+"0X!f`EE"MS8G$kZ[1Hdj%8kDe`XB*5*XD1Jc(G1h#Jh+Y&f[M"GSGAVaZmAA0q!
+G@[+XS2`0AV*MC+"kiX$6M+5b$Yq'!mKhZ85ikD0)bFl)HrZAphYmkeqR[,l3TiB
+1)@82QBSSiB!ESr+R)B("!AP29fGe!m$b%#rEA1-A4`E61U2A2(DZYT`'pHB0rLi
+F-"06ScKJrXiVPpd%VfD[i8$$Ah&!f+1[M#ND(*!!9apd0[#*VQ[#j$EGd1#![0Z
+hXk%KirTQLiAANEB[V9YHYbaT$4&#$cM!FPLQVmfD9"YT(!mFh$idK2(M'a2@3+&
+i*Q,8b+i+MP$K#+##[16r)Dr2UrR3cRiBfbfL`SQ$(ri1hXCr,0qilfmllE,[)im
++Fm%9IUa8H@59XjrY,1"kT!39ZM$[RaNHrY@K"$G-m&#mLIE,!b-HXpNSI9J#-Eb
+d*Sfc$bHS2P`KQYM2bF5qG`K!2"`RHV"5[,R"e`B$-!PK2jkic3heLA!6qhFQaNh
+XJ`-H[iRpl[jHl!GZEh-+GRma)B`dr(TLhdF'!KB(r(!6qcFNaNhXhaP0l'I8qkG
+IDMSehSMkKm0$9RKpJ"mJMk@CpYARla&Ufpj@TJC+CI[Z@*TVEdN)b'0PZLNCS+i
+RjcXQ-pbCaiVQlXkkhT)U"%'pd[k`A9fdGR5MIq1Zb,I!X'dAVd!ibE3VVlX*[hT
+2j![cm45EbH2-FrR+iaUkPU3A,hkp1f`H$ekF&*!!ajD#r$b2,BrDqApjE%jNHaj
+RErE8S3HfaIekdp1PiGq[dZLIp!6QrLlDV6V-VHSb6(XdVLP'2ETKA`hLEpB1lHr
+4lVTiH5@2TrbhAhP1J-PM5hZ3!%Hh%43-qh4KScc@m*N6AS!mcMaEf9TGH8k-c@-
+)LEER-Icd%pUeGN`HkeAT$%j,'HB(C48"Y3e0FAT91M[0BlKMd4Y-jLbhd$pGY1%
+$rhK'i,r"'VEQXEjNpjkrTl[jI&8PM`[k%`,bi-a"NrbZVVc(Bq39-Ii2aLf9lE[
+M2XBpQ)FhJ(%[@lefqQNM5h2VTq[Kq@$Z!e@pMlQ2j,'0ZBrNXBfjhj2(9ZCHbk2
+'h$R+h-2EjrFN!$$hMIAi&A-I,1a1jPl,BaYchjM',jPl,BpKjLjjM*!!piLjRph
+hrllhIM"ZHFe5hahh-Hk"2$LH!-DpdR+@I9cI[1+D5FEGp$CMNM`f)m1pM'NNMfe
+-jjimYM+G@Klh)[R'2(k*j,8mKN&2mT!![Vq(QFqaVE0S99!N0R@)j(&HlmBcH5c
+Vh6LG4e2QM3Hc0fBbkGDr`pr!q4RLGF@GH%mHkmja4FQ$&j`bChSq4Sl5iVU12X[
+FN!!380HpR-&ak@&1[Mf2'R)1pjRVM`[1YYR26N[d,,e0'$-f8KrA1!p"94T3SDS
+RVd,G09"4(ld!HA6C3D!!-3)J!hN)eP2Ai)a1EP4$,d!pM0VR"FM$URe$H@aAqji
+5PQfe&fq9)ip,X4%Y[%-l![rNcpGV!`FpY8[Emm5q[GZdRGF46!l!Ne(14IccY6f
+20fN$cdFEe%`H6f8A$GCMY-p8C9RVRHjA*"B$4*[bi&f&!CqIZ,I[MFVL"HKASl*
+i!I,J4(!@r+HZ*JpTMq"rrI%BecRhd,-`NmQpmp5jmZ(K@$AU%Fa,RTKmk-VHH9U
+ELSlYXD&M1)`A))r&'rd0GE#rUbZXe&maXcKdUP`S2ANZp)Iqb(1K2r5V2f"@c(#
+K[IJ"!TpZHG-61+0ep8mSeacP9,q[UmPMq-@MShQ-2"6a`15h'DqKXjhTq*9Q[2B
+Hcp+-erRH@ACDUkZ2B-TECXAf(Jr)V0K'!2RPV0J!8[X#CX8+cfVZZk3KHB+jHbU
+BU4F!1Id+5$9kDSYb2##DMXGP8ml3m4"S-AkJ66PlMfGT8mjf,DB[%5r"aTh04cI
+ZE$lqVBdlYI(rS#DTB[jr'i2cEq`4Z*GjEFcM9maVX#!lQ9FY$qr%IS6Yc+X[%Er
+!RS8S$r2NjB&$%V+00#)&Qqla!c!#NiGABZr$2[A$5cr@[6G!H*[R2Y(#5cm16)a
+lk3GmS&RQLaVaahc4Q2Hd$r0&(VUh[bFi)&lI'L8`1*!!6BbE-r[jI*([E-kX-6&
+ZcXc-&hRIjXbLq5*Ih*aCLjSerEUYi6-ZhC,"jGIQVE*RQjf&%iY`IA#6Dfa*@h2
+qP3iqQ-1E-4BhhY")feC9Dm`V6*CIhU%[dZS(lp2U0kcUbZSGV59eKClRhi,D"5Z
+9YQirRUVpqCS&De@IhT@0%Y+hGQIdeN(aE%LYh2fN'KiHMYcb(cjhEmqBhpR8AiX
+EMUr@G#6RUMmq3h@SeDSrPeTFQYH12(E9EhGqrI8I[DqDGrmpZrTQ4mm1jL&l8r`
+[,+(RC,!L8bD$cHGp1C0UdpQQjPUpYUQaXa'rh@hTcYT%PIVVQrZR#N`+)L53!""
+UpeIZi3heVC9lFRc5I1'Lr$h6m([#j$dZ1EPR1RiAcY`c!lq,+[FdM0pc5I8HAS%
+bBDU1KAYQiRI*k$ep"%(ZkF"[if3qm6fcm0X`Fmr"q'fDZHF3r1D5!qlCTe)iXT0
+V3Q@SSAeK21C`k0XTb-9,iMH'Y1cV2T!!"&#5ih'Fma4Y3*ZEZZAB$GNAq"HYLM&
+(ITZLal'dCr[2,'NIcYT8%8jDep5qTVZ`b5VQI(IMq[aV,d(`TVe8q16SGE[Q0,C
+qKEr9pjGNPQb0I1(45k**"!r6qdXHXRA9f,XhT4mI0I95BBRG`(l0,,P9eeimM#%
+a2pK,K5XiAAfTF)V6I[1A#RX4Q,XIk"9V3mbGBeqXqmdMp3N!c0d[p9,K[Afr6m[
+`8Z([I[XTX08"&DTkmLV8c-'+qZJ&b+2b8Z&+(Y8AfDDUQ&%0[3$e-'UI&b!2UrB
+0jE&Gl61[Fedb-2T5iFbF9$ImmP,Kc,c2(9)r6eflp+Af!bRpm01i8PiU21jRL2q
+ce,8,YkIQID'qNSGjRHYJ28ElV2*5i8SHeCF+ThP8ALUmTaj'CI%#p+Y4@E`!HA#
++,aAH8eH64r*5i6ejl#2D[&6B-lH*-rc0Vb0Iq2@lG[,I3l@*dr4[Y)Pc6E"*Vdc
+8HpFfFDBilB2Ia2PljZj$fX3CVG[h"c"hRpBQcT'qhkGPf-4jmj8rJUVdLif$H4A
+UM6XVkU-A))rl0h'QUTK4$Ed!p6"URaFJ$k[f$H@aAHflCa2RXEHIfX4jl+dR0h%
+1eQ1dcqlIa*RQFImQcM32Sl*i!IV9U#aHJ$`iZcGaTR8eHIak%fHDalk9cLE1aD2
+!eVJVm[91q,rfRXJAjJm2m0r$T#pZH'$Ef&kRN!$qRKI@Q4lGX+m'm6GVKrEhD(G
+G[,b5KcGU%qI2phR&QcJV10flLE1%dhlc6CaH"1EZ"jV5hXEF`p[Rpb3!-(I[d5E
+1AdaAlqhlI9U'6CaVR)HJ+JfS80@69k(Z'ULSMek!2#UE1#Yjp'iF,+PL4MAd!Y6
+$U(eHJ$cF*Xj0H@aAqmcfZ3rN4MGaKRGS4q#A6CcK`%&2ADAYU9faGjZfmcU#L@c
+LE(-3rhaYcf@2D!22iljiqpaJ28ElV,+*Xj*(lbE18Kk96CalkQ&8&Lp![aU9a3Z
+3!!HRZ)Pc6ee0(XNQcMejl#2DE1,-`@E9((VNN@DY5Q[iGiRpB)Gh[)A!JFiqdc&
+pUj!!f!B)B3SrGF5"TaR*E4KJF!!q8+p5$I%Bb[*qMibbXp8dLUBI*+N"3fKMMMm
+mJ3-L9Mc$m#dc33d*3Zjcb"!(cJjppfE6ha6SqG"`LSCIK-`0'Pc8N!$*Yq[TKY@
+@dk$H[-(IK31L&qEH`J(cGekjl$S0ZIjHfbVSE8l"lLmQK*%'J`-0Im8"BBpH-K#
+`10")[I"-,&YF%bDh5BEKTF#"*Z*!CmEec4DXh9b[,keEAVFXD3d4$"pSIZrBmZE
+fVIfkMi2cjRCr(!kB[8$a#GAdq*S(jkbq-3L0XeML36KKp)UA0HGR5hd`KdRRaBd
+h00+f9EI@Qpd"bbr[d"GTpB2hDI8E9R9PpBl@NVT#cr0[3Hf#P8TEYeqTMcjDXf#
+YkY1lXY*jjQ6deN(aE%LYh2fN'KiHMYcb(cjhEmqBhpR8AiXEMUr@G#6RUMmq3h@
+SeDSrPeTFQYH12(E9EhGqrI8I[DqDGrmpZrTQ4mm1jT%l#%UceV&#bl#YVHGfGf`
+m(J"'Y$SdrE,P'1'lkCZh5IJ3Z)5(i`MlRjLhbTjYkTd&@emBP+lf[-+LX5Z)LqE
+-@[EKF8MI3BJXGPKe)!'K0Z%RFG4hTICX5TX9eH8@+"RlkqKQH@@`IYkA-kNfR@e
+UVY9VQaSl'r(EhCEZV%eLD31,!`I#@UbI"jX9hmQ`9ZeLadkpq&i-blZR10I!STY
+`2JAE+,i[`cD*lapKQb9PmQN4hd(iD48IZ$9'I+IMCkcid%AEa(FjIKJY`(FMIXD
+,lbra-d&mhm$242(p$eXpmQ9Birh%abkYbH*EM*rpaEF@2l*hbrKHJ*mTiRXpIUD
++li25,rMZ`-m$a!I+6iYp@IE'G2(0a-m-m4f((j8+XphiSIliRSiIlX(h-[adL1q
+Gq*NP[NrLjf$ar5eq$K(I[q"(SDZ126aEI04&@8NGHrT"iMX&2kTBelRi18amj(f
+iq-KlM[KJ,3m4heIa3qrJqajqMSappHcEZH)Mjk2%p`MmQ2I5Lqp8r"`M2NLYUU[
+eGq,RSH*lKq!2[SrLjf(Lqa*qp2%6p82iHAMXba&(k#Pmp!2jiL2QNH*EJ4rP4$R
+f0bYfm&f-RrRLZ`Sr1S@EqaCq9"r22B)IRBE0X3B,aAFAIR5k,2F5INk-I3h%*Yh
+mf-!qH,6ib"qF`8IrkAam!l9SR8CZf)kITH)$EaiM[[IM*e,*JMRI`ip+iJe(mI0
+BmIfcB$A`#`BX&amB32hadEINMSqkdiriq&mT2LDD`59mi0pTiRX6IX"NI1$Iim3
+(rMeHI0r&ca0LAa-arSRL!a0ALimqee9!6Db&,ZKTiUb"k[Y01r#M-`00c&[hT6A
+GMam9-TTqJKrGVp9%(0,0$FhN%MVIdda-T0ra8@r9rCZC[qi,Dpk#(jhLE[ibIR5
+QX*NUj,RLSmEJ*$lkAVAKjTIa!fl,D5%Id)Qe&Z+GcNkdX1G9`'PK(AA'Sq8fr$a
+,I'r%ciAL%l8Jf#`qm)Eki2X(r1MSC#Xjfjq+MlbI)ck`'%c$"bim9hc8QRcaJ6'
+-LZ"l!hiZ%4pjdqri[S#I&iV[QrMK6R`r`!qm6miBmV&,a3H[H)Ri`%Vk&api!DI
+!4qeH,MjkqM,aL4)F%2rab8VQi%[Lqdrm[#VfM58hJrIKSlId"GeML9YALSrH!m2
+aF4HpM1mQr1M1[l'2iHGUmAdE2kq0I@hNY+m6(a`-l-8(6k"(m)'$p#NqqSdDiRX
+,IYiX[NrJ"cqqVq(RVH,l-AlH&[['N8rUAX"aj%[`(AcJ1j`,(aJ%TmC(Rla,I2#
+5DmAh'IaF*lkramqlBppiBX0la!IfAbmqqZB'mC%VZH!$+pQ#M3pFJ'[JSarJerK
+Z`3ppK1qcq&'&IMah9(j!I2q&(hL"R!RNfpb*$djfUrMJBlH*$q`(cr&4l`q,MaU
+!4IMS*I!"(c(`3AaJrqhLJh0m,2C0*1IqZ2LS2If)$qi+GmB(Ce-9EL,j#AU&TqR
+8$AA`N62#[5DTFK"@ThhVKMl9U9+,`)UEYb'bX'1MEZJcd$UQ)5,,519RK31LcND
+NXVlScY1!+I1!Fif5Te&M6H5TB-32!JVN'%P@,[)dF*lf&bQ*4ARDb1MNb"+D24p
+lN!!c"kR81$8e*$E1LL0[*kijr6`NJp!l$bIk@B8Yd-McVSSMAd&-Gp0P'6,FaA(
+N3kPN@I8YZ)#DcE`imR(NA&D,LeMkQ$LbMFcI+R14eR"%(2PbmM'Vd`9cb'`dcjZ
+)P&De#pT`Cje%[SMBVaUHA)&+-#Q1R%,%9d92$PamDKcjXFIK8he2L)!S0j0kiXK
+A-hY9qq5!lh9aj11*bkVp5AI!A!k))dmKNUX5+!IFeilkm-2`U5iSI8-AMSdM2d)
+QU#UKT!J(rh3Fq5Pb6G8-TB%+(A8#kkN+SP3!IDBeM[`XApZ[HU)dZY3cI#+1[*'
+-5Y9&U3$F3l[M[Fa6Y8Dj$f9$UcDCl%b94kN!YIQ,1,+&[&ae5"(hK(Q(Pm54(b4
+DU#STR3[hqfJFq@eU%DT4#P6!bZI%N5(CVLU@)Rm*&QDNRY1T'DPq+H+6-,9--Bl
+m$k+3!+UCJISqY+LM[KK(6U-f)0UQS,%`rEQXl!(P-#"1+`l@$A@MBUH#McHmVaa
+'@h*Fj'R)XC(-q1KbD&09XC%Gck"r-cpQjmUG)(JbSe"AaGa[%4088D@ImjKl$2A
+,r#JQ#SAHH6Q9$&9E"AcKm)UjAk6HSGUV("LP)YkjC1kUa%SAJZ@+%*1S[kSZ+l8
+"V44clk"US5UYG'%"FbmR,eI09L),Q,Z"D1''$lV4paCclbBI9MeAlU6E&9@H6FE
+YCNiDH)GLlQdrJ%qehN#p$-A@BZiel%3hUaa5Ke$-[C!!U+3kX23RADLBqbbU1DS
++UmDR(E@3!2UADX452Y4CaGc[8)e3a9L+40D+Z9G6ae,p@1j%+G@1ZTjXAp9NLD6
+ZLP&I)ZDUYL`#XU#+aGb!@+K+Xpb*MU6Gm89LQZV1%NQP,AD!'kT#5bRJ'SUjee%
+cG41r#c'qC6(h@e3r9+'@Y1"!LVP[TYkXHVANLF+LQ(XVle2e@Q44kAD,ZGqQrZ)
+HmV3DM-pLlVQr4B!Ufi&@KKjR-AFLX8FdlEUKpDMjA(JFjLV$&$BV1Z2CB#5j9B+
+j,[*dm-#CB,0"[@#ZMHai'KbUJleL-6HCp`V*4V9[$U2bUHUk($3iaGcEb!G8DjI
+XBD*kjq1)mhBD+@JKBLRQ[TVBVMUmS-S24l(`Fe6"9*8A3%$c8B3iL(UQfj496p9
+G-IG5pTfED-p`2N!apaV@e'fcbR)L3r2m#T959I0&SKAYbQ,Z!mJ(h1DB,"8b4CA
+h-8G9qJ9cZ8-aG`)Vl9jmF$Akdf,ZhH6J1J8J"ie9-IFLGSV1"%LP[cq+Z9hdZ3e
+k1I*DlDKR%BRFpV)QpSPLlN[*HA9k3'4qf,9LlVZT-HSXJ@!((%)lkJjU"6TC)*(
+JQQ,8&@3NG[3qF+"`@X`pKbLV8`Gb*pUHGXG&e2"d"N'k!j9GUhB"F83R%U3fp*G
+LlKH)[cUI)!+kU2X@Fap'(UA6#Y+Se&-aG`he5TeG%)5%b5RQ(NJ&@#FC4%BAIQ)
+ap`kb#jeV%2&FXV'Bqh'bHCeb#,42!&8XjKj($9-k40LX-*!!ZCa1X*LVfSf`@G'
+&cN)0``("h(bNB%#'#UN`B)1j6Zma6!%HC$%hL64X6r[QViNE1QNK&8#(9m`G5dD
+MFaH#KI5ahRN9'CP1B3KBdDf+Z4G3fG'C$+NbM-SL(MaA*c3%LHKl4BLh8hqfUjZ
+$TH5#LVPAF+,,V9F1141KQ$Z$f1&f04a&Y9Ac[*JFh'f$Z"MpBM(hJCb,F([aMb(
+5+kTmJ`MTaPH2T(k[Q$Z2R-2Z@!rRJB90,X@4AbFlGlXmc9b@BZlhU35jr5pcUD)
+VjVk"16[Gm%MLV(E8Fri%RpXC-CIpTCKlqqrJFj[Rcb"q+ZDqLE--6VNmQP0%9Ue
+$9h+EUqB5qa5MEL(,GTVQ1Z4T-II2UA$S")Td&(a0Zq09R'e`Z`VQ8Q(3UKh)6YI
+T&+N0(&Sap`M@aHQYjf-+a@,Z&839YrAM%ZVcLVR2T%VP"T'2MTLreSEZF*Y,AS"
+D@-cp(KQRcVM)%)RJY-AFk84MRAJ*Y+p"(l5BZiV+SmbrL!BXfGj+hR#5B+kUSS+
+XSSpFKXKF56$A4Di!FR93q6K--0G'GK`&VRH3!$0Bc(9hVJ*ZA!pqdqbA`lja$IK
+8)2&98(Bb(bYl!Hl-4ki%ehS*TM,#Kh,Y33Kf$K,TT)l36G"(9HMmRFY4e3iLh+f
+S!$f@9m3%(@C4khZl4$VH[K,h2BL+a'b*G1aL*AMl#Q,XZb3bf8Kb#(%YkX+'$*8
+'Yh6Y%#SQ8HFfIZ3T8L%E@8Gp-%,*KKHTNHK8NHJhi0SCFH6GC"SkBb3XKQP!cI0
+jj0BkF56iLCi@jGR`3r*[R6m5VN)24(NfANTY6DH4T'rS!FhcR94eG$C*q!#+NHC
+j$R&0*j@%@+1%D*jIilbTcLh4CrPkISJX3DHB"&$JcjVR(Db6cM3*#U%M4(NfcQD
+11Z%NiJmiShdcLlfQmdk#3LLZQZGrF`T9TjqNRR5Gj[N$mJkCK4)F%0ai"R99LfZ
+UkBY+Fi$5PJ)rRAlM)PHKCpDc8be#f-L1Sp!FCP%lYlMQlP`1,*p&hL$BBE$3c3k
+BHU)q4M`UDj!!CHYXPJ`Mb&58DKIC1eJeRG3+0+TSLZ$CUmQBG@iVd&i!$l))rNV
+QUP0F8NY33ERAPmJVGDC,+N"r4Y`V@dr-eJN[b36H%E'Bl(ELTmjlbCfI(q9HAk@
+qU00I3LVK34(hb[B5jh8@61k%L8AF+pY$K0(*-%'9JUlrBfT'lQdB,`1b+[I+pT(
+MkY5Bb%p`S1M1V%HQVM0N%JQ1+5HkN3a6*mS#l5VJKI,Fl!l1DHTmQ@JNU&RD(Cq
+QKUc6CN)$d6XLl-KHH!3qR6d6Q3Z'U28mL8LNNfK5!HDe)RDH[BbcEMUA*RI#Sj3
+aANY8e5NeZC-j+Q@-Rk6@TM0V!ReS&a&Mc*Bj3k)6E)&@"bh*-XBl1DIQhVRa'R)
+0CB`r)YlSG*Z!(6J3G8HfMTaACpd#E3Q`64PMGJGhCqMNQr3RHNfNGf4A%Tpd$Nj
+i,XLU9EZC'VK1a3RSdd@4hT(p009+RC%6'%-Y8EAK)q6Y1M%Rc33UG*H$9fB1&P#
+TXT'*-YV&HYV)K(YeNA[Cb!4cMb&A'3GH#&p20*q6f,QAbCdDqAm!N!-K)3jdBfa
+0B@03FQpUC@0dF`#3&Y%"J!*L!hF!N!-"!!)JN`#3"aB!N!1'!!!#!2q3"!-!V6C
+3$,#%lk8!N!8-8kd!N!8#6elrerrl!*!'F!rhL`!!:
diff --git a/mac/tclMacResource.c b/mac/tclMacResource.c
new file mode 100644
index 0000000..db06571
--- /dev/null
+++ b/mac/tclMacResource.c
@@ -0,0 +1,2165 @@
+/*
+ * tclMacResource.c --
+ *
+ * This file contains several commands that manipulate or use
+ * Macintosh resources. Included are extensions to the "source"
+ * command, the mac specific "beep" and "resource" commands, and
+ * administration for open resource file references.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacResource.c 1.35 97/11/24 15:03:58
+ */
+
+#include <Errors.h>
+#include <FSpCompat.h>
+#include <Processes.h>
+#include <Resources.h>
+#include <Sound.h>
+#include <Strings.h>
+#include <Traps.h>
+#include <LowMem.h>
+
+#include "FullPath.h"
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclMac.h"
+#include "tclMacInt.h"
+#include "tclMacPort.h"
+
+/*
+ * This flag tells the RegisterResource function to insert the
+ * resource into the tail of the resource fork list. Needed only
+ * Resource_Init.
+ */
+
+#define TCL_RESOURCE_INSERT_TAIL 1
+/*
+ * 2 is taken by TCL_RESOURCE_DONT_CLOSE
+ * which is the only public flag to TclMacRegisterResourceFork.
+ */
+
+#define TCL_RESOURCE_CHECK_IF_OPEN 4
+
+/*
+ * Pass this in the mode parameter of SetSoundVolume to determine
+ * which volume to set.
+ */
+
+enum WhichVolume {
+ SYS_BEEP_VOLUME, /* This sets the volume for SysBeep calls */
+ DEFAULT_SND_VOLUME, /* This one for SndPlay calls */
+ RESET_VOLUME /* And this undoes the last call to SetSoundVolume */
+};
+
+/*
+ * Hash table to track open resource files.
+ */
+
+typedef struct OpenResourceFork {
+ short fileRef;
+ int flags;
+} OpenResourceFork;
+
+
+
+static Tcl_HashTable nameTable; /* Id to process number mapping. */
+static Tcl_HashTable resourceTable; /* Process number to id mapping. */
+static Tcl_Obj *resourceForkList; /* Ordered list of resource forks */
+static int appResourceIndex; /* This is the index of the application*
+ * in the list of resource forks */
+static int newId = 0; /* Id source. */
+static int initialized = 0; /* 0 means static structures haven't
+ * been initialized yet. */
+static int osTypeInit = 0; /* 0 means Tcl object of osType hasn't
+ * been initialized yet. */
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static void DupOSTypeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
+ Tcl_Obj *copyPtr));
+static void ResourceInit _ANSI_ARGS_((void));
+static void BuildResourceForkList _ANSI_ARGS_((void));
+static int SetOSTypeFromAny _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr));
+static void UpdateStringOfOSType _ANSI_ARGS_((Tcl_Obj *objPtr));
+static OpenResourceFork* GetRsrcRefFromObj _ANSI_ARGS_((Tcl_Obj *objPtr,
+ int okayOnReadOnly, const char *operation,
+ Tcl_Obj *resultPtr));
+
+static void SetSoundVolume(int volume, enum WhichVolume mode);
+
+/*
+ * The structures below defines the Tcl object type defined in this file by
+ * means of procedures that can be invoked by generic object code.
+ */
+
+static Tcl_ObjType osType = {
+ "ostype", /* name */
+ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
+ DupOSTypeInternalRep, /* dupIntRepProc */
+ UpdateStringOfOSType, /* updateStringProc */
+ SetOSTypeFromAny /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ResourceObjCmd --
+ *
+ * This procedure is invoked to process the "resource" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_ResourceObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
+{
+ Tcl_Obj *resultPtr, *objPtr;
+ int index, result;
+ long fileRef, rsrcId;
+ FSSpec fileSpec;
+ Tcl_DString buffer;
+ char *nativeName;
+ char *stringPtr;
+ char errbuf[16];
+ OpenResourceFork *resourceRef;
+ Handle resource = NULL;
+ OSErr err;
+ int count, i, limitSearch = false, length;
+ short id, saveRef, resInfo;
+ Str255 theName;
+ OSType rezType;
+ int gotInt, releaseIt = 0, force;
+ char *resourceId = NULL;
+ long size;
+ char macPermision;
+ int mode;
+
+ static char *switches[] = {"close", "delete" ,"files", "list",
+ "open", "read", "types", "write", (char *) NULL
+ };
+
+ enum {
+ RESOURCE_CLOSE, RESOURCE_DELETE, RESOURCE_FILES, RESOURCE_LIST,
+ RESOURCE_OPEN, RESOURCE_READ, RESOURCE_TYPES, RESOURCE_WRITE
+ };
+
+ static char *writeSwitches[] = {
+ "-id", "-name", "-file", "-force", (char *) NULL
+ };
+
+ enum {
+ RESOURCE_WRITE_ID, RESOURCE_WRITE_NAME,
+ RESOURCE_WRITE_FILE, RESOURCE_FORCE
+ };
+
+ static char *deleteSwitches[] = {"-id", "-name", "-file", (char *) NULL};
+
+ enum {RESOURCE_DELETE_ID, RESOURCE_DELETE_NAME, RESOURCE_DELETE_FILE};
+
+ resultPtr = Tcl_GetObjResult(interp);
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], switches, "option", 0, &index)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!initialized) {
+ ResourceInit();
+ }
+ result = TCL_OK;
+
+ switch (index) {
+ case RESOURCE_CLOSE:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "resourceRef");
+ return TCL_ERROR;
+ }
+ stringPtr = Tcl_GetStringFromObj(objv[2], &length);
+ fileRef = TclMacUnRegisterResourceFork(stringPtr, resultPtr);
+
+ if (fileRef >= 0) {
+ CloseResFile((short) fileRef);
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
+ }
+ case RESOURCE_DELETE:
+ if (!((objc >= 3) && (objc <= 9) && ((objc % 2) == 1))) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-id resourceId? ?-name resourceName? ?-file \
+resourceRef? resourceType");
+ return TCL_ERROR;
+ }
+
+ i = 2;
+ fileRef = -1;
+ gotInt = false;
+ resourceId = NULL;
+ limitSearch = false;
+
+ while (i < (objc - 2)) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], deleteSwitches,
+ "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch (index) {
+ case RESOURCE_DELETE_ID:
+ if (Tcl_GetLongFromObj(interp, objv[i+1], &rsrcId)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ gotInt = true;
+ break;
+ case RESOURCE_DELETE_NAME:
+ resourceId = Tcl_GetStringFromObj(objv[i+1], &length);
+ if (length > 255) {
+ Tcl_AppendStringsToObj(resultPtr,"-name argument ",
+ "too long, must be < 255 characters",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ strcpy((char *) theName, resourceId);
+ resourceId = (char *) theName;
+ c2pstr(resourceId);
+ break;
+ case RESOURCE_DELETE_FILE:
+ resourceRef = GetRsrcRefFromObj(objv[i+1], 0,
+ "delete from", resultPtr);
+ if (resourceRef == NULL) {
+ return TCL_ERROR;
+ }
+ limitSearch = true;
+ break;
+ }
+ i += 2;
+ }
+
+ if ((resourceId == NULL) && !gotInt) {
+ Tcl_AppendStringsToObj(resultPtr,"you must specify either ",
+ "\"-id\" or \"-name\" or both ",
+ "to \"resource delete\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetOSTypeFromObj(interp, objv[i], &rezType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (limitSearch) {
+ saveRef = CurResFile();
+ UseResFile((short) resourceRef->fileRef);
+ }
+
+ SetResLoad(false);
+
+ if (gotInt == true) {
+ if (limitSearch) {
+ resource = Get1Resource(rezType, rsrcId);
+ } else {
+ resource = GetResource(rezType, rsrcId);
+ }
+ err = ResError();
+
+ if (err == resNotFound || resource == NULL) {
+ Tcl_AppendStringsToObj(resultPtr, "resource not found",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ } else if (err != noErr) {
+ char buffer[16];
+
+ sprintf(buffer, "%12d", err);
+ Tcl_AppendStringsToObj(resultPtr, "resource error #",
+ buffer, "occured while trying to find resource",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ }
+ }
+
+ if (resourceId != NULL) {
+ Handle tmpResource;
+ if (limitSearch) {
+ tmpResource = Get1NamedResource(rezType,
+ (StringPtr) resourceId);
+ } else {
+ tmpResource = GetNamedResource(rezType,
+ (StringPtr) resourceId);
+ }
+ err = ResError();
+
+ if (err == resNotFound || tmpResource == NULL) {
+ Tcl_AppendStringsToObj(resultPtr, "resource not found",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ } else if (err != noErr) {
+ char buffer[16];
+
+ sprintf(buffer, "%12d", err);
+ Tcl_AppendStringsToObj(resultPtr, "resource error #",
+ buffer, "occured while trying to find resource",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ }
+
+ if (gotInt) {
+ if (resource != tmpResource) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "\"-id\" and \"-name\" ",
+ "values do not point to the same resource",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ }
+ } else {
+ resource = tmpResource;
+ }
+ }
+
+ resInfo = GetResAttrs(resource);
+
+ if ((resInfo & resProtected) == resProtected) {
+ Tcl_AppendStringsToObj(resultPtr, "resource ",
+ "cannot be deleted: it is protected.",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ } else if ((resInfo & resSysHeap) == resSysHeap) {
+ Tcl_AppendStringsToObj(resultPtr, "resource",
+ "cannot be deleted: it is in the system heap.",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto deleteDone;
+ }
+
+ /*
+ * Find the resource file, if it was not specified,
+ * so we can flush the changes now. Perhaps this is
+ * a little paranoid, but better safe than sorry.
+ */
+
+ RemoveResource(resource);
+
+ if (!limitSearch) {
+ UpdateResFile(HomeResFile(resource));
+ } else {
+ UpdateResFile(resourceRef->fileRef);
+ }
+
+
+ deleteDone:
+
+ SetResLoad(true);
+ if (limitSearch) {
+ UseResFile(saveRef);
+ }
+ return result;
+
+ case RESOURCE_FILES:
+ if ((objc < 2) || (objc > 3)) {
+ Tcl_SetStringObj(resultPtr,
+ "wrong # args: should be \"resource files \
+?resourceId?\"", -1);
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ stringPtr = Tcl_GetStringFromObj(resourceForkList, &length);
+ Tcl_SetStringObj(resultPtr, stringPtr, length);
+ } else {
+ FCBPBRec fileRec;
+ Handle pathHandle;
+ short pathLength;
+ Str255 fileName;
+
+ if (strcmp(Tcl_GetStringFromObj(objv[2], NULL), "ROM Map")
+ == 0) {
+ Tcl_SetStringObj(resultPtr,"no file path for ROM Map", -1);
+ return TCL_ERROR;
+ }
+
+ resourceRef = GetRsrcRefFromObj(objv[2], 1, "files", resultPtr);
+ if (resourceRef == NULL) {
+ return TCL_ERROR;
+ }
+
+ fileRec.ioCompletion = NULL;
+ fileRec.ioFCBIndx = 0;
+ fileRec.ioNamePtr = fileName;
+ fileRec.ioVRefNum = 0;
+ fileRec.ioRefNum = resourceRef->fileRef;
+ err = PBGetFCBInfo(&fileRec, false);
+ if (err != noErr) {
+ Tcl_SetStringObj(resultPtr,
+ "could not get FCB for resource file", -1);
+ return TCL_ERROR;
+ }
+
+ err = GetFullPath(fileRec.ioFCBVRefNum, fileRec.ioFCBParID,
+ fileRec.ioNamePtr, &pathLength, &pathHandle);
+ if ( err != noErr) {
+ Tcl_SetStringObj(resultPtr,
+ "could not get file path from token", -1);
+ return TCL_ERROR;
+ }
+
+ HLock(pathHandle);
+ Tcl_SetStringObj(resultPtr,*pathHandle,pathLength);
+ HUnlock(pathHandle);
+ DisposeHandle(pathHandle);
+ }
+ return TCL_OK;
+ case RESOURCE_LIST:
+ if (!((objc == 3) || (objc == 4))) {
+ Tcl_WrongNumArgs(interp, 2, objv, "resourceType ?resourceRef?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetOSTypeFromObj(interp, objv[2], &rezType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc == 4) {
+ resourceRef = GetRsrcRefFromObj(objv[3], 1,
+ "list", resultPtr);
+ if (resourceRef == NULL) {
+ return TCL_ERROR;
+ }
+
+ saveRef = CurResFile();
+ UseResFile((short) resourceRef->fileRef);
+ limitSearch = true;
+ }
+
+ Tcl_ResetResult(interp);
+ if (limitSearch) {
+ count = Count1Resources(rezType);
+ } else {
+ count = CountResources(rezType);
+ }
+ SetResLoad(false);
+ for (i = 1; i <= count; i++) {
+ if (limitSearch) {
+ resource = Get1IndResource(rezType, i);
+ } else {
+ resource = GetIndResource(rezType, i);
+ }
+ if (resource != NULL) {
+ GetResInfo(resource, &id, (ResType *) &rezType, theName);
+ if (theName[0] != 0) {
+ objPtr = Tcl_NewStringObj((char *) theName + 1,
+ theName[0]);
+ } else {
+ objPtr = Tcl_NewIntObj(id);
+ }
+ ReleaseResource(resource);
+ result = Tcl_ListObjAppendElement(interp, resultPtr,
+ objPtr);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(objPtr);
+ break;
+ }
+ }
+ }
+ SetResLoad(true);
+
+ if (limitSearch) {
+ UseResFile(saveRef);
+ }
+
+ return TCL_OK;
+ case RESOURCE_OPEN:
+ if (!((objc == 3) || (objc == 4))) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?permissions?");
+ return TCL_ERROR;
+ }
+ stringPtr = Tcl_GetStringFromObj(objv[2], &length);
+ nativeName = Tcl_TranslateFileName(interp, stringPtr, &buffer);
+ if (nativeName == NULL) {
+ return TCL_ERROR;
+ }
+ err = FSpLocationFromPath(strlen(nativeName), nativeName,
+ &fileSpec) ;
+ Tcl_DStringFree(&buffer);
+ if (!((err == noErr) || (err == fnfErr))) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "invalid path", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get permissions for the file. We really only understand
+ * read-only and shared-read-write. If no permissions are
+ * given we default to read only.
+ */
+
+ if (objc == 4) {
+ stringPtr = Tcl_GetStringFromObj(objv[3], &length);
+ mode = TclGetOpenMode(interp, stringPtr, &index);
+ if (mode == -1) {
+ /* TODO: TclGetOpenMode doesn't work with Obj commands. */
+ return TCL_ERROR;
+ }
+ switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
+ case O_RDONLY:
+ macPermision = fsRdPerm;
+ break;
+ case O_WRONLY:
+ case O_RDWR:
+ macPermision = fsRdWrShPerm;
+ break;
+ default:
+ panic("Tcl_ResourceObjCmd: invalid mode value");
+ break;
+ }
+ } else {
+ macPermision = fsRdPerm;
+ }
+
+ /*
+ * Don't load in any of the resources in the file, this could
+ * cause problems if you open a file that has CODE resources...
+ */
+
+ SetResLoad(false);
+ fileRef = (long) FSpOpenResFileCompat(&fileSpec, macPermision);
+ SetResLoad(true);
+
+ if (fileRef == -1) {
+ err = ResError();
+ if (((err == fnfErr) || (err == eofErr)) &&
+ (macPermision == fsRdWrShPerm)) {
+ /*
+ * No resource fork existed for this file. Since we are
+ * opening it for writing we will create the resource fork
+ * now.
+ */
+
+ HCreateResFile(fileSpec.vRefNum, fileSpec.parID,
+ fileSpec.name);
+ fileRef = (long) FSpOpenResFileCompat(&fileSpec,
+ macPermision);
+ if (fileRef == -1) {
+ goto openError;
+ }
+ } else if (err == fnfErr) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "file does not exist", (char *) NULL);
+ return TCL_ERROR;
+ } else if (err == eofErr) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "file does not contain resource fork", (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ openError:
+ Tcl_AppendStringsToObj(resultPtr,
+ "error opening resource file", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * The FspOpenResFile function does not set the ResFileAttrs.
+ * Even if you open the file read only, the mapReadOnly
+ * attribute is not set. This means we can't detect writes to a
+ * read only resource fork until the write fails, which is bogus.
+ * So set it here...
+ */
+
+ if (macPermision == fsRdPerm) {
+ SetResFileAttrs(fileRef, mapReadOnly);
+ }
+
+ Tcl_SetStringObj(resultPtr, "", 0);
+ if (TclMacRegisterResourceFork(fileRef, resultPtr,
+ TCL_RESOURCE_CHECK_IF_OPEN) != TCL_OK) {
+ CloseResFile(fileRef);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+ case RESOURCE_READ:
+ if (!((objc == 4) || (objc == 5))) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "resourceType resourceId ?resourceRef?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetOSTypeFromObj(interp, objv[2], &rezType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetLongFromObj((Tcl_Interp *) NULL, objv[3], &rsrcId)
+ != TCL_OK) {
+ resourceId = Tcl_GetStringFromObj(objv[3], &length);
+ }
+
+ if (objc == 5) {
+ stringPtr = Tcl_GetStringFromObj(objv[4], &length);
+ } else {
+ stringPtr = NULL;
+ }
+
+ resource = Tcl_MacFindResource(interp, rezType, resourceId,
+ rsrcId, stringPtr, &releaseIt);
+
+ if (resource != NULL) {
+ size = GetResourceSizeOnDisk(resource);
+ Tcl_SetStringObj(resultPtr, *resource, size);
+
+ /*
+ * Don't release the resource unless WE loaded it...
+ */
+
+ if (releaseIt) {
+ ReleaseResource(resource);
+ }
+ return TCL_OK;
+ } else {
+ Tcl_AppendStringsToObj(resultPtr, "could not load resource",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ case RESOURCE_TYPES:
+ if (!((objc == 2) || (objc == 3))) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?resourceRef?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 3) {
+ resourceRef = GetRsrcRefFromObj(objv[2], 1,
+ "get types of", resultPtr);
+ if (resourceRef == NULL) {
+ return TCL_ERROR;
+ }
+
+ saveRef = CurResFile();
+ UseResFile((short) resourceRef->fileRef);
+ limitSearch = true;
+ }
+
+ if (limitSearch) {
+ count = Count1Types();
+ } else {
+ count = CountTypes();
+ }
+ for (i = 1; i <= count; i++) {
+ if (limitSearch) {
+ Get1IndType((ResType *) &rezType, i);
+ } else {
+ GetIndType((ResType *) &rezType, i);
+ }
+ objPtr = Tcl_NewOSTypeObj(rezType);
+ result = Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(objPtr);
+ break;
+ }
+ }
+
+ if (limitSearch) {
+ UseResFile(saveRef);
+ }
+
+ return result;
+ case RESOURCE_WRITE:
+ if ((objc < 4) || (objc > 11)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-id resourceId? ?-name resourceName? ?-file resourceRef?\
+ ?-force? resourceType data");
+ return TCL_ERROR;
+ }
+
+ i = 2;
+ gotInt = false;
+ resourceId = NULL;
+ limitSearch = false;
+ force = 0;
+
+ while (i < (objc - 2)) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], writeSwitches,
+ "switch", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch (index) {
+ case RESOURCE_WRITE_ID:
+ if (Tcl_GetLongFromObj(interp, objv[i+1], &rsrcId)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ gotInt = true;
+ i += 2;
+ break;
+ case RESOURCE_WRITE_NAME:
+ resourceId = Tcl_GetStringFromObj(objv[i+1], &length);
+ strcpy((char *) theName, resourceId);
+ resourceId = (char *) theName;
+ c2pstr(resourceId);
+ i += 2;
+ break;
+ case RESOURCE_WRITE_FILE:
+ resourceRef = GetRsrcRefFromObj(objv[i+1], 0,
+ "write to", resultPtr);
+ if (resourceRef == NULL) {
+ return TCL_ERROR;
+ }
+ limitSearch = true;
+ i += 2;
+ break;
+ case RESOURCE_FORCE:
+ force = 1;
+ i += 1;
+ break;
+ }
+ }
+ if (Tcl_GetOSTypeFromObj(interp, objv[i], &rezType) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ stringPtr = Tcl_GetStringFromObj(objv[i+1], &length);
+
+ if (gotInt == false) {
+ rsrcId = UniqueID(rezType);
+ }
+ if (resourceId == NULL) {
+ resourceId = (char *) "\p";
+ }
+ if (limitSearch) {
+ saveRef = CurResFile();
+ UseResFile((short) resourceRef->fileRef);
+ }
+
+ /*
+ * If we are adding the resource by number, then we must make sure
+ * there is not already a resource of that number. We are not going
+ * load it here, since we want to detect whether we loaded it or
+ * not. Remember that releasing some resources in particular menu
+ * related ones, can be fatal.
+ */
+
+ if (gotInt == true) {
+ SetResLoad(false);
+ resource = Get1Resource(rezType,rsrcId);
+ SetResLoad(true);
+ }
+
+ if (resource == NULL) {
+ /*
+ * We get into this branch either if there was not already a
+ * resource of this type & id, or the id was not specified.
+ */
+
+ resource = NewHandle(length);
+ if (resource == NULL) {
+ resource = NewHandleSys(length);
+ if (resource == NULL) {
+ panic("could not allocate memory to write resource");
+ }
+ }
+ HLock(resource);
+ memcpy(*resource, stringPtr, length);
+ HUnlock(resource);
+ AddResource(resource, rezType, (short) rsrcId,
+ (StringPtr) resourceId);
+ releaseIt = 1;
+ } else {
+ /*
+ * We got here because there was a resource of this type
+ * & ID in the file.
+ */
+
+ if (*resource == NULL) {
+ releaseIt = 1;
+ } else {
+ releaseIt = 0;
+ }
+
+ if (!force) {
+ /*
+ *We only overwrite extant resources
+ * when the -force flag has been set.
+ */
+
+ sprintf(errbuf,"%d", rsrcId);
+
+ Tcl_AppendStringsToObj(resultPtr, "the resource ",
+ errbuf, " already exists, use \"-force\"",
+ " to overwrite it.", (char *) NULL);
+
+ result = TCL_ERROR;
+ goto writeDone;
+ } else if (GetResAttrs(resource) & resProtected) {
+ /*
+ *
+ * Next, check to see if it is protected...
+ */
+
+ sprintf(errbuf,"%d", rsrcId);
+ Tcl_AppendStringsToObj(resultPtr,
+ "could not write resource id ",
+ errbuf, " of type ",
+ Tcl_GetStringFromObj(objv[i],&length),
+ ", it was protected.",(char *) NULL);
+ result = TCL_ERROR;
+ goto writeDone;
+ } else {
+ /*
+ * Be careful, the resource might already be in memory
+ * if something else loaded it.
+ */
+
+ if (*resource == 0) {
+ LoadResource(resource);
+ err = ResError();
+ if (err != noErr) {
+ sprintf(errbuf,"%d", rsrcId);
+ Tcl_AppendStringsToObj(resultPtr,
+ "error loading resource ",
+ errbuf, " of type ",
+ Tcl_GetStringFromObj(objv[i],&length),
+ " to overwrite it", (char *) NULL);
+ goto writeDone;
+ }
+ }
+
+ SetHandleSize(resource, length);
+ if ( MemError() != noErr ) {
+ panic("could not allocate memory to write resource");
+ }
+
+ HLock(resource);
+ memcpy(*resource, stringPtr, length);
+ HUnlock(resource);
+
+ ChangedResource(resource);
+
+ /*
+ * We also may have changed the name...
+ */
+
+ SetResInfo(resource, rsrcId, (StringPtr) resourceId);
+ }
+ }
+
+ err = ResError();
+ if (err != noErr) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "error adding resource to resource map",
+ (char *) NULL);
+ result = TCL_ERROR;
+ goto writeDone;
+ }
+
+ WriteResource(resource);
+ err = ResError();
+ if (err != noErr) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "error writing resource to disk",
+ (char *) NULL);
+ result = TCL_ERROR;
+ }
+
+ writeDone:
+
+ if (releaseIt) {
+ ReleaseResource(resource);
+ err = ResError();
+ if (err != noErr) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "error releasing resource",
+ (char *) NULL);
+ result = TCL_ERROR;
+ }
+ }
+
+ if (limitSearch) {
+ UseResFile(saveRef);
+ }
+
+ return result;
+ default:
+ panic("Tcl_GetIndexFromObject returned unrecognized option");
+ return TCL_ERROR; /* Should never be reached. */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MacSourceObjCmd --
+ *
+ * This procedure is invoked to process the "source" Tcl command.
+ * See the user documentation for details on what it does. In
+ * addition, it supports sourceing from the resource fork of
+ * type 'TEXT'.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_MacSourceObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument objects. */
+{
+ char *errNum = "wrong # args: ";
+ char *errBad = "bad argument: ";
+ char *errStr;
+ char *fileName = NULL, *rsrcName = NULL;
+ long rsrcID = -1;
+ char *string;
+ int length;
+
+ if (objc < 2 || objc > 4) {
+ errStr = errNum;
+ goto sourceFmtErr;
+ }
+
+ if (objc == 2) {
+ string = TclGetStringFromObj(objv[1], &length);
+ return Tcl_EvalFile(interp, string);
+ }
+
+ /*
+ * The following code supports a few older forms of this command
+ * for backward compatability.
+ */
+ string = TclGetStringFromObj(objv[1], &length);
+ if (!strcmp(string, "-rsrc") || !strcmp(string, "-rsrcname")) {
+ rsrcName = TclGetStringFromObj(objv[2], &length);
+ } else if (!strcmp(string, "-rsrcid")) {
+ if (Tcl_GetLongFromObj(interp, objv[2], &rsrcID) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ errStr = errBad;
+ goto sourceFmtErr;
+ }
+
+ if (objc == 4) {
+ fileName = TclGetStringFromObj(objv[3], &length);
+ }
+ return Tcl_MacEvalResource(interp, rsrcName, rsrcID, fileName);
+
+ sourceFmtErr:
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), errStr, "should be \"",
+ Tcl_GetStringFromObj(objv[0], (int *) NULL),
+ " fileName\" or \"",
+ Tcl_GetStringFromObj(objv[0], (int *) NULL),
+ " -rsrc name ?fileName?\" or \"",
+ Tcl_GetStringFromObj(objv[0], (int *) NULL),
+ " -rsrcid id ?fileName?\"", (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_BeepObjCmd --
+ *
+ * This procedure makes the beep sound.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Makes a beep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_BeepObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *CONST objv[]) /* Argument values. */
+{
+ Tcl_Obj *resultPtr, *objPtr;
+ Handle sound;
+ Str255 sndName;
+ int volume = -1, length;
+ char * sndArg = NULL;
+
+ resultPtr = Tcl_GetObjResult(interp);
+ if (objc == 1) {
+ SysBeep(1);
+ return TCL_OK;
+ } else if (objc == 2) {
+ if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-list")) {
+ int count, i;
+ short id;
+ Str255 theName;
+ ResType rezType;
+
+ count = CountResources('snd ');
+ for (i = 1; i <= count; i++) {
+ sound = GetIndResource('snd ', i);
+ if (sound != NULL) {
+ GetResInfo(sound, &id, &rezType, theName);
+ if (theName[0] == 0) {
+ continue;
+ }
+ objPtr = Tcl_NewStringObj((char *) theName + 1,
+ theName[0]);
+ Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
+ }
+ }
+ return TCL_OK;
+ } else {
+ sndArg = Tcl_GetStringFromObj(objv[1], &length);
+ }
+ } else if (objc == 3) {
+ if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-volume")) {
+ Tcl_GetIntFromObj(interp, objv[2], &volume);
+ } else {
+ goto beepUsage;
+ }
+ } else if (objc == 4) {
+ if (!strcmp(Tcl_GetStringFromObj(objv[1], &length), "-volume")) {
+ Tcl_GetIntFromObj(interp, objv[2], &volume);
+ sndArg = Tcl_GetStringFromObj(objv[3], &length);
+ } else {
+ goto beepUsage;
+ }
+ } else {
+ goto beepUsage;
+ }
+
+ /*
+ * Play the sound
+ */
+ if (sndArg == NULL) {
+ /*
+ * Set Volume for SysBeep
+ */
+
+ if (volume >= 0) {
+ SetSoundVolume(volume, SYS_BEEP_VOLUME);
+ }
+ SysBeep(1);
+
+ /*
+ * Reset Volume
+ */
+
+ if (volume >= 0) {
+ SetSoundVolume(0, RESET_VOLUME);
+ }
+ } else {
+ strcpy((char *) sndName + 1, sndArg);
+ sndName[0] = length;
+ sound = GetNamedResource('snd ', sndName);
+ if (sound != NULL) {
+ /*
+ * Set Volume for Default Output device
+ */
+
+ if (volume >= 0) {
+ SetSoundVolume(volume, DEFAULT_SND_VOLUME);
+ }
+
+ SndPlay(NULL, (SndListHandle) sound, false);
+
+ /*
+ * Reset Volume
+ */
+
+ if (volume >= 0) {
+ SetSoundVolume(0, RESET_VOLUME);
+ }
+ } else {
+ Tcl_AppendStringsToObj(resultPtr, " \"", sndArg,
+ "\" is not a valid sound. (Try ",
+ Tcl_GetStringFromObj(objv[0], (int *) NULL),
+ " -list)", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
+
+ beepUsage:
+ Tcl_WrongNumArgs(interp, 1, objv, "[-volume num] [-list | sndName]?");
+ return TCL_ERROR;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * SetSoundVolume --
+ *
+ * Set the volume for either the SysBeep or the SndPlay call depending
+ * on the value of mode (SYS_BEEP_VOLUME or DEFAULT_SND_VOLUME
+ * respectively.
+ *
+ * It also stores the last channel set, and the old value of its
+ * VOLUME. If you call SetSoundVolume with a mode of RESET_VOLUME,
+ * it will undo the last setting. The volume parameter is
+ * ignored in this case.
+ *
+ * Side Effects:
+ * Sets the System Volume
+ *
+ * Results:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+SetSoundVolume(
+ int volume, /* This is the new volume */
+ enum WhichVolume mode) /* This flag says which volume to
+ * set: SysBeep, SndPlay, or instructs us
+ * to reset the volume */
+{
+ static int hasSM3 = -1;
+ static enum WhichVolume oldMode;
+ static long oldVolume = -1;
+
+ /*
+ * The volume setting calls only work if we have SoundManager
+ * 3.0 or higher. So we check that here.
+ */
+
+ if (hasSM3 == -1) {
+ if (GetToolboxTrapAddress(_SoundDispatch)
+ != GetToolboxTrapAddress(_Unimplemented)) {
+ NumVersion SMVers = SndSoundManagerVersion();
+ if (SMVers.majorRev > 2) {
+ hasSM3 = 1;
+ } else {
+ hasSM3 = 0;
+ }
+ } else {
+ /*
+ * If the SoundDispatch trap is not present, then
+ * we don't have the SoundManager at all.
+ */
+
+ hasSM3 = 0;
+ }
+ }
+
+ /*
+ * If we don't have Sound Manager 3.0, we can't set the sound volume.
+ * We will just ignore the request rather than raising an error.
+ */
+
+ if (!hasSM3) {
+ return;
+ }
+
+ switch (mode) {
+ case SYS_BEEP_VOLUME:
+ GetSysBeepVolume(&oldVolume);
+ SetSysBeepVolume(volume);
+ oldMode = SYS_BEEP_VOLUME;
+ break;
+ case DEFAULT_SND_VOLUME:
+ GetDefaultOutputVolume(&oldVolume);
+ SetDefaultOutputVolume(volume);
+ oldMode = DEFAULT_SND_VOLUME;
+ break;
+ case RESET_VOLUME:
+ /*
+ * If oldVolume is -1 someone has made a programming error
+ * and called reset before setting the volume. This is benign
+ * however, so we will just exit.
+ */
+
+ if (oldVolume != -1) {
+ if (oldMode == SYS_BEEP_VOLUME) {
+ SetSysBeepVolume(oldVolume);
+ } else if (oldMode == DEFAULT_SND_VOLUME) {
+ SetDefaultOutputVolume(oldVolume);
+ }
+ }
+ oldVolume = -1;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Tcl_MacEvalResource --
+ *
+ * Used to extend the source command. Sources Tcl code from a Text
+ * resource. Currently only sources the resouce by name file ID may be
+ * supported at a later date.
+ *
+ * Side Effects:
+ * Depends on the Tcl code in the resource.
+ *
+ * Results:
+ * Returns a Tcl result.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+Tcl_MacEvalResource(
+ Tcl_Interp *interp, /* Interpreter in which to process file. */
+ char *resourceName, /* Name of TEXT resource to source,
+ NULL if number should be used. */
+ int resourceNumber, /* Resource id of source. */
+ char *fileName) /* Name of file to process.
+ NULL if application resource. */
+{
+ Handle sourceText;
+ Str255 rezName;
+ char msg[200];
+ int result;
+ short saveRef, fileRef = -1;
+ char idStr[64];
+ FSSpec fileSpec;
+ Tcl_DString buffer;
+ char *nativeName;
+
+ saveRef = CurResFile();
+
+ if (fileName != NULL) {
+ OSErr err;
+
+ nativeName = Tcl_TranslateFileName(interp, fileName, &buffer);
+ if (nativeName == NULL) {
+ return TCL_ERROR;
+ }
+ err = FSpLocationFromPath(strlen(nativeName), nativeName, &fileSpec);
+ Tcl_DStringFree(&buffer);
+ if (err != noErr) {
+ Tcl_AppendResult(interp, "Error finding the file: \"",
+ fileName, "\".", NULL);
+ return TCL_ERROR;
+ }
+
+ fileRef = FSpOpenResFileCompat(&fileSpec, fsRdPerm);
+ if (fileRef == -1) {
+ Tcl_AppendResult(interp, "Error reading the file: \"",
+ fileName, "\".", NULL);
+ return TCL_ERROR;
+ }
+
+ UseResFile(fileRef);
+ } else {
+ /*
+ * The default behavior will search through all open resource files.
+ * This may not be the behavior you desire. If you want the behavior
+ * of this call to *only* search the application resource fork, you
+ * must call UseResFile at this point to set it to the application
+ * file. This means you must have already obtained the application's
+ * fileRef when the application started up.
+ */
+ }
+
+ /*
+ * Load the resource by name or ID
+ */
+ if (resourceName != NULL) {
+ strcpy((char *) rezName + 1, resourceName);
+ rezName[0] = strlen(resourceName);
+ sourceText = GetNamedResource('TEXT', rezName);
+ } else {
+ sourceText = GetResource('TEXT', (short) resourceNumber);
+ }
+
+ if (sourceText == NULL) {
+ result = TCL_ERROR;
+ } else {
+ char *sourceStr = NULL;
+
+ HLock(sourceText);
+ sourceStr = Tcl_MacConvertTextResource(sourceText);
+ HUnlock(sourceText);
+ ReleaseResource(sourceText);
+
+ /*
+ * We now evaluate the Tcl source
+ */
+ result = Tcl_Eval(interp, sourceStr);
+ ckfree(sourceStr);
+ if (result == TCL_RETURN) {
+ result = TCL_OK;
+ } else if (result == TCL_ERROR) {
+ sprintf(msg, "\n (rsrc \"%.150s\" line %d)", resourceName,
+ interp->errorLine);
+ Tcl_AddErrorInfo(interp, msg);
+ }
+
+ goto rezEvalCleanUp;
+ }
+
+ rezEvalError:
+ sprintf(idStr, "ID=%d", resourceNumber);
+ Tcl_AppendResult(interp, "The resource \"",
+ (resourceName != NULL ? resourceName : idStr),
+ "\" could not be loaded from ",
+ (fileName != NULL ? fileName : "application"),
+ ".", NULL);
+
+ rezEvalCleanUp:
+ if (fileRef != -1) {
+ CloseResFile(fileRef);
+ }
+
+ UseResFile(saveRef);
+
+ return result;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Tcl_MacConvertTextResource --
+ *
+ * Converts a TEXT resource into a Tcl suitable string.
+ *
+ * Side Effects:
+ * Mallocs the returned memory, converts '\r' to '\n', and appends a NULL.
+ *
+ * Results:
+ * A new malloced string.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+Tcl_MacConvertTextResource(
+ Handle resource) /* Handle to TEXT resource. */
+{
+ int i, size;
+ char *resultStr;
+
+ size = GetResourceSizeOnDisk(resource);
+
+ resultStr = ckalloc(size + 1);
+
+ for (i=0; i<size; i++) {
+ if ((*resource)[i] == '\r') {
+ resultStr[i] = '\n';
+ } else {
+ resultStr[i] = (*resource)[i];
+ }
+ }
+
+ resultStr[size] = '\0';
+
+ return resultStr;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Tcl_MacFindResource --
+ *
+ * Higher level interface for loading resources.
+ *
+ * Side Effects:
+ * Attempts to load a resource.
+ *
+ * Results:
+ * A handle on success.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+Handle
+Tcl_MacFindResource(
+ Tcl_Interp *interp, /* Interpreter in which to process file. */
+ long resourceType, /* Type of resource to load. */
+ char *resourceName, /* Name of resource to find,
+ * NULL if number should be used. */
+ int resourceNumber, /* Resource id of source. */
+ char *resFileRef, /* Registered resource file reference,
+ * NULL if searching all open resource files. */
+ int *releaseIt) /* Should we release this resource when done. */
+{
+ Tcl_HashEntry *nameHashPtr;
+ OpenResourceFork *resourceRef;
+ int limitSearch = false;
+ short saveRef;
+ Handle resource;
+
+ if (resFileRef != NULL) {
+ nameHashPtr = Tcl_FindHashEntry(&nameTable, resFileRef);
+ if (nameHashPtr == NULL) {
+ Tcl_AppendResult(interp, "invalid resource file reference \"",
+ resFileRef, "\"", (char *) NULL);
+ return NULL;
+ }
+ resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
+ saveRef = CurResFile();
+ UseResFile((short) resourceRef->fileRef);
+ limitSearch = true;
+ }
+
+ /*
+ * Some system resources (for example system resources) should not
+ * be released. So we set autoload to false, and try to get the resource.
+ * If the Master Pointer of the returned handle is null, then resource was
+ * not in memory, and it is safe to release it. Otherwise, it is not.
+ */
+
+ SetResLoad(false);
+
+ if (resourceName == NULL) {
+ if (limitSearch) {
+ resource = Get1Resource(resourceType, resourceNumber);
+ } else {
+ resource = GetResource(resourceType, resourceNumber);
+ }
+ } else {
+ c2pstr(resourceName);
+ if (limitSearch) {
+ resource = Get1NamedResource(resourceType,
+ (StringPtr) resourceName);
+ } else {
+ resource = GetNamedResource(resourceType,
+ (StringPtr) resourceName);
+ }
+ p2cstr((StringPtr) resourceName);
+ }
+
+ if (*resource == NULL) {
+ *releaseIt = 1;
+ LoadResource(resource);
+ } else {
+ *releaseIt = 0;
+ }
+
+ SetResLoad(true);
+
+
+ if (limitSearch) {
+ UseResFile(saveRef);
+ }
+
+ return resource;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ResourceInit --
+ *
+ * Initialize the structures used for resource management.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ResourceInit()
+{
+
+ initialized = 1;
+ Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&resourceTable, TCL_ONE_WORD_KEYS);
+ resourceForkList = Tcl_NewObj();
+ Tcl_IncrRefCount(resourceForkList);
+
+ BuildResourceForkList();
+
+}
+/***/
+
+/*Tcl_RegisterObjType(typePtr) */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_NewOSTypeObj --
+ *
+ * This procedure is used to create a new resource name type object.
+ *
+ * Results:
+ * The newly created object is returned. This object will have a NULL
+ * string representation. The returned object has ref count 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_NewOSTypeObj(
+ OSType newOSType) /* Int used to initialize the new object. */
+{
+ register Tcl_Obj *objPtr;
+
+ if (!osTypeInit) {
+ osTypeInit = 1;
+ Tcl_RegisterObjType(&osType);
+ }
+
+ objPtr = Tcl_NewObj();
+ objPtr->bytes = NULL;
+ objPtr->internalRep.longValue = newOSType;
+ objPtr->typePtr = &osType;
+ return objPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetOSTypeObj --
+ *
+ * Modify an object to be a resource type and to have the
+ * specified long value.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's old string rep, if any, is freed. Also, any old
+ * internal rep is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetOSTypeObj(
+ Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ OSType newOSType) /* Integer used to set object's value. */
+{
+ register Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+
+ if (!osTypeInit) {
+ osTypeInit = 1;
+ Tcl_RegisterObjType(&osType);
+ }
+
+ Tcl_InvalidateStringRep(objPtr);
+ if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+ oldTypePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->internalRep.longValue = newOSType;
+ objPtr->typePtr = &osType;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetOSTypeFromObj --
+ *
+ * Attempt to return an int from the Tcl object "objPtr". If the object
+ * is not already an int, an attempt will be made to convert it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in interp->objResult
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already an int, the conversion will free
+ * any old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetOSTypeFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* The object from which to get a int. */
+ OSType *osTypePtr) /* Place to store resulting int. */
+{
+ register int result;
+
+ if (!osTypeInit) {
+ osTypeInit = 1;
+ Tcl_RegisterObjType(&osType);
+ }
+
+ if (objPtr->typePtr == &osType) {
+ *osTypePtr = objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+
+ result = SetOSTypeFromAny(interp, objPtr);
+ if (result == TCL_OK) {
+ *osTypePtr = objPtr->internalRep.longValue;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupOSTypeInternalRep --
+ *
+ * Initialize the internal representation of an int Tcl_Obj to a
+ * copy of the internal representation of an existing int object.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * "copyPtr"s internal rep is set to the integer corresponding to
+ * "srcPtr"s internal rep.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DupOSTypeInternalRep(
+ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
+ Tcl_Obj *copyPtr) /* Object with internal rep to set. */
+{
+ copyPtr->internalRep.longValue = srcPtr->internalRep.longValue;
+ copyPtr->typePtr = &osType;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetOSTypeFromAny --
+ *
+ * Attempt to generate an integer internal form for the Tcl object
+ * "objPtr".
+ *
+ * Results:
+ * The return value is a standard object Tcl result. If an error occurs
+ * during conversion, an error message is left in interp->objResult
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, an int is stored as "objPtr"s internal
+ * representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetOSTypeFromAny(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr) /* The object to convert. */
+{
+ Tcl_ObjType *oldTypePtr = objPtr->typePtr;
+ char *string;
+ int length;
+ long newOSType;
+
+ /*
+ * Get the string representation. Make it up-to-date if necessary.
+ */
+
+ string = TclGetStringFromObj(objPtr, &length);
+
+ if (length != 4) {
+ if (interp != NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "expected Macintosh OS type but got \"", string, "\"",
+ (char *) NULL);
+ }
+ return TCL_ERROR;
+ }
+ newOSType = *((long *) string);
+
+ /*
+ * The conversion to resource type succeeded. Free the old internalRep
+ * before setting the new one.
+ */
+
+ if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) {
+ oldTypePtr->freeIntRepProc(objPtr);
+ }
+
+ objPtr->internalRep.longValue = newOSType;
+ objPtr->typePtr = &osType;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfOSType --
+ *
+ * Update the string representation for an resource type object.
+ * Note: This procedure does not free an existing old string rep
+ * so storage will be lost if this has not already been done.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to a valid string that results from
+ * the int-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfOSType(
+ register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
+{
+ objPtr->bytes = ckalloc(5);
+ sprintf(objPtr->bytes, "%-4.4s", &(objPtr->internalRep.longValue));
+ objPtr->length = 4;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetRsrcRefFromObj --
+ *
+ * Given a String object containing a resource file token, return
+ * the OpenResourceFork structure that it represents, or NULL if
+ * the token cannot be found. If okayOnReadOnly is false, it will
+ * also check whether the token corresponds to a read-only file,
+ * and return NULL if it is.
+ *
+ * Results:
+ * A pointer to an OpenResourceFork structure, or NULL.
+ *
+ * Side effects:
+ * An error message may be left in resultPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OpenResourceFork *
+GetRsrcRefFromObj(
+ register Tcl_Obj *objPtr, /* String obj containing file token */
+ int okayOnReadOnly, /* Whether this operation is okay for a *
+ * read only file. */
+ const char *operation, /* String containing the operation we *
+ * were trying to perform, used for errors */
+ Tcl_Obj *resultPtr) /* Tcl_Obj to contain error message */
+{
+ char *stringPtr;
+ Tcl_HashEntry *nameHashPtr;
+ OpenResourceFork *resourceRef;
+ int length;
+ OSErr err;
+
+ stringPtr = Tcl_GetStringFromObj(objPtr, &length);
+ nameHashPtr = Tcl_FindHashEntry(&nameTable, stringPtr);
+ if (nameHashPtr == NULL) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "invalid resource file reference \"",
+ stringPtr, "\"", (char *) NULL);
+ return NULL;
+ }
+
+ resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
+
+ if (!okayOnReadOnly) {
+ err = GetResFileAttrs((short) resourceRef->fileRef);
+ if (err & mapReadOnly) {
+ Tcl_AppendStringsToObj(resultPtr, "cannot ", operation,
+ " resource file \"",
+ stringPtr, "\", it was opened read only",
+ (char *) NULL);
+ return NULL;
+ }
+ }
+ return resourceRef;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacRegisterResourceFork --
+ *
+ * Register an open resource fork in the table of open resources
+ * managed by the procedures in this file. If the resource file
+ * is already registered with the table, then no new token is made.
+ *
+ * The bahavior is controlled by the value of tokenPtr, and of the
+ * flags variable. For tokenPtr, the possibilities are:
+ * - NULL: The new token is auto-generated, but not returned.
+ * - The string value of tokenPtr is the empty string: Then
+ * the new token is auto-generated, and returned in tokenPtr
+ * - tokenPtr has a value: The string value will be used for the token,
+ * unless it is already in use, in which case a new token will
+ * be generated, and returned in tokenPtr.
+ *
+ * For the flags variable: it can be one of:
+ * - TCL_RESOURCE__INSERT_TAIL: The element is inserted at the
+ * end of the list of open resources. Used only in Resource_Init.
+ * - TCL_RESOURCE_DONT_CLOSE: The resource close command will not close
+ * this resource.
+ * - TCL_RESOURCE_CHECK_IF_OPEN: This will check to see if this file's
+ * resource fork is already opened by this Tcl shell, and return
+ * an error without registering the resource fork.
+ *
+ * Results:
+ * Standard Tcl Result
+ *
+ * Side effects:
+ * An entry is added to the resource name table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclMacRegisterResourceFork(
+ short fileRef, /* File ref for an open resource fork. */
+ Tcl_Obj *tokenPtr, /* A Tcl Object to which to write the *
+ * new token */
+ int flags) /* 1 means insert at the head of the resource
+ * fork list, 0 means at the tail */
+
+{
+ Tcl_HashEntry *resourceHashPtr;
+ Tcl_HashEntry *nameHashPtr;
+ OpenResourceFork *resourceRef;
+ int new;
+ char *resourceId = NULL;
+
+ if (!initialized) {
+ ResourceInit();
+ }
+
+ /*
+ * If we were asked to, check that this file has not been opened
+ * already.
+ */
+
+ if (flags & TCL_RESOURCE_CHECK_IF_OPEN) {
+ Tcl_HashSearch search;
+ short oldFileRef;
+ FCBPBRec newFileRec, oldFileRec;
+ OSErr err;
+
+ oldFileRec.ioCompletion = NULL;
+ oldFileRec.ioFCBIndx = 0;
+ oldFileRec.ioNamePtr = NULL;
+
+ newFileRec.ioCompletion = NULL;
+ newFileRec.ioFCBIndx = 0;
+ newFileRec.ioNamePtr = NULL;
+ newFileRec.ioVRefNum = 0;
+ newFileRec.ioRefNum = fileRef;
+ err = PBGetFCBInfo(&newFileRec, false);
+
+
+ resourceHashPtr = Tcl_FirstHashEntry(&resourceTable, &search);
+ while (resourceHashPtr != NULL) {
+
+ oldFileRef = (short) Tcl_GetHashKey(&resourceTable,
+ resourceHashPtr);
+
+
+ oldFileRec.ioVRefNum = 0;
+ oldFileRec.ioRefNum = oldFileRef;
+ err = PBGetFCBInfo(&oldFileRec, false);
+
+ /*
+ * err might not be noErr either because the file has closed
+ * out from under us somehow, which is bad but we're not going
+ * to fix it here, OR because it is the ROM MAP, which has a
+ * fileRef, but can't be gotten to by PBGetFCBInfo.
+ */
+
+ if ((oldFileRef == fileRef) ||
+ ((err == noErr)
+ && (newFileRec.ioFCBVRefNum == oldFileRec.ioFCBVRefNum)
+ && (newFileRec.ioFCBFlNm == oldFileRec.ioFCBFlNm))) {
+
+ resourceId = (char *) Tcl_GetHashValue(resourceHashPtr);
+ Tcl_SetStringObj(tokenPtr, resourceId, -1);
+ return TCL_OK;
+ }
+
+ resourceHashPtr = Tcl_NextHashEntry(&search);
+ }
+
+
+ }
+
+ resourceHashPtr = Tcl_CreateHashEntry(&resourceTable,
+ (char *) fileRef, &new);
+ if (!new) {
+ if (tokenPtr != NULL) {
+ resourceId = (char *) Tcl_GetHashValue(resourceHashPtr);
+ Tcl_SetStringObj(tokenPtr, resourceId, -1);
+ }
+ return TCL_OK;
+ }
+
+
+ /*
+ * If we were passed in a result pointer which is not an empty
+ * string, attempt to use that as the key. If the key already
+ * exists, silently fall back on resource%d...
+ */
+
+ if (tokenPtr != NULL) {
+ char *tokenVal;
+ int length;
+ tokenVal = (char *) Tcl_GetStringFromObj(tokenPtr, &length);
+ if (length > 0) {
+ nameHashPtr = Tcl_FindHashEntry(&nameTable, tokenVal);
+ if (nameHashPtr == NULL) {
+ resourceId = ckalloc(length + 1);
+ memcpy(resourceId, tokenVal, length);
+ resourceId[length] = '\0';
+ }
+ }
+ }
+
+ if (resourceId == NULL) {
+ resourceId = (char *) ckalloc(15);
+ sprintf(resourceId, "resource%d", newId);
+ }
+
+ Tcl_SetHashValue(resourceHashPtr, resourceId);
+ newId++;
+
+ nameHashPtr = Tcl_CreateHashEntry(&nameTable, resourceId, &new);
+ if (!new) {
+ panic("resource id has repeated itself");
+ }
+
+ resourceRef = (OpenResourceFork *) ckalloc(sizeof(OpenResourceFork));
+ resourceRef->fileRef = fileRef;
+ resourceRef->flags = flags;
+
+ Tcl_SetHashValue(nameHashPtr, (ClientData) resourceRef);
+ if (tokenPtr != NULL) {
+ Tcl_SetStringObj(tokenPtr, resourceId, -1);
+ }
+
+ if (flags & TCL_RESOURCE_INSERT_TAIL) {
+ Tcl_ListObjAppendElement(NULL, resourceForkList, tokenPtr);
+ } else {
+ Tcl_ListObjReplace(NULL, resourceForkList, 0, 0, 1, &tokenPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclMacUnRegisterResourceFork --
+ *
+ * Removes the entry for an open resource fork from the table of
+ * open resources managed by the procedures in this file.
+ * If resultPtr is not NULL, it will be used for error reporting.
+ *
+ * Results:
+ * The fileRef for this token, or -1 if an error occured.
+ *
+ * Side effects:
+ * An entry is removed from the resource name table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+short
+TclMacUnRegisterResourceFork(
+ char *tokenPtr,
+ Tcl_Obj *resultPtr)
+
+{
+ Tcl_HashEntry *resourceHashPtr;
+ Tcl_HashEntry *nameHashPtr;
+ OpenResourceFork *resourceRef;
+ char *resourceId = NULL;
+ short fileRef;
+ char *bytes;
+ int i, match, index, listLen, length, elemLen;
+ Tcl_Obj **elemPtrs;
+
+
+ nameHashPtr = Tcl_FindHashEntry(&nameTable, tokenPtr);
+ if (nameHashPtr == NULL) {
+ if (resultPtr != NULL) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "invalid resource file reference \"",
+ tokenPtr, "\"", (char *) NULL);
+ }
+ return -1;
+ }
+
+ resourceRef = (OpenResourceFork *) Tcl_GetHashValue(nameHashPtr);
+ fileRef = resourceRef->fileRef;
+
+ if ( resourceRef->flags & TCL_RESOURCE_DONT_CLOSE ) {
+ if (resultPtr != NULL) {
+ Tcl_AppendStringsToObj(resultPtr,
+ "can't close \"", tokenPtr, "\" resource file",
+ (char *) NULL);
+ }
+ return -1;
+ }
+
+ Tcl_DeleteHashEntry(nameHashPtr);
+ ckfree((char *) resourceRef);
+
+
+ /*
+ * Now remove the resource from the resourceForkList object
+ */
+
+ Tcl_ListObjGetElements(NULL, resourceForkList, &listLen, &elemPtrs);
+
+
+ index = -1;
+ length = strlen(tokenPtr);
+
+ for (i = 0; i < listLen; i++) {
+ match = 0;
+ bytes = Tcl_GetStringFromObj(elemPtrs[i], &elemLen);
+ if (length == elemLen) {
+ match = (memcmp(bytes, tokenPtr,
+ (size_t) length) == 0);
+ }
+ if (match) {
+ index = i;
+ break;
+ }
+ }
+ if (!match) {
+ panic("the resource Fork List is out of synch!");
+ }
+
+ Tcl_ListObjReplace(NULL, resourceForkList, index, 1, 0, NULL);
+
+ resourceHashPtr = Tcl_FindHashEntry(&resourceTable, (char *) fileRef);
+
+ if (resourceHashPtr == NULL) {
+ panic("Resource & Name tables are out of synch in resource command.");
+ }
+ ckfree(Tcl_GetHashValue(resourceHashPtr));
+ Tcl_DeleteHashEntry(resourceHashPtr);
+
+ return fileRef;
+
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BuildResourceForkList --
+ *
+ * Traverses the list of open resource forks, and builds the
+ * list of resources forks. Also creates a resource token for any that
+ * are opened but not registered with our resource system.
+ * This is based on code from Apple DTS.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The list of resource forks is updated.
+ * The resource name table may be augmented.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+BuildResourceForkList()
+{
+ Handle currentMapHandle, mSysMapHandle;
+ Ptr tempPtr;
+ FCBPBRec fileRec;
+ char fileName[256];
+ char appName[62];
+ Tcl_Obj *nameObj;
+ OSErr err;
+ ProcessSerialNumber psn;
+ ProcessInfoRec info;
+ FSSpec fileSpec;
+
+ /*
+ * Get the application name, so we can substitute
+ * the token "application" for the application's resource.
+ */
+
+ GetCurrentProcess(&psn);
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = (StringPtr) &appName;
+ info.processAppSpec = &fileSpec;
+ GetProcessInformation(&psn, &info);
+ p2cstr((StringPtr) appName);
+
+
+ fileRec.ioCompletion = NULL;
+ fileRec.ioVRefNum = 0;
+ fileRec.ioFCBIndx = 0;
+ fileRec.ioNamePtr = (StringPtr) &fileName;
+
+
+ currentMapHandle = LMGetTopMapHndl();
+ mSysMapHandle = LMGetSysMapHndl();
+
+ while (1) {
+ /*
+ * Now do the ones opened after the application.
+ */
+
+ nameObj = Tcl_NewObj();
+
+ tempPtr = *currentMapHandle;
+
+ fileRec.ioRefNum = *((short *) (tempPtr + 20));
+ err = PBGetFCBInfo(&fileRec, false);
+
+ if (err != noErr) {
+ /*
+ * The ROM resource map does not correspond to an opened file...
+ */
+ Tcl_SetStringObj(nameObj, "ROM Map", -1);
+ } else {
+ p2cstr((StringPtr) fileName);
+ if (strcmp(fileName,(char *) appName) == 0) {
+ Tcl_SetStringObj(nameObj, "application", -1);
+ } else {
+ Tcl_SetStringObj(nameObj, fileName, -1);
+ }
+ c2pstr(fileName);
+ }
+
+ TclMacRegisterResourceFork(fileRec.ioRefNum, nameObj,
+ TCL_RESOURCE_DONT_CLOSE | TCL_RESOURCE_INSERT_TAIL);
+
+ if (currentMapHandle == mSysMapHandle) {
+ break;
+ }
+
+ currentMapHandle = *((Handle *) (tempPtr + 16));
+ }
+}
diff --git a/mac/tclMacResource.r b/mac/tclMacResource.r
new file mode 100644
index 0000000..a25d476
--- /dev/null
+++ b/mac/tclMacResource.r
@@ -0,0 +1,92 @@
+/*
+ * tclMacResource.r --
+ *
+ * This file creates resources for use in a simple shell.
+ * This is designed to be an example of using the Tcl libraries
+ * statically in a Macintosh Application. For an example of
+ * of using the dynamic libraries look at tclMacApplication.r.
+ *
+ * Copyright (c) 1993-94 Lockheed Missle & Space Company
+ * Copyright (c) 1994-97 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacResource.r 1.19 97/09/23 12:51:41
+ */
+
+#include <Types.r>
+#include <SysTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include "tcl.h"
+
+#if (TCL_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TCL_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TCL_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TCL_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TCL_MINOR_VERSION * 16) + TCL_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TCL_MINOR_VERSION * 16
+#endif
+
+resource 'vers' (1) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ TCL_PATCH_LEVEL ", by Ray Johnson © Sun Microsystems"
+};
+
+resource 'vers' (2) {
+ TCL_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TCL_PATCH_LEVEL,
+ "Simple Tcl Shell " TCL_PATCH_LEVEL " © 1996"
+};
+
+
+/*
+ * The mechanisim below loads Tcl source into the resource fork of the
+ * application. The example below creates a TEXT resource named
+ * "Init" from the file "init.tcl". This allows applications to use
+ * Tcl to define the behavior of the application without having to
+ * require some predetermined file structure - all needed Tcl "files"
+ * are located within the application. To source a file for the
+ * resource fork the source command has been modified to support
+ * sourcing from resources. In the below case "source -rsrc {Init}"
+ * will load the TEXT resource named "Init".
+ */
+
+read 'TEXT' (0, "Init", purgeable, preload) "::library:init.tcl";
+read 'TEXT' (1, "History", purgeable,preload) "::library:history.tcl";
+read 'TEXT' (2, "Word", purgeable,preload) "::library:word.tcl";
+
+/*
+ * The following resource is used when creating the 'env' variable in
+ * the Macintosh environment. The creation mechanisim looks for the
+ * 'STR#' resource named "Tcl Environment Variables" rather than a
+ * specific resource number. (In other words, feel free to change the
+ * resource id if it conflicts with your application.) Each string in
+ * the resource must be of the form "KEYWORD=SOME STRING". See Tcl
+ * documentation for futher information about the env variable.
+ *
+ * A good example of something you may want to set is: "TCL_LIBRARY=My
+ * disk:etc."
+ */
+
+resource 'STR#' (128, "Tcl Environment Variables") {
+ { "SCHEDULE_NAME=Agent Controller Schedule",
+ "SCHEDULE_PATH=Lozoya:System Folder:Tcl Lib:Tcl-Scheduler"
+ };
+};
+
diff --git a/mac/tclMacShLib.exp b/mac/tclMacShLib.exp
new file mode 100644
index 0000000..8936114
--- /dev/null
+++ b/mac/tclMacShLib.exp
@@ -0,0 +1,1069 @@
+AddrToName
+AddrToStr
+BuildAFPVolMountInfo
+BumpDate
+ChangeCreatorType
+ChangeFDFlags
+CheckObjectLock
+CheckVolLock
+ClearHasBeenInited
+ClearHasCustomIcon
+ClearIsInvisible
+ClearIsStationery
+ClearNameLocked
+CloseResolver
+ConfigureMemory
+CopyDirectoryAccess
+CopyFileMgrAttributes
+CopyFork
+CreateFileIDRef
+DTCopyComment
+DTGetIcon
+DTOpen
+DTSetComment
+DeleteDirectory
+DeleteDirectoryContents
+DeleteFileIDRef
+DetermineVRefNum
+DirectoryCopy
+EnumCache
+##EnvStr
+ExchangeFiles
+FSMakeFSSpecCompat
+FSReadNoCache
+FSWriteNoCache
+FSWriteVerify
+FSpBumpDate
+FSpCatMoveCompat
+FSpChangeCreatorType
+FSpChangeFDFlags
+FSpCheckObjectLock
+FSpClearHasBeenInited
+FSpClearHasCustomIcon
+FSpClearIsInvisible
+FSpClearIsStationery
+FSpClearNameLocked
+FSpCopyDirectoryAccess
+FSpCopyFile
+FSpCopyFileMgrAttributes
+FSpCreateCompat
+FSpCreateFileIDRef
+FSpCreateMinimum
+FSpCreateResFileCompat
+FSpDTCopyComment
+FSpDTSetComment
+FSpDeleteCompat
+FSpDirCreateCompat
+FSpDirectoryCopy
+FSpExchangeFilesCompat
+FSpFileCopy
+FSpFilteredDirectoryCopy
+FSpFindFolder
+FSpGetDInfo
+FSpGetDefaultDir
+FSpGetDirAccess
+FSpGetDirectoryID
+FSpGetFInfoCompat
+FSpGetFLockCompat
+FSpGetFileLocation
+FSpGetFileSize
+FSpGetForeignPrivs
+FSpGetFullPath
+FSpGetIOACUser
+FSpLocationFromFullPath
+FSpLocationFromPath
+FSpMoveRename
+FSpMoveRenameCompat
+FSpOpenAware
+FSpOpenDFCompat
+FSpOpenRFAware
+FSpOpenRFCompat
+FSpOpenResFileCompat
+FSpPathFromLocation
+FSpRenameCompat
+FSpResolveFileIDRef
+FSpRstFLockCompat
+FSpSetDInfo
+FSpSetDefaultDir
+FSpSetDirAccess
+FSpSetFInfoCompat
+FSpSetFLockCompat
+FSpSetForeignPrivs
+FSpSetHasCustomIcon
+FSpSetIsInvisible
+FSpSetIsStationery
+FSpSetNameLocked
+FSpShare
+FSpUnshare
+FileCopy
+FilteredDirectoryCopy
+FindDrive
+FlushFile
+FreeAllMemory
+GetCPanelFolder
+GetCatInfoNoName
+GetDInfo
+GetDirItems
+GetDirName
+GetDirectoryID
+GetDiskBlocks
+GetDriverName
+GetFileLocation
+GetFileSize
+GetFilenameFromPathname
+GetForeignPrivs
+GetFullPath
+GetGlobalMouse
+GetIOACUser
+GetObjectLocation
+GetParentID
+GetSystemFolder
+GetTempBuffer
+GetTrapType
+GetUGEntries
+GetUGEntry
+GetVolMountInfo
+GetVolMountInfoSize
+GetVolumeInfoNoName
+HCopyFile
+HCreateMinimum
+HGetDirAccess
+HGetLogInInfo
+HGetVInfo
+HGetVolParms
+HInfo
+HMapID
+HMapName
+HMoveRename
+HMoveRenameCompat
+HOpenAware
+HOpenRFAware
+hypotd
+HSetDirAccess
+InstallConsole
+LocationFromFullPath
+LockRange
+MXInfo
+NumToolboxTraps
+OnLine
+OpenOurRF
+OpenResolver
+PBXGetVolInfoSync
+ReadCharsFromConsole
+RemoveConsole
+ResolveFileIDRef
+RestoreDefault
+RetrieveAFPVolMountInfo
+SIOUXBigRect
+SIOUXCantSaveAlert
+SIOUXDoAboutBox
+SIOUXDoContentClick
+SIOUXDoEditClear
+SIOUXDoEditCopy
+SIOUXDoEditCut
+SIOUXDoEditPaste
+SIOUXDoEditSelectAll
+SIOUXDoMenuChoice
+SIOUXDoPageSetup
+SIOUXDoPrintText
+SIOUXDoSaveText
+SIOUXDragRect
+SIOUXDrawGrowBox
+SIOUXHandleOneEvent
+SIOUXIsAppWindow
+SIOUXMyGrowWindow
+SIOUXQuitting
+SIOUXSetTitle
+SIOUXSettings
+SIOUXSetupMenus
+SIOUXSetupTextWindow
+SIOUXState
+SIOUXTextWindow
+SIOUXUpdateMenuItems
+SIOUXUpdateScrollbar
+SIOUXUpdateStatusLine
+SIOUXUpdateWindow
+SIOUXUseWaitNextEvent
+SIOUXYesNoCancelAlert
+SIOUXisinrange
+SIOUXselstart
+SearchFolderForDNRP
+SetDInfo
+SetDefault
+SetForeignPrivs
+SetHasCustomIcon
+SetIsInvisible
+SetIsStationery
+SetNameLocked
+Share
+StrToAddr
+TclAllocateFreeObjects
+TclChdir
+TclCleanupByteCode
+TclCleanupCommand
+TclCompileBreakCmd
+TclCompileCatchCmd
+TclCompileContinueCmd
+TclCompileDollarVar
+TclCompileExpr
+TclCompileExprCmd
+TclCompileForCmd
+TclCompileForeachCmd
+TclCompileIfCmd
+TclCompileIncrCmd
+TclCompileQuotes
+TclCompileSetCmd
+TclCompileString
+TclCompileWhileCmd
+TclCopyAndCollapse
+TclCopyChannel
+TclCreateAuxData
+TclCreateExecEnv
+TclDate_TclDates
+TclDate_TclDatev
+TclDateact
+TclDatechar
+TclDatechk
+TclDatedebug
+TclDatedef
+TclDateerrflag
+TclDateexca
+TclDatelval
+TclDatenerrs
+TclDatepact
+TclDateparse
+TclDatepgo
+TclDateps
+TclDatepv
+TclDater1
+TclDater2
+TclDates
+TclDatestate
+TclDatetmp
+TclDatev
+TclDateval
+TclDeleteCompiledLocalVars
+TclDeleteExecEnv
+TclDeleteVars
+TclDoGlob
+TclEmitForwardJump
+TclExecuteByteCode
+TclExpandCodeArray
+TclExpandJumpFixupArray
+TclExpandParseValue
+TclExprFloatError
+TclFileAttrsCmd
+TclFileCopyCmd
+TclFileDeleteCmd
+TclFileMakeDirsCmd
+TclFileRenameCmd
+TclFindElement
+TclFindProc
+TclFixupForwardJump
+TclFormatInt
+TclFreeCompileEnv
+TclFreeJumpFixupArray
+TclFreeObj
+TclFreePackageInfo
+TclGetCwd
+TclGetDate
+TclGetDefaultStdChannel
+TclGetElementOfIndexedArray
+TclGetEnv
+TclGetExceptionRangeForPc
+TclGetExtension
+TclGetFrame
+TclGetIndexedScalar
+TclGetIntForIndex
+TclGetLoadedPackages
+TclGetLong
+TclGetNamespaceForQualName
+TclGetOpenMode
+TclGetOriginalCommand
+TclGetRegError
+TclGetSrcInfoForPc
+TclGetUserHome
+TclGlobalInvoke
+TclGuessPackageName
+TclHasSockets
+TclHideUnsafeCommands
+TclInExit
+TclIncrElementOfIndexedArray
+TclIncrIndexedScalar
+TclIncrVar2
+TclInitByteCodeObj
+TclInitCompileEnv
+TclInitJumpFixupArray
+TclInitNamespaces
+TclInterpInit
+TclInvoke
+TclInvokeObjectCommand
+TclInvokeStringCommand
+TclIsProc
+TclLoadFile
+TclLooksLikeInt
+TclLookupVar
+TclMacAccess
+TclMacCreateEnv
+TclMacExitHandler
+TclMacFOpenHack
+TclMacInitExitToShell
+TclMacInstallExitToShellPatch
+TclMacOSErrorToPosixError
+TclMacReadlink
+TclMacRemoveTimer
+TclMacStartTimer
+TclMacStat
+TclMacTimerExpired
+TclMatchFiles
+TclNeedSpace
+TclObjIndexForString
+TclObjInterpProc
+TclObjInvoke
+TclObjInvokeGlobal
+TclParseBraces
+TclParseNestedCmd
+TclParseQuotes
+TclPlatformExit
+TclPlatformInit
+TclPreventAliasLoop
+TclPrintByteCodeObj
+TclPrintInstruction
+TclPrintSource
+TclRegComp
+TclRegError
+TclRegExec
+TclRenameCommand
+TclResetShadowedCmdRefs
+TclServiceIdle
+TclSetElementOfIndexedArray
+TclSetEnv
+TclSetIndexedScalar
+TclSetupEnv
+TclSockGetPort
+TclTeardownNamespace
+TclTestChannelCmd
+TclTestChannelEventCmd
+TclUnsetEnv
+TclUpdateReturnInfo
+TclWordEnd
+Tcl_AddErrorInfo
+Tcl_AddObjErrorInfo
+Tcl_AfterCmd
+Tcl_Alloc
+Tcl_AllowExceptions
+Tcl_AppendAllObjTypes
+Tcl_AppendElement
+Tcl_AppendObjCmd
+Tcl_AppendResult
+Tcl_AppendStringsToObj
+Tcl_AppendToObj
+Tcl_ArrayObjCmd
+Tcl_AsyncCreate
+Tcl_AsyncDelete
+Tcl_AsyncInvoke
+Tcl_AsyncMark
+Tcl_AsyncReady
+Tcl_BackgroundError
+Tcl_Backslash
+Tcl_BeepObjCmd
+Tcl_BinaryObjCmd
+Tcl_BreakCmd
+Tcl_CallWhenDeleted
+Tcl_CancelIdleCall
+Tcl_CaseObjCmd
+Tcl_CatchObjCmd
+Tcl_ClockObjCmd
+Tcl_Close
+Tcl_CommandComplete
+Tcl_Concat
+Tcl_ConcatObj
+Tcl_ConcatObjCmd
+Tcl_ContinueCmd
+Tcl_ConvertCountedElement
+Tcl_ConvertElement
+Tcl_ConvertToType
+Tcl_CreateAlias
+Tcl_CreateAliasObj
+Tcl_CreateChannel
+Tcl_CreateChannelHandler
+Tcl_CreateCloseHandler
+Tcl_CreateCommand
+Tcl_CreateEventSource
+Tcl_CreateExitHandler
+Tcl_CreateInterp
+Tcl_CreateMathFunc
+Tcl_CreateNamespace
+Tcl_CreateObjCommand
+Tcl_CreateSlave
+Tcl_CreateTimerHandler
+Tcl_CreateTrace
+Tcl_DStringAppend
+Tcl_DStringAppendElement
+Tcl_DStringEndSublist
+Tcl_DStringFree
+Tcl_DStringGetResult
+Tcl_DStringInit
+Tcl_DStringResult
+Tcl_DStringSetLength
+Tcl_DStringStartSublist
+Tcl_DbCkalloc
+Tcl_DbCkfree
+Tcl_DbCkrealloc
+Tcl_DbDecrRefCount
+Tcl_DbIsShared
+Tcl_DbIncrRefCount
+Tcl_DbNewBooleanObj
+Tcl_DbNewDoubleObj
+Tcl_DbNewListObj
+Tcl_DbNewLongObj
+Tcl_DbNewObj
+Tcl_DbNewStringObj
+Tcl_DeleteAssocData
+Tcl_DeleteChannelHandler
+Tcl_DeleteCloseHandler
+Tcl_DeleteCommand
+Tcl_DeleteCommandFromToken
+Tcl_DeleteEventSource
+Tcl_DeleteEvents
+Tcl_DeleteExitHandler
+Tcl_DeleteHashEntry
+Tcl_DeleteHashTable
+Tcl_DeleteInterp
+Tcl_DeleteNamespace
+Tcl_DeleteTimerHandler
+Tcl_DeleteTrace
+Tcl_DoOneEvent
+Tcl_DoWhenIdle
+Tcl_DontCallWhenDeleted
+Tcl_DumpActiveMemory
+Tcl_DuplicateObj
+Tcl_EchoCmd
+Tcl_Eof
+Tcl_ErrnoId
+Tcl_ErrnoMsg
+Tcl_ErrorObjCmd
+Tcl_Eval
+Tcl_EvalFile
+Tcl_EvalObj
+Tcl_EvalObjCmd
+Tcl_EventuallyFree
+Tcl_ExecCmd
+Tcl_Exit
+Tcl_ExitObjCmd
+Tcl_ExposeCommand
+Tcl_ExprBoolean
+Tcl_ExprBooleanObj
+Tcl_ExprDouble
+Tcl_ExprDoubleObj
+Tcl_ExprLong
+Tcl_ExprLongObj
+Tcl_ExprObjCmd
+Tcl_ExprString
+Tcl_FconfigureCmd
+Tcl_FcopyObjCmd
+Tcl_FileEventCmd
+Tcl_FileObjCmd
+Tcl_Finalize
+Tcl_FindCommand
+Tcl_FindExecutable
+Tcl_FindNamespace
+Tcl_FindNamespaceVar
+Tcl_FirstHashEntry
+Tcl_Flush
+Tcl_FlushObjCmd
+Tcl_ForCmd
+Tcl_ForeachObjCmd
+Tcl_ForgetImport
+Tcl_FormatCmd
+Tcl_Free
+Tcl_FreeResult
+Tcl_GetAlias
+Tcl_GetAliasObj
+Tcl_GetAssocData
+Tcl_GetBoolean
+Tcl_GetBooleanFromObj
+Tcl_GetChannel
+Tcl_GetChannelBufferSize
+Tcl_GetChannelHandle
+Tcl_GetChannelInstanceData
+Tcl_GetChannelMode
+Tcl_GetChannelName
+Tcl_GetChannelOption
+Tcl_GetChannelType
+Tcl_GetCommandFromObj
+Tcl_GetCommandFullName
+Tcl_GetCommandInfo
+Tcl_GetCommandName
+Tcl_GetCurrentNamespace
+Tcl_GetDouble
+Tcl_GetDoubleFromObj
+Tcl_GetErrno
+Tcl_GetGlobalNamespace
+Tcl_GetHostName
+Tcl_GetIndexFromObj
+Tcl_GetInt
+Tcl_GetIntFromObj
+Tcl_GetInterpPath
+Tcl_GetLongFromObj
+Tcl_GetMaster
+Tcl_GetOSTypeFromObj
+Tcl_GetObjResult
+Tcl_GetObjType
+Tcl_GetPathType
+Tcl_GetServiceMode
+Tcl_GetSlave
+Tcl_GetStdChannel
+Tcl_GetStringFromObj
+Tcl_GetStringResult
+Tcl_GetVar
+Tcl_GetVar2
+Tcl_GetVariableFullName
+Tcl_Gets
+Tcl_GetsObj
+Tcl_GetsObjCmd
+Tcl_GlobCmd
+Tcl_GlobalEval
+Tcl_GlobalEvalObj
+Tcl_GlobalObjCmd
+Tcl_HashStats
+Tcl_HideCommand
+Tcl_HistoryCmd
+Tcl_IfCmd
+Tcl_Import
+Tcl_IncrCmd
+Tcl_InfoObjCmd
+Tcl_Init
+Tcl_InitHashTable
+Tcl_InitMemory
+Tcl_InputBlocked
+Tcl_InputBuffered
+Tcl_InterpDeleted
+Tcl_InterpObjCmd
+Tcl_IsSafe
+Tcl_JoinObjCmd
+Tcl_JoinPath
+Tcl_LappendObjCmd
+Tcl_LindexObjCmd
+Tcl_LinkVar
+Tcl_LinsertObjCmd
+Tcl_ListObjAppendElement
+Tcl_ListObjAppendList
+Tcl_ListObjCmd
+Tcl_ListObjGetElements
+Tcl_ListObjIndex
+Tcl_ListObjLength
+Tcl_ListObjReplace
+Tcl_LlengthObjCmd
+Tcl_LoadCmd
+Tcl_LrangeObjCmd
+Tcl_LreplaceObjCmd
+Tcl_LsCmd
+Tcl_LsearchObjCmd
+Tcl_LsortObjCmd
+Tcl_MacConvertTextResource
+Tcl_MacEvalResource
+Tcl_MacFindResource
+Tcl_MacSetEventProc
+Tcl_MacSourceObjCmd
+Tcl_Main
+Tcl_MakeSafe
+Tcl_MakeTcpClientChannel
+Tcl_Merge
+Tcl_NamespaceObjCmd
+Tcl_NewBooleanObj
+Tcl_NewDoubleObj
+Tcl_NewIntObj
+Tcl_NewListObj
+Tcl_NewLongObj
+Tcl_NewOSTypeObj
+Tcl_NewObj
+Tcl_NewStringObj
+Tcl_NextHashEntry
+Tcl_NotifyChannel
+Tcl_ObjGetVar2
+Tcl_ObjSetVar2
+Tcl_OpenCmd
+Tcl_OpenFileChannel
+Tcl_OpenTcpClient
+Tcl_OpenTcpServer
+Tcl_PackageCmd
+Tcl_ParseVar
+Tcl_PidObjCmd
+Tcl_PkgProvide
+Tcl_PkgRequire
+Tcl_PopCallFrame
+Tcl_PosixError
+Tcl_Preserve
+Tcl_PrintDouble
+Tcl_ProcObjCmd
+Tcl_PushCallFrame
+Tcl_PutEnv
+Tcl_PutsObjCmd
+Tcl_PwdCmd
+Tcl_QueueEvent
+Tcl_Read
+Tcl_ReadObjCmd
+Tcl_Realloc
+Tcl_RecordAndEval
+Tcl_RegExpCompile
+Tcl_RegExpExec
+Tcl_RegExpMatch
+Tcl_RegExpRange
+Tcl_RegexpCmd
+Tcl_RegisterChannel
+Tcl_RegisterObjType
+Tcl_RegsubCmd
+Tcl_Release
+Tcl_RenameObjCmd
+Tcl_ResetResult
+Tcl_ResourceObjCmd
+Tcl_ReturnObjCmd
+Tcl_ScanCmd
+Tcl_ScanCountedElement
+Tcl_ScanElement
+Tcl_Seek
+Tcl_SeekCmd
+Tcl_ServiceAll
+Tcl_ServiceEvent
+Tcl_SetAssocData
+Tcl_SetBooleanObj
+Tcl_SetChannelBufferSize
+Tcl_SetChannelOption
+Tcl_SetCmd
+Tcl_SetCommandInfo
+Tcl_SetDoubleObj
+Tcl_SetErrno
+Tcl_SetErrorCode
+Tcl_SetIntObj
+Tcl_SetListObj
+Tcl_SetLongObj
+Tcl_SetMaxBlockTime
+Tcl_SetOSTypeObj
+Tcl_SetObjErrorCode
+Tcl_SetObjLength
+Tcl_SetObjResult
+Tcl_SetPanicProc
+Tcl_SetRecursionLimit
+Tcl_SetResult
+Tcl_SetServiceMode
+Tcl_SetStdChannel
+Tcl_SetStringObj
+Tcl_SetTimer
+Tcl_SetVar
+Tcl_SetVar2
+Tcl_SignalId
+Tcl_SignalMsg
+Tcl_Sleep
+Tcl_SocketCmd
+Tcl_SourceObjCmd
+Tcl_SourceRCFile
+Tcl_SplitList
+Tcl_SplitPath
+Tcl_StaticPackage
+Tcl_StringMatch
+Tcl_StringObjCmd
+Tcl_SubstCmd
+Tcl_SwitchObjCmd
+Tcl_Tell
+Tcl_TellCmd
+Tcl_TimeObjCmd
+Tcl_TraceCmd
+Tcl_TraceVar
+Tcl_TraceVar2
+Tcl_TranslateFileName
+Tcl_Ungets
+Tcl_UnlinkVar
+Tcl_UnregisterChannel
+Tcl_UnsetObjCmd
+Tcl_UnsetVar
+Tcl_UnsetVar2
+Tcl_UntraceVar
+Tcl_UntraceVar2
+Tcl_UpVar
+Tcl_UpVar2
+Tcl_UpdateCmd
+Tcl_UpdateLinkedVar
+Tcl_UplevelObjCmd
+Tcl_UpvarObjCmd
+Tcl_ValidateAllMemory
+Tcl_VarEval
+Tcl_VarTraceInfo
+Tcl_VarTraceInfo2
+Tcl_VariableObjCmd
+Tcl_VwaitCmd
+Tcl_WaitForEvent
+Tcl_WaitPid
+Tcl_WhileCmd
+Tcl_Write
+Tcl_WrongNumArgs
+TclpAlloc
+TclpCopyDirectory
+TclpCopyFile
+TclpCreateDirectory
+TclpDeleteFile
+TclpFree
+TclpGetClicks
+TclpGetDate
+TclpGetSeconds
+TclpGetTime
+TclpGetTimeZone
+TclpListVolumes
+TclpRealloc
+TclpRemoveDirectory
+TclpRenameFile
+TrapExists
+TruncPString
+UnlockRange
+UnmountAndEject
+Unshare
+VolumeMount
+WriteCharsToConsole
+XGetVInfo
+_Ctype
+_Stderr
+_Stoul
+abort
+abs
+acosf
+appMemory
+asctime
+asinf
+atan
+atan2
+atan2_d_dd
+atan2_d_pdpd
+atan2_r_prpr
+atan2_r_rr
+atan2f
+atan_d_d
+atan_d_pd
+atan_r_pr
+atan_r_r
+atanf
+atexit
+atof
+atoi
+atol
+bsearch
+builtinFuncTable
+calloc
+ccommand
+ceilf
+chdir
+clearerr
+clock
+close
+closeUPP
+completeUPP
+cos
+cos_d_d
+cos_d_pd
+cos_r_pr
+cos_r_r
+cosf
+coshf
+creat
+ctime
+cuserid
+difftime
+div
+environ
+errno
+exec
+exit
+exp
+exp_d_d
+exp_d_pd
+exp_r_pr
+exp_r_r
+expf
+fabsf
+fclose
+fcntl
+fdopen
+feof
+ferror
+fflush
+fgetc
+fgetpos
+fgets
+fileno
+floorf
+fmodf
+fopen
+fprintf
+fputc
+fputs
+fread
+free
+freopen
+frexpf
+fscanf
+fseek
+fsetpos
+fstat
+ftell
+fwrite
+getStdChannelsProc
+getc
+getchar
+getcwd
+getenv
+getlogin
+gets
+gmtime
+instructionTable
+isalnum
+isalpha
+isatty
+iscntrl
+isdigit
+isgraph
+islower
+isprint
+ispunct
+isspace
+isupper
+isxdigit
+labs
+ldexpf
+ldiv
+localeconv
+localtime
+log
+log10
+log10_d_d
+log10_d_pd
+log10f
+log_d_d
+log_d_pd
+logf
+longjmp
+lseek
+malloc
+mblen
+mbstowcs
+mbtowc
+memchr
+memcmp
+memcpy
+memmove
+memset
+mkdir
+mktime
+open
+panic
+panicProc
+perror
+pow
+power_d_dd
+powf
+printf
+putc
+putchar
+puts
+qsort
+raise
+rand
+read
+realloc
+remove
+rename
+resultUPP
+rewind
+rmdir
+scanf
+setbuf
+setlocale
+setvbuf
+signal
+sin
+sin_d_d
+sin_d_pd
+sin_r_pr
+sin_r_r
+sinf
+sinhf
+sleep
+sprintf
+sqrt
+sqrt_d_d
+sqrt_d_pd
+sqrt_r_pr
+sqrt_r_r
+sqrtf
+srand
+sscanf
+stat
+strcasecmp
+strcat
+strchr
+strcmp
+strcoll
+strcpy
+strcspn
+strerror
+strftime
+strlen
+strncasecmp
+strncat
+strncmp
+strncpy
+strpbrk
+strrchr
+strspn
+strstr
+strtod
+strtok
+strtol
+strtoul
+strxfrm
+system
+systemMemory
+tanf
+tanhf
+tclBooleanType
+tclByteCodeType
+tclCmdNameType
+tclDoubleType
+tclDummyLinkVarPtr
+tclExecutableName
+tclFreeObjList
+tclIndexType
+tclIntType
+tclListType
+tclMemDumpFileName
+tclNsNameType
+tclPlatform
+tclStringType
+tclTraceCompile
+tclTraceExec
+tclTypeTable
+tcl_MathInProgress
+tclpFileAttrProcs
+tclpFileAttrStrings
+tell
+time
+tmpfile
+tmpnam
+tolower
+toupper
+ttyname
+uname
+ungetc
+unlink
+utime
+utimes
+vfprintf
+vprintf
+vsprintf
+wcstombs
+wctob
+wctomb
+write
+#DTGetAPPL
+#DTGetComment
+#FSpDTGetAPPL
+#FSpDTGetComment
+#TclMacInitializeFragment
+#TclMacTerminateFragment
+#_Aldata
+#_Assert
+#_Atcount
+#_Atfuns
+#_Clocale
+#_Closreg
+#_Costate
+#_Daysto
+#_Dbl
+#_Defloc
+#_Environ
+#_Environ1
+#_Fgpos
+#_Files
+#_Flt
+#_Fopen
+#_Foprep
+#_Fread
+#_Freeloc
+#_Frprep
+#_Fspos
+#_Fwprep
+#_Fwrite
+#_Genld
+#_Gentime
+#_Getdst
+#_Getfld
+#_Getfloat
+#_Getint
+#_Getloc
+#_Getmem
+#_Getstr
+#_Gettime
+#_Getzone
+#_Isdst
+#_Ldbl
+#_Ldtob
+#_Litob
+#_Locale
+#_Locsum
+#_Loctab
+#_Locterm
+#_Locvar
+#_MWERKS_Atcount
+#_MWERKS_Atfuns
+#_Makeloc
+#_Makestab
+#_Makewct
+#_Mbcurmax
+#_Mbstate
+#_Mbtowc
+#_Nnl
+#_PJP_C_Copyright
+#_Printf
+#_Putfld
+#_Putstr
+#_Puttxt
+#_Randseed
+#_Readloc
+#_Scanf
+#_Setloc
+#_Skip
+#_Stdin
+#_Stdout
+#_Stod
+#_Stof
+#_Stoflt
+#_Stold
+#_Strerror
+#_Strftime
+#_Strxfrm
+#_Times
+#_Tolower
+#_Toupper
+#_Ttotm
+#_WCostate
+#_Wcstate
+#_Wctob
+#_Wctomb
+#_Wctrans
+#_Wctype
+#__CheckForSystem7
+#__RemoveConsoleHandler__
+#__aborting
+#__ctopstring
+#__cvt_fp2unsigned
+#__getcreator
+#__gettype
+#__initialize
+#__myraise
+#__ptmf_null
+#__ptr_glue
+#__system7present
+#__terminate
+#__ttyname
+#_atexit
+#_exit
+#_fcreator
+#_ftype
diff --git a/mac/tclMacSock.c b/mac/tclMacSock.c
new file mode 100644
index 0000000..fe276f1
--- /dev/null
+++ b/mac/tclMacSock.c
@@ -0,0 +1,2615 @@
+/*
+ * tclMacSock.c
+ *
+ * Channel drivers for Macintosh sockets.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacSock.c 1.59 97/10/09 18:24:42
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include "tclMacInt.h"
+#include <AddressXlation.h>
+#include <Aliases.h>
+#undef Status
+#include <Devices.h>
+#include <Errors.h>
+#include <Events.h>
+#include <Files.h>
+#include <Gestalt.h>
+#include <MacTCP.h>
+#include <Processes.h>
+#include <Strings.h>
+
+/*
+ * The following variable is used to tell whether this module has been
+ * initialized.
+ */
+
+static int initialized = 0;
+
+/*
+ * If debugging is on we may drop into the debugger to handle certain cases
+ * that are not supposed to happen. Otherwise, we change ignore the error
+ * and most code should handle such errors ok.
+ */
+
+#ifndef TCL_DEBUG
+ #define Debugger()
+#endif
+
+/*
+ * The preferred buffer size for Macintosh channels.
+ */
+
+#define CHANNEL_BUF_SIZE 8192
+
+/*
+ * Port information structure. Used to match service names
+ * to a Tcp/Ip port number.
+ */
+
+typedef struct {
+ char *name; /* Name of service. */
+ int port; /* Port number. */
+} PortInfo;
+
+/*
+ * This structure describes per-instance state of a tcp based channel.
+ */
+
+typedef struct TcpState {
+ TCPiopb pb; /* Parameter block used by this stream.
+ * This must be in the first position. */
+ ProcessSerialNumber psn; /* PSN used to wake up process. */
+ StreamPtr tcpStream; /* Macintosh tcp stream pointer. */
+ int port; /* The port we are connected to. */
+ int flags; /* Bit field comprised of the flags
+ * described below. */
+ int checkMask; /* OR'ed combination of TCL_READABLE and
+ * TCL_WRITABLE as set by an asynchronous
+ * event handler. */
+ int watchMask; /* OR'ed combination of TCL_READABLE and
+ * TCL_WRITABLE as set by Tcl_WatchFile. */
+ Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */
+ ClientData acceptProcData; /* The data for the accept proc. */
+ wdsEntry dataSegment[2]; /* List of buffers to be written async. */
+ rdsEntry rdsarray[5+1]; /* Array used when cleaning out recieve
+ * buffers on a closing socket. */
+ Tcl_Channel channel; /* Channel associated with this socket. */
+ struct TcpState *nextPtr; /* The next socket on the global socket
+ * list. */
+} TcpState;
+
+/*
+ * This structure is used by domain name resolver callback.
+ */
+
+typedef struct DNRState {
+ struct hostInfo hostInfo; /* Data structure used by DNR functions. */
+ int done; /* Flag to determine when we are done. */
+ ProcessSerialNumber psn; /* Process to wake up when we are done. */
+} DNRState;
+
+/*
+ * The following macros may be used to set the flags field of
+ * a TcpState structure.
+ */
+
+#define TCP_ASYNC_SOCKET (1<<0) /* The socket is in async mode. */
+#define TCP_ASYNC_CONNECT (1<<1) /* The socket is trying to connect. */
+#define TCP_CONNECTED (1<<2) /* The socket is connected. */
+#define TCP_PENDING (1<<3) /* A SocketEvent is on the queue. */
+#define TCP_LISTENING (1<<4) /* This socket is listening for
+ * a connection. */
+#define TCP_LISTEN_CONNECT (1<<5) /* Someone has connect to the
+ * listening port. */
+#define TCP_REMOTE_CLOSED (1<<6) /* The remote side has closed
+ * the connection. */
+#define TCP_RELEASE (1<<7) /* The socket may now be released. */
+#define TCP_WRITING (1<<8) /* A background write is in progress. */
+#define TCP_SERVER_ZOMBIE (1<<9) /* The server can no longer accept connects. */
+
+/*
+ * The following structure is what is added to the Tcl event queue when
+ * a socket event occurs.
+ */
+
+typedef struct SocketEvent {
+ Tcl_Event header; /* Information that is standard for
+ * all events. */
+ TcpState *statePtr; /* Socket descriptor that is ready. */
+ StreamPtr tcpStream; /* Low level Macintosh stream. */
+} SocketEvent;
+
+/*
+ * Static routines for this file:
+ */
+
+static pascal void CleanUpExitProc _ANSI_ARGS_((void));
+static void ClearZombieSockets _ANSI_ARGS_((void));
+static void CloseCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
+static TcpState * CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
+ int port, char *host, char *myAddr, int myPort,
+ int server, int async));
+static pascal void DNRCompletionRoutine _ANSI_ARGS_((
+ struct hostInfo *hostinfoPtr,
+ DNRState *dnrStatePtr));
+static void FreeSocketInfo _ANSI_ARGS_((TcpState *statePtr));
+static long GetBufferSize _ANSI_ARGS_((void));
+static OSErr GetHostFromString _ANSI_ARGS_((char *name,
+ ip_addr *address));
+static OSErr GetLocalAddress _ANSI_ARGS_((unsigned long *addr));
+static void IOCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
+static void InitMacTCPParamBlock _ANSI_ARGS_((TCPiopb *pBlock,
+ int csCode));
+static void InitSockets _ANSI_ARGS_((void));
+static TcpState * NewSocketInfo _ANSI_ARGS_((StreamPtr stream));
+static OSErr ResolveAddress _ANSI_ARGS_((ip_addr tcpAddress,
+ Tcl_DString *dsPtr));
+static void SocketCheckProc _ANSI_ARGS_((ClientData clientData,
+ int flags));
+static int SocketEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
+ int flags));
+static void SocketExitHandler _ANSI_ARGS_((ClientData clientData));
+static void SocketFreeProc _ANSI_ARGS_((ClientData clientData));
+static int SocketReady _ANSI_ARGS_((TcpState *statePtr));
+static void SocketSetupProc _ANSI_ARGS_((ClientData clientData,
+ int flags));
+static void TcpAccept _ANSI_ARGS_((TcpState *statePtr));
+static int TcpBlockMode _ANSI_ARGS_((ClientData instanceData, int mode));
+static int TcpClose _ANSI_ARGS_((ClientData instanceData,
+ Tcl_Interp *interp));
+static int TcpGetHandle _ANSI_ARGS_((ClientData instanceData,
+ int direction, ClientData *handlePtr));
+static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,
+ Tcl_Interp *interp, char *optionName,
+ Tcl_DString *dsPtr));
+static int TcpInput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toRead, int *errorCodePtr));
+static int TcpOutput _ANSI_ARGS_((ClientData instanceData,
+ char *buf, int toWrite, int *errorCodePtr));
+static void TcpWatch _ANSI_ARGS_((ClientData instanceData,
+ int mask));
+static int WaitForSocketEvent _ANSI_ARGS_((TcpState *infoPtr,
+ int mask, int *errorCodePtr));
+
+/*
+ * This structure describes the channel type structure for TCP socket
+ * based IO:
+ */
+
+static Tcl_ChannelType tcpChannelType = {
+ "tcp", /* Type name. */
+ TcpBlockMode, /* Set blocking or
+ * non-blocking mode.*/
+ TcpClose, /* Close proc. */
+ TcpInput, /* Input proc. */
+ TcpOutput, /* Output proc. */
+ NULL, /* Seek proc. */
+ NULL, /* Set option proc. */
+ TcpGetOptionProc, /* Get option proc. */
+ TcpWatch, /* Initialize notifier. */
+ TcpGetHandle /* Get handles out of channel. */
+};
+
+/*
+ * Universal Procedure Pointers (UPP) for various callback
+ * routines used by MacTcp code.
+ */
+
+ResultUPP resultUPP = NULL;
+TCPIOCompletionUPP completeUPP = NULL;
+TCPIOCompletionUPP closeUPP = NULL;
+
+/*
+ * Built-in commands, and the procedures associated with them:
+ */
+
+static PortInfo portServices[] = {
+ {"echo", 7},
+ {"discard", 9},
+ {"systat", 11},
+ {"daytime", 13},
+ {"netstat", 15},
+ {"chargen", 19},
+ {"ftp-data", 20},
+ {"ftp", 21},
+ {"telnet", 23},
+ {"telneto", 24},
+ {"smtp", 25},
+ {"time", 37},
+ {"whois", 43},
+ {"domain", 53},
+ {"gopher", 70},
+ {"finger", 79},
+ {"hostnames", 101},
+ {"sunrpc", 111},
+ {"nntp", 119},
+ {"exec", 512},
+ {"login", 513},
+ {"shell", 514},
+ {"printer", 515},
+ {"courier", 530},
+ {"uucp", 540},
+ {NULL, 0},
+};
+
+/*
+ * Every open socket has an entry on the following list.
+ */
+
+static TcpState *socketList = NULL;
+
+/*
+ * Globals for holding information about OS support for sockets.
+ */
+
+static int socketsTestInited = false;
+static int hasSockets = false;
+static short driverRefNum = 0;
+static int socketNumber = 0;
+static int socketBufferSize = CHANNEL_BUF_SIZE;
+static ProcessSerialNumber applicationPSN;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitSockets --
+ *
+ * Load the MacTCP driver and open the name resolver. We also
+ * create several UPP's used by our code. Lastly, we install
+ * a patch to ExitToShell to clean up socket connections if
+ * we are about to exit.
+ *
+ * Results:
+ * 1 if successful, 0 on failure.
+ *
+ * Side effects:
+ * Creates a new event source, loads the MacTCP driver,
+ * registers an exit to shell callback.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#define gestaltMacTCPVersion 'mtcp'
+static void
+InitSockets()
+{
+ ParamBlockRec pb;
+ OSErr err;
+ long response;
+
+ initialized = 1;
+ Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL);
+
+ if (Gestalt(gestaltMacTCPVersion, &response) == noErr) {
+ hasSockets = true;
+ } else {
+ hasSockets = false;
+ }
+
+ if (!hasSockets) {
+ return;
+ }
+
+ /*
+ * Load MacTcp driver and name server resolver.
+ */
+
+
+ pb.ioParam.ioCompletion = 0L;
+ pb.ioParam.ioNamePtr = "\p.IPP";
+ pb.ioParam.ioPermssn = fsCurPerm;
+ err = PBOpenSync(&pb);
+ if (err != noErr) {
+ hasSockets = 0;
+ return;
+ }
+ driverRefNum = pb.ioParam.ioRefNum;
+
+ socketBufferSize = GetBufferSize();
+ err = OpenResolver(NULL);
+ if (err != noErr) {
+ hasSockets = 0;
+ return;
+ }
+
+ GetCurrentProcess(&applicationPSN);
+ /*
+ * Create UPP's for various callback routines.
+ */
+
+ resultUPP = NewResultProc(DNRCompletionRoutine);
+ completeUPP = NewTCPIOCompletionProc(IOCompletionRoutine);
+ closeUPP = NewTCPIOCompletionProc(CloseCompletionRoutine);
+
+ /*
+ * Install an ExitToShell patch. We use this patch instead
+ * of the Tcl exit mechanism because we need to ensure that
+ * these routines are cleaned up even if we crash or are forced
+ * to quit. There are some circumstances when the Tcl exit
+ * handlers may not fire.
+ */
+
+ TclMacInstallExitToShellPatch(CleanUpExitProc);
+
+ Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
+
+ initialized = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketExitHandler --
+ *
+ * Callback invoked during exit clean up to deinitialize the
+ * socket module.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SocketExitHandler(
+ ClientData clientData) /* Not used. */
+{
+ if (hasSockets) {
+ Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL);
+ /* CleanUpExitProc();
+ TclMacDeleteExitToShellPatch(CleanUpExitProc); */
+ }
+ initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclHasSockets --
+ *
+ * This function determines whether sockets are available on the
+ * current system and returns an error in interp if they are not.
+ * Note that interp may be NULL.
+ *
+ * Results:
+ * Returns TCL_OK if the system supports sockets, or TCL_ERROR with
+ * an error in interp.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclHasSockets(
+ Tcl_Interp *interp) /* Interp for error messages. */
+{
+ if (!initialized) {
+ InitSockets();
+ }
+
+ if (hasSockets) {
+ return TCL_OK;
+ }
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "sockets are not available on this system",
+ NULL);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketSetupProc --
+ *
+ * This procedure is invoked before Tcl_DoOneEvent blocks waiting
+ * for an event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adjusts the block time if needed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SocketSetupProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
+{
+ TcpState *statePtr;
+ Tcl_Time blockTime = { 0, 0 };
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return;
+ }
+
+ /*
+ * Check to see if there is a ready socket. If so, poll.
+ */
+
+ for (statePtr = socketList; statePtr != NULL;
+ statePtr = statePtr->nextPtr) {
+ if (statePtr->flags & TCP_RELEASE) {
+ continue;
+ }
+ if (SocketReady(statePtr)) {
+ Tcl_SetMaxBlockTime(&blockTime);
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketCheckProc --
+ *
+ * This procedure is called by Tcl_DoOneEvent to check the socket
+ * event source for events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May queue an event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SocketCheckProc(
+ ClientData data, /* Not used. */
+ int flags) /* Event flags as passed to Tcl_DoOneEvent. */
+{
+ TcpState *statePtr;
+ SocketEvent *evPtr;
+ TcpState dummyState;
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return;
+ }
+
+ /*
+ * Queue events for any ready sockets that don't already have events
+ * queued (caused by persistent states that won't generate WinSock
+ * events).
+ */
+
+ for (statePtr = socketList; statePtr != NULL;
+ statePtr = statePtr->nextPtr) {
+ /*
+ * Check to see if this socket is dead and needs to be cleaned
+ * up. We use a dummy statePtr whose only valid field is the
+ * nextPtr to allow the loop to continue even if the element
+ * is deleted.
+ */
+
+ if (statePtr->flags & TCP_RELEASE) {
+ if (!(statePtr->flags & TCP_PENDING)) {
+ dummyState.nextPtr = statePtr->nextPtr;
+ SocketFreeProc(statePtr);
+ statePtr = &dummyState;
+ }
+ continue;
+ }
+
+ if (!(statePtr->flags & TCP_PENDING) && SocketReady(statePtr)) {
+ statePtr->flags |= TCP_PENDING;
+ evPtr = (SocketEvent *) ckalloc(sizeof(SocketEvent));
+ evPtr->header.proc = SocketEventProc;
+ evPtr->statePtr = statePtr;
+ evPtr->tcpStream = statePtr->tcpStream;
+ Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketReady --
+ *
+ * This function checks the current state of a socket to see
+ * if any interesting conditions are present.
+ *
+ * Results:
+ * Returns 1 if an event that someone is watching is present, else
+ * returns 0.
+ *
+ * Side effects:
+ * Updates the checkMask for the socket to reflect any newly
+ * detected events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SocketReady(
+ TcpState *statePtr)
+{
+ TCPiopb statusPB;
+ int foundSomething = 0;
+ int didStatus = 0;
+ int amount;
+ OSErr err;
+
+ if (statePtr->flags & TCP_LISTEN_CONNECT) {
+ foundSomething = 1;
+ statePtr->checkMask |= TCL_READABLE;
+ }
+ if (statePtr->watchMask & TCL_READABLE) {
+ if (statePtr->checkMask & TCL_READABLE) {
+ foundSomething = 1;
+ } else if (statePtr->flags & TCP_CONNECTED) {
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = statePtr->tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ didStatus = 1;
+
+ /*
+ * We make the fchannel readable if 1) we get an error,
+ * 2) there is more data available, or 3) we detect
+ * that a close from the remote connection has arrived.
+ */
+
+ if ((err != noErr) ||
+ (statusPB.csParam.status.amtUnreadData > 0) ||
+ (statusPB.csParam.status.connectionState == 14)) {
+ statePtr->checkMask |= TCL_READABLE;
+ foundSomething = 1;
+ }
+ }
+ }
+ if (statePtr->watchMask & TCL_WRITABLE) {
+ if (statePtr->checkMask & TCL_WRITABLE) {
+ foundSomething = 1;
+ } else if (statePtr->flags & TCP_CONNECTED) {
+ if (!didStatus) {
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = statePtr->tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ }
+
+ /*
+ * If there is an error or there if there is room to
+ * send more data we make the channel writeable.
+ */
+
+ amount = statusPB.csParam.status.sendWindow -
+ statusPB.csParam.status.amtUnackedData;
+ if ((err != noErr) || (amount > 0)) {
+ statePtr->checkMask |= TCL_WRITABLE;
+ foundSomething = 1;
+ }
+ }
+ }
+ return foundSomething;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitMacTCPParamBlock--
+ *
+ * Initialize a MacTCP parameter block.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Initializes the parameter block.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitMacTCPParamBlock(
+ TCPiopb *pBlock, /* Tcp parmeter block. */
+ int csCode) /* Tcp operation code. */
+{
+ memset(pBlock, 0, sizeof(TCPiopb));
+ pBlock->ioResult = 1;
+ pBlock->ioCRefNum = driverRefNum;
+ pBlock->csCode = (short) csCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpBlockMode --
+ *
+ * Set blocking or non-blocking mode on channel.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or non-blocking mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpBlockMode(
+ ClientData instanceData, /* Channel state. */
+ int mode) /* The mode to set. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+
+ if (mode == TCL_MODE_BLOCKING) {
+ statePtr->flags &= ~TCP_ASYNC_SOCKET;
+ } else {
+ statePtr->flags |= TCP_ASYNC_SOCKET;
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpClose --
+ *
+ * Close the socket.
+ *
+ * Results:
+ * 0 if successful, the value of errno if failed.
+ *
+ * Side effects:
+ * Closes the socket.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpClose(
+ ClientData instanceData, /* The socket to close. */
+ Tcl_Interp *interp) /* Interp for error messages. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+ StreamPtr tcpStream;
+ TCPiopb closePB;
+ OSErr err;
+
+ tcpStream = statePtr->tcpStream;
+ statePtr->flags &= ~TCP_CONNECTED;
+
+ /*
+ * If this is a server socket we can't use the statePtr
+ * param block because it is in use. However, we can
+ * close syncronously.
+ */
+
+ if ((statePtr->flags & TCP_LISTENING) ||
+ (statePtr->flags & TCP_LISTEN_CONNECT)) {
+ InitMacTCPParamBlock(&closePB, TCPClose);
+ closePB.tcpStream = tcpStream;
+ closePB.ioCompletion = NULL;
+ err = PBControlSync((ParmBlkPtr) &closePB);
+ if (err != noErr) {
+ Debugger();
+ panic("error closing server socket");
+ }
+ statePtr->flags |= TCP_RELEASE;
+
+ /*
+ * Server sockets are closed sync. Therefor, we know it is OK to
+ * release the socket now.
+ */
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPRelease);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ err = PBControlSync((ParmBlkPtr) &statePtr->pb);
+ if (err != noErr) {
+ panic("error releasing server socket");
+ }
+
+ /*
+ * Free the buffer space used by the socket and the
+ * actual socket state data structure.
+ */
+
+ ckfree((char *) statePtr->pb.csParam.create.rcvBuff);
+ FreeSocketInfo(statePtr);
+ return 0;
+ }
+
+ /*
+ * If this socket is in the midddle on async connect we can just
+ * abort the connect and release the stream right now.
+ */
+
+ if (statePtr->flags & TCP_ASYNC_CONNECT) {
+ InitMacTCPParamBlock(&closePB, TCPClose);
+ closePB.tcpStream = tcpStream;
+ closePB.ioCompletion = NULL;
+ err = PBControlSync((ParmBlkPtr) &closePB);
+ if (err != noErr) {
+ panic("error closing async connect socket");
+ }
+ statePtr->flags |= TCP_RELEASE;
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPRelease);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ err = PBControlSync((ParmBlkPtr) &statePtr->pb);
+ if (err != noErr) {
+ panic("error releasing async connect socket");
+ }
+
+ /*
+ * Free the buffer space used by the socket and the
+ * actual socket state data structure.
+ */
+
+ ckfree((char *) statePtr->pb.csParam.create.rcvBuff);
+ FreeSocketInfo(statePtr);
+ return 0;
+ }
+
+ /*
+ * Client sockets:
+ * If a background write is in progress, don't close
+ * the socket yet. The completion routine for the
+ * write will take care of it.
+ */
+
+ if (!(statePtr->flags & TCP_WRITING)) {
+ InitMacTCPParamBlock(&statePtr->pb, TCPClose);
+ statePtr->pb.tcpStream = tcpStream;
+ statePtr->pb.ioCompletion = closeUPP;
+ statePtr->pb.csParam.close.userDataPtr = (Ptr) statePtr;
+ err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
+ if (err != noErr) {
+ Debugger();
+ statePtr->flags |= TCP_RELEASE;
+ /* return 0; */
+ }
+ }
+
+ SocketFreeProc(instanceData);
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CloseCompletionRoutine --
+ *
+ * Handles the close protocol for a Tcp socket. This will do
+ * a series of calls to release all data currently buffered for
+ * the socket. This is important to do to as it allows the remote
+ * connection to recieve and issue it's own close on the socket.
+ * Note that this function is running at interupt time and can't
+ * allocate memory or do much else except set state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The buffers for the socket are flushed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CloseCompletionRoutine(
+ TCPiopb *pbPtr) /* Tcp parameter block. */
+{
+ TcpState *statePtr;
+ OSErr err;
+
+ if (pbPtr->csCode == TCPClose) {
+ statePtr = (TcpState *) (pbPtr->csParam.close.userDataPtr);
+ } else {
+ statePtr = (TcpState *) (pbPtr->csParam.receive.userDataPtr);
+ }
+
+ /*
+ * It's very bad if the statePtr is nNULL - we should probably panic...
+ */
+
+ if (statePtr == NULL) {
+ Debugger();
+ return;
+ }
+
+ WakeUpProcess(&statePtr->psn);
+
+ /*
+ * If there is an error we assume the remote side has already
+ * close. We are done closing as soon as we decide that the
+ * remote connection has closed.
+ */
+
+ if (pbPtr->ioResult != noErr) {
+ statePtr->flags |= TCP_RELEASE;
+ return;
+ }
+ if (statePtr->flags & TCP_REMOTE_CLOSED) {
+ statePtr->flags |= TCP_RELEASE;
+ return;
+ }
+
+ /*
+ * If we just did a recieve we need to return the buffers.
+ * Otherwise, attempt to recieve more data until we recieve an
+ * error (usually because we have no more data).
+ */
+
+ if (statePtr->pb.csCode == TCPNoCopyRcv) {
+ InitMacTCPParamBlock(&statePtr->pb, TCPRcvBfrReturn);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ statePtr->pb.ioCompletion = closeUPP;
+ statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;
+ statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;
+ err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
+ } else {
+ InitMacTCPParamBlock(&statePtr->pb, TCPNoCopyRcv);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ statePtr->pb.ioCompletion = closeUPP;
+ statePtr->pb.csParam.receive.commandTimeoutValue = 1;
+ statePtr->pb.csParam.receive.rdsPtr = (Ptr) statePtr->rdsarray;
+ statePtr->pb.csParam.receive.rdsLength = 5;
+ statePtr->pb.csParam.receive.userDataPtr = (Ptr) statePtr;
+ err = PBControlAsync((ParmBlkPtr) &statePtr->pb);
+ }
+
+ if (err != noErr) {
+ statePtr->flags |= TCP_RELEASE;
+ }
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketFreeProc --
+ *
+ * This callback is invoked in order to delete
+ * the notifier data associated with a file handle.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Removes the SocketInfo from the global socket list.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SocketFreeProc(
+ ClientData clientData) /* Channel state. */
+{
+ TcpState *statePtr = (TcpState *) clientData;
+ OSErr err;
+ TCPiopb statusPB;
+
+ /*
+ * Get the status of this connection. We need to do a
+ * few tests to see if it's OK to release the stream now.
+ */
+
+ if (!(statePtr->flags & TCP_RELEASE)) {
+ return;
+ }
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = statePtr->tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ if ((statusPB.csParam.status.connectionState == 0) ||
+ (statusPB.csParam.status.connectionState == 2)) {
+ /*
+ * If the conection state is 0 then this was a client
+ * connection and it's closed. If it is 2 then this a
+ * server client and we may release it. If it isn't
+ * one of those values then we return and we'll try to
+ * clean up later.
+ */
+
+ } else {
+ return;
+ }
+
+ /*
+ * The Close request is made async. We know it's
+ * OK to release the socket when the TCP_RELEASE flag
+ * gets set.
+ */
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPRelease);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ err = PBControlSync((ParmBlkPtr) &statePtr->pb);
+ if (err != noErr) {
+ Debugger(); /* Ignoreing leaves stranded stream. Is there an
+ alternative? */
+ }
+
+ /*
+ * Free the buffer space used by the socket and the
+ * actual socket state data structure.
+ */
+
+ ckfree((char *) statePtr->pb.csParam.create.rcvBuff);
+ FreeSocketInfo(statePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpInput --
+ *
+ * Reads input from the IO channel into the buffer given. Returns
+ * count of how many bytes were actually read, and an error
+ * indication.
+ *
+ * Results:
+ * A count of how many bytes were read is returned. A value of -1
+ * implies an error occured. A value of zero means we have reached
+ * the end of data (EOF).
+ *
+ * Side effects:
+ * Reads input from the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TcpInput(
+ ClientData instanceData, /* Channel state. */
+ char *buf, /* Where to store data read. */
+ int bufSize, /* How much space is available
+ * in the buffer? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+ StreamPtr tcpStream;
+ OSErr err;
+ TCPiopb statusPB;
+ int toRead, dataAvail;
+
+ *errorCodePtr = 0;
+ errno = 0;
+ tcpStream = statePtr->tcpStream;
+
+ if (bufSize == 0) {
+ return 0;
+ }
+ toRead = bufSize;
+
+ /*
+ * First check to see if EOF was already detected, to prevent
+ * calling the socket stack after the first time EOF is detected.
+ */
+
+ if (statePtr->flags & TCP_REMOTE_CLOSED) {
+ return 0;
+ }
+
+ /*
+ * If an asynchronous connect is in progress, attempt to wait for it
+ * to complete before reading.
+ */
+
+ if ((statePtr->flags & TCP_ASYNC_CONNECT)
+ && ! WaitForSocketEvent(statePtr, TCL_READABLE, errorCodePtr)) {
+ return -1;
+ }
+
+ /*
+ * No EOF, and it is connected, so try to read more from the socket.
+ * If the socket is blocking, we keep trying until there is data
+ * available or the socket is closed.
+ */
+
+ while (1) {
+
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ if (err != noErr) {
+ Debugger();
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return 0; /* EOF */
+ }
+ dataAvail = statusPB.csParam.status.amtUnreadData;
+ if (dataAvail < bufSize) {
+ toRead = dataAvail;
+ } else {
+ toRead = bufSize;
+ }
+ if (toRead != 0) {
+ /*
+ * Try to read the data.
+ */
+
+ InitMacTCPParamBlock(&statusPB, TCPRcv);
+ statusPB.tcpStream = tcpStream;
+ statusPB.csParam.receive.rcvBuff = buf;
+ statusPB.csParam.receive.rcvBuffLen = toRead;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+
+ statePtr->checkMask &= ~TCL_READABLE;
+ switch (err) {
+ case noErr:
+ /*
+ * The channel remains readable only if this read succeds
+ * and we had more data then the size of the buffer we were
+ * trying to fill. Use the info from the call to status to
+ * determine this.
+ */
+
+ if (dataAvail > bufSize) {
+ statePtr->checkMask |= TCL_READABLE;
+ }
+ return statusPB.csParam.receive.rcvBuffLen;
+ case connectionClosing:
+ *errorCodePtr = errno = ESHUTDOWN;
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return 0;
+ case connectionDoesntExist:
+ case connectionTerminated:
+ *errorCodePtr = errno = ENOTCONN;
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return 0;
+ case invalidStreamPtr:
+ default:
+ *errorCodePtr = EINVAL;
+ return -1;
+ }
+ }
+
+ /*
+ * No data is available, so check the connection state to
+ * see why this is the case.
+ */
+
+ if (statusPB.csParam.status.connectionState == 14) {
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return 0;
+ }
+ if (statusPB.csParam.status.connectionState != 8) {
+ Debugger();
+ }
+ statePtr->checkMask &= ~TCL_READABLE;
+ if (statePtr->flags & TCP_ASYNC_SOCKET) {
+ *errorCodePtr = EWOULDBLOCK;
+ return -1;
+ }
+
+ /*
+ * In the blocking case, wait until the file becomes readable
+ * or closed and try again.
+ */
+
+ if (!WaitForSocketEvent(statePtr, TCL_READABLE, errorCodePtr)) {
+ return -1;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpGetHandle --
+ *
+ * Called from Tcl_GetChannelFile to retrieve handles from inside
+ * a file based channel.
+ *
+ * Results:
+ * The appropriate handle or NULL if not present.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpGetHandle(
+ ClientData instanceData, /* The file state. */
+ int direction, /* Which handle to retrieve? */
+ ClientData *handlePtr)
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+
+ *handlePtr = (ClientData) statePtr->tcpStream;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpOutput--
+ *
+ * Writes the given output on the IO channel. Returns count of how
+ * many characters were actually written, and an error indication.
+ *
+ * Results:
+ * A count of how many characters were written is returned and an
+ * error indication is returned in an output argument.
+ *
+ * Side effects:
+ * Writes output on the actual channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpOutput(
+ ClientData instanceData, /* Channel state. */
+ char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+ StreamPtr tcpStream;
+ OSErr err;
+ int amount;
+ TCPiopb statusPB;
+
+ *errorCodePtr = 0;
+ tcpStream = statePtr->tcpStream;
+
+ /*
+ * If an asynchronous connect is in progress, attempt to wait for it
+ * to complete before writing.
+ */
+
+ if ((statePtr->flags & TCP_ASYNC_CONNECT)
+ && ! WaitForSocketEvent(statePtr, TCL_WRITABLE, errorCodePtr)) {
+ return -1;
+ }
+
+ /*
+ * Loop until we have written some data, or an error occurs.
+ */
+
+ while (1) {
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ if ((err == connectionDoesntExist) || ((err == noErr) &&
+ (statusPB.csParam.status.connectionState == 14))) {
+ /*
+ * The remote connection is gone away. Report an error
+ * and don't write anything.
+ */
+
+ *errorCodePtr = errno = EPIPE;
+ return -1;
+ } else if (err != noErr) {
+ return -1;
+ }
+ amount = statusPB.csParam.status.sendWindow
+ - statusPB.csParam.status.amtUnackedData;
+
+ /*
+ * Attempt to write the data to the socket if a background
+ * write isn't in progress and there is room in the output buffers.
+ */
+
+ if (!(statePtr->flags & TCP_WRITING) && amount > 0) {
+ if (toWrite < amount) {
+ amount = toWrite;
+ }
+ statePtr->dataSegment[0].length = amount;
+ statePtr->dataSegment[0].ptr = buf;
+ statePtr->dataSegment[1].length = 0;
+ InitMacTCPParamBlock(&statePtr->pb, TCPSend);
+ statePtr->pb.ioCompletion = completeUPP;
+ statePtr->pb.tcpStream = tcpStream;
+ statePtr->pb.csParam.send.wdsPtr = (Ptr) statePtr->dataSegment;
+ statePtr->pb.csParam.send.pushFlag = 1;
+ statePtr->pb.csParam.send.userDataPtr = (Ptr) statePtr;
+ statePtr->flags |= TCP_WRITING;
+ err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
+ switch (err) {
+ case noErr:
+ return amount;
+ case connectionClosing:
+ *errorCodePtr = errno = ESHUTDOWN;
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return -1;
+ case connectionDoesntExist:
+ case connectionTerminated:
+ *errorCodePtr = errno = ENOTCONN;
+ statePtr->flags |= TCP_REMOTE_CLOSED;
+ return -1;
+ case invalidStreamPtr:
+ default:
+ return -1;
+ }
+
+ }
+
+ /*
+ * The socket wasn't writable. In the non-blocking case, return
+ * immediately, otherwise wait until the file becomes writable
+ * or closed and try again.
+ */
+
+ if (statePtr->flags & TCP_ASYNC_SOCKET) {
+ statePtr->checkMask &= ~TCL_WRITABLE;
+ *errorCodePtr = EWOULDBLOCK;
+ return -1;
+ } else if (!WaitForSocketEvent(statePtr, TCL_WRITABLE, errorCodePtr)) {
+ return -1;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpGetOptionProc --
+ *
+ * Computes an option value for a TCP socket based channel, or a
+ * list of all options and their values.
+ *
+ * Note: This code is based on code contributed by John Haxby.
+ *
+ * Results:
+ * A standard Tcl result. The value of the specified option or a
+ * list of all options and their values is returned in the
+ * supplied DString.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpGetOptionProc(
+ ClientData instanceData, /* Socket state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL.*/
+ char *optionName, /* Name of the option to
+ * retrieve the value for, or
+ * NULL to get all options and
+ * their values. */
+ Tcl_DString *dsPtr) /* Where to store the computed
+ * value; initialized by caller. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+ int doPeerName = false, doSockName = false, doAll = false;
+ ip_addr tcpAddress;
+ char buffer[128];
+ OSErr err;
+ Tcl_DString dString;
+ TCPiopb statusPB;
+ int errorCode;
+
+ /*
+ * If an asynchronous connect is in progress, attempt to wait for it
+ * to complete before accessing the socket state.
+ */
+
+ if ((statePtr->flags & TCP_ASYNC_CONNECT)
+ && ! WaitForSocketEvent(statePtr, TCL_WRITABLE, &errorCode)) {
+ if (interp) {
+ /*
+ * fix the error message.
+ */
+
+ Tcl_AppendResult(interp, "connect is in progress and can't wait",
+ NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Determine which options we need to do. Do all of them
+ * if optionName is NULL.
+ */
+
+ if (optionName == (char *) NULL || optionName[0] == '\0') {
+ doAll = true;
+ } else {
+ if (!strcmp(optionName, "-peername")) {
+ doPeerName = true;
+ } else if (!strcmp(optionName, "-sockname")) {
+ doSockName = true;
+ } else {
+ return Tcl_BadChannelOption(interp, optionName,
+ "peername sockname");
+ }
+ }
+
+ /*
+ * Get status on the stream. Make sure to use a new pb struct because
+ * the struct in the statePtr may be part of an asyncronous call.
+ */
+
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = statePtr->tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ if ((err == connectionDoesntExist) ||
+ ((err == noErr) && (statusPB.csParam.status.connectionState == 14))) {
+ /*
+ * The socket was probably closed on the other side of the connection.
+ */
+
+ if (interp) {
+ Tcl_AppendResult(interp, "can't access socket info: ",
+ "connection reset by peer", NULL);
+ }
+ return TCL_ERROR;
+ } else if (err != noErr) {
+ if (interp) {
+ Tcl_AppendResult(interp, "unknown socket error", NULL);
+ }
+ Debugger();
+ return TCL_ERROR;
+ }
+
+
+ /*
+ * Get the sockname for the socket.
+ */
+
+ Tcl_DStringInit(&dString);
+ if (doAll || doSockName) {
+ if (doAll) {
+ Tcl_DStringAppendElement(dsPtr, "-sockname");
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ tcpAddress = statusPB.csParam.status.localHost;
+ sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,
+ tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,
+ tcpAddress & 0xff);
+ Tcl_DStringAppendElement(dsPtr, buffer);
+ if (ResolveAddress(tcpAddress, &dString) == noErr) {
+ Tcl_DStringAppendElement(dsPtr, dString.string);
+ } else {
+ Tcl_DStringAppendElement(dsPtr, "<unknown>");
+ }
+ sprintf(buffer, "%d", statusPB.csParam.status.localPort);
+ Tcl_DStringAppendElement(dsPtr, buffer);
+ if (doAll) {
+ Tcl_DStringEndSublist(dsPtr);
+ }
+ }
+
+ /*
+ * Get the peername for the socket.
+ */
+
+ if ((doAll || doPeerName) && (statePtr->flags & TCP_CONNECTED)) {
+ if (doAll) {
+ Tcl_DStringAppendElement(dsPtr, "-peername");
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ tcpAddress = statusPB.csParam.status.remoteHost;
+ sprintf(buffer, "%d.%d.%d.%d", tcpAddress>>24,
+ tcpAddress>>16 & 0xff, tcpAddress>>8 & 0xff,
+ tcpAddress & 0xff);
+ Tcl_DStringAppendElement(dsPtr, buffer);
+ Tcl_DStringSetLength(&dString, 0);
+ if (ResolveAddress(tcpAddress, &dString) == noErr) {
+ Tcl_DStringAppendElement(dsPtr, dString.string);
+ } else {
+ Tcl_DStringAppendElement(dsPtr, "<unknown>");
+ }
+ sprintf(buffer, "%d", statusPB.csParam.status.remotePort);
+ Tcl_DStringAppendElement(dsPtr, buffer);
+ if (doAll) {
+ Tcl_DStringEndSublist(dsPtr);
+ }
+ }
+
+ Tcl_DStringFree(&dString);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpWatch --
+ *
+ * Initialize the notifier to watch this channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the watchMask for the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TcpWatch(instanceData, mask)
+ ClientData instanceData; /* The file state. */
+ int mask; /* Events of interest; an OR-ed
+ * combination of TCL_READABLE,
+ * TCL_WRITABLE and TCL_EXCEPTION. */
+{
+ TcpState *statePtr = (TcpState *) instanceData;
+
+ statePtr->watchMask = mask;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NewSocketInfo --
+ *
+ * This function allocates and initializes a new SocketInfo
+ * structure.
+ *
+ * Results:
+ * Returns a newly allocated SocketInfo.
+ *
+ * Side effects:
+ * Adds the socket to the global socket list, allocates memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TcpState *
+NewSocketInfo(
+ StreamPtr tcpStream)
+{
+ TcpState *statePtr;
+
+ statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
+ statePtr->tcpStream = tcpStream;
+ statePtr->psn = applicationPSN;
+ statePtr->flags = 0;
+ statePtr->checkMask = 0;
+ statePtr->watchMask = 0;
+ statePtr->acceptProc = (Tcl_TcpAcceptProc *) NULL;
+ statePtr->acceptProcData = (ClientData) NULL;
+ statePtr->nextPtr = socketList;
+ socketList = statePtr;
+ return statePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeSocketInfo --
+ *
+ * This function deallocates a SocketInfo structure that is no
+ * longer needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Removes the socket from the global socket list, frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeSocketInfo(
+ TcpState *statePtr) /* The state pointer to free. */
+{
+ if (statePtr == socketList) {
+ socketList = statePtr->nextPtr;
+ } else {
+ TcpState *p;
+ for (p = socketList; p != NULL; p = p->nextPtr) {
+ if (p->nextPtr == statePtr) {
+ p->nextPtr = statePtr->nextPtr;
+ break;
+ }
+ }
+ }
+ ckfree((char *) statePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MakeTcpClientChannel --
+ *
+ * Creates a Tcl_Channel from an existing client TCP socket.
+ *
+ * Results:
+ * The Tcl_Channel wrapped around the preexisting TCP socket.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_MakeTcpClientChannel(
+ ClientData sock) /* The socket to wrap up into a channel. */
+{
+ TcpState *statePtr;
+ char channelName[20];
+
+ if (TclHasSockets(NULL) != TCL_OK) {
+ return NULL;
+ }
+
+ statePtr = NewSocketInfo((StreamPtr) sock);
+ /* TODO: do we need to set the port??? */
+
+ sprintf(channelName, "sock%d", socketNumber++);
+
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
+ Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
+ Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateSocket --
+ *
+ * This function opens a new socket and initializes the
+ * SocketInfo structure.
+ *
+ * Results:
+ * Returns a new SocketInfo, or NULL with an error in interp.
+ *
+ * Side effects:
+ * Adds a new socket to the socketList.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TcpState *
+CreateSocket(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ int port, /* Port number to open. */
+ char *host, /* Name of host on which to open port. */
+ char *myaddr, /* Optional client-side address */
+ int myport, /* Optional client-side port */
+ int server, /* 1 if socket should be a server socket,
+ * else 0 for a client socket. */
+ int async) /* 1 create async, 0 do sync. */
+{
+ ip_addr macAddr;
+ OSErr err;
+ TCPiopb pb;
+ StreamPtr tcpStream;
+ TcpState *statePtr;
+ char * buffer;
+
+ /*
+ * Figure out the ip address from the host string.
+ */
+
+ if (host == NULL) {
+ err = GetLocalAddress(&macAddr);
+ } else {
+ err = GetHostFromString(host, &macAddr);
+ }
+ if (err != noErr) {
+ Tcl_SetErrno(EHOSTUNREACH);
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "couldn't open socket: ",
+ Tcl_PosixError(interp), (char *) NULL);
+ }
+ return (TcpState *) NULL;
+ }
+
+ /*
+ * Create a MacTCP stream and create the state used for socket
+ * transactions from here on out.
+ */
+
+ ClearZombieSockets();
+ buffer = ckalloc(socketBufferSize);
+ InitMacTCPParamBlock(&pb, TCPCreate);
+ pb.csParam.create.rcvBuff = buffer;
+ pb.csParam.create.rcvBuffLen = socketBufferSize;
+ err = PBControlSync((ParmBlkPtr) &pb);
+ if (err != noErr) {
+ Tcl_SetErrno(0); /* TODO: set to ENOSR - maybe?*/
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "couldn't open socket: ",
+ Tcl_PosixError(interp), (char *) NULL);
+ }
+ return (TcpState *) NULL;
+ }
+
+ tcpStream = pb.tcpStream;
+ statePtr = NewSocketInfo(tcpStream);
+ statePtr->port = port;
+
+ if (server) {
+ /*
+ * Set up server connection.
+ */
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);
+ statePtr->pb.tcpStream = tcpStream;
+ statePtr->pb.csParam.open.localPort = statePtr->port;
+ statePtr->pb.ioCompletion = completeUPP;
+ statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
+ statePtr->flags |= TCP_LISTENING;
+ err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
+
+ /*
+ * If this is a server on port 0 then we need to wait until
+ * the dynamic port allocation is made by the MacTcp driver.
+ */
+
+ if (statePtr->port == 0) {
+ EventRecord dummy;
+
+ while (statePtr->pb.csParam.open.localPort == 0) {
+ WaitNextEvent(0, &dummy, 1, NULL);
+ if (statePtr->pb.ioResult != 0) {
+ break;
+ }
+ }
+ statePtr->port = statePtr->pb.csParam.open.localPort;
+ }
+ Tcl_SetErrno(EINPROGRESS);
+ } else {
+ /*
+ * Attempt to connect. The connect may fail at present with an
+ * EINPROGRESS but at a later time it will complete. The caller
+ * will set up a file handler on the socket if she is interested in
+ * being informed when the connect completes.
+ */
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPActiveOpen);
+ statePtr->pb.tcpStream = tcpStream;
+ statePtr->pb.csParam.open.remoteHost = macAddr;
+ statePtr->pb.csParam.open.remotePort = port;
+ statePtr->pb.csParam.open.localHost = 0;
+ statePtr->pb.csParam.open.localPort = myport;
+ statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
+ statePtr->pb.ioCompletion = completeUPP;
+ if (async) {
+ statePtr->flags |= TCP_ASYNC_CONNECT;
+ err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
+ Tcl_SetErrno(EINPROGRESS);
+ } else {
+ err = PBControlSync((ParmBlkPtr) &(statePtr->pb));
+ }
+ }
+
+ switch (err) {
+ case noErr:
+ if (!async) {
+ statePtr->flags |= TCP_CONNECTED;
+ }
+ return statePtr;
+ case duplicateSocket:
+ Tcl_SetErrno(EADDRINUSE);
+ break;
+ case openFailed:
+ case connectionTerminated:
+ Tcl_SetErrno(ECONNREFUSED);
+ break;
+ case invalidStreamPtr:
+ case connectionExists:
+ default:
+ /*
+ * These cases should never occur. However, we will fail
+ * gracefully and hope Tcl can resume. The alternative is to panic
+ * which is probably a bit drastic.
+ */
+
+ Debugger();
+ Tcl_SetErrno(err);
+ }
+
+ /*
+ * We had error during the connection. Release the stream
+ * and file handle. Also report to the interp.
+ */
+
+ pb.ioCRefNum = driverRefNum;
+ pb.csCode = TCPRelease;
+ pb.tcpStream = tcpStream;
+ pb.ioCompletion = NULL;
+ err = PBControlSync((ParmBlkPtr) &pb);
+
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "couldn't open socket: ",
+ Tcl_PosixError(interp), (char *) NULL);
+ }
+
+ ckfree(buffer);
+ FreeSocketInfo(statePtr);
+ return (TcpState *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OpenTcpClient --
+ *
+ * Opens a TCP client socket and creates a channel around it.
+ *
+ * Results:
+ * The channel or NULL if failed. On failure, the routine also
+ * sets the output argument errorCodePtr to the error code.
+ *
+ * Side effects:
+ * Opens a client socket and creates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_OpenTcpClient(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ int port, /* Port number to open. */
+ char *host, /* Host on which to open port. */
+ char *myaddr, /* Client-side address */
+ int myport, /* Client-side port */
+ int async) /* If nonzero, attempt to do an
+ * asynchronous connect. Otherwise
+ * we do a blocking connect.
+ * - currently ignored */
+{
+ TcpState *statePtr;
+ char channelName[20];
+
+ if (TclHasSockets(interp) != TCL_OK) {
+ return NULL;
+ }
+
+ /*
+ * Create a new client socket and wrap it in a channel.
+ */
+
+ statePtr = CreateSocket(interp, port, host, myaddr, myport, 0, async);
+ if (statePtr == NULL) {
+ return NULL;
+ }
+
+ sprintf(channelName, "sock%d", socketNumber++);
+
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ (ClientData) statePtr, (TCL_READABLE | TCL_WRITABLE));
+ Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
+ Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OpenTcpServer --
+ *
+ * Opens a TCP server socket and creates a channel around it.
+ *
+ * Results:
+ * The channel or NULL if failed.
+ *
+ * Side effects:
+ * Opens a server socket and creates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_OpenTcpServer(
+ Tcl_Interp *interp, /* For error reporting - may be
+ * NULL. */
+ int port, /* Port number to open. */
+ char *host, /* Name of local host. */
+ Tcl_TcpAcceptProc *acceptProc, /* Callback for accepting connections
+ * from new clients. */
+ ClientData acceptProcData) /* Data for the callback. */
+{
+ TcpState *statePtr;
+ char channelName[20];
+
+ if (TclHasSockets(interp) != TCL_OK) {
+ return NULL;
+ }
+
+ /*
+ * Create a new client socket and wrap it in a channel.
+ */
+
+ statePtr = CreateSocket(interp, port, host, NULL, 0, 1, 1);
+ if (statePtr == NULL) {
+ return NULL;
+ }
+
+ statePtr->acceptProc = acceptProc;
+ statePtr->acceptProcData = acceptProcData;
+
+ sprintf(channelName, "sock%d", socketNumber++);
+
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ (ClientData) statePtr, 0);
+ Tcl_SetChannelBufferSize(statePtr->channel, socketBufferSize);
+ Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SocketEventProc --
+ *
+ * This procedure is called by Tcl_ServiceEvent when a socket event
+ * reaches the front of the event queue. This procedure is
+ * responsible for notifying the generic channel code.
+ *
+ * Results:
+ * Returns 1 if the event was handled, meaning it should be removed
+ * from the queue. Returns 0 if the event was not handled, meaning
+ * it should stay on the queue. The only time the event isn't
+ * handled is if the TCL_FILE_EVENTS flag bit isn't set.
+ *
+ * Side effects:
+ * Whatever the channel callback procedures do.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SocketEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to
+ * handle, such as TCL_FILE_EVENTS. */
+{
+ TcpState *statePtr;
+ SocketEvent *eventPtr = (SocketEvent *) evPtr;
+ int mask = 0;
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return 0;
+ }
+
+ /*
+ * Find the specified socket on the socket list.
+ */
+
+ for (statePtr = socketList; statePtr != NULL;
+ statePtr = statePtr->nextPtr) {
+ if ((statePtr == eventPtr->statePtr) &&
+ (statePtr->tcpStream == eventPtr->tcpStream)) {
+ break;
+ }
+ }
+
+ /*
+ * Discard events that have gone stale.
+ */
+
+ if (!statePtr) {
+ return 1;
+ }
+ statePtr->flags &= ~(TCP_PENDING);
+ if (statePtr->flags & TCP_RELEASE) {
+ SocketFreeProc(statePtr);
+ return 1;
+ }
+
+
+ /*
+ * Handle connection requests directly.
+ */
+
+ if (statePtr->flags & TCP_LISTEN_CONNECT) {
+ if (statePtr->checkMask & TCL_READABLE) {
+ TcpAccept(statePtr);
+ }
+ return 1;
+ }
+
+ /*
+ * Mask off unwanted events then notify the channel.
+ */
+
+ mask = statePtr->checkMask & statePtr->watchMask;
+ if (mask) {
+ Tcl_NotifyChannel(statePtr->channel, mask);
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WaitForSocketEvent --
+ *
+ * Waits until one of the specified events occurs on a socket.
+ *
+ * Results:
+ * Returns 1 on success or 0 on failure, with an error code in
+ * errorCodePtr.
+ *
+ * Side effects:
+ * Processes socket events off the system queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WaitForSocketEvent(
+ TcpState *statePtr, /* Information about this socket. */
+ int mask, /* Events to look for. */
+ int *errorCodePtr) /* Where to store errors? */
+{
+ OSErr err;
+ TCPiopb statusPB;
+ EventRecord dummy;
+
+ /*
+ * Loop until we get the specified condition, unless the socket is
+ * asynchronous.
+ */
+
+ do {
+ statusPB.ioCRefNum = driverRefNum;
+ statusPB.tcpStream = statePtr->tcpStream;
+ statusPB.csCode = TCPStatus;
+ err = PBControlSync((ParmBlkPtr) &statusPB);
+ if (err != noErr) {
+ statePtr->checkMask |= (TCL_READABLE | TCL_WRITABLE);
+ return 1;
+ }
+ statePtr->checkMask = 0;
+ if (statusPB.csParam.status.amtUnreadData > 0) {
+ statePtr->checkMask |= TCL_READABLE;
+ }
+ if (!(statePtr->flags & TCP_WRITING)
+ && (statusPB.csParam.status.sendWindow -
+ statusPB.csParam.status.amtUnackedData) > 0) {
+ statePtr->flags &= ~(TCP_ASYNC_CONNECT);
+ statePtr->checkMask |= TCL_WRITABLE;
+ }
+ if (mask & statePtr->checkMask) {
+ return 1;
+ }
+
+ /*
+ * Call the system to let other applications run while we
+ * are waiting for this event to occur.
+ */
+
+ WaitNextEvent(0, &dummy, 1, NULL);
+ } while (!(statePtr->flags & TCP_ASYNC_SOCKET));
+ *errorCodePtr = EWOULDBLOCK;
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpAccept --
+ * Accept a TCP socket connection. This is called by the event
+ * loop, and it in turns calls any registered callbacks for this
+ * channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Evals the Tcl script associated with the server socket.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TcpAccept(
+ TcpState *statePtr)
+{
+ TcpState *newStatePtr;
+ StreamPtr tcpStream;
+ char remoteHostname[255];
+ OSErr err;
+ ip_addr remoteAddress;
+ long remotePort;
+ char channelName[20];
+
+ statePtr->flags &= ~TCP_LISTEN_CONNECT;
+ statePtr->checkMask &= ~TCL_READABLE;
+
+ /*
+ * Transfer sever stream to new connection.
+ */
+
+ tcpStream = statePtr->tcpStream;
+ newStatePtr = NewSocketInfo(tcpStream);
+ newStatePtr->tcpStream = tcpStream;
+ sprintf(channelName, "sock%d", socketNumber++);
+
+
+ newStatePtr->flags |= TCP_CONNECTED;
+ newStatePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ (ClientData) newStatePtr, (TCL_READABLE | TCL_WRITABLE));
+ Tcl_SetChannelBufferSize(newStatePtr->channel, socketBufferSize);
+ Tcl_SetChannelOption(NULL, newStatePtr->channel, "-translation",
+ "auto crlf");
+
+ remoteAddress = statePtr->pb.csParam.open.remoteHost;
+ remotePort = statePtr->pb.csParam.open.remotePort;
+
+ /*
+ * Reopen passive connect. Make new tcpStream the server.
+ */
+
+ ClearZombieSockets();
+ InitMacTCPParamBlock(&statePtr->pb, TCPCreate);
+ statePtr->pb.csParam.create.rcvBuff = ckalloc(socketBufferSize);
+ statePtr->pb.csParam.create.rcvBuffLen = socketBufferSize;
+ err = PBControlSync((ParmBlkPtr) &statePtr->pb);
+ if (err != noErr) {
+ /*
+ * Hmmm... We can't reopen the server. We'll go ahead
+ * an continue - but we are kind of broken now...
+ */
+ Debugger();
+ statePtr->tcpStream = -1;
+ statePtr->flags |= TCP_SERVER_ZOMBIE;
+ }
+
+ tcpStream = statePtr->tcpStream = statePtr->pb.tcpStream;
+
+ InitMacTCPParamBlock(&statePtr->pb, TCPPassiveOpen);
+ statePtr->pb.tcpStream = tcpStream;
+ statePtr->pb.csParam.open.localHost = 0;
+ statePtr->pb.csParam.open.localPort = statePtr->port;
+ statePtr->pb.ioCompletion = completeUPP;
+ statePtr->pb.csParam.open.userDataPtr = (Ptr) statePtr;
+ statePtr->flags |= TCP_LISTENING;
+ err = PBControlAsync((ParmBlkPtr) &(statePtr->pb));
+ /*
+ * TODO: deal with case where we can't recreate server socket...
+ */
+
+ /*
+ * Finally we run the accept procedure. We must do this last to make
+ * sure we are in a nice clean state. This Tcl code can do anything
+ * including closing the server or client sockets we've just delt with.
+ */
+
+ if (statePtr->acceptProc != NULL) {
+ sprintf(remoteHostname, "%d.%d.%d.%d", remoteAddress>>24,
+ remoteAddress>>16 & 0xff, remoteAddress>>8 & 0xff,
+ remoteAddress & 0xff);
+
+ (statePtr->acceptProc)(statePtr->acceptProcData, newStatePtr->channel,
+ remoteHostname, remotePort);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetHostName --
+ *
+ * Returns the name of the local host.
+ *
+ * Results:
+ * A string containing the network name for this machine, or
+ * an empty string if we can't figure out the name. The caller
+ * must not modify or free this string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tcl_GetHostName()
+{
+ static int hostnameInited = 0;
+ static char hostname[255];
+ ip_addr ourAddress;
+ Tcl_DString dString;
+ OSErr err;
+
+ if (hostnameInited) {
+ return hostname;
+ }
+
+ if (TclHasSockets(NULL) == TCL_OK) {
+ err = GetLocalAddress(&ourAddress);
+ if (err == noErr) {
+ /*
+ * Search for the doman name and return it if found. Otherwise,
+ * just print the IP number to a string and return that.
+ */
+
+ Tcl_DStringInit(&dString);
+ err = ResolveAddress(ourAddress, &dString);
+ if (err == noErr) {
+ strcpy(hostname, dString.string);
+ } else {
+ sprintf(hostname, "%d.%d.%d.%d", ourAddress>>24, ourAddress>>16 & 0xff,
+ ourAddress>>8 & 0xff, ourAddress & 0xff);
+ }
+ Tcl_DStringFree(&dString);
+
+ hostnameInited = 1;
+ return hostname;
+ }
+ }
+
+ hostname[0] = '\0';
+ hostnameInited = 1;
+ return hostname;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ResolveAddress --
+ *
+ * This function is used to resolve an ip address to it's full
+ * domain name address.
+ *
+ * Results:
+ * An os err value.
+ *
+ * Side effects:
+ * Treats client data as int we set to true.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+ResolveAddress(
+ ip_addr tcpAddress, /* Address to resolve. */
+ Tcl_DString *dsPtr) /* Returned address in string. */
+{
+ int i;
+ EventRecord dummy;
+ DNRState dnrState;
+ OSErr err;
+
+ /*
+ * Call AddrToName to resolve our ip address to our domain name.
+ * The call is async, so we must wait for a callback to tell us
+ * when to continue.
+ */
+
+ for (i = 0; i < NUM_ALT_ADDRS; i++) {
+ dnrState.hostInfo.addr[i] = 0;
+ }
+ dnrState.done = 0;
+ GetCurrentProcess(&(dnrState.psn));
+ err = AddrToName(tcpAddress, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
+ if (err == cacheFault) {
+ while (!dnrState.done) {
+ WaitNextEvent(0, &dummy, 1, NULL);
+ }
+ }
+
+ /*
+ * If there is no error in finding the domain name we set the
+ * result into the dynamic string. We also work around a bug in
+ * MacTcp where an extranious '.' may be found at the end of the name.
+ */
+
+ if (dnrState.hostInfo.rtnCode == noErr) {
+ i = strlen(dnrState.hostInfo.cname) - 1;
+ if (dnrState.hostInfo.cname[i] == '.') {
+ dnrState.hostInfo.cname[i] = '\0';
+ }
+ Tcl_DStringAppend(dsPtr, dnrState.hostInfo.cname, -1);
+ }
+
+ return dnrState.hostInfo.rtnCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DNRCompletionRoutine --
+ *
+ * This function is called when the Domain Name Server is done
+ * seviceing our request. It just sets a flag that we can poll
+ * in functions like Tcl_GetHostName to let them know to continue.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Treats client data as int we set to true.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal void
+DNRCompletionRoutine(
+ struct hostInfo *hostinfoPtr, /* Host infor struct. */
+ DNRState *dnrStatePtr) /* Completetion state. */
+{
+ dnrStatePtr->done = true;
+ WakeUpProcess(&(dnrStatePtr->psn));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanUpExitProc --
+ *
+ * This procedure is invoked as an exit handler when ExitToShell
+ * is called. It aborts any lingering socket connections. This
+ * must be called or the Mac OS will more than likely crash.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal void
+CleanUpExitProc()
+{
+ TCPiopb exitPB;
+ TcpState *statePtr;
+
+ while (socketList != NULL) {
+ statePtr = socketList;
+ socketList = statePtr->nextPtr;
+
+ /*
+ * Close and Release the connection.
+ */
+
+ exitPB.ioCRefNum = driverRefNum;
+ exitPB.csCode = TCPClose;
+ exitPB.tcpStream = statePtr->tcpStream;
+ exitPB.csParam.close.ulpTimeoutValue = 60 /* seconds */;
+ exitPB.csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */;
+ exitPB.csParam.close.validityFlags = timeoutValue | timeoutAction;
+ exitPB.ioCompletion = NULL;
+ PBControlSync((ParmBlkPtr) &exitPB);
+
+ exitPB.ioCRefNum = driverRefNum;
+ exitPB.csCode = TCPRelease;
+ exitPB.tcpStream = statePtr->tcpStream;
+ exitPB.ioCompletion = NULL;
+ PBControlSync((ParmBlkPtr) &exitPB);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetHostFromString --
+ *
+ * Looks up the passed in domain name in the domain resolver. It
+ * can accept strings of two types: 1) the ip number in string
+ * format, or 2) the domain name.
+ *
+ * Results:
+ * We return a ip address or 0 if there was an error or the
+ * domain does not exist.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+GetHostFromString(
+ char *name, /* Host in string form. */
+ ip_addr *address) /* Returned IP address. */
+{
+ OSErr err;
+ int i;
+ EventRecord dummy;
+ DNRState dnrState;
+
+ if (TclHasSockets(NULL) != TCL_OK) {
+ return 0;
+ }
+
+ /*
+ * Call StrToAddr to get the ip number for the passed in domain
+ * name. The call is async, so we must wait for a callback to
+ * tell us when to continue.
+ */
+
+ for (i = 0; i < NUM_ALT_ADDRS; i++) {
+ dnrState.hostInfo.addr[i] = 0;
+ }
+ dnrState.done = 0;
+ GetCurrentProcess(&(dnrState.psn));
+ err = StrToAddr(name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
+ if (err == cacheFault) {
+ while (!dnrState.done) {
+ WaitNextEvent(0, &dummy, 1, NULL);
+ }
+ }
+
+ /*
+ * For some reason MacTcp may return a cachFault a second time via
+ * the hostinfo block. This seems to be a bug in MacTcp. In this case
+ * we run StrToAddr again - which seems to then work just fine.
+ */
+
+ if (dnrState.hostInfo.rtnCode == cacheFault) {
+ dnrState.done = 0;
+ err = StrToAddr(name, &dnrState.hostInfo, resultUPP, (Ptr) &dnrState);
+ if (err == cacheFault) {
+ while (!dnrState.done) {
+ WaitNextEvent(0, &dummy, 1, NULL);
+ }
+ }
+ }
+
+ if (dnrState.hostInfo.rtnCode == noErr) {
+ *address = dnrState.hostInfo.addr[0];
+ }
+
+ return dnrState.hostInfo.rtnCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * IOCompletionRoutine --
+ *
+ * This function is called when an asynchronous socket operation
+ * completes. Since this routine runs as an interrupt handler,
+ * it will simply set state to tell the notifier that this socket
+ * is now ready for action. Note that this function is running at
+ * interupt time and can't allocate memory or do much else except
+ * set state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets some state in the socket state. May also wake the process
+ * if we are not currently running.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+IOCompletionRoutine(
+ TCPiopb *pbPtr) /* Tcp parameter block. */
+{
+ TcpState *statePtr;
+
+ if (pbPtr->csCode == TCPSend) {
+ statePtr = (TcpState *) pbPtr->csParam.send.userDataPtr;
+ } else {
+ statePtr = (TcpState *) pbPtr->csParam.open.userDataPtr;
+ }
+
+ /*
+ * Always wake the process in case it's in WaitNextEvent.
+ * If an error has a occured - just return. We will deal
+ * with the problem later.
+ */
+
+ WakeUpProcess(&statePtr->psn);
+ if (pbPtr->ioResult != noErr) {
+ return;
+ }
+
+ if (statePtr->flags & TCP_ASYNC_CONNECT) {
+ statePtr->flags &= ~TCP_ASYNC_CONNECT;
+ statePtr->flags |= TCP_CONNECTED;
+ statePtr->checkMask |= TCL_READABLE & TCL_WRITABLE;
+ } else if (statePtr->flags & TCP_LISTENING) {
+ if (statePtr->port == 0) {
+ Debugger();
+ }
+ statePtr->flags &= ~TCP_LISTENING;
+ statePtr->flags |= TCP_LISTEN_CONNECT;
+ statePtr->checkMask |= TCL_READABLE;
+ } else if (statePtr->flags & TCP_WRITING) {
+ statePtr->flags &= ~TCP_WRITING;
+ statePtr->checkMask |= TCL_WRITABLE;
+ if (!(statePtr->flags & TCP_CONNECTED)) {
+ InitMacTCPParamBlock(&statePtr->pb, TCPClose);
+ statePtr->pb.tcpStream = statePtr->tcpStream;
+ statePtr->pb.ioCompletion = closeUPP;
+ statePtr->pb.csParam.close.userDataPtr = (Ptr) statePtr;
+ if (PBControlAsync((ParmBlkPtr) &statePtr->pb) != noErr) {
+ statePtr->flags |= TCP_RELEASE;
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetLocalAddress --
+ *
+ * Get the IP address for this machine. The result is cached so
+ * the result is returned quickly after the first call.
+ *
+ * Results:
+ * Macintosh error code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+GetLocalAddress(
+ unsigned long *addr) /* Returns host IP address. */
+{
+ struct GetAddrParamBlock pBlock;
+ OSErr err = noErr;
+ static unsigned long localAddress = 0;
+
+ if (localAddress == 0) {
+ memset(&pBlock, 0, sizeof(pBlock));
+ pBlock.ioResult = 1;
+ pBlock.csCode = ipctlGetAddr;
+ pBlock.ioCRefNum = driverRefNum;
+ err = PBControlSync((ParmBlkPtr) &pBlock);
+
+ if (err != noErr) {
+ return err;
+ }
+ localAddress = pBlock.ourAddress;
+ }
+
+ *addr = localAddress;
+ return noErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetBufferSize --
+ *
+ * Get the appropiate buffer size for our machine & network. This
+ * value will be used by the rest of Tcl & the MacTcp driver for
+ * the size of its buffers. If out method for determining the
+ * optimal buffer size fails for any reason - we return a
+ * reasonable default.
+ *
+ * Results:
+ * Size of optimal buffer in bytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static long
+GetBufferSize()
+{
+ UDPiopb iopb;
+ OSErr err = noErr;
+ long bufferSize;
+
+ memset(&iopb, 0, sizeof(iopb));
+ err = GetLocalAddress(&iopb.csParam.mtu.remoteHost);
+ if (err != noErr) {
+ return CHANNEL_BUF_SIZE;
+ }
+ iopb.ioCRefNum = driverRefNum;
+ iopb.csCode = UDPMaxMTUSize;
+ err = PBControlSync((ParmBlkPtr)&iopb);
+ if (err != noErr) {
+ return CHANNEL_BUF_SIZE;
+ }
+ bufferSize = (iopb.csParam.mtu.mtuSize * 4) + 1024;
+ if (bufferSize < CHANNEL_BUF_SIZE) {
+ bufferSize = CHANNEL_BUF_SIZE;
+ }
+ return bufferSize;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSockGetPort --
+ *
+ * Maps from a string, which could be a service name, to a port.
+ * Used by socket creation code to get port numbers and resolve
+ * registered service names to port numbers.
+ *
+ * Results:
+ * A standard Tcl result. On success, the port number is
+ * returned in portPtr. On failure, an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclSockGetPort(
+ Tcl_Interp *interp, /* Interp for error messages. */
+ char *string, /* Integer or service name */
+ char *proto, /* "tcp" or "udp", typically -
+ * ignored on Mac - assumed to be tcp */
+ int *portPtr) /* Return port number */
+{
+ PortInfo *portInfoPtr = NULL;
+
+ if (Tcl_GetInt(interp, string, portPtr) == TCL_OK) {
+ if (*portPtr > 0xFFFF) {
+ Tcl_AppendResult(interp, "couldn't open socket: port number too high",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (*portPtr < 0) {
+ Tcl_AppendResult(interp, "couldn't open socket: negative port number",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+ for (portInfoPtr = portServices; portInfoPtr->name != NULL; portInfoPtr++) {
+ if (!strcmp(portInfoPtr->name, string)) {
+ break;
+ }
+ }
+ if (portInfoPtr != NULL && portInfoPtr->name != NULL) {
+ *portPtr = portInfoPtr->port;
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+ }
+
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClearZombieSockets --
+ *
+ * This procedure looks through the socket list and removes the
+ * first stream it finds that is ready for release. This procedure
+ * should be called before we ever try to create new Tcp streams
+ * to ensure we can least allocate one stream.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tcp streams may be released.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClearZombieSockets()
+{
+ TcpState *statePtr;
+
+ for (statePtr = socketList; statePtr != NULL;
+ statePtr = statePtr->nextPtr) {
+ if (statePtr->flags & TCP_RELEASE) {
+ SocketFreeProc(statePtr);
+ return;
+ }
+ }
+}
diff --git a/mac/tclMacTest.c b/mac/tclMacTest.c
new file mode 100644
index 0000000..2452ca1
--- /dev/null
+++ b/mac/tclMacTest.c
@@ -0,0 +1,242 @@
+/*
+ * tclMacTest.c --
+ *
+ * Contains commands for platform specific tests for
+ * the Macintosh platform.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacTest.c 1.9 97/09/09 16:36:37
+ */
+
+#define TCL_TEST
+
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include "tclMacPort.h"
+#include "Files.h"
+#include <Errors.h>
+#include <Resources.h>
+#include <Script.h>
+#include <Strings.h>
+#include <FSpCompat.h>
+
+/*
+ * Forward declarations of procedures defined later in this file:
+ */
+
+int TclplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
+static int DebuggerCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int argc, char **argv));
+static int WriteTextResource _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int argc, char **argv));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclplatformtestInit --
+ *
+ * Defines commands that test platform specific functionality for
+ * Unix platforms.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Defines new commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclplatformtestInit(
+ Tcl_Interp *interp) /* Interpreter to add commands to. */
+{
+ /*
+ * Add commands for platform specific tests on MacOS here.
+ */
+
+ Tcl_CreateCommand(interp, "debugger", DebuggerCmd,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "testWriteTextResource", WriteTextResource,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DebuggerCmd --
+ *
+ * This procedure simply calls the low level debugger.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DebuggerCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ int argc, /* Not used. */
+ char **argv) /* Not used. */
+{
+ Debugger();
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WriteTextResource --
+ *
+ * This procedure will write a text resource out to the
+ * application or a given file. The format for this command is
+ * textwriteresource
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WriteTextResource(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ char *errNum = "wrong # args: ";
+ char *errBad = "bad argument: ";
+ char *errStr;
+ char *fileName = NULL, *rsrcName = NULL;
+ char *data = NULL;
+ int rsrcID = -1, i, protectIt = 0;
+ short fileRef = -1;
+ OSErr err;
+ Handle dataHandle;
+ Str255 resourceName;
+ FSSpec fileSpec;
+
+ /*
+ * Process the arguments.
+ */
+ for (i = 1 ; i < argc ; i++) {
+ if (!strcmp(argv[i], "-rsrc")) {
+ rsrcName = argv[i + 1];
+ i++;
+ } else if (!strcmp(argv[i], "-rsrcid")) {
+ rsrcID = atoi(argv[i + 1]);
+ i++;
+ } else if (!strcmp(argv[i], "-file")) {
+ fileName = argv[i + 1];
+ i++;
+ } else if (!strcmp(argv[i], "-protected")) {
+ protectIt = 1;
+ } else {
+ data = argv[i];
+ }
+ }
+
+ if ((rsrcName == NULL && rsrcID < 0) ||
+ (fileName == NULL) || (data == NULL)) {
+ errStr = errBad;
+ goto sourceFmtErr;
+ }
+
+ /*
+ * Open the resource file.
+ */
+ err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec);
+ if (!(err == noErr || err == fnfErr)) {
+ Tcl_AppendResult(interp, "couldn't validate file name", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (err == fnfErr) {
+ FSpCreateResFile(&fileSpec, 'WIsH', 'rsrc', smSystemScript);
+ }
+ fileRef = FSpOpenResFile(&fileSpec, fsRdWrPerm);
+ if (fileRef == -1) {
+ Tcl_AppendResult(interp, "couldn't open resource file", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ UseResFile(fileRef);
+
+ /*
+ * Prepare data needed to create resource.
+ */
+ if (rsrcID < 0) {
+ rsrcID = UniqueID('TEXT');
+ }
+
+ strcpy((char *) resourceName, rsrcName);
+ c2pstr((char *) resourceName);
+
+ dataHandle = NewHandle(strlen(data) + 1);
+ HLock(dataHandle);
+ strcpy(*dataHandle, data);
+ HUnlock(dataHandle);
+
+ /*
+ * Add the resource to the file and close it.
+ */
+ AddResource(dataHandle, 'TEXT', rsrcID, resourceName);
+
+ UpdateResFile(fileRef);
+ if (protectIt) {
+ SetResAttrs(Get1Resource('TEXT', rsrcID), resProtected);
+ }
+
+ CloseResFile(fileRef);
+ return TCL_OK;
+
+ sourceFmtErr:
+ Tcl_AppendResult(interp, errStr, "error in \"", argv[0], "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+}
+
+int
+TclMacChmod(
+ char *path,
+ int mode)
+{
+ HParamBlockRec hpb;
+ OSErr err;
+
+ c2pstr(path);
+ hpb.fileParam.ioNamePtr = (unsigned char *) path;
+ hpb.fileParam.ioVRefNum = 0;
+ hpb.fileParam.ioDirID = 0;
+
+ if (mode & 0200) {
+ err = PBHRstFLockSync(&hpb);
+ } else {
+ err = PBHSetFLockSync(&hpb);
+ }
+ p2cstr((unsigned char *) path);
+
+ if (err != noErr) {
+ errno = TclMacOSErrorToPosixError(err);
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/mac/tclMacTime.c b/mac/tclMacTime.c
new file mode 100644
index 0000000..e5b6a1f
--- /dev/null
+++ b/mac/tclMacTime.c
@@ -0,0 +1,312 @@
+/*
+ * tclMacTime.c --
+ *
+ * Contains Macintosh specific versions of Tcl functions that
+ * obtain time values from the operating system.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacTime.c 1.19 97/06/27 13:07:10
+ */
+
+#include "tclInt.h"
+#include "tclPort.h"
+#include <OSUtils.h>
+#include <Timer.h>
+#include <time.h>
+
+/*
+ * Static variables used by the TclpGetTime function.
+ */
+
+static int initalized = false;
+static unsigned long baseSeconds;
+static UnsignedWide microOffset;
+
+/*
+ * Prototypes for procedures that are private to this file:
+ */
+
+static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
+ UnsignedWide *y, UnsignedWide *result));
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclpGetSeconds --
+ *
+ * This procedure returns the number of seconds from the epoch. On
+ * the Macintosh the epoch is Midnight Jan 1, 1904. Unfortunatly,
+ * the Macintosh doesn't tie the epoch to a particular time zone. For
+ * Tcl we tie the epoch to GMT. This makes the time zone date parsing
+ * code work. The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
+ *
+ * Results:
+ * Number of seconds from the epoch in GMT.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+unsigned long
+TclpGetSeconds()
+{
+ unsigned long seconds;
+ MachineLocation loc;
+ long int offset;
+
+ ReadLocation(&loc);
+ offset = loc.u.gmtDelta & 0x00ffffff;
+ if (offset & 0x00800000) {
+ offset = offset | 0xff000000;
+ }
+
+ if (ReadDateTime(&seconds) == noErr) {
+ return (seconds - offset);
+ } else {
+ panic("Can't get time.");
+ return 0;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclpGetClicks --
+ *
+ * This procedure returns a value that represents the highest resolution
+ * clock available on the system. There are no garantees on what the
+ * resolution will be. In Tcl we will call this value a "click". The
+ * start time is also system dependant.
+ *
+ * Results:
+ * Number of clicks from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+unsigned long
+TclpGetClicks()
+{
+ UnsignedWide micros;
+
+ Microseconds(&micros);
+ return micros.lo;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetTimeZone --
+ *
+ * Get the current time zone.
+ *
+ * Results:
+ * The return value is the local time zone, measured in
+ * minutes away from GMT (-ve for east, +ve for west).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpGetTimeZone (
+ unsigned long currentTime) /* Ignored on Mac. */
+{
+ MachineLocation loc;
+ long int offset;
+
+ ReadLocation(&loc);
+ offset = loc.u.gmtDelta & 0x00ffffff;
+ if (offset & 0x00700000) {
+ offset |= 0xff000000;
+ }
+
+ /*
+ * Convert the Mac offset from seconds to minutes and
+ * add an hour if we have daylight savings time.
+ */
+ offset = -offset;
+ offset /= 60;
+ if (loc.u.dlsDelta < 0) {
+ offset += 60;
+ }
+
+ return offset;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetTime --
+ *
+ * Gets the current system time in seconds and microseconds
+ * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
+ *
+ * Results:
+ * Returns the current time (in the local timezone) in timePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpGetTime(
+ Tcl_Time *timePtr) /* Location to store time information. */
+{
+ UnsignedWide micro;
+#ifndef NO_LONG_LONG
+ long long *microPtr;
+#endif
+
+ if (initalized == false) {
+ MachineLocation loc;
+ long int offset;
+
+ ReadLocation(&loc);
+ offset = loc.u.gmtDelta & 0x00ffffff;
+ if (offset & 0x00800000) {
+ offset = offset | 0xff000000;
+ }
+ if (ReadDateTime(&baseSeconds) != noErr) {
+ /*
+ * This should never happen!
+ */
+ return;
+ }
+ /*
+ * Remove the local offset that ReadDateTime() adds.
+ */
+ baseSeconds -= offset;
+ Microseconds(&microOffset);
+ initalized = true;
+ }
+
+ Microseconds(&micro);
+
+#ifndef NO_LONG_LONG
+ microPtr = (long long *) &micro;
+ *microPtr -= *((long long *) &microOffset);
+ timePtr->sec = baseSeconds + (*microPtr / 1000000);
+ timePtr->usec = *microPtr % 1000000;
+#else
+ SubtractUnsignedWide(&micro, &microOffset, &micro);
+
+ /*
+ * This lovely computation is equal to: base + (micro / 1000000)
+ * For the .hi part the ratio of 0x100000000 / 1000000 has been
+ * reduced to avoid overflow. This computation certainly has
+ * problems as the .hi part gets large. However, your application
+ * would have to run for a long time to make that happen.
+ */
+
+ timePtr->sec = baseSeconds + (micro.lo / 1000000) +
+ (long) (micro.hi * ((double) 33554432.0 / 15625.0));
+ timePtr->usec = micro.lo % 1000000;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetDate --
+ *
+ * Converts raw seconds to a struct tm data structure. The
+ * returned time will be for Greenwich Mean Time if the useGMT flag
+ * is set. Otherwise, the returned time will be for the local
+ * time zone. This function is meant to be used as a replacement
+ * for localtime and gmtime which is broken on most ANSI libs
+ * on the Macintosh.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The passed in struct tm data structure is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+struct tm *
+TclpGetDate(
+ const time_t *tp, /* Time struct to fill. */
+ int useGMT) /* True if date should reflect GNT time. */
+{
+ DateTimeRec dtr;
+ MachineLocation loc;
+ long int offset;
+ static struct tm statictime;
+ static const short monthday[12] =
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ ReadLocation(&loc);
+
+ if (useGMT) {
+ SecondsToDate(*tp, &dtr);
+ } else {
+ offset = loc.u.gmtDelta & 0x00ffffff;
+ if (offset & 0x00700000) {
+ offset |= 0xff000000;
+ }
+
+ SecondsToDate(*tp + offset, &dtr);
+ }
+
+ statictime.tm_sec = dtr.second;
+ statictime.tm_min = dtr.minute;
+ statictime.tm_hour = dtr.hour;
+ statictime.tm_mday = dtr.day;
+ statictime.tm_mon = dtr.month - 1;
+ statictime.tm_year = dtr.year - 1900;
+ statictime.tm_wday = dtr.dayOfWeek - 1;
+ statictime.tm_yday = monthday[statictime.tm_mon]
+ + statictime.tm_mday - 1;
+ if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
+ ++statictime.tm_yday;
+ }
+ statictime.tm_isdst = loc.u.dlsDelta;
+ return(&statictime);
+}
+
+#ifdef NO_LONG_LONG
+/*
+ *----------------------------------------------------------------------
+ *
+ * SubtractUnsignedWide --
+ *
+ * Subtracts one UnsignedWide value from another.
+ *
+ * Results:
+ * The subtracted value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SubtractUnsignedWide(
+ UnsignedWide *x, /* Ptr to wide int. */
+ UnsignedWide *y, /* Ptr to wide int. */
+ UnsignedWide *result) /* Ptr to result. */
+{
+ result->hi = x->hi - y->hi;
+ if (x->lo < y->lo) {
+ result->hi--;
+ }
+ result->lo = x->lo - y->lo;
+}
+#endif
diff --git a/mac/tclMacUnix.c b/mac/tclMacUnix.c
new file mode 100644
index 0000000..e820fc0
--- /dev/null
+++ b/mac/tclMacUnix.c
@@ -0,0 +1,464 @@
+/*
+ * tclMacUnix.c --
+ *
+ * This file contains routines to implement several features
+ * available to the Unix implementation, but that require
+ * extra work to do on a Macintosh. These include routines
+ * Unix Tcl normally hands off to the Unix OS.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacUnix.c 1.56 96/12/12 19:38:08
+ */
+
+#include <Files.h>
+#include <Strings.h>
+#include <TextUtils.h>
+#include <Finder.h>
+#include <FSpCompat.h>
+#include <Aliases.h>
+#include <Errors.h>
+
+#include "tclInt.h"
+#include "tclMacInt.h"
+
+/*
+ * The following two Includes are from the More Files package
+ */
+#include "FileCopy.h"
+#include "MoreFiles.h"
+#include "MoreFilesExtras.h"
+
+/*
+ * The following may not be defined in some versions of
+ * MPW header files.
+ */
+#ifndef kIsInvisible
+#define kIsInvisible 0x4000
+#endif
+#ifndef kIsAlias
+#define kIsAlias 0x8000
+#endif
+
+/*
+ * Missing error codes
+ */
+#define usageErr 500
+#define noSourceErr 501
+#define isDirErr 502
+
+/*
+ * Static functions in this file.
+ */
+
+static int GlobArgs _ANSI_ARGS_((Tcl_Interp *interp,
+ int *argc, char ***argv));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GlobArgs --
+ *
+ * The following function was taken from Peter Keleher's Alpha
+ * Editor. *argc should only count the end arguments that should
+ * be globed. argv should be incremented to point to the first
+ * arg to be globed.
+ *
+ * Results:
+ * Returns 'true' if it worked & memory was allocated, else 'false'.
+ *
+ * Side effects:
+ * argv will be alloced, the call will need to release the memory
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GlobArgs(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ int *argc, /* Number of arguments. */
+ char ***argv) /* Argument strings. */
+{
+ int res, len;
+ char *list;
+
+ /*
+ * Places the globbed args all into 'interp->result' as a list.
+ */
+ res = Tcl_GlobCmd(NULL, interp, *argc + 1, *argv - 1);
+ if (res != TCL_OK) {
+ return false;
+ }
+ len = strlen(interp->result);
+ list = (char *) ckalloc(len + 1);
+ strcpy(list, interp->result);
+ Tcl_ResetResult(interp);
+
+ res = Tcl_SplitList(interp, list, argc, argv);
+ ckfree((char *) list);
+ if (res != TCL_OK) {
+ return false;
+ }
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_EchoCmd --
+ *
+ * Implements the TCL echo command:
+ * echo ?str ...?
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_EchoCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tcl_Channel chan;
+ int mode, result, i;
+
+ chan = Tcl_GetChannel(interp, "stdout", &mode);
+ if (chan == (Tcl_Channel) NULL) {
+ return TCL_ERROR;
+ }
+ for (i = 1; i < argc; i++) {
+ result = Tcl_Write(chan, argv[i], -1);
+ if (result < 0) {
+ Tcl_AppendResult(interp, "echo: ", Tcl_GetChannelName(chan),
+ ": ", Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (i < (argc - 1)) {
+ Tcl_Write(chan, " ", -1);
+ }
+ }
+ Tcl_Write(chan, "\n", -1);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_LsCmd --
+ *
+ * This procedure is invoked to process the "ls" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Tcl_LsCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+#define STRING_LENGTH 80
+#define CR '\n'
+ int i, j;
+ int fieldLength, len = 0, maxLen = 0, perLine;
+ char **origArgv = argv;
+ OSErr err;
+ CInfoPBRec paramBlock;
+ HFileInfo *hpb = (HFileInfo *)&paramBlock;
+ DirInfo *dpb = (DirInfo *)&paramBlock;
+ char theFile[256];
+ char theLine[STRING_LENGTH + 2];
+ int fFlag = false, pFlag = false, aFlag = false, lFlag = false,
+ cFlag = false, hFlag = false;
+
+ /*
+ * Process command flags. End if argument doesn't start
+ * with a dash or is a dash by itself. The remaining arguments
+ * should be files.
+ */
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ break;
+ }
+
+ if (!strcmp(argv[i], "-")) {
+ i++;
+ break;
+ }
+
+ for (j = 1 ; argv[i][j] ; ++j) {
+ switch(argv[i][j]) {
+ case 'a':
+ case 'A':
+ aFlag = true;
+ break;
+ case '1':
+ cFlag = false;
+ break;
+ case 'C':
+ cFlag = true;
+ break;
+ case 'F':
+ fFlag = true;
+ break;
+ case 'H':
+ hFlag = true;
+ break;
+ case 'p':
+ pFlag = true;
+ break;
+ case 'l':
+ pFlag = false;
+ lFlag = true;
+ break;
+ default:
+ Tcl_AppendResult(interp, "error - unknown flag ",
+ "usage: ls -apCFHl1 ?files? ", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ argv += i;
+ argc -= i;
+
+ /*
+ * No file specifications means we search for all files.
+ * Glob will be doing most of the work.
+ */
+ if (!argc) {
+ argc = 1;
+ argv = origArgv;
+ strcpy(argv[0], "*");
+ }
+
+ if (!GlobArgs(interp, &argc, &argv)) {
+ Tcl_ResetResult(interp);
+ return TCL_ERROR;
+ }
+
+ /*
+ * There are two major methods for listing files: the long
+ * method and the normal method.
+ */
+ if (lFlag) {
+ char creator[5], type[5], time[16], date[16];
+ char lineTag;
+ long size;
+ unsigned short flags;
+
+ /*
+ * Print the header for long listing.
+ */
+ if (hFlag) {
+ sprintf(theLine, "T %7s %8s %8s %4s %4s %6s %s",
+ "Size", "ModTime", "ModDate",
+ "CRTR", "TYPE", "Flags", "Name");
+ Tcl_AppendResult(interp, theLine, "\n", NULL);
+ Tcl_AppendResult(interp,
+ "-------------------------------------------------------------\n",
+ NULL);
+ }
+
+ for (i = 0; i < argc; i++) {
+ strcpy(theFile, argv[i]);
+
+ c2pstr(theFile);
+ hpb->ioCompletion = NULL;
+ hpb->ioVRefNum = 0;
+ hpb->ioFDirIndex = 0;
+ hpb->ioNamePtr = (StringPtr) theFile;
+ hpb->ioDirID = 0L;
+ err = PBGetCatInfoSync(&paramBlock);
+ p2cstr((StringPtr) theFile);
+
+ if (hpb->ioFlAttrib & 16) {
+ /*
+ * For directories use zero as the size, use no Creator
+ * type, and use 'DIR ' as the file type.
+ */
+ if ((aFlag == false) && (dpb->ioDrUsrWds.frFlags & 0x1000)) {
+ continue;
+ }
+ lineTag = 'D';
+ size = 0;
+ IUTimeString(dpb->ioDrMdDat, false, (unsigned char *)time);
+ p2cstr((StringPtr)time);
+ IUDateString(dpb->ioDrMdDat, shortDate, (unsigned char *)date);
+ p2cstr((StringPtr)date);
+ strcpy(creator, " ");
+ strcpy(type, "DIR ");
+ flags = dpb->ioDrUsrWds.frFlags;
+ if (fFlag || pFlag) {
+ strcat(theFile, ":");
+ }
+ } else {
+ /*
+ * All information for files should be printed. This
+ * includes size, modtime, moddate, creator type, file
+ * type, flags, anf file name.
+ */
+ if ((aFlag == false) &&
+ (hpb->ioFlFndrInfo.fdFlags & kIsInvisible)) {
+ continue;
+ }
+ lineTag = 'F';
+ size = hpb->ioFlLgLen + hpb->ioFlRLgLen;
+ IUTimeString(hpb->ioFlMdDat, false, (unsigned char *)time);
+ p2cstr((StringPtr)time);
+ IUDateString(hpb->ioFlMdDat, shortDate, (unsigned char *)date);
+ p2cstr((StringPtr)date);
+ strncpy(creator, (char *) &hpb->ioFlFndrInfo.fdCreator, 4);
+ creator[4] = 0;
+ strncpy(type, (char *) &hpb->ioFlFndrInfo.fdType, 4);
+ type[4] = 0;
+ flags = hpb->ioFlFndrInfo.fdFlags;
+ if (fFlag) {
+ if (hpb->ioFlFndrInfo.fdFlags & kIsAlias) {
+ strcat(theFile, "@");
+ } else if (hpb->ioFlFndrInfo.fdType == 'APPL') {
+ strcat(theFile, "*");
+ }
+ }
+ }
+
+ sprintf(theLine, "%c %7ld %8s %8s %-4.4s %-4.4s 0x%4.4X %s",
+ lineTag, size, time, date, creator, type, flags, theFile);
+
+ Tcl_AppendResult(interp, theLine, "\n", NULL);
+
+ }
+
+ if ((interp->result != NULL) && (*(interp->result) != '\0')) {
+ int slen = strlen(interp->result);
+ if (interp->result[slen - 1] == '\n') {
+ interp->result[slen - 1] = '\0';
+ }
+ }
+ } else {
+ /*
+ * Not in long format. We only print files names. If the
+ * -C flag is set we need to print in multiple coloumns.
+ */
+ int argCount, linePos;
+ Boolean needNewLine = false;
+
+ /*
+ * Fiend the field length: the length each string printed
+ * to the terminal will be.
+ */
+ if (!cFlag) {
+ perLine = 1;
+ fieldLength = STRING_LENGTH;
+ } else {
+ for (i = 0; i < argc; i++) {
+ len = strlen(argv[i]);
+ if (len > maxLen) {
+ maxLen = len;
+ }
+ }
+ fieldLength = maxLen + 3;
+ perLine = STRING_LENGTH / fieldLength;
+ }
+
+ argCount = 0;
+ linePos = 0;
+ memset(theLine, ' ', STRING_LENGTH);
+ while (argCount < argc) {
+ strcpy(theFile, argv[argCount]);
+
+ c2pstr(theFile);
+ hpb->ioCompletion = NULL;
+ hpb->ioVRefNum = 0;
+ hpb->ioFDirIndex = 0;
+ hpb->ioNamePtr = (StringPtr) theFile;
+ hpb->ioDirID = 0L;
+ err = PBGetCatInfoSync(&paramBlock);
+ p2cstr((StringPtr) theFile);
+
+ if (hpb->ioFlAttrib & 16) {
+ /*
+ * Directory. If -a show hidden files. If -f or -p
+ * denote that this is a directory.
+ */
+ if ((aFlag == false) && (dpb->ioDrUsrWds.frFlags & 0x1000)) {
+ argCount++;
+ continue;
+ }
+ if (fFlag || pFlag) {
+ strcat(theFile, ":");
+ }
+ } else {
+ /*
+ * File: If -a show hidden files, if -f show links
+ * (aliases) and executables (APPLs).
+ */
+ if ((aFlag == false) &&
+ (hpb->ioFlFndrInfo.fdFlags & kIsInvisible)) {
+ argCount++;
+ continue;
+ }
+ if (fFlag) {
+ if (hpb->ioFlFndrInfo.fdFlags & kIsAlias) {
+ strcat(theFile, "@");
+ } else if (hpb->ioFlFndrInfo.fdType == 'APPL') {
+ strcat(theFile, "*");
+ }
+ }
+ }
+
+ /*
+ * Print the item, taking into account multi-
+ * coloum output.
+ */
+ strncpy(theLine + (linePos * fieldLength), theFile,
+ strlen(theFile));
+ linePos++;
+
+ if (linePos == perLine) {
+ theLine[STRING_LENGTH] = '\0';
+ if (needNewLine) {
+ Tcl_AppendResult(interp, "\n", theLine, NULL);
+ } else {
+ Tcl_AppendResult(interp, theLine, NULL);
+ needNewLine = true;
+ }
+ linePos = 0;
+ memset(theLine, ' ', STRING_LENGTH);
+ }
+
+ argCount++;
+ }
+
+ if (linePos != 0) {
+ theLine[STRING_LENGTH] = '\0';
+ if (needNewLine) {
+ Tcl_AppendResult(interp, "\n", theLine, NULL);
+ } else {
+ Tcl_AppendResult(interp, theLine, NULL);
+ }
+ }
+ }
+
+ ckfree((char *) argv);
+
+ return TCL_OK;
+}
diff --git a/mac/tclMacUtil.c b/mac/tclMacUtil.c
new file mode 100644
index 0000000..254cfb8
--- /dev/null
+++ b/mac/tclMacUtil.c
@@ -0,0 +1,441 @@
+/*
+ * tclMacUtil.c --
+ *
+ * This contains utility functions used to help with
+ * implementing Macintosh specific portions of the Tcl port.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tclMacUtil.c 1.53 97/07/30 16:46:16
+ */
+
+#include "tcl.h"
+#include "tclInt.h"
+#include "tclMacInt.h"
+#include "tclMath.h"
+#include "tclMacPort.h"
+
+#include <Aliases.h>
+#include <Errors.h>
+#include <Files.h>
+#include <Folders.h>
+#include <FSpCompat.h>
+#include <Strings.h>
+#include <TextUtils.h>
+#include <MoreFilesExtras.h>
+
+/*
+ * The following two Includes are from the More Files package.
+ */
+#include <FileCopy.h>
+#include <MoreFiles.h>
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * hypotd --
+ *
+ * The standard math function hypot is not supported by Think C.
+ * It is included here so everything works. It is supported by
+ * CodeWarrior Pro 1, but the 68K version does not support doubles.
+ * So we hack it in.
+ *
+ * Results:
+ * Result of computation.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if defined(THINK_C) || defined(__MWERKS__)
+double hypotd(double x, double y);
+
+double
+hypotd(
+ double x, /* X value */
+ double y) /* Y value */
+{
+ double sum;
+
+ sum = x*x + y*y;
+ return sqrt(sum);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpGetDefaultDir --
+ *
+ * This function gets the current default directory.
+ *
+ * Results:
+ * The provided FSSpec is changed to point to the "default"
+ * directory. The function returns what ever errors
+ * FSMakeFSSpecCompat may encounter.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+FSpGetDefaultDir(
+ FSSpecPtr dirSpec) /* On return the default directory. */
+{
+ OSErr err;
+ short vRefNum = 0;
+ long int dirID = 0;
+
+ err = HGetVol(NULL, &vRefNum, &dirID);
+
+ if (err == noErr) {
+ err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
+ dirSpec);
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpSetDefaultDir --
+ *
+ * This function sets the default directory to the directory
+ * pointed to by the provided FSSpec.
+ *
+ * Results:
+ * The function returns what ever errors HSetVol may encounter.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+FSpSetDefaultDir(
+ FSSpecPtr dirSpec) /* The new default directory. */
+{
+ OSErr err;
+
+ /*
+ * The following special case is needed to work around a bug
+ * in the Macintosh OS. (Acutally PC Exchange.)
+ */
+
+ if (dirSpec->parID == fsRtParID) {
+ err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
+ } else {
+ err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpFindFolder --
+ *
+ * This function is a version of the FindFolder function that
+ * returns the result as a FSSpec rather than a vRefNum and dirID.
+ *
+ * Results:
+ * Results will be simaler to that of the FindFolder function.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpFindFolder(
+ short vRefNum, /* Volume reference number. */
+ OSType folderType, /* Folder type taken by FindFolder. */
+ Boolean createFolder, /* Should we create it if non-existant. */
+ FSSpec *spec) /* Pointer to resulting directory. */
+{
+ short foundVRefNum;
+ long foundDirID;
+ OSErr err;
+
+ err = FindFolder(vRefNum, folderType, createFolder,
+ &foundVRefNum, &foundDirID);
+ if (err != noErr) {
+ return err;
+ }
+
+ err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpLocationFromPath --
+ *
+ * This function obtains an FSSpec for a given macintosh path.
+ * Unlike the More Files function FSpLocationFromFullPath, this
+ * function will also accept partial paths and resolve any aliases
+ * along the path.
+ *
+ * Results:
+ * OSErr code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+FSpLocationFromPath(
+ int length, /* Length of path. */
+ char *path, /* The path to convert. */
+ FSSpecPtr fileSpecPtr) /* On return the spec for the path. */
+{
+ Str255 fileName;
+ OSErr err;
+ short vRefNum;
+ long dirID;
+ int pos, cur;
+ Boolean isDirectory;
+ Boolean wasAlias;
+
+ /*
+ * Check to see if this is a full path. If partial
+ * we assume that path starts with the current working
+ * directory. (Ie. volume & dir = 0)
+ */
+ vRefNum = 0;
+ dirID = 0;
+ cur = 0;
+ if (length == 0) {
+ return fnfErr;
+ }
+ if (path[cur] == ':') {
+ cur++;
+ if (cur >= length) {
+ /*
+ * If path = ":", just return current directory.
+ */
+ FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr);
+ return noErr;
+ }
+ } else {
+ while (path[cur] != ':' && cur < length) {
+ cur++;
+ }
+ if (cur > 255) {
+ return bdNamErr;
+ }
+ if (cur < length) {
+ /*
+ * This is a full path
+ */
+ cur++;
+ strncpy((char *) fileName + 1, path, cur);
+ fileName[0] = cur;
+ err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr);
+ if (err != noErr) return err;
+ FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
+ vRefNum = fileSpecPtr->vRefNum;
+ } else {
+ cur = 0;
+ }
+ }
+
+ isDirectory = 1;
+ while (cur < length) {
+ if (!isDirectory) {
+ return dirNFErr;
+ }
+ pos = cur;
+ while (path[pos] != ':' && pos < length) {
+ pos++;
+ }
+ if (pos == cur) {
+ /* Move up one dir */
+ /* cur++; */
+ strcpy((char *) fileName + 1, "::");
+ fileName[0] = 2;
+ } else if (pos - cur > 255) {
+ return bdNamErr;
+ } else {
+ strncpy((char *) fileName + 1, &path[cur], pos - cur);
+ fileName[0] = pos - cur;
+ }
+ err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr);
+ if (err != noErr) return err;
+ err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias);
+ if (err != noErr) return err;
+ FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory);
+ vRefNum = fileSpecPtr->vRefNum;
+ cur = pos;
+ if (path[cur] == ':') {
+ cur++;
+ }
+ }
+
+ return noErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpPathFromLocation --
+ *
+ * This function obtains a full path name for a given macintosh
+ * FSSpec. Unlike the More Files function FSpGetFullPath, this
+ * function will return a C string in the Handle. It also will
+ * create paths for FSSpec that do not yet exist.
+ *
+ * Results:
+ * OSErr code.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpPathFromLocation(
+ FSSpec *spec, /* The location we want a path for. */
+ int *length, /* Length of the resulting path. */
+ Handle *fullPath) /* Handle to path. */
+{
+ OSErr err;
+ FSSpec tempSpec;
+ CInfoPBRec pb;
+
+ *fullPath = NULL;
+
+ /*
+ * Make a copy of the input FSSpec that can be modified.
+ */
+ BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+
+ if (tempSpec.parID == fsRtParID) {
+ /*
+ * The object is a volume. Add a colon to make it a full
+ * pathname. Allocate a handle for it and we are done.
+ */
+ tempSpec.name[0] += 2;
+ tempSpec.name[tempSpec.name[0] - 1] = ':';
+ tempSpec.name[tempSpec.name[0]] = '\0';
+
+ err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ } else {
+ /*
+ * The object isn't a volume. Is the object a file or a directory?
+ */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrDirID = tempSpec.parID;
+ pb.dirInfo.ioFDirIndex = 0;
+ err = PBGetCatInfoSync(&pb);
+
+ if ((err == noErr) || (err == fnfErr)) {
+ /*
+ * If the file doesn't currently exist we start over. If the
+ * directory exists everything will work just fine. Otherwise we
+ * will just fail later. If the object is a directory, append a
+ * colon so full pathname ends with colon.
+ */
+ if (err == fnfErr) {
+ BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+ } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
+ tempSpec.name[0] += 1;
+ tempSpec.name[tempSpec.name[0]] = ':';
+ }
+
+ /*
+ * Create a new Handle for the object - make it a C string.
+ */
+ tempSpec.name[0] += 1;
+ tempSpec.name[tempSpec.name[0]] = '\0';
+ err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+ if (err == noErr) {
+ /*
+ * Get the ancestor directory names - loop until we have an
+ * error or find the root directory.
+ */
+ pb.dirInfo.ioNamePtr = tempSpec.name;
+ pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+ pb.dirInfo.ioDrParID = tempSpec.parID;
+ do {
+ pb.dirInfo.ioFDirIndex = -1;
+ pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+ err = PBGetCatInfoSync(&pb);
+ if (err == noErr) {
+ /*
+ * Append colon to directory name and add
+ * directory name to beginning of fullPath.
+ */
+ ++tempSpec.name[0];
+ tempSpec.name[tempSpec.name[0]] = ':';
+
+ (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
+ tempSpec.name[0]);
+ err = MemError();
+ }
+ } while ( (err == noErr) &&
+ (pb.dirInfo.ioDrDirID != fsRtDirID) );
+ }
+ }
+ }
+
+ /*
+ * On error Dispose the handle, set it to NULL & return the err.
+ * Otherwise, set the length & return.
+ */
+ if (err == noErr) {
+ *length = GetHandleSize(*fullPath) - 1;
+ } else {
+ if ( *fullPath != NULL ) {
+ DisposeHandle(*fullPath);
+ }
+ *fullPath = NULL;
+ *length = 0;
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetGlobalMouse --
+ *
+ * This procedure obtains the current mouse position in global
+ * coordinates.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+GetGlobalMouse(
+ Point *mouse) /* Mouse position. */
+{
+ EventRecord event;
+
+ OSEventAvail(0, &event);
+ *mouse = event.where;
+}