diff options
Diffstat (limited to 'mac')
46 files changed, 0 insertions, 21451 deletions
diff --git a/mac/AppleScript.html b/mac/AppleScript.html deleted file mode 100644 index 4a73fbb..0000000 --- a/mac/AppleScript.html +++ /dev/null @@ -1,298 +0,0 @@ -<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 deleted file mode 100644 index d23235a..0000000 --- a/mac/Background.doc +++ /dev/null @@ -1,92 +0,0 @@ -Notes about the Background Only application template -==================================================== - -RCS: @(#) $Id: Background.doc,v 1.2 1998/09/14 18:40:03 stanton Exp $ - -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 deleted file mode 100644 index bf130ab..0000000 --- a/mac/MW_TclAppleScriptHeader.pch +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: MW_TclAppleScriptHeader.pch,v 1.3 1998/11/10 16:30:35 rjohnson Exp $ - */ - -/* - * 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 deleted file mode 100644 index b6623ac..0000000 --- a/mac/MW_TclHeader.pch +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: MW_TclHeader.pch,v 1.4 1998/11/10 06:49:19 jingham Exp $ - */ - -/* - * 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 - -#include "tclMacCommonPch.h" - -/* - * 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 reset - diff --git a/mac/README b/mac/README deleted file mode 100644 index 956a0ec..0000000 --- a/mac/README +++ /dev/null @@ -1,195 +0,0 @@ -Tcl 8.0.5 for Macintosh - -by Ray Johnson -Scriptics Corporation -rjohnson@scriptics.com -with major help from -Jim Ingham -Cygnus Solutions -jingham@cygnus.com - -RCS: @(#) $Id: README,v 1.4 1999/01/04 19:25:03 rjohnson Exp $ - -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.5.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.5.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.5.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://www.scriptics.com/man/tcl8.0/contents.html - -Other documentation and sample Tcl scripts can be found at -the Tcl archive site: - - ftp://ftp.neosoft.com/tcl/ - -and the Tcl resource center: - - http://www.scriptics.com/resource/ - -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 2 or 3 - 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 3, 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@cygnus.com - diff --git a/mac/bugs.doc b/mac/bugs.doc deleted file mode 100644 index 3e1efb9..0000000 --- a/mac/bugs.doc +++ /dev/null @@ -1,32 +0,0 @@ -Known bug list for Tcl 8.0 for Macintosh - -by Ray Johnson -Sun Microsystems Laboratories -rjohnson@eng.sun.com - -RCS: @(#) $Id: bugs.doc,v 1.2 1998/09/14 18:40:04 stanton Exp $ - -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 deleted file mode 100644 index 2183651..0000000 --- a/mac/libmoto.doc +++ /dev/null @@ -1,39 +0,0 @@ -Notes about the use of libmoto ------------------------------- - -RCS: @(#) $Id: libmoto.doc,v 1.2 1998/09/14 18:40:04 stanton Exp $ - -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 deleted file mode 100644 index 58f0929..0000000 --- a/mac/morefiles.doc +++ /dev/null @@ -1,74 +0,0 @@ -Notes about MoreFiles, dnr.c & other non-Tcl source files ---------------------------------------------------------- - -RCS: @(#) $Id: morefiles.doc,v 1.2 1998/09/14 18:40:04 stanton Exp $ - -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 deleted file mode 100644 index 5e71969..0000000 --- a/mac/porting.notes +++ /dev/null @@ -1,23 +0,0 @@ -Porting Notes -------------- - -RCS: @(#) $Id: porting.notes,v 1.2 1998/09/14 18:40:04 stanton Exp $ - -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 deleted file mode 100644 index 593232b..0000000 --- a/mac/tclMac.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMac.h,v 1.3 1998/11/10 06:49:22 jingham Exp $ - */ - -#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, CONST 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 deleted file mode 100644 index be9dd11..0000000 --- a/mac/tclMacAETE.r +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacAETE.r,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#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 deleted file mode 100644 index 7a8efc4..0000000 --- a/mac/tclMacAlloc.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacAlloc.c,v 1.3 1998/09/14 18:40:04 stanton Exp $ - */ - -#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); - *hand = NULL; - 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; - if (*(memRecord->memoryHandle) != NULL) { - 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; - if (*(memRecord->memoryHandle) != NULL) { - DisposeHandle(memRecord->memoryHandle); - } - DisposePtr((void *) memRecord); - } - while (appMemory != NULL) { - memRecord = appMemory; - appMemory = memRecord->next; - if (*(memRecord->memoryHandle) != NULL) { - 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 deleted file mode 100644 index 693470c..0000000 --- a/mac/tclMacAppInit.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacAppInit.c,v 1.3 1998/11/10 06:49:25 jingham Exp $ - */ - -#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 Procbodytest_Init _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp *interp)); -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; - } - if (Procbodytest_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init, - Procbodytest_SafeInit); -#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 deleted file mode 100644 index 21e013e..0000000 --- a/mac/tclMacApplication.r +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacApplication.r,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#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 deleted file mode 100644 index 173495a..0000000 --- a/mac/tclMacBOAAppInit.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacBOAAppInit.c,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#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 deleted file mode 100644 index ebec082..0000000 --- a/mac/tclMacBOAMain.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacBOAMain.c,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#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 deleted file mode 100644 index 781ee64..0000000 --- a/mac/tclMacChan.c +++ /dev/null @@ -1,1356 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacChan.c,v 1.3 1998/09/14 18:40:04 stanton Exp $ - */ - -#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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpOpenFileChannel -- - * - * 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 -TclpOpenFileChannel( - 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/tclMacCommonPch.h b/mac/tclMacCommonPch.h deleted file mode 100755 index b06a494..0000000 --- a/mac/tclMacCommonPch.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * tclMacCommonPch.h -- - * - * 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. - * - * Copyright (c) 1998 by Scriptics Corporation. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclMacCommonPch.h,v 1.2 1998/11/11 07:46:04 jingham Exp $ - */ - -#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 diff --git a/mac/tclMacDNR.c b/mac/tclMacDNR.c deleted file mode 100644 index fa7058b..0000000 --- a/mac/tclMacDNR.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacDNR.c,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#pragma ANSI_strict off -#include <dnr.c> -#pragma ANSI_strict reset diff --git a/mac/tclMacEnv.c b/mac/tclMacEnv.c deleted file mode 100644 index 8f6b58f..0000000 --- a/mac/tclMacEnv.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacEnv.c,v 1.2 1998/09/14 18:40:04 stanton Exp $ - */ - -#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(¤tDir); - FSpPathFromLocation(¤tDir, &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 deleted file mode 100644 index f7d92c4..0000000 --- a/mac/tclMacExit.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacExit.c,v 1.3 1998/11/11 07:46:13 jingham Exp $ - */ - -#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(); - -/* - * If we are using the Metrowerks Standard Library, then we will call its exit so that it - * will get a chance to clean up temp files, and so forth. It always calls the standard - * ExitToShell, so the Tcl handlers will also get called. - * - * If you have another exit, make sure that it does not patch ExitToShell, and does - * call it. If so, it will probably work as well. - * - */ - -#ifdef __MSL__ - exit(status); -#else - ExitToShell(); -#endif - -} - -/* - *---------------------------------------------------------------------- - * - * 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 deleted file mode 100644 index 92cce37..0000000 --- a/mac/tclMacFCmd.c +++ /dev/null @@ -1,1408 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacFCmd.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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(¶mBlock, 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(¶mBlock, 0); - } else { - err = PBHRstFLock(¶mBlock, 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 deleted file mode 100644 index 4de2267..0000000 --- a/mac/tclMacFile.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacFile.c,v 1.4 1998/09/14 18:40:05 stanton Exp $ - */ - -/* - * 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 TclpStat 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpStat -- - * - * 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 -TclpStat( - CONST 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpAccess -- - * - * 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 -TclpAccess( - 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 deleted file mode 100644 index 13015a5..0000000 --- a/mac/tclMacInit.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacInit.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index a6ceda0..0000000 --- a/mac/tclMacInt.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacInt.h,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 7f37d2f..0000000 --- a/mac/tclMacInterupt.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacInterupt.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index ea84b9d..0000000 --- a/mac/tclMacLibrary.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacLibrary.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -/* - * 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 deleted file mode 100644 index e775d94..0000000 --- a/mac/tclMacLibrary.r +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacLibrary.r,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 9c84ac8..0000000 --- a/mac/tclMacLoad.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacLoad.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 1d11099..0000000 --- a/mac/tclMacMSLPrefix.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacMSLPrefix.h,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 14af9a8..0000000 --- a/mac/tclMacMath.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacMath.h,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index a652c8d..0000000 --- a/mac/tclMacNotify.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacNotify.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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(¬ifier, 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(¤tMouse); - 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(¤tMouse); - 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(¬ifier.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(¤tMouse); - 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 deleted file mode 100644 index d4bc14d..0000000 --- a/mac/tclMacOSA.c +++ /dev/null @@ -1,2937 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacOSA.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 4cde512..0000000 --- a/mac/tclMacOSA.exp +++ /dev/null @@ -1 +0,0 @@ -Tclapplescript_Init diff --git a/mac/tclMacOSA.r b/mac/tclMacOSA.r deleted file mode 100644 index 6521ac8..0000000 --- a/mac/tclMacOSA.r +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacOSA.r,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - -#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 deleted file mode 100644 index 081c856..0000000 --- a/mac/tclMacPanic.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacPanic.c,v 1.2 1998/09/14 18:40:05 stanton Exp $ - */ - - -#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 deleted file mode 100644 index abf1d6c..0000000 --- a/mac/tclMacPort.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacPort.h,v 1.5 1998/09/14 18:40:06 stanton Exp $ - */ - -#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 TclpAccess. - */ - -# 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 defines replace the Macintosh version of the POSIX - * functions "stat" and "access". The various compilier vendors - * don't implement this function well nor consistantly. - */ -#define lstat(path, bufPtr) TclStat(path, bufPtr) - -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" - -/* - * TclpFinalize is a noop on the Mac. - */ - -#define TclpFinalize() - -/* - * 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)) ; -EXTERN int TclpStat _ANSI_ARGS_ ((CONST char *path, struct stat *buf)); -EXTERN int TclpAccess _ANSI_ARGS_ ((CONST char *path, int mode)); - -#endif /* _MACPORT */ diff --git a/mac/tclMacProjects.sea.hqx b/mac/tclMacProjects.sea.hqx deleted file mode 100644 index fc875e7..0000000 --- a/mac/tclMacProjects.sea.hqx +++ /dev/null @@ -1,1704 +0,0 @@ -(This file must be converted with BinHex 4.0) -:#d&bBfKTGQ8ZFf9K!%&38%aKGA0d)!#3!q8B!!"Cp2Kc8dP8)3!&!!$P'(*-BA8 -#G`#3!aChG`d0$%eKBe4ME#"08d`ZZ5q,G!FhpA)!N!J(0rGdP-!!N"3S[!#3"2q -3"%e08(*$9dP&!3#[Pi&PXQjr5J!!!4i!!8q,!*!$D3!!*mhGH6DA!*!'kiF4!!L -bdAJqT3$Ldi`fC,5RjQK+Ai"mIT)55NR(rQ!RhrRB-b[h[pkGBp2c!SVId'RY!kK -haCaq&5hRD[I2dCBfR+[G08GE9QZZGR51GREPZCSq4k[%Fl9EXc9lIc+GAH0VibK -8hm)N!!!'!-@fALIKK'IN@0H46AMN9V)pXQQE-(*dNf14,@(N0YNqj@YA4i[+P&! -VE8XiS4a2m8RI`RHfm8mlVhfQC(YN5lEI5lBIfIENYT&Y!`R[*2YBPdFff8GZ(qX -kb5Dhb6E*mFJQYmmRqmQ@r$l#*EI2A-JqFJXrXLR3i39D"fa32Z%6XkF%J0`Q)dj -3`$YbQj,$A`-fm"VDh%BjXN'1l$I,mlMP*H9RIV%Qk@BCjE%VIER@8AleZTaRpRk -pGTfK3,*`XJICQ3-lqr3@,ff3!&j[HFN@lH+,rR*HZRMN&V)cXT!!@`6!!JJBh`1 -XEjfGYCld2Cjq(q'I4hiK#ePBjbd!2)!m4hk($q)i-XDX-XCEElc5cidhq)3aDcm -2RbZpJSHRGaVL@VMG6j*kR"3V56`A"PR(ej*bBXE6ZGQXpXc58Y[a4dYddUE*hAl -jcCZ-fA%62qAMQK0@Pq1Q(m5[C"JakmeDljl#hXilHh3Q[&h@)[$H2TPQI[*Q9dD --1Fl[MqH2T4$Mia3N2m$@`LZ,AjY"C6qi)24VBC,fcckIJ)[)LDMNl+aDGlGC+qq -U05drf1R2K#rQAbhrZR5amCcri1TLQS@08Z5RDCJqipr[[2PQ,AST2Bf%R'(iI[6 -DSAid+6ErRIAA2NQN50KFfHJ#Bi[*4TXC@hHm5,X1fIb'fHGe5m-MBj2b'rCk2Hd -&KeS*Q*RDq5LJ-8$U('H,*T[aqcE#q!PM6V2fJifl'RFpe-$c)*lDT[c@iQl+Hm- -aCq2CKPYP((q%1#AfV@C0RY1jYPQFLh#[B9c-kPl()J$EY%hfT3!rKA8Te!2f&"S -lCJda@GZaDT4-KNU"GE5JS%NIC9L#qq5m$#l![r[SQ$VG(2LRB[J958BVjkAl`UZ -(HLbe)*-#`kT([T(RE,k`9l`qN!!5*j)C*02`,)K!%jUU)j8NR+i[2%-8fUYEl#G -P'9J1NjQ`12SUF5QHG6MV+j@4['Ua`C(c*i+Gp4T*lVCUTG6Yf'JRDqdRS*ZUa1, -#'HDf9Aej`HBEEd*8)P(2%EfBdlY8`pRBUr$T!N%1,-8(`jp[pkNk[i,E)e'1Z4A -h30Nq`9i9fd2N5T)q13q5E6)jNYL@ic&%YLBmKXTfDCG!Z!Yi$*IYcDSKYMr&Bk4 -X(m'M4VB[iM&+YZrJ-GVD)UcT'0Q!mV'bJAVMC$Z,8#qfRAK-N!$Y@M`dr#[E,AK --NZfGH&"2E04JLQarKdHYE0r$BkUJPekD*KXqp#!fqQ#'E#r'BkCX&q-a5lDVm0# -GV@`hib&S'[dk(R0NS`CcCD-'mf4l')rj25"E)"XeVC-0$&JS@b-HLf6EJFGLfAj -1@)%0JBEH`IDAH#b9l@ra@#EEJhK3@b#&a&I)4YiVC52@+YR1`D0H0PM9DYPq#3q -B%VEIaJ1fKHepH-#fX(fH3#UfIm,M&'[V4qaC,a[pZ8%fmJ&$XCf,"cA("Q8r9ED -Em0JSfarJFCTX(m+$2XAf*@%QYZrLFBDep5FQ[N3fH[j-fDJ[@)GY#ajJ$MEb2PZ -fAm9MNfarMJGpJBdDEjB0E#-q8!`ZEj80A+#Hf+J[,"2EGY)'XEdD$m9SYHehm6K -I0[VT!YQqJ-H&XP(ALkaY)2(pCE*49c!+'re$MYM!ljI,GMdHB!JfHZJ5fHl!!ic -&pJpi%"2E[iYh3#AJ!*I*"QDp3MCk6%KE94d2EQb[`q0bfFMePE+"LiL-f"3MGb6 -F9$f*aejVUbBQL6T@6GaTNBhHZ&+fUr(B,a[i*r*10IY'Z&meq`DXaUE8!iFae4P -%$S-+J!fmKYGJ!e2J&pMSJ9I*pKSm`&YXB"lm#p[(m2J&fEk""lfXMUC8emN'2a' -pBc!a%Ic%4Mq6&cEUp9VCi&Ad+EEhi%%IB32,Ej!!$3ai[E80)3Dm36Eib4YP!fp -ZP)fq"6qaN31F"4Ymm8fbI3D2AjEYfhM!+p8C5Z`%!l(4pp3('hJ+rm*'Rlp&0R* -lUfarKXH[bABA(VmZfcrMm6CV'dDmT(qa`DQdMU"XF)2INJfXSHq`8G2INHhGH)# -Cf$k(aqr*"XrlI@XE6Ni,rQ#Merp30MM$(mN'I[faE265RmMf$McH,YZRmB$IBB0 -2`hR9'8%HHDYXF%9k#KXmKrMB`&ri+6E`iPfb8@YUL!hFSPq`hBX([Bm0[JM[8'F -NHr%[C+0AhLXE(!RHK`eF)4GXB0clCD0A2b!EHAj3YNrLFCYXF%6iP$Sej1JIPJd -qI,YXB"JBMJf1m9(C`%h`%"Yim9Hb8IH2brBT21!Df1#&GeVE+'SLIbdEf)pfJ3f -q5Rf``E[q4MEi!,PJ!fr!&QcN5TpL``G-`rBY2$iV'kS8@+(1D(*3F"8E["G1K`h -qGVGXF)alC+1ZF!TXB!(k"MEU#2I%"UHKIl(p*ajIYVBaj%rS!0MJm&q4$@lj9GR -J2(m['cMh0GR!NB1bd4Y`0'ciN!![YKrJFCqeMD8Z!ar"KUE`6GRJ[ImS'jKk[fa -`%[S4'pK+[f#Mjaq3!)fDJJrBISJ('+M111Sii$NfG)TrNBdHJNGJ!iIJb0M!qRq -9$Ib#bf#M0m!kE260[eREH'T!i$NfG!eiR+hMH0*b4LF-6e(AjA5Vd)jhKU3MUmZ -"b%*J!@`)+f!+dB8%393KU""Pb!-%&@)+)3@F)'836`JRB!M"K&K#+#'5%%L))i3 -DdJKCK#4##!!c3!c`!V3JHK!m#"H%$U))5B(33H3!3)JN`!V)!kS313JFa!h#"P' -$S%(-)'5!-J3-iJAKJQK"X##HN!!Vb!L!$+'#,%#@%%dJ-SJNL#m3$83(a"&%%F3 -Ca"H!'M%%-SIiJHL"f!&T4Ga!e%$-J$!JAL"D)&BJiL"8)#iJ6%#L)3)3!)!I`)H --3F)JAj!!,XJFC!h5"GQ#C%(f)#+3!$G)#'3,NJ@jJS"!TL!+N!!R5"0N#C)%%B) -83BBJ3C!!3`J3a!F#!qQ"l#$))6BM-N-X4*!!eQ)d!M2N%m%'d4Sd4F!&X&&d%$m -3%b"8#,L3!((%&i4ea2*JDJ9K!k%GF4jK'V+*%)hBM&L(i!ba4M4!-%HmJG3M8N! -@%DNJFJMV%"r%@3Ja`Le%#m%Ai4ELLT!!#HSM##1B)DJLc#,)3YJ4B"%N%&83KK! -)%3d39"'p%%-JTBLR#(U)1j!!484V4%l%63JGBLBL+@3F-4-4%r%5%48LLd#(D)N -)J8L*1)NSL9#!#),iL1L)f)M!KVL)1)AB#L&&L%&!&1(`IiiD*UNYp9F`PE&qDh@ -i@#U1e+F52eNdfjVeK@*e[Y@+-4QhB`U[lHHX2M"p&FF$hhV3q19f2`T6'rI9 -XPQme2,DI85j*3cm*k(,*r24dQ%c@BpKf"R'Mi6GV01hbfdllQQNFK66ZmCRC6L5 -c1r#Mb55FUF2CGcZ`f!Va[V5HB)M5LpfF*%fqUB2Ri9ZmQ0VD%V0%Pd@aRlAGX'e -[q0RXj%`d(l)"P*HUkik)'HkC5V1NhTbKUEPKApZRjjX"mpK66`1EDJ[L,jP1kG5 -#DG$YlFj)'Eed@j!!c)&T'+j-d8MU[Grf3'[J0qR@@TpTqK%0IYUH`8Y6f3l%84i -2be9jS'[6X,N,KJ2e"LZQRe,ERFdXNNd00[SP[kTC6l0DehK0fj3+I9@@0[dmRrS -1-03"%4cFYF-0BN%YX@)$LlZ[@E`JM&UQ[,eBHPpT`iEF8aNhq5MV&EPeFlM(i,d -qECL*dZMQc3Gcf$4db&aIAL`HcVPT4pI"kB`qLEdHeUe"p(6)V*06(4lG0S&bk[G -T86cP4qa@E@i+Qr-GibCfD(250QqV0f[aERUR8PUqkF,q9M*h+(GmVMLFZA)arB+ -jUE,pN!$ClaJa5XGJ6A8&j[T@+rKD0lHJb,S69"`6JQUdKYPFSpA2iZJ+RPeP+)A -YHhH'L4b8Xqr3-*pQFD0iBELi1djUU4N)JM"08CB$XkNCpc%MGU"B$E--L04U0J0 -4DmYqUj9E0mcASeTaD#&,r03-KP2c-c0K8V3a(9[NKVM43Nb9TMDV@HLp0T'Y&D5 -i0ic-m&KaY!8BfVd(85J8-p1RKFhFePK255Vf6$'&9"8aU@lahM*Al@'0C+A!*jN -leIDc`TE1+Y8+Q2aX'MDAfB-HEk#2324cXhS1)@eGrY)@S(dd2QZ,aZHf!"fKQ)Z -fH,5Pc9+*YJiCD'[$IeX(pYX%jiZ,)hjcCKlMZXR'@j)AX"B9E%lm$,c)1E2E6%Z -,!l8D@*1DPEiLEbC&Qf`PFT@Pk2Lk+"U0,lULqrL$PZJYrU!P@SSrD)PqiJpDSS[ -iJjES'rkJ*6U(2fL*PZ%2@U+VbD#PeXpNd&*VC$*SUI9''E68qU!-@QV06`BYYCi -RJjCD#j0"5kf&bD#PeVCNd&*VE$*SkI`$YqKD,R1@38ZA2M*Sk9+$NN&,PjU6$&U -kl!-CY(5T(mQJTFXqN!""5jFDN!!-@VV8EQ63dQAYCG$5TBiSJjBZG8-CY(5T$mU -JT8Yp9JBYAHUZ-QMT8Nq938ZAZUN-@VV83'A3dUA1+B1@,[Y$"LeGkS3bD1P5rj0 -"5jFkT!aDZZ`2'E5-%"G%,Bq`*fA3-X)qN8(,#21A3FX)p6FCY)a34j0"b`La33B -Y)p5lC0!b3Ue,"LdMe,9Nd$*#E*!!3FX)G@JCY)a3FjC"b`LeBKQdM,$f-QJCS9i -UJjB4ePJ',528MQA3-X*K%"QdM",[C0!b5Kb438Xpp#U$PP(@83BYpG#V$&T'UHr -*S'@8[5k$PRS!9JBYSp5"CG!b5VeG"LfMe-YPd$*+69X',D28TfA38Jr'bU"PP,U -[$&T'1AJSJjBaiV)-@XD)F6*S'51Qb+#P(TL93FXBHd!',@2-@3BYBp3LCG!b4Je -F"Lhe)+d-@XDSBFZJCBbc!M*S'D2q,i1@-HVi-QJCSai[JjBaeP8',@2X84QdM&' -EPN(,'(9j'E5-XFBbD"PRM@A3-YiEY06$Z6*S'5GZbU"PR"JRJjCaiSMSTA(fX`a -DaYPM-QJCCpePd$,1@XLJCCbaC0!bc[N!'E5-8r1A3FXiHd)',H2%E1(JFFj,b+" -PR$-0-QJCjeb#$&V'LFdbD'PC106)c$F%QM1i3+q!Vf!q234ZJC9JMGkb33(9l@[ -jB!cm$pi(e[MD0pb2ISAh`IIJA(!*Ab1(hp(6F"6`bZMkp$BF$PccYA1`&qi"A`- -2`8H`'Gb'!i#Ti!#mcX`b#%jVM)DMJ-rJ1Y`#6JG'`crm'BHm4Jp[!F2-[!+m"Lb -$,i!Ti'jqVJ"--M-0rM`$H!fRJE["fH"Nm#li'$`-rZ9VrZ!4Q!9@J9&JNjPI%5l -9Hla0&`lh&E'P)BBlMTZ"+E@B`cNHpd$F9ELVF3r#24Mh%0a$F3r$24ch50`eZ*P -1()el$1kaZ-IK(Spl!Zk*Z#IKCYI2&0beZ+ILRSCl1ZiCZ'ILRSAl*0bcFFr"24I -h20ccF5r!ABGl)Hj&Z"Hh9i#SHbRZCELAiek"HbAZ9EMVFDr'[3EhfRc0LDmdr'5 -KKM&B$pCQH%FKkG!YrLjIqhMUpY6&0j,RJZ&+FF[!4F58Ril,T5[kb()89C9dESF -#k65H+Te1hRd,mZYBcC3l[ZJM0HmkfBEb"D4(XNY'iH@,@FH1ALeP!GJ[pIbK6D" -')K'SmlrpB"ZBbI31K-0E$f-jb%i@J-@dPdhf$59cL@U+&bUNRR%A"rVEcm@"([G -hFD$2!e`F+2C!&`IdUR*aS1R9,Jj8IT!!L`2&(qcL)!%-FA%JDd0G(+5%B5i1k$I -Fa8'+'1(L`%K'ZMK)'68Z$P,(D"F(+@5-Li0F-YE&38)Cjq)JTBahFC!!@bDi1%J -b%edFC*Y*,Jlbc@3A"fPRLSZ$r&2ViL!$6A9aN!#+TVNib%R6A4bNTKNZ$P,86"F -(@@U@Li0dGC+,Jl`efm9"!T[MiL#6cA9aN!$3jVNi@QElF4`Nb38Z$Y*HRBZ$Y,I -3a8(k@q6L)!qZHb&1-U!R)ClLiL$eVRGaN!"I0lJi5-)0,Jjbl#iA"lPfYiZ$*(Z -jLi1FqdSA"eRe#KF(qAL2Li1F[YI&3CVHjq,S(9!rMS1FIk@,Jibqhm9"jQjp28i -LRR)h#ckYLR(3ppKiQP3DeB*Lp6TcAh-1Ba460'jPD6XE!3S",TbeVlN6@Q"0Hf6 -8cRE3qY'eH3rBelambp,5SpTePca26YrBcNlhFQjQ-[ba5(mGNKQ$p-FIcGLM2r+ -)2Kq--CSe61@e5Ik)S6pDL*k*9SN1DFB,dIh3p0$Vd1+#G8TQMC+r2ZRiBH$`b#b -5r33dl!1$F)R8'$N8flRHGGi*"@eSeFIMZFG2"&MR,hD`",6#-!aQeQT[M9iF8kI -PR2l4irYk*i9kb,ZpYMD"6+`a++@S5kkKRNiK-IqUIQlJ[(rpUm1c*`9ZHAJ$"8b -@XQMcZI2`UG'U!hFVUDmrX1V4"pYVLjdKc,TL9fI034pJAGeXd9"lmG8N)P1'hTV -[rVJ(i"k)Z`Th0Hj"Z!IM(S*l+1jKZ)IMVX%p#[GSh'0`Mm8p$[Gih"0`6m3p#IG -Nh&0`eq+HLRXDlZQiCq#HLAX@lT0`cmBp"rGFh20`cmHp!(FGlS@i&q&HM(X*lU@ -iPq&HMRX&lT@i9q'ZaldDpaVFDh'r+2mRK)(BS0'aQZURMCeZEJX#8!KFf!6J-[2 -r"6ShfIYLp6QfKi&UD@0r[C&pjX6a@b+GbrQ5ack!kdpdVFRD'1d8h0j#)FXNfVR -q[!6,%GNNQ2!i&F[RpKedf"JhXjkjDEK5l5cJblTjUrGNDer@epr&Ph,EAlUieEU -Nq+a,4hlLQGL6Ph,G-9-2LL@r9Fch9#4A"HC$q*X61eb,&3S+QPjcQ(4M98BqL`E -X0FaQS0C5EZCfa&bPVYPdeV29abYA1CcDXa82Ij0MdM(B$CRd6'q*6''$f3LCG-X -YAFbijXTN&M'QUT(C+"NiGV5j,(&-9GTEYYQ4JhKf*'&f8QDm#L8efcE66QbXc(U -dpk,CBTPd5qqc6,TYLHH6)+ckdb&5DCiqdN,Y93[fHDBJ1lhCddF%lA8QGXHQdBm -0SYiDR+"-'Xl8ET`@V-I*HVfdI'LTDcZf'1F-["M2A!@0FkD)DGF--KR2G+F%MTN -@$lcp,Jrm%QfG,RJ@[YTpNq#6pK83-ciC0Q%mdafBFq`X6'GlGR5jFFm"DBGc9cR -6F"Si&Y[0J'VJTh%ejj3[G3CGM@F'B)eR`,Z-EjTk"BljFKN#PPeVR%2%`$m0LS& -cJ)Z"I`BD!qmd1JE1"L$c[ZQQc3H3!%E)ZalUK3aBGVNR!#ERlN&Qi*C'cF$C!'H -REhHTI2J-r0S40)J3J'M"re#C$C6QIAXD-`@SH9F`YG1[d!9TC!fFdq!D1'Ia0A! -h%*[h,G3`VA4N&FPflKN%b2$2`$[(3B-!@4iDZ'HiD1#GjU0jj`a*bNG)l[TZpbd -f4CDIG[NR59h1AhKUi*IKUS&hQUpf1KmU@)+h"SiGh$8)NH1[K3$&FUGjE0kjYdd -c+pREI6@RlA6XESF-Y`fm-r`fm!iiEZ#IjVPjjqj5&Q"BYZQ(31b(k)CLhlm%aRk -)3h$X"qJ'C0qr!-R'[E[E6Bcf*M(HBCXFJZC-K$aD*5,Ni0Rhl!CShlm!d@Rh8[% -kB0Thl3&U2dJ*UV-K`[)Ai0UiPeZi#l+0GaDddkl&"ZN'EYqr'lTprb*iqa%+m'h -FLi8Y3RJII)I3h3IE2C!!(F*e#DV,-&f%k")mpd*c,bah3A))ab8S$Q'i!-%9q1f -$hMlB,8&Z'@k,8&Z!f4,%K[!D3QX[V*BJY3LRh9$D*dQ&JP5I(08M4S959%Q)+XY -344'U*%(e#P#pmP1Aq"4+6bAK+C5G#U*64A,U%jckj+D5f&5@QST#8d&Q+SP-SF3 -8#NbpmP**A#T+5b9K#GIJ6d3#2%cmHNK(5UFZ"+(pJBiZ`P$+6G2@I'iqmSHjNAr -q[cqb)GTr!b3E)29A)&R2cTm%b9DTV`+%k+N!!ESUJ+IPkcG&@''KRYe,Y0ADLd5 -FF)QfL4-Zd6Ca`LAD*Nki40[%#CGSQcMK%Qd6*ebLEH+%5l40R(#*YSN6,Y%fFF) -PfLC1Z%6Ea!QAD*Xii4*Y%bGFSQhLK%Zd6Ca`1ED*%bl(0R(#jGJQ6VJFfm3*Pf1 -E11&bE"-RA)jYiS6,X8fFF$QfL4-ZacCa`ZAB*Nki(0[%#CGMQcMKFQ`6*eb1EH+ -%bl&0R(!jYSN6,XFfFF,Pf#C1Z"cEa!QABjXiiA*X%bGFMQhLK-Za6Ca`1ED*%bl -(0R%1,mG@F3i[aeCa$Lr(9R%1,mG@F3i[aeCa@-CA@BkYiV#`Vl)F@m9KU9pP1ED -+`q+rbR*X&BIPJ*APf#S1#`3Vbl&9(*B-9TCMUcJX)U`XaeCa@&CB@BkYiV$dZV) -F@m9KkA9P1ECHKfA,A)jp*%i%2a6LrmkZpHA8p*9'"iIkLRf$!q-$H'iD,ShV*jc -X2FFG`N,1D#kplRMZhf&X-mIrNaVZSH8``fDZjQ4R@Z53!*,D2+PqrUTa[lRb`D+ -jl)%ce[%h'bF@GTQhcpBLrNl4RGAaXG24Djm[$fhGe[l6&krr)MFmh[l"UhX+0ca -jD'PKj2SPrAb8lH"deG4HF[6I*VZQS%%bqII#H[d9Z*l*fY)+JrTd2G![F&Pc$Mq -aj0SGh'U1T"pTUffRJ@`N"kSM%NHFrrKGhf-C@c,mR111T0Eq&8V[9aKYCiL4`J2 -q38RK35F(Bh,CeX2"V"eiS"I#&r&!r56TeALV@9EI`hU'"dSCbr-$MbRZ$PF`krp -Z2&$m325$0"iSUr@-%"6`3%mZG1cmY`%G5m61Ic[)(q&CEIjEB-5cIpYVMLAL[`9 -X,,mKmN)#B4*--BRFcdpE9drf4m9Y,-F+0rfT6m5Fa"pCb[`DHrD-YlqTG2c`Mm$ -V@bhpA[,a2*V+)rSpkH,*rUYpjfQUM1LhT8rNXDfNhk)qAYI0eE%A-R`UMke$%q2 -p8l-Q501r'ZqTQMRjTrTYD(ALTqDfp-rVbh'['XdeVXL"Ac)0,`rjqHMZNrl[rF, -amZMp3kSRmZJYb"0jp!UT2mQM*j((mfKHX(RiXVCllYlpEH%pkPf'(d0qrCDI'Hq -admlGqi@ehYl#Jl"rYah2[DU64ql[MCqU"cX)G4jp1R2bKrf,KIAb82Z8,3&jl$a -@fA*Gq3XY2im3L4l2BlpK(fkjqSGj2jkrk9j[r+fGC8(Z$Q`"GVbYhYBl)UqmRcr -Tl-$r[a(R6M2ZhIGZrXkjPdHVQAd&Tle0`di1e)RXXMKpAQPdQFF3Bq0V61E510! -[HIrIS5$ldq3eeR!NMpECD2PAZG6HjJSrDmhQ9`M)Je1(*RQZVJ`+#1-ZbUrf$mC -p5&0lQR%Aml!'-1kccpZbr#0L6CAYbr@`I$$hNJ,k*(1[j('8Z9Ib1-VF(mRM#(- -[jk'Cq`qZaDd`1hS,GQGkc"h5*mcpR%rdQ2X@f$9IpcShNFGMc,e3MfHCHl'`6c( -hFKj(QAXKM@HBHcQ2,(0IGmUrQIZkG8mcpqBCFa5R(55LIj+JNlNIc((DqX'iPfr -LlpGhR+FCpk%m1*B!aUeq[1$NMFAHAa4Ncq!h'00jQlJbYSKiMc'Q5Kj(QFiMH4a -K1Z8m@N`F4$GIC`ThVcHR6(d(EYZphE#2HZI0X&hIC35UdC6$aP%JAY[02mlp,rr -@0lYj+'CK#FMM+,-Se28CCP(1S`q%94lk"b$#'&iHcDRCX1%PCN%5cDR!8pQ"Xd! -"5#"R+3p$i6"RmMKiDAZSYIc,LLR&aQ[BEL6I0cAh5KjR6mdYje'G8kV5e1+3!&` -lfrcHNlbVYVjFqBjM+Tr3cU`!H64%D@Vk!rjHhD%m9#2UBGj3jG@DPa@J(PUVXJ, -Ni@Y9B4k2De@lXNCNAQB%DVArkpjcJ4K!cBjE$M1#flNShF[MFRC4X4k2pTPS",Y -E4rX9MD$)lEdmQ%4h1,"rSZqe4Q!&k&HY%9J"mY")VZ(-q@pGG4lX-cM4(`2,,`k -Zb4P4'YP@"4PURRkcm[`HUeE")9@P22,UG3l*8F'Y!(PSp9UeBZ[42!,e1Xm94I[ -Sc51VVKAc8%cD%T!!Kk+ZPS!mVNL2e82pMN[QcaFcH55i[G*LE!(e8&U-(5!2"@G -K(Q8m5qDK0)*MH548jedQr3qq*ZV4BLM'K2f49Td2p3FDNb8J$k8a(H[AV-CN!mM -M3'VqefI9[4r1l!aB*8E`X(IJkYqE`Td6jT5(VZaiMrliRBFU4ME+cX-pF%dq6a2 -j`$[)fj1-`"+3!)GL"*D!2"55f`,bD&NKS+kl6+[eCKl*Z3q&9-Ibb#,9mhP`k[a -AmH28Ja1*NNXbMdXHk15aEb@!2+Tl[kA8LAMpFp@`kIlE9hePmYaFKCViI[jQKRF -Q2[c5PM)96aFU0M54G94$+d!H@U@c!Z6KUh4K(RQ9,TR(kGb5j+YL2I9!&5[@`mY -$Ue"@J,VU5C86HI!H1MEVYp+iY[JL(aTVNH(ZXeF+3!BE3"i*&DU84hjV3G#*#4A -Urr0!PlB#e09$2"Y!(MlL+4,c11*4fNl%fiQ*Pe)pmY2LAANS4Q8*b%0aB%Y!(SS -$f`,bD&NKS+l-8*j!mJ5A2PD20*FqPNH@5pX!mYLIUf)pc%ZY#G"!hG0RVDrQ)GX -'H[,3f`E8U&1B4hlE3*!!KjjVS2&2i,eQP&D!2$5Mp"Uff"mG@`+#ZZVC4bY!(Kb -YcKkV+a0FCmA0jc82rlMPFQ8&J!e`HMkL[&9Z`XT[H`h#NeHKJQ0MfQY`r&L@pKU -dY)lY%LMA0D8ep*bmbY[C(qa(1(%X)2X4#J$bc(k%dSj+1m"qK2*iK-a(@!%kb"l -!h#d9c03+J*af"D4kp*5A3eT!0"f,bhE)m&J)Y"Kld(E)BmHbY"hbF5fQ+a%EJ4E -6'd2Q2RU1I@[,C(RPPA2b'`bZY0RR53CAbH-SJk[NFC6"2C,(%3CAcZ-ajPA)ieR -Q95c)8mbVR-G4jP9)iaRQ9FRM-HE9PBLPB*GAk35l[,U2(B!4k$bX%VZmbUZmR,H -Y2+%Y0SaHHh46B3)C+MrQSAH#@3(b1'-ZQHl(r9aGB4D@%ie5laBlhKr*h@,(qp8 -HS1RSh@)Rm)1*c3[UV@90jp'kfLFd(BlX+(ZqVMU2[RqZ1Cb(prGpr"0622qE-[k -rSVlKVh6frfbp*r@hGI*hECDm[qqcqIchMV8$$a429hp"C-(lqclEfpr@*IlTU65 -TDcdpUApkkTQYXjLF&ek+rr38!3&6rebK2q[,UHNVM3i1p4Al"JI'"r$F0&`DleY -CT3'X-"KJL6Qf1"5`ija4RXA+a,paH*F"8'@ddH$T#rN%TURq`86GQr'hA*`Yj[M -m[CArcUA1ZG"c15meaqA[E8,B!hTITII9HVITICij-AqIRrrGSC,IaHp#[5p5[Lq -6r@,PZehj[ecjlP$qPqLpdkc1hjFUEV2LAQC1b0q[@,%KA`i4L%UQH*%4dBP)PN5 -X`Pf0QqiBM(X)lU'i'EdBMRX%lT'iDpLKkKk0H`cZXEM(U9FRi*k)Ha,ZbELRi'C -'BLVZDELRijk"HbEZ@EL4R'IMRS0l,QjQcpJM[`"h(Hk&Z0QDZaMh%Y`RifEreM, -Fc$1Y`,d5pbVFr%V9kK8#m)GZLBk0MSiIG)UH2lDY2ErPRM5`Y6TFj$S'rEH(9'I -Mm-J3!VYk4r51kKh61kjh2lhlkce!li&k9qPGVIFJ[3IV286[SAS2dhZihLIV29, -['VfAkMe+lp&kMp&lV0lMp"k[p`5p*qSp5Hr*HNr4ZeE[UAT2dhZkhM2dRURh,,e -2dRZChX[eAU(h5VeAk9f[pfUpeqLp9ZmApGSeFL,qZHqDpSrA!Ad5C,EHFr5HUrF -m[HIV[D#A626iCVLl1MbkEB)i+J(Up&kSpb+p&qZp*2q$60@9r6plcGkPTDIqIaP -rl$,(aU-i@QI1QAmM,Gf6CNHQr[TI3VUVr,+ML6AhN5BV[lf(r@*Ia'-fr(BIpKZ -,H!18Ar42AEpDq296IXC[&[`LbXriZH6#JeS*rLTJf$hlZThXN[-ZXRiANA0l#S$ -MFG[m'GC[d51`H8U#ipf1a`$VYraq&Nlm2S$(9ZZhE!Jf6eP`#Z6qbkhIYGq&c9- -@R!,(%qZXhhANqjl#i"6B&j,IlG3$2+A#+HcUqPhf-'bH%Z%82XBDH(lVYm*'[[L -pTZ[h[Xr"K[k!h`eih'Mp6[deHm,cLd+,F+qaIUYr"`Gd#XU&hM$HqYh)(PGaG(q -IcQEfr&b1*+*EU$2b*mJMS[jJf4Cp4c[Fa+EGNkA%Ja5+,[Jf5M#JNHAcbbQrfHK -MjrmD@43IpS[GbaUSH1"%bQr9pq#lY*(0(-'$YAp'cHFh@LRLTIcFFk#A42C@4Y) --f9"MrBmG+SF[GA()j(%+kZXL[aC1A+EbM[qa9eI"$XiZi'+LVNNrpi0rkH@4LKG -lXPIAP0p'kM6I8aqNr2T4Rr(kX[&GRi40rc@-Bcjb+f&1qcAXfJB(CHHmq3l%p2# -[i4aU3qq`IQrl%DDeGeQrhq"HeRGD[rASEhH0pIX[%[Yh+Hpc#-UHhrd2`DEk9rI -"hF3Hcqrlh'%26K)2h"aLrDiP[Vl(qTd'rFTGEHZhj$0`i*p)L%IpepKi0a22`%c -mhYl0irf6X)(KkV`BHTIl@qYh0c&'e9R(ibherSmI`+Chk5XGiZ)1lMCF6La8Z-& -T3diaLrF00r+rdm"cmU"Q(SifRNiXqk$m90mi8pD[rMH`h@EpjRmIMj8fM`p49m0 -1hJm68cfrYh`CYJm,4p([2"aYf(m!0QT&2j'6p0-[FREp)pC[hKr`q)601dTqm&( -VGcVqm-K9AcCp'JiIXhi[BIeZYAl[TTC(hF"TaFq%pc4mD3YX(lGq"k#I403hhq! -'K$Z%dp4TK[AlqMpKZe0qF"fTdkA8EF"RH#'Fi"EVpa$c9Vb!dm!qPMl6Iqh`5G8 -EIL*i0Tjk*rL[cN&J9G@PeQrG&A$iP29l!2m9*AM@H#CVICIeqmleA6alp4JF2Uf -m`9h"XlZSNhj'HD1AHRh61%4-qDcmeREUfPLN$[SjqCh@aD(EN!#6m`[VerMh$Ti -er)UB"6G8C`llh-1caJTj&6K*(Q#cj2&$lK5iarUp!AU[i&RMKmLT[U"ic)e,Ael -2H&m8(UKi2TkpPcJ0Ie(R6F"4(mmZqbSFlK9ZS60lH0C`"@[`CG9*e8r`V#&NIm! -0b3rq)(M@6!lb&H%@HV$JfDhXkDqU6X6`m+aa)hXH(--2AL(pY**mpf[@lie2G2# -X)HC#"$J&&&AKV1"Cid@2`3(1Umj0l"r"XeZ)@h"cm&ApRjD2CpIZKZdqblIU`+Y -m2,Z$I8`2JP[AGI(X"R+8EmU2AT%kE3'(FiLhkQ`JMJLHlHFZJ2Z&+aGfmHbf'f' -$$kUm&i224baIGcj+A2Q@p6XCZRpdSr9l,E@("p3Im"!2rjcEVSEY34Y[aBHlH@a -McceNr9C"'IIcH"8A+JKA(IQTEKkhN!$M+IkVH3Np1UL"R4**$NNHDpLApcEm)rY -$h,-'m2$kUASGGbKm@hJ!rRNk4p9kiK#p#Fm!(ppUrAC3d)A,U"6@SjrFNkhIIC` -lJ&XTP`hJCj*IeFAA`30q4*m4@r*lN!!jJ,(Uh-bHp[+VANh1iqd3Gd[S0mQ[fN2 -0R-ITpM-!!!d39'0XBA"`E'9cBh*TF(3ZZ6IeFJ#3#!Fhph4)A`#3%4B!!%*P!*! -%rj!%68e3FN0A588"!+rBraHbERkj!*!&!3fp!*!''6N!!%21!*!''hF1q&l+kA@ -CJmc,V[2AlIADK2)hYqGQ$6`jc5YD9%k2kcABGXEfbYE`c&EZ1QL[(cq[K9YXiBY -N)6YqhX*RjAHmLbrR`-@*REFmAcMjaF[cbmk"NFA)BVSS@FjMC,[`4Drc&Ni@RTd -6J3lJa1H9$6JGj&RQ*CmXI$R#"d8'ZqF,f`+`"CJ!122kBZPd`V+XN!"P"@CE!FZ -a!S%YPMAT12KF%JJ'S'UT6VFi+k+C6$bG#6GQdZFjX9cHei`LcE&%Y+dYi@4MQAK -EERjeHcDA6SE2G$CFN!$1Y'5lh+YL-5HE$6G'FfZlICZMQ9BR&fjbFVPiUVAE[6D -HF-)4H23kRpiH6l5%DpER-Y&Zha2RR4PQPbjf8VfZLq,CD$EV*&FRR%b[IhdmYDl -IdfhhVKBiY[USSj!!FE)0&HX1V,f"'+RH1PEA4T!!@CGAhG*`3eXZRSaIf*22NZM -jdA"$HkkY[EX3bR@J5-ThHD6,,4+0065&)`ik%8fDFK*G!4UMf9Jd-9KGFGpHhXE -'kZfY50IK9U4rIb[5Xl'QYXqY[rK`VFSQq`Zme,P`Hh@EeYE(9qp%1"fM"(-k`!M -@k4M$J+FMP&"2"aL#2Xqre(4HN!#qc[2FqrY-qQ8B$JXK"N"$3[3#ShBYSD-1-!5 -4[[p`#I["8[Z1)UD1-J+E(6&fY-%3J(VqB`dp#+@HH`qHqVkP6LNKU`j3JPI9iZY -fiUX%+3'X4"K"@!Nb$,%5SS5a%Q%)C2d!TDEdSr4eTHrIhhTZi``$E8H-!BKaBr4 -#VIL@X&BL$)&Y)F#13[E$V6L2iUf%'3(FBT!!NABBJP`r`+lf(J4Ghlm(G3[1`be -6`Pf*8!*H"0q*ZSa3JPbkMq!Y)`b$,Ie,5%[h)CKe[8Y0k)ESkd$AZEr$9(F-3kX -AB!")9)"H8+9M#9(T2J5RHHqKX[8$+6e(8C3a4L$8Me!Uqa"iZYilQhB30PhR(Xc --H`lf43NYkGi"PC*&@+&AI6cEchXA1D[E@eZG6&M$B&q-fZE'%M&H2qp%B&r-!4D -N8i6C353IbG9PYJ2*L[YiYZb%N939U!rN5Gra*(AYM`rA4e1Yl9'!dBk*f"b&*@' -!LC1*-UQq+#H-M&$QKUYD@Z+-$ZJLp+)fr8fbUb`5D,3Z%QD`-1)rAKQfeDkb--T -S64KMX#"dlUY'Reb-Gj0P6IQ*C8eel6ABQD$8@Z9+Ai`h+2'mj3R6JJ54qHY,rYM -eX-)X$YibU-[`[JZQ@CC93ArD6j9kRLE9A-#SlpP'8lHf9dq+U[3"D(Le$@mjE1T -4jNR5(j2!dFj`SLe1*PZjYUpH2AeN&re95[RDUV6lfX,D'qmqH#IMRB*h+Yj*H#[ -`PZ1GL0I@qDM#k65#36U%3Y6JE3@Q&e'N-VXfXIUPAC*k&90PY+KqmFVBZRJ,'GL -+TXCUeA("2)U-5U(,9#p1)4fZ6T!!E@BV,ibhG38mTkia[+4UHC9d9L&2!J*,`R) -VD$!h3*K43M`dJ)TQQH$Lca[`(NS$'i9b'0ih&KcHK2I)JX2KH'F6KmSdC"&M*q* -9X#Y)k[BN8CTj-MCc0K68&NQqA%q%R#MPdrAd)mcGb6cHJXUUH!1b0pk`KMp3V!i -%,0%2)48HYG#`T3L-,P5HEJ5XJb)V9J&rU`MI63Uq0IQ3!-(9)1Dp#+`GTE0G#2( -`a#YU0eXTi[PNMdUKljBeeP@fCC`emI8$r5bDQj!!UarLPq4N`4C9-EIh)4IiMAk -eB"(PXfiV3ElTBp@p(Li44K51d8BBB4r6YJ$+*,'49HiMYRHVbQVECLK6a(B$&%@ -YBIXLP'PLqbFSqiU0,6pGfi)(3pP2E'q&-N0XEi-b8f`NmrZ,l9)SB,R+pM%S"iM -Y5e!1&0[G8&iRlFRq%6`,%4S2%PXY&1C1'cNVqiZfhb*qLHf2"&*TBpmSD)AYai+ -XE$hfJd*Bf,Ka5B#PV3R+Qm@@%TbPlA)AEf'l%FS4B[X@J9PXpd-j5Y[+f$0(Lqe -%+-H)MAeI+EB,S4`VYSp!B4eSq`+8im9f&j3jBRX8bJQ#LHb6Z@)l4H'lYN@K-&r -DIJ2+5@*MImm6fpHJX'GTBdr-elCbiJ)aLMEQaVaSDiCbUYMDSC`QYJp#)Fl3pZG -3&SVYZe!)aE3p"Z9dEDYJ2eH,M6NX%Y[ESG5)l4)Sl((D2J'&8ahD[JlP$,'aCRA -D0S&iY%4Xl!h&)f"VK&)[0Q*H4'c%el2%pLG3'X6f(5L-5GY2SCbYE41*@8[&a[i -K2Y#f!JVlJMEf"$'@YJp!@5ifjXFiY(dEbNUar4X8iL6KQVK*6+#0Z-"HS)heHSI -BeN%j9fc%dAH+lD039SRYUe!`59+f(d%K$T!!!T!!!mL%C"*a+LBfjYFLY[1J1'* -l,j3eB[X$++eL)dl,M'J518&FE!p"BAa5$1)qDd8EmB2EcE5aGNQaXEq*Ul4G$b8 -Y0Q+5d,Tpf0rX@9)9mTb-f)L2-L#Fc&k50HM*R!Db"fQl$XVjB[X+&()VfKk!)Y4 -Y#ZZd3@c%5Z)`EHbIAa2EEd+j5'bIK,*4E(m*KIN1#5T@&Ue-Bj[L[f8"T+Ua%IJ -9f,35FmrAK2RNMFX#9`3Q"+A1VJ5-!&PfbXJXp*9Tf35p5S*&P9re92rNljGXrm@ -*BFFF&Y6GaPZ'Gfqm%r(ZKEFFE`AHbALRiTf#PfbFk-XT!DF$R!T`'X"%1%8J5R) -+)1aI64Q)r'5jC(9Nq@6hc)2-P+b*l*hXJfK)PNkQ3eE1@K*"LC`X2j'5E*%XNHc -3CCYN3f5&C(*%&aIab6L*pQ5$l&fb2l)qXMfb2,)lXMUb1E)iXMHb0V)eXK)L-KN -#8CNS443QqT*jNA'4DC&KNEQ4QC&KN3f3!&'4fC&4N!#p%8r)V-LSb+6)3XLFb*L -)p'4)C%CN4'4#C%"N2Q3mC)*N)'3HC"c%($)-6KXiCA!(GQ6KR%DimcT1%6M0)$[ -La),-L0-%GeV(U3&C'+F%R!j`+N$@abN!f3eC2pNqQ5ba8pK8e`d%UcDHbA)6VMA -TT(,@I%dhX(S5VNZfT61j-1GTNFB9"I2Td83LR8k&ch!5E9CN49M[NkP!+l!iSpD -XD-9UNS@0Td,Sq4ld2VAZdVGTdV2YBH9L#H`E)'!QQYP3'40l3e09KbeMqI0"CPH -AbMQC0G'B3f-%Ui&+EkS2,fe2BDR03@U9LqVVPBZUKrK9q['iHPFER6dh[QTHba( -D%G%L+b38('3'fC@%GP-4rHjL0I-G*%ET)&VelTHeXVUK0Yp'bXrV+TUjLU#D)3l -kFk[9eKElQ$5(04qqal#`#551ELSk`N%j-L,XZJRT1Drb1!C9q`dS@lHc9&2jD`p -Y%hI2@1cF2Vp#,Y*PfU@cdECRRXm,P8bQFqPH&2%#MKHN0eDi+GfHL6P@diCXcNP -LYdlDM@&dC`b-T#[EBQY4e[`'SpMmr8lYi1m1GUfh&TGC1eGALiZU(@ZTA3Yah[T -EcdCPaaTKBAZeHeI9VeaK$l9ckl4cae4!X@0rY,"ZfEeFkEH$ZcKC@*2X@)VXh6( -Vf5McpmGHf"BcQBUl9F*jMMYciTc"h5VK$-,G+Z%-`GdUi3c'h5VKh-6G+Z&Fa0d -UiDc#hAELr%@f5Y6XaCdV[3q[E*9B[iGAYNUXcq19V4,V0UN2K90[f5UarK'[E*9 -Bpq'9V4+,@`fb94*JA@5V*-!FC+XN`&Q,E*8%1&q5VC)!jc5b94,Jh%Df5J+F-XY -@5H"++,*9%[J`&*P*"MiY[82Ec9"NUb4`1a6C+JQ`IV*9%[J"&0NU#@!2eGdU#A$ -$3EC+JUbIE*8%@8IC+JNbVQb9"$RMNDf5)'GRXP85j-a+YNU#R&A*9NQ3!(dT@b9 -"eP@f5S+FG-Y@5I"@+,*9%Z3NAEC+JY`HNDf5)1XR@bA"ak()9NQ)[5GE*5(@3VC -+3Ub0E*@%L"Qb94,LV%ff5N+FLmP@5BJ6C0NU#E(RC+XNa#d#f5S*h34&YNT#h$+ -5VC,3R9"NUb6%,5#C9SHib5"E*5(LK'b9f-3if5UaL3Zb9@+c$f@Va'B2b&D*c4a -NUm6QV&'f5Qc1$Q@Va1EX6lC+E-lkC+[%j[a4YNTXEKR*9SPp,46C+V%r$N@f5Qa -LS@b9f1a,f5Uali!L@bAfhd#4V4,l(LLb9@,r$)TXPA!Xl'k9'#+%Y@20h$PXedb -AH%L-)bmKGf![%[H)DF3lBL%aKeK'E#-QN!!2N!#MX2F,-f&L"c'!q%$1`riPAf" -2XLq)mqa[BJqaL,K!l#'@%3q)NF3)mJ4hcNfH3!j%AN#F*LFJTT(c%2X,-fMf-RZ -BA)(p5`j!A#GA)Zkife(%5hH'5b'1NKm4FmQ0L,IN6Z36K6NmF9@ial1LeS+4Mj` -&a!k"5rQ8j,Fhe*idqQ`m$[YZQKGRC0qBlYXJBhADNd')ifik8kqi+AAaVGZfA5H -EIX8J4MK4qfmGkrfm(J*q$YbiFYZfacP,-VF*Vp"iqjSD&iiQ,Q#9N!"EjZBfiEj -Y&emi#VK`eECYGh''E@U6iVdVL"(Q,T-"3&DYbZDL'F2$&IX!G[(cjp(qVikQKf* -b)i%E"ZlQ9Zm0+rGL!+GRl[D@+8"qH69"hbj3YF*U"bp&"'4Gb1!Q"!01J0@k&a$ -"+)F(i'TBbr+hmG@'ZA&9HLq['&E%#$FM8"+dbXj+Tq4HhB!%)T&'!`"$j#4#hEH -ANbCp-NhIDGXY2%I&'c4QJ$bU'cERVdCY&p`VBQ&ha+K1C-I1UcbGaj,c-QXUmEj -D9kj-4eC8bfErl[jBfV48VJAXcU1jCQ9cjHVqXpQZG0cF'K#9apTFmYAQChqS2-i -EkFDRqeAPX4-lH50X9(LplcAm)!+I%fq6b`flkpU5MXQ0b0epRmPQj)EQlM`SPH$ -d`bMlG&e9(NpG6h`jMqi,9ehb1[-%diP%kZ8'b*!!G0l%kkpmBrdB`Mb6Kc'!S65 -F[Q3AFKD2qr@*SB,Tl-61MX1%1r)i5QlL[*E(5%&Hb'-(!2pR(U0)rQ`Hc[U4JSb -,CUDlqcA26(G@ShL$XP520Tc)-`6NJ30rreYA(P*amaK'SKIbD0["6NIVQXr$#-$ -F94jC4birriqB*aMhdhq&k,amfLICA,XK)!p+*CVNeEVb1&&K-kC2bXd6c0e3`8b -0!-KT9N#UTkAl5'QAQ$pQ1LMY319IR1N-j@%fQ6Sr2iXCl)kACM&MH6`hLaR,ilP -Cc+imRTh&M1CKATM&$06M&l1BSF+q1)XCcH1j@Fa!'Ur-BXEbH(i@djq)L@!@-a* -$lSh[%"iM(mfeqf$j8f,mQ1N-!Y&,-jd5iTX#CMVjUlcQ'F%pLp(I944q6k&I,K+ -Yr!X$3Qd#rMmVM$&Iq$'$(&RTq%51ZN9JIT0)8eh0028aL44qG9#c[Lf4cVamND) -18b''aA4SC*ICB#C"-(hpe5d$$&(Flr$UKN8eKiF2Ae69A!@eXDkk@@lNQe*NJQ8 -I-23$MQFNrl8aBi$XqM51&U-!H0PGphX$Z,`qVGJAaeI+K`E-+B,bBiqR,S@[Ed3 -6q)0(E5DU[rhb[2aUG+,cEhBbbAJUQ[Y&qUU0c6AM6(f3!#p-f&2Ir(RPUhGl%JM -c+28"3hbc)[mPL'!('Fr6I-3KjCJe(SHXli$a1$aH'Xl(i9IrqZ[$!kE(M1I$JkL -9!eqJq(8r$VRAp2&mq*@,+D0IT8!FI[&Ll%X9L-0[B*`d(SFEHe-0bPqd)&["F6P -Sr#r-"!2G8@,L`Ia@rNdU(M1f!B1,"e"$"VSMeF3$IA'PUEf0Dq,cjA1e*M@8m2& -!mi1)NmZN,h!bkl,KTP`de4,0Y-Jhj$E-jfIcm%pUDZPN-TfDhpLq1K'2KHY5X84 -lLf-'J`dI$qcr`!1`##-C'"6aS%c2NqC(X(2$l`"Q`mGAcUdm`E3f8I$aS-+JFGV -%,,HhES`jFf1+qI1Yqp(V!`GqeHPGcHU"M-,IV%d)[ld0B4DME[S8XUC4[Rr068$ -q,8rrHpCSpJFJ-EakBi&eG,qLr&qL8RreaN*&lkIAc#p(-e4hEjFp#)3,A[P[#C@ -q6@%mPEl2AjY9C!mVjPY#Z$44["&I[+fH2lN!,ei'mQkV$mAK[aEf'ir$S`dcaZ2 -`L[2-m6M2h*a((0kF2f,dPMbmH(2qZ2'mH50ql*Bmi["'r0JYHF3KI4Ul*Drq&M& -q5ajaH1Yq6[j@pN!Gm`kQea[a%rIi(fl%llA([A!MIS*hFE#d2@XmPH,&`4dVEkB -5fF1+Z6M)(ILCh5ZIa@paQ`Gq[[h[8[`9'prq-i)p8[K$@djprJNJZ-KC%dmjf9& -kBa`4!m`IfS``rkJca)JT$JA-1$*$cYIZf5F`TqfbCk,!UE"IL[GNqDMP+HU+['@ -G+Kq42%ff4KDSZr)mpU)cU4,pG0'V*FiLp@F'bkS4[eV*Bl(kdi*PRB'2Q&,Uj11 -L5d3r8q)Y&Ee*p'E4PiPH,h@+L2dXbDp"kYBSG6TEe80rSp5'UI#CdZh#e6Z4dUS --Fc*2G$N,%PVDd0"FF!SYAVT-E5R40V9T3cER*19@DpcKYPT&E9ep$GV*&Ve-p,e -%,aGGa8&(+$Ydecl46c"i)"DG*,X0B4b'$6HY6@"eYcVG`RehP4T#lLdT646GY8m -@IB+I8Q!IT0639"A1TYXcXA`@U(9)G,GJdd5I+Rlf9GFZA"FJXMcjB2P9Pfd5YaR -8bkqkeK,lrU,2XZkqqqk1efe`hHXGd#'IF$A0L(QQ)i`mq'&3i@R'QElhHp9NLj0 -@B$EE1CR0G9iVf2r[q&%$q(AHG3NIcCk(AkVS0`ej@,2K&brk(BTi&C*Ik&l2ldM -ifCYdIJ@rbNqM*[4$IJ@ria#[c%VQe*dC[iZRFDLc#AkF1aAm[X9L*A2CVRJ23TQ -+H+b6llFIIi!c+CP,T)Yqqe+4ZKEUm4Ef`G(*YQbRhdNVd6Ieb9aVCehhCAmFf*C -aePKP%rL$(Xj')3XI44mFTrcXMEcLm(VY9h-NmTLNidhNVcS1dRjRRSL2rYbMr6D -H!SH$TAi(S'cPfQr$!h!i42,Q2CeC1VrE@%bj,EM[19!QkRMRrLYXEa#rmk"-e[% -HrN-fX2Bl#(J3f%[(1r4q1"`QmGC$18AlRI-jf0iSIRrXjE(ahE#p5IZGqP(NFCH -1G`b[+,aCiRfCrDIpCR-N*m[`dlp*80"jE,QF[DMpVN6HGTh%Z`B14dLmak(B%Zp -k!Shim5[3UlAIeLGKNdXK#jRh21ehaqGK3eqVIU+bMrDl(,eP(50eBMhfdhQI`VT -@5RlX,Ge2pKFq"GZafQr"a9"Zer&D2d)JdhkVdHF"kF[h%T11ehkaZ9"Zd2&QmIG -#Fb5rUr*p8$E[2YK1d(jaB%03qQE10q$!q*!!((SPMjFq5C["Sb-ZA[Tq-jH`'33 -[#hkAqRMTqqhl)i@,'Lm,m6lKiGaK934+lEF"pCLm5GIlcqJ!(+0Fqb82jaC%#+$ -DlhG45aIRbRQMLKm6Chpmcm1j-lm+"hj@R(NM$aIRV[NGf14Bq(6q%PrkmZU(B6Y -CiRhA`kF(ELH'DEm%IV6NiP`VHq48LII2HCbc(eS+ffR#NhKr3qG4GNJ0'ell*G' -l,XiGr'hfPX6Mp4eGEr[qRm2'(U%Im8j`lJPZ(-JG,1G22Ca,I4%1FRPN1RQ#aVQ -bi&r"*RHU$L(HDC`VUb+RB8fBhiFpR,[r*l$*2CMpPq9aVQcZ"f&E,(iAH6LArQ[ -BcK$m)(m3hV#F[9HRr9UfjR(1rKalRRJ#53'V"1I+cQ'Gj"VHqrM6*m'jeHq%6Hk -3!"h#AK5F+rppf)J*M(G,(ZIXcF6@Xl6I66Il11GrffNKqmI&1Gr[B1"(RKIkIQf -dZ6MRqbQkG,6JA#(Hp$c1fCrP&q-EY0mYU)IJA0PbrU*+PJkq!V`@R,0rb0c2eRj -I"eki1"Fp(`l%&XLPYq9ac[i1b8L6j%dH)MMhCI)cfFcBr`S2jcE6Khh0IRV)`kF -31GYblAFCHYV&ZAUHdPQKr6D60`ZIHpIlB31I96K%A*FmPP`*fpZdhjBEmMKRhdc -q4ej*2flM#+krp4lBhLlp4hiQrAd4qqBG8PIJNH#FrI&9F$KAH!B[K`[19A$Z4+a -JIV-m2[FCBKYMXYkE2CblILCXFQajjSFm2[F2c%h1)@mK(p)iChqIh%2Zk@cjE3r -RbXL2jDE2jCGiI#j`,B&2qef"qVPmlK[-3BiaELA[e6KRIrq(X-NPp+hNDS,h(q) -'NpcEh2UBKh0r5kiLCh%Hq3cb@pKBRmeCpL1F6mLFC3Ea[M'ClH*R-c"Ab2[jZ$@ -GJ$B9m`cb%(r1F3qfRB)9+QrV8k`Cj`#3!(Z"dk%jfZmka,$NZ[b9l%10IpB0ej% -iDErl`'IF2+iQRXPPUKq$*lKjh)*CJLAcS`H*!C,(9[*TiLcpd&YZ(US[j@VC3mM -9c@-pq40M3Kkqdm[MlmR9C*kej31UhVL*jp9DaIXA+0p,4V[Z&[lX#E5&QXHmCp[ -2,i1$A0rkk4h%@TeIJM-)qDEm)j`0A+2pPY`)Qpc(HK3i(CLUrGj2IXpHJ$`'2UR -cXka,L*FAD,r(f5H5hb6dZX@j#[h)Db@rGH!@eJEYp`6`hFe[lar!3Bk*23RFFI0 -Ep$8iX,mJfiK9NYqGR(q3!0r4MhdJqGe)6Vj4Z3@SZrPP1%rL(-2kI`!!$3j8Bfa --D@*bBA*TCA-ZZA3(0r9b!*!)"cIhG)rF!*!3+,`!!([+!*!%rj!%68e3FN0A588 -"!+qqEj+bElZd!*!&!NT8!*!'128!!#Hf!*!'dPd'q)ZeF"X)Me#qb,Djk-)A[Li -mb@CGAT5lr9`BBG[)`Qj6lYP(,bAdZXeZHE)F&mr@NhQb@bI,kP%HlBSXXReNRf3 -jRr#&lL2lA)jIPr(,4C2`KC0pV#2l[&`'I0&EMLaNGi6AXHAj`PU14rLLNH9iZQK -TC%pFq'*2XF)VeHUDq6Ze@!5!E,+3!0pNNadC,@5`N!$EV3YClA23p6EXl,aSPf1 -EfGY)ZclDfmQG0HJm-hZhjb#rJI[LqCf$aFY,FcPGH'CqRJdb2kqccXp*[,0hmHb -XmcX[MbbHbdQ@LAPN)C[F3QB,"m!##,M9Ep$PGq,Ca)VYmp`@Lr",XMqbG6-#`"E -m!HI8UpaXeS)JQ"F%i4P"iB*D82LTp`6"Mhi5Qbq'KC!!Tr[90L[aKUMGVMEEa9+ -lZ68ZTaeE5mSAcfXKmVI)l`A"Lpm5"#I0kZp5$DP[Hq!Fh@h[Ck1+CBlLhr@hliZ -5Jp)H!KPAq5L*qTZ6caAkE*Fkpb([jH&dH'cKXRejF58C6S6"c-bXi6-cS6j8rGf -6lpeA"F&2cqKA*Nj`l0($c8C8EMkAUe4`4R"FH&GKCqIGR%`Rq(LiYl"JhMR"1D6 -Ki5"iH$MirlPj*$KZI@PeIkXGEkP129mA6TE0l+F+Rj4&JMGPLI9I+YPqI*k'A#Z -TANPH@QK,e35-0R#L#kX3KkfMTlaDEe)M9SF1NUrkU&@RAf-k%kj9C""jVZ@X)I2 -K*['X`P'&&I01k6DKK0@m*0*)rF#R9rkGc,KmH--PkmUe9A&8LGZPdX#ccE[`*9e -j[0S4cVSN5D2XXEQA`r3APRr@aDr+2ql,[q5(j@-0qGaT,YF,prYc++TGAcJmq81 -5,N$6[Xb3!'5Q*('cS$[ij*,M"1h`MX,TKDrN,AG6UrbKSHVQGY6H[Y5f'4A$eD3 -Fc"QZV$C'"iS$cAUV@S[Eqd`[Ah)"KZI'Jh(M5EZ&eFDfTpfCT8PJ0kG56C[lAFe -Y0[ElD)b5FP3lN!!'X99lQ3h9aRLbchCqG'RdE0!Qhh1QdRDdhfIYC*)fkm@,iqe -[D,BVqfeVbZ8i5BUP+*hBEjLCV0BUcd46YH6LCiX%ZlTU%L9*A0rm4%SahP&"Q,8 -NXrDFJE211P!FVQPVEG5Z(#DJI&8dUY5ENi9GHl)`hT%Xc"TAV(c+TU8D'`H@*hA -+DN0FffHi*0ja)+r,S[CiR"E(iM4p-V&cm9Ba(,9DQ@A9NQd(ZPaJ@1KbJ@R3jBT -fN[DLQ8PaB#GG,M$4A5kARN+Aff'EVH6!0YIP@[)YI5N`,ADj`$EAj3,$A*F,$)- -Z9l6,0BkLmBi+#VTF,Q2j,YGXfPSEdZ9b9H&hZD*GHl,m,PFdSmXefE48Bp$P!X0 -FP`X-LedZecebABlqThBK5bF`EalQXTBlTVQXEA'FbaRk$6jR&h4c,riGdeV41$H -5C)hp@6"VNad'XaC08ee6j[e",'[E-YGPMCX'ZkaPdf5AY5b1GMR$TR%TCpe56XA -TcNYFmhKAX'dV*Rr!m`UN-1(P$-1F&@DmR*dCm[*'VG9C(21bPNecAYDbCG$c@N1 -Z"jVLeeB,UmRq'E0qY$M55U[ekSl(4dRG64C2TLefr%ef+iEhf64%jC'aiR"-6PV -5f"4M[QAj3HB0*FUX8A1B3HI24GNd"dU3!%ef+XE!TLA%"Ir4,(2'KIR3Yf`H@(c -MiPcZQaB'5pmb2eN@$![6@X%k1ki9l,cC,%KiFETXX[A(bm$@c*Hq6D&!IFYmK4B -0@a2M&Dp[Y,pkQaF*cFCYkFc2aJA$X0abdh("cKf2LdBYU5i-b,jPB8,f,CXf0lj -YIR96-'a*9c$4+U-TrB[lNiRD8pd`X-de`m#`f!X$fh`V$#acR6!`$"TKd5jAQ%9 -M5A64V$A2q5EBE*TY'MP6Y`8'*VN1'"J'$E$*VL8PT[d&0XhG,l!Z0VmGYUeT$&T -IdDkp`2c'9c5MlcACl-K`VZX&KVQQ&aJ@HPjJ'V5mSYf12"8DAY[XecEhYFpm1qH -pYPQ[GFi,Clb@qDjeYYXeeqfDkBVcA0XXecV(YFe`6I2ElYQYI@jVRpPDjl9`9QZ -CdjTQY0EjV'df#rFfCVe3&fqH("q2fdAA(A+fFpH9RPlediVQ6*9MLQeM3dfQZ2B -SKK6BHL%9Gr&0)H8@,5eTm[TA,Nqj)A&(S[`aXMP6[R'3!+V#k0QD+j2-FF@KU$% -q'G%e@P%2il-q8%%M@0Z1&%61HX)"$-M%i[)++eIP6A8AqTb+29G#,9%(pXe4"pC -qe)&CDp5j'YZ9l+b$YQaRc3[TcYVYc,GIKfd*pafdC0`hckAFYfZ0h!,j2BRm#[+ -Vb+H3!+13!+14P8L&%ibm!MN514Bj$MNH14`*-m,*b'R)3FLr3Uj"RSXFLPb,2!m -j'$N%13%j%6N*@B@FM*b#""(C(cN9@Bdm#9Q"I!`j!$N3q3hN0j&rKral*%`0kj% -EN!#J@5p!ASMFK,`BZ4Pj2[,cb0FK[i#Ne3,@[34j+I)b*($VEFMA)m(Tr`(b#Z3 -EN9FL!EqZ3ek09"`(N8mKhibm"[N%mUq4Ad*q'3QLZacC&GN0f3RC'GNGf32C%eQ -'r#35!'drC!,j+H3Cb$14DH4VN!#[4B,e6#&l)AXMqb!K@6JHf4GTX1JR)%p%'T! -!p+H4-$!!P[iDmQq3!(q,r$Tb2R)"FL'b!AN+XKkj#,NBfBJ%V[eC*&MUdj!!GFM -2)Fp#RSfFJeb02!GCJm`J6d8Z35j&,N-Z4kj!cN914kj%VN,13-j%2SkFKB3eiA6 -N@j&rK(`EmZh)kj!!Ed(q-I)Gb"Z3!0FLra$j6Z50b$p"+SD1b(Z40b(r$(Nc%Jc -Y,FMh)'p&[KGj'r*kj1h)1j!!ld2HLE`2qAlNrFJ2),FMld8qJ(`3q4$b,Z3pb!m -L&@BfFM2b3mJ2)ap&IJ6jjmLr3(i8q6(Naj&rLI`%mZl$h9G9r!&ZLIhI,,kD8SQ -DGRCZI"+ZrHYiXXTQ$JYDM48JbYcR!IY0K0D"!1dXRrf"Rd#A-41-RHBV#HBGcf* -S0$[9bPT9Xe664ar1p@+,3YAk84Yf!6kiNI)d(hbDhN1)E4B`BATX"9P'!NHZSmJ -BXJ5C3+D43j!!TFM"b*l)l[YTB,a3)L(@E"8)9)q$lj6E%XZ1Q3IeB2dLYiSE!9' -fNSU!"0MT-rJ1Fd'm6*5MG`AP!K,8eV68hp+rSkTY4qilIA@TZ'Ejkc@9ac-f%&1 -p,N@,i9A*4R9`bMUF@,pL24)+3eQK!dile)-#6[bk1@@RA@++Ac3dZ,'mV9S49Q( -P'2`[B8VGr-I*C0$6GReXFI`+f2QCM[(6`YK4+Rk*Cq[QF*8A8X0kUC0f2lTCjJ, -8kk69ci4MQrP-F5(,Kq1dhAa$h0k@&$-)cp,64SYRKSYhh4!ZhV*Xr8KaG09%F(T -a6+r-SP-[$-+e,(m'h0ehkTTJ[,KH#lAphfM0*&hUD8Y,aPb,Q-(U+IV5HMV1UM1 -fGmjb&N[)k0Re9S,2['A0ec3R03k"HSlZeHU29DVq-Srb'2C-6Z1Iah,Ee6Z$lBp -SUSU%CehA&pkq9J[BcfYULK3qI'f`r3YIlJ6*bR1+Xha5UlYXPZQXN3A1mJBY09N -QkZmUHSjcRl1m8#XqeS@Z6dDeRXjbQaCS,"(e0eZVZ9*RZ9AV0eD,VLA,Ymmjbkp -S8FV#8Ap[BVhTR1JXTfTeb"T5Ifr@i[,McR+ePRXX*pfDB4@Xjm0)i@50ND`UpAF -05pDSjI0*,4&CB1V[1Ufcch'@Rp4DPc@TDkN@P-FGl5bRDd&)KHM[0ZAMmRUD'-Q -Jppe1bhFHS!Fd@GCS(6QfRYDdiXjEXX`eI50RUGIT8MIId'UAeE,lXEJIj#blD!R -+`YRpU!E*fSeDql1#GMpmh'"9b'+CHSY5fB`UlTKRHIPk,KSBZ@M&SZ+LLjD[@mk -cFIA!1QdT,#UI0BB*,'hE2)9`flA0krMX!pZqClIi&S*[0i1CTD*,-+!T&&-DY!Y -J(DeAZ)prE4hp`&Il`0Fii"*!mLJ)L3eKFH95ZfP2TP31li*8+qj!NJ4)%9H#`&N -P**IYi!XfbQBck4Sb40SQf$PPSfF0B(aYaJdaP)-c!hF@B)pB5l#!!+I%+JEm'Z- -f1$I`DH$1k+kX)9KRJ'd#e`5Q#D`5Z3,ra+U#IJ#Q#``8q#c`91#j'2["Fl%bB$8 -"$JVX(0JZPM)X2eMMJ+8#8d@(!'m&9JiF&ZXU&KNX&F$%XFaK23l1La)!'dCGJ!P -J08'r!U-(GJj-(GJmF(KJkeKUJ-d$5mED"r`HNa2,"mC+Jp0M,3+1N!!2E"ki0E" -Ei,*BN!#!Vf*""1i3l"Bi-R"Ze$'B16#*,*0B9,(1B&N$2K$F'2JhX'+XUX#J8EN -X3`c@$!`D',-!G`Ifcf$Z`2#"A@64"PD4Y4Pi4A#4B#)0pT'G!)XCF*-'6fP`PQ! -X@ES%q%V`H@!$'3V!")+LB99'Kf2*#kk3!*(&B1h!"`EB3jCP!Hi3$1%Zr#Ai6B1 -p"1m'MJ,-RX(UdEI"j)(RI+@EfS'JA2D3!'r"B3C8jT,SBIXi([EB,mcSDm12QHJ -L$5T+[Ri1)&%!V0J%jMpE&1`L`e"ELkb$*rQChJZb*DGfKMaB0L6I+cjImI[EH&r -eqe)FrU$#acE#S,qBkJd)K-f"391cqG#!528aNl"4i'1$SpH0kQ0lC$#k)0EC0[$ -"Y'$fDB"rf$S32Qqp,&8kYKTX)Y!a$3RZdY''K@d%1MBqJU9c&,IHTbSG@aXf&1K -J4'"6J3jf"cB@k(l#Jmd&U5ChE$R3XA&KXi11lB8q28(Tf#*4&qMB','Y3FIQLBd -01MCEE'l3XC9MJi-1"JIL3JFN5U"68G8G@ae+M(MBmU"M5m1Q"adE26Bqk0KQXIP -"ar6)"JJG'b8f3HMBZJP+*+EFbm3D%m-&'b*drm@$64(P6)fa-8*($'b1d,'CBB1 -%MXdG@b4da-e@#4hE-$C,k0LBX@&#"d#,(+,MDJHf3qKqD2f%eN%IB9Z%MVbc08, -(eSMY%6Vk$ATdE1$B*+&M8mG'#4fE41S8(4Y3YN[SU$Qf61LS1EC0Y#RkQQb,%kT -E2@NV(6PLXiQ1Z0PXSQ26+-cr#@dkfA#LBl2(4K)Gfe@fP1KJ"@&$LHjT(Q`"d9( -Ve$,YN6l#&K%GF3X)1+QiNHMBAV+04-H'Nqd#1VDZ-S8Q"@S6)&a5,"`#I8Xqa%2 -!EVVp#V`YT4iNJ,D8kNdJE#R&,k#eP1T-B'STp6B"TU@dr48S@NUX&!)q5iR94@" -J+H9EJ&qTEr)3U&GDrCGY-cTk%aYKG032ffCdf0$Id,%*&Ta,@YY"CJede"Rj33I -,Kf`0drIcN!!YEPUpMHdf)`Cc!KYSG23eDKNGY8TpS5-fYX2Sb$FEBA6NQqdi1VE -VE*V4`@3M0`k8UXjNpk*('1B4G-`!E)(4dEq%L+P-Y5eERc,PLbdd1ME@E+24XB9 -R)ik1MDN!bm[%T-0@(pfrmf"VVlj1QV9N*p4*X`6EIh6d1rSN1QUEh+)Mem5,MQf -cX'eddVDIV6XkQ%ES1HJ!!i)132HI22#T[XkDrCJld0&Ak)hSk-ZJ$0$4GpKdSk0 -Qf(LMime'("hEGZB)G$#EX29(aia)lD2l%3rQ1r9edD`'@J!GFi-'PLSGI4md!6V -k)fJ(G05r4ZmV(EPQiik11Q0,M`k%!h-%1KKhQ1238Grd!I@9D`E'*cVQ"[Sr1ZU -ERSb1Z%&1S+1[J*C!4he5AqL)RlNB(A'$QN!(q`qc'cTepBK')D!$A-YXTEkZkQH -J%Y!ae`Rl5eI91LJ&G24ZN!!+k1KCS"238EFJ3Y#44j!!)HM!*B%333H6%6d@hAG -iN!!IG!VkUlIhkZZQq4c8#6Vk((-Z1ZBpqL3kjKpQ-A6-!#lf+A+#mJ'V$6Tk!(- -%1R)0b`dkpJ6-0HLB,HK&k1KjX0qJqamHp!VeG9G0i"-GXc'X11MS3mbrk*L4Q%R -4dGm"Qk+Ma`NqUEYU$*BTG0M$%)81GLJBLp$p0`rBLY6A3c-0-`JkCQRQ2R6dH1S -)(I-'GBf1hJ1V%cVb$G3C(A(5Fp"4pmbYk+KlHVlkHQS(!BX@1[S0-`JkqMSeJSj -C"9Jf1RSPc%cSU&9Q3h6%3$p(ada-EYAA5d-Lq`&dl!MS[HLBAGQCS'01BjDh&Aa -fN!#c18TBB2RFTbdZP2R#3lD@Jbr!b(Pm(AlpU@@$TJhe#6bYUjp2@fTV+3#&TT1 -PUZhYXpH`UZdk)+KeDl(i-"Ja0hXI4Z,rKRmXQ'iDfh%jip4H&eH+MSKXLmEr#YB -6NBahH*h6066EX8M@YjbGNA#[6SX[afj6-%GK9YNU6`4TZBErQPUY@Hi[QlCf)QT -dP(-DPhCdG@Y(1lUj!r9+VP5KCTAeM64Z6lE5VX'kA$PRUUYFe%bV@lChe)VDHPf -HKL9adTaXPr2!PME,fcV+CG9kEVQm8Ch+P9ZVYBjbB605QME(ir&8beR9*0XE&Q8 -Q5QB$cP3E9*LVUpd@j394LdE#9LQ[@G94e3pe9!drDbTGR*)AP(1Q@QfRVBY5XmY -@e*a,iiE9`TbTZ$`jkm!V,HTU865Ek(QaH6XP5LC-SflCf$LEY[T'*CiDfEae9U[ -+8&*H2c,lpSUMIU36*QXMSpQ5GL+3!0V4KE611J,Cf'*4"G@EGGSBY42,9q1fF90 -XMT1iIHQXfHECdQTX*Y@TXG3U4#N81ABf%!TF,,fNVBKNXTlZGTkk@f@P@3iZUY) -9UB,DCN[CS'L-DQR,Y6pdPp4)cPB96VBlLUiZ6VDPcGE`Z),,'VYh##L,,@Ql8Bk -5Z&aAiRfkmTCqV2hV3d1+[9FUDP'cS8))b-FMY)Q0lG4G*U)Y+XTL%Kp5T("d$p5 -mrXVH$9YabDa[TNfkZCLX`i(d5,aAdZY-rh0GH[e3p*VP2dXc+3(TFUTC1lDk10! -[8e+cP*kaUU296H@mU"a,f8!eD4HmPN`fZ)9JEHDPBB0T89E2"8TUkqYCXT9*j(A -UXaXEP-j&QNdUh1N&@#UPA$D!9Kd6%(&R"N3f$SbXA$NAJcT3)&$VF!hKMKmZK)d -0T3hle#CJ88V!D2fJ8"08GM[F-$E8V3qdq4Val1Z'KM+Y9)-a@CT@"MUZLl@c"[E -hMB`3@p,*c9PrfPCm21$6-S0#c'SJ8JfLi-NcbRX,k1G0EYhV&Y`-"b@%,bm3E8, -VmNe-+S1UGk0TbV!%+FPC2*D&)fh%YDdiircU*8XUChDMFJf$'T'8N8k6,r(ZTM5 -SeVR9GU)6*-k[-fa&PMViIQ[+#a&9M'@Geq[aIS[2C@aZ0*HcVG[fG9Qr6Mif9j! -!ZP@e&*,R3MHH(H@AV9aQ@CP6eBKbAPBHUQ%8d3#ZJAm@4I'+Lrca&S@E,I+R@Z3 -ZY#JHXe!iU+*`4i9hh8,ZF)VJ6)QQkb6m,*TE*))6*(+A4a3233RZ1fQk6m@rm53 -EMI3X999X(Ll+aY@@Q`qDccc`,cZ`%4jcX(9d[((-kUb,''3rZd%3qBE2(d5Ri39 -L"`a#2rAIr,00h`%'h9`m+KeJB$dqCK5'E8$c-5X23c+#CQX-5@"l#EKePq0&Xe* -`SS%"hXIHXj6HY-IqEI5Yd0j549!FI2P0AGZhE-A'G4RFB&mFh[S[plANp*8ih!m -iVml(jU"C2ZQKCF'mbYjJiH#Q`TkC6iISR4-KP[$)FlGG1F[c84(XZ+`[Q0IA@E" -Jqc,FXMcEDM9Z',#09T0rfa'@bma2S1(02!dEJDPi805'+3H@%c1l`ZKKQ(,-(4j -mS0)0lJViS@(+J@("6&N-`F+8SpN%K#P(SrH&+8HMh`e##,5j-19SG,GKRIm"8TK -b)Q,"-8`jj-X`j@"[Q(*JGa#Q(%G--F+8i`L*,N`jMTJmK#R(%91*-19SYKjKbR( -%h#&-1BlQ-'(+FF45)8`jMYJLK#R(%@Z$-18ibVGd8%FX"X+8iiJe3*Kb(#(cK5R -(%G*GQ()FSGQ&+FF43iN`j6L2m"#Q(1Fa(M)p4P@6`T369Fd)8dj8H45QR+Mm#P0 -1928Y6$P4)E5%+5FUYKGKbSQ+D8@BFU*#dJY66P3X*-+8%pA'3jKbSQ,L%+DFU0J -aK#P(-``*8dj8M!A#P"-9Di-`j86&RL"-19'a'mJJ%&90#&019+KqBFV4M%6#P"2 -p1JpKbY'Y6$$M-I8JBFU*U8F)8dj-G5K-16(P9'DPQ')6TTbB@!5%+5FQ4K"KbSQ -*m8@BFQ,U"m+8%a-VJc$Pa,6m%DDFQ*JeK#NR*YB*BFU*UFm*8dj-Y5j-1E&ri#& -6D%`X8m+8%eGp#e01A,N8TTbiHT-`jF69#i3T*kkk%UDFZ()N6$Pa-H-)8djF[8f -BFZ,+T6$Pa-@d)N`jFE'C#&01A1`K`T36&aZ%-1A%aC3K6$PaeDi`jF6&"#&-1A% -aFmMN'[p((X)Q%"FlK6$PD(BPBFSTd9`K6$NPQJH%+DG%r95BFNV8Tf5Z,P(Y#P0 -1LHT0Q(*+P%GKbLQ4Af(++4',M6$PP)KP4*Kb5M5[#&01L4K2C2G5)TB3BFST%G1 -'M+iPBUb3!#ehbAdmK-@K4(eDQ(*+a+)N6$N*p@CKbNQS[`X%-U&q*a$ZK1TCQ() -5UKpKbNNS6Q(+5DK'K5NRSGfL-18Na+iL6$N*c9A#P*03Ma'QR-6RH!K66N+-4m+ -8Ne4I%DDFT'B5BFV4E%r#P*08Ea@QR+6kPc$P*09hK#NRU9S9TTbNDN#BFT,+K6$ -P*$8R#9018Q`I`T56&11*-18Na6!L6$P*eCB`j56&V#0-1FPrib&-15R0Im+8Np, -F)d`j+G@C-1@N0-m)8dj+mi!`jD686i8T*kAH*%`j+I8#BFT*UDk%+5HPh!P66NU -qK#NR*BBDBFT*LIP&Q(*5ADDFP(U'-1@N2XY$Q(*5$r-3TTc8[r)3TTbdHVm`jD6 -9#i8T*khH,d`jDI9qBFT*Dqi5TTbdFLa-1@RP@*KbdZVG`T569Ym8TTbdqTd`jD6 -9Ai3T*khD%kDFY2)P6$PTq4@Q(+[&"dYUlR0Q"h1VcfH*Z+E',RGkJq`PSk!%"AU -r,UU"Y*[EMK`%mUFI2Fd-mErkG1KZr-[LGKeJrGE[Kqpp!IQ44d&rFdjkj%2jV+Y -I3%0JDIRXFD4(0Y46b3TV@li%,!@+Vm,Z8T`fK0YEc"PAhHGBXi3PSLNA&SEXH*r -U$kc'PKFkR'(jI'LXRHZ(9V,LS"qRk`I8ij,F6ki$"Aj!4+lbmB#+210J2%&q3+Z -GkH-'qEMjN!!I[bj!3QleIN$([2'J(d%-D6mJ%&IkH&Jj[b2hdhBVQ2)$H[*LPBd -kjZ#C3r&BF*J5h#[*)USh,[AJBSm5*%HcUF2K)XHS'5YCLLa$GN*f3CBMZb+l)EX -MHb"l)RXKHb2l))p$(SrXLc`"H5+b(j*VqNp#9L!()!FL6dB13Jj'$N%143j$$NH -13)j%MN+14PBLab$()XFKab-R)#FL*b'VN!#6N913!&14eFKTb1R)'FLCb&R)fFJ -DC!CCLka$cN-Z3#j%0Y"kD$pcN!$eb2R)"FJS8Y%*kr1m5T!!A&H3!%5QN!"TC#Q -b$0N*f4PCMZb+l)EXMZb"l)RXKHb0l)-m$RNmXLrb"15*b(l)rXL6N!!9b!()JFL -6NB13!)143j!!3j($N!$$N513!#14Sj!!Sj'9b$()XFKab2()#FL*b%R)+Z4Nj"6 -N9'3eFKTb1R)'FLCb&R)fXJETRIhKUkac'"Sl,+GfPQM1c[,Ciq!PlXk8[56[e#h -0hrhBc-ae3UER2N-6BhRl$Kr&fIETrC0&i-Sd6$9m`,G3kXJPYfap&f`59pKY'TD -fMe9`X5pF3&qSRCQjbaJi,'hI)X2r"(eK`beETf#Ek[m$EN$,f2GkKJA$HQIk`K[ -F[2#%-I"BfEjdF03*6p'TrqpR(lLYj[NE0kd#3"pc"Bm0K(A&h)ZqLeXD*+Hj0a% -q3(22H[(1pH+GL5fhUVIFb`JPPER[rCIh-TUlj)0l'AIGYQMZ@S46XAM6)TXeFlm -k)&Zi%)8$dEE`c9dpY%+!3RN2Y[F3H`qepc"l$lIh#(Z2Y2FSHiqfGk@papKlV,h -(fAZm[5IBHk+p*pQlbYk6l6h&hP2YA@h[DICH1$LkI[ENhrK,$YdPSRU+q*YZlaR -fRQR[@IDHEHmDHfIXA@[["IDZkmDG1[(J84@UeH&1p6RcMRAGTR888[ES#Y8Dm3% -)f2G41KplIBb&a+$X5qbGk2ST@l$[@![*Yh+LkeS&VZY9kBeGGh[h02[,l+hVAle -ehDVhTIBHdaPRh+YDFeKXZEhDK[DeF[cCAmJLAKh+pAH8"X3+3)9QXk%"X@IFlQ@ -A`jG,Gp"G`3UeDE-)I*CB@NVrY#!lbfH2i`e`cdf$ALPh-YV1ceaiSElGm(%V38a -UmE!0H6Pb("+-hhVN"Z4'j#ENaFM0b#h)VFK,N!"e5&!(Fj(cN!#R)1Z4mj%,N!! -,N3h)4FM&b%ENUFJPb+A)CFMPb"A)PFK9b013!+FMcd#HLA`0mVA)Xj!!Cb0A)mp -"VN'HLeb,2!pj2[)#j$VNkj!!&b+jjRNmFJ*b)R)5XJSj'6N&149CMCb'R)kFLCb -&R)fX3@D3!&&N$$N'14Cj+A))FL5r6HjqEECVllEGr#ef#FTl$#GlUcAHpaUHqME -V'JrEqa&lImMH(lEhlABKbKf'chqIfGeTllXXhZfQ[p[L[FIL[pIL[FrLIlqpllF -,9MjJIKm`[`rDe5S2@EbZYBhLeL#b'mebaTNFd(-k5jH1Zl2hV'e$0fe"FfHb4pI -pB(h8ZkdA&2T"R&R"@HS@mNXR@cVQVYTZCV5T03M6$a6BK$Xj9$r`lSKDQND05Y5 -Zc%*mUl2cqI4,GBhUdZ6Q'ZG8eMI+YFP+h$1XCjKqS2B(*IrC$p4PQ$DcHF(["mR -[c3H+['"pXcGC@r$l3HUlrD$j2%M,@&I`qd(Dl4HTpY9TllB9Spm25PdrU1j`fP5 -mU[rmr[0kVA8'[aq8'6i&l!hi&*NAMUNAm#QfZAf#I3k2)22L)IbDMD`Cj2Z"BVk -cc1%48YRq1HEiil,m#0Df[K"mXQp-pTc$)mMmD*($)b4keI&Pj2T"PX(HRYB4r(l -!C6Yf1Ei-Q4GrL8qaN9(Ur!D[C%IM9dVe`1I,f2H"BeVG[k0UemIEDll69jH+DjD -rIVPNHAIkRKpG'KA(6KXYRKNZhR9$Z(M,X[8MaG&9%m(Ta6'p-SY1[6!)eh+Iqi# -lqdjG%i`AerrJZLYed8aMP*5MQZjNh1PMfBU0krTECEY3[cf1fR-'cMVVU6"DF[T -+(1l(cEdk(jZ$C[QNKjB&mbTlJi@$Q`TlCMiGSRG1C-[TA9Qbl8SlMce@$(CFeKI --kqXF"BRYbmFpP'HEMmB0!k16ME4DImUrY3LYjal%SdiFhAqRV,+#*c[TrG!P8Yi -2I0TTl`I1S&,["rlZ-Zq(fDQ6p`0LY,2h!cpi&qm(VZpbliICVk[h!`pk0qq(QdK -kH$rF6G,6qq&fJPlH$rHAp2CqZ0'NMrI$(5I(H6rFHR+mpm-p+(fp(fj'1F(liDk -8%ldIENrTjre`RdTrl`H@rC1m(qjFUI"qZ)9PJ2I$[5`$[4pZDMRCqq(ZPN(H$j2 -RB1q(qef'H$rFq$,8qq%1Q'(H$lI#$2GqZ#GQK2I$c6%M[4rZNKRPrA#lc'M[KrY -Q+VdIEU!Cire`*meBliGEDXCj2paE-plli5DE#Gi2GpY-p(kil@D5pm2p0eAH$cI -L62CqZ#0RL[I$V6P6[4rZdDRfIVKCCjVh`edldldIEYqCiIe`(mp-liI&d#c[KcY -lCRXrh1*6Fq4HE'A&[6iC(`mhrG4k2pcp8qIpF"[3(1q(qi(QHMrF'$62qf&[H)V -h`ke#pGl22*l[1Z6(9h"3q%hHMcT42[*4lkH"CrFMIVb%C6(JHlpM'!3rpVKEDQ` -iAbmEjHeap`FGDd&-6KD+TXNPG1Uj#pQG46)T2dT%KMYq4,($$mKZ$`%HqJ(Cl5( -!3cpjC(IS"f5hKa32rB$XpK$JS4q3!0dH!McdNdGfKhj!GRY)mG!2b'i2!4lk!GR -Y)F"$2ebmk5(!3cmJZcd%H1J(C,H(!!rpJ1cf%1#K(j!!h4i#22564hE([Z8RMq` -1rH54hD'I2,)lp*0(GSGqmXMZd%mHf4hkb51l3cpjC(IS*irX$[hNNGfKRcbb1r5 -64hD(I[,)lY"2(YNGqXNMZd-rH@4hk#H2l!lpj*(GSCmmXM[dNdGfKhlbb1l36al -C(IS"fHdKYN-r),Xp"(MS*irX$[hNNGfKRcbb1r564hD(IN"fHiMYd!r)EJm"([V -*)lY$2hPNGqJRMq`1rB$XpT!!f+%IN!$G(J)mp!1bfd1!Khlbb1l36alC(IV*)lY -$2hPNGqJRMqb1ImX2b'i2`4ck!GRY)F"$2b#l234ik!GNYiF!$rf!l2B3i+'I2,) -lp!1bfd1+Khj!GRX)m0!2PqVZ3RCR2q@RRZFZC(IJCcl2AFMZ`!p)m9h)lUE['"! -"f@d,L-+lDb24HqkZ$GB*e[Zl0UaeGk!Hdf$FY@&!Q5jM5JkMUC3f'ZBKqda&@(R -kKi@L+1`e2Ff'q`RIfT!!`G(e*6-TRFqUHAdcED+,VP`pY!+@XK*l*lTqbKC`!dd -@bi4MF6*BEl@E''PkBpIGhMh0rM*l$l(h@(YIDQpBCQE2Imr@,`CAA68c+j2[[QT -k6Tq6jffj1d[0GqqrreNC$Bl2lkT4ZG[`p&deICHA5VTmi-Kh0V+QeDVe"SLMBAK -)[#0l2e@'&D[V3TH&jr%dP)C@pJL)Bq@!H%XX!(PG-MCk--,$FHJVHmkC#-T*XMJ -)(hYVX'"0fR'3!,Sadf@L@UhCE(!dqd@G#iqF+kr1G-lBRQQpG4aVRSqhiqSI,ik -4iR#b!X5a,b'rL'2IB8X[a,%hN!"$FDbGDJ@lEp[Tk[@$$dc-2,SXP,lRIA!ZE,X -T')eh"$r"E*)DV'3eqY3RqV"r10apqkE`LKH*YmQ0BqqY4mrQ!i)q(FHqmRMKqU6 -9QS5X!((mpSSPpmYHRk6Lf01*AVKLUD-qU0LpRijM5c$aA*p@DDK*kN(@U)eTX8q -['KKjBBl"apc[6$,R0XZ64q,Sq*Jr0LIYld`02ipMbd4Yma%rM5Z1C&A&XA@b4d! -FI*88bDYjC9FJ%hI9NSYlPNcF+V0Y2PkFZ--iV!%6pq,AVE%VXm*2RBae)"q@MmQ -p2DX[6Zi(iRKZFMm3ah16ql0ar(abliLMBh,RNmRGHG[#66d!*[HGqAKjFJm6HhK -bliMMZFPpCaJ[6HiGF9J%*[HeirpEppD2LEYUbEB$2PkFZ0[Mi,-%60`VUihccLe -1,ERJi-5Gr[l%T1,BfaQHRjJ1a2(FT20X($qIG$VLH,k6licMT8lH%FIqTUIL8(A -rl'4H@DXHlPEq4Q*hKDJi0QlHqP`FLcG[I5'1p2!K')CmUH(KJ9AIDhrYhmmkAUf -Va'IMZ1Mj@9(&F9'8*',Xf!4)ZjMFE%@I'frT%C!!ek-c3hD@hMq6(iUMSh2ZVl0 -XI@`pA'BrqmUbda4hpjJZfICaGH-1YNVY@kL@cpY#26hGf6jD!H+SV59*3)Y4$D3 -p$YAVb@[NZ6fjhKTD!I+KYhe@J$M-YQp2()HfI4HNp9T`FmR&FGeZV+m,ldAIqaF -AKp0hYB,6`KYERlTjChM0Dp4-e"d"j3hXV`T[V0`66Mq)2iRMGDUL-"m(kdbf,1Y -DhkjA9Lbk%Hf1JpXU)cT"mfMGkbf,&D"HpCE&#K!(Rp[1&"rmlr+Uie$P%IPKI5a -U0Z,$)i-c2&ckVh-VQcki3MY'MmJ*[5H3!!qe)qrmpQl+r8b0lIRd$'-&L'2qe[D -@IZ5VH@8UY9GJ&[Gm,E03mI0QSGrAKcF,rEjH$fkF$kbEeDGRSD2pJ`jmHVAe!J, -RB&lY%jYV2TQTMZ49al(rkYQ$FA4![#)Rphl$H1hj$NdkGL@-ep(2XS6afY3k2*e -fj29jV0M"b6f,&6[k@8#`BMXEb%YBXIC1E3[!LVQ6Hd2F(Mqi&%hfRTMF,4@6U4@ -JFpS91YA"Vi-Sa`+bdl'i-1AXq5`%ZaJl%&21dFqba*4cD"I6&SL0B"HcciF`lZc -pl&Z-1ah`rdKIV`Vmrh-6R(f$4q$jb@YR(#p2AQ&#$NpH(A&B*rJ4$NeHEB(B"AJ -@h$Jd+fEl4a#+[pdG#RElX30-"$S1U`6[J`@0LI0KKp#ZcYJEpCGUI8h29S6r4ql -iF[CHmh-CGXh#Y&mFXf2C(+p692UG6*c+pLRNTX)jEbb'ApbMbb3Y8dbF,q`&BH* -Xlp1Y6*b&2QdTCq+d+8cZGL#8pTl*RFm`-[l6[BYl!%cZGLNQcU0eIdc,`-5jkDY -Vf5UeEk&D2Qm,GAkaXhfd!X6K-h'fap(+1&MBLZQYS48J(hVEC`@))m[%Z6Z13pX -qc6khF$TRiSc1,fa%VjJiSbImr'lZKTldQ61'2PNSlRN!PiU*Xq[RXIp-iG9rmE( -##@r@KF!qqebBMi0ejM0aYXI4bX4CL-0RiMb5$lePX3,8Upkb@!(Li"2@Z#0jeA' -i6*a(iMK'Y'(LG,mS8ThQ'IN4*!`a#@35Q8DQN!#Pb$*N*b36D'GN&f3jNVEB$GN -Gf32C%pN,f4[C"kN`hj%I3rC&RS!m%GN2f4pj%K+8e!$N316*b%()`FJKb+()iFK -Kb"&)ZY-Sj'JNpi&@)X'3!)p$MNGbCpSNj!3N'Cq-R)+FLZ4)jZR)'FLCb&R)'L6 -`4,D9dj!!A%0+2f&E11GrD[ehRkNpkSlk#fU[THiDHKV8(R9(r49VMlUMrS,DSqC --rEA8([99V$pUMaUNrS+kSmI-3aV'%HU5rN5ISMr4TqU4mj(J-L`!fqrrqq`dYrG -f'KdC@6GRP1VH$HXX,,9M(65qVPD0+kbh9eILYZBc4hHr+[G1eePd2Z#(LR9PS4, -drE$+AKmPUpiaHmIYVBq89Hq%[C2f6YNlE@ppMkakPpQlNldEl0h&hZAflQV[E[E -@H9#0+0V08qci`EJ4YcR&hFf9[Re@qHTKlhRfeVI2URF[HrHfGapl(fI[iqhGepi -Rf2Y%HrHcGhplRf6[#RX2X2G!HjpXld(feMIDUVHq[9DpKpTlQ,f(fhZ%[8dq4pP -lY,dVl6h'h[U'@r8HCqrapTjJliRfRQ6[+RY2Y[F8HdqeGl@pTpPlBEIQiLrTA%% -q+L2i@Cd@AdlpXCda06lGhM2X2G2HXq`pfpiepXlBZpEH#qaGeidlGH,BK%Ed0Fe -+6-"UZE"aXPh19Jbk0DRja,aMAEITifN0jSaldql86'1pZ,hArj,[ISG@-mpp+JU -JkT-+EN*5Yf5hM8V+$pZ3!#V[Kqh,C1m(0T)ThJp!ZkRH$k`AeGi2@-YThJrEZZR -HccUH-l`IYN!c[4mB4@Cj2d``XldId!SehXm'RKR[KlCAkrh3iHZmRiYjc[&qf-[ -2pAlSY21m(jD)ThJrE%RV[Cp,HEkpibHK48MfbcUPUk[R1cTqNPU@Y-Cc1FphjAl -DifC-ZHQ)Rf`LP$PAbHpeFQb)i-I1Fr'q%al&0+QH"lb"5T!!Vfhqp'[23T&RZmc -('P-pParD6cLhG[b`N!"BFG#2dr8$UZ5+JhZ-UlYaJc3j`qmlf&*HkIf!8VR+q`( -*N["l%G!Z5Eqh!4'6mRj!cD5p(j!!0DAH$qLE-Zm(K%iRl`F86fI["k42&qm(0&# -jp`0LU+[h!kUSQrF$kUL(p`-bUDIh!hUTPrF$`UQhp`-+USrh!dVU11m(*0AahJp -SUllH$iLX%l`I8&XRHMmJZ2Tj2k#mqRXr)-&1mRj!Le9i2b$V"RJrLhJ1p(i@mcc -Cq`(Q-FMl1CARB1pR#FmKhXp5RN1p(l"G`lbIj6b(HcmVH)l`IPEb(1RpV1)jb[X -jMHGSlqGdRTAHcaNmahJrCr)FkrfmKZFilqHe2-Gl2fIaR1$p3-N`dIZaT10lP"m -)EVVr(b3""f5eq*L`b*fD[FTkdL#5l(9I,eZaf'P3I(D@calA"e`qV(GR1-9)F(A -'V"8*hTHaE%@#paY3pEdCUe3Nq)"eMGXcaUe)F%h'1"8*VM@l1qepPm@chI4h@cc -h@(ch@Mch@Ac[YrIp'F0A*2KYmrZ!qAd`BrZ+""qaH*rr9"5PDdI@,KpHdEpLid( -5-T!!DQjBkL([jH&dH'cKXUkABcb[U``YmeFCfXqB1-FkK2Em[,'PEXadV3MrQkl -1G-lBRQQp,8claDGZfcR(kq4)RfIL92AV-R%kZcr4Krh$iHlE0i9A[%LAr9LQQ$K -r`HHPQ6MEqh3V%fHK6e[+Q6KY#T1l(3LP[@Gbjj2*hARE`Ndp!#ChZa36jp'k2kC -PB1*FhEL$V9,l&UVPmlC36dphYSp@J$Km*Xlf1&SC"`YE-EdeY!,N3frlV!"aC*N -iGmGaD0ZRfHFH+H9-R-lPiEhS&41R-heA+eJDhV4peFdl`fYHSfDLQ$M,'pKI&Gl -8Z#HFIK"r!IYFQ)q$GHBcFEE(dFV%@BM$Cq)mNJqpCE%#e+[HXPJ"iZ!6eVJMHG9 -aZ%bF4q)i4V4KiS`Fm`h"XYFRkH265HBDlZkm#V[#4V!#Ic(CF4@hrcRRmKL'(9G -rqpq+Yd",)r(&pZCfkri8eJRX9(b"h45ZCBr*6X8Af*9Fak1deBDT)AVVlbYJLC[ -Ve3FjZiGeDDLFMHhm8Zj[`#2Sj1aXjjGjh1MXVKBd8Di4MEk8ahaR0qVA&E"VPlL -CaeKRYrM[C#"fhmrpaEk%cVeb0&,iGbA4YEYbS3V-YBZT!MXlZqfkc0fpKM4bpQG -*JF5a6IfPe1VbD4ipR9hRMk!VXcMSGhfGh52##,YAR%BqrNk1f,l$f9hr3FAUfLA -Tk-jmCpIicaKdX6Li[[diCeIr*qM+cBlH,AAcJ(``pQ"hTAblGJqp%PdhCcH)klk -GSkdZKf,3hHVe34l6RGd8jDq(aI(f2)j2UAp4)qSEr%ELq,DcZdYRR[Db1+EQGA# -(iZ2@9HbiAPrb9+EYEKqcqcFHRh0fN4pAMPflSI39ar*pVbie2plC$9-IZmrCI8H -e4"qJrZKRPCQGm`ek@14NCcIZ6'UmNr2ArCm`)%Ee,D*I*XcZKlq*36rA$Z,8mi5 -hQlrq@##*Mm9(46e0e&rp1fjrr%H8iKhe00[%qhEAIJMeLI@dTYcjGL@k'VmVrZL -l[PhXYr,kq0Dpk%ib1fT4qZ9`m5m)5M(fPlQrDbj(0m$X[T2hbmrV)[@"cQkQDNA -keKTb(hQCXi[IN[I,Y(V'),1MRiQraekPJKFlkNrkj6A#f!ba[)l+qqAM!Ve5qm5 -YkYMdbqmTjQ(QMlU3!$karMI3U6V9GFBi+IhbIX8k`YPpNILkl(4f0k[hbH3liG9 -j[la)[Cim%0qEmhjjSAc4!iR[PVaZUPAhP@C(r8QIqqiDG'1FhF3,mhljePp4VEK -f)c5h5,qm6A-*08)Fe*2%mB6Q@2U5qMBc2dQrG,kZbpNR1,[KUNqTJmIr3!&,(*r -TpS2(d+Nmmc@SrU9IhX*X&l&*F4P-BUCIIRX8JmR1VNTa5,qm3GGe6E(mcHcdbqJ -08*&&e,I9Yj8k-2hb(lk#3E@cZqbpHEpFShPVQK[2TY%A6Ep-d[-Le![I$-h-9eQ -rp%k$GrlI"lVpdV1,A(jRYerkGX19Ap-[I6Y(IF6-Lmb)-bb[2mRljIhb3CkTTbr -Pr[3HFCDcQkaeX26,kkp(4be6*Rkrr23JZKV,KkTMdrpkUjm*FLEeehRrHi0@"l, -RL'Vl*2hebr)Rb*DSHV$%edeV$$Q9Gbhpcr6,1c3Eb3BjqS@m6b39!cNKhp54p-Y -rr"Gd`[Vd6IT"ceh@Aj8ZXYVCV@(q0[ebLZUBANFFc"#QAbj(*rLjiBT(kZB+HRR -%N!",`q92qYbYbJAcRIUZZ$E[Pl5Yb&UEQqPVdLq[&6IaBS[l+hNFCkYAbYVPM4r -1jmX0QQY20Ar-0e)(kj3,HKhji#ejqUaf"%ZGhD@lmRjCU4`XFhCA[6R[Pb[NQjb -6aRr1qf9Ap8TbcVM"[#VpmM(90R1FqUjRjf(kj51rJm%UCrF@,K`crA+FpJG)&I) -'kYMdbbI8NpL(%$il$c0IqLIh[iPql$aJrG+h'ri,QU@NArTfSqLMfAlTfphiHr5 -SFq[Tq12l'kKGSQIA@`RqI$[RHZEDH&!D5P,f*I6@-jcK*&eR*RZM))jEbDXc6Gc --20jFkhb3!0k@YI2lpcP[9em8Zb#[l!ZNEZl46(LQc6%hj[9ArrISk!Q%4&h%RGd -PkYR8"I9+McR(fAf9R8IN%UX2qV%EAq`8l9f%&Q+%qV%EAqbiGk!6iSDijQq*lfZ -D$f3A@+9pJF4hmeqTX8TmAq[%PjMr'$UjHQf&pJjZI)NpUJq"MFC[l-5Aq"R0N!$ -#fA,e9Chi%Mpj!cT""Ur9r(Hfp3R[-QIReLXSHp-RI,[Yk*aG9QHHAH5eQZp0Rr$ -Y(QC'G-kh[Z,E6G+FimiCQ6Xe%lSlE1H8YhEQM-b[DTk3!(hLrFcKd[mb-qUjlZl -6fFem)rd[Fj[f@-+EF`eab&b5ZIjK$'52ZC`q*(0*l5Y[3bHBQj'DPpaqRhRSAHK -N[eQ9lldb[kEG'AP8hhZS'jP,-Tp6h3XUi1T[GZD5fT-e6l!cB5iN[a)(kiQ)l9[ -[T"r)A*+j8ce!GY8c0#Y,[Vq[2LHVk9'DNpbkchcd(R5bDrm2jNkCmfSAD*p"Me* -IbIXkrD$fYCVjf48`"c$2ZrdJmk"fPTGEAf&qFqI4c'HdCpeQF6rDQ8FcIkCC5f" -2LpJlb[a8frpqG(*ap5MfHDDH(U)@)p,6epR[Z206CNCaA1(XYM0cbra8qc,0a1a -[eAHhqUJl2pAfDhDN(TNrf-ZiG9"lK[S%HalehB-2QCmbZc4RU,P-ckRXBGdj2[2 -RUJPfHZUEUGlTjURfaCTVfI23CPArNcQqpK9rV)BLF91hETePVY'-IUh0(qb'hIM -UEP,2)Qrd&HC20lkk0fRq82-Xhk1DVGhik[j32CJH3MpM2b&er(AeD2EHc$(89Q8 -pH@)1@j29JGMjrA@NjX"5jLVkNZp['[0Rp*JX[XKbl@)rjH+H60h%cR9f%lA,B(G -%(16HlG14,kPhX2p4hiHBUd`Ffp8$Q"29p`ccLBPMYRCEHQKApF%X+h&FS9apeX8 -G[6+2idRYHqM2bLl1AXI%FIhY@$aZGFNF*A&d9[mM2l4kVN#81,CU"rB&CjIqQcb -1(kPf[qMLZ&BcQBlMbTR(Y)YKGU!pXT2V9!Gpkp@-VPIfYPq[4dmJT1pJhR,F2UC -ESYdp[BZkB6Hfc0PpG!mkCR2Q(ZE22h9f3l3rrV,,dphd9kI2fAe#ZAM5fBeRab$ -aG6rU85cBEc"AX8Z3!2Jdf[UVcPpRj8$LqaI0Z*TM,a+H4efDq'lA(-"Fb@M'2#h -jZd'pK$d`m9(6%Ymbc8,-T-V9*1de*Ei'cCI8S,+V)KmQ[KqSCp%EPFQ(U6Z6[j6 -Q''T"Q6a+hC[iIUbFXU2'MVf8a2F0p6"9[pKpK(R!a$G-ZrY[bHcr!3#3"!d,9'0 -X8fKPE'ac,VN(,iYd"cIeFJ#3#!Fhph4RU`#3%%*P!!#br`#3"2q3"%e08(*$9dP -&!3#[[Qr$XQjqU3#3"3+2k!#3"ME&!!$,f`#3"N,c"J$&pZPQ#lY0MNBf)j[X6V) -pr-)@[M$V1PFQcb0XBB4YYT!!BlBbmp[VXI8@DXHp&R)l,Tjk-TAGqXEa(m[I,XC -DMYdQE$PG'+&NaaG1ET%X6pKf)F[aLhAZf&9Nkj&0EXF)f`hi3KEM#peN18,j3ME -K&f(,bA)a[RJ5RSX$Zl`Sd1'9DNh+kqMaK3dfff3P#eR)-l,*M*2C3REijI"pjcI -SE##hYkGC0V"&4eiMYjf[CHr#VR0VNlaFH+a"TjhjRBdk,r-beLfmJGIR`1[bmfh -U,ClAjGQ)E"Fl,hkG9lbhJEhAahY[1A,,HpPj'3I'!JLimTX`E9E8LZjM84jE@(B -,)fcKbr%"h3#-!!5-"ajj$3UZ@eC+c92+@+i5pcbT%VYH91VY,m2Q&dE#`+rrfYb -L[GRb2-Iec*cREVF,3F2@NI*USPV`cU"Dj(IM"j4kKqLpHeK$mXi066fe@b8Qh)[ -a9Ep$aB9M-hri)ET8k$J-Xr[K)i%INIlhN!$A@L[TeLm9lVjKU[9(r`mhKSd&L3m -f[D6(`mf&lHFZ5%SqTD%9[Zm2dmklI``Z-II8pIUA4k(X-mC262`UbPAIB+CVrX[ -,!bq*NUf2#8!18kd1JGV,S*!!M$""eB6PSbANc8YS@kX[qeYEI3Qei,U-@l8+lU8 --Cp9bp42'UF6HaRqj"",U9iar0%ER,9FVN!#'kj6ked`X4Ch'Q+h*b@(2b!R$qS& -FEl,QfGZFAImC$hm*Y8J`S#QcqDlq3VR(YSUfPmZPjRa'VeDTYVa6UC9Y%kjEPm2 -YGY-ZcR(m8QFZPeCUiA'!`%pd'%HGM!QSLK89X`pHS'f#h%&`CL1TQiM6Z"f`CjR -a+H2Ca(HEf"09qLD6C#9(V(,F,+K&*`"L18"HRR4S43MeN!!+l!)+UXRP82p8FA) -+fhYI$eA[iVe2iV[2f3aTLmSP)-bA3EiGD4Cff$LZpp56Sh[Rrpcf'TK2!LaU0$b -0K15r'GE0Pf[45*F!)IA8@b%RkaVcEN4N,c3(XKIihT*Di3mePC%LQ5CGT0D-iaI -8P1Q46V8[CDEF5XdTfpkdmEQV9X,d4,[EVTkhR1e8GlcUdMDY#NQBlaHXmPbSDLe -pVd91GFLIYYkrk!6ZM-ZCER8QaPR@6QXZI+f"rAF&RM86Ae[G$pb+qAjlpcfZ9jb -ahUp3X(hIc&P"DFCdHYdT&eq,DIG9ljmY(LaR1,lPqhCPm*95`,a5@aKf*,GY4HV -GljiV,GqiXl,D0Q339V&@jK)5fP1(C@rU-+qN$X1jA4XZ@(98kpa8Tep"b5fbbp1 -QKpTljM*pQ180fB'CYi2JI+TR`Q0VaUV93YZPT6Q!M#d,q"ME4["B-Y3b+0RCI1I -M,f"MZh&3`,'a)Q0XBi!aYSKaXC*jKE$BYSL+XA%-LV&PM)QaC35**F-B9NV@lH8 -8i@%qFANiA'lE88`+K[N##E'`C0L6Xa!*5hB!BGQS8Td4$-D@-3V'PN83c%0$M)& -L-DpNPkIa,l!UB&pJ&q&HE+3*MfeXAR1a&V#ZD"L8CQ#S'"IS$Ei&fKME5KP9'!V -XLTJ@'-Ci&PM&@"CB46J@'m9i%&X@5b2#VPabmVK9X#XAKZ*9,ZNK9X9'(AN*-5U -f!Crb"UAULR!TX)Sa+E!UiP'ZM'-XfRh9MMP#PMFYS&,H1)+QXU8QZfaS%ea)3J' -T+YC"9HDY&E2b4JDimLBaHRA8J+*2hVL)BhRV'-cbTM'Lj8dM@#YEaKK50Ur89S4 -bKIcPSDlGZ,1b&23+Y4)LApQb0h8K"TB0!F,P9Kh9'N&LhM6'aEaT%4`,H"%MT-8 -$BcAEm@Gk*JIeQGPDi&5F2HFD)`CP$UN(063KPeXHNCQfQQ-9XRNcBb-jlH3cMV6 -FD0"!biB5Cfa8$M-J"h')HDkRiH@0*,6!S"a@[UcLf*E$X3Dih&+Lc&Z93rAKU4H -T5`jLX#jC&a'Lj#!2%LAc'1p,eK(N9iaMk+ai825Xf&US,"G&([ill3-'8,Eh58$ -*,LlYNR98h4h'h3Qcj9mbI"!"LMbbbd&2ZL0k8c&qS%a$NP1aKHGd'(D93maf5YB -ai5PC&`Kmb6lLm"AMVP3@fNh6Zep[q9M6BY2(fLh[@9M68JI0'KCE4GDZd#b+c)T -YQFJfejL*V0V6@fSDj5fMYP&J'651V%@4EeQl!Z1+cCBR)q4LeU4#mUcamQCJ`E3 -pIB8q9f6@99,jAPGNTGfZf+5Ff',(bpVe6L2-X!IV3d1fCfSd+9M2l-qp1Yi!L1f -rUf#M'"GA#8dPpPf-+cE1K9@D2#K&&4$QBN5"B5kDZ+GELL42LS[Kj+ec-CAlF+A -!5KKIM+e-Ki2`+[bJ&''qqRBadeCeU'i"UcUR5+D%b0-+k$R*XaK)`AlUh+60VQC -R%8e"m5LS"YC+$[*&fKjml+!FHf`HKKlE95)2#VSpkX#i((&J'NBEf&3LcCGjHlK -j$q@BmrCKi(R$5[3P&'K23-P*13FP&f%D5VD96$J@APeVk,$r-A(XccSRpQij0qZ -j2Tj!f6lF+(%k"kV!I6#0QTri$hFb5-KE3'BJ0i*XJ4`(@3rC"$N5FL,NPT!!Nm* -4cRM39`C!%j!!5FJ8j&M)@XJdC!Db#E)4XJ&b&()`Y-bLkaehPapBiFmCEq#&30i -F+r`jS@ZA%r4Be5,Tm-02TVh(6NcH,bhG![)8$pq,hHciKmPl5G-fN!#YN!!Cb%Q -3!&Y"ELef@d#f30C$6Y"6[(%J$S48Z9$H%b$P%-#$H'Bm$6LQkG9@CYYTDA+28jY -aH(4[cYcBH8FR9'k'V4DjUIHFc4TH*-M@0q8Hm4kK8*Y#MSGXKC`)kqp#hJRj2FM -[3ji-Z3$b&-K6)9m!q8*)GL1G"VN)mL6),d21Kc`(mRM)[i0m1H3bb"-J,i9N3[m -ib1G$XVU!fMXG%Zi"i3BS6Q3*LM`,mQc)Bb#I"hNcj,'3!(m#q32)Zb$[K[`Kj+X -KVi#m%[)eN!#A3li+mV@3!+q$P'e%hUp$hJ,j5XL[3,iHmJf3!'q%I"-N62*Ub$G -$[JAbcb(I#[Nf50Nbi(dFmKf3!+q!I#INZb#r#RN0j,XKEi@m$I*VN!"r,pM"hSp -4N!#M)9P4`$U!-C!!Bb(C4Y!!qAR)6&LcE'c`e#R)mb"I"#PG!BqFqha)0Q`)HTR -p)H-J0iCNaG+QN!$M#8pDhCY"ELl)!Q*mJCJL%Ri$F0d1qAA)Ed"q%h*lb"dJGi5 -8I36HcC!!ci$F'A)Ab#Q3!$#lQb#hKR`Qj$D3!(m0H3(N5b#hKE`3NRl!*-LY)+G -#lJUj'q6ZN!"l31i*#5ke31i&13eb!Q3Vj"FK`CmY)6m)q5()$d0H#rPHb!p!bUi -%laMN4b$I!rPqb)p#AJpj!q6()$m1+Bc61`(j5FJE)6m&q@R)cd"q&K)@qMl)1b# -r"IPYb1p!cS,mBdKKV9i'mN$)Jb!2KM`%FLlN!C!!I`-*Q$mAFJENhd*H"(Naj2k -3!#q$[!35$M%GmMQ3!)G#cS-m$2*`b#-JCd,Z$ANNj&'3!-q#I$ENPb$KX'E0K(2 -KfGaCl+DqE@f6Br*)cC)rDS)k!5I!"2!$,N$1`3rb6Hl*,6NQlq!hq!p()2p`#(! -5c!$(`!GiJH8%e"4e"1q!Fm!Ai!j`"I!6RJ"'J8&J)*J*6i'[J%p`&c#&'UDZUA& -`'#bMeX")X)SkT+BY6S&0e,DY3fS6c!,r`$8`%9`&hm"-m"lX"CI"Gc!26)A$`)R -!AS[VB#ki$Tl``!3`'`i!YS1rB$jF!D`%Km!GX"8H!HF#-q&*CTq3!1)pH!5'`MR -J"Q!4q!9rJRI"cq"3F#a`$Ni"0i0$`22J+A!4Z!Qm#li"*i'l`IRJ#Dk$4l4ZQZH --fDr8er+eM4lEhY@@,cp"blA5Q''dU[6+a4DhI2hfL5ZKQe6Sq`$+p@3HTQ%M2lD -PRI2mC+5Vqdc`!MB`#9ma'jM3,pBP*ac1Mq2db9E@S'lYcXI(3#&HZfJHkGZ10%T -Nmc4Sj*GkPE)@"Z)@@"d&iPYHak1DU(V+hmV-Upe#,@DR`*B`9madLM`D$T0CQ5+ -hZ3*1b6FEl+`QqEIT&'UXM00X#AZhm6RMqiNA*VG#PQ[6!I3F%6-+DjKNrdj"H42 -KSFqq"PbLaliE9T6U!'EdZ!`HQHBQh,T@--jf13f&iG(fSc89'0KqCf!3aJahY3b -8(TDr1pM[YeRmSlGQAG0$J`[ak#[kl02[rpPZ%[dhqS)mHTZf9mkm!*!!cQ-'`*! -!@(Rdp1N4mZJ[@cj0,jPH*Bpj"rTX2(V)p-ji2iDNEmIl0dMUK2554rTUk1MadEG -$4bm926VkI[32dG&A*2rSk*25Sd0(rj8q+6TkS[3FdG%(TBH)MTiT[84dc$I33d4 -($jeidG%6TiH)MPc50d6(c!Ip8R6hiSHH)lTIi)FH,H9*,ZQISL-Ap(l4d8HP$iZ -1hU-L6**SS00K5IBJkCHLSip*cY(4lk3[LJlQTVh'*(X+p&(48D2dQ0(4rkI(M)j -FdS0'ap`*r@"dc,'3!"0dpq'([LfkAq1(qJ*H`!M`""ee52mA(IQP$ic1pRl4d5Z -L0ib1ALVpB(6dR1NKSk2[M%pdB!apCR6-M5KV66&RfYp2FBl%ah9[(QGDk*qMqeI -mk0"3$A'0IM3kkTEk3NHq`!Gdp(VT%k-$KHNES`-RX%9(rjNH1$TQBV6h9F0C'2V -Mk-!rq[VSQ+fJGik113GkrZLB(G(qG3ea!KU!lTHN!lk1)8M$"Y#"PBB9L!jXJK5 -J!`ZB*8"(AF%0d*&(`a&%4jrE%!M4dBG'Mikj"2V8k*MhSFq0MPa5QqM!#@B1d)( -Ip-(4-Dm$Ad!(CS0,PNS`Qi!1(+FrMSimd6G(4jdcji#12&&Ik-J&q8%((Y"64dG -RJMN%G1!Ch!3GH)BIG-`6-Gq!MPN@jL,3-@F$6U*MYNLE1@RLK(,%02E5QlN)G,r -"MmjbCXKKG*!!180ZS#3h3mb&,k!$"jP43!IZ`*A38I2D--b`CTKG3%IZ`""da+P -GP`cR4-"`G-a)JB(Sb$'fk*MAS@E4-DZM(CS-jfQB,8&(MZ%[k*K"Bai&(68+Gd2 -h(rKK2N9HP[b0149di$IeKBiFqaYKh6F[#4`2eZ@lAPjcHbUl[U[GE&rIfGq*hlQ -pUAiKY+k84l2AhrdL5f6@Ka"dHQN(eDa2GfmTl(#+h0&bC"iMX!pMc*UH@$be80M -$VEN9&c$RA0F+KHdMGA5Ya'A,H&qVf,9LjKq'f"Z2Q0D1Zqr[JMdqXp(6Ua0E54r -pQ`3LT+Hc1[1P6)Pb3TK,lE!PP'19XApS(8EmBB1"GeH!K38,UPE`4[JZQcNc9mb -NKi[LqJEA4%Bd+mi$TVKf'Sff00h`TeL10C!!@1LDQqN$fSHQE9JV48MId23,V@X -DKUC4L!&XG!ehK9(0[q$$0I0Xa5#E-REJZIIBhJlIC+'ejTIfQ6FC(8FI-6UfV4h -)QRdp*A@MQHIIp2BEeLKM%cB#62amf`dEp48'LQ%'1#Em[6#)j%KLc@22U!-($Sc -,a*Q(YkTRRhef8Pk&HF0)rrl$KmrjH%5fjl6LUaLlqd(Hq*R2a#6%DCml)ZrJ3jH -YN`!IIKHlBkkADiIGad`-ZqXUdI`VBd8IHVLIf'TV$rIJS2(Ck[eb1iVm'lBDkJ0 -Ce&IYqZdVE,8DFlXqHRejU1DU+jDUA6'ZeA'XcGqkq,Vb2qL[2HiZ2f[VCRA09Z1 -`A)2HRHhf-APT*hpTipR*AkEPE010#6!lqFYNTChmCD1@lHqcjFT1r[i88[ZIM'l -BbGm%*epemMI"6V01rLBiCDK6'@Dk9LGr%p`dTT1r#@kSdXRI"+IBG2)h`HeNG[, -h[r#MNlp*jPJRIj1FAYA*hb3R-RAb0mP*3Chm6A)56LGrcI5V6[iQZ3&,*hq6h'U -QNlp*l&QdNlmTeSC1rUBirD'6[bP1,qVNEiVp6Thm6A'#8#Gr8j`-eFRI&,HHkH4 -[LYZcG2)ha8ea1[QEiJ5LNZXDeV"1rYB`,cVj@m1DeXRI'MCIGI+hKK101[PV*P* -emVH'FH[NE`dhGZRNE`fhGZRNEmhAmD16[l@X@jhmV@A-1[PEbdPFRIbYjD5T6[l -@XQZYNlqeh!URNlqeh25QNlqeh##QNlqeh*bQNlqe,q"(*hr6a"'Gr%fc(R6bedb -*kZ4[QTeRR@*)XljemMI0+8QGr%ec@je1rUBjUDf6[fPZAY2*hc4cS*1rCJ*8*hr -6[%T-*hmca#DGr-f`$R6b0m2iGI)h`rV6,S#Ck06*h``R,(AbedaZkZ4[KY[BG2) -h`iP8RIc0X#qRNlqCV`P@!lpJJ%lqCSN"1[QECGhUj'q@HGI*hbcrGI)hbbPBRIc -0%[pdmMI,cA`kqCXPrZRNEjEiTj1rfHIaSj1rGF4iRIbY)bEUj'mGke`RIqZB#jh -mVH1NV%lqeR&b9#GrkaLh6[l@F@T94ilUZ192*hrVL%-kq9Y2,U'6[rA%4*hmV@H -qGI+hR[(Vj'mp*fYemVHHf`TemVHH,&mRIqZCBjhmV@p1rYCr$cmkqGY!2U#6[`h -%1jhmE@$0ki4'!r1SNlm0R-69bGm'EMl8b9rfYGV*h`ELM8lq0Tc&Mdlq0T+ck44 -1)q2@bGp'BV&1rMB5&h6bYj'jeXRI4Q+-pYXEZEG(*hmE'EG1rMCb3k01rMCb`k0 -1rMCq!cmkq6Z#I%`RIdH3!&ISj1m)BU91rSiJAX!Td*%l0N1LSkDC8NE(TN$`(af -E!*NN4mH8-CXPjBdN0i2hSD1fQ1T("fkaF4)GY3H'Sm-AYBb1$BCXS%6(T$qE*p( -GJamQeH8eNG1bU3%G(!cX43G2S%E3JB28+6VUM4bLBe-P'b[4XH%326Sf'V,"%Ke -6i@bbP$H+I*+0PZMJ5r!GG1!lR!XG'!5R4NHG-*f1$Pl#GJ"dE!0Jmb8klRaMdPi -HTcDCMBhS`(if,D+METJ!4dHXa))1V'6M)cT`!Dk"MRU!Ak0M#`GeK)lYL0S"'me -0S'b%42FVr-!,j)dKhmBR1MJC@`c3`FHBVNF(pS2Rk-JhQb24N31`#"fe"$kJ``B -qL!lXCjX!1MJ(facNM5ARCY-N1R*22D+$Zm+GdF(CG!rb@2)6qKAS`'+fIk)$,pM -FLBlDJ!1L!crJAqMBD-(@6(R0l*A3Id!(2kFfdGPYNZM!BcCpS)0,X#N$(AM(GP9 -de$CF!adaJ-2Sk*d3Zlb0b+[BRS!1h'AV+6Si*02lk1!ce!Jkm"SHJ3jFB2XS1[* -#I`BGI3Xf5XJc,4%i2MU`N!$Y+ZMJVq!c1R!GI%-(4k)AJ3iFeeQ4FF310JLJ)ip -X0N%(lS)EmMCQ2iKH$6TU&'k&$Ki,ld"(I1#EJqM&"aH`-E`e2%[!blLia@CafF) -&%-GlPVGEC6D,DS%GALpJ$9ZaZEbecrEGZSI$-,`JA'QqAkh@@h@#C)(k`faI0'+ -C8k)jC(!lP!ZG`3V#hE(S0R4HEaA6a5q`#ME#p2+pfB%Y55a[hT(D16Jp`r`IQHU -V9h'!a8QKfAkEmVeQUZ&&8V3$G4+3!)CZNl6Me!%ZAUi3(L1a`#kDHMiMGje"P'J -[5R)dc,&MV9#LQcf6(8Qr9"i29LTJS9-)lb#3!(K&'k9UcQE4STcVfDmN`-EDZXc -%`3EQXJ*[BYZlc)pX0hA+J8N9IX4P,P08JEJa9@#ZbM!D[jiNKU"`CPV,EhG@V#V -HP'UBDCQ*ZV9KE3bRR6[i6UaDHbXee`Y-k,ee9VRXZP8NFf'0Z1%IeB'P+29'$E4 -b#)DRMm6`YU5b'cC-a#!RCN6U1'DlkRjD!kjD8Aej(kC!`Vb)hX[N0NqUE@C8UCP -"'dC[M1HPJ5a"*4`hAJQq(5Jc)jd1YIR+bYPEE3(*a+))$@+LqJ,HGB5[[U+)3rH -NTAKTJkd68bDqmAE6QI#YJS!LZ-UG35)PThi-l&'-2QBZ$kqpH[d3b*,a$cF3FiP -haa1d$FL'U(1f2KK!@N*rIT%%,XJ2Pjp%,N!p[&SX*eX"23"(Bd1,Q(JdD6@`9dJ -B%4D0L`84N!!#Je3q*KIa18qVr("%)HHb,,6pJZI8!Pd3S8%ZjXL,$65d-INiGFC -6P+@mTDQZNNQ"em$XTRH$Yq9Z1SQaGhUhCJ8Ri)+,a@8lk3Ie3CqFle6i2c$GYG1 -Z"U(H"(4)[K-kSk#ilF8Ti3NXUSX1jbQF*j1r5DC`L%cqqTMij*M5C55&%h[bam$ -NcL5*,hq*,QXTRG-5CY3HcK*Gba+Ib",IaG*qN!"4G'T8kELSm*bSiK&"hSAl2FV -RHS6AH951m9$1,V'GX-iYlYEFhIhpp2l)M"a6@eKM,9VYc[Z(5XK3d8Srp+EV@Rk -BYkK[qD'Iha$jX51**6r-(ME1q['DITK&(0Q+KaQLdE0q,QVk-4G&2*K(jKLI14G -hU'#QCZq@(fBHRphb``cNl-K2ac)A[Fdb2CI(8-(Xj'9ArH3+`!bFPUG30eJ4r*M -RLVRdSDm#)*[f'KRQc(+q(&#E5A6dd@iQiHR'Kf!cbC2E4b+pIB1E5BVqUh'[bdq -8Mbkr$m8p[*eP4Gfi!qT[R4rhJHbV`ICDlF33Ebc@l0)'*m6pA3k!Plff&G1YmU4 -h-Q*U,V2dbKH"Xi[&`A!4H2'jRcSA%fq6M6$K6V@qcS8EJ$dAp#Xk&i2GKZ,r1[E -FVZq+HcMIrjF2pd(FkrDCpG9NPlrU,VCL21f[&)GEEJ1SZ6a(pRrPjUALYPD`09h -mX&IZ`*BIGMd0c(2TlZaM@hl-*50GFh1K(hE8lGIb`rcDISejLmkj0,&L4pUc@Rk -BAfZ)$r$MMVRL5SBJ4jhEPl(Q4HFPZJ'D0bZ2$$#Y)VI!!`JDql*C@BhR[h4hhm$ -i9@L*"G&+(*PXRGQElS,2C[P2bRp+rQZDRT0YjeESj"c@bRm8DQV4j)SGQ4G9*aR -jVq-r0dcUIk2B@6p0mMpDl%Ia(hcRR`XUq4Iifd,daTri-I(*Ie-c'69K$bqhTb+ -AZK(L2G2dPPNiX5G(dUS4Q65,VaD*I),%B$-h9M,8dSbPIJPM#GIRq-Y[0!(3+Id -IM`@A6V1$)DA$EMI+r'mU!Rl5FGU#8q"5-$EGTX,q-IH'X[-l)8Y+(@q22S3"%2" -JfK!hV5`Sa,B"!m48jiqj)d6`i$3V[Jd,#RK3bd[5p1EVHI8DYmj0Ncf!,M@!X(J -JI*%E%)Yi%23&h@Q)%1)"ppF)(Z5QdZB&f,NkhbZ1GebRKAXQTkecUR&Qk'$aJ*Z -Q9q'"q9YFUEM9eERk)0VTVEh93VPHM!NM%5%HC+lKJE"+*aNBj2%JUrZ,,*@H(m5 -hY4K$2+M6H$!YihSfPq%Z0@p0hTkm,@i0'8)mU1HN8QRKXR2ejHpHF,)mCpb-)T2 -FmLXh%KYeprjLmF1G(J2lPF82HiklpN3%`BNIpN3mUq@(IF2Gqjp$2a`YdVhA1I6 -$(6VGqjT$2qc2f(3f(VfAa[KKImE!2JkaBRp'erlXb!rhPR6YiilmF"Y5ejlYb!p -h)hAYG5ljbHh2H'#8hL'r0pN*fdZ-VmPaXcaRA#r4%E,Aei&`8k[Bd)a,d9BNCjb -0J15Ze64NKJN3f33j%T*6[TVPkJSAa8fd5E@`l5Vp(ar@`["M05a,`G`!FFc*T1A -'ZjjA1'QTmZENdR,lhA!F4kENYVbRmhTS[Qmf`M9a(0DeT6mj@&)&hqp3aRIfU88 -E)b6-(JjemBe2&K$Hm,&3PmL2KVHjQ6Mk6m5*ci2UI(iFcj!!@`Ar%-F$#ANiMJI -@42mqMK@"$-9adUkD'RPLVklADdqAaVkpeU#q'HHD0Hjq,$bfUJ@%*0XGhY'A'$R -H"[[VM*%6@if$E`Y[-c4ak09mMqI$R"K2(!q84q%5V0km,X'G4Sk!114-VbIbbJ* -@'dFI%Jh&dGmPT9bVcm5a9*8ZiE6Hef@!fTS@FCVMZkUaPJld@[lNIM1pDr$r(rc -M$0q,!6JXL6M-f9,pVh"R@19a`*3E)!kH1A,YLFHD6'AFiFe2KHIqB0cPkfMe2F+ -iHq*`"M$Z3pCYP#XqHelKkV6+Fh``pqkX2X,F"q*BaG`(iPM&h&I'm6[QASfMbYa -jbY`6qjGXM3&JlThjH)bjpb4f$A1[aV'+ZAH'm5KcVmE4cp`PMJ(blM2hNiEqYqk -G(ibEfq3Ula('h4d(ca(!Z)pdUVHpepbeDZ8Xikll%@151&BJ`d1-D5#198aRC4b -rBcV91"j#mXii(NAbDKcpS#Ga50f[C1EQ9X$H&hBNHLY%iPJm+,I*GMbjZ'iJMVV --$kB`XjP-5Ll6IIVp&[(N0$iUF@8F#kp`4BQ$+qjcpr&e9[5*YPb$1jcABFi3F1P -q6Mi84a8jqqXXU)mc,jICEep$H1K*,mD-$,Z2mkZI49HTZ`[9rR*GU,Z('pe(*d! -FE@AI9i!B!C!!lMJ%kmQVGkP2EVU'6S"mQ'kI%b!1fqhVLf1SfhGb8#QVBlKEK$L -@iEEBa)H0Tk%IGhH(-AbUTJiE4ljir0KHip$l##Cb'h96&IB[0BjmBEdar&aiLkb -*ia4@88mq"ZY-Zb`,DKIVP4D,!D,H1,K8aZ0"0m0eElSX6S"k09d@*d!F2"r1j!E -V*r*UiT!!m["qA"m(Ze@jalNVJA-bZ4L!V3"XdUp5$fpar-6N3e[frSZp+IrC'ZY -lKX-i!H+BYGhEPS4m-Uq`8RI&c',IDqG#aCIM3NrA4ii,29f[lS"C-F1&K[%$"$l -DUIe`!QF`Vqk*cM921G96H69ap0m304K(GF6,HfImfiaAhaYL1QkP'DrKjeLDm9T -5Zma1UhPe%8ajbkcBm(1!c)Te!XLMXf,G51d+Q"@,,PHZ[%cm"(0h9$"6*`"bZK@ -3!'V`$Hc*FhrdG"`ZQh,kRS1J&q-'fT3cr"a,Qh+'HM%GJ6J*0ZkXH,TaCm9cEfh -FUBlrHfea&I2rUaLFHf12`%2-Uc11ajKA6d,@-+pU(-k*r3K$c+XM%,I!RJ8r$R1 -*A[FM#,PZa#F&[AlF!)c!a1'8f2Z`!BjbJeaZALREQ&GbbFfRe-E1cDHNiqAQ'EQ -"I81)B9l*FBB(DqH9A'4JN!$(!kIqcF6qCPmhkjf6FYlN[**GMQZjFC,RMVYcNYP -90mfVKCLIG#rG64RF4ZNC@!q*j+b3!+01aL$N*X()9CI%#NI"F[-jAejcHbUl[U[ -GE&rIfGq*hlQpUIlfH*8##2Sk[EH@1%qIR-rQL,f&A4j(RR-G,IrCakXIqS45Gpi -eib3GaiB,j5Hp,KG-pmJ-5SeTF-I@jDN0'I44Y[Y4#1*iYQi*0Kb2"fJ%KSdq6`d -B`mD#a!HR2+5q`MqUeaP3`6)KP(q*m#Tmempc1e`"(C5a!q%Fk0c4e!ZXXV2RbL& -YICAbC,NF&k$VZD"U"@q%EmM3@-d#@N-DX,4d5ke@Q+3"f&Q89`4f-66q+km4%Xj -I"pN!#CK6NM!mU$ilbRMd"*+3!1k&k3rLRhreTM!Ac12#Y9QGGh450M8Rqmh0H21 -@pTNh'4e((c%kYUdGb*Tp259eSjRRhr6f'pBSBp-*TAlkmfdhE&4$jN"@!iFI9p, -X15UD@a0V(RZ')k&',Iq*-`p[RG!(XUL[f[AEYqGd)1CfII6kmP$099FX9EYLA+[ -M@*ZrGI&ejAr3Ah[FAAl@eXhUQZf*`jPfVIQKiBAIjQ9l(Z"[j3V-Rlm8kK)2(6c -%I`I6$8Sll9NlFIY[N[VS@R06[rkej[2p(5EXrAUpEc4X0lV!VM8[ih6P@[-#6V[ -0Vc9h)M"h0p!PMhh-hID0h3(-h5eeVIP`h@r3-PaVIYfbTp"9kZj#YEpF&qVU3ih -ZSa-JM[+ejZ8i+PGT&lTLTQ[S"-L(kIBj!H))VMA[M@1SffFZP*ip(&eVRTbIf!+ -pA'ZHA2b"%I9mBZAqPp-R%qESDEL8Dme(RBApja)VlpfA@(aI4b-1Fk&d6ci'kka -mVANjMXUejS8ibYHDVmq(kE)i!HV9G&QF!((`mYHDVmqVL51qeRap("Z)0YHD1qB -fF3ClJZjmHlKTf%'eLE-&+pTeVj2BhXTk6DkieiaIfm4Ca'NAr#E1TjLl#fN6TcI -1h"0IIVSM"S#jZl3fF3l8r3BY`bE1Rhhb5f#Vrlea-0H&f[*SSr[S")MMm8fFaDk -Bk4Sk!I*KZRe1J$KXYkm[MU&ZhmT0R([FHQ%6jal,cfrLl-R(B*dp[SQc'-IMQcL -,FCJZLa1JANfAa3N3"frG*XjLANdFrl1*XaM("U,0*NkZH8f&IfQXKKN4(hF,YKa -0HMrR0JdH6"ZbUlER&',EJ)($lX!$qDh4H(#D&Gq'"38mU-8Qjm4U2D!bVeiMejc -@BeY&fr2Me!$#iS(`aF4j2*!!GXBCPZIB-@U)%1*"mM`HL0De4K%KT2-KGFMd -[X+T&bbYL3!+@F0lU6$jYTPD[FkTaCZ"Jm8$kcCRraJ2cYlK5FDZVFrA"XP-`HkZ -&FVdB%dBU3cc)AX-$iC&1-M$)id'GlMHIJ2@Gmi2iYTCcL!Ie'JqQC9c2hS#&VN[ -0@j1h*fq,@d1'%!mDS+UPLGLBcHEQ-DALUIE(Gacq9D@'BJ*fF$LlhYL%aSF)&hC -qI2ZZIU9+[a[VKJXEcAX&&`l3Z$#6BplZYYF+%LR3%12#&1,#r@0RAYqcl%4ldd% -@-Y1id!CF1(aXl-@IMA&$"Aph!VM!lS6'rkY3l%j`b-h+Tf2RCZ9Aldj`Smh+Cf2 -RCZ9eGi*$EPDq2YbZiUCj5DcQ&D`dRr2P0EHRXZZlfXhfpChpRILGfj[UEipA+3! -R$!BiBTkJ3-)`hJ6#*,m$hX+G!DXTeZ#'EQ&Za*p*k#`)2ZA6NIKd``qKelAm-1' -HEIPK3m+@$6r*D$"HhN902fRmMSRma2%NQRkBP*h8m*1DM#H+QkdZHmlk#B)c%lH -H@Yhbdi6II9TqU1*p@hl'i(Gf9$mG&5pqaZ)h29GRSCpQr#kJZCN-kiHE`%m9`0c -lIS5G$9`2jMapE4Xb!,pVmNkP9VEl#c%!Ya!j1*icES1*-ki(lXCj'dQleKdh0b, -AQ)Nm6EB),JThK(R+PHea5f3mj(6C2RQ'S-BPm[pbq9mQrjI+rp*`eX&6J@bj28[ -XcTErFb6HFd9rRX6l)SRra4,[q4,r"I,r%[&hB6M$`HNp[[iLmAmaTNKj,`[MGKA --a)b3!(mL`K'C*&Sb4PE)"&NN%r@3!%b(8!dMBcC3JDcC8L$6C*K-GfACVhHh`U1 -k(4KPY!qHZAE1E(bHNHlH8YMK&(1HZhec2VcQkQJNFI,&!'T3EAhfak!5Zqee#q6 -ifCQHB0C*r*JD$[bNAjYe%MpEi(I'V*mJ12(6JYrp@hiQi(GQ`dpQdXp&66rFTTQ -Ef5VN-I5c*Ai(CTh%cb6L9hA@5IaX4Dald!pE0EYRf8)rfq"hB-E+qYN!4*LamRN -K2"mH#GH(L0K0j&(h`qr(Z"GH8LeXZhTZj2MiVQXM6fMFDcdV1R-YHcM8Y9mEQAM -`Bk%ZN4mGjVq$kGV)@jp!2jCk[ICdDHcED`hUQlq)[Y*jMi@1@X!hXYhKlGf*NH0 -YX,r1'$Qae6MiYYXEFEL6VShXRj@91!B1KG3V)8qqK00k*D3"DQYDa'RheT@3!-U -iHmDZh4q-f`&dXl9MJEQlJ@kfAXAF%rZAE)d"B1lZRjZYh3+h9JrA[32NeZT6Ar2 -ak+h9RA(`(!'-ZhUBDeeFa9fZcSPl@Yd6GkFk!Hj&03MMP,M2Y#lcqYAArXYQ-UQ -HDr$ArAk,H'fk%PI'XI!+9j3i&PUqcchP5l#DYTMFS+*2Y,I&"14eQ$-%A,UIN`r -&88A1rMS,kZ2-(ab9r1"Vf'MYY#jKc-L`qcLrqPPdPEUl81d[ei@kHlM4IA3#a0& -@pRd&L"%!kBj$X*kmHTIkj+CVk!6)KqRf13(LX0fq[ML'ZRdR"j@b1SDpYX5aE!6 -@bibRS4phGiFaI+UQEMD1Y+mkYYFip$k#b5CBNVJ)pLmeMPcrCmE`Fr#RFCc#+ZV -*af#GDCGP3HeL[G*P-8$8'mI4[6P6*IGFMQ-`(kE,iJ5S9p0PF3,%`I2Kc2ZI[*S -iT$bm(pI(`@jepJ4pkh"1*KF$X"Z1#fQUe-0E($maqG#@[IpLEmTrYXEkRZ%`6S! -iCQhhYL8KRm`VV04aFL'pi8*2edH1#ceGVqk!MV2K3X2i!3)IlG4q1)%cQ&Ih41H -DTjcUUEbD11"8`r8aX&PcXrLh'Dqq0m4dh%ScAX22X66M0A54I%FJMS*CXH(R!*N -9k`53!%GRaEU4fK8`+qBcpcQf0c6E&-h%6c"h4`8cG3)JTeX"U3CIG9'1!k5Rih$ -CP02h(!5p'$I3TTcKjeMDP$28LqN)a%A3LhR!KflF@I(F@aYhUZ2rAPYFaIcr+JE -RhYJMm"$ckScM-HE9Nj!!0FbV'SGcBMr#%22U#-3YX'I"Mq1Nbh9'%(+ePNm+H[f -i!4L"LF-TXII"RED*mp"`Hk0jfCl``Z$+K2r2A`TeLBF1(Z+rJkQrZ01HY40lRC, -8fle1YY'NQcMRqcY-f2[eHYpSH+q"@fS6jqrlJZ%QcM*19cCa&R$DEEk*diR!h0e -!8pTpc0eH1Z%1B1l1SdfF$qr3PZRUiEVIS'ABa(RGXUI39HVZ3V@rA"IUkN10lU- -6))lb*Xjb(*@0Ji@ZQ1ND1J(bBETp6S!iJNfF[A%-GI[-pVRC`p%QcZ6ma"ESC40 -RF[%(4Y6cLCAlAdkI6*LMTq&50R'11J[lcb9@hVX[XILqMNBFC[YF6ci'kkbmLE- -F4f86Cb'1mLE1pIN`A4BR3,fD,SX6)!jHIK2RqVbD11*0R1[Mf%#dfF5j)Cp`#rH -'X`CcmTrm)b)!&D@,"NrG-aAKj-%2"d94Z!%a,@'m+4(q$RKM6&LIH1b,b9f"#dk -CZJpVG81"!5FEql,CrJQMG(II`2KQL-5#rN,Cc*IX-YH`e@lS6AI"Cl2m*q8r*Im -EbAp0-i*N@mB0A-mYFprjmClPlDD41V)"45'R&Q'0KZpU3EJQBk3ibFKr(IrPDT! -!"[P[&$[VTdRq4i[p+2kRP$,j,i"Pr03Up5l4'hrLam3Rrdh0C05mPIQAC4b,kei -Kc)C0h3MaRQPkbbbNYebDda+45E2iDT()*dJ-0R0M*8-Yc9MUPc!@pYmY+&L"Jle -VE@k4LaK0!X6CT[)r2R5hlr`(YRpeV2Nb(rh)hJPplRhMdI$pkY'A%+@8p5DUiJI -6Qi!1ack3!%ED&EE[6Ii'DJ+l4G0!-SA'BVGJbQlqH"`5AqSVNGeHf!q6fD[MLqb -f4ha*fNPmN9eQ+8YLLBHV+*+RILC#mZ44r'bPl@lNVLSP*-Nl)hml$""9e1jfr,a -@flhbMeMJ#MVXNCqPlIEi$d+GEeIl([cXUHf1iFDqY16lD2b-d(C04-q-YXYbrmR -1fZjbVZ(+LYh98AcArLPdGGTZ&[c9L0dPIm@FDI8IKCpQEEIT%ZJD*'kfTilAGTr -k!Y(EYb1Ac8HehHXBm`LT'mPIBVkfHpi[%8be$VKrIa0YGrJ+k*SN[Vq+kZEMRi0 -1Z9k+G6C5fhhLYk!EVHff42dQVY0fRrp0')b4ZZ(qJVfeh3cQEkc%mCNSMLrakQe -Xj@hp!Z,iYVElm+-`f%Mmh4c9`3FBhcM*(pXP08rM2J(GaYTZUc[`Fj1fDlL21IE -YGX)DRB6Nqb2%J%dP6papm&jYGmrGV#fYearKCdGYPrKRk$E6G[X#Nj+,Y&e,(`` -fehCrJEM6B[I[a*3YY0d0L'rUEfLl,Ai0"Ld5(e[6@LZ"6h`0@HPT`-[-@bT"Z28 -bY,ZH1GZc%T6G+EXd,b!C"ArJEQKAfm6,(l2@*dKpIc(#bpeZB3l8EPRNliS[3cG -4q-rj%9lHpK3,A[hp,-+c4Gq($Nb'!S#rLTI0cc"@c3HiShKjbd%@[1B[a-XV(S& -Z'l%,mI*@BXDffZijU'H,PrGb,G0Nm8Hp+NkFqehSYY0fGF3MaFXErKUk2p*f2m@ -raFYhXYCdbp61pdGiH3jh+i(ra-'riXIC"k#MGX!KI'MGl2mpBSEL&VGP+-lpj'% -#N!"[Ya[`hH,PkmmbB)d2EU&iqElIJfiA`BQT84bh%brK@I*frfL%Paka!6r%38e -S(Ga'E+,fi3(JZ-8$X'!hEEFrm9(amYej"UCf8VX@,hrmac$B3h!DI&5mI-[2XpC -pZdRNMiUAep2AAYVZi$q*m2+H,!bQDEX2246KjD*[`Z#C'PCffK6Kj9KLbGk5ekm -em6*X1Vd(H*PH+hJCfNhk+QY,m6+dUqpXiQ9SPb3Ae2VBrTqJ)lFNK![0&5p[)(i -r@qS*(UMqM[Ppk2E4GJF3Ha3[AdFmjY3%m[I,#-qqM0alc!2Pr-N),bGq#$VG8TY -q1F,,CBHKdjeL+I!NLjI[C!jeLf`0HBA'pmeICJ(lGQFp(Z(PjX4[hGCB`reXLK- -IC'`(50h!Ka3[ac#[HQ(0Eh$+NFA,HmPh$p*fCqk-m2)meX3XLB1m+RkdSFrJbDl -U1YlLSA9c0R&&Y`42BRdVcPe'VMP(fme%2m$LjAXq6N"4RJ'1+&lH3Li1YP#UB*l -'F59jJlC6cJ-f@l`m&4M[rB,%)IQcGA$H%p$"kFJ(q+ej1T2B!$E+Hr&SK*GI)Cr -@cYRji#X@,rFL[k(R)1m#e*r&brQmK!Pq5YbA4hLj'E$FfkcY,[jdK*HhN!!(d!H -3!0$'`*r&bdq6-p2I%,[Mrb(#bldr"3YUJIMJm4B[YII"Zq38-8ha-V5E62iNZ'M -`-V5EmYY0[!cY%Z4G@KpI*aBFSqfQlS[`FL5aj(Q#Cq4&rEf@(1PBEAFJDe(amNc -f4DJTD!Xmaq)@r2)ib3IeV(MjpSp!TbG26#%R8lbmmPqJdk-NNYb-U(JjJALJHqj -f24R&G`(jVZl4H`RU`Z,PYY`CU(HNl%jX9TbiLaLR+p&hB5p%mA*2FJ2r(T(%JiK -ch%PYp`2bB0ek[`ciB[(bApK$d6f*Zab*m2)UaUTpY'fIM1VQr(q(6[IVlI,R%Fl -Gq#hSp$D65i%,&LrI$-cfT(qhbpp&H(N-Hc'keh8+qciDadI*DE@[GcNiSXA,,l" -R!#lJljUS$Pj0,0I0Nj1"3cC2Ql''kDA)qqJR)lcFQER`qib*Gc`BiH@9a!Pr(f, -L*qP2mI)XpR4drH%8FJM&bbq`$[apMSQI!TjD[2aRFMl`A1`f*bp8ZaELk$RDlTq -3!#q,PdHa"hHZMQp2pKZH,hLT28(mI3fkG%R`-QIRhFJq`[D#Pk(G92C&,&k'FA` -)IC2kHb["d&5r-l%8pCCm6kAQ`epSPpcj)ZRTh,3IJ!H$+l56i8p`-Zfc4R(mL*c -eHX40(HAk3)QELAG[&lZ3!1rZbVl1C,(,iAVL1H,0Zm3ZbLXmd+qR6)EF5eF-Em[ -HJeqAfAGpL36*YkYP[ka'qlZ2r3ELKGi+Rr-'YGfpj!4`9H+$4fPm&j,,JS(82Id -Q2ll-hj!!keiSI!*FpZ2,[T1p*rSHd&*mDhc[B%q%(L$a`4-d[P1*6aGVZeRX,fK -mhb'hJq06#0+hX2Rl'$%GAL2[&Gq*iVZ&ZAQja!Fqq2&PhmcBk+H"+pKTI@c&HVT -8ffAB4p(ir[-[SB1r8-,JSmEhFr+$2pATZ)Gp)SY2fTXfGY+I#2SISGdrXPGNkcj -RjkeN6"DI3VZYLI'#"`E23VZTl-Rjr#CPNG2#@b@qM`1(Y"q3!2S`Bi+,LGdGb)2 -LEZS@FP6iR5$2424&,1kqLM(5ba9r@j%h+aqkRG`1lNcF`P19$k8kL,9AL"fFaZF -CUAh%2rScf0&h84jc"hYYVp(aEBfHJI+Ke##j0eaEhPcb2jm2TEDb"`D2!aITR@X -F[f'[aEpP+,%-26cP3kNKFNYi-IlS4fZqPj!!%`Z[iE84Mj5[I*JFlidkMQF!!j4 -ITJjm$4C[d[kbl2[iH*!!r![f5Um5QJeqqAL3!,VZDHMJ+I*QN!#Rq6`ie80FHE2 -%$ArbHA$UqVq&lLf5ThG&[1dDaJ3R`LlX%hq@24[i"A($LAhHPUT`YZ&YfZjQp&m -XEl[c$iJa[Yefl(%UErXemB0H$ALFUi08NKK2ld[mh3*-9Gk@1M!'#f)"RqKhq2f -$e"TL$AQM[Z%EQUIVf0Z&KmUlJEALp`p5Gl*R4km'f+([S$cq%q6(j%IHAUceZ49 -rTPrHaYkBY3YjdJcb#@XAmU%Cj%R@,X*Aq-3Sm$0iFGJ[1BKeq3Va&r+YV`,[Nfm -*mq5GB$m-h"1lli'ATYkVl3jR(6#,3AcdjAdmp[DcEQl5rZj#Mp$'m5PL#Id"-6N -F[-A'F41j2MJ2G)#A'XHh'$FF42`GaIk6aV'-'%'HaH4Sp%jX(*Ha[mZX#R8$TQS -Fah%@jF[Dhl(NVaV("iMTp0l&j$Md0@dFLmJ4QHqJRUKEMH-ZcP[FS[fG!1bhFAb -5I46U9%a13Rr)a['AV%Z`MT+N"kpa[)#B"3q5GaCaH93&&bcNDT+kq5(lFpqY@00 -A4L4,i*F*h6FDrB[Xh6"V)bDh%BF1dhBhXdp*he,XrS(qrdcEIB+FQhk,a,%!r#( -4TZfH5rb',i[G+F!e'pq,L%0Ieh(mL,@LmHh$rJ5F92bG5VmDhlICXb!@X9X)EQ( -M1i+e4"p'l%k$$a[I%HaYI8[E,5+IdrMZCKm&2S8GGD2aEF)krSkf@`aqCH-E5kb -P"X9Z#A$IaMH&f(5RYMZGpDEahI&ek1J*L0dCR!2aia[e6FkFI&rXT%pTicZBR*! -![U[B,3AZf2MH5Nbm5pZGbEkiaVFAqhRd2F6Z,2D40Ap6f31'[f!Rm@KmSrk0R*! -!2UIhr`#3!`d23Np"Ae4ME&0SC@aXFbkj"cIeFJ#3#!Fhph4`f3#3%([+!*!)rj! -%68e3FN0A588"!+qqEm1bEl`a!*!&!H(X!*!'-DN!!"d(!*!'R,J'q)lh$M+bf4& -qRH6jN5fHl$0TjG1ZGc2#0NZbMmPTpVDTQpkQAl3Lq`KhcI#F(TlGqXEa9rc-VY- -k2lE0M*(EAZq4rB346MECjlQpcMbbcipY`RZf6h+EE-+IX+iME,mGfi4hAK*1pX$ -HMQ`l"e%XB,a!9'Q6[Y00MR[ENe#bb5Dr#5HE62D4iEk9Y`,36lXqVeJfd"cPjD" -Ll[Gl&lE2KFFqqic*[HeCAYlLZE$YGel(ZLlZlII+LcIaHUphdBB0[(b[3EjAIJl -X1MX[1bFjb'%6Vr0kXj'$TJ"B!'IP),04GVh(ciAGCXYa`VmMQh#bbH,&h3#-i$X -!S$V2ldY492BmEar2bdhcFRI1p(*h[GhcAVk@Q1Ybq4a(qkf0KS+"BKb(8Hcha0( -bS&4[a(T5[VDX&Y6&r,r#mikHkAR(#-qpcfT)IeGklU+VdKYE8l"`GI2EFmHFBQX -dZV[dlTFQ5`jb2Lfh0VGrrZ`GfE5jDFpjBf2MBImePV-2U0FGq9jkZHHpDFaq1U4 -P@bhXbPVEhfrCmE93AA1E"03aZI!*e0(YeD1mr9p5L+V&8V3l4ahH01q!h-EmkXB -j5k,bcXhp1,GjRfRHG0*`JqIp[0#FSY,)P$+S`"N*,rSG+ZL+h!fj,IP(YPC3N!# -E)Xm9XZ&pb&V1QmVrU+9(rkpS3X"S&9i*(kqrTDS1[U2jYlSRjr@12dprMq*rMV$ -,V9i%HaArH@'rP@EFITrK[e2BAr%[$+6X2I1%$A#B,qaB$JF)1j2$!Q'2jE"3f08 -F$K6f*Y80f1pb@#6X5a`1%[DI("D,"-Ra`F,ZcZ%3B5Ga1&6B"4`1%rC8$NZ%[B4 -$Pl"I8lf!IC4$Yl#rj0$MX&DVM9jKbcMd#EX[KhjKCh!Jrf!r`i&l`*l&B9$B+cN --#IY0$XZ&r5'(B@&rcf&%0%`0M`SM,f2#U'Pi"H`d$SF,JlU3!,YJ[(ZP-0ip,Zb -p($4['1ac(+JGX(rJF!q(cE'k28)BEcj5f$%FY+)ff)-ih&-BR(B[B5MYH`[l&I% -2f,Xir)5`6h&B*Ha[1Gc(BHh')p38'2A!Hm')q8PKQcM!,@$8Yq&-M6f*`fTKeh" -B)qaA1D`9pRi1a`NM"qZ%ICR$mF,qQF-*$XXE0jdSM$Ui[c$H$mq!8Am2%2C)$ZZ -&2Cf$m(,Hq1CNB@rNX%(Blh$B+1b21$a3f0q)Uk&I11"8BA!!q3HMERNl'(QR(X% -iRbi-h`KH!S2r(LcX&cM!b@$`heR#i$rY,4RXDa`HiV"1irL(#S-6caC'RIqd-(+ -a@GK@$Jm6pN`1j`MMhHF+qh81j`Rl!`i2&`B22F*KFde,R#m-6U6H`FJhY3E'qp% -bB*Gb)1GJcqG`S6#YNA*9BH4B*0jFUr[(#2Yh$[#frZDC(VKB'(a(2X'SHG&[mbb -2D"Q`bcJm6YM,1$aHf$XiA#)-[L%rB&rPm!5(c6I0*ZTZ[VhlLF,JBMJ0$&li1@( -NQ[H#`6'L31HMCA2R#H2Ge$[Blh0iQV!rim#GB0rNJ1l6h`'Qaki3KUjiKM#iN[S -&Jbr3&'$NlNTKe249`Yl*!Ii(q`+(j`Ml&`l2GGJ#dfES2M"U#am6$0jkRM"U$`i -(ibjU'Hak$Lm3pM%1,a6f&aaHj,#&TQPI,!`0"[H#S41S%6"iN!!k"D2Hb#(B,h( -i4@'r`3%Fl)XFIPRBIh"iZF-10$fTA8D$SCI31f$`1jS,$!j#8i04*km@KLkj9YM -[FEK1f*pcH)h$lQ,Fm&TKF2rVK&%hVaI'@hN,'&cj"Q(`!PS$M(T!Ai1pK30e"2C -"$R!Mf*pbH,1`Iq@!,Y$I)Y2Eh!Q'*RZV-26Bfi6"rI!j'2PqZc"b!"H"88[`!aJ -ak%%`Z2p'B@L1Gc[X)02Fla&'lUP(-,3VfKN-cBDH"81Ii&H!`F@r,3b1H*m`mSX -'"2Xi"r3A'(VV!`jEE"i(rJ-B@ThD")-,U4F`h[SKBA$kKi94Cam44QfJ0F#)KiI -"i#Ui5hm(QlBM$f$i#jm3KUlqT$"iN4S"3fqJ)m$J`8m,SjlaCm"iffH&iG1JmI9 -Rl*(2#d0R`-pJD$Mi$3bGL4F"KZC"Ni,"dAmX$,li%f(N&0i!qfX1H$Ak1p6m)l3 -9'2i&ZJ--(3krJD%K[b)-EB-Q!S-RU"%`Z!BI"ScD)*pJe#YFSEr$c)ILl@$`rGH -&8DrF!iC@`fF!3rrmR6#i'lm&$1j!Hi*4!rmS$*hd$BFY-6m!(!a[j9[#d)AI&JE -rrC-`p!pq!KKeJ`i#)jG`,"K[rMH(GGRld+&JF$aD!``[!1m,$)dU[QBAZXKCIPh -`MA-fZq!!*Iq[Le`VqAp,mH#-A`HQr5!PrfmT[SD5rlF8RDcNrbe&MbRjIdZT45A -rEbPmT16r,5AA5[jI0hkFN[rAM6qKj2peSe'8r,pZY,H5rpH0YP2brlVK-#ArVaX -19I,rZUPR*Iq[KcFVqAmpq!&+rPm2[+,Nrr93kdVqA`mk@FRrkd(M+IPr2@J2*Iq -["dj8m[pki!)PrkqAh#RjIlei2dVqAbqD3mRrkd8(+2Pr[@JGihq#D9j4m[pkd5G -+rPm[[+,Nrr95fdVqAamj8[,rqUaZa2rV`d[526m@dpk(N[rAKeCAm[rkd)T+rPm -IHNE*rqZ$6jAm[hlUA-RrkbFA5[jI2jTBbIrVakp4m[rki@-PrkrIkNEm[hjdQT, -reipQ82,rqZ&(*Ip[J"T@m[m'M'2%raZ`A)Vr0i$[Sq6r$H![+2Pr!qKE*Ip[!(f -Pj2m0S!H8r,pPF*!!mCE"G2dSqAr,L&IbrjEKCbRjIm[3CdVqhc,dQC,rYmab+Il -I-UY,mImS95ArEj!!'PEbr`D0Bm6r'm628[,r"Leri[m0@Lf+rcH)KP6br`E4+NV -qhj!!mBViId28YT,r0f3F,2lIN!$9Z[Kr3rJX5[lI%"k"N[mhC"`TrYq3!2'@q(r -,i8FPrfmjYDVNrbh(me$brjEM54P2(NcV5#ArElPa[2Krbp'@5[lIFV50N[mh$#m -VqAr$m)k5rcG-c5MjIm1FPIbrBE`L*Ip['%p(bImE0ViArfmBlDhNr`fM-jAm[f( -dNT,r0f*j&Ip[a,KIr,m4ic$ardE)YC,r0i*18[,r4[#jP2br%E`B*Ip[""p"bIm -E-6i6rfr%q%cm[e(dLC,r0fV[&[p[&-ib[3aJZMk9r,p4hUrNrihDZmAr'mAV8I, -r4ZhGi[q0SSH9r,maY*D5rcH'(P$brmC-2iRr0dDZPIbr-I`q*Ip[$,p*bImEXhS -5rfm-rDcNrkf`(N,areBBpiMrY`)18[,r9T!!4bArE`AHLC,rY`,r4FRr@f%e+[l -I#[5UN[ph1$V0G0Vj@6jm4Uhl1Z%@)i("Rk*1QUHU'qGTeSP$ej'fF)f'$dqkAmP -q54Y6EPpkXmbI`HHVPfKKBH$8rP*j89!F#Z+H(JQFk-[kc0V5&LMA*p@D9qYAe$F -90)2CjLAA3l6V@mbYSPA,Ac2[`C-[ZrG4idTm"A`'2!@m#V+$6i%riIU5m$2)$Gi -%rJ(H!Ti#IS2i$pk#Ve!K1Km,&aI2+,DALdN5*+fV3LQ*`RGQCiqrZ1eNTdV2h&- -Ij,Tp6raCC(mbAK0!X9BTKe'V're[l!%G2m,r-2r,q4rJIaRrJrchm*rR(cqbPrp -$q*r,rd,q&r!rTMBfbSd5T$aG@FV66%P5VT3Tj8Mj8XU8SpK!hS22N!#$*60PU9R -"raMr9!%15*lr3Ik(q&r1riK9K[l[iEqArlRmBqaSAYaHL)jFSka("%@98#&NRbS -Jqe3MP8"PL"(Q@IJJbC@@)2fr&+PK"B9`[rX[#S4)'-MR8QF#jblTk@bYaF&TS54 -ZT8JiUBCU@E49YDaG8*Je@mj*mFlS+qL8L)9GcqVY,)aV6NF!h5+ipEJXZ!3SGSS -I&i@1%aa[ZP(S3X'Y`FR"@F#"31QMr((,F1e`dh!b825i$*3$lK21'Xi0VJiZ$+i --MJe1#Ui*$JQZ%fSHJX!Ca*@%I&$[+(881Qi&cJ%CT"-'T`3h!&@2iNHj3c5SGP` -lh%1RSR!3F"4`)h'JF+G`VL!Ph%GF0BJ-K`rR$5'*HiGVKd1(@iEEKXZ''iH$KeZ -(#iJE#3(L!L)2B!HF90aA(&XF39a(FEK-jaTZ!Li#lJ'Z!@i"ML911FiVMLY1,T+ -&ML&F(K`Ah'!F@0`ih$PX1JJ9p`-(&MF,0pJT4T`Zh&L)$`FBT`rh$RF,p`UR#RF -,G`P(#JF',R*GX6K@Z-8i3M!+EK!Z%!ie*)m,M@X'Td,i1&ELYNjp[-`(d2rY!IP -d#A3@JRJim,[hY%02IFIbVHlTk8UP30[mVS9,5b[#)4YlFASIBVKT0`6e&qYPJZE -hGRI,A*9U2D&hb6KhUIh4,Iep)d(C9%"q3@GA"kAIS[2"1VIUh+EcS6SICQINC[L -LPLQ&U"l&8ERSGi@$F6%fLRF2QU0cqm5&V3F@"R69"B&a8BFZFGRSe(Q"cRI4Uh[ -YM*3A[%Ii`SR(YEh-mRY+N!"%Sh%TICh,j3'keEfbDq,@r%[YeN,k60ia%H612Yd -jAqH$,VpmM-,-rTZNZ0X@SaDT3fU11U3'U6[H6Jl*'f9&59%a9!Z93T8i9dPjBE% -FVT)RIHYhpUP*[CJH,[i2SCeG$f)[V"EVrhkqCE0Er,ViTP[(S$4G!L[9c5b&U&J -p!Q-2I!*M*E`(qX-dSZ`H&h0GlZZjar-2EK[PJ+K'`(2ZZ$lkmR&MB`qV,5!NaMX -5ja[lY-8cbkil[i$*G#[*'8q`j4h[#F#-aIAR@PBm!TmED9*iSHH'0(Cr2e+chS" -2SI*&PRSpT(QKC@55PUaU&U2eabElpeZ$*M-6ZfSf5h3@BlNDeXAE0Tf+VKF%`pZ -iD#i!ar["A0RlBMN&f1#Q+G(FF,Z"6mmbC[BYVim#c1Xef*HQ`aYMb1Sb1+J[V06 -+J@q'hQJbFQbY9P+hXIf)Xc+4U5DYeT@[ECXc0(h"Dr#T#8(C*&!1KrT0+FDVq5B -b`ZF'H[PR2Nf#KiS%eh5hrB8)GFckl54)F@pU`N##@P)b'kcFS9AkC,b#TC(Qq`S -G9IElJ3Lemd#B!m,m$qCq-%Z$H5(-r@$H"h-qQ$I#2"(QI+!NQ1["2!rQH$#rJlN -Gc1YJ6JIc1CL4`6`1jR!`Id22*@'H!A--Q&r!h!,Q)6$[J,N&c#YJ6J(c%TL(`*` -#jK-`Pi"j"-`KB2i!F`HB0m#F!HB,-&H!H3,BYm`2-(-9k"#LkiY1*,U$k,kLfiF -q%$V(k2M#'D#ML#ibZVVSfU)VLbiLZV,SHU,VL+i[h'XN,Te&VUX)Bi)Z*,UBk#b -M`icZ)VU9k&+LBiaj)F`*B6i)Fd'B0m)m%HD#k-B@8i,-)p(c4N`a``rdHfZKM'C -Q[JGc2CMR`4`2jRF`Yi0j(FcT-2-jQ1@KZmlS#kFIR$j`jKm`pi"j"m`jB(i#ma' -BFm"m!qBD-&q"IRCQ+0$,cR`$jKS`ci!j"X`[B'i"m`UB8m"m!ZB5-)q!136-(f$ -Z!2-B62mlR9p4&alGBR5)dBe("aaGI(54d6d@GI24FdhE$l1GQ1R%,#IQb6#lLCP -0c(YK4K1cQHJqBbi6mjLB`m6m*GG($'R5kH@D9qNqSk10VLmklHJBS9-0+8AI#je -rG0YKG*)re`j+4aVGE(6%dB9'4aNGINl-d5e(ee[D6JV0-Sq)186-(f,Z%21-Q&I -%h#(Q#6&RL*Nec$0LcK#cH*Mp`c`KjXX`2iLj3F`,BNi3mi'B#m3m)1B!-Ip(cdA -#M'9Z!2-#Q"2!I"AQUM"2K6NUc'GKrJTc9*LI`Y`8jVF`ii!C,F`hB(i+Fe1BPm+ -F&1DM-"H&H5M-3@(q#A02Q(I#R"2QQc$AK(N[CLB#(B"dcp%Y5$FPhB4`,af8G&R -5eBJ)drHElN2p"Y2C5"HNIS[TS-48eZmdAC4d-p+K5'FLABLZSe'rfA34dX9)Gk2 -1Nl'bG*k-UF6X,'CQ-5Z,Q8V-hQ+f&V0lQ"h&6#aQFc&lLjPBc#GLcK1cVjKja9` -VCP`afiUC9XbbBSB9XkZB@B93C-B*-d-dIc&$JGN*c-TJ4JDc-CL*`D`0CQN`%i0 -C'-c!B"B(mb#BYm%X#'CK-!1$f4I-['$@"6-ZQ'h"6!YQ@6$$JYN9c+aJ9J8c+TM -GBHC(d!9+ab-GS65Gd&P*Kb4GSR5mdZ0&TbAq)3iDRD"dQp+C5MFPhDGdU',,dHh -U[$KR`H'md8e,KbZGTFlfSiZ8VP2A9HSCq,4B[pCTH#h9M@GP@rC+VACa+ehBa0C -IV!j0Y-&Y+j8,a9*EVGCC$HZY*F-h"BN3(9N!36B-,JIF%Jj@H1li806!FTe9615 -(&dX"cmceGAB[@GU+-cYZk%5a2T+H6fr[(Dh@`dU3!)DYINYITprHZ%@RD+9KqN( -bG*HNmGK,4LD5[V%89@TK13b'I'F"QrcD-SLkp3T*M[cLm9TTa+ijZR9'Dc*5(Rq -XVS!YBDPB$k-Ulp9SP+U*!D'!'q2Jb35iYrBIkFqD[F+h5H@jVAkMlJ-ImiJXeLl -hk#X,QD)+p$@Q#R4@0[5PL+dRrBDJF)i[6TXC6TmpG&4l)dc+6-2pM@J6Z'TV)R5 -*MAP%pAG@DP&Fpm&c*aA,j5LUNX`Y0H10YG2EMcikMG6JaQ*5+TC6p*4JPFGjG9, -aPVCh,eL`p3dE1lE"mCZGal5U39Ip9&pbKbQ3!$!['Xm9HJDf`5ic!NTQ3-2AQq" -6Zf#@S",1(Um%'`I,(0I9PD**C4AL(9TN-Kf48S-1%Ec)GlARbeh4Lm2V5BZG'K! -5KG5*+4-E2,BM%cBUH&"%9cC8#%rZ-E4(-9V1,$q[8Vhf#@6*h)mfd1(k[H-h@f` -J0M4FL,9NJ'J*ll0&%Pa"IPCCbX-VB$eZG9a1YJ*j!)r'JBiaZG'NeG"H-@'m-!e -1#b)3"BDT,#HRr*c)+[XF$@a'3*bAP1+`9RF&%3B8hKcGiKiDaTKm2'VR69'@NNK -6AD@3!++Z3GQY@BKZdaHY@HKU2Z,H03ZG+MJRULC41@K0kU1$L@Qq4h(rL9dGC`6 -9HSTcr83aV)+jqpFXh%i5J9"EXp#S5h+`VVm$8CAH@G4%pNDja)!&2SSj-ATDN!! -3"mG+PSJ0E8q&b+@&E'eSQhKmjSkA!Y2FaIGEY*'pj+QQ!$HdZ3UN3$Hd5G#MrU" -2c6FAVD""b`DJ+L4Jl@K5MbVqQi1ccScLSF4V+m&3@j&&fdDJTXedrflcqi*k2D` -1*pk#N!$(6X!6"Pdc'TD(r)k9pELBH21$`G(Ki5$fhCdj*l,@TKUACaTBlpe`NA[ -)TKkHH&&3pMTlrHiD-N1hV9eXZY#Sf41#DSSG&bE@lR6KS$dKc#+3!&CVpL`l2&K -0+Dr5)V2`GV,YAJ8@[bSX"5$h'P%mpr#lLYAKd5)pd%%4(1%%Yhl0HA%UpA-RC)N -pbQmE'JSY5SY+%U[Td$rJhRJ"[dl-kjV-f2Y&66k,Q`+dpYc8%'fkk3TMQ(`!R`p -K`-UYmbDDDGdH@3cf#Zc@N6e@aVKkI6j24-0iar-c#hdURbqQdAP+d%`A"j6LfSh --4c-Gr@#&*R3G-(qm`Ae2%hS3d%+[M4d2i)'Td-8YlGhc1eVmP[PYr@dF0hDfpfX -BYLrPmm8-G-Qd[brLme1-&bJ(qAmqhm6SQhejr'%bY4-k88`2jh5X$1Z,k)fNXq# -@,2S)4KAFmY'R[IR2)f9m-jmEX-2r`N*3Mk-cJhK&iYYFR[kq9rIk4q9QA(G9EXC -TmjCdqlf,4V`Mr$ilV@NjI#i$!(6(mm"Y8`jIl!hl5paQ!e,V,BGr4mU`C90qlM8 -rp0DX@62qVqllp$*[bjBYfrjIbY$1#(rpq[92h((EIb@ReE[5YrXIrQrFX+&*`M[ -Gjir)1rc3L285m-2ZYmGpjD[85p9I#*25pTEc930KYGGD[D4$+`QqC2DX4Vp@&LR -0@PQJ2,FB+IfppDG+G0#qP85[Sj2Vd6Z[2$kUlRbM%3$ejdX05*GF%TcfhLA4F5G -H%KThhL@K8E0E&KQh[QAKeGU+fZ++q8Ykr#V"pFU5pVTLVB6GIeRN91V#cX!XN!! -q`A*8V9UM(X)N01iS6%,6,XNLAm3pNp%-JS3JimJL2mDa%6f@!U8-5R%ZhmRlLpa -B#3i+1!i@CSaM$$('%6%[9M-[&"E(TU`B"mHN'%I'R"K(4T4B#SaTT44G+DH)$j2 -%*A4BMUd9Nj!!B9)J)4H@!TXj#jQ`&!F4CN(9kSaS-)k-@6#16%N`SBDB!ph-J)6 -rJUJLp`9a%Hr&3C,`1-EPYI$@)YHPJ8&T"S(#F3&Zq#e!BfiVC94S+)K,15d)60U -YA96-C8&8a'0a8-`(F@4D'K&h&C+6m&Ba,LZ-`M3)5AV)9A&3,5mK4m8am&-58+U -ZL*H#U*L6JUL8M`TP((042%dP)D3NY-K+5A"%69PNd&kH"VS%&j03C+TUG_E4 -`9K*NL#X*LGQV9J2#2NP`bQ0*G%aQ5@M-D%PSdTkI4KDEpG2`DQe&,&I-Ad*ePH" -kC3RT&@XPC,iXFLTe)3GQJ4"K1DT@V4%P*U(&'3K4D%U14Ek)'G,aJBPD(bBl2C0 -iJ%2C&p1YeBqK6kXFqD$#MLJlR-*fC*I&Crc5c'L3!)GQJIUGF9$fc%!Fa%p-Y*i -m,`R56`X#XQFPC4@rV8c(mX"bT(jP%T8p0Chh8f,UdJ8a@CHL8iBSAC!!N!"%+6c -Qqe*d42R9i*JkUcHim5@9f'5)4j2qkr'"!XMLV3JSaF@PABU1UVX@2*N`9rkP`*X -C)0@4M3ZDkBlN669i4jQ')UFDLmkT"6E+)9BlTHKBm*5LL`+q&"pTq'T`)j9&ZdQ -')e8X(aHDQMiZVZaCZ0#5JqB#8k[)a4A0SLJXY@@Lf))a%d99dPXbMC,)b$B+)J2 -Mb%@NHX[&&49A(&C14UM&A%K9j,RJXKPB$+fNVqKc4@'0NNUmVLK+h+ii*%YXkRL -jZ*S2DfCD0Iec'ejcd'hXT)PV`qZY$$DijVrEf+S$A`LYqGQ&q064,N5@l'XTJES -6(d9RAVa%&pei'eAc(QaXeAd)3qY*+RN60Qc+",%A6(CYa1'0p&BE#`UKdk9BD5i -S4-EY"@&B,IQe&J-E@cHZDZb@aYFpb"UrTI%0ElM-F'P`cF@XFecPJT)GQ,&FU4B -DEQD9jdVKUD0CCVSdZ'C8PEQZ'Kcl@!ff5fpSfZ%e[L[&9chD1Z09,UJACZE8CU4 -AMUfiY@ADbfB9lR$dbZ4AMYrZkP8SX(a"dpR,L,!HhV505R4BMkik4&95R,bKCR[ -&e&L1E$Tp'8%f`UH59rAl'NaC[Q5ljeIMbmS9$Gq[cTVe1jSPA(Ar-[UXKGFG`$+ -*&LGc6MNM0VjZMGMJTMGLia[QL)fZZb-fZ'D2&',VSVa`38Q9&d)cr5fed,")S[# -bL5$KU8PL`qSZL3fZf54KE#09Q9&LikDG%RY$dbU*ibI6A$0,#V(E#l0UPa4#%lm -NM+YA3GdaXF%0bk6'Hk8,'UC*MIP+&dcD*QAZ+dAAMC-kqe9[b"4kaRpC88bD*e8 -'c1*,pNQC!d[4G31Pc)+ek-4#DI"JkBST%kA'K0N&04ZPcSA9'aTP@RC5-MUX"&H -pP$)KPNFRlh46bV4BZ@#(Re)KamS08ij+4T'0q#P"AL,+4RK0GeITXRP&h9L)5E- -51Z@XC03j'6qG`TUjdZ$3bLdll*8DNeE[Q$4BkRcDZ'5US'XH5dDXpIL'be+Qeh$ -JH,AVbF@@fTjFB+A[bF9QM8mZXY6jj!,6eUFSVY5S%`@(R6T4@05A%q3jDhp+3Z- -'SL#dd!$P3NSG8#i`EB'+ibSTLCUJA%bY#mT&9pUJLV(90+D08&(FC)%9@k'L-0F -,&FH8-ecUKR+"fefrG$*p'PqB4Cp'dYQhEQ8TF'2FTqJ`I@*9"`E2V%4ARaUP1(e -Lc*("dk+SkT25&&F'h+GhC!2[da[#!IKTD(8JIU8#+TQSh*0PSh*,Q*&+H$8V8I& -8XK(&CeQ)SX2A4f%HP18!@*!!9"qlmSe0Kq*aKLURlEIe2@ETdF)pE[9qZDK`$l[ -QV0je6r!iI3rlk"`cH3qljXbE[)GpG"C-hX0q1i[qQZr`([DT@E,V2E+2VVQ(!H[ -VXhYU%aje&,[BG%bqQheYmT2hX"01jq3pl*DcEGFp8AlB2@IVj$f-,6jrmKif%pJ -bH3mlm6cLZAX+K+5A3Y,I$+pjPHp"'$d@(RFci0ddkFGG(feJpkd$Y(1cTqel!U6 -JGPYf[(!TLerUAE-fD5Gj6p[h40YMYFJ,2`X[M)q0VG%qqckf6l6#V"HTldQmb2D -R[8Kp$elIFE[Z#4kRlm(V@cGj$hZ9(Gqi*rqd*kM[`41Fp4KPiFGCle$IJpFhkah -UHpJ4EGBle2IJ#FjkKrSH[,jC$drI`rjTXjkJ[JG2F0CMe2IJ#FjkPV)!Z0rE1r3 --h-1Zc2SiUAqF,Y6hQ!@%Eli(Mf*5*iAhi(h1REa(rc9l@F*ld-'c[6Ek(RBcR1a -j#HpKhm1ll,VR+42hQ*d3EmiM26lhHDlAaZ`JVAILZrNHGSkCeF(k(RU"'[SaHJp -l+6EdD(32ZbXfG'Cd$lXY0R4`G!pl,ckL`92eHr`V[1aY[XIT$E5D%e6S(5I#m1+ -F"mmZQDjrKrdSh3lHl(AUqMIB%p@Y@-XqU'K22RDPG([IX0FSHi6bXE-SZT12286 -4PRcXPqQfF'@A62T!qGMrdfh+`KkID%FqGQYP6e%qGN0&+j*HmXMHSQ$dIU)0`I" -S`F(`"p'#B1c-5Il"f0f5R8A"f1d5I3I'$UaS1$$f9@@(86"f`m4,"Q-I8raL-(E -Sj,eJl-3TbhBTbbApRQ$X#)[2#mBHX(LjB1bdLPp,HC*,2&N`FN%[*KMlIXUD5#f -fQbBq+aKE1-RQCbffRbYq+4JlZj*c-2BeCIp3-,C9N5hq@k`ILhe%`DK4pK)&Brp -2pK)&)jIX*`V'6UEX+3V'9LAN")apCYP&&)cpADN[k!@1J%r!U%0f&!8M[q`U#XD -ZR1`U#XDZRZ`X#XC1X1a"#XC1XZcA#FD58Y`*"XH`CbFBHkl+$NHYPM2CZl29pN@ -eDcARpV&pEGRM%i`pDf9[k$EM0AEr"+0ZU5m`mJ8rJ,%h+,Z#JV(p&,Z%JX%6a)+ -a)bXlKi+aZb[j"'0h9hB3"B2rf%88M0e+f888M"eBl@BaZ4IC$UZbIhkEm36V9i( -Th@AY,Y#DSZ&VmJ!'9mTDrh1-QeM'#J`ZB$p4-1U+RDc!b+2Cc8TMl'0V&VI5'$[ -IJS1a2bRlfB+aPbalfS+45fS6$*jJEeX`q*[pEm(Bca@p!!CR`dY15V!l,KJmcZk -iB15*hA$"U(2C3V[GmN4pJC%,mJ-'(l#c,KKl1V'l,KKmKMB"BaGDlJ&Mee9ff38 -M6qbd#dDHi%N`G[U9VH[E69[)2MejdcEXX3Z'CT!!hB$bPM-C!*!!0ck5lB2b9Y[ -S"6$UK$eh`6LMPF$Bk9E@$-lElVEX"`X'(m!KB2#"l##90kk9jHMcYNF`(!M'[Vb -bX&H(D5eU&JcG)P[TG*K1N!"qP!lMA23,',c'IUYJm!MD$BbDC,GI-(,0MVpJ[%( -k0cYXVecfr39$0m"eB1bCbaklB1`-bceJE*K(cX()+h`#aYkfl-%,aMl&l--,4Ym -Ah!j'MYQ29hqGPQ2fi`9$6l!R,aLDLRej`G"#l-X,4Ph#9f"`+hS0$)iMEck%6bZ -,dKU2hY8[AE(6`r,T,J%a0Aa[RpGQ+I9S-rYJ&pE`HhbBM$bjP,SIB(20R9qdP,V -eKLq6DrjNeI06j)Sr9Flkdq5H2efZq`YeIT(1,pEj*6TI,QIm#MR`ce$F-h9qPYj -lTI#Vp0jRkrh2dAZIUrGIVI22blPrRZkp4[FqAflp#p,hqLQfd2-FE05QYT!!pVP -0S,CQkepNqiD$f+hCA!q,2TZYf8)mq%raQELGmC@FcVkjJNIIG"jQFY9ibdaFqUj -EhR&lrVlr[NEqGpeAHAIMRY[VjTDDEEl$,lICTVrJfjp!8+YiKUeTAqjFI,"$QXI -e*Y"$EKTQiB09`cBBqB*5dcCL326+6!'Qm@NqZ,$B[)d,LR``ar("U[U+fDdcQVI -*"-F(fMmiD"XI'*RJHH1$aG[ii**b10L866H'I(!`h6&UcS4VI@UGrCShad1-3RK -BA)c2QP2Skr,Edj-HNl#U,aU05d(6-Fi)rB01a`GQ)-DTSl9D&0IR,!U+3d'F0&- -6#Si2Y0qXRZ)$U``Z#*US-8,)"bhrd)YV`QSc-hB)rB2fIrS(HS@F#k2UR*l4`A* -BmMZVTI,S8*-`%4(b3IjIIT+2M!`52ZK`I[-jE)qdZGkmV88Tj)01p4p-4(&JZfG -YpBpVRGPk3V-eCJMjB#jkFGk8j`B`GVR*8RGqM$YGADXe!4K[acXQ#PfD8Y[mY1$ -YlkbBBdTQDhG-p(4THZfqGjcHVZQiGqEeP,lHA5qmp4fE1TEfY`k1H+8NQH(PrRL -qGf#[TXIUVf041JPd6E&FMU+U[bJS0kCQU0mpP',UbN[@fGQm3fE30Vk*!GrYK$C -C(HiGKf[DmSrIX5-Krr11(F0#r[FGfaqbpahRVDajdeI0Fr9kr6dMB`r2baZqq'j -QJepkMFFDD,Cq6dKVHA1b`LIHeZ[A0kHcdF`lC1l[$r*K4LAcMTfc923lC)ZfCQ, -Y1r3#Fjk!Gjbc*l-cH@AFVh[(0"2YIFI11E@ZA+FrmikYhXKZRVCV`H95SRDK+8q -IdGkp9mG`ar(2+TPcSj)Q-rrIKrki1)QI93flhl&eT+aTf-e2VeFhUmqfeNHE",b -$Ej`Lq9&H'9XZLM[FbUriq6m8YmjXlBlE&(Ic(Gi!aEhKT-AD3k$j6I3-l-f(jd1 -j6fEe0Z8qqiipbRhf(AZ8qdh[f+hFCpiaSpcGR#arJ(+[jq0lbVfCf&Z9qm`lpLM -hqM1qUpaRhV&6ZHYhc)ThUpc2'rjIhAXr&,IH6,9faff+Hr)GI*i!aDdAT$rbH(p -LdrRLerQmBY,[f-i-he&-XqrBSh4ZHXGZT62cMZm`HIdGhfAbQAIX*$hp$V-Br`a -$M$1)BcSqG#5Q+N5rip'$fUkLpQdBA,lh(Cf&CrGJk#J8fV9EajhIIc1HhS@85Vc -T(9[qTKAe1lD`1QPKNG&k4CmED*q0IARGTaN#,Ee6Nqppa`aclUbcS$kf032BUA0 -H1ZjcLQ-@T1lM$8IHJDXdk8*9[S),pE*e$II4#r#1YH8NmD!B65#6lp"F6ejcZhe -biaTk!I*Kh$i[`$ZFfcIpMVeZhrRe5YRV@Z[HF3@EQl6XQem+IXMT-r*6hl(*qeP -qeJ9rk2TUhYpXQjcS68d1[*ripqCRRA0qIZTjk6BcjKf2Y#TUjQ0ARBR,FN(YQAV -&BM&%0281jYAQE+c[[VSh,SXAS&k0bq)&H!HIT61p4Fi2mfVHSFXMpprk1$QUDU1 -B4J)R#Me0!2BbBAlQM26)6@dqdIQ`Y[[LCl`TqlNDQrk-K[%#[11NjI&TVIcr++q -S8Rp&cq,d9p&#k9I33RI@4d%,h9Q[rS"H-D1&p[%($(aQ@0[EJE-VVri*jjT200A -rjp@mBqFNq9h[Q'RabKhDr+h(DrVEUh6m5MeHqcl28SrABfTle1P-ARd%AGkk9fc -Ij`(T&DX6b(Gla5DCfKI3+aDZ&9ql*0pm3VPl+T5T&i!jr3T-YHZEh96-rq(TH&` -Qj8ar(J)[aJmd+@IIjeQDP,2ALkNpa%X`F@Il*a0hYRrqVBNl-qhrZ5R0+[VrpbJ -irmBFJHmSVrSl[UHmQJQj9AR0[--l-4pKVr+U2F3[-'I"[Z1m2AA')r4-8LX+TZl -a!bJ#m`k[a0b(F21JMR3cL2hpKmf$&MfjHC!!MqfEh%6*EKlNHpY%b6HhHC!!E!k -bAm@aHC!!hYPiGNDQpr4EZk!!q9hVGV[ADphVlHjp+`AJMCYaX*pUYSA@h"FU%&Y -SHGliS,+&PSIYblE3fJp!f$V+RlDP@ZF,'BSYY+EQ+AP22leePYipkp54S0adCIX -XphRAYp!k+4[UdV%qaDVE,EcSLK46IC[AfYR$0&[[icHZhVV6M$)mfN+V0jFEhfP -'EETT#[%hj$EG[#ahb8%c'qr`I'fKPI&dG3ZY)NrlcEI3mL)SGcr3KJ,6bTe2P,Z -ki1"P63#8ZepU#kepGEpIbl#&eZEU,EK+Nbj8j5Zi8&pHfh!I[3$[b,E3bYj4hED -Tk)SCep!,N!!2irCj!Gi4E+%epBkpETrC[1M02GN@@ZV#h(I"p4CDDZh'QVFqGqh -G0heqG@lGL8BQHJZYK9ALRjblpXljZE8rjEjSmk*Q2RE9@ED&9[D1kKCDaAGN@fM -GN3rMXRJ"kY@i,&k!Gr!P@fMGN9IcMRJ,V6[HXCpSXi9@#fR48eR0cr[b,@jTljl -IdH+hc'rVEq1iXE1p[k@j5J&iB6M!%r2jCeM!AmZ,2V[[B1B2m[RRP*-qmaH4JJC -p0"cKje@DrJc5p2pT)CqNP[EaZK5j8mlh['1m5P,Id3[HIJ3V@ckCZ1,mPD1Bjpp -ZF4GYMe2(FaJPlS,YFIFjKL8!j(fY$f4a,er+!#&jAa6AYjJ@8(PI&$IR-!jcDc& -cX9Xf[XBHE10DhXKKb-AGD0-+@T52EfIhV9`#eUVlk(5paX8pqe0JHK8S%rG0$LH -jZ([rb4iXlkC2pHiZlNSEV-#@a-3aH96ZZriVB*fU'jUb&lZi*3H$X8mack3M@[, -a&GYjS%pjHQD@[hXH#bBcqY6EX[ZZ[KGX`-@ehTEPla0hJ#h6IESZA6iZHKb-'Z( -G0#p,rUkq#QaBF6GNphhm&M"T,'el*-[I*BD0ZELZ6eTZ,U`RaJG5BhbA`arYmbV -eG%j2'0HpN!#$MYX5EBqEBqmqN!$li)N`VX9U3[*pejq!(D1mXZ@,e-IEhJ0'[I1 -1"GPpChd#l&JAG`rV&jIkH,jaK&PG@0rhJ5cI(lS5E,AULIG)IEc+FL*cH9U0hq5 -qcli6E*hLhT(9aaZXdjXmNkI4,"qIlJ3lbm80fp4FbGq#G@!rT6U$Eq@qDeV"(U, -m[5I,hcEMPBIU(F4*2VUY[Xp@hA#3!2ce@4e,*rF)fffjqjjNr#'GiL-rb2,h*EJ -fTq&H9hf$1PjIU3r[i114Ar('ZeCU#E84a3hb(V@kTbZTHrQ$V)BZGA&,M#G%"d6 -hGIf#`bZSHcVI`lTIbVYcbm3V`VPmem#M!Dq%FGh[RAK(&(IN"+q%F6f[jh#dH#L --'lQa8CHYFbm#)fr8'H0-T5j[-1kleX8pd1k`GGPkLR%6fN&rpcFp)(Af6Y-FVh& -aiarJX,'5l15jZjNHF(&4RY!ZMPrEXlLAd+5Ihdpe%-Eef2[HUMS)ihU0ee`GK(( -,dA1jZDU$-'l#*PqlI)4a5daRG+9jlCMk8@SGAD1r'p%ahEpfFIG#NkLT,Zkklh( -pr$3ZIr9Ma#ebFCp$jaejNEZ[l4A%(H6L"Vi&PRIhIH-8-,35lriUKm2FIDGpN6K -pTq&,H0$@CFGKD$Ee5Yf(9P[JiZkhJEK$AGb+3m(DhIXqmeN`2HRGm0"mU`0lhq& -h%EG%FHb5B0q4Ir`KiVTFh1'@ibqiqp4R`25lM*j!4dQqRiIf9DC2NA@Fapep$rX -FF6dZlJCQG,3jRXK[SFl8Ur31G(1ELhYh,h'L#jIGD9aZhh%kR+'N#eI#alRC,Zl -i!iJ6A6Ki-SF$A&cR'F5*,Zbb1-[hqIY[*djdBCG0DT!!HMUC@PI'$r!%ifrHlq, -QSF28DehF%Ge@3rBG(riDQ1M))ffHifYGh&[3B8SkXXX'9pJkb$q'9MEk5"rIm5" -dD1ZQSr0X!Tbq4!F)hh6!LmVT-'8jF(ac00T*14fQTP'lMQmq$cFU0iG)YIiSijY -HhU#Ncqk'(R0mmd@cU@9hL0kh0[JQr`!k6jPf)aAk(Diq9U,9P'NPH*Im#YqXXcc -*&-B6m$Q%EcS1J918jYreEXcijYk@l`R&`EIbMP8I)qjNk3Ni`2*0rL2'SlVZc(f -2crMQdqKATH%GieXb[PQ%PP1@6rfp(Ai4[ZNidAK)[m[`$IN3[[N'QP2e53paVq@ -Er+eS(GA[iSkb1KDq1GIi!bm&R85mm-f+$a%(cj!!*rMBmNh(kXZ)1edklpPC2Dd -R"`TG`(IA4aYmNlmHEDI3!R`2X(S5(I"!0+[a3j!!ZZKEbcFGCE5('YICm*I8`4( -i(%SkHq+HM'm@QMi3R6eSHY(b6Ilf,a&RGEDb)AM#0rRISl'8dpRUA2)PI00a#$@ -Xh,"YG3(qK2"0rTYI)%$'BDmhlK'qqG`[l@%fEXLdZr$0ZfmJ6R4jRqNPUBrchbA -I!cj'r`K2('Bk5I6k"[5dijZ6H*25*2aaibIKQc'i8QRHk[!(XhFFJrC9QY"c#RV -&mFhVb+Q5IcImmBa[[[CYiQ5bbp)2Claq,Ck0dPB!Tl&'Qp-hhrSYFH)EYTh6i*Z -13dfhb85a%dhhL,ijbh)TIQ+[k@c,0rR,,+rS9I3pHX2b6Ai62Tc5c+2KUc0pmdV -HUNkA6X)lNAUkZp@Cq*ZRQNBA[[NNRU$5**ihh*IacIRN9'R`cK[KB+G[[[PpiQ5 -5d)QACRA`((`1KHELHbYFi[KQ,MP9aY[kq#kmY*EpdVMF!A#Y@ZRL2[BkI*)MA0` -TF+L5Mc*NRShPTe`!KbNhe%hG!NqiGkc%%e*S#Z,HLejelhMS&343Gk3)IT&hh0I -d%ek@2Vi2IH,Hm5UV!mdja(d!2mqpil2fMXY86ar-hR'9m3Hq)[a+r2`+Xb%,hJ( -IQma2q95PZ'0qTlS9hD#FAj@l$Up#R5HGXC!!`bBApfSdZRUhLpZ)&XpGkZ+10Cf -("kL2lm&6890Fh0IH!+Ec4Yb(M-2NI9Y0cehZhV'*ZV6[ZfcX%E`$GD',ZplU80j -hlFh%i5rTiiIa4GclPTM1`kI9airJiERhhGGbq5cTHh`&bGp4q,,+H%`I2iL(iGk -h$8fThZrL2QUEDFMl6[S0'2SSphm!G`)!!!%!N!0AHJ!!9RS!!!*kEf`l$3N*CR- -ZF'&b583J25!UC'Pb1`d*#8jKE@9$Eh!50#i`)&0PE'BY4AKdFQ&MG'pbFJ)!N!0 -"8&"-2j!%!!""8&"-2j!%)!$rN!3!N"+Xp[d9!*!'@I3*#3d*#5TfEf`J25"QFbj -f8Q9Q6R9Y1`d*#5TNDA)J25"QFbj`BA**4$X0#3P1B@eP3fp`H5KQFbjZB@eP,'j -KE@8T1`d*#3d*#5ThBA0'EfaNCA*"E'PKFb!p)'Pc4QpXC'9b1`d*#3d*#A*PG(9 -bEL"bCA0eE(3l$3Pp$3N0#5Th!!!#L%&%3e)$!!-S$9d,iCE!0Qd2b6Z[IH9Ehp5 -Ue9CEkEAkC*9FPqJ9+UeD(CpNDpA*@5)i3-Q)R'5k55HY1-"hcYF,r!1f#E,M5[U -MC@C+a!jlH+aC@B3V[%icXLX@fR,DNr0`SMITBMNC8cDC6Z*'D,'pk"KZJpfp@@Y -N0fce%Me#6X-#1je1j30JAcZ3!!lQ+MM%ppFL13@,l3`kNiq#Xra)29V1aZ2p8$e --6X$$l9JkMKI#GRp!ljGYH)IYT+em*paYXfN1h`AcrADp66EM8cD0CR)dR2%&qSc --`1RqK$iT8r%HQd[cZ"kHY4l823UZ0RLjRL2VFBIRp%(CJ[IC4YV%pd*IreFIPcl -iY(@PE[`Sl'hl8'rq(IEcAE4D$X)KIUZ@bRMmhLE5"2iFIVC40*TrJM&HU6r)*&a -MlDNGr`LGr#[p@MVJ5&qYUk3cVV@a0)lA34GE5X[i1hM(rpDrj$emhrr6A[)FrQm -Id,[m$hcUYIUPI),If"+DaGp#2rZB2Z-'k1NVp3[TL1IC#r3+A`5[qX9kSEb-Jra -'[88'i`hf%Ah)em-)[dU[PQ&iV8fKSA`Gh'3$D6KI!rhpCLf6!ILDAk+AbZYiZEe -*Er%9F,kp5-rcZI#5Ak#Ab4Y4q[3RrF'2`GYqT6iN[q#[rV!q)VmK'T-`3"4Cj"V -@eLC8PNBMkcLAbb96p2B`aCDaP&9&U@-[5hXk6QI5UA49HN(DD[*0fCDk4QmZA"b -hC9*QKDeY8Bq9e54!3"2#XdXQSE`ZSEJ`S5P3&#J)Y)Ab`R#S$SIkd&B5D'e1lV3 -f*HZ5PSJk56D-!bP*#TP!2[bb3,EL8QK,"6+"jSS2"5`IY[4X3MD3!)N6iRa#69) -'!*!$,d&%3e)$!!"@$8X$RHJ'ApX&YA!,!-!YrkSA!!$3@iYDH!'Kj[m$@)8Habq -AC[SF!*!'*lp"4%05!`!rmJp9$AC'!4!aiqGMIjYcMV()-TE9'U0IM"@MlZFhK%X -0M$Q(cV&kM"'6f&`D[K#b%A#b!`R2br85Na)aK#$0iD9FNLE'pSA*#4a,Z66Aaq2 -4A%Sje-FeP%XTKkD%BiLe3#RJ!((Ipr[[lr[QCJkplE[hrI`('k5R+%%3*%%52*% -"I!+Dpk1@k$81XCK2KMmBkh)ImdEZFT0$AjL%ESQ#Q[A"f+5lUd1X8%03`%TJXZ0 -G8#P3K%U%iPa9heDKjeeZFCT8f%RNL[a%6Xl(Kq@H#NEkblD+H`kJd#!9&R6m19E -#N!"@#`8L1LLBQkT*bA,EbTI8INfUkU#1afYrX(Z[U%d8m(MZKZ%5'MEBDhm3C0i -JK)p5BU8akQ"S@![63Pml6kiTHVpAihr2j32Lf+fkG@ZlZ2qbbrfRcfYiFSC,bG5 -Y8d[GbakZ`C*!PqQbISC,9cUh[kq,Qp3XJ@&0&dqqhqhq(hIamEjq6RGIeV6GIBq -pj1,qPhCcdd[G20RajrS$`9R3X$UYkqliY"IALYEQ6KjA1h*[iHHed5N0*R[[V!i -NhcQ&U81EjPqfE9TdZ9HB2YR2ihfK63fRECZq21eb,hd!JqT8iV&%8@1[1[8Q"(U -mB&C#-Z4L!dNfeDUT$R9UF**EDh0$am8D%VjcI3Bl(HC)AEh(&bT[R-U`MaT@Jph -SYKeETNk06r)iPN6GqD*Sf))1(1bLli`H9iDUf$lE2P[YrafP#h@UQh(Y)eAQU!L -"dYE4-rA'5f-6,@jF-Qe%FM+L3VJ20NjCD2[LY!M#e4HMHX0pp*'1e"CVaQ'`l%a -NBCU5(l-J1fM"hCpL`8$3JXIql3+aM&$4Hci))BmbK)3b8IXe[G)kX8DXmGE#9&M -+5leI#B-maQ2H"K3Xh1,p5L*fe2eSD8VFMHJJ,'U-N9kHY$IM&A@14GXKc1b`Hlk -a#dE#'"h5B*,%,2(+4)Bb"DC5Ha+[)UFl$+3fh58MPq2TKVX`,*Ffh(9Z5fmH6'* -kV36NJGU[XHe(eBR)*"IjkhBV*CH*BS&Sc6Z#@4$*j$*aR`5JE-J6C6Ipj21m0$X -JhJ(&3pi1JdT0KrXQ%UFk2KPJ`VB,"cZ,'"TZmZ(lPR9cGr$a4m0KCXk*TNYKFSp -YHhhhRQ0,4l28MU&5Yd'*'I5aqTrc4RhL6FjhV[TCfdHr%IGq0&dXBm`2Mikc4%, -+@0*N,QQb[)%-qeJ+-%*D`qVDc`fVFC523&LG+9bj#Y#X0$9Ui43UG*CT1*UeZ$- -F$A'rYYPZ6BHdUY$*Y4Tq)8-aGJ&aY'VER[)M13EffUT"Na`H$cDX3T@*GS,X08Z -"CB0,'qRUekSEZVA*YMhDbLkheN3,(9Yc&$4Q-14,NpdlLXR5TB0q3RQIrN+'IDR -`b5[G0QfPm0'CPb*#")P`%e"+4ZV'kRakDTVYa6dZ0+%Prkm&#-&!I"N-DG'NMce -bMIHiTM)8,Si3q[-$J5YPmE@i8MYGLDH6Jc$mLKi'SNEij!B')[YiVD9UbRj-DG0 -1[I'i'*K'!T*0Y$1`(BE&`Z(N'&8F"N6`Z(-S%G,''V#KcX`0"D*)KeKq*2GM*E+ -K9rK`Q(+8`"Df2d,Ej0`Af*!!0%-d""9Lh'Vi%L%'#LqX9cXFhmY4*SpAS4&M)`E -+)JL)i2AD"&H4I)(XkdYI1mk(IPL!6"35#,a@i(MZe8,H"d,$!8*94Z-S*BVF#+$ -U[H0)p#,f2X1rJ$J5[Le6M#a%jGIcYS$XYr,iXcbdKC(G3Q$fUGmKST5B)N(k2K) -L(V39,*!!!15+8"J+5V)4'G%bL'$'UYdM6b%m8d5NaGX18lL%KTpj[R"peE$L++d -DlUXDpMRmUH(c!4,V(899``%5BijNeA#!4"5Ek8#QP,C5hSp-d"F@e2PQ3jiX'qD -,qILjGK$!Liqdl4Ah)l"e`f'%dRF5Ri@14)kbKYZ6L9))T%24-2H,C441`DF(`TL -d-03V[S2N*jXYf4TBBMN+BHf'I'!b,*l%0$(mH0L56,$k(DU3!0%X,G3*FKi3'3Y -eLhfXH`X4!ZReSrjd*&f+T!hCc,b%e"8,AcdFFXZ($0qUr8TU),,5NA%NbL0eeYP -pif-VZ+Af+erhKBa,h(,6B%rV$#2G(GkR$akADkj4Q'm00Aid1*MPE@CS`#dU)B% -MfRKL9"rjGpSdTkGcXpSrh,rlMcbZ3rM#[Icq1h-I8)cYQeAAX)Z'ep,`RqlrHXB -$1-bMIrd04*+P40V9dqmDI19Qe$XqG&b0fa&98hY#%r*H3eMH!pBbA*JI[-RpFS8 -b1T3Rm[kM!mQ%Y5&2VR!f2iY`XlcRi"PZN[FVaKk`$i"Gl8q%j6)NSrj,XhdJBqq -NL3M-`E#mAjV)3arTX,bhkVLF3)"Q&8-0mq8$GM@5ar@bA&L[jXQ(3&"f,lXrZr( -NX(ji[V`A8mRi16V`ZHT#je%f'4HhTG#pThGPRPacLF[,-F@Ke"3e6fSZePkQT*Q -)jMk&N!#XP$c*9`MCd*!!NY(FBc"5`c`)0GZbPa)STi*0K@%EQaHR`18J"F$U,1q -Yj3MD%YV'R(d4&`*2fha'CjJYeSN)I&NDf2,@l5jAeR+@H"9KLbGad1mj6#'p21q -J5clY"[$8i&X!3R0,fekj"JKd!S9(@(+I*hpLKb#T0"ZfJ$8A@EI)qi2-FF0mq33 -Y*mEFMk('RY#0'lB!kHb'e835a#CUrkSC*p5Vr@S`UrBd8kSQ*MV!R-X#[jbIa-F -rq)kM35QQJ1l3fGXFE'MQRilk2V6I&$iL03Xrc,ZJ@LN`j25icj!!bJ0NAS6NcUS -ZiRiS'4Ui"85MIXkG-2A'r(-JVXF`e(Kp50pIaZ11q*`5CGjfZVBkYU,V0#P2&!l -f&6Rp!2AbB,,f0!AS@`m%+3FHk9KM`V(bq$K,[19Y8R*mQTRf&l&-h)"AXcJ23h% -44bUHTLc,$!N3mk"dH+9&FD"l+eZLJZdL%TK1PX#%m4QR")BP+pP1[d08aX!XN!# -IcdLUM'3m-9pX##,C(#VijlEGCm@5N!"02#V'S#l24!EH54Rpr$2f2+",#EE3Md) -P3UlImhS-pb&6MR6hT(@f5lHIS!j#*pT%m9"#YpRSp@#k'`"YP%hHb5l9I4$0QTK -!Pj'3!)4e&50"baHc$IHaaF@%Q!k6pbNb,80KjjCZTXUr4U!m9rM-HIU%`m8%a') -N&46J&&Y5)!QUD!Kr`R!bj[@`j8m4HI`$&F@j#9e@dZY*63k`XL&FhA#3!),AR"2 -qFB$`q6m4N!#C3B$-C@3`P0`D!%)!d(RqL8)"%!+`DYKfr[QdV["5(SNX-6VXK#k -q)m8!FQMk)-lNPeE394+kTlmPG@)5NcmeVI!aPF%%RjBQRj9"M)H%$fRc#p0C%)$ -c,BQfLL-m0j6l[0Y@2HE0mmVN$##+kRMZYPTVED+f"HVPIr&1j+l*A@1`-j%'dir -8*9YIc"0r8Gj)+1%mVkSBVKLTbh)JJdD"L"EaGdi@,RGBAY5A[dX(k-blG8jLmff -AEGC)AH[bK'iVhk![hi@I-P+(b[FDE18l0a6`52QqNESM2Q6hJS!5YF'QM4fZJ!U -Q(LkMB6M$',[e'r6DT-'QM6#Q,'a@5$X'pBf!G!cU*TYVIiGX3pY4+!hjDhm(Yje -EdQHdpRFrq&Yh&TCj62U5%V[TQL9!''Lm#kTIc'(XdQZ0KXAP0EiXTj@TD3R@$&Z -"2&Tlj-dDEM%C(5Di5m#4JlF,kKUIj*b5#--@8ZSTF8MVB&Q!FKTe)V'49$Va"T* -mZ&)B`Z,AKY$KbLk%BEE'S'lD$PH3!-*jZ%bViVU4&p(%D6I$D(!%kZBK8MVAjIV -d!aP1AUT9EFHmEpUd8AkGLQd9@jB3f$L@9SH(3'G+TQN38kmVp1QRD0%l)h9KE'f -XPCC%ER,,PKCR+j3i*hjZN[VVYXN3K*i+Al-J'B9"q4TR`rPEBaLZMj!!NPmjNI' -m!9F*D5ZK*$r8Z!cCl,F1IfiBcE%IcN@f6@iFma`NKG8qr85'diUK%@QSJSEXrQp -L-5ArCkGke%'Gb8)L0E'3!"Jp2%mJ$M-E('YH(Mr4YJ#,#Z11F4L9jlbS"cKj0)f -f%Nh"`SQ-)%+F#1hHFeJ@&"pe+LHFJ-&"-(3Np@)2`NF($KE`E@5@`Bq4b#!,fJl -)K2DeCEl3!GNCTd-rA!Qe,FpY1h`%2hX(3j[3J+[c-29#A!I*r(!%Qh6N-,Nq[8r -$)h8[9!0ajM#4!8Z#d60L-h4V%fKZ-qdH*X4K'hqp8jJ'`KJNi0Ym68JElS5iN!$ -2frhNR)1IDA$QmU@,e*!!20#i@*jUI1`X'8`AFpqd%J`U',``Y`4ESXS@Cc-fe8" -Eh6`'iHFc#'0*fHHX'f4UAR-FJr0pa8Kd6bqmH'ZYkMrj"`5YLN$-N!$Q`P%QFe, -('K!fr9Mmkli!S*DhI,h1YqLkkG$K)i1K`h$kDVh'",@i8fhDmFZEK+ba3e)hYic -4J3P#P#1CSa#`X6N#@PT-,(X$aCXI6d2TH0S4AVcaHZh`50hQkHN3LNqKDcU&BA! -NR$IkN!"KS#)XmIADNiD3!&P@M-,'%1UU,a2!CRNL!iX+KR&3Xh"3XdT#EH)RdQ& -jQS*U,#-3P625SH(i)f90@9km,&eMY'R(NB[XNM'Kfak9%'HE`p')F!pY%'XqJTE -%YT'5#H6l"0HX(#!aG46Al-6R!XU5'flbkpSSblJir+j1GY8)3jUl)h9l)aFb)+! -%LE5P6*!!JQ1$XG8BcB)"*KTTKhKAk&cMbcUe$80qChXNbE2XSc$**,P&BMMMp2M -DZH98$-0qER(5F"B+ULpNVT%QK!PhMqj#"LAEKbYIe*YV*$2,Rf2,#!"I[ZR1UH' -%MTrm[Q[BMF+(UedrAf+2NBNk-ClHQRYb%!DpN9I95p6JFFZ`@dQ@VYX-MdKma[E -TcqS0!amY%@ZfVB!4-0mdrj8#8BBE&4PiYYS02TMPmP3-LYc%TNUm3SkPq0JmI'B -)(bCZ8PS0cl!P*M$(l&%-qc'F4+%84T0RZ$r5adf@G&imeQG*pqMAkAN@)pBFlH2 -qcF2fj$SL'ShN$iUQ1eH&ckfa2Y-Bh%6rfcBGpcHSprd($2&YVl6aZ+r2p2Y6pGB -qbdEFB8F%aM"R()$2AAF64rId+rQQ''rfjCGUEGfBZKR,G3El4eLZI[TQIRb!ecZ -L1BTck-fEI$hhj'3j-eqibGrLL4F+qRY@IBHh1LcS6VjbNhYB+15+ZQViq)9205[ -+,Skm5eZY-QI$eDid1ARah-AIGrhXchB)+ccb`@*bpKc19NCKBPq6d*9p0)cKHDI -Y5GpTZeA4lUlQkUmDBI`RYK)$JZNm0[+NHK`CT"(X2FVHfdqF1irf5E%ppra0&'k -GrkrREk13!1diG`N44Ik*dr'ULX*lrh4,T8,&UDZh8,"N2[Gbi5N8$$BE-9KZRA[ -14SAX3T5S`+8r)-iM`pKLKcrb$(m9,X$@b$0)mD*1IipH5FEk)Mqr8)+-S+!4Ka- -LL[HL!@"EKJmI0Y&[5G[lT%eEVhjk&1EjBeX5h`Ul)rVaHVXRSKqXYmI`kS2j86r -H"mGD##HB0Zi!1MK+#@e"LJXERGHDd0&4$V'Mr*I5e5kKX9L3!1e-BJPANM3!Gd3 -ZcaD3!)&lKYh@HMZACmhM6Zh[rd10SR-H3qCNPVmSZK@K))BHRLES%5AdL%hb,," -I&&$4jU'V4Ai@`Bcf#&kP0[pC[3#JV!3$jXd!B(f@k)*XHjbF&VR(Qk'1JfhY6`i -")FY&KLq43h'XhUf2rG#(%)bp'DqNhImMR4,,e5N4iI0Y(3*%ZMM!'3GDU-I*r@@ -N%FV*E+!Y%!D1SA!YiR&#Q+N-eV9-rI3&U0EFbKJmZ4q$SARN5D"V"S%63qM*kFr -j@$'pr6%5am#3!"&$aU#KT#-V4e(mMUbhP5D-F6$'Q`a&-"5K)8T++*3%%A%[%2M -6N8BFaMJ3)fQkidcQ2KJ'%cPjKe2-%l82i5$m`pP)LU,K$b9Re%qCZ[!8#@beZFJ -@%F2VkVKp''lT%iPk"$5MGXmmr98%CFqffC1aqRHA+GTBV%HI'djP'aa$5cS,!NC --I2c"$&,((C`F5N8MM1iJ#!&X(h2(K)#"d+BaM2!j,4D1pkklYhrUhNml5%N8@d) -N&MjqN!$F4ID&5(#T#5BT0a`mcUh5iMJY2KYBA*c1`N+2q!i@@X@&M04TU*1jca+ -j$eMJ-SH4+jE)[F-!M!,!p`"B23"l4#)H)q+I6[52p,L#L"XCm4JM(K')`qM8P1K -E!P'SJ'qVIa(q3G`64,ajT2%"ZV4VeBMV8q(D%[Pp),HI!GVN)-f2-k)a!,U,$T3 -18MV3#SRiNL$LS(eIGaAa#R)#V!qc`%3F"XCQ'&@XNAbdI@rCeP-@qm!&dE@#13* -R#Sl!05X3EUeSq0"ZI$"MN!!C!mIphN`F[4%+F#-6E(F&ZJ4AGlP%-qk-B$K-Rc@ -c0H034U*`r[eI8%`qH6#$`XYJ28)"$&`*$-iVM2f)&0Bi))5[j+2S8S3&0!@Bbc# -8q@#''XPpN!$#e)0mh&qlp1"a!U,f(c6M$K-F%Jii2G)LFQB2XdRQpBdVXF!``1V -T!eK1NmErjYrL%-R&AGc)A"CR"Y$aT,$Yr@GGUcVkHcXHl1I-p0qRdd9QU%Rh-JT -Z9Jp2ZNR*RMMra-ZN[0EQKXG(1kj`YAGS)YqL&2VmpQM-kLkTd#[q@+Dlj2D1jGc -R[fpTYppA#TAL$GfS#V(M-[Im5@"4`T&5[Q2lE$-#E&((TXC5'S!,RU[`6PG(GGq -UACBf&(453EpU&ip"K0aFh8fL9+PBlF+`6qSHN3Sp%Y[6eIF5ffDaHJ$$&k4Z45V -FNYLDUfm5fcUaqJb'mk6ZFe,KGY@89k3T#c"F)R9IP!VCM1@'a(+(QC!!"&0p&Sb -Vj1`GSDDjjh8Nekr$058kV,I#FELRPlS`''[S,Cb"KMiD&*UaEE`MK)XqcJi%(5L -,D')8K(0DQG)-pCRI%04RT4iG1j`80SY')Clb)JTP34aI,T!!K8%BM0lcETYjP[I -lJb%%Q'SDEHBjU*!!mHqDN!"jfRXfmdbB'M#apmE+ii@Gp'(Hllhah['JiH6Cd-B -lbPjdPG%J%X6-L3c@I4(6`-(!dS2"p`'@MKe"039Zl5`X[ZL(%($,&N%FUdjk[mh -#P$RiD2CqQc%P'C-a&EUV!RBk!lD&!6ZEJ2ACc!XZ654XjRRTU#$@E'UKJ[FL#qa -3#"-+qkCUB4#-#kSBIp5%dF3BC`Q$!$P*Nd2GjX,N[XAQKCF+ZQcQcmUAi,@m[!A -(Y!6(Y$5b'+%2MZj%SKI%mbeBBUk$S28@%pd-l9`DA#J-3Ya"SCdVQE4!BJBEXD3 -k%k(bkBdZ'%YQNqX!1F`-3!cJbl"a$"bfb4r$K,)%2p-hf-b9j5eil4-@H,m2BLY -C85XJ#aaJSZrLmR5T(Kb@-)b!B"4J93@5Q""`6qf+VZ2QP8$L([0RH'de,m9,-5r -I8'!aQCIJ)f5HMYHRjKDm$TTRSi1E'r'K0mpL(62a'M(2B4h69*YjTF28H(*5MbS -6bC1&h,4"Epkh$8,)*e-EfXb9kb'XRi"c`!Qpql2(),*[-*42aq"m$#ikdFB'NdN -$0k*M550G&SFb#eIEd&EH`P"PQ)4AZLc3BbrE5*i+lLrUlcUqmEUL"V%FDFT5Zij -BK%-e!*N01"cm,$!X0YIKCq&JU(bRpbjHqlcAT9"ChE2Cl2L0`L&54RdAl05TdQB -'MTB0JXa4bQiNk[PZ`[4#KM'$3fa!"rYBik0LR"LkEQkCCMk+c6Y+VM4NmV'6dGF -BaP#A69i$aU4$l0+EMkTC,)-4!&8Lj1ip-ZpDTD8%bJ*cN!#$c%%%L(BXB"5b$*! -!q-h)5X&N3[&V[$dNDdJ-&qF,dbDbP'faN!"X1G8+HrS,GZXCB`mr&32E'M$0IPb -[c!*,6"+I66fpe+@X&"&K5b'-S+#UZS[Uih3U6Cj5-Mb4FQV8NB!SX")+P[Ur -!iKX&FLJDZ*-NJj`&KU0G5,b-U#,6aD1Q%R)D1"G'&B%i-piXJFT[TF9`1NMDNk0 -ReFh1P55`eJZ11%H`aDqLZY&Lmi&E-F1@3Gh$6e)6AIY2[R&lM$SGHBdIiN!2T$) -m,F)90F5m854Q)0Pb(0JB(9K#RdCie+YJHC`kiIUE2j!!N8UNf-ATD(8q#[V5jQk -$)H'Y"$N,5)P1H5*PEUN+lMmf8[H,*B)CJE+T41i,#TKUT0!e"50(kM)253I13Kq -EbJD3!06+f04IPl&0XkB-416NCRE#%4JQKZT-r#cVkS#"#N(R,TF8d)i5-SJG$"Q -D,Jc$0(88`D2N)+T@aGr[+TKilYc,fPKA`GP98bm!S9)NR[E"2%8U+Z6&*C,4dU6 -Gr'qQLY08mVke)5e$#CQ-`$1!c"GN"ej6mXZ'qk`KqDEli8'Ul"#5E9)K,48+T3) -IY+6!-Ph!346*&-Vbf'%fP8IPPjR4**k18"JrqID&$!6`*C-+NY*T$6EjPPeP6*Q -8c$9eVCKl"FGj,i5CZQSVVM@!+af5c%flYRme`65lp5db"FP*ZP`J'`VC$aR2+Q@ -mERCaLh4aK9em3(jCJa!X,[C-eG925B@`9$JM&5b"UeZZXUYEF29kG[91q@8!Ib( -iqNAHl9cIqH1[rim&)h8("ZMkQi`-KHY6drhL-Ph32-T-CCc2&G"YlYbe2(a$B)R -H0YP%@IE"K'4QaV*Y+-VfGPqrIC+51&PM9`'Q4TZ*E$6,RQQbbFJR5G[2GQTEf5Y -653U$'fbb6eX2CJ13!-dQZi"U0VP$fiIAK&BA3$Yf!$kl"J6Rf$YTBZI3`9j82(# -*+j!!*CG4eSJi`iZC`Pf(Mp1Np#V0U8[Y(#0!!@$%&j+(cM!hM*`fU-JlUi*R-J) -B5El1(Yd!JD@m8['MLC@U1U(D+"b!+$YHXd5-I2ajIrd+2SkTGY,%QrI#I(kekR0 -R*-aI&(I#F*k%N4a&9VeKjl-VH*Jre)-LUf##*!9,CX"i5L'fIa5BGQ[j3k`i)bF -Fk5epp"*9JQbRJAHT+J008H8fNM`UQ5+,dk4BlF686R+-LT8%9dBCTdT59BN*a,S -l!SUEMK#`jHrKjdJ)4bkHa'Y#2#&Xl%&XLhJDVfla-MTFiN*m1-9jH0d5&`J)-D2 -&`hfP-2"(fCDl8S'ICr9LKUr8RSNX0HT-iY9TE`D486LN!h(&q3VX3B3Z6Mr!b@! -Ej#H"9ET1`#!r`V*HGb"4)9-bQFd&jjrUBX'JE"V&G*e-Q5XL8NNZ12"dSH+*YYZ -(+c-8C4R$%Fp4N!#m1H(ZU6@%4&N6NK-!5b0H&`c*-(XhrVL'&35[DmH%jMA3X&C -cbDbG#d*Va1[5iD!CKQQLl[!dAbr#0dQ3!(p"YV#'&Dl-V'P9cm#XKXD9@iaRHmQ -F,B![qi4XCh%(VP38EJpTTqJB!-4*C)immB4@Y`&1qpSa[%jVkhfi$$Zq*,Ij13C -+l4'`,8+Q3M8FV4((N!!")b%GHj38#FU!k&U)$)S$#Kb1$aR)ILXG%V9)jPBLJ*) -0XEhi2lI!H,e0YBRDiBjI03*Gka`ap5pNd%hmK@@qX,J#BLLbh82A#)`H,),!"'F -*XEJ"cLqfT3,*U0D`@$MiJ3a-9@drFl"Eb-*JU"BbEK3C4qNjfrX'!hNpMQ!XB,3 -[KcTbE&rJf'UH9*28P)9,!S-(&J!B)@RMFR[!P#iH*4@L+Pb(N!$q50e[@aRk0GZ -Mj'3#B`#3!*-E!k)c*3qNVUcD`kpSG+89bM"6*&G6dM*cfUJqr,RhI2J'Z4M@rKk -Z"(rSkCh+U(+FcI+1qcjdcJjbcMa%$RF`9V$Q3c2*Vb1TQ8Z"369dl-XZrE%[m,0 -LJfYMYX'fXG9JUmj"H1N+IMLDT8r`8lmY9$l$e#EZX-GJPDhfYr'R%GVHMm4kEfG -)GU#`-[)BjrFFX%8RG9436*0&%,)3L$!0851@KU0$1R5X!8h,LXXA"@CFe@U,MNS -,4V&J)j))bb%JiKNimY'#"4LiFIN2)hADph`ADF'P#ck!P9FYC%RY)CBCh$39$"a -qDBT'harSF#mP`(b&-D2Ke5jKc+dd$CK,*I)r)PCKdd50!$)H2##!FJDSdCN18G- -A[3+8(+2%X%Qc9ScYZ*d+B@h!SCC2DqS8@-U4)$RbS%cMN!"+)-$KXV+M-+R5X6& -Mm$d(`P``3%&B*b4mKT!!N!$#V&fpD*`QY$%KmiG$f[VfV'q$(&#[UTV)50fK'Yr -G2%r%*[j&LbUC`X'8cjh+`*60T'JI@iiNrdF$'D5XmQ@TTJFErdA$iQ-Vk%#1)6X -Fqa+&,mM4M5&QK+QA%D$,&cf,Mhe"TS)Q6S"@##20$A5e1"9rMb*3'+qAb%@[(Lk -#%8-KEiFEB$-pm!$'A,Kdr3J"Y%-MkABq",!5!![9D!29q1N3I$Gj,%p,46K1)jZ -8'`11iD`jY$*MBBf[%)c9QRBHSkQ%#GK$&)CH+N#9arDAb%@`(P1@![RQ5YN16GK --V`D"VN-V@D0998NH6IblpMK0kmL%fCK9pFLTFLH%JY@-CS(%Qk6JeTS+[C)VbSp -RBikBriD4A#E`F)US[CiF'[*H,5aN,Z-!6h!#dB`(h'5C'8GJ(`-lBb,h#c)(1U8 -VL9pUq%"'X'XY1mL66PBC(qBm90Hh5`fP4(Bq((Zdq+Pfk+K#*BS,m92'R$fd31S -qE`DF+`U%!DT-LF'eE("ZC$kjlSLI1@G&jM1hRqA1*A!5LpKeM(d[@,r,@0Z&!BQ -%L)k$V)-D"Y(1(R4J1!RA"J6aP'E*r+Tp!BBBlKFH+'*1+8NcbE(f'JH)j%Uq#`e -@(6QPS%$KFP59P"F*lL4b$VNDNT-+'BFB'K[46)i+3r,q9Zj,3RL*UNphjQreGh, -D!-Ij2*8pB!3L)j&2EB,6PA)h`HY9"lPel+Tb8jSVZ#Q"6C9!ZTFf`@NP9c6DPT3 -,%0XScYmK9b!NPbHfj`L8qceQbUfXQYV*MQjZP6Y5TH$ZJki1iH,Q#MDG4Q#Nbc- -(-B3pK5BLjH4$KPlKD-`,fC+)F'"Q,hdbB$Tp#01S4ArrQS'B&0b0T%@251aAT'R -2#CFeRi%lmPkqNicNJXU(V6R0R+,)l63ARcNS[)e'ZjL#-*,,f0X`3cB2!pA34,m -IP"NX%(6L3VBK!5MPPN0,i3J6F("1`T8QU54lHTAC$Tj#GMP1e345&9LZm3)%!aZ -q4*8!M`HSm0dTMXI)E0%M@0[&a)S'Z!R'hB@FUKG4*LL%+f%Fj[Tc)CJ$a*-(Tm6 -E!,d!S#Z8C6AFe`[hNRcQ%RI0EN`4h3+95#*k!@5QiHGa,0iABX&@XB+4U`'C&JU -l%KRRHVJp'C(`Q@Kk(16%50hqDXdiN33j9#Ak,Ki9Jkj62!9Jmd3'Ueba,0KP1RA -9dEP0rNqNR*mGr)0K04T)"R+IHS0,0!i*lV9*5P+J20p4ZJ8AkmT)H"aC`)9(R-$ -pSjeIFFfiUaE"fA4)J`F$)I4!4TTkaN*'3d2ML@'pJe8PJ!0-9X#P'C@,9J[*dVr -@898DYS6F38'f+RN#XX,4&5#NT3S3+A-)!l12h-+TfJ-fl*h*l`ceYUjc&b[eQ8E -hBjGG[[km0EjqCj`HL0+!#N#h*JGZV,aaGCqLCPS&"PXV'+b*6S(K,+Y3iG2R*Ep -jr4[6RjMa[eZHMlBE*cmC+PDmhjMZp!pmVUaTAcH+!69qm[0+226KQ`prFVd5MmH -i&%[(@B@5-lePc1'c1Cd&4e#UG$!3MNpNU&NR2rpQb98Z2JQ6qmlYEC*UR2c9k,+ -Uelq2PJ5lU,0!'Djj9Rq1UhpAr`l9YTSk"r&3'ULQb(JNU%A[3&L@QVmX5Zch96A -E3*)$DjXfd%!e`C5`6jG9iA)QVd5RSi,H&@lUj9R*AJ6ik[b'39f-*TK*9@8d+pK -NU&3ZjKPX)J`3BUA2aC4kPm2kpq@VpP520YkBe+H0JcT,Ql!-XYfAh%m$8-jRZQr -UbHeX#!ea""e48YQ)B04+"K0P#X,[8'"a8I8`&ZhqSjkj'q#&cj``((r8)+BjQKA -"a)Z@%d!T`N9IN!$aJ-H$8Bl#5E5!+Y$4Bk"'m3%EFL,iU!l(QKk9HjNe*1lj9fm -*VJc"V()#eirBH,fiblCNE8MFEqVI)G+M&S#SR`rT8D89#"ATjj%mDap-@'*P@5i -Yq`V,P!%D1"ICaiEm0LJRZpCDKi[FIhrdJ9Q,aCfME3T9NZ(LSh$#4q8e0'fS'VH -@UdAZCBpQ0a+,RNMX+b%#C`Q3!,0S)&[keN@k88Pq9%hf&)1Y!T@8,dD+bDR5&LH -P,RQS!)NiA4DZ"bj*`(i,9CjVX&"c5j2``af0hkYI3iqb@"&m'&Vr6hmB4-cCZSD -1C(HTb+iDVlTU(0I[")[H+B"d&5,NY$@kHm6P0R%rBpj4aEa$h*AFcGZDEN[jPIr -[E9NX6[XrfjLKi)hTC"[6fA4MKYki-6eXBkaA1#TkAh@)MGdDIXAbDe[65aekqkH -rP2V2MApVr&YL8Vkf$%GfR8fiP`(m)GKkqK2p+l),Qbql%[f6c*hfG,D5a%IbG(C -LGbFEZTaGGr'5[kii$bjh24F&4%QK$!*p*i04a[mCS8cN)KXbjI1cZjh6&@k1NaJ -V9Z#kILSJG,*lEVCa,VUV&9kcLbh&idCD$b"4HP)`S*0a3Lk!)D1!URJqQMfT9cb -M(ErG)qidR-*MTC!!m+jC)BSp[4-h)VeCIPYPbN3ZK(l*+-3U58H%"f&XfN80pa@ -Hcrrk'b5dlXH,eBjhIq1*ZIm`p*hre&+hffjF@aVT&d@R(pPk&"ArL`SX$mhhp9r -+(-5@$4E4BlRiF,K%DNa1N!$`dY-pm2NA5)5IQ"IX8ZrJ3f"Ufb1rBc992'*UicX -D%kMY*(hm8Ip6I"VBCmP2qM3CK+)D9#9T"f[D*R&aQ0STN!!DbCXXX2`k$a8G2)P -q((mf*6H6qVljh2V$AQkDiBVdalJ0CLPHTr1EA$[%6VmMXR0arU&Tl+%DpfH[1KB -e#89+TXK)D)q4NC!!YUE(*KHX[kXi09EPDV5)FhYBf#`NP6[a'!Lrm,RU506[Fk& -jKfY53PV@9k,K5RX6GP-9ZfPll&89cYmA'#RlU2S%,S,M2a*Fe4M9ijLD0QQ6me( -T$Jri#mim[cbcrFccm1+UM"0$aQQKM%,KQ4dL5`VQMZVleYhQ(UTbM+lp,![p&3Z -fq@'Q')qdmD+VR"rGA@eC2kYYeLpMI14GHMJ!&YmBeIHi2(Mi#+m-$*d9KQB&KU# -QNI#q6%S`QP-2#VVrJ4m@#`mZN!!BLjXQ'9Kd)cpV#6,h9$F$MAAG4ee[)"*8BEq -+Q$+52dL,NpfScS2PZpMb(rbdbf1"6iHPdHmT)8@UTlHZpbUA[lJQ2AVXrZbAlNC -0E2J)QI5&6&4c,kUk(K!H##"Abh2N#M%LkX8#SEUl`Klq"A6B)hp*kX&J9J`"9RI -*)%mE"GA&('1CX"G)rVdRCU8UUV-+VAh#eU0bPT'bprm%SP2P#50c54MiI#9Pf[e -TUZ`LLEFETb2a+4%$&D@4h5Y23%'-GYR%LZTjAEh9#j%JUG8V0pJfCPF[-LbZIUp -Y6r8R9B)rJYj8A@"T!`(PJf',c%(915"6*i3RBI$+&J3+CY$aerlhVZ0i"*!!6Gb -,kSeiT@2HMdCHp8k-[!S!!!*#!*!$#J#3!h)!N!4#H!T+RFj1ZJ!d6VS!*%*R5(N -!!2rr5'm!"%KA5(J!!5)krpC1Y4!!)'d!E%k3!+Rd)MVrbQF%6V83!%je@Bm[2&T -&8Np#CkQJ*&GCMbmm4%&838*RUD!J9b"3)RJ*##45B!ibf'B+-KTJ!N)C8FRrr,[ -*CZkTSkQM@Bm[2%4548a#CkQJ)&HJ*5"3iN!N$@!'-KM9Y4!!8FMrq+QM6R8JAc) -B0"L`@&I*rrT+3QIq6[!Jr#"I-KJd',#B9mRrqNT#Crj1m#$k)&mb'$3BX%*Z#T! -!3@d'd%""m!!#-""RrNl`!!!J,`!%,d%!"#)[!!J[A`!%51Fm!#3!*J&)3X6$+!! -U!8K&b-A84%K#N!2!`G##60m!2#)I6R8J,`!%,d%!"#)[!!J[A`!%51Fa!%kk!*a --h`#-)Kp1G5![!!3[33!%)Lm!##pI!!4)jc%!6VS!I#!"60m!M#)I6R8J,`!%,d% -!"#)[!!J[A`!%51Fa!%kk!#a-h`#-)Kp1G5![!!3[33!%)Lm!##pI!!4)jc%!6VS -!$#!"60m!M#)I6R9+J'SF5S&U$%5!4)&1ZJ!J4)&1G85!6VS!&N5!4)&1G8U"DJT -%J8kk!!C%J%je,M`!!2rrXS"M"L)!F!"1GE#(BJb!`8K!-J"#3%K!6R@bKf)D,J" -#3%K!J-&)3%K(2J")4il"-!G)4c)(6R8N!#B"iSMLLE+(B[L!`F#(-J2#`#i$5%I -1`%K(dSGP#*+#BJ4%J8je8d"Jj%je!*!$A!#3!i!!!!aB!*!$B!#3!b!!!$mm!!1 -Tm%&%3e)$!!"B$9-$R1S'YiZ&ElRP&ZjU#kJ&,-#Y&VE`,r!YGe&Vp9i!!4lq2r+ -65hNQLaM%"%SP-R')#kJ$EAISXa!"!*!$#PM!!!`!N!--!*!&I!!"!*!&D3"M!(d -!R`3#6dX!N!Fp!'!!miKF9'KPFQ8JDA-JEQpd)'9ZEh9RD#"bEfpY)'pZ)0*H-0- -JG'mJBfpZG'PZG@8J9@j6G(9QCQPZCbiJ)%&Z)'&NC'PdD@pZB@`JAM%JBRPdCA- -JBA*P)'jPC@4PC#i!N!05!!%!N!9Y!'B!J3#L"!*25`#3"33!5!"R!31)-P0[FR* -j,#"LGA3JB5"NDA0V)(*PE'&dC@3JCA*bEh)J+&i`+5"SBA-JEf0MGA*bC@3Z!*! -$6!!#!*!&-3"R!%8!V33%8A9TG!#3"3S!8!!F!4#)'P9Z8h4eCQCTEQFJGf&c)(0 -eBf0PFh0QG@`K!*!&#!!1!#J!,U!#!!%!N!0q!!%!N!96!(-!C`#["!*25`#3"33 -!53"&!5k)A8&Z)'PdC@dJGf&c)'0[EA"bCA0cC@3JGfPdD#"K)'ePG'K[C#"dD'& -d)(4SDA-JGQ9bFfP[EL"[CL"dD'8JFf9XCLePH(4bB@0dEh)JC'pPFb"ZEh3JD'& -ZC'aP,J#3"&S!!3#3"9d!F!"a!+`%!Np,!*!(5J"9!41)1P0[FR*j,L!J5@jcG'& -XE'&dD@pZ)'0KEL"[EQaj)'*P)("PFQC[FQePC#"[EL")4P-JGQpXG@ePFbi!N!0 -Z!!%!N!9S!(S!I!#f"!*25`#3"dJ!AJ%PL%j6EfeP)'PdC@ec)(GPFQ8JFfYTF(" -PC#"LC@0KGA0P)(4SCANJBA*P)'j[G#"cGA"`Eh*dC@3JBRNJG'KTFb"cC@aQ,@9 -iG(*KBh4[FLi!N!0D!!%!N!9G!(!!F3#X"!*25`#3"dS!93%6L$T8D'8JCQPXC5$ -5AM$6)'eKH5"LC5"NB@eKCf9N,L!J8'aPBA0P)(9cC5"TG#"hDA4S)'0KGA4TEfi -Z!*!$+!!"!*!&c!#1!1!!dJ3)3fpZG'PZG@8!N!8%!!3!``&L`!)$k!#3!``!+!! -S!,B"(!3"998!N!--!#!!#!#L!4`!JP99!*!$$!"L!*)!m!'B!)9993#3!``!+!! -S!(8"2!#(998!N!--!%B!TJ#k!GB!KP99!*!$$!!J!!J!SJ%F!)"993#3!``!+!! -S!+i"6J#e998!N!-2!!)%)'pQ)!FJDA4PEA-Z!*!$-33!J!#3!`-d,M!Q0#i`,#! -!U5!a16N`,6Nf,#""E'&NC'PZ)&0jFh4PEA-X)%PZBbi!N!-D"!#!!*!$!c3Z-!p -6G(9QCNPd)&0&35!d,M!!N!--#e9Z8h4eCQBJBA-k!*!$#!FJCQpXC'9b!!!%-d& -%3e)$!!Ch$9803b)5%HCHEK"N,4P%D[*%*!X3@DZQ*LHh2BZ-i(ERb%Qh-e2bQAp -h[qrELM`EhmbhY8#5eFlXbH4*f,ilNa'5j9ENLDc)laq42j1IbEcCeRB454B6XMF -Yb5)S31)(rdjCKT&84$LS#cYiiLGf)5c5J1e3aD%@GK*H(mq1D3bR6lpC+R)6)mR -Y[@4[%r6@hmf'R%[)+8FIZEr5&V,ejRAjaL3*5bPTf0kN&a@6NPGC,a$mi-RK`KF -HI%V$*QM4BN6+hFfqTX2b,*5j55k)jb(*(2h&i)XDJqim&Fee*9$cG*JIMZ6*i#S -GjViNe#Xq)@+3!*h[`af,NK")heX@$ED[(5XhPA-`LA1fRcbNbSE0RBqrZ,m'l)Y -Vm[NQUD!A@)"Ck2@aqNDT+'b%UlJKdF4%D4j'8D8QKLJRXm5(8JQR40@4X8N6+L, -JmB-'82KL!,85ECR3J#8d%@TbLdfC`eLTT"qR$+aeU)[Di0J#T6DMFe4B`aLflrd -NJ-)Z!m3jBTLiESAmcl%RFHbLl9fAJNh,JDRU`pD$+ZFdM(GdeX@!G"Z$#pDfYBX -aSNc2)HBbh"2bA1lEQ20L2d(0f,[Q&#I)A'ZQ2(KBb@@qIDUNT-rSkShVZbh3b(2 -j4EE#Hi"%aD`5%YXK48JPi!JpjfESS#*')G-lpU&Zma9#N6ZP%AF+hP-PhjBJ16h -DlDNc*qDmR%1jlK@TB-cEfPh+FK[jplG1#3aZ,GrmP`rLNbG@J3Mpl)N"@`NmD#E -1Ye,'NV,SJ&0-'N"4lGDH(L15jV)kGQArf*KLjXEBBNT+ilSFVqIQ2L6S6,2!-qd -r5A,SM5rZ8%e+qrrFIEa)TAK+(ePf3"KU9mH96KeiJM&J8-CCH2(UplHlTpQ8&pI -V!mfS&!eYS22Y"H59K,,GX(5'$iDUN!!D1!1%4[Dm+R'd+EK+q$Ll6eBP[SHY1Jm -&+*f0f9@c1LPl$U`!LB0EA#,N"l-#h9`&eEjM4RfXIVf`GZf$Y!rlJeGII3NEUUX -[JA!5-Xp,Z*!!K9k#PFalib#6LH[)jR!53fYB8Y@+#cA4e!fZkRA5eL(bC5reTB0 -Nq+`1N!#ULm1*SfpKL@KA(V8&MK(J'6fDpK)ZJ-$X$'lTUd'pQXb1L-Hl60lqhlJ -2YkIbbBfVNkBAI5lbXT26-1CCQI@i%dADZX@J'V("P$45$f-VG@mlh@!+D@pipZK -GMr,CUC9ZcXXMqF'dI'XXGU%XA8IkajQ+#fPh$2Aj@FVRjqVrINKT#[0r9hl1a'B -ar[EhjGLF9@FZ6fPZ&[UQ90aX9RVbi))fT0[hNY60m9Pip++5qIc2PqqBK`c8pE9 -GaLXRlhFHm(""&mY9YB2CTqfiUkZ$G385RX(1bd[ERX3qk'4JZaVPpDGj!R%'T[" -3[!PH+Gc$PhJ`"hHqIVA3@F0Eeq31!!!",d&%3e)$!!&Z$98,Sa,3(`,[MX0G"i1 -VS')4Q(4+"CeP@S'Clmb(SM82Ip(I(*K(D4A2I'$q&[0K9K8c&"2&r$@V5EkTU*K -9439&phSP6c(*!"1aC5A+J0LHE33'eM"R5Q-Af($455FbMP!J*%5L5"VfFJe#ABT -bVcRA4B@a96dp+RHhD`rFF&F@))QYk$RCaCMM3iY@r'%I9"NNRi3H&+6Nb+Ekq,R -[CKIQhmVFF$J`VdQ5m'YemhE`p&D5E6j5(VmrPl$l$k3rXTPHl)!0@&jc$0ZABIP -&mp&"JI!#DaENdTMml81I`#icTcGeq@6Upd1K&[m+1ImYiqD1UMI2ikh!"rA+h@G -FD3IbmLC@e9$jp9!k6JUl9a2!KP1+'B$U)Bc230$[U!%J"*%91SCK"!!!#4G"4%0 -5!`!1K3jG#k55),ibhjhrq-jHjTcIRm3X@FlH1F3CSh%X80,b[R0QLXqEJ*aX40@ -UcFUD#%5Rl(e8JllrGqBa*dc)b``NKG+`*T5N3Y"1UPMIThV[djD9N!!b0-6@8G9 -SS`-*3XV@EJZ,ppfG(@H&VG9l$HjZ05)#-d3M(d0&9JkT3rK[IJhrMG+c8Cl(B+4 -U`aFMihF0N!#jkkJ(bAf)aK,IG)P[ca,IG-NC,*)9Q2S@4ApLIjK&+S'Id[Z4`Ve -!C&F!hk33*VJjb0NB50)-%!X)p`RCp6"I8pTh4UI[+E8`dFID4ZkGr@lA$AQDlbl -dTY[ZH@,hr!+XiD9#H+cpQa8c%jVX(JTT(9@GRD&+8bJflXSeSl4`5cY$Y5BUZhI -&Y(p9rDdY9MhmA'a'S26RfD0D,'"MJPS)PR+'Y$*IGS48-42MQe(`[2"&@fPYS(Z -$2,ZVS#hMPle6m-bhq8GG`NZPN!#-)R+V%99PNPlh36fhm*9bM*6G5(DLl6*[`RR -N%1kYe0apJX"08h9pBpI"UeK@ZP%fDY[@f0f"j$FB'16,"hmb'lqqr(ZIF,[qqr( -8P4F2LPmU8Y6lJ@,C*HD'0C[m5%SlDaYhr0f9c5@RlpTrl%Ba0h%pIrF&([T)hhC -PQkhZV!V"p*ICGPYr00)ATYFTIIZZ+Zh!F'lqJ+RpekRmf5JSrZ#`Jfc9YhilkVT -Hh9L([6AGJPqp[j5#5'i#SGl@1!l!f0$([Z4B9)JpbTMr8K%pV8&b'lM9+a*8%hV -&U'bb498Z@DQS*MRZ&3U9S9IX$jNN*bhPP@UI8TA)Arc+eR608jlGh#RG(Y%mCIV -ZHjY0eR5&1qC1dXc90emD5,Ej@(eFD1XV&rqi5CRVdF[i&43@eN[fU#"2lpYa(Vl -C*ZUUNZp0XGNQB,2*LUI#aR9CrBK0&Sp+b8*6C1J9E63Tqf"5i25flDL4ELQ!0#R -1JdB29[1P&-F&`EQV34i-5ZXME9iP2CJ#Sq!JM5UKU,HpAUd@9Ujj,Ce3erhrA2Y -0)fVEk2m'%q('2UUC%2HLD&+GqD$mXUXk4$HdCk9'VaEk0mH(e6-fT4pmjRa9e3I -09fm)JH',*UjGkCYBVDUp[eRI+)5dJF4`UL@ija2YP0UeSHUUm2!Y1A!N#i,p%r+ -mraE)KC!!h)mYI"M-*-j`h-92m%VhR)6A)GbRK)!S@)q!m3bE39ZF$L3#NlajP54 -K$2XaQX4Q&+bEm4`j1AMiN!!D$8bLH48j)NdQ4ZlPFU1$$j(RK3$Nj8cC#bja3Z9 -@VceajE1aV$3CP1@85*e1e)0Q)jGcLA5!ibD49*QcdSUIb6+I1lrc$,UNCTa,i@! -(l&NX8Z!UXl)Fc@N10p%$TmlaarF12*%VqVQP+IbmGAC[Z(*i4%i0ElMdXHT++-Z -e+['9N53H0#4Y9,3%Ib#8d),3L422HK!GJGBFY,LYf`X9ljIeI"9HZ54kVCUF308 -$Ta+%AGi0FXiSpX5"dhYD$!,RQ3U0(P3fjfdBeq`NrZ'e,erl6RVGI#'mVR"`phb -T-2,3[')Sd$cb3&!%V`adK&KR!aa2Y%%,Z,h0rNH#iVJi,$5IJe1*KV4GN8AeTLJ -dhii*%jh+4+0lL-6G`Gb!1(p'+l"R#Xqlj[FAI)G0QQ+9i'Uh+QCdXfkhYb)Q$Qa -("&X5L'&#mPXXm@0)Ucd%5eJUcINKX48pJ6d%PbS*K&[ci9Z%V*(I3hJPL`MrdJS -I3`D53``T(FqmS[EkqkCA(rKLZIm!-KZ&[1GiTPFGl*ZpSH[blmr0kANl3fU1pr3 -DII1R0R@Yr)*!qJH3!1C*GFpaYEH[Hmh&ZN*A@%M6!%pD0diEiCSl$VHQjr`k#`[ -26@IZ9DI$daI6KAA2pN(q9D3Y+FMIp2MMdq%6Qblq,Td1hibPQPH&k,ZJH0C&,1f -SJfdU0CD1i33[B404!YdjT'r8eK+UMqe@Db3GV(dcl%e2@"m1dpJq%Rh(6	H,q -%2[!CM`9RLm[r%li9iPZYi6IUKXJLDiC`*LQ1j@0C1-R3A,AUd"L@,!$X'#)f9Q` -GU4qjDTIlE$mqA(M5%LlfVkUm(4R$6f-Y*2qH0D6p36il*,[YSYC3Ef@,rIqX9*l -!Ebf0'B$Bc0CR("AbR`1@-IY,[Y#8e9pF9R&@mL*83(aXZ8)Z"La%VB`"J[[p584 -Bj!eI5+Z3!-m'FQle8ke"Xl)9E+f!P-EiV3U5Rr1e(UmFZASXGdNpP#jSPS%Mep0 -4%N&XLQ8J!kB+PhfShJLZT1Hk&EZ'!AIMZcc23,,Q+,p414k9S,B6,'a82bfhAaY -ETNrA%56ja02ZG*T5j4lME!"-qUA2Y$MMJiY4T!6X@Z)k)D`B8d'!AjJ-cVeXTE3 -(16-(E(Pb4Q#Tj'@9#%5hl5$Glld`DH2L9KVmeH*EFa9hpIDl1`$QYF(BlY&bTX2 -dqBA$reLmd2TDRl(Y0,(GBIAPhAX"rrC*9qj6Dcd$H#M1@jc&$Y'NGA48bXlAXh* -S@kH!Zkfbli`-Z2M"q(b&pHX4I'G4%de6YE9A(RA@qh)a&f[!UpMFMmNq0q"eB[p -iVX)kEUcG1DPY3V0$`62A6#EC@@pc!%i&h!kia8UMBYEe3)A945F$!Zi8m+KTci2 -1HV%pT#rHl4bkG*dEl!9mF@EmL(@Qr)X@N!!HQJGM-lYP`%2C`r@*QVC6V('0%[" -TN!#F,[k0%(eX#hU3!0aHNqRj@JSe6JF*I04KqTHADUE2Tc,B-J[*j9f1hMkq&-B -!U*!!KfX`AB-8B"Ah@IS[4f&li'IQ$1CAe9if%aiqGN!&Q%S4&CiQhDIf@FS1cNU -jaA2YaBpQiQbY3i'CP4mCLmX+L8rILUK3`8dZHmjaV0YkRM[jP2ccRlVip*4Me-q -APMjP-@A,$9P,I85&#Ulqe@iaGfcqU-aPXh*qlF1-@ZZSlH5C1mA0TJqUQTkf2j& -8)5`qd`4i3-FVSVN)cQ3YT[jL52V`9&+&J$mj!EMGASjQX`p@2&,*6%A`c5D4[Tl -00DT3H*AkL5leI''P)l9im[YlhCrhTp2DG*J[E4#Y4L*[6e`je+K#q,'4%64@!PY -K&Z!k%mV9AKd1kGd&SBA5Q+kqLIFl@5H@2&IJeq44!*!$'!!d!!!"(!&S!!%"!!% -!N!8$k!#3!j3!N!-)!#!J!3!#!*!&('&eFh3!N!-"4P*&4J#3"B"*3diM!*!&J!# -3!`G"8&"-!*!&!3!!!3#3!`+!!!!%3!!!#5!!!"13!!!!*mJ!!%%%!!#"!J!"!!% -!!JI!J!32i%!)''!J%"[m%#3DP!K-'[3NRc)%-N`ek2NN05Jb%$Ii*!J`i!J%(q! -3!J$!)!%$m%!!J!#!!%#"!!!JJJ!!%q3!!!R)!!!%N!!!!!)J!!!"3!#3!i!!!!% -!N!-$J!!!"m!!!!rJ!!!Im!!!2rJ!!(rm!!$rrJ!"rrm!!rrrJ!Irrm!2rrrJ(rr -rm$rrrrKrrrrmrj!$rRrrN!-rrrrq(rrrr!rrrrJ(rrr`!rrri!(rrm!!rrq!!(r -r!!!rrJ!!(r`!!!ri!!!(m!!!!q!!!!(!!*!$J!#3"#!IU5!a16N`,6Nf)%&XB@4 -ND@iJ8hPcG'9YFb`J5@jM,J!!&8J!N!-"GJ"1F8U$CKT"l3!J-,`!#$&m2c`!!M& -m!!%!"$&mUI!!"Lm$,c`!!"5Q3IVrd0$m!+)[#%+RB3!#*Ylm!""R%NU$C`4`!8j -e6Ud!)Q%!!pDTp%ja5S0Q!URdF!"1G@"b38a"4%4$69!!!`#30&"b3@e)jf$`G$+ -I`Lp)!#!J6b*8-@N!&!!B)8!!*$&m!!%!,0+4)8%!,U!#hm*-h`m'6R9+1!THC`` -J+J!)C``J3#!3C`B[1[q%6R9)jam'3IVrRR!-)LS!"-+i!aTKT'B!!4*)H[q16VS -%i&K2X(Vr@QB!!1bK'Li)##S!"J!%C`BJH!+QS"XX+J!%+LS!#"JU!!5Ae*A8)$V -r9U%HCJ!!c#a))$Vr5L)'`VJ$'PK"B3$r8L!krd,!Z!-D3IVr2L#!5S9Q"+%LB!3 -J4D!RCJ!!Q#T),cVr!Lmkr[S[1[lb,cVr!Lmkr[T)H[m5,a!J1[m!8B""q[lf))! -J$P#!3IVqk##!5(S!HQ%!#L6Hr!!J5N"R!URr)%kJ(b"(S"Yb!")%j`RM'H34!!% -!)!)"!1!J6D"T!J!!(i!")%fJDYA8ep4"q[kB5T!!C`K`!D'BF!1KQ#"0*8J!#(! -!60pJq%je60pJq'!!rZ!J6U!IeG6Ae#"(S"X`1!)J-F!+B*()B1"19J!!51F!1#K -Z!!a(q[jD4IVq@L!8X**Y"#!5+)"+J'm5)&-LEJ!)SLiJ&0'6NC*`!'!%-$crf8c -I(!"1ANje6PEreNMR%aJX,J!35IVpmN)(S4SY52rQ5Li!#fF')(J#TU!E,c`!!+$ -m6VS#RLe!rqTB6fF!!Ai[,[rU6VS"q%S!@%pR"R!"B!!"FNKZrrK)E[rd5'lrlNk -k!j)J,[rdS4iY52r`6qm!$'F!!8JJ,[riS4iY52rmC`!"1LmZrrJ[#%kk!qC+VJ! -88%pQ!!#8@Bm[2%024%9`!$m!U"mQAb!,ChiJ%h)Bd)%[!%kk!Y`-3!!$@%pQDL! -0FLM3J5e!rpSJ%h3Bd))Y32rH,`"1ZJ,`5-!Y32rL)%ZJ+5!Zrpj3J#P!!#KCMbm -,6VS3d#!IFL#3!)%T3!!X,blrr#mZrr3[,[r`,`B[,J!-5'lriLmZrpT)H[kX6VS -)9Lm,UD02l`!N+@lrkJ!-+@lrm!!3+@lrp!!8+@lrr!!B,c`!!+'B6VS"L#e!rpB -[2!!!U*p1ZJ&k)LlreV#"9X0%!dL$5--T3`!F+8B!)#PZ!!`!*%Kkr*!!2cbJr#m -m!!#Jr%kk!54BMam!6VS3@#mm!!#KQ%kk!6T+J%r[!!aR"%kk%&B`1!&Di%!-3!! -'CJK"qJ!D)FJ$2(i")'lrjU!E%!G-lKM)rm*1ANje6PB!!%MR!4K#"bmm!!#Jr%k -k!2)S3#!-@%pR5#m-6VS!8%S!@%pR2#C-,bX!$$mmS2`[2!!!S2a1ZJ#L@)mI!%k -k$pBJD`!3S"mJD`!BS"m`1!&Di%!-3!!'CJC`!#(!!caq!4!(61iBJ2rd6Pj1G8j -@!!")ja!)+'i!#(B!$+a"6%&%!!*Q&!bX4%008!!'CJT`!l"X!!TQ!RB"%!0-lK! -)rrK1ANje6PB!!&Q22cbSER!"(`"1ZJp-@Bmr2+TZF!%I!%kk$ciJ(l#ICJB`2!) -!B!3`2!3!6Pj1G8j@!!![!c!m#!$!EJ!+FJ!b!%U"8X0%!fF%F!&J!R!!*Llrr%j -H6R919J!!51FI!$iZ!!T)abm(6VVraKS!F!!3"3a!!!&B6fB3!NF(rdkkrhb`4fi -%F!"J+PQ22cbSRh!"(`"1ZJl#+"pCMcm((`91ZJkf,"qiKPI$4!0R"(!!B!)J"Nc -Z!2Mrl%jH6R919J!!51F4#$iZ!!iJEJ!)+&"f!(!!-"3-J!!!384Q,R!!-#`!!Jb -!!!"$8QBJ$%IrrfFB)#`!"%*!5%$J5#)m!*!$rm+!5-HqJ@B#GJ%3!dcZ%)Mrp%j -H6R919J!!F2m[!%KZ!!K1Z[qB5J"36fFD)'i!##!S!!4#3%K!i%JL2!#3!rr#J$! -"B!*`rdjH6R919J!!F2m[!%KZ!!K1Z[pL5J"36fF3)'i!##!m!2q3!m#S!!4J!R$ -r6Pj1G8j@!!")j`!B*Qi!%#KZ!!`JEJ!)-,`$!A!!+)!'P!!!!53'P!!!!NJ'P!# -3!b!'P!#3!i!'P!#3!i!'P!!!"*!!"T3!!!%N"T3!!!53!!D8!*!$I!D8!!#!!#D -!"T-!N!-N"T-!N!-J"T-!N!0)"T-!N!-qF!"-lKJ!rrK1ANje6PErp%MR%aJQEJ! -),8[rp!DZ!*!$*2rd+'lrp!DZ!*!$)2rd,@lrp2ri"Ui!N!0)rr3YE[rdrr`'VJ# -3!clrp#!Zrr53!+i!#,#Z!!aM"R"PB!!!X%*(3NCJ4R!!-!F-3!!%9F0%!fF%F!" -J$(!!-!GCJ()%6VS0)R)!-JFAJ"J!F!!`"b"ZrrM3J$''#!"`!$!(%$-)!()"iDR -F36!(8NG`!$!($%!!*'@`3NGm!@"'F!!`"`a!!!&9`d3$C`4`!'!-F!!`"e1!FJ* -1ZJc-FJ!b"aQ!'!"`!$!()'lrr0#!-BB)!(!!-!F30!J!FJ(KUGa"-!G54h!!-!F --3!!ICE"`!%cZ'-Mri%jH6R919[rm51F2'#CZ!!`SEJ!83NCJ$R!!-!E3J%*d#!! -`"P*'F!!`"R)!-Li!%Y+"XS"ZiN*'H!*J!!#D3N9#4h!!-!BJEJ!)jB!YF!J!rra -JE(!"`+lrr0j!F!!`"A)!-JCd!"3c'!"63NM#Y)"[+(!!-!I3J()!-M3)!%U"CJa -`!$!(d)!jK!J!9%4`!$!(d)!q0!J!B"K`!$!'FJ!b,J!5dS(5J(!!-!I3J$Q"#!! -`"9*&)#lrr1+),8$rr(!!-!9b!$)'G!!8-aJ!Y%"LJM!'8NDmEJ!5C3$rBNcZ'2$ -rj%jH6R919J!!51F2'$iZ!!iQEJ!3+'i!#$JZ!"Bk"qC0F!!`"h`(c%"q!(!!-!8 -30!J!l#Kb!")!F!(!!A)!%J$HJ5!(d)"b!$)c#!!Z!9*'F!!`"R))XS"Q"N*'-!9 -54A!!-!63J,#(BX"`!$!%d)!L"j+!%!&-lKM`rqK1ANje6PB!!%MR$`Ji,J!52Li -!$LKZ!!Jm"qC1F!!`"hS(bN"`!$!'IJ!H0!J!F!!`"A)!-J65J1D*CbT6J@F@8i& -Q)R!!-!C8J()!%M3)!%K"3N'1JA!!-!C5J()!%M3)!1'*MS&`!$!&i+p`)*!!"(, -ri+R#Kc!"61i3m2rX6Pj1G8j@rqT)j`mB*Qi!##KZ!"!'VJ!!!53!&!DZ!!!#5!! -8,@i!&2rd"Ui!N!-J!"3YEJ!8rrJ'VJ#3!i!!&#eZ!"6rr"!6jJKb!")!F!I!!A) -!%J"536e"rqS3%q))FJ!5!(!$`!&b!")!1!&84(!"kDJp32rbF!!3%h*!`J"`!"! -"28$rm(!"kDK6J$e!rqj`!"!6FJ(#!'F+F!!`,[rZ8i"J!R$r28$rl(S)5Qlrm'G -@,bi!&#mZrr4`!$!Zrr)[!#!,8S![!%kkrcKb!$)!ji(D35mZ!"3[,[riF!!`,[r -b,`![,[rd6VS)I#mZrra`!$!Zrr)[!#mZrr3[,[ri6VVp)Nr[!$"#4f!!!2C+E[r -`Cc*`!$!Zrr)[!#mZrra`!$!&,`![#dkkrGjm!"`!F!!`"L"Zrr4b!")`#!$D38r -[!""J'R!!-!3[!(!!-!8[!#m,6VVq,M`!fN42l`!-['lrl'B3-!G54h)!-J"#0"J -!B!!!MVaZrqjQG%TZrr"R-R!!-#lrmLm!,blrr(!!-!8[!#m,6VVpF(`!(!"`!$! -')'lrp()!%M!)!0T"6qm!%'!DF!!`"#m!F!!`"5m!,`Y1Z[h!2!$D4%r[!!a@4Q! -8F!!`"e1!FJ!b"aQd#!!B!$!(8NF`"P0'5N"Qj'!5%!E3,[rV-JG54h3!0!%CJ#J -![Qi!$Q8!r`C`!$!&AS$QL%cZ'2$rdNjH6R919[q'51F2'#eZ!#6rj!DZ!*!$*!! -N,@i!*2rd"Ui!N!-J!#3YEJ!NrqJ'VJ#3!dJ!*#eZ!#6rq#CZ!"c@r!%Ne[`#50E -m!#$@r!#!e[`!J#e,rpM@r!53!#e,rpc@r!%N,8[ri0Em"*!!,8[rm0Em!(`Y5rr -)er`!!)!!)!Z3!+i!(,#Z!#"M"R"PB!!&8RS!3NFJ,[r)d,`!!)!!,8$rc#KZrmJ -YI!!!J!$rr%KZrr`[,[r))'i!#%k3!%UZrra36fB'F'GJ!!8B)!a5J,#ZrmaMC#e --rlSYE[r-rliJ$&+!N!#ZrliY32qf)#lrZT!!V[r),8$rXL!Zrlk3!+lrZLe!rkj -R$#"-)Qlrb#!ZrkkL,LKZrklCl[r)5'lrXLmZrmJJEJ!)6T!!)#lrXV#ZrlC36f3 -'F'GJ!!5U(9crah!!%#lradM!d)"63$e!rqa`!$!Zrqc3J$e!rqiJEJ!3)"$3VJ! --,8$re#mZ!"`[,[rF5(J"*#m-6VVmG()!-J"+JGR",bi!(#mZrpK)H!%N,blrh%k -k"E`[,[rJ5(J"*#mZrp`[,[rB6VVkCLmZ!"`[,[rFF!!`,[rX,`![$%kkr#jb!$) -!5S(C`5mZ!"`[,[rBF!!`,[rX,`![,[rF6VS&FLmZrr"`!$!Zrq`[!#mZrp`[,[r -B6VVk'(S!3NFYEJ!-rp"2l`"JB!!$X%*'B!!!Q(!!-!G+J'Cd)!a5J,#ZrmaMC#e --rkBYE[r-rkSJ$&+!N!#ZrkSY32qL)#lrTT!!V[r),8$rRL!ZrkU3!+lrTLe!rjT -R$#"-)Qlrb#!ZrjUL,LKZrjVCl[r)5'lrRLmZrmJJEJ!)6T!!)#lrRV#Zrk*36f3 -'F'GJ!!0HHJ!D((i)F!(!KGa!F!!`"L"Zrq$3J$``#!$LM6!(8dG`!$!'$%!#5'8 -!rf!%4J*)F!!`"Ja!!3"N%#!Zrp"5V[r3)%!3KQ!!!ZS%4J%!F!!`"L"ZrqM3J$J -`#!"`!$!')'lrj()!%M!)!$e"rm*`!$!Zrm*+J'-!!+*JH#!-8S#`V[r-Bf3Y62q -Q,@lrc2qU)!a5J*!!V[qU,8$rSL!ZrkD3!+lrb#e!rjiJ,[qUN!#ZrkBY32qDC`` -J6#*ZrmJJ,[qDSLiSE[qDfHlrb%KZrji[,[r))'i!#%k3!#!Zrjk`V[qL8%pN"R" -RB!!#G(!!%"c[U)U!8%G`!$!($%!!''-!rhj`)*!!,[r$F[rJUF+&f%&`!$!Zrm, -JVCjZrm*#4Q!!!*K`!$!(5S"QG#!-8S#`V[r-Bf3Y62q5,@lrc2q@)!a5J*!!V[q -@,8$rML!Zrj+3!+lrb#e!riSJ,[q@N!#Zrj)Y32q'C``J6#*ZrmJJ,[q'SLiSE[q -'fHlrb%KZriS[,[r))'i!#%k3!#!ZriU`V[q18%pN"R"RB!!"b(S!'Kaq#(!"`)A -F3(!!-!BJE[r`d)!m-!J!iSd`"e0(['lrlQ8!rf5FE[rZF!!`"L"ZrrM3J$e`#!$ -ra(!!-!BJE[rdFJ!5-!J!28(r`R!!-#lr`NU!B`!!T'"i)!a5J,#ZrmaMC#e-rkB -YE[r-rkSJ$&+!N!#ZrkSY32qL)#lrTT!!V[r),8$rRL!ZrkU3!+lrTLe!rjTR$#" --)Qlrb#!ZrjUL,LKZrjVCl[r)5'lrRLmZrmJJEJ!)6T!!)#lrRV#Zrk*36f3'F'G -J!!$qF!!3(1qSLS"34h!!-!F-3!!BB`$rIR!JN!!Zrm0brq#T`SA6E[r%F!!`,[r -#i+fHE[r#F!!`,[r%5S!QE[r3Pm#hlJ!-C6BJE[r38Ulrd"#E)'lrd&+Zrp!3Qb! -Zrp"5V[r3)%!3Qf!+)'lrd&+Zrp!3Qc!%8d4+3'EZB&C@4#!Z!"M3VJ!8FJ!b,[r -%*#lrd*5Z!!b5JLC!Pm&J$L"Zrp"5V[r3%*X`"&0%5N4R$#!Z!"M3VJ!8X)YLiLC -Z!!aJ#L"Zrp"5V[r3%*X`"&0%5N"QlL!Zrp#`V[r8C3$m5#!Zrp#`V[r8C`4`Cf! -3)#lrd*!!VJ!-)'i!%##!F!"-lKM`rfj1ANje6PB!!%MR$aJQEJ!81#i!#LKZ!"" -J!!%`2!3q,J!18NDmEJ!1C"*`!$!'FJ!b""!d#!#`0"J!CHC64lK(C"*`!$!(FJ! -b""!d#!#`0"J!BZLq4Q0)F!!`"RS!'M3)!(!!-!Gb!$)''E3)!"J!F!!`"aQ&#!" -`!$!'d)!k-`J!F!!`"p#!FJ!b"Y+"0l-)!"J!F!!`"p#!0i8)!'##Z%GQ"P*%B!! -!SR!!-!4k!"Sd#!"`!$!(FJ!b""Qd#!!B!(!!-!FCK3J!F!!`"0#!1M-)!(!!-!I -3J()!-J65J6Hc#!!B!(!!-!I3J$H&#!"`!$!(FJ!b"*!!JA)!-Li!$R3!0!G5JT+ -#XS"M(Lm,,`a`!$!(,`"`!$!%,`"1Z[lQ1!G54%r[!""J)#m,,`a`!$!Z!!i[!(! -!-!G5J#m!6VVqa$e(!!j2l`!3F!!`,J!1FJ!b"*!!JA)"XS"Y!2l!61iBm2rS6Pj -1G8j@rra)j`mB+'i!&!DZ!!!"*!!8*Qi!&%*'B#"`!$!')'i!#()!-JBCX!J!'!" -`!$!'d)!hKJJ!-!C54VaZ!!jPfLm,,`a`!$!Z!!i[!(!!,`"1Z[j)3NC2l`!3B!3 -`"P*'['i!$Q31F!!`"R)!%M3)!%U"CqK`!#e!rraJGR!!-!C+J'-NF!!`"R)!%M3 -)!(!!-!C6J(3!&$3)!**#5-%J,[rmikJY32rmF!!`"RJ!'$3)!#SZrraq!'!1)!I -ML()"`S@#J#i"iSd`"&0%5N"QkR!!-!E3J()!-M-)!#"Z!"$PJ5'('!!`"P*')#l -rr&+ZrrbmEJ!1CB4-lKM`rq41ANje)PmJAk!P,S"U!N+A6Y%LAa)I-"p+!@F%TdC -J!U0',SK1d5*I%Km`(b"I5J&R"+C(B!+L4dl4)Pp`!D'B6Y%L,`!%)#m!#%(k!!S -bI!!#6[#5rQ!'6%%)!8je6VS!*#!"6R8L,`!%)#m!#%(k!!SbI!!#6[#5rQ!)6%% -)!F0!6R9+J'X85S&V"Nkk!%C1G85"6VS!2N5"6R9%J%U"D`T1ZJ!`4)"%J8je4)& -1ZJ!N4)"1G5)[!!3J,`!)3IS!#M*m!!*1m*,qB!K-33!"`d"1G6m"5%&+3@BF)J" -#38K"C`U#edK"5%!`!8K!J0mb!%*!5%"1G8K"2S)[!c3!*J&b!8*!5%"Q$%K!-!* -b!'!@dN&P%Y4#dB#`JfAdN!#$dN%)`3!!C1iQ(c3I6R8!!!%!N!0AHJ!!9RS!!!* -k!3,f[$J`!*!$(!*U!"&%394"!*!$NPT&8Nm!N!1H4&*&6!#3!kT$6d4&!!-!YP0 -*@N8!N!2Q4%P86!!(!2*"6&*8!!B"8P088L-!!!'QGQ9bF`!"!E*69&)J!!%"bP" -cCA3!!!(L8%P$9!!"!Hj%6%p(!!!#"NCPBA3!!!)53Nj%6!!!!Kj'8N9'!!!#+NP -$6L-!!!)fBA9cG!!!!N)!!2rr+!#3#Irr#!!#M!#3"[rr+!!#[`#3"3,rrcJ!!X- -"![DF!!(rra`!+SB"![D!!!$rrbJ!,-`"![A-!!2rr`!!35i"![A3rj!%!!!Y,!# -3"!3"rrmJ!#dk!*!&KIrr*!!YZJ%#pR3!Krrr!!!Z%!#3"BErrb3!,Q!"![C-!)$ -rr`!!,Z)!N!@errmJ!#p!!*!&J[rr!!![XJ#3"!2SrrmJ!$!3!*!%"!(rrb!!-$` -!N!@#rrmJ!$"-!*!&KIrr*!!`A!%#pP`!Krrr)!!`E!#3"BErrb3!-(`"![CB!)$ -rrb!!-)`!N!@"rrmJ!$#F!*!&J2rr!!!`V!#3"3(rrb!!-,m!N!8#rrmJ!$$d!*! -%!J#3!b!!-4)!N!3#!3!()!!a)J#3"B$rr`!!-5i!N!9rrrm!!$9P!*!%!qMrr`! -!0TJ!N!3$k2rr)!!rX`#3"[rr)!!rc`#3"B$rr`!!2pX!N!@!rrm!!$rl!*!&J2r -r)!"!"J#3"[rr!!""#J#3"!C`FQpYF(3)a#"cG@CQDAM(93: diff --git a/mac/tclMacResource.c b/mac/tclMacResource.c deleted file mode 100644 index 77879b4..0000000 --- a/mac/tclMacResource.c +++ /dev/null @@ -1,2205 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacResource.c,v 1.4 1998/11/10 06:49:44 jingham Exp $ - */ - -#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, iOpenedResFile = false; - 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); - iOpenedResFile = true; - } 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: - - /* - * TRICKY POINT: The code that you are sourcing here could load a - * shared library. This will go AHEAD of the resource we stored away - * in saveRef on the resource path. - * If you restore the saveRef in this case, you will never be able - * to get to the resources in the shared library, since you are now - * pointing too far down on the resource list. - * So, we only reset the current resource file if WE opened a resource - * explicitly, and then only if the CurResFile is still the - * one we opened... - */ - - if (iOpenedResFile && (CurResFile() == fileRef)) { - UseResFile(saveRef); - } - - if (fileRef != -1) { - CloseResFile(fileRef); - } - - 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 behavior 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 may be 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 with a different permission. It it has, then return an error. - */ - - new = 1; - - if (flags & TCL_RESOURCE_CHECK_IF_OPEN) { - Tcl_HashSearch search; - short oldFileRef, filePermissionFlag; - 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); - filePermissionFlag = ( newFileRec.ioFCBFlags >> 12 ) & 0x1; - - - resourceHashPtr = Tcl_FirstHashEntry(&resourceTable, &search); - while (resourceHashPtr != NULL) { - oldFileRef = (short) Tcl_GetHashKey(&resourceTable, - resourceHashPtr); - if (oldFileRef == fileRef) { - new = 0; - break; - } - 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 ((err == noErr) - && (newFileRec.ioFCBVRefNum == oldFileRec.ioFCBVRefNum) - && (newFileRec.ioFCBFlNm == oldFileRec.ioFCBFlNm)) { - /* In MacOS 8.1 it seems like we get different file refs even though - * we pass the same file & permissions. This is not what Inside Mac - * says should happen, but it does, so if it does, then close the new res - * file and return the original one... - */ - - if (filePermissionFlag == ((oldFileRec.ioFCBFlags >> 12) & 0x1)) { - CloseResFile(fileRef); - new = 0; - break; - } else { - if (tokenPtr != NULL) { - Tcl_SetStringObj(tokenPtr, - "Resource already open with different permissions.", -1); - } - return TCL_ERROR; - } - } - resourceHashPtr = Tcl_NextHashEntry(&search); - } - } - - - /* - * If the file has already been opened with these same permissions, then it - * will be in our list and we will have set new to 0 above. - * So we will just return the token (if tokenPtr is non-null) - */ - - if (new) { - 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 deleted file mode 100644 index f0671b9..0000000 --- a/mac/tclMacResource.r +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacResource.r,v 1.2 1998/09/14 18:40:06 stanton Exp $ - */ - -#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 deleted file mode 100644 index aea4acf..0000000 --- a/mac/tclMacShLib.exp +++ /dev/null @@ -1,1071 +0,0 @@ -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 -TclAccess -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 -TclpAccess -TclMacCreateEnv -TclMacExitHandler -TclMacFOpenHack -TclMacInitExitToShell -TclMacInstallExitToShellPatch -TclMacOSErrorToPosixError -TclMacReadlink -TclMacRemoveTimer -TclMacStartTimer -TclpStat -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 -TclStat -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 deleted file mode 100644 index b36ae1d..0000000 --- a/mac/tclMacSock.c +++ /dev/null @@ -1,2615 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacSock.c,v 1.2 1998/09/14 18:40:06 stanton Exp $ - */ - -#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 deleted file mode 100644 index 3c982c5..0000000 --- a/mac/tclMacTest.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacTest.c,v 1.3 1998/11/10 06:49:51 jingham Exp $ - */ - -#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)); - 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 deleted file mode 100644 index 79633de..0000000 --- a/mac/tclMacTime.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacTime.c,v 1.2 1998/09/14 18:40:07 stanton Exp $ - */ - -#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(µs); - 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(µOffset); - initalized = true; - } - - Microseconds(µ); - -#ifndef NO_LONG_LONG - microPtr = (long long *) µ - *microPtr -= *((long long *) µOffset); - timePtr->sec = baseSeconds + (*microPtr / 1000000); - timePtr->usec = *microPtr % 1000000; -#else - SubtractUnsignedWide(µ, µOffset, µ); - - /* - * 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 deleted file mode 100644 index 8d99ee3..0000000 --- a/mac/tclMacUnix.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacUnix.c,v 1.2 1998/09/14 18:40:07 stanton Exp $ - */ - -#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 *)¶mBlock; - DirInfo *dpb = (DirInfo *)¶mBlock; - 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(¶mBlock); - 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(¶mBlock); - 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 deleted file mode 100644 index fd981c9..0000000 --- a/mac/tclMacUtil.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * 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. - * - * RCS: @(#) $Id: tclMacUtil.c,v 1.3 1998/11/10 06:49:55 jingham Exp $ - */ - -#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. */ - CONST 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; -} |
