diff options
Diffstat (limited to 'mac')
49 files changed, 0 insertions, 21275 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 84b09fc..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.4 1999/05/11 07:11:46 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_TclAppleScriptHeaderPPC" -#elif __CFM68K__ -#pragma precompile_target "MW_TclAppleScriptHeaderCFM68K" -#else -#pragma precompile_target "MW_TclAppleScriptHeader68K" -#endif - -#include "tclMacCommonPch.h" - -/* #define TCL_REGISTER_LIBRARY 1 */ -#define USE_TCL_STUBS - -/* - * 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 5253291..0000000 --- a/mac/MW_TclHeader.pch +++ /dev/null @@ -1,49 +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.7 1999/05/11 07:11:48 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" -#include "MoreFiles.h" -#include "MoreFilesExtras.h" - -#pragma export reset - diff --git a/mac/README b/mac/README deleted file mode 100644 index c7569cc..0000000 --- a/mac/README +++ /dev/null @@ -1,78 +0,0 @@ -Tcl 8.2 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.8 1999/06/25 23:29:53 welch Exp $ - -1. Introduction ---------------- - -This is the README file for the Macintosh version of the Tcl -scripting language. The home page for the Macintosh releases is - http://www.scriptics.com/mac/ - -A summary of what's new in this release is at - http://www.scriptics.com/software/whatsnew82.html - -A summary of Macintosh-specific features is at - http://www.scriptics.com/mac/features.html - - -2. 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.2.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.2.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.2.sea.hqx - - This release contains the complete source for Tcl 8.2. In - addition, Metrowerks CodeWarrior libraries and project files - are included. However, you must already have the More Files - package to compile this code. - -The "html" subdirectory contains reference documentation in -in the HTML format. You may also find these pages at: - - http://www.scriptics.com/man/tcl8.2/contents.html - -3. Compiling Tcl ----------------- - -In order to compile Macintosh Tcl you must have the -following items: - - CodeWarrior Pro 2 or 3 - Mac Tcl 8.1 (source) - More Files 1.4.3 - -The included project files should work fine. However, for -current release notes please check this page: - - http://www.scriptics.com/support/howto/compile.html#mac - -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 a051cc8..0000000 --- a/mac/tclMac.h +++ /dev/null @@ -1,38 +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.4 1999/03/10 05:52:51 stanton 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)); - -#include "tclPlatDecls.h" - -#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 c5daa8b..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.4 1999/05/11 07:11:51 jingham Exp $ - */ - -#include "tclInt.h" -#include "tclMacInt.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 c4e4746..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.5 1999/04/16 00:47:19 stanton 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 the interp's 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 4fc34e8..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.3 1999/04/16 00:47:19 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 the interp's 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 d863e9c..0000000 --- a/mac/tclMacBOAMain.c +++ /dev/null @@ -1,361 +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.3 1999/04/16 00:47:19 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, Tcl_GetStringResult(interp), -1); - Tcl_DStringAppend(&errStr, "\n", 1); - TclMacDoNotification(Tcl_DStringValue(&errStr)); - Tcl_DStringFree(&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, Tcl_GetStringResult(interp), -1); - TclMacDoNotification(Tcl_DStringValue(&errStr)); - Tcl_DStringFree(&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_GetString(objv[1])); - 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 2fbac8f..0000000 --- a/mac/tclMacChan.c +++ /dev/null @@ -1,1394 +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.6 1999/04/16 00:47:19 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 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; - -typedef struct ThreadSpecificData { - int initialized; /* True after the thread initializes */ - FileState *firstFilePtr; /* the head of the list of files managed - * that are being watched for file events. */ - Tcl_Channel stdinChannel; - Tcl_Channel stdoutChannel; /* Note - these seem unused */ - Tcl_Channel stderrChannel; -} ThreadSpecificData; - -static Tcl_ThreadDataKey dataKey; - -/* - * 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 ThreadSpecificData *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, - CONST char *string)); -static Tcl_Channel OpenFileChannel _ANSI_ARGS_((CONST 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; - - -/* - *---------------------------------------------------------------------- - * - * FileInit -- - * - * This function initializes the file channel event source. - * - * Results: - * None. - * - * Side effects: - * Creates a new event source. - * - *---------------------------------------------------------------------- - */ - -static ThreadSpecificData * -FileInit() -{ - ThreadSpecificData *tsdPtr = - (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); - if (tsdPtr == NULL) { - tsdPtr = TCL_TSD_INIT(&dataKey); - tsdPtr->firstFilePtr = NULL; - Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL); - Tcl_CreateThreadExitHandler(FileChannelExitHandler, NULL); - } - return tsdPtr; -} - -/* - *---------------------------------------------------------------------- - * - * 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); -} - -/* - *---------------------------------------------------------------------- - * - * 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 }; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (!(flags & TCL_FILE_EVENTS)) { - return; - } - - /* - * Check to see if there is a ready file. If so, poll. - */ - - for (infoPtr = tsdPtr->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 }; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - 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 = tsdPtr->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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - 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 = tsdPtr->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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - /* - * Invalidate the stdio cache if necessary. Note that we assume that - * the stdio file and channel pointers will become invalid at the same - * time. - * Do not close standard channels while in thread-exit. - */ - - fd = (int) ((FileState*)instanceData)->fileRef; - if (!TclInExit()) { - if (fd == 0) { - tsdPtr->stdinChannel = NULL; - } else if (fd == 1) { - tsdPtr->stdoutChannel = NULL; - } else if (fd == 2) { - tsdPtr->stderrChannel = NULL; - } else { - panic("recieved invalid std file"); - } - - if (close(fd) < 0) { - errorCode = errno; - } - } - return errorCode; -} - -/* - *---------------------------------------------------------------------- - * - * CommonGetHandle -- - * - * Called from Tcl_GetChannelHandle 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_GetString(objv[1]), - 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpGetDefaultStdChannel -- - * - * 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 -TclpGetDefaultStdChannel( - 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[16 + TCL_INTEGER_SPACE]; - 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 *native; - Tcl_DString ds, buffer; - int errorCode; - - mode = GetOpenMode(interp, modeString); - if (mode == -1) { - return NULL; - } - - if (Tcl_TranslateFileName(interp, fileName, &buffer) == NULL) { - return NULL; - } - native = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer), - Tcl_DStringLength(&buffer), &ds); - chan = OpenFileChannel(native, mode, permissions, &errorCode); - Tcl_DStringFree(&ds); - 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( - CONST char *fileName, /* Name of file to open (native). */ - 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[16 + TCL_INTEGER_SPACE]; - - /* - * 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; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_MakeFileChannel -- - * - * Makes a Tcl_Channel from an existing OS level file handle. - * - * Results: - * The Tcl_Channel created around the preexisting OS level file handle. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_Channel -Tcl_MakeFileChannel(handle, mode) - ClientData handle; /* OS level handle. */ - int mode; /* ORed combination of TCL_READABLE and - * TCL_WRITABLE to indicate file mode. */ -{ - /* - * Not implemented yet. - */ - - return NULL; -} - -/* - *---------------------------------------------------------------------- - * - * 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; - ThreadSpecificData *tsdPtr; - - tsdPtr = FileInit(); - - infoPtr->watchMask = mask; - if (infoPtr->watchMask) { - if (!oldMask) { - infoPtr->nextPtr = tsdPtr->firstFilePtr; - tsdPtr->firstFilePtr = infoPtr; - } - } else { - if (oldMask) { - /* - * Remove the file from the list of watched files. - */ - - for (nextPtrPtr = &(tsdPtr->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 the interp's 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. */ - CONST 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; - /* - * Guard against international characters before using byte oriented - * routines. - */ - - if (!(string[0] & 0x80) - && islower(UCHAR(string[0]))) { /* INTL: ISO only. */ - 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 347ff4e..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.4 1999/04/16 00:47:19 stanton 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 -TclpExit( - 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 dbd0680..0000000 --- a/mac/tclMacFCmd.c +++ /dev/null @@ -1,1535 +0,0 @@ -/* - * tclMacFCmd.c -- - * - * Implements the Macintosh specific portions of the file manipulation - * subcommands of the "file" command. - * - * Copyright (c) 1996-1998 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.5 1999/05/11 07:12:00 jingham 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, CONST char *fileName, - Tcl_Obj **attributePtrPtr)); -static int GetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, CONST char *fileName, - Tcl_Obj **readOnlyPtrPtr)); -static int SetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, CONST char *fileName, - Tcl_Obj *attributePtr)); -static int SetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp, - int objIndex, CONST 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, - ConstStr255Param srcName, short dstVRefNum, - long dstDirID,ConstStr255Param dstName)); -static int DoCopyDirectory _ANSI_ARGS_((CONST char *src, - CONST char *dst, Tcl_DString *errorPtr)); -static int DoCopyFile _ANSI_ARGS_((CONST char *src, - CONST char *dst)); -static int DoCreateDirectory _ANSI_ARGS_((CONST char *path)); -static int DoDeleteFile _ANSI_ARGS_((CONST char *path)); -static int DoRemoveDirectory _ANSI_ARGS_((CONST char *path, - int recursive, Tcl_DString *errorPtr)); -static int DoRenameFile _ANSI_ARGS_((CONST char *src, - CONST char *dst)); -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_((CONST 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, DoRenameFile -- - * - * 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( - CONST char *src, /* Pathname of file or dir to be renamed - * (UTF-8). */ - CONST char *dst) /* New pathname of file or directory - * (UTF-8). */ -{ - int result; - Tcl_DString srcString, dstString; - - Tcl_UtfToExternalDString(NULL, src, -1, &srcString); - Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); - result = DoRenameFile(Tcl_DStringValue(&srcString), - Tcl_DStringValue(&dstString)); - Tcl_DStringFree(&srcString); - Tcl_DStringFree(&dstString); - return result; -} - -static int -DoRenameFile( - CONST char *src, /* Pathname of file or dir to be renamed - * (native). */ - CONST char *dst) /* New pathname of file or directory - * (native). */ -{ - 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 (DoRemoveDirectory(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; -} - -/* - *-------------------------------------------------------------------------- - * - * 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; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpCopyFile, DoCopyFile -- - * - * 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( - CONST char *src, /* Pathname of file to be copied (UTF-8). */ - CONST char *dst) /* Pathname of file to copy to (UTF-8). */ -{ - int result; - Tcl_DString srcString, dstString; - - Tcl_UtfToExternalDString(NULL, src, -1, &srcString); - Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); - result = DoCopyFile(Tcl_DStringValue(&srcString), - Tcl_DStringValue(&dstString)); - Tcl_DStringFree(&srcString); - Tcl_DStringFree(&dstString); - return result; -} - -static int -DoCopyFile( - CONST char *src, /* Pathname of file to be copied (native). */ - CONST char *dst) /* Pathname of file to copy to (native). */ -{ - 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, DoDeleteFile -- - * - * 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( - CONST char *path) /* Pathname of file to be removed (UTF-8). */ -{ - int result; - Tcl_DString pathString; - - Tcl_UtfToExternalDString(NULL, path, -1, &pathString); - result = DoDeleteFile(Tcl_DStringValue(&pathString)); - Tcl_DStringFree(&pathString); - return result; -} - -static int -DoDeleteFile( - CONST char *path) /* Pathname of file to be removed (native). */ -{ - 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, DoCreateDirectory -- - * - * 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( - CONST char *path) /* Pathname of directory to create (UTF-8). */ -{ - int result; - Tcl_DString pathString; - - Tcl_UtfToExternalDString(NULL, path, -1, &pathString); - result = DoCreateDirectory(Tcl_DStringValue(&pathString)); - Tcl_DStringFree(&pathString); - return result; -} - -static int -DoCreateDirectory( - CONST char *path) /* Pathname of directory to create (native). */ -{ - 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, DoCopyDirectory -- - * - * 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( - CONST char *src, /* Pathname of directory to be copied - * (UTF-8). */ - CONST char *dst, /* Pathname of target directory (UTF-8). */ - Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free - * DString filled with UTF-8 name of file - * causing error. */ -{ - int result; - Tcl_DString srcString, dstString; - - Tcl_UtfToExternalDString(NULL, src, -1, &srcString); - Tcl_UtfToExternalDString(NULL, dst, -1, &dstString); - result = DoCopyDirectory(Tcl_DStringValue(&srcString), - Tcl_DStringValue(&dstString), errorPtr); - Tcl_DStringFree(&srcString); - Tcl_DStringFree(&dstString); - return result; -} - -static int -DoCopyDirectory( - CONST char *src, /* Pathname of directory to be copied - * (UTF-8). */ - CONST char *dst, /* Pathname of target directory (UTF-8). */ - Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free - * DString filled with UTF-8 name of file - * causing error. */ -{ - 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_ExternalToUtfDString(NULL, dst, -1, errorPtr); - } - 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 */ - ConstStr255Param srcName, /* name of source */ - short dstVRefNum, /* volume ref number of dst */ - long dstDirID, /* directory id of dst */ - ConstStr255Param dstName) /* name of dst directory */ -{ - return true; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpRemoveDirectory, DoRemoveDirectory -- - * - * 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( - CONST char *path, /* Pathname of directory to be removed - * (UTF-8). */ - int recursive, /* If non-zero, removes directories that - * are nonempty. Otherwise, will only remove - * empty directories. */ - Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free - * DString filled with UTF-8 name of file - * causing error. */ -{ - int result; - Tcl_DString pathString; - - Tcl_UtfToExternalDString(NULL, path, -1, &pathString); - result = DoRemoveDirectory(Tcl_DStringValue(&pathString), recursive, - errorPtr); - Tcl_DStringFree(&pathString); - - return result; -} - -static int -DoRemoveDirectory( - CONST char *path, /* Pathname of directory to be removed - * (native). */ - int recursive, /* If non-zero, removes directories that - * are nonempty. Otherwise, will only remove - * empty directories. */ - Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free - * DString filled with UTF-8 name of file - * causing error. */ -{ - 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_UtfToExternalDString(NULL, path, -1, errorPtr); - } - if (locked) { - FSpSetFLockCompat(&fileSpec); - } - errno = TclMacOSErrorToPosixError(err); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *--------------------------------------------------------------------------- - * - * GenerateUniqueName -- - * - * 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( - CONST 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. */ - CONST 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), - "could not read \"", 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. */ - CONST 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), - "could not read \"", 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. */ - CONST 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), - "could not read \"", 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. */ - CONST 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), - "could not read \"", 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; - Tcl_DString dstr; - - 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; - } - - Tcl_ExternalToUtfDString(NULL, (char *) &name[1], name[0], &dstr); - elemPtr = Tcl_NewStringObj(Tcl_DStringValue(&dstr), - Tcl_DStringLength(&dstr)); - Tcl_AppendToObj(elemPtr, ":", 1); - Tcl_ListObjAppendElement(interp, resultPtr, elemPtr); - - Tcl_DStringFree(&dstr); - - volIndex++; - } - - Tcl_SetObjResult(interp, resultPtr); - return TCL_OK; -} - diff --git a/mac/tclMacFile.c b/mac/tclMacFile.c deleted file mode 100644 index 45e0181..0000000 --- a/mac/tclMacFile.c +++ /dev/null @@ -1,918 +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-1998 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.7 1999/05/11 07:12:09 jingham 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 initialized = false; -static long gmt_offset; -TCL_DECLARE_MUTEX(gmtMutex) - - -/* - *---------------------------------------------------------------------- - * - * TclpFindExecutable -- - * - * This procedure computes the absolute path name of the current - * application, given its argv[0] value. However, this - * implementation doesn't 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. - * - *---------------------------------------------------------------------- - */ - -char * -TclpFindExecutable( - CONST 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; - Tcl_DString ds; - - TclInitSubsystems(argv0); - - 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); - HLock(pathName); - Tcl_ExternalToUtfDString(NULL, *pathName, pathLength, &ds); - HUnlock(pathName); - DisposeHandle(pathName); - - tclExecutableName = (char *) ckalloc((unsigned) - (Tcl_DStringLength(&ds) + 1)); - strcpy(tclExecutableName, Tcl_DStringValue(&ds)); - Tcl_DStringFree(&ds); - return tclExecutableName; -} - -/* - *---------------------------------------------------------------------- - * - * TclpMatchFiles -- - * - * 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 the interp's 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 -TclpMatchFiles( - 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 and must - * not be static.*/ -{ - 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; - Tcl_DString fileString; - - /* - * 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. - */ - - Tcl_ExternalToUtfDString(NULL, (char *) fileName + 1, fileName[0], - &fileString); - if (Tcl_StringMatch(Tcl_DStringValue(&fileString), pattern)) { - Tcl_DStringSetLength(dirPtr, baseLength); - Tcl_DStringAppend(dirPtr, Tcl_DStringValue(&fileString), -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) { - Tcl_DStringFree(&fileString); - break; - } - } - } - Tcl_DStringFree(&fileString); - - itemIndex++; - } - *patternEnd = savedChar; - - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclpAccess -- - * - * This function replaces the library version of access(). - * - * Results: - * See access documentation. - * - * Side effects: - * See access documentation. - * - *---------------------------------------------------------------------- - */ - -int -TclpAccess( - CONST char *path, /* Path of file to access (UTF-8). */ - int mode) /* Permission setting. */ -{ - HFileInfo fpb; - HVolumeParam vpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - Tcl_DString ds; - char *native; - int full_mode = 0; - - native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec); - Tcl_DStringFree(&ds); - - 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpChdir -- - * - * This function replaces the library version of chdir(). - * - * Results: - * See chdir() documentation. - * - * Side effects: - * See chdir() documentation. Also the cache maintained used by - * TclGetCwd() is deallocated and set to NULL. - * - *---------------------------------------------------------------------- - */ - -int -TclpChdir( - CONST char *dirName) /* Path to new working directory (UTF-8). */ -{ - FSSpec spec; - OSErr err; - Boolean isFolder; - long dirID; - Tcl_DString ds; - char *native; - - native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &spec); - Tcl_DStringFree(&ds); - - if (err != noErr) { - errno = ENOENT; - return -1; - } - - err = FSpGetDirectoryID(&spec, &dirID, &isFolder); - if (err != noErr) { - errno = ENOENT; - return -1; - } - - if (isFolder != true) { - errno = ENOTDIR; - return -1; - } - - err = FSpSetDefaultDir(&spec); - if (err != noErr) { - switch (err) { - case afpAccessDenied: - errno = EACCES; - break; - default: - errno = ENOENT; - } - return -1; - } - - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * TclpGetCwd -- - * - * This function replaces the library version of getcwd(). - * - * Results: - * The result is a pointer to a string specifying the current - * directory, or NULL if the current directory could not be - * determined. If NULL is returned, an error message is left in the - * interp's result. Storage for the result string is allocated in - * bufferPtr; the caller must call Tcl_DStringFree() when the result - * is no longer needed. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -char * -TclpGetCwd( - Tcl_Interp *interp, /* If non-NULL, used for error reporting. */ - Tcl_DString *bufferPtr) /* Uninitialized or free DString filled - * with name of current directory. */ -{ - FSSpec theSpec; - int length; - Handle pathHandle = NULL; - - if (FSpGetDefaultDir(&theSpec) != noErr) { - if (interp != NULL) { - Tcl_SetResult(interp, "error getting working directory name", - TCL_STATIC); - } - return NULL; - } - if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) { - if (interp != NULL) { - Tcl_SetResult(interp, "error getting working directory name", - TCL_STATIC); - } - return NULL; - } - HLock(pathHandle); - Tcl_ExternalToUtfDString(NULL, *pathHandle, length, bufferPtr); - HUnlock(pathHandle); - DisposeHandle(pathHandle); - - return Tcl_DStringValue(bufferPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclpReadlink -- - * - * This function replaces the library version of readlink(). - * - * Results: - * The result is a pointer to a string specifying the contents - * of the symbolic link given by 'path', or NULL if the symbolic - * link could not be read. Storage for the result string is - * allocated in bufferPtr; the caller must call Tcl_DStringFree() - * when the result is no longer needed. - * - * Side effects: - * See readlink() documentation. - * - *--------------------------------------------------------------------------- - */ - -char * -TclpReadlink( - CONST char *path, /* Path of file to readlink (UTF-8). */ - Tcl_DString *linkPtr) /* Uninitialized or free DString filled - * with contents of link (UTF-8). */ -{ - HFileInfo fpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - Boolean wasAlias; - long dirID; - char fileName[257]; - char *end; - Handle theString = NULL; - int pathSize; - Tcl_DString ds; - char *native; - - native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); - - /* - * Remove ending colons if they exist. - */ - - while ((strlen(native) != 0) && (path[strlen(native) - 1] == ':')) { - native[strlen(native) - 1] = NULL; - } - - if (strchr(native, ':') == NULL) { - strcpy(fileName + 1, native); - native = NULL; - } else { - end = strrchr(native, ':') + 1; - strcpy(fileName + 1, end); - *end = NULL; - } - fileName[0] = (char) strlen(fileName + 1); - - /* - * Create the file spec for the directory of the file - * we want to look at. - */ - - if (native != NULL) { - err = FSpLocationFromPath(strlen(native), native, &fileSpec); - if (err != noErr) { - Tcl_DStringFree(&ds); - errno = EINVAL; - return NULL; - } - } else { - FSMakeFSSpecCompat(0, 0, NULL, &fileSpec); - } - Tcl_DStringFree(&ds); - - /* - * 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 NULL; - } else { - if (fpb.ioFlAttrib & 0x10) { - errno = EINVAL; - return NULL; - } else { - if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { - /* - * The file is a link! - */ - } else { - errno = EINVAL; - return NULL; - } - } - } - - /* - * 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) { - DisposeHandle(theString); - errno = ENAMETOOLONG; - return NULL; - } - } else { - errno = EINVAL; - return NULL; - } - - Tcl_ExternalToUtfDString(NULL, *theString, pathSize, linkPtr); - DisposeHandle(theString); - - return Tcl_DStringValue(linkPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclpLstat -- - * - * This function replaces the library version of lstat(). - * - * Results: - * See stat() documentation. - * - * Side effects: - * See stat() documentation. - * - *---------------------------------------------------------------------- - */ - -int -TclpLstat( - CONST char *path, /* Path of file to stat (in UTF-8). */ - struct stat *bufPtr) /* Filled with results of stat call. */ -{ - /* - * FIXME: Emulate TclpLstat - */ - - return TclpStat(path, bufPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclpStat -- - * - * This function replaces the library version of stat(). - * - * Results: - * See stat() documentation. - * - * Side effects: - * See stat() documentation. - * - *---------------------------------------------------------------------- - */ - -int -TclpStat( - CONST char *path, /* Path of file to stat (in UTF-8). */ - struct stat *bufPtr) /* Filled with results of stat call. */ -{ - HFileInfo fpb; - HVolumeParam vpb; - OSErr err; - FSSpec fileSpec; - Boolean isDirectory; - long dirID; - Tcl_DString ds; - - path = Tcl_UtfToExternalDString(NULL, path, -1, &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), path, &fileSpec); - Tcl_DStringFree(&ds); - - 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 && bufPtr != NULL) { - /* - * Files are always readable by everyone. - */ - - bufPtr->st_mode = S_IRUSR | S_IRGRP | S_IROTH; - - /* - * Use the Volume Info & File Info to fill out stat buf. - */ - if (fpb.ioFlAttrib & 0x10) { - bufPtr->st_mode |= S_IFDIR; - bufPtr->st_nlink = 2; - } else { - bufPtr->st_nlink = 1; - if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { - bufPtr->st_mode |= S_IFLNK; - } else { - bufPtr->st_mode |= S_IFREG; - } - } - if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { - /* - * Directories and applications are executable by everyone. - */ - - bufPtr->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; - } - if ((fpb.ioFlAttrib & 0x01) == 0){ - /* - * If not locked, then everyone has write acces. - */ - - bufPtr->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - } - bufPtr->st_ino = fpb.ioDirID; - bufPtr->st_dev = fpb.ioVRefNum; - bufPtr->st_uid = -1; - bufPtr->st_gid = -1; - bufPtr->st_rdev = 0; - bufPtr->st_size = fpb.ioFlLgLen; - bufPtr->st_blksize = vpb.ioVAlBlkSiz; - bufPtr->st_blocks = (bufPtr->st_size + bufPtr->st_blksize - 1) - / bufPtr->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". - */ - - Tcl_MutexLock(&gmtMutex); - if (initialized == false) { - MachineLocation loc; - - ReadLocation(&loc); - gmt_offset = loc.u.gmtDelta & 0x00ffffff; - if (gmt_offset & 0x00800000) { - gmt_offset = gmt_offset | 0xff000000; - } - initialized = true; - } - Tcl_MutexUnlock(&gmtMutex); - - bufPtr->st_atime = bufPtr->st_mtime = fpb.ioFlMdDat - gmt_offset; - bufPtr->st_ctime = fpb.ioFlCrDat - gmt_offset; - } - } - - if (err != noErr) { - errno = TclMacOSErrorToPosixError(err); - } - - return (err == noErr ? 0 : -1); -} - -/* - *---------------------------------------------------------------------- - * - * 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; -} - -/* - *---------------------------------------------------------------------- - * - * 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; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpGetUserHome -- - * - * This function takes the specified user name and finds their - * home directory. - * - * Results: - * The result is a pointer to a string specifying the user's home - * directory, or NULL if the user's home directory could not be - * determined. Storage for the result string is allocated in - * bufferPtr; the caller must call Tcl_DStringFree() when the result - * is no longer needed. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -char * -TclpGetUserHome(name, bufferPtr) - CONST char *name; /* User name for desired home directory. */ - Tcl_DString *bufferPtr; /* Uninitialized or free DString filled - * with name of user's home directory. */ -{ - return NULL; -} - -/* - *---------------------------------------------------------------------- - * - * 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; - } -} -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; -}
\ No newline at end of file diff --git a/mac/tclMacInit.c b/mac/tclMacInit.c deleted file mode 100644 index 53ab851..0000000 --- a/mac/tclMacInit.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * tclMacInit.c -- - * - * Contains the Mac-specific interpreter initialization functions. - * - * Copyright (c) 1995-1998 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.4 1999/05/11 07:12:16 jingham Exp $ - */ - -#include <AppleEvents.h> -#include <AEDataModel.h> -#include <AEObjects.h> -#include <AEPackObject.h> -#include <AERegistry.h> -#include <Files.h> -#include <Folders.h> -#include <Gestalt.h> -#include <TextUtils.h> -#include <Resources.h> -#include <Strings.h> -#include "tclInt.h" -#include "tclMacInt.h" -#include "tclPort.h" - -/* - * The following string is the startup script executed in new - * interpreters. It looks on the library path and in the resource fork for - * a script "init.tcl" that is compatible with this version of Tcl. The - * init.tcl script does all of the real work of initialization. - */ - -static char initCmd[] = "\ -proc sourcePath {file} {\n\ - set dirs {}\n\ - foreach i $::auto_path {\n\ - set init [file join $i $file.tcl]\n\ - if {[catch {uplevel #0 [list source $init]}] == 0} {\n\ - return\n\ - }\n\ - }\n\ - if {[catch {uplevel #0 [list source -rsrc $file]}] == 0} {\n\ - return\n\ - }\n\ - rename sourcePath {}\n\ - set msg \"can't find $file resource or a usable $file.tcl file\n\"\n\ - append msg \"in the following directories:\n\"\n\ - append msg \" $::auto_path\n\"\n\ - append msg \" perhaps you need to install Tcl or set your \n\"\n\ - append msg \"TCL_LIBRARY environment variable?\"\n\ - error $msg\n\ -}\n\ -if {[info exists env(EXT_FOLDER)]} {\n\ - lappend tcl_pkgPath [file join $env(EXT_FOLDER) {:Tool Command Language}]\n\ -}\n\ -if {[info exists tcl_pkgPath] == 0} {\n\ - set tcl_pkgPath {no extension folder}\n\ -}\n\ -sourcePath Init\n\ -sourcePath Auto\n\ -sourcePath Package\n\ -sourcePath History\n\ -sourcePath Word\n\ -rename sourcePath {}"; - -/* - * The following structures are used to map the script/language codes of a - * font to the name that should be passed to Tcl_GetEncoding() to obtain - * the encoding for that font. The set of numeric constants is fixed and - * defined by Apple. - */ - -typedef struct Map { - int numKey; - char *strKey; -} Map; - -static Map scriptMap[] = { - {smRoman, "macRoman"}, - {smJapanese, "macJapan"}, - {smTradChinese, "macChinese"}, - {smKorean, "macKorean"}, - {smArabic, "macArabic"}, - {smHebrew, "macHebrew"}, - {smGreek, "macGreek"}, - {smCyrillic, "macCyrillic"}, - {smRSymbol, "macRSymbol"}, - {smDevanagari, "macDevanagari"}, - {smGurmukhi, "macGurmukhi"}, - {smGujarati, "macGujarati"}, - {smOriya, "macOriya"}, - {smBengali, "macBengali"}, - {smTamil, "macTamil"}, - {smTelugu, "macTelugu"}, - {smKannada, "macKannada"}, - {smMalayalam, "macMalayalam"}, - {smSinhalese, "macSinhalese"}, - {smBurmese, "macBurmese"}, - {smKhmer, "macKhmer"}, - {smThai, "macThailand"}, - {smLaotian, "macLaos"}, - {smGeorgian, "macGeorgia"}, - {smArmenian, "macArmenia"}, - {smSimpChinese, "macSimpChinese"}, - {smTibetan, "macTIbet"}, - {smMongolian, "macMongolia"}, - {smGeez, "macEthiopia"}, - {smEastEurRoman, "macCentEuro"}, - {smVietnamese, "macVietnam"}, - {smExtArabic, "macSindhi"}, - {NULL, NULL} -}; - -static Map romanMap[] = { - {langCroatian, "macCroatian"}, - {langSlovenian, "macCroatian"}, - {langIcelandic, "macIceland"}, - {langRomanian, "macRomania"}, - {langTurkish, "macTurkish"}, - {langGreek, "macGreek"}, - {NULL, NULL} -}; - -static Map cyrillicMap[] = { - {langUkrainian, "macUkraine"}, - {langBulgarian, "macBulgaria"}, - {NULL, NULL} -}; - -static int GetFinderFont(int *finderID); - - -/* - *---------------------------------------------------------------------- - * - * GetFinderFont -- - * - * Gets the "views" font of the Macintosh Finder - * - * Results: - * Standard Tcl result, and sets finderID to the font family - * id for the current finder font. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static int -GetFinderFont(int *finderID) -{ - OSErr err = noErr; - OSType finderPrefs, viewFont = 'vfnt'; - DescType returnType; - Size returnSize; - long result, sys8Mask = 0x0800; - static AppleEvent outgoingAevt = {typeNull, NULL}; - AppleEvent returnAevt; - AEAddressDesc fndrAddress; - AEDesc nullContainer = {typeNull, NULL}, - tempDesc = {typeNull, NULL}, - tempDesc2 = {typeNull, NULL}, - finalDesc = {typeNull, NULL}; - const OSType finderSignature = 'MACS'; - - - if (outgoingAevt.descriptorType == typeNull) { - if ((Gestalt(gestaltSystemVersion, &result) != noErr) - || (result >= sys8Mask)) { - finderPrefs = 'pfrp'; - } else { - finderPrefs = 'pvwp'; - } - - AECreateDesc(typeApplSignature, &finderSignature, - sizeof(finderSignature), &fndrAddress); - - err = AECreateAppleEvent(kAECoreSuite, kAEGetData, &fndrAddress, - kAutoGenerateReturnID, kAnyTransactionID, &outgoingAevt); - - AEDisposeDesc(&fndrAddress); - - /* - * The structure is: - * the property view font ('vfnt') - * of the property view preferences ('pvwp') - * of the Null Container (i.e. the Finder itself). - */ - - AECreateDesc(typeType, &finderPrefs, sizeof(finderPrefs), &tempDesc); - err = CreateObjSpecifier(typeType, &nullContainer, formPropertyID, - &tempDesc, true, &tempDesc2); - AECreateDesc(typeType, &viewFont, sizeof(viewFont), &tempDesc); - err = CreateObjSpecifier(typeType, &tempDesc2, formPropertyID, - &tempDesc, true, &finalDesc); - - AEPutKeyDesc(&outgoingAevt, keyDirectObject, &finalDesc); - AEDisposeDesc(&finalDesc); - } - - err = AESend(&outgoingAevt, &returnAevt, kAEWaitReply, kAEHighPriority, - kAEDefaultTimeout, NULL, NULL); - if (err == noErr) { - err = AEGetKeyPtr(&returnAevt, keyDirectObject, typeInteger, - &returnType, (void *) finderID, sizeof(int), &returnSize); - if (err == noErr) { - return TCL_OK; - } - } - return TCL_ERROR; -} - -/* - *--------------------------------------------------------------------------- - * - * TclMacGetFontEncoding -- - * - * Determine the encoding of the specified font. The encoding - * can be used to convert bytes from UTF-8 into the encoding of - * that font. - * - * Results: - * The return value is a string that specifies the font's encoding - * and that can be passed to Tcl_GetEncoding() to construct the - * encoding. If the font's encoding could not be identified, NULL - * is returned. - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ - -char * -TclMacGetFontEncoding( - int fontId) -{ - int script, lang; - char *name; - Map *mapPtr; - - script = FontToScript(fontId); - lang = GetScriptVariable(script, smScriptLang); - name = NULL; - if (script == smRoman) { - for (mapPtr = romanMap; mapPtr->strKey != NULL; mapPtr++) { - if (mapPtr->numKey == lang) { - name = mapPtr->strKey; - break; - } - } - } else if (script == smCyrillic) { - for (mapPtr = cyrillicMap; mapPtr->strKey != NULL; mapPtr++) { - if (mapPtr->numKey == lang) { - name = mapPtr->strKey; - break; - } - } - } - if (name == NULL) { - for (mapPtr = scriptMap; mapPtr->strKey != NULL; mapPtr++) { - if (mapPtr->numKey == script) { - name = mapPtr->strKey; - break; - } - } - } - return name; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpInitPlatform -- - * - * Initialize all the platform-dependant things like signals and - * floating-point error handling. - * - * Called at process initialization time. - * - * Results: - * None. - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ - -void -TclpInitPlatform() -{ - tclPlatform = TCL_PLATFORM_MAC; -} - -/* - *--------------------------------------------------------------------------- - * - * TclpInitLibraryPath -- - * - * Initialize the library path at startup. We have a minor - * metacircular problem that we don't know the encoding of the - * operating system but we may need to talk to operating system - * to find the library directories so that we know how to talk to - * the operating system. - * - * We do not know the encoding of the operating system. - * We do know that the encoding is some multibyte encoding. - * In that multibyte encoding, the characters 0..127 are equivalent - * to ascii. - * - * So although we don't know the encoding, it's safe: - * to look for the last colon character in a path in the encoding. - * to append an ascii string to a path. - * to pass those strings back to the operating system. - * - * But any strings that we remembered before we knew the encoding of - * the operating system must be translated to UTF-8 once we know the - * encoding so that the rest of Tcl can use those strings. - * - * This call sets the library path to strings in the unknown native - * encoding. TclpSetInitialEncodings() will translate the library - * path from the native encoding to UTF-8 as soon as it determines - * what the native encoding actually is. - * - * Called at process initialization time. - * - * Results: - * None. - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ - -void -TclpInitLibraryPath(argv0) - CONST char *argv0; /* Name of executable from argv[0] to main(). - * Not used because we can determine the name - * by querying the module handle. */ -{ - Tcl_Obj *objPtr, *pathPtr; - char *str; - Tcl_DString ds; - - TclMacCreateEnv(); - - pathPtr = Tcl_NewObj(); - - str = TclGetEnv("TCL_LIBRARY", &ds); - if ((str != NULL) && (str[0] != '\0')) { - /* - * If TCL_LIBRARY is set, search there. - */ - - objPtr = Tcl_NewStringObj(str, -1); - Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); - Tcl_DStringFree(&ds); - } - - objPtr = TclGetLibraryPath(); - if (objPtr != NULL) { - Tcl_ListObjAppendList(NULL, pathPtr, objPtr); - } - - /* - * lappend path [file join $env(EXT_FOLDER) \ - * ":Tool Command Language:tcl[info version]" - */ - - str = TclGetEnv("EXT_FOLDER", &ds); - if ((str != NULL) && (str[0] != '\0')) { - objPtr = Tcl_NewStringObj(str, -1); - if (str[strlen(str) - 1] != ':') { - Tcl_AppendToObj(objPtr, ":", 1); - } - Tcl_AppendToObj(objPtr, "Tool Command Language:tcl" TCL_VERSION, -1); - Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); - Tcl_DStringFree(&ds); - } - TclSetLibraryPath(pathPtr); -} - -/* - *--------------------------------------------------------------------------- - * - * TclpSetInitialEncodings -- - * - * Based on the locale, determine the encoding of the operating - * system and the default encoding for newly opened files. - * - * Called at process initialization time. - * - * Results: - * None. - * - * Side effects: - * The Tcl library path is converted from native encoding to UTF-8. - * - *--------------------------------------------------------------------------- - */ - -void -TclpSetInitialEncodings() -{ - CONST char *encoding; - Tcl_Obj *pathPtr; - int fontId; - - fontId = 0; - GetFinderFont(&fontId); - encoding = TclMacGetFontEncoding(fontId); - if (encoding == NULL) { - encoding = "macRoman"; - } - - Tcl_SetSystemEncoding(NULL, encoding); - - /* - * Until the system encoding was actually set, the library path was - * actually in the native multi-byte encoding, and not really UTF-8 - * as advertised. We cheated as follows: - * - * 1. It was safe to allow the Tcl_SetSystemEncoding() call to - * append the ASCII chars that make up the encoding's filename to - * the names (in the native encoding) of directories in the library - * path, since all Unix multi-byte encodings have ASCII in the - * beginning. - * - * 2. To open the encoding file, the native bytes in the file name - * were passed to the OS, without translating from UTF-8 to native, - * because the name was already in the native encoding. - * - * Now that the system encoding was actually successfully set, - * translate all the names in the library path to UTF-8. That way, - * next time we search the library path, we'll translate the names - * from UTF-8 to the system encoding which will be the native - * encoding. - */ - - pathPtr = TclGetLibraryPath(); - if (pathPtr != NULL) { - int i, objc; - Tcl_Obj **objv; - - objc = 0; - Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); - for (i = 0; i < objc; i++) { - int length; - char *string; - Tcl_DString ds; - - string = Tcl_GetStringFromObj(objv[i], &length); - Tcl_ExternalToUtfDString(NULL, string, length, &ds); - Tcl_SetStringObj(objv[i], Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds)); - Tcl_DStringFree(&ds); - } - } - - /* - * Keep the iso8859-1 encoding preloaded. The IO package uses it for - * gets on a binary channel. - */ - - Tcl_GetEncoding(NULL, "iso8859-1"); -} - -/* - *--------------------------------------------------------------------------- - * - * TclpSetVariables -- - * - * Performs platform-specific interpreter initialization related to - * the tcl_library and tcl_platform variables, and other platform- - * specific things. - * - * Results: - * None. - * - * Side effects: - * Sets "tcl_library" and "tcl_platform" Tcl variables. - * - *---------------------------------------------------------------------- - */ - -void -TclpSetVariables(interp) - Tcl_Interp *interp; -{ - long int gestaltResult; - int minor, major, objc; - Tcl_Obj **objv; - char versStr[2 * TCL_INTEGER_SPACE]; - char *str; - Tcl_Obj *pathPtr; - Tcl_DString ds; - - str = "no library"; - pathPtr = TclGetLibraryPath(); - if (pathPtr != NULL) { - objc = 0; - Tcl_ListObjGetElements(NULL, pathPtr, &objc, &objv); - if (objc > 0) { - str = Tcl_GetStringFromObj(objv[0], NULL); - } - } - Tcl_SetVar(interp, "tcl_library", str, TCL_GLOBAL_ONLY); - - if (pathPtr != NULL) { - Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, pathPtr, TCL_GLOBAL_ONLY); - } - - 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 - - /* - * Copy USER or LOGIN environment variable into tcl_platform(user) - * These are set by SystemVariables in tclMacEnv.c - */ - - Tcl_DStringInit(&ds); - str = TclGetEnv("USER", &ds); - if (str == NULL) { - str = TclGetEnv("LOGIN", &ds); - if (str == NULL) { - str = ""; - } - } - Tcl_SetVar2(interp, "tcl_platform", "user", str, TCL_GLOBAL_ONLY); - Tcl_DStringFree(&ds); -} - -/* - *---------------------------------------------------------------------- - * - * 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; -} - -/* - *---------------------------------------------------------------------- - * - * TclpFindVariable -- - * - * Locate the entry in environ for a given name. On Unix and Macthis - * routine is case sensitive, on Windows this matches mixed case. - * - * Results: - * The return value is the index in environ of an entry with the - * name "name", or -1 if there is no such entry. The integer at - * *lengthPtr is filled in with the length of name (if a matching - * entry is found) or the length of the environ array (if no matching - * entry is found). - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TclpFindVariable(name, lengthPtr) - CONST char *name; /* Name of desired environment variable - * (native). */ - int *lengthPtr; /* Used to return length of name (for - * successful searches) or number of non-NULL - * entries in environ (for unsuccessful - * searches). */ -{ - int i, result = -1; - register CONST char *env, *p1, *p2; - Tcl_DString envString; - - Tcl_DStringInit(&envString); - for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) { - p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString); - p2 = name; - - for (; *p2 == *p1; p1++, p2++) { - /* NULL loop body. */ - } - if ((*p1 == '=') && (*p2 == '\0')) { - *lengthPtr = p2 - name; - result = i; - goto done; - } - - Tcl_DStringFree(&envString); - } - - *lengthPtr = i; - - done: - Tcl_DStringFree(&envString); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * 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 the interp's 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. */ -{ - Tcl_Obj *pathPtr; - - /* - * 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. - */ - - pathPtr = TclGetLibraryPath(); - if (pathPtr == NULL) { - pathPtr = Tcl_NewObj(); - } - Tcl_SetVar2Ex(interp, "auto_path", NULL, pathPtr, TCL_GLOBAL_ONLY); - 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_WriteObj(errChannel, Tcl_GetObjResult(interp)); - Tcl_WriteChars(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_WriteObj(errChannel, Tcl_GetObjResult(interp)); - Tcl_WriteChars(errChannel, "\n", 1); - } - } - Tcl_ResetResult(interp); - ReleaseResource(h); - } - } -} diff --git a/mac/tclMacInt.h b/mac/tclMacInt.h deleted file mode 100644 index 9e94e61..0000000 --- a/mac/tclMacInt.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * tclMacInt.h -- - * - * Declarations of Macintosh specific shared variables and procedures. - * - * Copyright (c) 1996-1998 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.5 1999/05/11 07:12:19 jingham 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. - */ - -/* - * Prototypes of Mac only internal functions. - */ - -EXTERN char * TclMacGetFontEncoding _ANSI_ARGS_((int fontId)); -EXTERN int TclMacHaveThreads(void); - -#include "tclPort.h" -#include "tclPlatDecls.h" -#include "tclIntPlatDecls.h" - -#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 eda1f7f..0000000 --- a/mac/tclMacLibrary.r +++ /dev/null @@ -1,221 +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.3 1999/04/16 00:47:20 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". - */ - -#include "tclMacTclCode.r" - -/* - * 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 622eb65..0000000 --- a/mac/tclMacLoad.c +++ /dev/null @@ -1,284 +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-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: tclMacLoad.c,v 1.3 1999/04/16 00:47:20 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 - * the interp's result. - * - * Side effects: - * New binary code is loaded. - * - *---------------------------------------------------------------------- - */ - -int -TclpLoadFile( - 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. */ - ClientData *clientDataPtr) /* Filled with token for dynamically loaded - * file which will be passed back to - * TclpUnloadFile() to unload the file. */ -{ - 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; - Tcl_DString ds; - char *native; - - /* - * 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); - Tcl_UtfToLower(packageName); - *(Tcl_UtfAtIndex(packageName, Tcl_NumUtfChars(packageName, -1) - 5)) = 0; - - native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); - err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec); - Tcl_DStringFree(&ds); - - if (err != noErr) { - Tcl_SetResult(interp, "could not locate shared library", TCL_STATIC); - return TCL_ERROR; - } - - /* - * See if this fragment has a 'cfrg' resource. It will tell us where - * 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) { - Tcl_SetResult(interp, - "could not find Initialization routine in library", - TCL_STATIC); - return TCL_ERROR; - } - - c2pstr(sym2); - err = FindSymbol(connID, (StringPtr) sym2, (Ptr *) proc2Ptr, &symClass); - p2cstr((StringPtr) sym2); - if (err != fragNoErr || symClass == kDataCFragSymbol) { - *proc2Ptr = NULL; - } - - *clientDataPtr = (ClientData) connID; - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * TclpUnloadFile -- - * - * Unloads a dynamically loaded binary code file from memory. - * Code pointers in the formerly loaded file are no longer valid - * after calling this function. - * - * Results: - * None. - * - * Side effects: - * Does nothing. Can anything be done? - * - *---------------------------------------------------------------------- - */ - -void -TclpUnloadFile(clientData) - ClientData clientData; /* ClientData returned by a previous call - * to TclpLoadFile(). The clientData is - * a token that represents the loaded - * file. */ -{ -} - -/* - *---------------------------------------------------------------------- - * - * 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 773490f..0000000 --- a/mac/tclMacNotify.c +++ /dev/null @@ -1,554 +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. - * - * The Mac notifier only polls for system and OS events, so it is process - * wide, rather than thread specific. However, this means that the convert - * event proc will have to arbitrate which events go to which threads. - * - * 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.3 1999/04/16 00:47:20 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> -#include <Threads.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)); - -/* - *---------------------------------------------------------------------- - * - * Tcl_InitNotifier -- - * - * Initializes the platform specific notifier state. There is no thread - * specific platform notifier on the Mac, so this really doesn't do - * anything. However, we need to return the ThreadID, since the generic - * notifier hands this back to us in AlertThread. - * - * Results: - * Returns the threadID for this thread. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -ClientData -Tcl_InitNotifier() -{ - -#ifdef TCL_THREADS - ThreadID curThread; - if (TclMacHaveThreads()) { - GetCurrentThread(&curThread); - return (ClientData) curThread; - } else { - return NULL; - } -#else - return NULL; -#endif - -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_FinalizeNotifier -- - * - * This function is called to cleanup the notifier state before - * a thread is terminated. There is no platform thread specific - * notifier, so this does nothing. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_FinalizeNotifier(clientData) - ClientData clientData; /* Pointer to notifier data. */ -{ - /* Nothing to do on the Mac */ -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_AlertNotifier -- - * - * Wake up the specified notifier from any thread. This routine - * is called by the platform independent notifier code whenever - * the Tcl_ThreadAlert routine is called. This routine is - * guaranteed not to be called on a given notifier after - * Tcl_FinalizeNotifier is called for that notifier. - * - * Results: - * None. - * - * Side effects: - * Calls YieldToThread from this thread. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_AlertNotifier(clientData) - ClientData clientData; /* Pointer to thread data. */ -{ - -#ifdef TCL_THREADS - if (TclMacHaveThreads()) { - YieldToThread((ThreadID) clientData); - } -#endif - -} - -/* - *---------------------------------------------------------------------- - * - * InitNotifier -- - * - * Initializes the notifier structure. Note - this function is never - * used. - * - * 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. This function is never used, since InitNotifier - * isn't either. - * - * 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_ServiceModeHook -- - * - * This function is invoked whenever the service mode changes. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ServiceModeHook(mode) - int mode; /* Either TCL_SERVICE_ALL, or - * TCL_SERVICE_NONE. */ -{ -} - -/* - *---------------------------------------------------------------------- - * - * 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); - - /* - * Yield time to nay other thread at this point. If we find that the - * apps thrash too switching between threads, we can put a timer here, - * and only yield when the timer fires. - */ - - if (TclMacHaveThreads()) { - YieldToAnyThread(); - } - - 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 (TclMacHaveThreads()) { - YieldToAnyThread(); - } - 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 e45c746..0000000 --- a/mac/tclMacOSA.c +++ /dev/null @@ -1,2945 +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.4 1999/05/11 07:12:36 jingham 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; - - /* - * Perform the required stubs magic... - */ - - if (!Tcl_InitStubs(interp, "8.0", 0)) { - return TCL_ERROR; - } - - /* - * 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(16 + TCL_INTEGER_SPACE); - 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[16 + TCL_INTEGER_SPACE]; - 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[16 + TCL_INTEGER_SPACE]; - 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 31ffcb0..0000000 --- a/mac/tclMacPort.h +++ /dev/null @@ -1,292 +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.9 1999/05/11 07:12:45 jingham Exp $ - */ - - -#ifndef _MACPORT -#define _MACPORT - -#ifndef _TCLINT -# include "tclInt.h" -#endif - -/* - *--------------------------------------------------------------------------- - * The following sets of #includes and #ifdefs are required to get Tcl to - * compile on the macintosh. - *--------------------------------------------------------------------------- - */ - -#include "tclErrno.h" -#include <float.h> - -#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 /* __MWERKS__ */ - -/* - * 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 - -/* - * 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 WAIT_STATUS_TYPE int -#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) - -/* - * Make sure that MAXPATHLEN is defined. - */ - -#ifndef MAXPATHLEN -# ifdef PATH_MAX -# define MAXPATHLEN PATH_MAX -# else -# define MAXPATHLEN 2048 -# endif -#endif - -/* - * 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 - -/* - * Variables provided by the C library. - */ - -extern char **environ; - -/* - *--------------------------------------------------------------------------- - * The following macros and declarations represent the interface between - * generic and mac-specific parts of Tcl. Some of the macros may override - * functions declared in tclInt.h. - *--------------------------------------------------------------------------- - */ - -/* - * The default platform eol translation on Mac is TCL_TRANSLATE_CR: - */ - -#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CR - -/* - * Declare dynamic loading extension macro. - */ - -#define TCL_SHLIB_EXT ".shlb" - -/* - * The following define is bogus and needs to be fixed. It claims that - * struct tm has the timezone string in it, which is not true. However, - * the code that works around this fact does not compile on the Mac, since - * it relies on the fact that time.h has a "timezone" variable, which the - * Metrowerks time.h does not have... - * - * The Mac timezone stuff never worked (clock format 0 -format %Z returns "Z") - * so this just keeps the status quo. The real answer is to not use the - * MSL strftime, and provide the needed compat functions... - * - */ - -#define HAVE_TM_ZONE - -/* - * The following macros have trivial definitions, allowing generic code to - * address platform-specific issues. - */ - -#define TclpAsyncMark(async) -#define TclpGetPid(pid) ((unsigned long) (pid)) -#define TclSetSystemEnv(a,b) -#define tzset() - -/* - * 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. - */ -/* int TclpStat(const char *path, struct stat *bufPtr); */ -int TclpLstat(const char *path, struct stat *bufPtr); - -char *TclpFindExecutable(const char *argv0); -int TclpFindVariable(CONST char *name, int *lengthPtr); - -#define fopen(path, mode) TclMacFOpenHack(path, mode) -#define readlink(fileName, buffer, size) TclMacReadlink(fileName, buffer, size) -#ifdef TCL_TEST -#define chmod(path, mode) TclMacChmod(path, mode) -#endif - -/* - * Prototypes needed for compatability - */ - -/* EXTERN int strncasecmp _ANSI_ARGS_((CONST char *s1, - CONST char *s2, size_t n)); */ - -/* - * 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 - -/* - * Platform specific mutex definition used by memory allocators. - * These are all no-ops on the Macintosh, since the threads are - * all cooperative. - */ - -#ifdef TCL_THREADS -typedef int TclpMutex; -#define TclpMutexInit(a) -#define TclpMutexLock(a) -#define TclpMutexUnlock(a) -#else -typedef int TclpMutex; -#define TclpMutexInit(a) -#define TclpMutexLock(a) -#define TclpMutexUnlock(a) -#endif /* TCL_THREADS */ - -typedef pascal void (*ExitToShellProcPtr)(void); -#include "tclMac.h" -#include "tclMacInt.h" -/* #include "tclPlatDecls.h" - #include "tclIntPlatDecls.h" */ - -#endif /* _MACPORT */ diff --git a/mac/tclMacProjects.sea.hqx b/mac/tclMacProjects.sea.hqx deleted file mode 100644 index fcc775b..0000000 --- a/mac/tclMacProjects.sea.hqx +++ /dev/null @@ -1 +0,0 @@ -(This file must be converted with BinHex 4.0)
:#d&bBfKTGQ8ZFf9K!%&38%aKGA0d)!#3!rQX!!"Cp%iX8dP8)3!&!!$jV(*-BA8
#)!#3!aErr`!0$d*239p8Bfa6D'9XE(-ZZ3Gi(9)!N!J(H"p8`cm!N"3fP`#3"2q
3"%e08(*$9dP&!3#[[Qr$XedMi3#3"3)AYJ#3"MB4!!"h(`#3"Y9U"[L1jf,mBT&
MYrK*RTILbF+[Sr`@[[#9h6i[4YM#VZAjbYFZ[kK-0re5[T!!K40qq&lQiGRK1q2
iMjrI,pb@ilr`KC-G*i`Xjq@lf$1bbHl9KGpbAT`XjlN`FRaj[TaNX52l#9Y-`RE
RaCEM0E!MbiJYI*NB*pZ&BSAhf#VYEG$#[H@iYcd**3YCb(1bN!#&6*BM#aNXJh8
6[(6L0FMEjpP!Hl14fH8Y1ZKGq-+,*bf[bc4[HaEEEfqXGp(V2,F,prEEb'[J0I!
cVfR[`1bc!ErPr2bdbmr-Xmr1cP&Rlh9fjMGbd"3B#b$JbJm"IHR9`'cKK(p(0Z&
NNeZ-5`$BJJpi"Ejm[fp%8HJicMQ18lM8+ElL#DGilKFFCpPHBMj3+"Ei'hkVSUD
rdB[M))VG@KaYpKYT,pD6mRAN[@$HMrfJij4@1mi+k`rZGCCN`CFiVmMq[b"lX6e
l0IIdq,IVM8k[&(92Ypk$Xf,T(rer5Q&RiEcLl3[9$'[69A$QjJk'rIGF34qZ)I1
AlcA[FCa[RG023YS1pm,09H[ieeGZr0T!U*iq!Ae-,A`#IA4hpaMR[+qU4Qf[%Cf
Z8GDje$Qrm'4a4qprZBM'ZD[`qF+qFbjePP1'kacR6k[p+6U05KQjFTL4ad@r3`G
G8RLXX,ric+%1LQT6`,PF0E`2940b*RDTbL0f@4m#4+[L5Z!mKId+pU[B[m$q#IE
2X(q*r4T@1'2`1HbIB[mDqhAXhf#rJIdQpP[B[mAq(IE[XIq!r8IX2f'rMId1pXX
N[a)VH4YSPANc9ZTVVX!HJMd8HaKf&(X3p[lB"f!IL$dFqj0BB@4Q$IC)l)1`2id
p#LZe0fAX'(BjZCk&24[l"1`6X6q$I6`@,R`ZGJYf-hB6pURBdl%ABbr"RS&p!ID
&f01`Mm25eZGKIaCl2RBVPPim%rXSl*1a6m'HLRddpM(Baf,r$I[[f2r!rLIfHpK
raIkAB%AlrE[BIl&3+Le[a0@PIFfjf#jX"T[&GQ-&ZFfVX-*&c3ABIYlqCrir(b[
e-p628$XcJRd)pKABil%2a4k$24Cl!PCkhUc(VX+q(2Ydl"UX))8Cakl(2Jal%[C
Nl!EX+GL(BcGLAiPp"2D4@+QrSHk'ZTXKl+Z`VmBq%bXBD4l#[Sik[34l"IDPf#Z
a,mCHMVd+qc+Xe#(i(ZaP@+PE3)i"Z36N%T!!4d!HJI,i1Hc2Bhm"qhVX'l"[a,i
*HbRfDLb-r4VX@l$db!$f2KCEiI(51m(AB2I&cX4+6`Ad@I"e'8S(cMDXp%4!c`9
#6kPP3$m'p'2`@Zcqf!1`"f*RB3HaMPA0aXkaZ!f-5cpE1,i!qe(Xlf)rK[dipX2
Bhm(HJ2d%pT2B$f%rJ[d8p[H`RmDLer`"pM2B2m6q%IDcf-pK2irp![D,f#pKIj[
8K9QBZl(2a6i2+c8fe-h3EiED'@TRk!G$r3de00638%0$RaMkci#*K[i`e-a36d-
p$EeKhS#GKah'cXFZ`#l%5QqE5l#,X8Z`)jRH&"6S0d22'hVHd&1'[MIdZe'r#mB
(B(m!*i#,@+i$GL1j#$F)i!3"A#!JT`$-$mJVZ"2lE+cN&pb&K8&*rJ'j"r#(!2i
3`"X#H%-!E`MJ$F+eK,H*&Ii3`"m#kKG3[i$k"G3[H!6l+pKIa9k,I4[fPl$#MB)
2BAmGqeEXfl([`,i6qblXEf$IMAd2pVhBhm5q$hXpp[hB$f"r#bY+8[!`04FqBF!
h!qiCF-V!13aF`i"P"KjKi#-'cQ$J*!DqBZ!V"KjMi")'c$28hX"&$28hF"X$Yc&
`'`1R-A!D!kFam"3$6c(`&!-q'VL+JDXBZ)U"SaJiLS(6'($6J*Z'(M*JT`%lMA"
6Z%)!9`MJ#)&iSI#)!"i4`"8#H%%!,`MJ%!'m)3$l!cK&!-i%i%`!pJGJ63!A#H"
L!9`XJ%-%F)J!$K(!)3)i4!#(#1!D!4`ZJ%X%m)J!,KI!j3+iA-KMr3VIHCh'Mdi
'V8lS6c9#"cXm1HZ(S910dLL13XmG#qUa&fpcUKZYkf`rbGl4`''[hA3Rr#6UaJd
LYcA#UYFSGcUMl5!Y0H6Ii#I@)j%j*jjepFdic`RU,G*GfBak[Q#dRIVa*UrKNfB
`16UqBET8Ue9+mUledYRXrmE+4,HG"Ldr#cYkrH5S@qQp)L9D)CmNT+Ql)Uf-R@4
f[ZMV'e'V%i5"hh4(I+rTaePp`cD)#ahN49klm5B#`mG@GKUcHZE`dST5-KXH6&B
ki*bJiD9"e#CIm5DP@V[4HR'ZMrhM"A#j$Vr*AEPULbZ&1M!9'eC*PUjFGGeP$T'
&hZ8GH6*A+ET!RV&G)&9C0jPj`Rk5(+,'@H0GHP@`I&AcXNS[60Y-h-1pD"Yia+&
#5)Z01N30MlBk8Cbkq)0V[6#-SME&2+FMh&Le[(,jj9QN10Gl5F-,-qp*rRD(rdF
R,@Hk-VjflD%FeJmGGUFjEjfp!YJDG9Ehi'UBlXZrB4XNVS[iJfTYif'hUi`kY6*
iiqaYm-PM)%[8#DFGl)3`$T3jCQ`XmqBl+aI[[!8NNiJL0%L)qJYi9dpIhdSbMTq
R,+[@9SQ1J8,la,C*'$bk8)N`+NSSJDX`9!&2hl'`4c1'Q&P*VpUpB3T8bEi20j!
!F-PhjH1+MFL'Z(1a)4K!@Z,h`LD*RU!q4kMNm41J(Umk,+GD%6d!4p0!KjLmD-Y
UBDp3-$)X"KFE)L)&&UP#6#lLFjj@KHQ)Ba-%BR25L)01DKSL$XMPR,cL%SeME$f
HH25PT%Vj50YGTC!!!Uq"fBd0`p[NSE&Kdr-*pSi0'eC`4Y41SY![*@QhRSMc2C(
hMaXEZY9[TjQIjpGk34ZIHhpXq!K)4%4YE&M3T69B268%U5Uq@H"%iB[kL(AQm#M
&a#5eU#$1R6*C)YD96i6SSlPUV5[2*cq-Zm"FLS(&fUA[KpjQpI+TfJCF9cBG5)1
Z+eY#$rX$2J9[YQcaBaX!Up#!9GdNM9VZGIkffk+iQ6MP"JLe&9UdE4CSfK62q+N
lkDGTd*j*R,8"bDi&*kahV"Z%6AGSDaTlL62SelXc-hlXQMF$3l*@C4bA0+eEjUf
fQ%3fe%KaLamkSa2ZH!HDFICfAU&3X0PMrAEQ1bC)[#6a@h@P%&F4Pl#em,r1ES@
F8V-5NTR,R@UlV2#P@F@YJ-YPSicRB(I-Dmpd[4NrEi*$$1'@E$E('G82VX`,HjK
EEMB$43QTT,!#KlC-aiC4hBD%Y5EE8P")(`iff'Y9'S(4L+8)mZ#h,-Arpc&2)(T
S0pUj(I2$Arj%b@IU4k4R1aX8rf-f`!F`Qq8"q6,C+&JjaTT`LXP18LAM9[DE55`
kIIhV,"*HH08k55@H33YR-*MCB*k$Q3Z#h0b'GV#Gb@$'JhN30a[#2!L0c`b)cq$
,e8cU-E$1Zp@VK1*H@d[E!ddATGqM4Q[ZZ[,e8Y,&ZEdrU(AAQIK6U@`VAJ32HL,
qD)QPkKZaM'332i*GJPf-RBpGJ&f)RB[0B2I$$Q(harCJ"l$pf&%laNE,d9kdTfY
,65dDND&0D8RDPeCfScTH"13+qp2qSc6,X+0BZQ!BQm%Za#l#,XD1U$2%cX81BAZ
`$*D!9*10'#DBVlS$+'T!Pp!K9*mZS2Td)je!Cf$p#ap!Z8)&%M[l"4+8!(%*iA1
P#i(kP0TSU42lQ`+046@DK(q'&JLj`m#KN308ZXDEKFCf"#&(6D)bhBh#6+JPNfP
-YM"0b!3KcFpNLjY`Sd@BFQ1kMFNCTQQB2Q3UN8P"*JDCFQ+ULHNRTK'C1'-bNCC
JHSC*+#CRQ+*K5SCT'5CSQ)4MZT!!b85d$kCTQ)TM)JU`B"U+L65!L-NF*R+BEQ5
+NFNfUXN%&P146&-aYF-8$p12J!l6MdaI-@AP'"@69dc"-6(&0"!63N`,!9"-D$'
p!kJaKF9N$qhT*V#BZQ*5b%hh-1h$0"C6A8aX-H8&'$+j"98!+CLLBm+1#6fQZCJ
5BrU)MbP!TSQBd'4LN!!*3DB*QIjMHT!!b6)Q#jR#Bk+2D6eS$"1)6)3bZFRd(e0
K6$JadF38'5$,4"R6B8ae-ZRR@#666Nb-!BC-r6(Ya'38djj-L6**bY3RNkG-K6)
eb#39dkF!2&1P6!Sb33V+Z#P5*K)"IUB3Q4i&Cb%"6+Xb(CIlT!ZRCi"hI%Ia(9f
VD3,dSZPMdmIhj"-jbl2'Y)iA)-XLaRGAI869iI(rlS5S#b!'(B0M`p10,8&6@ZI
'5@K&AU)3l5'N)5Qj52NbNAd6iq1#T1MV(*lBF"#[c(Rj8*PdqjV4X5%4D2fra2k
IErm[Y2p(l2r&p[qbqBcDPKiE6T-J(K,mk,32lMIrB2Z5`m0VJM(k5)rp[lpp[0r
q[krq3fiehXC"H08r-*pFa`@UEfkL3p,99paVVZDMmkpQAR9SXNbbd$GXaY"TV85
IM4[H[hpri@+D62kR0Tb9,dJBV5q[4bN0E-2ZKcd!filY`"kSh-A1`!kUVF4fB62
BER8+AH)8)q-%ASKSr8-m1ZfQ*2@b2qIr&k+GaTaJ%,5pp$r6$p(XpJBUS0qGDe$
bi*US"&AYd#q`pX!IX+$"b4(l(*)MG%#Lp&MTQe429*GJNF'ZG6&[+Ia5iGRLAaa
Hj3#4KV6c2r[BM4GrIQlZJ-K`qMNpe22fKBZ-iXm,-m(J!IKqc11m!Cr*"#3rc5H
U`J'RjK(eNjJ6M%6@bf+(GKEGJ)SEY-6"Hp#eXCM@UFeX"6im$Xj*j)p%GKq#V"D
@N`dhb+Z@HlMY%0%XL&X6%3@JGMq5*iI3$@b!@aJ4[R#hJ-p1(36X1l*2!QcfiTb
APF-M-r5PkSrA3`%6AM$FPf+pQQqL)RcGl"'U6f6[rK+'0E-[!+rD1B3!Li[8AMr
!*mLrlh2l(2*9(Ml#)e%U(p&[J8H@baf13R9SceKj3U[d-H`5`FKiaX@!(j(3I$T
NiE*QiJC"NimfFp)9Nd'1R$&Ai(40*U2F,#F62di3B9+,D5BqTU)F-$+aaH36(p0
%iDl2F)HB'd"Npj1V,(ZHQ,6LBhHADa4fF$(4`mIH2+D-q0MlaL36jD@162[JBc+
*+50m6*!!iFI(Y",66rLBLU,qq*MdBSS)(pb9+5pm6()a-B@2b6)QRr!arF8%&$i
QeTKi`XGq+r,&aliU+$NqDXQ8%clfrd'@mE(MM`NTI1bVBm+-pU5@6(rKSaC-Xq&
M#ScT-Aa-5ZP)C*[SYF*NQbDQQ2E#ap5E(639(e0Q6($K3i$A+DJf6D8a"BD2(Q9
U$KqlZCL8`dFYQDV$acieTYM`bHj"1jQ'Mef&6*hKBcFIr3@mJ"(J#6lkN!$T0Ac
8PbNfI'jb$4pb2j0Yq*MmBTS0(a0I6-$KBfU10r'"-8c*i@2APS*dZfUQ1krDYHX
YP#U#Fl5,N5P!I1a3e)(($Z%Ddh6ik&[k#are!Kr`-CR'9"XqC!fQh2#"%m6LBpU
3!!NqI%c4kIK#KkBEQHl$"ria9)#2[@G-rZ&MIae6MIMB2kFc24h##A39I,+A-04
A"+,"DqU!$kc88DP1B4-U#ck`J!P+I239BJXqkQJP(r%aP@F9'I%a)BFI(j126-r
KBpL"U6ame*,Ha!G1-$@*$raQDJmIZrAJ#rM!E($*83RG,0%P('H#$apeBX)2(hf
ZNN1AkN4riD-@e!FIH-"8)$k)+41Jq-!cZ!NqpKMb$Mlfd$%RKSmk-@'+McU"NrM
BekQ6,&hL<lCF4YQ$$%"fGJbK!I0@-Z#apiT#T,4Vd0Am"(Rc#CLSrrF#9m6&3
UGFYS,`+c@[M!!c!%(hLJT$XMV!A$mE%M&!c%abj-TNhPbiTVdE2ii#dkD*-96f!
5&4qB#hr""kiaTBS2()'liD-RQ@c&4kfCB-9($[3A2UC#Q46&"fm!kr#a)j+T8Ac
Xmq-GI&"dDSk2ZZV`6&Bl&jNJaFHZ9#CpmE(c&'c(4ifCqT@[@c9QqKFII)+*@ha
`+LD*mF'&Q#M'4eq#9rM!9[JD2M#1ZZ'MjqhiN!$ik!%QJI%4`e3X2RCH-Jf-Maf
&p9d@PBmj2INlD0H#kj!!A25CJV)*hl($qEPh($AAKh,[`*H22[P1P*bm!jGqd1)
lF1AHaAISYrl&Gq!IqjbUGr`1[2PejjVef--,q5KHDDa`Te`qGG&%SZ$BfF@m`BV
-iMY`mql&Gq#bfdkqNp3((Vpem4dirPQ,li"cjbbq!dpjr%[[j!#*hFbj2Fhqk(I
X*dbbY'l0ZrS99b&k@$jKm#U3!2[H[RXh10fehL1D%mVRiK0B*G('Y%-i-ZZ"'Ik
F19!C(a`DF!F'be0PrUiIV8cCX4pIbPGCSD#M9&kIca1a3Z(@FIZE)L%ZlQb&m"@
C,')@-$H%,J&p"`IFG`fK4`(CPrIfq&8qEma`[JpKVm01q*%AHYD2VbpAKdT$dhC
DXIMGYX8Tpc@*IRMkLjILme'X&r$0+4Pq!(3Uk5%rqN)3pa#X+VL$+c-,ZHQjP6+
qQFmYf-%192ddMQlcibf*Uldm`j0I2q&H9PMa`3m89QbkCX1i1c%bkecL6ZVIf-"
&9h1%MPc1-[rM5bpDjmbi'ma%ZICkfd@IYP2"EAZ,9crbfmlpppprd*Srq2'EMkf
"I!f,p4,rfhI[2[E'AECDdpTEaGcp$rCpHrEd5FM6IIk)ZS-2c9J[!6lFQRZ1dYL
2HAI(3jKaGc)'Za)FIh*EJrQBEhGl6GJEiIDDF#H3!0YV`Ke!EUm*-rHU%A"(NYY
V`VdqEUm*0c1j[5EFEq6fQYMG)EVAK,Yp(+XbfNQJHdf-lKI5[5C'Fr"ZV`Nh,HP
HNcE9@2HDY'NhKqieDG1q#GeVdUBp#,VAT%ecrVVAa1lfd,dQEEUp4rHDY1NH)Ye
VdUCe1VVAK(@YEUp*ZqDPGDp*ZhBcU"MI,Ve8pjUdDcq#lM9Tebi!h@[5V[Z4G+p
*ZqlfdEdQlEU&5[HDY1ZZ+C8&)+CZVdQ(kU*l66V8dlVAT%2LVHiekG$X[ZieXIX
fG+p*Kr,@[5BGfMfJHddkG014lMATd#e9ZYHN8hfVHddkPE2Z0HR8rJ$GDp+T24U
kek46XTrZ0HR8AJ2GDp+TQjPdVdQREKI5[5DGfR1JBeZGfQfJHdfkK#1kek4,rD"
l6H`1$0eVdLAP@[HDG+QrGDp*P`4`h@[5TCd)ZYHN5hYSG!bS5cF[k9k6,Y9!PF)
Zl8(4[5CGh%RPpTTNK%fkeb5M2Y#p*KRPVhY0-ZSrh@Z5dDi0h@Z5dHi%h@Z5%Gl
SAT1-lN$5[5BChH@NHdhX6J[GDj,4R9Zkeb3V$0#p*PPKJ1iebDT[GDp*9RAA[5C
CrGHp*PN0"1THNkc`6rHDC,A(3IHDC)9rZYFN+rc6[5CChGfPHdfkKI'kek4EQ+K
l6EV9jlVAT&Zed,dQhGS$SRY0ZV8A3rHDG#Y[h@YLpdESAT0Zh4ZPHdfkK81kek4
(A%,hQ[3)%h@[5BrUVAY0HT5rlMATdGi3(B,Xd5i-h@[5ScZEG+p*MfUXHdeke2H
U[I6SILlGDp)V2U#ca,h#1peVdUZH9iQl9hA8[5DpfM1LHdekY5p$pjU`PX[Y0HN
9hZKHNelG1UCl6IV%f95!lP2HZYHN6eLXHdhkK!Xkh0'R@ZYHNcjKM#SBIGV2SAX
LqT5hlMATdheAZYHN6hHAk9k62Ye,TRY0CSL2k9k6'H)9ZYGNKV"5pjV-%&lSAT-
CUThZ0CQKRYDp*M0dSj6Z0CQK1l&dVmN-h51QHdhkaFedVdQrHN[hQ[3,Yh5[5Ep
k6rHDp1XYh@[5VpZTG+p*[rBBk9k6IYf,TRY0"X4TGDr*J$LBlM8C%%r3[5B$`N(
GDc+JIY1p*J2DBk*l63Cd@jAZ04R3A@VF!SD2'm[BT52IIF3RZ3d-(h`*[S-2I)G
ci31$i06ik"0f`Z#$Pl$l#"mlB0LTJSplf0JM*0ppK3hFLS82l*FEVkb2[Z&@,(c
N5Lli`%TZcF)(,X!em0%2m'Yml"LMMr"a(aMBL)pp2pbLKBmG-r!#qIB4hqC0I(!
bG[,JJiqad`BIf+mE@IC4[EPC#ame!)[`d8[J!cjLi)2i`(jf%1'$Fl#V5VjpaEQ
jF3XIYDFImF&GiFlii'bklQjIm42d#RaJ-AH2i3-Mj1B5kk1qF%"ml$U#Iq'$Eh%
hQA`cTA'J2q#$Up1Eq-"#qJ8IZE,($"qBcKi`I23CpjAKScIJ'[L)"iIaJ99JPhc
FXf([,X1([X$pCIMJeGaKKJpFT%I``6IJ%IM!3Hic`dFrSmrJ)cIfCH&$Ti(MbfI
P%AE(iB0RJ-rii($J'cji*PS%2ML2kNVl#k1jb`iIH-(H0Rc8&0c!aeiZY"Vj$T!
!IJ5h`SGq!Hr!"`m(hr$")GQ&K3pZ!bI#"dl3)rM!'VYB8Acd"[A%4lq#&I)G+"f
+h2'"pqaH`dHrmJiqZ"Sk!cli$rIMi31ld9[`J4e`6hcd!(IPiB-RX4Y0[PR5!r$
M3eYK6adqH#%lX[#"Iq`P``Ir38r!4pr!Jr"45c!@(cQc)dkq3H8($m8(aX-em+%
&S(hKJk2UISa"H*'6r!E"'cI$-!J'Z-9!Jp6D,41DM3CRp6Tmh-QRqYpXhA'RqYp
XhALQqYpXhG+QqYpXHT(lm+a2m)JlmDa2DXfpH(acG2qEkRpcG(qIkRpcG1qGkRp
cG$qDkRpcG,HEkRpc`$"ZHE-q`9"ZJl-qk@GZL11E5mlF'@Gph2qQqYpFF-AZ1F3
R[FlYFGE(l@QUrmf&ih'$R28*pq!@1HX6616q11X6,1!11EiKDXFpFYE([B#Ur`h
TKMh9riCd5j[UId1kKdle[b&`KE[PV%ri#II,@CrJ#MI-@Crd0VI-mFfM4Y`dChh
dMHTrmh4&KHTrmh52QqTrmh5$RqTrmq#+GTFM2Z%ch$9SIB+Rh$h)ah8Th%9SI9)
,lL1d2QiD92e[@,I#UIihV2[I92mE9YqSrMF-6q0q3ZX6cQ$h4Z)6I1513Vljp$$
h&&SI'+2khhc98[@rqET$6[@rqETC6[@rqETK6[@rqI!VlLqd2Z%$h'()Y`!-XYS
b2ZNIlM+d2SQhC`hJieC!eIm@k#BmeIm@k'j!eIm@U*DUrbe3AkVq4kYb`k$e53p
cjk$eJ6'Urbh86A@Urbe8r96r@kKH92e[)4b5'`LY6lJ+Ya$b,4+ZU2khL0lQ$N,
V!i09reZNAPIpEj&ZZ92pEa%D!AF5@KmBUIVI)Z'@kRq,GBHIkRq,k99Z+,3qlLK
8r@qaEZj6r@qaEM08r@qa-&le[m9`5ql#XclK0Yb0alG%0rZTrVF%h1&H21Z6RZ'
Z21Z6rpbHChhFIDMkha,GjDIkha,K[HTr5q$HGVmS2Z'Ch+9RIF+AZ%q2Ed4e9Ie
[40L[qYq)-%ce[a&UcDekeXGpHUVrMHKZ4GAr4Y"LZ'(2qN4(i*Bpk`2292mE%Ck
TrVG80`bUrVG8HD[qYa6-XV--q+3rZA[2qL4rEKZd2[*@r@mT@Jrh#9SIHD[qYa3
qc%f-I+1k`9(e[e(G1+MkhkMiNqTrSp5DQrUXMrX,9ImEeAepU[q0UTp8ra[9HRR
9rjETlNI9rjB*He6r@`B'FGHMp8NGZHr4qVMY8I@rCHJ[h"CSII5SkRr,i+[F'XL
hA,FHU[khA0LMqYpbF)Vl$Dd22&$pElPZ"&6pElRb8re[1GS%0aaD(cG-U[jhN!$
Z4e6plb$GEDRkhd(#HpAr$U+qGJmY2Y'rZ"25qN4Ri9C)k`-[9IpESEX89IpES4X
`9IpE)5a4r@m&IFkYJpBRHA,ES2@*cX@0JpBRHJeh$PSIH+rkhdVG8URkhdVa#GA
r[%0IY!XX2Lr-ZrT9ljAcV(cqZ&eJAYLpN!$*5BUHPXmIa`9p-4H0qFc1-)SZSpP
6armYTR$0Y9lfjibKV8%k`UA#h2PjqqHe158T13%QZMFerTiD*,2(6dRb!j`mXq0
,6S$abqeimm*JJ$IQBall3VYjkL,,mCjM0dXpefkRHTlG329mLaSAfie4PpLi&pR
r,lEaVl(r,l9jA'EcZYbqma+EeaAfrd[Y1eIDGepVrepPiejQ0eUp[(H$SrXm&EX
+%hILeDY!E!rFHR,@kqc"@cD4r,CIqGcjm`6`JVYTkii%iqF,0fe9%p4paEN%TrF
9Pa1FU1#XNhHDl%dQh&ALMp0YI()ii)2lGQibVae)`#R6mRIkaLYj*hrM9GIc0el
*1qcK1ZEN1e&bmJilZPB[[X2qVM@pGc,2Di,b$TVJp1e@+Sj1DiIb$PVIY(BSll!
ME&SlP(I3"+He3hN(V@pD`j0hf$8fV3R+1fL#daUM[)-Q1+eCkJ(J([#EV2`"lh!
VXraYm4r(#q8GHi$`6Hm`Kp2L5I%lM)rd,,iMC[a'Z2JGH2$d$A2b$P0)V9[LiRI
BVARINqmmCriGTUKD[$9qKjfF2rA5$A2f"QRC[hl61mc`620JHBHpR8hqQ16$(Xm
Q(dhHBFGRNfFQll$cXmQ$NhIB"rVi(Nieh['[i,+(q4e[R!E[*6KXb0rfq5iQh(d
#@"FUJdmQ)6F3lZVp&-k9rr1jZIID,GfHYZrTGN)T`B@RQ62f[fXhER[D[QID5B%
%&jjKF1%'Hh''PqhcaHf4p(rYU!YRIqlH4r8+qrq9p[qVl2pAprC9KGH1A'*ji`Y
Xh![YraICI0hqUY[h9SAAQ,Lp9Dep94i+8GG2F&&E,VN[8rDH2P"AX`f2f*Z"p'S
f0m-Lrqh9E,%rXNAr90b1q'T0Th1ZqT0[XJj6Y@VQ-K9Ac1Z121kZh`rcDpErj[H
UH6IIZEY[lZMCm6cmFTY,r3AIAJ3#@cf[dl$(RBM5HS51BphF50eUN!!d&N)h"Zf
*LPZ*@Te!LpMc`4HX@NRSQIk`hci4UGGbP!-eh@)40L80,cb9UNC[p1*fd*j*&U*
A0i-d1[VNQUKp0%G,!"VTD`qXhTV'hY(m9R@60'UjerREES[LjY(SSaX02dRFQTI
1(JdGk`CKmrQF1#kRhMa%(K-NAT,iVIVa9SL[dLN(eSZlDRRPmXY2Y9BBh1LXm"#
BBUr),56edK%j8EViL**bi2UKYFp&eEYeID@FY'Lj,Aki%(U5[re8T6GiA*DlcCh
ddr4%UGI`iR$9kh5bf1JDmK*!TT%&I%aM%hJX"@SEP1*F[I2j&l#a'K`eF"UXb*M
'@'"-)e*FV&9H)5b0,D*L'Tb#BKUCBQ)DQ8"L+6#&P9*dYCd52-`A,Jq(PGKk-bN
BjKXNaX*5i(M0BL3Xa3'%jD"DGbB`Q%DQ+*K'&N%`$`dT"NU%2IXNMhp49!(lSVJ
%pp)J,AJDiqUDbl@!GFA!U$@M3-@ib'ra,I+Qf&DUU-*3&&I%Y#J`aE-S+X@b+#V
"X63SaB-dXYJD#AEPLT2(V8*FZ6%8Vh*&Ml%U$DVA*FDS0!CmbJH8ZL["T5JUaD3
SUSK(Z6C1XHJ"UlDF)Q6jd!)UjB-6D#T(DV(,JDl!K5)8N!#U&KeeC6jD-5XIC)%
V(j+L9ld(&(hb`88FbdHRB*B264%Y(jV!@MNbaC!!FRLYYa+8+p3[$hA9i%CR+HJ
9HL9'[R,N41PL$#`(!S59U(Uh*T!!Q!p0F6%I@J6(!PkN#1R``%DG%#4(0C1(6,M
MR64S"GZ2#5-@CH6Ll[1iEDB5qI$U3P4i%P0iU(H&I+DCPS8'6E3F+(QQ3H8d)h+
3!+DBjhUDAMj)8SX#bQRPfbV0V3,(QQ!P8V,-4j9665rVUL*ekB%8V%[44B3S2C!
!"iP5H)VhTHJ%mQ["+A6@AP$dV-8kU#`h44lq'r%4!bM(Kb5J&*HfGLNkkHjkF+Y
JV[e,J6FK3*&(0KmB,hG#EfV"0lCT6(*UXI#FHQ#c(9+f8iT1#8mTZN$J5r%*Kkm
&0dYCN!#EaSEr@I*aS8A4am990!XA@P,3A'"4+R*a"E%S#5[+-NPX6TK*SUVP,BP
'qFK%0SSL)q()446jPSXV-+idV&+-Q)ZjN!!DbA2"&6'`%&SYAd(R5X+D,CAAZT)
S9E[5N!"bBBZ+PiZVkl"M`fIdmc#mVU#(X5d40`a[M$+%`AAp2BbY+I#jd,UHRBX
[+YUjb**mV5h381+6k,)@Vp%&06k-UQX2B@a0IBK$'d8UD40Kf)3)%Ml3QYT)`j[
PV3d@j%)R@l%kA*!!Ldc(#q+`H[(V)`CKE%1iUU0E-EkK3GEaV4MIe)BV#&F-VUZ
B$BbV2P#5!mXS9qU&TTTC`lP5H&(4V#"G-EJZ9&@`VKDFkPK0Y#Zq-#k(er'Z&&r
6D"Z)9hfJdCKPTEB-HTABUPTEJEhmTB`ej+Xm-DlTeI'[mX5%VPG"`8Tm5pYVB'(
MMDVD8NE%DTY-D(`eA+bq80(j+ZKBL@pTI4@-E-BApEiQ8PBHfDljeI'bqN46pfZ
JCZ10m4DZUApPq+b(0a6!#SMQH+8p0A0#'3RM'p*)'$bZMB6a6A%NM'kS)f&`A4l
*a6C)HHk"%L[2KCEjYrC#8b**`LXLJSBA4C)`V+'5K-&eQ551ECDU,*5%FC0+5IM
#Z&55aVI+A"G,FV(E'l-QPq4#mhT*(0ISJSCL%JBh*C-klT8HD)SQGH3V2G#565V
B9iTZ##F0p+Zp8'ESCI`V0d9,2+NKB$Qq**p8-,!8h4"3+LKBMmj,+%dF,$da)D,
8NE$m3&e'D@"KlB9QQeD8P$)F9S0V@NS&%#YRaqj38bU`@(hJ4MfP#Sl9&bB8P6*
%0Z-R#(N*+*[KGGjGJm[a*aV#3JUDeG!*CD8-RDhib4,@aC8QKPCIZ9&HU50TlBf
@`0,!dqBM%`eGeeM+`0U)EkSX&AL0,cQY66fjf0,BN`ZXcMfjf2,JNiXX66kj`1,
S8a*A'Y4*JZ0*R53XQFZ*kP`HImU(TJ0%8@KZ!-U&P#DJA'"a"#U0UjBN'B*b-I8
T+"GG(B-Ua0E+@"b%5Z*D$9BBK8V#h#a8'P1TF'NDbJ9Z9rf1mH[GQ4NrGJh-P1,
A6091ULT-pUhHf[$TcbHe"9a01#bQ@11"8CV9k&UU5BQ,+DBB'D@@4095+TEiB(I
-Dmpd2I#KT@`HNMAl-0fq1ID861Q&3rp&3M[-,6GC5L#[#TU!G&+,@JG8+e&pTeb
0kLYa4DVKYDSNc91Y4K*IVN)5(@HIK0@bEX(95Gdf['$c2kQkaiC4hHC3&eZ"d1P
(QPZ'BNaUUTr%6ZGAA8J8Kdibd&)A0$@,8K'DI2H@KbD(K#YGdBbr*GIQ6('P3fT
%`(9'NDk@NLp5Uqd2P,I[T)5L5[YU&5mq8+&q5B@pB4ml`pXGlXN2cQF2p[lpifj
FjSBFHaB*H($%M%McfBfqEF$!dPZp+BMl0332c[AkYf&"!3mk$4iFN@jC99V4[id
Q1$`3r@$I`hKJDB,R$3pQ(XD$#m+JhTH00mCiX"rA-CM9me[V6dkjl(a6h%4Y2Mh
fiQfVUj0MELAl*j034da'hEMKpah$M&Jrk$CiB'IH6Zjf1P'FVKla[DBI*rh8L),
$!p'Ec3Nm#*R"fAiI085)mD$YhrML@0$ZCiB1XAl3pE*q)"0ajdEYeE9Z23`DlQL
l%ADEIF*)4)`(QIr3NhaNB*!!ai1XdC[2B"Kf8pUrE83TaS0Z1hq`0STpl5ACkVk
jG&ATbRjVb"$M33pmXAHTd4IMp5D&Ep"FPRE[pcMXdCe1f"mJMlA9X@YIHNF)lr"
S5iSTPDfrXEBfYVC23"iE+i2p!HTkdZ6%b3c[c'2$d248U6lV0**NK92iKhZF*42
0hJ2CNAISljJAKP(8GNImX(FeNrQETc1IHGq$Zr6IjR('Pr0GZp%eqi*DhH(b@+i
,Y,d!HGaBN!$EmlMa@+Mrb@0l)V[cf,beibcIIShTefZIQThlqfZ+mXrm,$FT2qd
4Ka9"BImHQrAbTQ5,5hcBVprDPpe'Cr-ikhrlPA2KE"ihYJGjk)DPmF+'HFKb+dp
!(QHFUHa8A5qDcf-5LAER8D**qFqekq4RmpMUc*l'kA"P9*!!!E8,,H,d)bVMChN
-EkajNFQF'6@kCiZfii0rR*r%,l+'@r2B1K[@AhT(9Qp0ml1YDEG23"jm+fQ5(pG
e29BCGlbaVI$j2aLh9,EqaPf-Hc`2E`$MARIY1YfI[reE@pYiYKkH$qEHUZTGc(d
kMeh-I6U2AFapCakh-[HT2+DBZlZ6c4r!h"[eq!&c(brXRFap+SpGc,f4a[HCqe3
H1jLlj$&0hN2Q[RRQrr[Hqm'iC@YarBfl'(FV$cj2!11@VA#([X@Ghq0@q,VrR6&
*(YZ4i6E'0*h(,UDc-ipEQFj8(VFKH512lb2j9"il3%rbX0X!Ta"L*BXi*Z0M4@+
L3b52*p8hRmjMAAhcf6bkUkI'-26,9UZ9NCIKVrAGJRLb5C&1h*R(19rQLT,(1Dc
9cHePE(6dQIkQ2J&ehF-C)LkpJj2[cQ-+1AId@G3Ifmkdf5eIElCRH3*MqM2emES
hI4*9UD9#9EqF#[ADA6hed3Z3!-HU-%NF)%B!T*@(B$ee$8lVj&Bep!,8`kTpAS!
mR0ShQFGZYHqXY"8kBcY0(TIXC9P!TML0IrpE9K5AhEMAqC2LbRZr12B,4AII8ca
j)0Md9m4rX,MbMRZ+bqjHdF[M#HULmAVFh'HUXTcGHD&IN9JX%%hN`EfDJFlkh02
h9QAa![5V99Qm!(R`KA!@r%pGE4l5(X(rpFH*8GXr3aP-Y9Tl86AEqE%rFiTk"-[
k6d`qV"Trq`[D92Lj(T[m,)Ia!Z4ar1Ci8`RlilV#5[d9-iZ6Aj8,&EmF&lUh2h*
Fk0jqp3I-LPNZY!Fr31"("Cfc%cJhep8rS9cc+DIk[lVD2(CFNRYc(P-MAX'&rGp
Q[#Drh8c(Vc6MYHIc,-eiRGFj`dkRkZSMQ2+@@E%pR`GN9U`")0qI&@XKY5pJ9L`
q1DAq5+Er"(2h9$"6,`"bqK@3!1VQEfT4MJG%dr'iE-UCr$`%@S`ID&21RXqcY#P
RYaC66m4,X(&RqkFEGlCrrUf01e2Mrm(5IKAcrlXBR(pMMm"Yc+Z4a`qBehK"lQ4
H8hPi*rBMl'CHp86m!RX@`M`fRqNcNT!!RD3K+CKia`r!#'`HASQp$r(P3GRX-SL
prBI,JrBjIRQ3!)rYDefL&&iHj(Zl4-NhGhQ3!&i1XVHUGRR3AK6'j8%pAkP!A"l
NHF1$kZ9"(VD[I(R3AJ$#T6RqY-ZNZVm#SEJm5,qp@Sq0C'f84DBfl-rlmXdFU)`
2$Jfi!i2PU6*reip@TJEkUc5!&`B$2$'II`B&r,@ik,2lpLXBV262-5IjMdP!3C`
q'Sc`mc*0I`CSq[qiN!"2NN[lH&8+EpSPjXIRBm6ChCQ[GZ(P+ar+I'Cbhdlppc"
YFrRp$qmiG0H[N6qja(`)e0DlIXhHMb`PrVV#hXG[,McikUYkHALq,M%[ih6Y%[-
#6[[0,c(h)M"h2p#9MT2-R8qCZlRh06Ih!@$ZIUP,c2Idr9iY`bAQQpT2S#Ue9+M
UPe1K[VUcTcjk!I)SAf*HcU0fFAC"&E1US4HJ(PEYm`,N%9eL2T((EVA2AKrpDqc
1FjHBQrX+Rm%[PjLER8pfR0f&4crlN3rY+1aD)c#45m`(fX4I9(Mde`F,1rq3!2H
5kk2(kh&cRj8[-5rR8E[%[*!!4rN5mh[UB98@,d#r@TA&#j!!"erq%[0lkQVc5#m
a[bH2[9Z95mahIRX0#hI2"([!M[XjV54GB#H2[%H(Q8YF34(XZN3(-%VFPL0ajLh
m@8VFf8ILC["HRmf[rBrcZ-2B9*2CBI*,iZDYBcdSFC*I%YIjH[ldG')f0E3pHE%
5$Z2D[S8rLdcFqm5Iff`p[THrYf)$[REl(VehPBQll-I`bB&f0Zilr$RHa$h`(j@
`jNhRh-r%[9K8Rp[9L@-@9YqlpZIaGG[qJ#E-0('cAS12+pG*%ic@HRa0@hMQf6U
p-+rIrDr!Te0MjY[bpkliIAcc69clar2krF%Rm5f`ll(j4qZaj9Pmp!Kj!kGD[bX
qJ'q*MEXZIqrhRm#R*pjd2*2Al`,j4NhFi2Y9Qh264(LJ2FChj$G5m`HhdN`jMZ2
Q$20(iXk*MX4e+Zrlm"ii%FHeU5HdhJIp(Vi(fEUbGe,liehIKBpq*irqr,e6IaM
I85EZB$%BlBqA#52X3HRbhNIcHYr`2Ra(fhiL(qf2Ue869BVEK@rkhZI[a,IDaVd
RlipI&[HJcY4TD9k2cilL1pA%,G%FYpD[IaHq4pXq!fre[DY+q"jMkrIq[(lEK#Z
2YAN3Tr@BSriqcIB0Il4qmp6(bLe'ATQrpbcKKh+ANFrPpIX+@"[BFC-hIappI%)
VR9R!ij'r*-H$@Tf%hNML&T+2f9%E5e+Rq'Ved00-h#c`h['!j,h"2q22'qKlZ&M
Fpl0rQ6q2XlLLQ-Yh&6JDi8SF0qHljr0)iJkGaj8iEZjEqA1iaD%iEZ6$[EjX[rS
"0B$f'31ffTIA#IZZ-A%2daYKAlEI)'b#1mMh%2%"lE2hLR1meF4Gr"hmfG4+MZ,
FaEml(jI8#HlLm,8VMhXeY$(ceEB2iVLjhmZIGpSqL11'K'ZZ$q+iaHV,)fdIa('
A#"pG2H+i@CSS'FcUQPhfERSGAL2I0q%aF`kBZ!I!5F`b%cHfPHIlXVM-`emLEKm
$LpPTalRb!I0HafX*f0IQ*rc*[0+mpqdEm-'95*Nq#2%TZq&RLC-h,9k#Jf&ICPm
2Cc0IDppl$Rrk6Gb$pa"hJ)QErf[iZNaqRrY*I,*la2E(Km8K`[H@IiUi@6D2+hT
jC*jpQVK"%lIX3RaI-ZqCRm!RIXXRi&&Dlb[K[NEm&&V(rjAQ[G0rLVLj*Zik9+-
1Ja1CrI5CHB20!plFBH+ZRb"1HH%#l8BjhH5a%3jT,#pF!4i(UdcF'Lk,0*BA,Vb
H2c0-A2HYa#N[("5qK[f8qF)RL&0H12LEH6qG#+Fd`JG`!N(f)bDZ&ajQhQMLP[q
YHLM-ia1rL%pjj)S,q2-f%rF1H*La2(+41%IB"jN[UGIK4q#Pe,M0p%efp(ELP&m
1[5h(QbbiD!`2-fZSJF1E`q&1a[+`,HJ6$Qqq#$BDSibEDAVDiFd314M,chi#2ZE
`jSpe-)*ZXl,YT[haGALH%AHM&("3lBm9F$8MVJ6Z8Pr&Qp@UNmi&(M,H`j[Xkm!
8BbHb4P4AaCX(UYjVEEr5pjV(%HmPlN36pe"`6[%QmblKU14Pqq1T1Gjm&[jUV*b
dFRq10r[!jBcbPHrGi)[L6AD0F%MkcZ)0q+GimfdiTjQdH9$A%'mb(iAVQ#N6GjJ
N-F@E-i8ID#R`*1)9EjCp2h(J$h@&6bKqAr41iMCDRRGChNmR8!-$,l$8&EiDiNh
QTq&f"Ll!YrDT(YjNh`CRYAU)I)FUra"[XL(F`acNfH#ApX%Kk"c'mZb6`'1(0`2
L"mUc4i6h)GjN2[&ca)8mflbGGa9[-Rm(ac+@CfpMCihL6ICep,!akar-ThK2m5E
cXCmK3"FdR2M&('qqm1IiP*F[H6M(QqXI)djjqC!!G!,YMl2JMPEh!)rK9iS6"iS
R+9prZM"$mHCip!"MGl-F"bik["N&+ifG!&k5mj[X0m0pMG@-Rb%X8Ecj4@TUV(k
hj)Gb[2R'Ea#R@Z2X(mKar4Sd'f2he*c#HDZ1hhchViP6hE$MMKlHC#m8Ep-CPh@
kY&RjcDPS!mEUL82Lf5(HC0kTZX*AiII`M4"[-R[4iBa9i9I3FkkIhN5ZjKEEhr5
CpY2pe'HUEcj,p9#mq3bDS,(Dm,2",BFhCe&6BkAJ#i96bQqqme[%UECpR("8qq"
bG!i$jq*$ER0idd00MA"E[ZFZ)5kEa3ARJp%'[JaqI2SEd%N1-A%RJD('kLJVIV@
(6i%[,03aSd[KFbk2&@K#"Nj"(Kq%VlSm([X3!G3C($dmcq0)m5Hd,2NZKr1j2+j
@(k"Ab0q2JKmZMmmVM`YY([!(cH05i3H&*Sli[KE6LMRYJ1rji[2[E(N,%kAQSr!
'Br5Ui)0S&8Em(Cia`*m0*Zl0p)Vj6K1h(LiH[-2%(5@HK`BSIpq2TQ+@QVK[I"-
qF%rqhL!-drbfLXpGE2,B!-D(q9dip`cDJER2a&fV2Y6mVRQF123PqIX*m0lP0dX
m$je@rRi5$FrPGk4Uq5,,lk9QVRk(SFXDiCMmr6JDKXY[fqm3F+Q*qj4fT@Pqarq
9L%HBaa@ITLp$[1cj',eZT21!"r$T%&GkPk-"Q!FY(d),e,JciDK'1%rI`%-@Q$`
qT(VVlUlM$[6`XRHTF1j+fhr`%-hM22%jd30Yhm$E3pfVpp[K@)CBQapp'1*pcar
T[CHEZ0H$PeUrhUCd!Z'!&LI!J6#rRJ25GH!4j#'FdZ9p2PUGHCIP%qLlBIekhrS
Va)N'CGm6$0Ekp6b0PQEHBr(QBhNHjm,*$GKPik5IA2dZTkEQ"dhF'm82YAlAIiB
ii9-f6R3p9lr,a"[J3I*G,(kPq3h$[BddCq,J&4Uh'JhHr)L*Ze,kLYC[")jZT2d
5Pp2AHpmS2[T'%hIelMb2rGAhD06%J4pD[eHSAkmfF@q@IK(@VrIGMa*RpF[r"`#
3!`d0$%eKBe4ME#"08d`ZZ@qbp!Gi(9)!N!J(H"p8NBi!N"%@!!"J03#3"2q3"%e
08(*$9dP&!3#[Pi&PXedMiJ!!!4i!!946!*!$D3!!+-AGHF4I!*!'Z[!4!!LbdAJ
qT3$Ldi`fC,5RjQK+Ai"mIT)55NR(rQ!RhrRB-b[h[pkGBp2c!SVId'RY!kKhaCa
q&5hRD[I2dCBfR+[G08GE9QZZGR51GREPZCSq4k[%Fl9EXc9lIc+GAH0VibK8hm)
N!!!'!-@f0NM#-h+X6V)*6l+5lC&0fi6YSjXF2l)PM0`QfkHYc0+LX[8)YG)k`JR
PH)T2qV,$GlEa(cZ2GkCNHjeNqlhNq%H1pq5fN@d$#HmNqeN46MEC4fiIkcV**S0
YNZ146@kI6rD%$2B4,VNp5(+Eh-)MQ`%GAU"e`!EP%ciaH`N!Z8e'R+#!Gq6f5Qk
e!4Yi)51(1E*"MU`hSpG[,bNrFj!!AHHE!mXV6ERI8HlZG6R2l2ekl6VHC92*2V)
(f4R[lHc6@lbd3AT0mY*&Zdar15pGG$R2M#cN&Jk!"4"`k`1X,hdlDchT'hmr+bd
H@FJ[C'&EE`(J#rim4hjA%-H4-@D&-GjUiehdX2%f2Q(-'fIJXpmVH,MkAdeF$lI
k5G+)Nf)eLEH(3GEcGD4mFH2TZmQXp-cqr9h(arE65CY1k2I,QficCYYYr*@2Cdj
F@BjEIK#rP'(8V$BRHIF9G[IZZ8pR`YeM,3,[6E0TjLH[GfA8Q12mdEKc0)8i,kF
Kq9kf&RjC6'hkP2eJBqMA`b3GAA`f!3q4Ne(*1E*LeEhQ*(PA(0rfJahq3[KmrTA
bVdUAQmripkdYTeRB,%9qQSET8ripeR9DpHL&p$35mJh!rpJV(r@M5E'CHmjIqk5
3!#*Tmf5M#k`Y,KYYCQhYmD,G1Z6b'f#[eqkIQ*bDPGq!9q[T,[LSPB#CVCe"!Bd
"8ZF%@c69M$qb%8DhM6P$pXL-16Rh[F"L8H45R+IJV-Yl)f,1ah8r6T9aMq1*8f*
IEf"9h`EE,*&,F*l-Z*M9ZCa&!,CTQpbY*a%Ai&Ah**!!D3IX1LmIN!$9K4,Q)#m
0eSN#BQ6a@eRQic`T,i-(m'rrG&#GXPr"m%Y9afqa-#qrZVSLkPaJ35B0KK@2IG8
@,Ihh9C5"@4!"p1YUNp8NR'mX23Al684&@MlUUTMXQJ2pT#bpbf'b%"BV,a1AiVF
FhiTUG6,[J2MkbBYQJKf01NRZaPUeK1i@5T!!5PVl#HLQ+c'[F,DjDm8)MI&h'fp
'FC1""`eL6ZT6MFJj!Mqq-`E9KU8B-2a&pURBIJfR6k)LjNkF[@Al'(Y9E!rLV&6
kj1aMCX3lNaa*E)Y`k5GE(5lpCG[@*a$H%Li$CAZGDSMYVEJ-PZe$Z!b4lI1i$*A
Y1lJ-8m06dq'b!H8MC!2e4XTf0LkMC0Y+f"FEk+hKApPZaQ@XE1r!KATLS`EMC2X
EA-E,pMeF*PKEM,dd86Cmk%&Xp-&Nf9k!ba6C,XCPUQaAiD)l@pPZ`NA302B9A+E
,4JeQb%B0CXVf%#kcV%fhq@cCU'Q9E'$!(0PUFCNVffCFjXRf#m)+E'r%KGl"pZH
i,*!!lDpa@5ME!lK3@b#&a"I,4Yj,C#2@8YR1aD9D0XMe-YPq"4HB%VBhi`,E`RB
V,V!YE*mPN!#+l4p`1FhDHK"l9XK'IjiZ'rQ!SGJfi%,0X8(C9mTf)bkVC2YpA&E
,pJ&Fk&0XAa"QB[XZ,QGD@dpLiJYPSqI2NShkJRABeZ%#jQ!Mlh0Nqh9FeXMfTlM
3&pLSm9VC`$EL!mAJmRVC`!AULBhk`M+aE5*Y%0[,F%&J`rBlZ&`J'rd%QmAf19a
H,"Ye[G$DHK2I,j+0ZS*4f1JIFX3'IPmLfh@iJ#(Bk+%YXYf"#aL,lHp`)5DfliY
h3#AJ!0YP!l-ZPBdH%jTAdF#&%pXVFEP-0R*pL@cJ)L)MYUrK)X*0"B6'5-[D+SP
*SSj9%RF8ipFfHZ0+fDl'CBpXi*r)1jAX'q&qPH`EX"VE`lJ38hepb'%DC31[i6A
B`"6i"6Cki+@b[4`Am"BEQ!Ir`[B4A(j*YUrM3LqV6e1UDf@$RiMHdCHB#(jLSjr
*#a[eHS9Xm#Vk&0ZlFD'2X)(PemX'"Vc+f[S4!eiY'rcN0E+"0cI)4Yq#RpM)!Fk
#$Eli@YNqKFZ[b[CYA1#9kZY2l!3$XG(he!FEH!Vr`NDI[eifFRZ$E(q#bfr)GKF
Z[bRE2q*bLl80)&l5[pMJ9&Tc86Di`@r*"YE3GpLSk@r,pLjF`%aXRm(PGf@$jrf
HY3dNT`9rX0(VIb!ER1%2C31rrNJfHZQ2CAXl,Qq4lC1i`1q``DIK[1SE4"lj0YR
JL[380RJ1mE'"[r"6E1$&1f@MeY33'lK&[f$l)Lld2MEi)Va$IB2CLhmQ'lhb(YR
J52!qE1!+Z@!$ipiV'lhk2YR)mrfbI4bAff5$)m+Re$H%(2f$XX'(EjF0$!2$XF%
a2L`EZ!NHBJ-[rN)fk[j4f6k"#e`$'lc`6QXE5NhN,f8$qp%ZX-&AU3mfH0GIb3B
I)"GXi!hBJSeFk90Xq)"Tf,k&bkGP3m%$+p3hM"`8A-8'liA6BB1rh5dE(1-HfDJ
VR!)E@)#qJBdk`Mfa`@RSAf`SP&qbYZ(N6qJ!f1$`AjB0E[N9fH!mIbXE12G9fF#
4Hf@M0q"Sf2!KAfb2i(+IYBfJ,J-I`BDQm!hCi,er,aZBqNhCi#6d)cD`PAl"4Xr
I,aXe"4q`2BS,'+LqNG4a`(0Xk"6r*"Xp")r!"Jl"NE'"pImX'rJ&Pm&'Ei"ef1L
EIl'f8G5!`(0Xk"V`1'a`jRq9$IlfEl*42hJV0R$R"l*48hT%ID1TIra30MJkpF4
'Ij!!Zk[J8qV(!+LMibZeBV9D+TEH@eUcCP6`E$kYP'KG5&hN[X'lb6Za)2kT[k)
fV6l[E%P(6TF2)JZ""E!KV)!T4"F5"&'&S%+8)3m39)JTK"4`SV%JRK"1`!5##E'
%8%)N)C!!%%F)0D34XJK*K"!!CS!Bi!9S3I3JH!!2T!Y5"eQ%U%$U)(1!)'35S!*
J!A[!&8)(N3-K)'i30SJD"!eL"MJ$BT!!-8JBj![5"HK"3L&D%"2!'B#$B%%H)%q
)+"!E4"2%')J()J4L#5)*BJeL$-!0Z%,Z%%-!)F325#aL"b)(iJB%!M%$%32a!P%
(i3+a!D%#8JdaJ""!"#!!N!!c5"NJ$L'$L%(`)(!3-3JBa!X##1K$8#"e!$NN$2)
&kB+B3,)J%*!!+XJ8*!T#!)'#*%'B)%S3*)JMj!K5",Q",%#+)%13!!(%D%4SL)F
)ePUX4S#'R#,S)'T$@K&i%694I""(%"XJA!LmN!"ea"Q%Gm6dB+S&i3-K([%Hi4S
bLP#0')fBKb!0m8C83&"(h)(d)f*!*K'a)(S)la!Ma&X)-m)Z4!a"''%ABS[3#5Y
!-%C33h"&Z%@`KG"$1a!X%&d3MK!3%483A"(&%%XJVBLV#(k)2j!!*84Y4&$%6`J
IBLFL+Q3GX414%k+'b!V44F"$e%5N3-4%[%5d4%K!*%'F4*4%M%5!3ha%[%+-KE!
Le#!`LV$BpURaNr'P89#Xb0MQfN5a9*aXc#9qXQbfY"T,a9URhBia'EGj$VG0i9)
M'`f-(d9a`2X9D@0f[K'&+Bel'YNLlfTiE!qME%P$2`RSXU8c2amQXidBYUe"h'c
kV6T01rbZdqj@'NFKMEYmCVB9bH`-r'Jf#4FDF$CZqjEE)HlE'JQ'+2hBp8R5iTd
kq"l'iXI8eSDB*GSHaAl@GF1fUHPRLl-,85GN!bJ[9GI0%62F0CGQ5D1e3&0pdpi
fcAGD!I2Be8J$QfS$iXqI6qR8J'R36Gh15"[pG"Z3!-bqH4LZ60&)kVl(pX$H`'r
4E@pMSH9(0*LdIB1ITV,YLk-m(TDVmN$ldl#e%iCpM5BVTUp5fkfY,**0$6DDNPr
9DU4C[@qmTQY+KliU5eYqRNpe$aLUJ!J4R1-RQX3#k(KN(BZlZeAF'%CY8pjUkER
f9-Be2XTkH@jG'ejTF&q40Xe-UE*K`i%FeS`I0&HAPiZ(FUlEeRH)p)DPa&i0krS
JHM*NcLP5QkKXQ8%jpAee&-rj%EY9Qq[#9UGRA--1V8qkjSf09MhH4Hpd5S[@AMc
D6VBIc"fIb`pPVPaX[f#ZUfipD$BG)dET'+cTVX"Fh@i(AqlR&K4CGi++Bd03MEe
KYVhC(Q9aG!9&46QVdGS4*R*3cXDKTT0QFE0iFELm+dlUU4N,JM"08CCpLkQCpM%
MYUpB#l--L,6AE!#LMLrllACZ2Eh6L1V&mD8Xm91c2TcV,#b%5G('M0JLem600Q+
U0,9Cc8*IB40CAd@+9i54QCJU9YU!SCeA)SU@Hp6-p1U`PGYU'bP*aDijTT!!VL)
Qe5hqAHDUIDb4V"6iT(+RfLBVE*QXdUf!b@46Xk(-([4j!hd%SQr)'MQ%02Ej5f1
!pY(iV#dDRaX$G)4L,YVLdjC'5b8DHf5JX3[rM6hBEa5FcbY1qUf&$XCe8idh2br
JH&5`2[%cm+,)ZIeQ@P!FUpI"QY5Xp19j-bRDT&[$"ledIe(K*LIhffF',G&Jc+!
PZSiCY%42-B1@D#9Qd"*pa!aDSRZB38[d#c0SLBjK"Lh4+XbJ*6UD$&TU[8`',E8
Q*S1@@Qq838ZY$mUJTGEkC0"5DhJbD+Ne,aQde*UA$&TUr8S',E@Q*S1@@K-8hFT
McM*SkG&("LdpDN`bD1P48j*"5ipp))1@([8K'E6df!FbD1P4ij&"5irDM!aDHUb
p$&Tke!ePd0+M6LL$PKle3"Qdp+M2bU#P4pe9"LdpkUNbD1P4-j9"5irDT`aDHY3
fCG$5Bhr)S+9(29!',6eUI$*Sk9&hP%&,MrdKJjC4iS+Sj9(fT!aD4YNR-QJCCIi
bD"QP[LD$PP(UC$*S'58fb+"PP(U@$&T'U@A*S'@8ZT8-@ND*$6*S'D81,B1@8@V
1-QJCT8iXJjC4ePi',D284QA3-XSDbk"PP*Ua$&T'U6I,S'@-H#H$PM(LL!aDkU&
A'E5-XBibD+Q(AQA3-NEp6JBYBqae'E68!l!bD"QMlLZ$PM(Ul6*S'D0H,S1@-@V
C-QJCSbBYJjCk-&B',@28GfA3-NC09JBYim4P'E5-%q0Nd$*16*&"5cd`+i1@FID
!$&V'QE--@XDT0FUJCCbDY`aDkN&D'E5-8l1@3FXiC`9Nd$*1r9m',H28m'A3-Ni
GAJBYikbV$&V'fD-bD"QRrLb$PR&Um6*S'@H0CG!b`4V,S'9L-'LTKh0Pd$*"h*4
"b`3a6JBY%m34d8-6l'FCY%b`af63-X'kbk"PJV@3!%(,"'2*S'@#M&N',428q'A
3-X'H%$DG)'E,S'@#ma)bD*RJ2)--@LBiLb#$PJPLX`aD*ULrbk"PJTUr$&Sk#Mj
UC1FCM+C-rNCA"K[S&c!@h+H2`#l`%Vc4QcBSPMU0AJr1`!(KIZ#0dEIKIr3Xh!r
1"qq#6aJG()j(Am06`#bVhG2Im$L`cHMMi#rm!mi'*S+4i$2B$3m!9m%#Z*fG9a#
XeMJ06`'M`AEi"E`1R)D$Q$N'Sm26SeD,Klq!CABZ!Ai$TX%E`"E`0cmr!$ECf38
cY`"Z`fhJF(!hZ"Rm#ei'(i1('@dIA!+l`#b`#SbbFb[#UGSqIpP&K2Z+BMMM1"-
ieCiHPPY%6X$C'fF&cNUFIA$faGN2ChqF!h!1a$NBja#F6#F1`cNFj`LF)h'1`MN
DjaLFBh'bkfFFc[%i*q#FL(-5cXNiTq#FL[0%R00`6XFj!qG-R,0`cXCCKA-1cVN
ijh9AJ+Kc!Fk&1"IKA)ac#FkP1+Ya,X0j-Xj6mM8RDL14!`!eSm!qSf5i!,lNJK+
p(S02S@Mr6Ij1ArYiUUjXL'qN[KG09)ZEaLiKPV#)*(!h'XU2&ifNFmLNSkU5@GR
4XS[&e&'j29-kAAM[$FL[1ChQciJqJSG&9%ZAcJK)KjVHMm,0L&P(2leDbJ'`AqS
i82Qd5#3#pIe22b5`F+Tel#,eX4''cm&3C@q3!(A,hKRCjK2AAMECfC0bMfQ+&bT
%TCq)3iipA"bSF8mA"qVFbm@"A[GfF8#[#KF(LPlTiN$MqlJiN!#L[Li1p,qILi0
%d0r&JHi-F(&![i%Z$M,%)"F(4M,Ba8(''1,L)(--Fh'3!%''ZcK)*50F(156N5i
1-XSS&`HTCE5,Ja`caX9"XKRViL$GR1$L)1Z-Fh'3!(l'ZcM)2a0F(#5LL5i1-Y)
N&`H*DE+,J`3eaF9"MTVUiL"CRHML)'Y0Fh'3!,kQZcM)Bc0F(+5cQ5k1PYHHL)-
F1G[&3G+VFR'3!26QZ$K)IR0G('6"jFr&53AdTF26A"aNhK8Z$Y,Vk5i1FR#0Li-
8Zm2&3DVGkH)Ja9lQiL$M[X6&38kph-9"1YlPiL#PAq(L)%[[GR(d$UJRiL$PAqR
L)+([FA'3!,Ih[KSR'8qjf`@I6X8ik(YX2%h*arii`&PleZl&5-AU[NlUB[Y@!43
#A$LEZ2$BrSrpDkQd8qe$kdIAjYjVcq9RB3A191d'5he2,q9eS(hYblQCb6!MN@E
GN4f"0+12GZ64M$ZLc`FMM(E08RNYNKNY0#1&k*PSPHL3!(DX%0d263qp$LdZ@*G
Neb5Cp8M(2JB1A3!$H@i3d(!3$-,eaKKlbhkBrrcF!b0GQ9bDerACGR!(I'Cc46S
h@ElJp2PF$e10dXBZK#Afrl9`hm+@Y3(VkQ5,4J`R-+qQD2@DljiiHq(XME-#CbA
12MMliZb(Xcr1!6J(iKb#FbM1B6L(iab"Fb6186K(iab$Fbc1%h#1`cNHj`5F%h&
1`MNCja5F8h'HL(-DcZNiCq#FLA-@cYNiUh$1`6NAjcbFmh%Z`,N3jb+FLh%Z`EN
8CcA1C6K2aRN+cP2c0b'Bp5rZQ5q+D9cc&J6RbcGNT&4C2cj5(&Nr0Mf'kjU*dV3
ff,K52QH-m[%iZh)*V!01YeYDLA"5p'&ba,jkAB*9K1cY5hUXa+Uhh3FF9X@YE'#
ZQkM@HZ[ZFQlqSM[CNCIc0C[[dQjl5THefjFARhCTb8mmNe[TdUkE&aT"XH5hLrP
@L04L[R`)XkH`aE9BSD#JQD@#+6F@8q5cU-%@`9`'DJRN@ZiLE+V80@[2HlVkH$9
9$UIQE-A$l%e-13DE'&1HQCf-D@b`qaG6ENdV$V1Z6@@bD`r6eFMZE``F@pTF9LD
Q+qf[YQc*36aENV!E),0HKC,DhCBC*rC$jMbDHp(ZM%bjCEC(TYc@aCdN#'[qI)K
8kZF2Ye"ceB,YQ@R)cZc40)LJ[Fl#TYB-qV'[djHjJM*T1&2D9`2NVjcAHH@$+e5
EXF8kCq(&HMC9d$TRLjKac5+6pFad5Z#BEI(!fh4ji*GXkdc"Fr$9l*X#Rib[J*M
ebE)*kjRT`#E(eX+dYQG,Pe[h*L"YF@iVC`C1!mGLZeP3$I`dVMBjj8ZG49IVQ39
BkaR`,ZZES9k"BljFPS$PPJJh)@,JR`(&`$R!aF!r#if"G`BG!fF,N!"jhdc6jJ0
))q4G$r4#&LcEh*-!dq6Z3fEJPN(0`0N#CkY[HkN-I!Cqc3JD4!K!Y1"rS-`@5[1
q(BfC"Y5m+jMDkPISJJbb"XiCF!fFFrJDZ&Z)cIX@DTK41R*ESTUjCa!Jbcm$lbB
1'J6)mG$!2FY&!qm-(mdlCdP52N*UXhDcEl%TF[bdc6p&kTVmKDF'IPQZ'RKRq'U
Vmi'#*APVi0M#AB-36Ibe%+"BlJb2c6YhYQPf!AUcVqDdVBlYlC!!jED"GjEI"Yi
"a`hm-c`hlpaHbJ)-bqlk%)K0L(BS0[iP-$BK$X#a#G!1b-Dr!-R@[EhEEBcQ*V(
HBCXFJ1CXK$aD*5-d`E2aE!GSieq!k)alUAJY-'eF1i$D"#P"G5j%@2i#A&[hFJZ
h3EEecS&faVAB)1h!EIcESG[i&m(E4#M!Yh8[&VB)i9h`(8*h&fah3(B)eb@S,X0
d%D*,m0`*cCf`h!E*)4bAS$L%i3)%Gm0[&r4f`@i*FXY`@i6D!Xb@)$D%ea"D1f'
e"+P&1'f(dLj*+K5NZZ5S$M%UP+*+3P4CKLU+8#8*UP1!kT5IfX5R8(SU#8qKl&3
3RESPTbl"U8YZ+SP0CDQT+$39C+D5b"4+6+(!e#N[PF5PSV48%TC`$Glp%H"KmU%
I,5QYA!T#qeb00X*3bNh6eRaZ"[R$h-JrrmU1A)MQ4hIN!U6Ii*(cE(f54kj+A48
J4%F�"@!6c,&FMdlYT1Lim2bG1(TZH#Y!"B13Ep'-E)p(T,,B`U8-kKA!Z$$5k
-*j!!1#Lfe,2#JVUd,hNdbdKPL9Vl%QdE*ebLEH1%5l4YR(#*YSd6,Y'fFF)PfMC
1Z%6EaJQAD0Xii4*Y'bGFSQhMK%ZdECa`LED0%bl4YR(#*GSf6VK%fmB*PfME11&
bE"XRA)jYii6,X@fFF$QfM4-ZalCa`ZAB0Nki(0['#CGMfcMKFQ`E*eb1EH1%bl&
YR(!jYSd6,XHfFF,Pf$C1Z"cEaJQABpXiiA*X'bGFMQhMK-ZaECa`1ED0%bl(YR(
#jGJf6VJFfmB*Pf2E11&bE"XRA)jYiaaFMUhL(&b1VH)FA)kYiKaFMUhL(&b1VH+
`M+pl1ED+`m+qlZAB+Jj,rEUABkXi,2lVASkYiV!FX(XjYSV$!X(ZjGJU$NX'ZjG
MUcJX)ZaHMUhLX+b`HcQfLX25kqlPf#S15kqlPf2VG9LZc1ABKq)S&DYT'e-jUGb
Ah,UR(MKmrP#!eFU2Ej8d$bR@RcbfmER2$I)mP#)4q@p2Cd"09Q+69ba[Vmh2["h
'0I1CPp4`pLq('AD&e5FldL,(TY3lL06MVfVhQQXI,TUV(MTl&CrC1+D`dlaeX4l
a+89heUDRcN+[IEBm[RQ,'YZcr4Hpj5rG"elG8lMPLB2l8U-hlpIMSe`(AeY0h5@
IIQfbHU'dM,E*f`ZVp5T`2GLbVKd'MIP'S#G`1A-q(V(Nf4hFDSkN"fcHX*d'FT&
m8"f41"*mihIeJ'@Xbr!iame*[IX85[mTM+ica%MM!FZH&4kdFM!'%&dp(-cCJ3G
kNf`4$p3M5Dr'AFf4'JrR'4iSC5c2$hbQZ$-FBYErlALJq)(S"aNm8&ER'5%Si)'
HA'KjES3,k(0%2$I#AI1Q"I8b[%&2[e6AISk)Pq(jJraVp6kmGHVRp4VPfU#(#*b
RjkeZ&(#IVkF8AL#r#h@r52lAk(kamYLN[#j4R-h+Di[Z@a9RQq,ZeleHIY[eA0C
,Hdc#eY$&mQ5%ja-)Nf#+563pIYUjqZ8H+ZjLqCa`djrkLjT6Z-3Lqc6fh$I+VUJ
ip[%fi"AYYTkAI#b2Z[+NRLGGr(*[Y@rpkUU6HVEdm6`fP[3XkQ0eA9ZEHLl$Cr*
B2cic26UhD))drE2arP%hTrjBciC@Aq)YZ5hcH(hj[1XUZFB9hIFcTZ(R)Bq2E[m
blpi[I(iHRGY4RXkMXb"2jp%TT2iiMij%MZ44[f6c-,+fGq(Z[GhKJCKh&4k'r+T
02c(HifGFZ2Zc*hQl#`r$rYeZ21qkAKj0laTqTKlX)04jG1R-U3Il&`[Vjk%f2$X
#mYKkY,,PZV,haZ34)Y'422BBpZ'kklqIpq-&DqrhTYr8@aENEF0HiSLhfGZm*r,
+HrP)j`Mmr`0alM66hJ2[i(21r6cfQX@AF0VII4c*J6UCA3kRcbp9M[%BBUakKFP
XL`-pbIYr2`Ub*deHB3f(mYLl'"elTC[D*0h0crCQR5%"HI"9S8PqAPF'"B4a&q9
Ap`IM2U#TrC4a&r0`"M$ZFpCY1[B'ZVVUeQ2eF(``pj)#qK2QhTh(BHEHRFGKj[j
i(SHBHcN2cG`IZ4'R`ZcB(GLGk60h5*m`ph-r2Q$Zkf$AI0h[h'3H6c(h3MeqaYb
,KAf'ZCIc1-cF#fNmbpc,HH5Bqr,6rXhFPkpkNVRA,jJM1"e")[VC"Uh-rGiFTjd
IM([4@Mkl[ZAl+H-qN!!(Rb1!FDZR)*ad6R(`VS2FerFeaR6q@Uk-,5,H8ibT1ir
$61Ia2!iaRA)H$5B1SYY[-S9l9j[6jVi*YdhH,YL([Zeff+lV-`,9D-TK93@)ehM
l$h2rbllqYAiHLPNi![)ic#`+GAf@@C6ck!*KPBGqNN3B`mqM2M9VeVc!,%LL2K9
i+MY`&LJ!5H3Xj@%T(1CX([GHd4eU,Eq@-khBq!hEMZ5ljlDrP-FjFpZ2j9'C8kV
5e'+rA$YEqkj6[1Xf[eMjPXp@2UQG13(bU)R5e)`'I2$GJ6a8)qTKhP$PeCUA%k!
H@UYb!Z4KY+S`Mb0DeBkX'CNA'B&DlIr+Gfi8!aLblBj$M1"f,NVhmlL-A95Xaj0
p*KV"c[D4IN8M+(*l2`mQd5-Ff$rHpeSMF!,dUpB)R!"jD#6AF"EjEeee(Z`c10i
I[F[2$kl*0kJdZD8'-P3rrhVPH9HM9X%K9D8mmZTe%j+MJMX"mY$UY@V&[8Ib#06
V2&F8lD-cMjbk9Xa$-@P(3"k+ZMS#mVJm29S2YENlqaE(E"j*EUqd'&G!2C3@i`E
)3m&CQ%FCce*j+)hJD"j*eAQ(5Iq$VmPk0"L+-@&rC&6R!rf"aZ3)b%0T6%Il0DF
aZ3$bf*HDrr9CjH!*R+d"+m3)([,fAImE8lKRaTcfb,8plf%I[HGJaFK'fEPiqfl
)jfQLlcqG[$h&#"`"H5K'i!M)3b'j+b#2KL%"GGeKfZhAmdM0I5LN1TT($UQHbi1
[bRmC2eBHQ%L8A&*jE(QSPmIZB3"j9!iHbY5+H$eceE$Z`EYAI((f`Pb&'[-q2M2
$rmBmqX,+0492&bSq2T2e9%-R3"jDTA-#j'&8ZM#2[%UAbZ--ENNbUPK(29$&L[A
`mp!UP"1JVRT5jAJHh2Y2,IVY0+i[2mq(4PKNZ2[mB3()i!,))kP#PI,)Ebd)1M'
T3[eI(ZM56S#kqSMR!XM$)*iL-8F3Mp+f)Yj@6,b8kT'I&Qr,3c%U4d!HLJ-l![*
3(0J9N!"(`j!!J,Sb3hNFbC0FqQJp-PckD"ij,Zd#b'02VSTe-#qe*N!$G8HIlAd
j$pNfd*'(hMDJ4Th#22,E"S)mp&`$MAmFlc@MG!,NS4QPhl$&rQMC%K$89Fmq1J(
bi02Ul0'k-X&eGYak9[-`ReFZ9iF!E)$6ma(PVA+MKlrY03Lr[!S9I#kQ[3E(2XI
5AS1'pY&G!Z@kTV@'MLq[mVEf"rX4MRm1N!$p#!8!HABr3QP(T4YJ2d*j2%,Q)j`
!(H31B1k1#QEU"%"1Y`*52IQ9Pd-k3$3GKmYfb2"c%'JalU$YN!"(2mI5GXJM@Na
E)Li#,DBcKXapG(cZV5f6jC9AN90IBh#Pc6irBA$GH4aQF0ej('C`MqGaL-'9mhL
+H4Abq"Rc+KEN'HC9cZ-`mbUNm5cckXlM+HE9PSLMB*GAk3YfHE9rEJ"'S20`5Zc
b+UrbLVajq)5f@&1jmFLQ`L3bG$r-3qm%F`,NFHEfC(i8jmrV#V0`R'L8HVIBXIj
)l4BleUrZ!%e(laBlMKp-E,kSd6kQk6aC9rH%TX-R1mUHUk[1Sq[003Icm&rIadY
f%[PVbRKr4AA6(hEfIVE1,rhD1RPGQb2[pAdZRhI[1$[`32&dp3SL"plVqea[Vke
,[ZQT0+RV22h5EhVUQ+ecQ(c2[a6Ip"3&!90[VY#rmq8E-P+UV"mI+BkX(jXH`hA
04'PkC,K+!cKK--!4mlRL8-#0m`he,&BQhmEK(aC!PG&&JkI2ja1BTRU$L6VAiV9
FI1[-#IPp2Gr1TEi0d(2jcM2(jIH03YKpZPqPqp@k0qTq[MNj[eq3!,rZ8-R[i[G
Lh5p8[KI*IV(bhD6m,e'qQjAr&YfhQTAjIC[LeL[ZGR0LIVpdD%1qI%3J+TRL48C
%*b*C%V%#Cb91ZU-[cRiiqq0Np')JcN%i"q-F`Jj9jc#F`h'1`$P5[6SDjaLFBh'
HJ(-F6QBN*Z#FL(-5cXNiTq#FLK2*H4V1k6KRi'6fM$hbXh&@iCb$Nkfjmh$1ahN
56[C[,F6*200LR%Y`,XA*8kU@$3R!(lSP0P@T6"p`LPddYD8l[q@G-VDj0P(N1JE
pfN1UXfTLFKb"2GfMZXGdMqZHd,f(lMeelk9lEpdVG+r8[BrZIAA[ThYrh3IS2P$
hNh3IV2X3h4IS2P6hBES2ehf%lL0e(kAlD0h(k$j@pa0d(kIlH0dRk$j4pdQk6pC
pLZj6G6p4pi@k,p*pXHj,G&qUHlAZbh3r@IG6G$ped+l4Nr(Q[QZk$km$qL6)00f
Rkcj$pjQkcp*ppL#Cf!QYF&GYSV*PKMJU!DTdRk2lA0hRk3jfqFJaD@YhT@iRrVK
P2KH2iZLkk`Gh+`C%*M'@1XBddqc`p'r2bbPl+ErFL2+3!!FSPbQr+`lja6q(bc6
il6cN0`,aHLQrf"rkIZ2Ked2j@EqTm)XU2q[R842Vddl`ZSJ"phfE$Z+(pMAAqPe
)lFeA!L-HAje`T[@EqaKX[U)BmHl'TCIe@r3J#bGqlm0P[I9E1!kEVc"'#Y3!&eQ
rrGq#c9FB)`@1+9GC[fZTqrP+Bk6![T!!r'kR,ZJVPT(#cVlIpNGKmaA*51%MV)(
[Yf)cE15,hm[lIVGq"MCd52bZaq8'klIb&q`*hbm'6G+l`ISYqc8Fd#XT&lVM+1Y
h!hYFaG(pI3DEfIIc1*U-IUQq`6p#(P(e"d[hk$[Di8BflDiX*4kNQF2XEk!%[CT
C[XFJl6F0I4cj@c1,iN0qmIYC!a82R%Ml,Id1I"FdXiA$H($+(e(c@FefLRKT2qm
#k+E4hGA*0%-fe&LrY8APm)8q$YNm6N0p2H6A`-RVG0k*h`rU+YM"Yq1[JlUQr,`
2r'Q3!%FkA[b*39h6IUZSehj2IC!!pNZ`RrfqV(hl*f$6V`H+Q!rG5CM6IM8lYm"
"fIPHY`Hpl10Ic3A8L0pZr@lj!EBfl,"qEq4qjRGB[aASEqpikrI[&2MHUEc4QIf
qVrRG)l#TrY9qk-89eZpK[Q8"R-52[3RpV0pqiZZlVGrTH%q@Yp,@ErkRiF$ED-!
Ep1G6EEbEL'GJ*RQFfmrM[E1`JH(UUd%G[9pC[lZ*-DV11JrZ8ZmIIJmfrDB'T8G
Hh-2GQUZ*K3Shq"U48pcLIFfYI(mHH%iHe-c(dGUcL'A[PjrUQmLFpD[q*@bh@Ep
Chm9PLFhM!p3SXC2h3m48hqreAi$YJkSVI5hpG-Fqf+J9I[5Kp0-[FiI&KkcIc0r
LmM'EGicmi-2@EcAQ!Vc6EEbk6m(K)kV(`m3'hqpGl&(U4[hBDq$cRTV2Ei,YSpE
["HLrU2VQkpb%FSIU3Cp-Y(jIqbGXGiS(-)FJpGY'r4Cm9Ypde[GQkrFJmeDm32-
$a3Z&9pANVrIiZ2cHfXHc8Cal!2r9Gbq`UZ)+klIm'MKm`[VGMrH&#Cl9RXYDhfA
p[R0c(mpH0J@(6eUr-i&$"XrZiVc%Tp5AkReM8VrDF@,+TeA[,rIkVlE)HBM2U'r
JJB*$Y`(,)cqeI[[q[iGR06mRCX%0bBrhF2Ki9PXPVlTEHEbPRmHMa-KlV0qV-IF
KH&Cl+6R9je32pNG)Ael(H*mA(UKi"XrH3jb'[kM[YH!4"XqfI`N1Ae6Hc*[iH&C
c$IR"PkcI5Q+fMfFe)IX$ENKqm!I"XhTL&Ae"hc-A)RMf0YEb+kSh2%EkD6jl(Qc
%MhdhdNp,b(HrD[fJYB*R06%ASm!Te2HDrq[K@HdPMm-"cUZq'mPl"-pZ*Ql"cDR
I!hdmflm,Y[XXhkT#23bHhF%qTJI9pd,'&MblRMhp$I(40rAVY`iF,N+mKFr"F3A
2pK!l[kNmi(I5ClIG#KYm818p$h`qD[Pkj-2%P@pC[j-`ra-larUpJYV$rHS$HXA
([mKGem0'29@ma4rXjl'42IHJp9Z+#4Q6adZj@%@ikY@XZq4a-cQHiVqD"p#MICV
B,C2LN!#kRq"*YcEp`hZ%[22'F2(lUA)9GkPm@hL`'KGIjkKB64bL0qN$m2%0eQm
c"c[J-LU&&F!Hle6VGarRMq"@bZ9dj#hj99af%ccJ4r"#BNYq$c!(-&Cp0l'RrI`
U9j,cq'm*m%VS0mQ[dN20)Z3lbU8@q"'e1"FrmfTid-[J%2hKid(X%FihU6LkVZK
2iVH2'XIhaEr"+['lK4cX"cDr9Ar[j4Il*$R%)iV(6*E%Hj5mA-A4r3'Ip2hLlb&
f2+Tqj5lahR`qE$qLerm$!!d39'0XBA"`E'9cBh*TF(3ZZAJG8J#3#!Gi(e6lZ3#
3%$DA!!"q#J#3"2q3"%e08(*$9dP&!3#[f2mAXedMdJ#3"3%`Z3#3"KeP!!!)k!#
3"Rrk$[JZMpPjM6ZlhP[jpekR*rFkpl00Ya2+DB0SdF[Ec10(ffbIfFSmZEGbIG[
VamqV-kqC[CHIP`dk*le[1E&MLjRNPZ201MYcN!$A1qJi@A`A,p0V%&r1-32'!MM
aecIS(H4C$T+rN8f@ipH!E,)m@AKf!(`"k)"R2X$CNNUeHCjAiRQKilc388GjSD0
V2'pfTm5m-K31L@P2GDSed4a2Tj1TG+`KRESJdC)0BTdUaaq))q8I9YrMl2bBXdR
q%I9G*2qSqUk9rc6e[8hqTHVlZ2bRUqqVmTqKC9*2QIU1%U0FIDH*-90pCiXa5he
2&@1fqUi3BilkEK"MV[VH+mBmpAe"M2RUfbA'!ZX,(b('3[8p9Sa&kRZ#')HS,b2
'SHTlS4L,eIGk-3j6hr[&1&ap0i[a)1XVBAiHV,kMaAL)qYD)3HhiYZTmiAZ"'$(
e[8N-CJ%IFd0qI&mAiaMVLc!2$eAI-M%HTVj'-4kZ[JiaMPAI9@)FTlkhLr%)pAe
5M%HUlcBaMVHq+$1c4(f2&Q1TqTMl#[9G,-B*kRZ0'23"hdeL,&IIjm8i8Adr%1-
Nkj['R+a3hmPL2%TpF6'S&pqcaAL-qTM[PHVlU"M-,$jQSY,k5X%&-!SIY9%A[LB
a6P&IPaLRUZm9BS!cq2j-M029pcNaUY6h3c(1X,lTc(1eqUKKPIUH+-CUp6e,$'B
Fha[&@+Zq[aEM62A4-q%HR"RJd6Ve-4YRUDp"M&VeJAPekJ0Iek[[A@,8UqmcBT!
!%ppha(LmpC@"@4[8arb!$rLDa@!Zm$%6B#bqPiYaM[USMcci2Lh'4[ApKaMJ*(!
0ES)*q-!&CJ%IrAU5qVD*FDlk`0%RUqm2a$K2I4m4ibRUqjSBi!!8!!k`@AhJ9)[
kU+p9I4H)N9$IFm3iAhfr*mB@pB(6i#dq1%&5IEH,3AiS"VK2Vr#"(r"&I25ZAAh
-0lL+lh9LT03(*X%Pm6(Ic#a8"Ck69Kri#+I!ab`TXCcp$$'B3Ab[%Z0#pIfj'(!
VI0m8Bl[ecD&21p3(9S,$q*LITkR[H@)mAAer+-BPk[X,-DJAhcI%Z06kjS*$PkN
2h(bQqTJVHSl[FM(!C(cJ-E1'lfr%H+lk[L8'YFZC"apl[[VS%rRad5Ii$Ml`J$m
qq1+,e2F*-H"hq,i[aTA@0arHp@,eJI[`'Rc-k0AUSbrAU1r0BVa%I@!`q)N2M,R
1qKE!&9qU2M$XHZYc1"a`#Mi0MiBr`j[KNr"Ym!5qV$cCm(%`%Mi)ri%2-hId&!l
(A-0c`@P`!ci,*f#1i29J$4J$YS!Tm#VQLVQ&5rRF$1i!Ki,h`*R!4qBFM)5MJBr
`*hJ6I!QH"$q#&m'(i%(`(c!!lJ2RJH[!FF"bm!&-!![!9h#!q@IZ`6G`$6`$aq!
`F"GQ(pi#Ai%(`A2J+f!Vr!5H"&D!dI!Km"QZ!NH"Qi!CF"%i#*J%ji"VJ#2`$2J
&q!HIJ%I!Vm!9m!4m"d[!%,!$M!IE`A5`(&i2R`GIiI*`H$J[h"m1$hH(Xk-GJ-I
`%63#Z!Mm(Gi1AiHR`h[JjI"aH$JB"9E$[H%8F'di0[`4MJTfJpP`'I!D2&4m[[1
!Ikm9k*!!f635#Il9UJLY889(H@fJ%i%l[Nj%(hfGL$ll1K(pmA8L--,ALCKGAbG
L,RfGL&P3RFKJJZT%"J0mr!029#IbIPGaN!$c$X9$cJHe2aaiV1T%hMmT6R*Z9Ec
NS&1S6K5L,kS6KDK"GD)3mk`k83Mm8jdS"%DS6K3#-e3R#M'2UK1&`"$9L8+[eTR
&paDG(A`l&5[`I8Ma""rp8jdSp#A&&Ra`1G@*3QJ@UK1&kCrU4'(kU$T4Q,bU%iA
"$p@*`Z#lkN4K-&0eSM"BU6T4Q,P8R5K-Ae8R#X0G95F+[dGa#KrF@(@L-(U3!1T
%BIUR1P(i4iTK3!HcTcT4#Ee3RDL%hUK19!*QU%j8!YkV6P3#rUT19!*'UNj8`Xb
T6P5#,U!k8FNlPH2J3cG8RDJ%rUNk83QkRZT%*I"'eBP+`!R9L5*JR1T%%A""GD)
)FkJk8B3C8*dS3JfU%dAJ3BUR%IL,kN34H)IU4"%iKHT%%AL3!1T%%6L6kN34H)M
U4*%hL+%k833X9*dS`PbU6K6jX"LU%d8q*BEU4*'[L+%k8H4lBUK1&!A695H+JR'
U%d@CHG@*SXb!kN44kP'G+!V(8TdS#Lp4R5J+pe'G+!VR8jdSqM)a9#FD2[51'Rd
q#2k"D6lhT&Fqri5E`"qB4l!2A!2c`%0k!ID!D@!Fr3-Ii!E`&A$!jkr-)cJ#(S!
9m"pQ'Hl!I$)MB$kc$Jk"5f!%1!5ZJ3hJ*AK"Vq%02MpRTZ"%m!4`'ii!aX'"i!,
J2M2%V)(T2RpQ$TPljTdjKdm`ir!SjY(A3X&5RcrUc"QFK6q"bA!Rm"KZ"GmSk!R
J,V1Xr-5#YYV-J-rhh!SR,*8VGaSip#4'Fq62A)%R`[1MSYmELQRaCFN6[G,&b8m
+1S4N+ZH4p9*Z#ZbaC#Ccpd6mhNZ%r1fRXe!U2[-clPQDG'CG[1A-4,`eNFj8U",
C9dYr6&#Jq[6i2,Uh#cU@jI+I*IrCmTmMrlRbRbRrkI)[PAqCr#2jfM4aQ)#5%Lb
*pN),QPVDiTfGEBP-5cVCQDh)E'e6,IDZ)qPV68j6dDVDY4YEYL9EZ9A6h0K3EAZ
B+pqIfC(TXihfjhR1Z[L&mHUfH#D6b&4FR&6e0AFfe66%eP@G!rU5e8HVhS%T-@h
S(chRbK%d#(!VbVbDiE#X))C$rS[[48Ir-,Z`,erC!BhpQD3df""Mk+XpVS(6MmF
Klr#kj[-%S+V!YdD$EaDG'`5CG#,fP++`Zf+FH6a+1UXUbX#"BF9S2YMFJd`fUMY
NXV8'bB0Zq3eqb&#$UpI82AUPd3rkjr8HB1hZ8p3R&$kHp)a0,p,hC*ZYp-PBC@F
he&4dTK2R*rA+`fkX8XYRRQ!,p[5GjalcU9flV[eLAd)h!cee8"elMm,`$T&X8!p
#+JNkh!jJX%Z1NA3&%CabH"##Y8EM&DQZiJA`dq48065)#KZ5f`Em8B-h[Xq&d#J
Ucr[(Y0#IUf8ckK,T,BPBr@M[4dm`&i2+hrq`rA[%NEcBd#0NHQZ5k8`feTMBdTl
Sb(U9GXKVNjYM0HfGUA3fKMj5ep"FF*m4EfY,T6TLCbED1VfkjPMe#GA((fm60FF
DiTQ@H*[aENKFl$@XAP0)ACNETTiq0'k9QRYMM$UcV6F)65VEdLB+XL4-ap-l+PV
8AppBeHe,HhQpKqTU1V+*p2RaPJ61ZRM@P&cA@"[Ed0@46EBRT,5+9E@e*X6d3q-
Um[QNLE%emH0@*-pEfIS)'bMCkTSeP35STY4AK!dc'I2646H$#9+R6K"Hq9GPfVf
0eI9VJM%bFEQT`SfiE)BK+B$f(UqcXqAe1KaHTF3ZTE&Y8VK-8dqJ"*K!-SVI$L'
4+bZ@NG3SeY+fhF(D640[)ka2`h21RXNGL#[8SP0Q3hS(E9rP39h5bIC80Y@2)VQ
%8`hTca9V6(@P@a*Hiij-0Y%H#mD00(BbKL6'LXk@VG*@3D5B`6ledGlDC-Hf4&S
$T"Pq3(9A*TYUMjf9f(&4+YfDmDTD@K+CM1"#GU[8'jFL!1aX0YQa*52ihCD)e8Q
RM2H-VQ4EDfcepQ`kR[&@*6ChEGQ55-GX6Qp08i-8dC&S+r4$)`5VBp@TpNkT*Xh
%Ll-eX6E4BAbVNKR)8[YQ2eJEKFYr'-4#@&##GF[V)4fQ,`U+04YLpCf#KXQ,*38
Gpk[%eeePIKa`#H"C@kZe`+Lp@akVMAGXkBT,-i1a10'8&T2D%ZPi0TRUm%l+G@0
&V+Ue08Q8i#`05A9N6$2AYU8fDdLZ4lZ$3-['E0IQ!%U&Fq!h8&V`N8K'6@!K*R6
!J*J&b19jr&)II+'k`UFJ6X1MGeQ@kd-rSL9dh`M3P`p-(ZkLR-6P&aX`R)Fl$I0
bp3cHIG'ECqF1eEdRRq4"IjVXTiXr6pmG[2llGh!9lZ"a2mer9F%9F+,F,B8QjAR
5rkUjhKaTfMcjFqXD4NA2c"dcrkQ0i(kXrpC'%-#&Eh2j@HiiQT,mPcD#$1Ej%)U
,jZl8pTq$MC2H60`LQ$L&@`BE!`jkIcf"mqc3eD%CBAdh+"Jf*d#92I2[bVK,)@-
2&XiIiZX"'%J8F,&J+JqBZR!U$rLmD#S2q(h)9"i`-CE,-iK@NJHXAcC9MhN0B%M
[+16KaB"*A86bm+V!BkEUi4@'Z90ji!+E*[3GFiGCE[i2jHQj98m#9kZH)&bNF([
$h%K`VTlqQhU1PH1%Zae[M[pkAh#F-'rP1!$1HHGPX['diq&PmC!!2"i62&Rekck
k(CVThfC`caahc+0@$S5R$%U$Yi9bieBB2&jE@eqr[UTZGFAUMIVkBpmaVimBRL@
'fRZ[CIchU`Np5NCPhdAVh[#HHpFpXAhAX([$HfjPp`ChAp,ZM5eF[GiEfRe(HQq
mATRH'qRIR1iEJCjVf`24`EhT[QKlUEXhU[Z1GfmX$fm!2jflhhq`S800-V(Re2@
&lER&hTY!Ae,Beed0hpIH`[hd[D'MSjLr[EihNX[Xr@'$cHqqkYiEfheVIkp-0ij
`0NF4jQb#-Dbc18B"cfBSSTj0-!*pZIMLd1@5$%aH,Ra`cR4H4Z'`N!"L#$3d46m
`fY!L1YS%)a#CMapYi5"BfYJ*a,4CaQ#c1mIq-4J"d&cmj%!23fNZI!qHjQ1,Ne*
%9TZJ#+rfECTaI08N4B$9$'-)UdP')9C6&$&@-ib!E$j"F5Mc@3DQ-Kmr1(Vqi)`
#EAH1)BMaFr4$VFB@X9BcM)"Y)F(q4Jl#V3C2i+fQ'32FRL4Mic!#ZIN%"mCl'(6
cmAY3Ya!m1M*&h08-4H#9j11S5iBLj")qKVGN'!9EiSY)5rJ)c2V4a5(d8`a-S"m
m1'&Q1NDK0CGJ#%K-JRj3*E#)U)52`'N32G+f35!PFJ*&b6%'SIN-aED2J+FI26k
d`l$T"qr"c#"bH#k+D%Pi0e4U&6'$AVA*c#$[lAXAUMp(lUfSrZMY+amYf0H5X%m
RM5,j@+dqXadU9X1RUQ85aNSeS$j8*l&64GVHplmfeCpRc`Y8r9RbVe,eK`qm9$8
`*!IDSSNQqU*TKKZMm91GBD`1Y)8X%cdKah"$#*lU4LrfkE0m`bVKlPHrpLP-GbC
U6RCXJ&`8&68!D&3Y)rl1@NP89-`)hdr2adFNVr#-Yb1["pb9DIq8j-R!IS9MDNl
bQ8C9MT&*kDBEJf2Lmr6a9[MmEbV0rZR`+F`)IjfD#cr0-)FY6)5Mii4P'iMmLJT
ZPl2`f1Vk9DZ2M4flUUUT5Xb'QZSQAAh%PA+i,aNfGmaB3D6F3IF'1RK3Z39*)YR
LE!-'(`r%,((3[BN2(YLV#BeGREc&ADNlVEM88#+2"jBIe#@bkG4&LI5f6+`a'qp
SMDGEpDh`(CAQKHG+,pRK-X1(2"l-X2T"C9dURH!kMV##LK89*lR@''3H$mS%%5+
(MD`QF1F*YJKb"T`$VjrQqZJ-1'k3!*Gf4TTAL#cipMk0)J%4qE0+9VRmTmQr92l
6j6pErR2P(lcYDplUp2G#FlUGZXDDeI2-'KXGFRejpIE10Q'Aplj(@C1`D5X5fh9
642IDLI6YJ"55IFVQp9$6j4@kQT`lj8Ml4FbYkC!!5k6a0VNEYbBGYbZah(eq`dG
Yr8f*G(Zb)jlp4IPQM*de6m$G5l9C3)j(`RreP,ibI218[Y43,VYGQ3cq*SifJlb
Rhlp4@N(DF3pS26q&N@j9U23UfCRc`2[qVS*hhT`a6rFj"!CUhp0pmhiKDFQEQ5k
B`A5r(%HJ(Q8@-#`X'K%HA,a"mN!j&NrP33FjE#V2RBY"`,l%A$T9$`Y%9!`Ye+"
Vj*Sm,"55@jKLT"i@$YbhD%5K2b`N-EPSK14K)BPpLdB8mV#3!-5q450f(`I`3M,
"LK(j4pqFUfGJm6HhbR((V4MKPRZJ5PFD&b$)B3(,k-T5CMXE2bJVYcIiUeqlf3j
,$HF%DiX,5hDZIpU0ZhEGT1Y81pS10aU(q-+KK68jA@[(&E0kQ3YYJC[lV[(64qm
h0rM[ZmBr[AmhCrI,Z`bbYl`$B&XB2IhlbA5[iAIJQ[[iLM2h2M6!&[4"'i)0VYQ
9RKhT+l[&B,[AV,cf[dVfR1Q3!$eI"aGRGjFF"i`BE)@FqipplGJ4F)V0B)rrabP
1RUa2NTbLV`@FUKKlQVkFFES@FSEDe4Ur5[1YeVKce&kMF@Ye2rBcc49CZ85ZpDc
6$YHU[dlc0UZpA[2ADemD0-rMG30(Gm$$&308ii%%`JYHB@rDqP6(f2#(kZSD(!$
hL'%lCM'6d@[*mk`UI2pjL[aCRYN08%Ger4@6YdGPd@SDZcp(G9XQi`DSBpd&kI-
Vj(pIAhQ5SDkjHT8EB$if0'kSGJ28dE4kBe2&jM%KURYCm+&MkYLDEEp[q*N28mF
&Bp0ialbD1XDaNqA'*`k,T2m@2d$J6FR1b4YGGr5e0GA5j3DBqh3QhH)'U)06)I,
f+-VHd9G6apj&hRp@aq3V$!pb6c#GZVVD-bEbp#lc2YMjKYT*K,Qc$QF!3kNrBpd
"j1cC5RlJ1#UBcMKfGQp8[lq1iiph"G3aeT!!RpDa(i$rXii**,qV$T(*IM[lPTR
H2km"-ah[4Xrbr-9qG-V+8Bk!1Q3cqIrV+jIcr$T'NHLRGA6ZCkF6I3hUF!)`Ge0
(*V(PYrMKRQ$FGc`S+NY+6I+UM+`il`DSJe-K3h*IAa[!K[b+YJ1Re$h"h"d9c03
*J*aZ"D5kieKNb'rQeAIF(jU1Y(DSmrGS1L0eZ%e8jlZeQ1(TZ&H,QDcMS"Bc@FG
",HC!(AGT-40eZ"HdQ+&qr%+,'@RX29V-4"d(YCLK-RkZa8c@FEF@-eL)Ld#,'FY
KPk3Ebl'aZRk5$j%M8#f'CX6jSHN-!p'pQNi4m9d"QSlX1hE5LE(m2Q*pCpCr-6J
TC$r#h-hJ*ZXib1!QkcM)i!l8F4H$QkLM0I(VqfY"(AFcZ+&qj"MF3FBd9-I2'G0
%(H0J,R@B"GiQCX30J*bQMVDa,EhcbNpamU@1e1B,4ZZShhc"J6UF-+mC1Q+1HH*
N3hep8b'SC1f'Xhh8+TREZ#166E6VdNc*",arqTUDfY8mVD*f91eTDTHUEI,`5Vc
D[VmXAf$iF(P24k[E%C-0R@+0@`8TcGjm%Qj+NT6P@Y*mY4HVlFI09RY'[V63,#Q
Y[V%UPNPeT9ZSaM4+HZihE*lDFc@Z41f)&ei61SDK#&UEVkYmTR!(dc'(()lUFAH
p#2r,c!qmD9jmX-ZeXec"0,R20[-"rm0blG1FFmZePcRRPQX[YhM3NQV[M'FV[B[
MF-HQE5XVPXH@aTV5A4hE+Q9r)R%(+CaQH##QV0IXP(Yad!ehh(!ii+*BSFXPX($
@24ZDhahTRMf,G&NmYlbUi-Sj2R0b8@J`ESV&#YP%RJ8(cA+#4mRrD"c'+qFBq6q
d%2!`q6qb%-"QM-G*$H94(EZ0mRq#CL##eH4r9D$1LLQ`N!$"&#K&cCHV&rI2NfY
BMAU3!2arYSaPeI"5PY1-l5pPZ@FCbjR'VP%fj#pMHCEQfk"fSpT0DTqYGUhfb9r
DFQaC5mNKZjY'a&9BiA6Ii4%C28@T[([9DQI%'GLC)Z+8f*R#P,ChCiTIlNSK@HC
-l%UKFBXNCqPEEVeaFRjZ[[RQlVmri(E@Zk&$Ph"ec4chc%3iHI$$SF,6R$0cRjp
9Pbe1LXBeq@+emr6dV$LqrjPC9mPa`Vf1DFi$EjSYIlc6Iq"j#lhf6,BAa82b1'$
TC4,AUja0[d%ZZ4,Ad40A,[Qmib3Zf40hj%mNTpCAmY9m2KQ(L0CAL*[c5DPGkb[
%(5Ye4,hfV&(bmLp3c'1X,T-iH'JK6ZV`BZhC6&qqE`&9NSmqjH-@m6VLc2CX@kS
REMk'pVA3Md2rAZCJ5AYRTMIZQ@q8*lTUfl0EH[XkRrNi[$-Y@"fGm8camDiE)I,
i4f5CLBYF!NpqX)ele"+TBkE09mC'$!qaF5pp[q5mdFCGFV)%('(M&KiQE5ZeF6Z
qbH"Th5L@#fep(k5CHRYVrMPLP0PmjrkEq(K$NMJ`CEE0pqhI&jpj9e,3CV[80mh
Q1rSf#H#*5I**R(HUMG[%@elQf8Q*qhLZMNZH+MjHS*6cZ*95aqGY[U9JlX-eh`H
B2aYh(&F&H+"5cJ,UU,"eA(N9XfMMVT'k)c@DlcS*H)6Qqj%B%Fhh1['C9bmPETN
BQfhF,B)PRM+,dkPlTBhlm$[%*h0RjJPMPSfl5QE,@kTe[#5BTqM*p,9#qrI(`6a
&ERUcq%k`FDF`FaqbqEDm4RcdJ6M"Mp"LQqmjB0*b'hI%L@,FB2-YRLFqr()1%9c
41BLZ[&9m*pQi*X([X-l0L4q6J"8f,LZc%Z"PrS'C4FJk2PlQi`jCac!SAKELATM
(bhcFr+mCA,4iQBpEm)BFcKe6"C!!fEKQHAP`CUIYpjm3S)aNKr6*alR6kL6J-6E
Zh6Yc1&I+,3$"$FkThmMKh&NINB$(DTrq,SGcele-I2SF`rarc-hPYGm'J,42lm[
KdcFr*$k`9%l,K6QFfm+-R+,er@Z!Fj(E0q"6(J#AXh9%Mf3"J00XA&)`fmHj)cl
0E'Nq1,rYGq5fliZ2'5%1[&1Fqc'[*HT0Ji6JLSpc(Hq9!1@T#q!*&ZHLiEm8Rpi
%1"+mXcJAVCSP2Pe+i0"Ajh$Z0TNKHI[4aTdGi&ada5[%YeEMRTl$ZG4ILHp-V4X
m8pj`$V0ABq0Db@Ga,R)M-`qHb0RfZ3$RST[SNpih1Z%C1CcEr'6ak8f2)jP&aER
5eiS26*!!FqR["$JAZ3*XA@rMPJPr#($1[MjTcK)`hXHjI0`4i)(2#r0aLm!M(qI
bFBRR8D6LA#%Imf0a,[)fpMLSYh'I%SeJpQ8k(f85B'Pr+(4PJ(14,e2lifeFUFb
FMh0a`4jjBp1FMMF&1"Ij$'5N8HY'@&5Fq`$m6&q9A-LX+mjG33ac66lK"ciqPF$
Ci(ebR[r[1CbVTDCQa6Q`4rRF8kiA(qm#J`GAjqTBGihic'2%RRHjB*MLA'3Rr'q
6MEZ5Pd39earl&I%p8HF2IUEcrA6QjNNfMR[dLR140j`R!HFUIU0Y+Fj04f)#+i"
CX&cjh&["0R+#(eINF1jeKiK2Vl-ImXSFRrX(DY-,jd[")CfR,m)p9*YC"%p@R)[
#MeAlH5&BVR`Zp&+!cmDp5$L(cqFq4JekhDhp@3(14EliCI'T9VF8(UPirdTHAp8
EM9HLVbK1r#eF4E@dGqk3!2T1EkM0C,h)Gp%R9'GTKlI(fc0pr'bTm-XJ,SpE#qM
VA0%ci#&jRH0'iE,KkDCZlme`GG@@[MT(dTpSiel&DklkINIRJJ$r["YH*6l9LEj
`5kk1Dm%ceIkr,Mc"Vq2Gp%EeS`5m51Zi"6i0cXVCqCjF(@BZ95ZpA@VekpJ1Ib)
RSd31VH1crb)qeE1ZI,RTYp`kb[@DFc@imkIYmEkEBGrlXBb&d@-ZhIAp&dQ!hQr
icSI"@PYI'aT%eXCp&fhJ1KZhlZhLdaX)2a#p)$6AaPd2[fF@j2a3q+5Ycr1H"9j
HC10qa*aSI62I+Mjd&H*%lr(VfbDFf"-Fi2aBm0f[Vra,%U$A0AiLZ12AYqUM%U!
lCZ`#Ul5q6m#0i'[%`@Ze[VI$J5ka[!6EVbq0RJ41b[PRi3eKLmIP5q#%PbSHS)p
Bh#Slp@DiPmE"%@eFq50I,$kd,qCbX4K(fhaIqlci`%RLi1d@MmXZKj-m@q2JHeV
(mHJScl&aArQZ'#qaFG2J&XqeFGG3hcTEaddm03Z2Nh1Vm'hYApReD($29ab#YfM
rVN*,Z&cM`'Z0q`bFl`A+cp"VE2r+Sh!mG",bJ6[D[hI"#F%3mX(IY(qaciS2RL,
R@mbRl9rC#["-H+,*"jr4rVdFRXIXb2Q5D$pqrfk"Ak+*`AYZcr9T&4`2[JB231I
`q`IRK,Z"PrKdrPj0Mq!MFNjRjV4rbm$'Dc81h0Fk,Q6qd0`Sripbr6X62!"Rb!H
ZDIpq#)H%5hVr$`!0$P4ME%aTBR*KFQPPFbkjp!Gi(9)!N!J(H"p8e&X!N""J03!
![im!N!6rN!4069"b3eG*43%!Vlj[NV0G)q%!N!8#NG)!N!C"&3!!+E3!N!Cb!`B
!kl%Mh+hCFT3[a`K2X[$&FphR%Hi&q8(+AILjA4KK#ipXjUDF0SR+P0$V0V[pC-F
26cfC*kHq,ILRr'MANH0ZX[$Pb#f5(9mB'5am)3YIb#E(&l)F[b6l*2ZmKEA`5r)
,Aii2&ViBZAdGff54X-Ma@cKCH'3Kqlc&ML`R@FimXSmX*m8+Im$VC9e[&rXGpaC
Z!C!!KGa#EL'E$"BbAXKb+bHVI9lI`$krY`RY1JGfFJIjFXmQd@q3!*GfFQHCI5b
cYcG[XfrJGZ'AGEl,mCl`kmcLejPjHCf3!jH,N!"I1E(hX[ML`,lh5[0cPTfI4jB
RbqA!2!!X[0DN3@F622[d@YJq6lLKr"CHNTf4EE%&J%2m!HI)hUT4e($1,A'ZX0S
9pbahaEeA12IfZl$jIU&Bi+QrTUJ@lJcLZ"l&T8SFh4"@dkkY*H9,,p5#X`aClGc
j2qAF6qIk(cbjj)NRRhMbZdqialrha,mqpVdrR2qZ+liC8eCejdB8a"NUrr0,%PG
P(i(-Ucb@"B24l-Q#2bP2RAl)Hf9KIq(-iXdp,f3f8h$cmaf$(miAp+%k1RrbhIb
EcVe[AVmbFGbCCj5M9P#06ZDSh+efb`Z2&rGehrR2MH5"`S[&&8XZGjH6K[ZFqpZ
bql&HCK,,Ge5f$,EMF(GplQ5X$Rp8fkU)59R#hCSP0RKPjD[JRP5iGPLl`Sfr$)e
SA5r'MAUl"H9qrE*i(2IMjChAEDmf0SG",B`VPH(AXY6kP3R3mbNKNdQ29HCEJcc
(8RDHpq[P-51AcpDE"'ee3*!!+0XPm0B9V3Zj@!#ZKH1Z+biYMLaj4`q%9$ZKh@L
BLK`5XPrqfDkArrV1ZLj*JqbaV9p$"aHMT8&!RGkb6ZhRXafA[qIL2mSrlFZIM0J
!QM-,b2I[(815SKPc-KTl3(ITGeC4FK`A&aiYAP6ma`A)hGUZhMeDRib$H-pkQfC
8PqY*e5dDVUkhaSG,`e'cA@q%m@(6bpGGKH%jiDD`pBVGiRTVjP9hCQJ5fXfVeG2
SL+[j8HZ)MjBJU3D0BfN3@c@AZEMHQNS1fbi+EJbq(l6*plbj0!k1q'bD6G+S@ES
fh(06&0H1f$C8Uf'5P#T"1Rh%X('fhULp&NhGZQZrAb6BcDdR3C+%cFQA8iTa@`9
K9NTQdqA$PejkV$LdDAYY0'dX%e#Z+PT8kUh*`Uil@4Lh*3ZcPT'04fe+eGJb2*3
d+DZ,`mCK`fAKhQ0jA4(%8f&DQJM6p*A%cXGEG6PSYc2,ZR8cae!Z0-bMA'JDSPc
"6Y*H-$-T$Zd%j8)6&q@Lp144VXh@Uq630N+j8Vi&Pd,6!XU&YK(+KBB4bS@')FS
9l#,J+"Lh99#)FP('FLMADYTH'i*b898%+&H`kdj@J()&-e#ZD&1UaK$P3X-)j8,
$!XT&k"'K(2LR4Q(,Tc&[EHBmblCZcV-YY(14B3$`N9f)jRlmEGeD`6KU56cMS"I
dE,aQd,-SGRA&c!H0Q'GEkZXmif*MjeN@1c[2XY$D4BE&GLQb,T96SE[c%pIDhZ9
Y1iSTD2$m!XPhH*&KR,0mMaICQ5B[Cp4HRB8fcl-XpRQHCDR4mk%K`N"6r+l9iRT
bT-GF1&iDDkIeCRh[5kfNLbC,Cp-fdjHLhDVbBC[QS$Sf85U(j+58aQ+-1FJ+JX`
C5T5H8@ZB)I*(84El3!QbD+GL$'e+)ClbEf!C'HIl`m#bY@%*M!YpH@#DEb`$bea
RQ6I-GfYjDkpGbp[j[9QBm%*h@E30fX[3e[5AJ8fq3!2,A)8@$0X6iaG[B,5hHPX
(#Dh'(HR-pFCj`lMFSZiiEkIEii*4+GAj"MQ`c(I)J@9aFK2BjNBhHF05ZX+19KP
0'e`cQ%`hMU*KD"Z"B@KB`-,30JH&S@@%K+&K#)3&ZkJ`#mD5k)*CHjjc)0KUkS&
'C+SK-$5*%$!d$!'`D&G+LB'rd+B9r8,V![LefEDR-B5qJPehJ3A!9c!$piSfE4Q
18#mdM%![0-aMAQJD3Pl"VLe2HF$Vk2dkqVlZRUqchq[SpGVl[,M(+r9hlEeG9er
AeG-9qVQ1AUkpMq[SiBVpfklHVEY[kqlCf[ZeZ&FVp@R&(Ufp2q[ScH+jM4N[c!d
RCkHQ`VL8Sd0N1hpljG942e!dEkiD8QaE@J+C`YLM%&*SkiG8Q-8A3iS',D8dqIJ
9j5PU%YX5&E54VCN+M-08j9[2pPbCC%iUM3DYUGN!e'MIHMJK`i&UJ'"M(#L)b(V
bX4f3!#QPS4SM9q90S3XiTf+25UJ8G@MI'R9S(83GQV9((G9B9l)p"ahCpXcckIE
X1[-Ge'&(`J-(TB`(jP(+!l[ZR"IKEGPXLhjMibZE2`XDdD6jEKeLJYPl()![43I
Ym'VL,qaNl2(H(Rm"LpX6e)UDB3&%cGhMrVY,)-,BYL59N!$E,i,mm2"arjePN!$
(qIBX,8pR*dqZS)Afa@f&d,Jd-3rY@aG(3Z[LZN0SA'UAfZh$%JiG&&BQ#VE&$B5
#Jpl5b@pA&%c$[B5SiPTh,&V0SjiL-[Fh,8+cMQf"d%0K(D0JZkFHZJ'[i+5c(X,
PMD*GCjd89cK#iq)d)$4Z@cd+c3[E4`AEpYkii+5h'[+V6!96k`UR4iAI1YllcH&
VU&4'@6#qHYFVkq)rMmG6YQihUmrT#a"Pp*Ah6bRhTlpfPJhDR1,A33IJFQ6S0IP
%b,-&HC(feT@mHS%33M%K**%TC!Bj#PQ'()QX3&BL"b-()GQIlbZTG2JG`erQPTa
&GSkR-4RIU%qH`*3)9q`*Rp1,fP,"D0162jp,T*hS`qFD+&'mq"&LURS00`)!!!S
*4B6L8Rk![Z5dcdY%-&jSU*AMdCeiVNHq8J"4CYPj&I)'+3MVD@i9(B(!8"FKKmZ
YB@T"[5VbMPk0rhpHH&l24%MTDdBhlDV1e'[U29G23'*6SNp4e9+P4B+QKXB"f`I
heYX[4l9f5k@dGHJ$3hQGGHC5NkbB4*V-HY9U$H#Jd$a4U5k*MhjhXIBd[F,EdmR
D3cf%N!!8q5R,bA%L()T)C*3bMBmSJ-j[`(q!j&--),QdjE,J#!bIUI)m[BIhZ@!
C"UMJ@Eh@[aD1EHBcaB@X+SGT(0d8aM0*+9[K@IlZmG)PK6AhheYBXh[$MV(5q1C
TGe&T3Ur'94GFl3VE(R(ZA9mBZ'#VQbVY'2YKY-HV*qRI60[ePk!XmGl280h$QZN
8T(5T&aFYjh`HbpTQ1m&RcV,KQqU6@NECHNkqq#8-MZPB0RkEajMAFTVq'TBllpc
Rp[b$ZUT%iG,I'5JmXJe5Ym46kTS5a8rqYY[cp@pdJr`BFPTZqGL(d(PC"PN6+h,
,kap&4l2[IPH$1FicZH@&(mIJe+j2@VA"ZHA1Kp%YkeLHG#q2bYabachSPRFYhmR
MNGcbNcq2ENA(mYHh%ZI3h(,kl4LXl&Mqa[8mhTYEVVm2hDTZc9c+`qd2%mAce8D
ZlPLq'&+lT1AcX8pJ`$$$r9jk-BqcFmX(9k)lV@[jQmkGGdCZ1I1!i-4BhUTmA0j
-%b-Cp,mhL!rXbf"!dE,KGhP-E+B0%6EP,$r6`ih)dKf3!%MGI(B,ZY1lPSV1-(&
4EYPIY)EVZTC8Jf6Y9B2ScZKDiZ0kUm)2SU2H%Zkc5%8IP(J!5685jkm*4j4m+r*
Zj2h)Yb'T0ZVU'N@Lj(N@a@EN#e5D5Ri#qA%N$5Y94VAHSU+K2*5m"dP,HK155U6
e@B*mRD#0XP15$T+XcV@+S2*Z4jk22-X`KpS'TAiEq4S"Nj+[4&k'[%leU54e5Xf
m#!P@-HZD,kK5FTlJ4mN&5#U2AZTL!Bq59b'IMpb1I#'5QVd!ZGj3l8*KKY3@8iT
,N!"Jcb0)+[pFUlJV$@1EN@p%hS%%5F##0b("`R13!(FKAiC8Q1Gf$Kp"IPLSVH5
Kb%H4'j!!i#JB65@$8pZ3!$FL6dDqeP$k@L601cM`%U4#XF5[)&q02!aj1&+KBH)
fj"&)Z"k23KjY2FB$b1&)ZSB4b(FKMaAD+$N5#9ib[!'EDT!!Bj(MN!#eDS'89(4
8#H(1413Nj-1'9QUNl!f*'"ia++*Md--LaJPk'%J(!0B249BKDGi(@Xm`#!Pb(D*
13mNKb-R)+FLTb$VNLFL(e0FS13-j(9Q2T#04I9MLFdM9fENMTTRU**4m2r*"0@T
+[Jp*ac0ElCQ5(d+q!UNkYF5I)KPpfJ5qX%qd6B`8$6&Kq,Nc*jGpcN,a2BEm-NL
Li!d8FI8+V0DePjhc*`18K%0j$A`pFD%P6+LY(XbmDp$L[%XfKH*Bc2I8,-JR4p`
9NRhRXc[`3hTPR+4*da0-#da*$eie2(E0b+V5UQZ'YJraE0Nb[&fGT8APXmC3EdB
mdBNpb-Z4Nj!!,d"HJE`+H69b-r*Lj"EN9Z6cNGZ3!0Z41j!!Pb$R)HFM&b"24Lj
%,N+HJPb-E%BZ35j&YL"245j$,NHZ3+j%VN+Z4Uj"RSCFLc`GZ3jj"[*-j&R)jb(
A)mp'EN#HJpb)2"Gj([*mj#EN"FJ,NDa,RB#FM*b#R)UX3jk)R)DFMUa(cN$14-j
'cN'HK'a!0L+6b"4b!R)LmP,N+#3c'#UT@N-@PjBiK*DRPKYqj1H88`bS$1k5Tqc
6H0KY[cLMVrdaD,cJKlY0AGlMZ)UI,@VYSK&dDN,1K5IjKrdAC#QRGSBm@$BNhmp
mrXc[,q*peZmcF5KljT1I4(i+q@QN'Crr'C,a1@0d-eShSh6'k)cF[iKN,-eBRK%
hShP'hU`)X%l!%)8a0@X)CQ4[aZ4I3SDMFXENG&Q-rmfSR$8!a[q-lY9-e9d(B"A
JXmJr4[j[j*mJ@A9JpB1e)eBR@*0J4B2e#(SN9LKB8@"0j"Y)eKPBSf#GJG8+4R&
QGB+e$9Bf@$YKPB39KQmL@89KMB+9$&Ba@20JAB19$PBe'-Zc1-AU#5X0M1KCZ@!
&K9889JaB)rK6T&NPB%$-ZJ(V"'D9J"@%cb&C!f!Z`dS%R65V!+b3!,"b`GS#+aq
X[*KG9eB3@&Ai2**9MA$&`JcLcCU&SEjRKH%,5,-rbd,@Ab2r"[Qh5,AkPIJkmUq
3!(q(r(XN5eprLI`HmV[)lb$r!IQ2b(p#rM2bqmKr3Ij!q#1Yl,GYp9E&cGUY3l`
1qA9A&&NVqd2N(b&C3Q,pK&Rf9j'XDl#f`QS*+d'Xk0#0X@,#bXaAN!#XU,#U`bS
+UcUX[l#H`mS2kc@Xbl!Q`d5Ee4l@GPLIq4U5G3kckX'U#QXjV'1`eX2D%+XBV'#
`#[0e*+XBV1Z`#X5+#qXbV25`QX(+%#XZV2Z`qX0UNPPpB5A)E"5c!X1k$1Y#V!f
aJX5D%UXcV"qaTX4+%UY+V$LaVX3D%UY(V1q`IQ0@SPL(BSf(e4h@SPKVBVf%&4r
@HJTV9DcpX%E&HJdV0DbMQ&889P"B1f%0KE8J'm*RLf'+X*PY@FK*%8RfG"4Tcm)
@4&hV'c$)c)q$U@B)rr6q4+SmZLhUccmhG"hrLM"ZePY"qU2`14`#*SaTJcq6F6Y
faVMiK+hYS-)kq6G8KeRN+2"B&q``m*SMaE!2Y'%-K3jq9SBfc1Ajm--,G6ImK'B
Mef$%r-4@mC91q[!f%$Sa6df20*PB31GPAId#-NYE5`'SKS&KZ`AZXp&XJHkbl2+
bp03bBZ6eU8hmrq3I#lZEPMLXCM5CQm*D+DF0f+lf[jVaA5,M(Gk8kjUM1"5EkrE
,-Pl0p@RTBZbfZNA#JI(YkV4,Xl&L3k-493HVTQfD$PTGjEc@M9hGh'hMAGhmi@C
Y3DP#pC3,@fNBclE6RX'Q"H@mZCjb5C6@GqrTUK9pjkD&0#`,NfJfVLi%YMbUcR5
9+b#4pC3V@r@j"H@1HU1VA"`&5Y1fF#UFDqG@$FQHPNAC'#5GJ"XCUfkc9$60"!X
&dB4'`PBTEpMF95dFlDUD2f3UYcJP,bMRcEAMA$ZASDh@H"8eldB'Z++k2+c1GKc
iT89G,3NkL9i3QVH6Jf6D01U@M5fGY#eXeF+jXFNE1PT9KT,bK@1GYemF#mHkB6)
f-TVYD6F#U4fhN!!f'5+3!)hY&P9B[Cl6PL"1,&mY-e1Qf"BQBAaMafaETl4DSU3
q0j&DK5L&SY$e!U(!aG*2fUT!*TY"Yh1&EZ0V8G9G8`F9UB+QU+eX8$4'YEbG`aq
k5aSNCiF+ad0(dFd0NjNdDTHR&*aRV*Q1PFAf0'j9Jb5X0TAiJ,UkK-HZIrI3N!!
#pNT&,BPD+S53!(ik!8aXLG2m-K(ASVSU*[&4*3V(a8#AeerCkl!9QqAQ+)e!Fc(
CK!2"5,b2"qX-rQQA2Kk+hQAjpkJa*5#hR"Uf6@`T$3r+P03X"c2@G,8ZU*`E9%-
TQkNQe`8[iA9f[66[0#h+qX9!5Hh#CTCXCC*i[h"f5i[5Z8Lp5A91TSbP8XTP!fJ
9IA!LjaG1l"SHflKa-3E&8abUhA"9M4E#K9ZPZE,cX0S%,%S*''d3&'U#-TFa*-S
6Slhk3*ZV%GpqlZKSTT9U-#E,dpT`eh@KGME!Blb&&Q)l"-3Z2ZdX[46`DCP"2QE
9%#Q!b([bMA,H3YTaNeY02k-c(*B3[[a!A"1J+c!aU3bVANG6c,!%+FPC1T'&)c#
LEDYAVkeIYkjf55mUE4M@L+5-G*TmLAHGdV"DjpIM4*6RHPZQ2Yq4D%pj2U,UL3a
jIB`2)$l+f2aJ-@FlCJkME&!RleNX5"HU5SANZh#"Tkhm[-UPPj8q9E8SjfEPS3#
MX!fJ$3,fm`+(I1jiLca(I)i62Z+!,h#qjjR5mmcSrR8,dH%8)FpjNGFmb++K*!m
Tb#2+mF)K+1&p*mAl9))E6laS",0896&jZ#KV9dXh(l5HH4"FGY"qc%%AphqVNB`
09'F1pV[$!Y8*UXLdGPP[M+'5G%R$"J,,Ujf*$EcPrVa&c8A8h'(pJLR0SHkZcir
"-Y0HRlX`9MNrPT8fhfiSirEdrLKMFCdQF,dkFXBUfq*)GUT[9d@dI,DYTJQrbKE
F&#pU[U%ejmCK0JHiF$&6VP,R*NqqRPK[QA1K6`0r[-9Q+IPX!rF&2MNUMH)rm,%
8c[kpcmH-`UaPZG[6bX1SM+$C$R+XR3f"mrQAZ3N@m1!S)&X$EF+lTGQ-@TAUp+"
)&R*H$9YI0q00iA[C'q`pbjQ6llCr16YXXEfPLU!ir(+6ZSj[aFLZlGQk`H0aq11
rk#[Pp'Gak)qG8cFIfea82Hq&$@j*l8@hFY2ea82cAbbJGmkPQI,*FhIH)Ii5pD9
+EZr0!fl*3(I!JZe2ebfVXUP@bmjKQfJ9rGZ,GVNUl"i%-pRmMmmqF#r#[K9T#m%
(9eVd14P"MqhRXd3`9GJ3CK(r4[h(p4EUZG+1T2@[5C!!I$RLVY&q3+49hJpcT'8
,IL)J#rh!5,6'a`-,dqR(idRdr-#qY-l($3[8YK0qJVU!*@U(p`2MePA(rF"DCIc
!bVADa`1Eeh8,IMS+@DlTH1K%AA4rpTTV544UpFa[3qS0,CRSfJ&)12CqiBc3+XF
R,&H@d!*`U`FhHj3Ke@Qad-iNhUC@8mP+C"pNAf4rC"9b!()JFK"b-())FLMb814
Kb-14`j!!4b#24"k&j$6CBj!!eFMKb"()Bj(()8FL4b&()mFJDj!!Bj(MN!#eb11
4ij%6N!!6NC13!#FJ*b1R)+FLkj!!*b+R)DFMkj%cN!!cNE13!,14Fj!!*b%EN!#
0b#ENA13#j#R)aFKQj",N8Q3,mP6N-Z3+j#VNDZ3Dj'R)YFM6NHZ3!'FJcd5HKGb
Bh39Fr[)8KLr$F&jYYpKI`0HDm&NM10`6blH0E4XUM`b1l",4BG[hj'8YB9cfJdQ
3!$eKlb8DN!#D'beZ@L!p#PEjV+YI5%0JDIRXFD4(qM-M5`LCc9`EXQNcCS(XfT!
!Y%*DE9C5)5D@'iXm-QBq#+R03"Z!C9@!$c*J3mE-ELYNch`3r4)l(i5qHZ&5%r%
DiKm)T5'3!1D$r0SFN`5K0@65I*!!0V0'3%V*&k65k,"RE3!G"0Z3!%@MJp3EdQK
d%("$()f1@3)%dZJJA)C)'Kd%ba"+Si2J'd*TG+aA#M'L)j*X5+[43Aa-[1JJ2TE
EJ4cP@rD'("%C8f[S@)D!i"XG*-i3Lk1$S"abFA53!(kcfS!1JQM@&p""5#e69NG
Ne,)8QP408VrSU"R)c0'44r+2$Vm3Rk1M[L&!4`Ia%L6Sk##IKJ`G(@64N!#KSi0
N@UCZ5C'+3ik3!d9Qb-l4X@i"k6Nk#+1*%4hc#!M3d8(B$"%k1SLFU8Gd%$4$L)k
1NEkd,8R9"+6Vk#""Kl3D(56SN!"@Si1d'r*U!f8b$8N*Jpc"N!$5J4(N'4ee#%%
f1R)UJj58BS0B'ae%h$*V5SNm'm*XG""Z3mL0$Mc!$cV)dDNGG1ad3qk0$T*V19J
P*B*UL,l4JA2J+MTU(Ia""rQf,*HQ4-BTPb#P9Gpbqe&DZC4VMp,#*VR[+#dXN!#
,MY+U+lRK++dFbG9'DC&pbje'D@'EA'D89LlP&U1dL0rPqU+d#,rP$U+dL,[PmU'
d#,VPeU'db,EeG81*TDTGDJ3GT2[J"MS)f'8K05eLG9NY6)YX(5*pfJf`R*bJSkq
3!0Y[bY32b)drCF*6#1l4J91b,PZQfS@S(Khe"NDK)im3j+2$,cd,1SM`)G0("j%
pK2VSk&INb2Fb%C,,5R@CL-8Kf%F(SEc-dXT%k!kj2MT)lfA39bDF*NCd%2*#ZUq
qM,!Cc%3([JZc@8Ci*d1+M1SC8Rjde)q--$1+%i*qG03S23Jk+!-Jl%F(S6Qfk1L
VK$df)ib4GDL-b16"+h33f82QVlkXF)9D3%G23Kq($Rb(p"dGf!TC1cV`Lpi((EJ
$+6`kDKA5H(68!,d!1R)"L6`kqL5`"4hNlC!!bD2M!!")jG&a9)"l@CA589XZ6i,
53FK2cY&"`%mXkLYAr`IT2$Vk(XMRd9&RN!$3Sk1IS4p"4cm!+6dkm03pqNcT`#D
`$KeB!&Np1ZS+2%G(lL#[4iF[HMedN!$9Ja[S)*Z(d"iGKa0!E)m1c!!rdA%J!Md
41R8mJ%YbMilM!S5F[N,B$mNp1V!3%RadB$mNqHM!IRT-G24Gj!%G1DEA4NH1kER
3JGf3!1LM!cFKddF(hP'2k-!AHKCde"iBL)jm3E+2$VrJ2cS1&)"d(afp'Z6lk$L
X3"B!+i3hp(VUUp5m!&*qG26Ue!XkqM0)qY(4Zd,@Milq%%a$4cr'm3MS`%Y`!af
p"rL-MYj!eX-UK8-FlB!1(1,B"R4J$AP$4fh6Mk1MaML'!"djiTJ'G2MPS!Cd(,a
!AD0M9N&2Kik$#cL+!4ep!$L'MMi!RqVVScQ)2TV)M[,CDeCjV!$d,ZjRJpM6X39
F8e8m%H%AAb%Ch'1Kj$cN3Z3Lj#R)aFKQj",N8Q3,FKPb"A)PFK9b0A)0mM6N@Z6
Tb(A)-j!!'j!!'j&*C!V*)@qFdTG"CT(Pb!TN*E)2XLqb(l)+13!j%$N)14Jj"$N
8H5Mb-16Kb'())j!!4b+23Kk02!CCM4b1()%m&RNFFL4b&()dFJbb"MN@13jCLc`
H14ij!6N413Pj!R)bFJTb+V)1H5*b'R)kXKij!cN613Xj'cN(H4+b!HNI"f1*16I
!)[1CddZk6TDNmcHAU$&P05HLQ204c1NSiFNSj[56`YNRTD[DQ"+D-eVqhc9YjK5
Bm!5BdX9V6&I0q5j-TjNqQK0+c1NNjJ`6TXY-PCPB-$Nf*ji`)@BUbl55LD`j!58
mrF5FF"+HEf)Mq1ab4h,Yqqa`ICl0l*3A$X)0f86E2P[%3EL&CIM0$c8IHVEj,!r
eG(ALbF`KQ%'!@i@V'-dFJKN%X`Kl`Kb#'35YC@%1`3c#A2CSjK"Q"X%mSM5(+-`
JQ$p3+F`JQ&%!ccD)@B5pK[bSl6Y`KCahYSj3HEGpPSLcG@acmf%qDm`K(K9Zk6P
(UIErlE-2!2b6M*Y@JHTYCpc8#f+bJ@jPqCipTmVp$Jk8RMfRbNB!%Ircd6jlqG"
AYHE1L,E6Y+M@f-ZC[(-bl#bI2Bj%bK*,+"JFK@0Rq5ab[D!3PpJp,RlF48TMFpN
jX#amlJMH%@P+H%pbefHS)0@hkl`'1d&-GMQ#""[&fIK@RE9Dr9N#pTSd#PJTd%!
p0*%@I*VFi1qXApm-URhGaME!JMU%'[T"m%VK`ARj'B6@0N`)m)#ViCheq9U(h#9
@lr+E'@eUi'$`32@,96NHq(G%,8q$9Lf)Djfl#ZZcmrRU(5q&'[@9fFN'je3ZE&8
EXl@`EaKQ"(M30qmA19*Z2Cf"VHd,m+!bai2klJ'Bp@j`lH#9rGD3!#(!JhlpiiK
p0+'')MlHHe'@1jf'((QI(lDcbVdICYd9hJq%3jAH$`4aIE`I516kHMrXCr6cIL#
NkqrpX#Y3jIe!DMI!qi(iEU$h!bRH)Gi2a(Q$[4pfViCi2a$`$I9q)1Nle2Z"a1p
`l`HL[f(H$f5!4hJr%!BHkIe!+RL8p`2ai0(H$q5%ahJr%"K@Hcq3!"`1phiJ3Kc
Kr8#@H+ch!k(LFGi2T)XM[4q)'8Gj2j!!0ilfIL"i(12p3!*Cire!&$R@qi&-FTc
hijjrmUpq)+Bmh[Z"Z(+mp`1jj36["`,-LGi2**Q6["p)0%r`IL$FR1cp3-JjaIY
KHALUp`1aCjhh!qRRLGi2*+(6["q)4+Gl2a#0eRXrN!#4c["q)#bGkIe!DMV,qi(
iG,Eh`h"bM[F$LHT*hJp%U`h(rAJAm5NVb&JEI6`3YMCj2h$bcI9q)(qGjre!$M[
Iqi%iGS(h!lRXbGi2",3,[4m)DQmmi5G33&Vl'Zm(8YYhH$m3h`lbIL$(IGF*(!M
m3+$lZpi2*,[[pR&$a2XHl`Hbh[Gk2j!!qElIqi%Jq!2H$`6#(r4q1$hR3liZ1%[
RB4m2Tpjmf2[KR*e(I0bFZ[14daFH+R01DINp(`mRmMcUrA$#bZpl2jc(mckIEml
HHI#d(aq![Gh!2CqpbimlM8jQXh$f`k[kd1d$fqIi!PVh`r@"jeDfrA!e@13Da`)
HH1Ieel[-6Kp1AHrb"A,Z3&HARfqV4r%2r'SlipHLK3GUIY#rlp`qF19rm8GBY2$
qPhK3dAH12k+mIaaI3)!(0VM2YRH!PJhJXmqG+UFj2'if2[$A'U2Zkqc3f9Z-'[V
eGK$YVHEc$AE!l'eQGiHplc6lqqhp*S[Mc4EAAHER,4EA@qepYrPjQrPp`0j[0lY
ll-$DHh[RGf'jIR"[hFi8YGGmDlG85PZ(2M!N@G@E6Lm+EJa+%qmH,ee5@(2r[B8
eZcIX'#Z0Ejjf&j8Qp'TFGF(9h)DV$Y-FrS@"#lDkUG)11mlebDpjCkN5*0@JS3Y
D1RfX'0QeIE"GY90@Zq0SZRcidNZ2KP(+kFrLd"qhFEVjf1DLkRN[E(",DLqkPCZ
Z,akDrf)"[A-Z@d$q+[611qc!h96*lEej`#dCk*i,Jqe26m5SdRj!FfARm2KX+kd
hMrUh&YfI!&qqHREaGhQm&XS2h8TceimSf[b!%Ml29qb(EXERqBVpj2LlBMr`GrP
mB,%IHLHIjb[f3pIQmhc&IR,mAE%Iq,Ym2V$B$raG2XpAl!Iq,TrR+rC$YqVcI-9
qi1rbHEjL2r"hq6aIX4riZhbHVpJ2r&dqceIX*mIIaHhp(Ajbr&faRaar9q`Rapm
9qmRaGm9qF[aGXCmFIeIX*mII&I[*mAI&IR,mAE'I((pAl#I(haAlbI&haAjbr&f
aRaar9q`Rapm9qmRaGm9qF[aGXCmFIeIX*mII&I[*mAI&IR,mAE%Iq,YmAUlB$ra
G2XpAl#I(haAlbI&haAjbr&faRaar9q`(rLkIPb[f!hqAcr-9qmRaGm9qF[aGXCm
FIeIX"riZRfmVpJ0rPmrc&IZ"[m[RqBVpj2LlBMmjrUlB6ikr+rD6iqq+rH6iZp)
rm!0rPmp6&IZ"[m[RqBVp`0rPmhc&IZ$[mRQqBMr`GrNmAl'I((pAl)GjS-m(&[Z
"[m[RqBVpF%aM&hqApbNr(+$BaGm9qZ&)a5lqVY!2I'"Gr&fK(rM!H[QlP"ri`(V
jZj3Iq-#kq,Y#2db3!,[iZd)rm)&emAH&IZ$jkZ,[#[h!mpA&haAkiE$(,[kZd!p
mB,hmAFS2I'"Gr&fK(rM!Z[Ll3Mr`JIAbGbNrm)(emRFT2r#"pI*h+6r`JIAbGbN
rm)(emRFT2jbphXAI&IU"jkZ,[k[i@FciZqacje2DE,iKeL,Cidi1YI0f6VDicp,
E19NS3*1,`&,CpR4jPl(4`J330ST2YJfbIHFB`09"iCBj"["-[cd'F!XE(L6rNr&
j8hmbUZFm([JA`pRQ,N5cbef3!+ISf9!IZ%MQ18R#"a80,*!![-X2I16#Vmc2Iq[
hARB#MD99m(2HabFk@m$9`Mi,pIqNaNk3!'rJ%iCAf&YKCJ9[B95&,48Q9+iCK1N
8&P-B5Q%$Ji(d%#3-Sl#(`J`+kbH-RV"e`X3*bbB-QV"M`R`*Ub@-PE"4`M3*Lb3
-NE!r`Z`)Db1-M,!Y`U3)5b)-L,!E`P`)+b'-Jl!*`K3)#b!-Il$h`F`(kak-HV$
P-6k$j3i'1pMTB*kMTQ'-J`d1TMGBh'"SJheY2T)VbNb4d@r!hN[PXJpk-K,f0CM
9B%f$`3af-KM2E!ZIUP521&SY$Pcmhm64&Y"[DlYkpd3k1fPV-cD@!V$'lDAE*6F
!E%2AQ!4E3(fk++mC8k)G)+@ddI3!pTQ+X2,JKi@L+1`eQ'E$r3cI@Y+GYA"a61I
Lb,#K5NAE2ErkRSGXD,FEr3(LD#k2DP0RckHf!+Uh0-@Z%Kq1de`CeBD2$5#1eF2
D',)!j(ACa2Ma#*q+`ldrjqaT9df50Dl`RG[FLUeTed(jTc*GBp"S4&'VY$PXG'm
IFZki-p-j%iIfkqh'!F[qVUrR(KirMR(Dh,)#a2&i3[j[()qII25612B%FL#1MA0
YGr$KIAQp[Z2jkIP[EbK)2rJCGZjfhZI'`lhZRB"fqDCD9U1IrY`!p[F9$MjbIH(
fRp6'QijMca9%qr,"1TmEaq2PmC1lM0BRr3,Lq-9p4rVclM*5FHa'STrFGp46(e6
XRXq0BlZE2SR6+Jd05G0P3'e-#cLpCRMXc6i'(r2Ik'61LDUcTq2SqHJrYLAa'eh
$Mq2B2YfB21fRCH4d9P8FDL[-$K!(hhL+j0QmFT5'G0aekklY@p*aUmafq(Lkiil
MX!Cdh%[I[pAZViSrG8a9EciX(jelGeDIlYalihLLFqq0iiR1I9mF2qlFHq,SkGc
jT(0hIQRPpAd!1[I1I2bdFim6qe6RhK2(%jelCaM2G1ipF9J%1[H08rpAppD2MVY
ZhF`a(dphh0eam&N#1Zl9pGD99j6QePee[11Zq&((T1,BJ`a2GNbpF6c4kHb,imH
G6NmF6b*jCac2)(P2((Y"6m@KkRjICckq86q&9X&%BPH&U$Lf60j`-SkPNcHm'8G
&q3hqM[*bH9Lm)aD!ldH)ej4AiVii,[VhAP(&F9'3!1LDjFeY5#d,bI8UqTa`Gjq
!["lX'EaHHQp2IL#1(Z6F@fGHIH`i9@Brq[TN4a[Z`TMqfI4aIHY4TNVG8kM5jdq
K[VUr1hfd!X64e%J5"m3S!1Q13f%pH8fFR*1l8d-V3$lFDCm9)!iclGXGai&ThrP
TXq%Hi!j8iRMT3DaI@RJDrG"I@&2BrhMEV5rFYfIc!rX+GrfF`%3a-P@eX,qkF&r
VbiApAm@Ia('"ULM1arikNbR,T[EVpFU)a3@LAA&`G@4#aeNHV(YhbQ)&U&GhbQ)
&L)02`jPLV[TPAYdi9(NNrVFqPN3Yh8J9IdkjA1N$`#F&b9C2kj%iTrr%jN26f-G
IRdhTcp6BlXrYBD`!F5bk)GipL(`fVh5PpSUGaGeIU4FUI(i[p0reiIG#ref[qbI
1[H0QpEQpd%(m!)(AeYY[EZ$XckYpBR,0*ch9Vr,UaV(h(YMpFI5XH#A1lrqfilA
l1p$Tf*9f[!jqPU8GVkhY8peT6ekIh"AEhlPlZf)(2`[)VPJRJ$bc+pD0e,D!A6(
GZ6H(mG6aS@Lfrd6REURS6+d!b'PA3+VpAbr$X[eMTQ0aBFVCr9N)CM&f)+DFJjp
PL5RR`#bQ)a!E`5cQF4r#Z,2RXfmal[5XrbF'qPAXrcr4`GNhH!5Hl,`kirKTja8
Rj+R1UbF1k`3r`S(1Ub-3Z`$2JSjMikNk)iL0L68&ZrcB!6S#0`kV"1q$KCZ*dhN
,lm$%kAEZ9MBQcMeerj`+JSPc41&6lFqrbX4jGqfYSJi6TlhaLY4r[lLH+q2Y*4I
A'ek9dYAeiFAe&S!Crhpp0TSZJGVNV&MU9(rTV%V11M$af0,jqBH&BrDfEa%!AX#
&m`q8VrR&qIR(ZJ`D9VC[#FdGI81)#imGf2R8Af2QXLYEfliAd#``#`PaiBUmArM
LAr9e`i@2-b6c*bmD&cjaB0YYCmr2rd&IYrN#9r(hq'!dCARcBqHjH0mT,'9bTjk
phYK+N!"2HG`GNj8LchDC6deH+1#9aE`Z&$,Q#X4jU1Z(cBa9ardi26pXP9cCpC1
4@qpl85pZ0Ne12ql(#dljB32PKGi2@bTAHcpXXQ5kIV,(!%(jBGXPHk)Z!MpXa*4
l2fc09(JrE0C8HMpXhr6aIYM3kH[pX-A6crYKdkHrpm-f8*Ah`mE3!1q(VD+"hJp
E4iGi2f`Q$ICqf&iDi[f`i668qf%,kP$[K`fT`ldIYUL'H6pX@KhKrE#0GD6h`fE
@8Gi2feY(HcpXH"hMrE!&9ZhpX$%hh2YC`R1%pl18jl(H$fZZahNrTr)FkIdXicR
+qeR1Fl6hXi,R'1pR*FmDlfF9cl(HcfUHilbI06aV[Cr6H"l[rDcP1Gll1ChR"1p
R(Fq*hXmC2#Gj2fIb2-(l1B[RC1m(3SNThJp%QP1p(hDekl`IGX02p(lBp*RQr8!
$0YhlJC1hh[Z"#@k'p`1A`%c[Ca22@Gi21qUc[4riMZGi2c"8RH6p`+A5i2eFc,2
4qpR#XmRlJ4eLV[IcI*lc["pB3qCl2h!F,2"qS$JifIZ"`f'Kph-TceIiZG0P2+r
VqXNHQjXU2jIc[0(2ThEbI)hh!ch2)1rR#Ti2,IL*mKMkZBVRqh`md&JmH0U29bM
fYhd0Hk%IfSkqif0MQRTjArQQm4dG0KTRC581UpPp(*[#'R5$kfYKV&l5fEKPG!6
h6XpCFKPNP0AEUqV"$j'pkZ+5jXHm8rBZXhIDhTAfcYJlDqm+HjIEHj!![I[BZkq
pQqhGhpjVl&ePl`(f(YM,9qUX6@%VM1ZGR0@EMc2XIEUpcl6h@ICHB1r"pKjLlk(
f2Y6HKpRlF(X2XrF4pMl5hN[XIC5pMlEh8RXIBqpUH`qhp`Kl(f[[iq`pdYkMl$h
DhQ2XA@2[XIBHCqpDHap[llAf(Qr[#IDHD1p*pMl"hT2YICUpTpMl4(Y2YAHG[9[
X[GMHTpTlQEfRfAZM[FqcpbTl6lIh#RZ[YVHTiaQp@Nqr[4c&i8E120Pq@AE`bIU
dG$&eccc'B-p-Hmqbpfalcl(h5ICZX(HM[C[XIBUpjrEL,MphBPU864ZL@NM!LQa
UbfaFc5LRA%K8J`6c6[AF9T`&*#PHZ,2M)0BS`i9Ej@08cdIP-Z`h4kP'6bB'&eE
91p2cdfF&A&JkP%eCi#jQ+LFZ6ULh`B9eTRFa9lhGZP"[&h29fm8lpAEaK&dQHEY
iS0kAfRZ#Hqkjj`SAMQc3Hiqd+hr`BGfFl5NQh*dCXeE#rCBa5paLLkU[0`D5@fd
fqiD-F5[KlM,'QY[0lShf[X2LZG2dEl*ihQcah@Aa[-ALHkZplmiB[K,ZdqEhlHE
hRScY+q%qdf2)fIma3&JbYQfS2$)iXNZVB@dIQfSk,2@3!2I+`[l#Q8A0GXeR2lX
pmElm*TRk"8DGm[Bhp@brDHH"4lq4[6Gm1,[@`X,%U$eKliE&5mD5dRIHRUKX2ih
F@VcmPP,Kl`jP!'qAZMha*dcBh*lBMG2YYbIQFGT5IRZL6D&cY`2G*E1lFqFc0`K
qlHNeI3!kGl[8lBN(krij,F2YL9[rD4Y6THiT91RcTe$RPEV64bY!(-(YLGeaY0r
BPjq+Z90$+d!qh'QI&5!1lrE%AA%FQ2DjppBYhVp`Hf*b@A%AHR9lB[+FMab%&@c
UXkY(rkKB1[3m,Y@9#!1qK[f(LZrjdS2&FciU[VcJhVSi(r[V,,JpX6Z1pYX6mh%
%YbIq+KrZP-8+8+rZP-8+%!HIKV2%rq69M82IR[LV1*iMfYbH#)0S+Z-2c8!08k8
V%cLDaIlf`@I[8VQ#"r961B'lY3dB)!q@q`E+FMcB(24[`i)m(U4KFRE@j`XUbfI
EkMAVlAS&QaT!'$a3rD,c+Kji0a(Bda!K`)0NMJFEdcLk+BaRNY*%'V4U39cV(0e
3AjiB,3f[Gr9@2c0d-(LJjSYpmrP"IIG+M(ShZ(E`bRjV`i3!$rVPH-$T+q[6rQd
MT3!2+Yp5QPd'S6pp1ELkVPp*I9@iZMKI5Af4Z%U*NZD+F'T!Ab+HF,Vf@emIRR#
h)rAPiG`kVQq1i(XI8PmLRR"2)bY0abj`(`ZIYlk12&&BaD1Ik9JGl'qkdhK8QHl
j2)"MG-3pd(4[iM()G!rb1-4dIm*MX1RqPXH3!&bA91kij4cGd6`10Gd-(QTAhG8
YXlT!arlV-00GaH-)drdfMb00Gaq2Sdch#4l%KHl2H4aM1PMeC6XXTAL'Qqi%(L0
-Yj!!al'QBqR[10-"8500pa)HSdah1`pU"afj(f1k2qC4BlUrjM%fek99Bi,fDF9
3DlSj2)ihh@V"M1L)Hi,TAXE$hGeAZMYi6$,G"hL3!%0dRq-afA6I-6`"1X#4UDB
Mli*-CHYiR'Jkm!Bp1RE,Tj[Z5Kj#)&af"`rU&0dlHF`d(68hbh68h1aFPa'ZN9Y
de+elq)65ND-'da'h6+icG4l5@f4qQBG-N!!cGr+3!,2B-f*ENSP-jLNH#dch94l
#PT*4V92,`#-iXXKda#dl*9R&,42mV$#pfA5rcQ1*k9iR5"IGlbkd%pQri('UkEl
*!l`bm,[FG'$3#Y04EbY04rbV6%HG8HrS`,BeTVZ*"pL,lJ%HDdfRZ"i5(cBGq9j
RZRrQF8DZUa$qRQNkX1NXde%rXMjE)4YCDUfBib'p8F@[@Uq"MMS6MS'+2qBK+c)
9cr'3!*hd#Q'EE$Y9UNq3!*ki8VK',D1M9U9RUP4XXQ0IUAc,jN1PmLecZ-S(H&a
XZNraf')kkNbQ!'i,3cq#MKj!TMapK&r5GrC4E8YVf8IjN[kickdm,MAGc6`Z-pf
p2+J&G)raf'QkEr'3!(&MAr9DFQepAr85[fBkm!kF4%GYNeYdj*TidEfB"fdfZPY
j[-KdlqB"jU$l$)rI-0eImF#Rq[UTpk2[3!HZJ)hS`19V6!IZr+ETU*RI-Kh[Ddh
h4Kld%HMHbq2PTU0(T2E4ICF(rChkqUYAZmjdp!hAQ`lFIkAT`-GAQBlk[m&dj2V
9TU21EM6G26cS)p"pR!Gp($VU'aa3Aj9kB(bLSfm!rp&4hf!b1Z+qaA6JbZY04he
5AqL)RliB(A(ICVVIjd([KJk1&1S#hIrK3@qP[J(#XcY04ep(RiZ1@RqckF$ZZd`
(CVh&G06Y@de((ZmfhIrLm6E62FT$-mFP"[k5"rP""jF(@+5qJHV2hf%kF)iq&ah
p(ML*M[k(AJ`G23!aSL-IpjX1$+#23%HZhf8kjJ6d0HMS,F!LG'$HHdch!ajJKIS
'U5E`LBlHq2fQ!iISIp(4)p'6SJ2I2fJk-1j$TU2'(M)GpJqElV-m2Qbk[qIa5+i
l4$d023JkHQRk2R4J2(@%MRk$ZNB(pRc8G16lBkBM6M!((A92hiU1ZJIce6GB-iK
2QJkmS3G""kj6)qMS9Il!G'$P(jU1@U8h4%F-i$NkHQ*bUliKDK+C$k"M4J$fSU0
hC@D#MMk0AKiGGD0S"PdG@2Cjde&,i!DkVr#J,e2I82AFIfBkCKpI-Kfp0cP(4qq
(6h6%4bq*$RcmQZQSPDqEM[FhFYfKkJR)*cS`!0a'4jrh&kDM$rK,dp&lJ#IS`-&
[QikkC8D"MKMSGp4hQ(SGHK"dc'@qCcTQ"#kAMG+"pr5Hk1L[rXCdj)pC%cV`3RK
k$P2HrmjdhqF"YUM[F28@e$ik-1`I6%G[riqQSjrm*p24#p&VS`1,L38GYId[TL0
(B+EkKUR@Q8@J8l9L4Rl$Q(dSYNLY8lfkBr1rBI53!)l0riE40cJfraX'RMSfraY
'I6SfraY'R%jRrQI6qDM+C$C2631+&IhK,M-+,Up4GjABj#icmLjYXEA"3!N25TI
i*-*'e'k'VA6pF&3,G`CaA)rL8L@15QXAEl3*M!X"f,c`3#jefRH*ceimf"H!,3X
2-NF[mE'aI3%HC2[,AH+Mm+"FXfHE!Jp[,c[PNIfhf#PE4U-q!"aA&K"Q*3XCbk9
Yih)31aNET"Z(E*YhimHrpQGZ('UXrfb6j[&F(baDYjpq$Vl!FQNaZEpXcfFRBi0
dipJldpPIVfiF9SQC6Lr,CEmq5bbApS"EKL`#E*R@NZZG,#9XN!$PX0%FkCT*HJ6
&NjYKM1Qh$l[mj+`4PTZdl)3PcAb1@+('B#I-DqCE"F02AiX[C3`pI&I#J&9TmB9
fNf!P5PPmS9fC@*XUfc&BPha)E%r#B11)R@j%ERHIf'L%cFB41pVJh'ki@(b%fFB
4LpLVFVXAD890@'k5B[YCP0[9LJP-''mbBVUDQ0XY&E14X0pNa'!NrP*L$")QR+6
BGkEPGLm8!k@`BUC8JIebZc[&VLF-QE8`*+8YMTh#&f(,G"Rf*(rpa-JPc*NTiG5
`h1jha2!Q,*S2`+E@YjhEA52@+@(8c)+JcV,FVN8-3m+ZQ4*EPm5h8'a9`V5C%V1
Ge0REj80B0e0L0ZZIfpdVYNKKi$`1r($1X,U%m8rB1&2+fHcFETTd`XbC%KZBa2%
"iCH`G0E"+18mNp[G)EC!BHa-LD9*mR5EiK2fcT5Bfb42I63&&5E2-M'C2C,EZ3b
G`ZSj%VBNjlcFlLlej-,`19VXBQr*lEkJ@K+f6aF@aQGfcVI%8LA-Rp0JJdZZb2d
0%QZ8X)!Z!4FcC[FG-@9T4P"R2H1Kb4mcIl$R#6YSZ4VTkQDD#&m0041T8i&AhG9
-XiPeB,G0GIDmCYT3lJ+lY0Jk"q!2h!hX8Q+2NrViR&LqK)Nd,3Bj`FXD-BV*9Q#
C'$HPcPiXKMpK+"fMANA`m[H%$F*@@Ulf5R"V!lNhc+9TXF%*APD)(8YB602#-r(
hX0K$KG%dV6j#m2,&fQN4GY-bX6J+ARj%M'(#G$SE*M5$Pep@c-*k@UDkN!$mE4B
ERc#JCT3c`FZl&DZ`SIi4l(Ippq9f0`RlT00FJCh"biZ%pF+5@LD'6SR[3[NbM+R
8XG4C[HTHf&2,a+3S12G&-B!+NqSQf1!-APiV,"4@eG(#3F(,@p@A#-0U4Sb*%XG
(08-8YY8,U&h"5qHIa5)Tc+XC-Ij*RMiLGM[$`JTMSX%$f0@%NA@$qLI"bpH+Q8`
ka5h8LF(,2aA$U$#eEY8'K1$Pp@)f%pE@FZ9&ifAbAM('#B2V9YMA$&jqANaTXS4
q'Bb-"LmhU0r5c+j1#r`cH*N9kk'`[-i5$PeYH'NBLpAh29Mk2,`-l+kPAr6`-V!
EV9`D[!cX(1')e-G`-9N+Sq`BXEJ*AYiY(m)Z@b-FP$TcThE#0$Y&6)H#PpH)U9&
BCmHTS4$FqU"B%i@"YNEXJ)*r3i9RXQ&5,PBh`EmV0$U3!2P%8M-M`GG2b*pXJ#5
&`4,I3$'2#Q2Y4R$Di19YBX@6#A*5V(L5[kaL%#EEXDS*`FX[LAP1XpSkCm0U1@#
ri5[-NF*`@dq1$9j18ad,fff0mQl`%[CCf9FV%jC,R9dT9N2Cm+N4DkAJh#h+K6$
L,U!r-AMT%M8+1qiiXF-+AVj%1Q(+(DYq61*iRM"*aLiRdeHBr[*LpEA#S$Y1[E,
NDC0bBGKdU8[*diG9Zm+XkkCAm(+mX&9BGRH3!%Z$PkX8Jc$Z,K+,T1$P!''PX1r
@bVIJjF1UE@(L[3l-0RMj1qT0KCAhGM$9i18Nc3md3kpcN!$k0RMj8E&,#P[[5Xd
m6(pT@,h9YaRmGCih[!cX4QYH8QYi'GV"+QV`dVGclL'[PEFddkNMma[R3[UIj'A
0GS+rd1j4HUrd[XTSNM)[!9Z&5ALU'!YPEK6i5pc1[-2C6pcd2%&IqaVkIXmZ`1m
DeH&%X`[b9k0jJG60Qp86#QYaR9KMTIi@LR95')b6USYdERH*jJ(#CMa@IH2CZGf
Ra1!Vc-De`Q-GAqSG`K)CY)m9(Z[i8X[9``RMF9Uc%)R[$p3Ib#c`(-d&*,kEa1)
TXmCD-AhUq$,,a!STV-LVK(-k[X`KeBHX9kE&FURMbha32D6-KLm9'kZ1,r-ZeE4
X"Qp8rkrk*"FR$11l+V&h`5`kS)-6JGdSkXDjhqV-YdZX8Ki06J4f-f"bGDifA!R
XaSUK92FCMBqT*p3ciq45jPr5Cc6qQ[S*Q5IH"HZRi&rM['TGcck6+jR(#2ie2U`
jPM!mhd*r+he*iceLrC3jjPLa$QZmErVrBTq9RC[4QRpU['pm3Efbc$I(#T0d2p(
i'jUGb6l(kqP,T5pTr)VUAQEjGFU0lNZDcPFr)8c4Bp9E5a`Z@E$-@fqPhj1qT2%
acBaN6fL@HQA*peH%Fm)QAD[CM+llaXq+i98fHEl0R%Rk[+B9QQF)bh5C')Xe(M5
p9cfr-%jI*Pc8H0$i9FdXKAekP4SFhBmf2UXjUc"4e`SrG$rDq'IUY@6YDCbD-UQ
Rm@*%&SEU'Xd4T*lZ9@mRE0Ah++qkIfUF9ac#A(d[V-$52c9GU0j,@+a[9MbkIfS
D9#mUM0Dc0(r8GG#d@MJKl0Eh-C13!2kTmAle'F*d28[pZHlM'rpF05'Xel18HmR
I%2@e`S$p6XdGG4rIp2r%q#YXf'I,VkkcaV[8S`XcpYQD$4qAfFfp6jJPE-rMe(r
U1TKlUrS2BAkqAlfeMQrZ%m*Jc3,Y(&6G5"er4KJYM0!eUUhacH5P2La4eAc+f!A
i1NjpB#9p&EJ8q(Z)1@MbE9PmL5'aEQZfC1GRUDh8&ERG&0@+-#I29Qid6LIqAYJ
K,-TI*@i6ajh#9'&8rL(pLBRM*-ffK&ejYM"HiVK5Z4+QjGFb`c"a2+CjMfCGGTB
bEc"aA#-fD'&JVY-m9q,S*rc6E-a1%9C[%mF1c@Bd-l0c*Uc'*Sl[#R1&TAQPQ+V
G1&iirah0BS5aq6,0j2Sff9,eDiE[@mVlrFhJj8hLfqLhR(`H-c$4l&lBRXGT0VB
LYhZh'*H&qAQUqXpAjhDM0$r@,0$1hH#V-j!!fleIZG#-d-i9c!NN[N&,a4BXl0$
hDCBJmEPEbCSTfMPE1C!!q,kT(PHc4MYA8TFQ[MHS$p!-dXjDqJU6[qZ&*F)QICp
U@Z*ES9j)-dXllp&F@H*V9RqT@DDGUmL(LHmE`Lc011dFS1j-rXV9afMfDHG"kYA
%pchP9$041`pU,LAaI9BBTPQTRGqR(c$aMG(XAKLU[diIPXclQe5'Vm*@ADYq92V
bpkV@KEQk9MJPGLrAE%pBV+H)-9hETDp8$bq-eRm"dl+*l`,emF*Z28[cE)RM#kT
,BETHUES9ZdHeqb'XebZ9,l&l@20McB$Y$$,2-['p3Mf"X''2%dZkj'1"X%1BXDG
U0LCaA+%iK#@l6V-ZXEY"61UD-GYC4[fEq,kP[NIBXfGV6d2m[9XB+NcDUp3l5Yc
pe4[,61CXiC5*MlVA$0[11jRhP$QE%jM,-06AV2j*c@[G18&S4aaQ,KABc44$YTN
I"(CTpIPTQam%GUHSAp9p3(D*-&@cI#GhJ%mbemq1Lr9I-hilUm&)Q4pN2kRB0IY
hXXCq`Y#m,mpq6,fG-)'ISMQ(RKpNefV@,kcJ,kHANMiMZe'l4-)3rNVm5TePIef
pXE#&efPHV2[,l%H&RF)FAL0XeReKjPp85m)L2N2l+j+R`c5(%%EaaCVV5jjZ&cB
*ZrKL,J#3!$P%pKCKJ6#0Rk1DeR1)l!I9Z`MVH,2LNcL1%SZi-*!!hd"HC!k4q4[
e@X*'IT(Q5AT1N!#GdCaBQ-QAU)BNVdhUii@PI*c`AI,k(Fe#K,&mP[DT*+mAULF
8p[,IdTl!ah+l'a5(-*RIa,k(c!1bbp@M#k[jMF*#23r)a[)R$1HE0D[6mi$X*c3
M&*ciFj(S5YbMk@m-mrN'p5*k(T!!r65iD&M3PfL1)(PGUPd3kCdhUVF@[(QCGL1
Nefl@43)5hcTdKLRp@[R9rAhQbqUa",XZe6a4prIC!AS*`k"HUrQ)kGHpHHIr"`!
0#e4ME&0SC@aXFbkj"fqbp!Gi(9)!N!J(H"p8BZ8!N""q#J#3#2q3"%e08(*$9dP
&!3#[[Qr$XedM`J#3"3,$8J#3"MQY!!!PT!#3"SRN"J#e[5kfX&X)TqeMC(INpS$
K#EX)Xp['9ZE#RM$##0YX)C[C@ZDeV-GdS9EHFQ6K+CjkdP1QE`crY-c0PT0&0VY
0f'*mB3XPbaNRbaQjjGM#Pb-,[pM#EcP@E$Re&XRaK42@NCf4jIP#Gf36GTY``Sf
`j6cVqI+-,-HA-pQLLe'J`b[&AmI1LZdijF8X,l+5dF,**JZCF(,,NGqa"EmFrVV
1ljYd$VCRN!!EVC%YRTCR)lS(,[`S(h4XiACZEC,A3El3E@bIEXdZcckf)Er-)&r
B[Mcc&kp"Hp#eiAilZ,r6@dj,b"Gq3HemH(T`Zm5$HTd$Z(Z&H`,P35pIH*l3%`U
-"4"`C9k$[#E*MeT42U$`q-)D3%ifj![C2Pf!'3(SG13$H%AAV5LPhU58X9LP2Y'
[8NIf+29pAi#pbdJCF)e1[eZbYeUHjlLHQIIF(ABaL(b0P0-4pd*`(YdKem8G5Ve
6l)'[jS5q'p90iIeLP@U'6ifY8f36FT*%LdE6'Kpm1[l0Fp[*)HAZK)$ZS"C5[VI
p!SeA6%cG3VM,ha@XB+L*d*2cGa-'$kBPqXSKLb-Qq)P,e$MPlK0lTj9f4fIJjmI
$N!"kdIXTaTJa+rA"CX0*4Gc2P@pf@*j3hC,EHZG!XG*M@bAEbqFc,pHkGMV$-QS
TJjY6BE@p1BSD0`%9cE8!`5!!$[&iZ2Y#0H[01EGQ&GfC#T68B[AGaXR8[ZMHb$a
8(c,qc$MeTX9U'FT`Se*rR8ZN`,#dfl3iCHbCdh6XhT,[6GFpHmMCrHrjF![4MFl
f4,(2ZY-2V2"bi4[%5b"YP49HcYk`f`PkV&UTBRZ[*c#'lS&U`hmr`G'G'QM[-6m
U[1f!2CZ0BmDCe0FDf*0fHNS&I1%m(T6l[r0'%jXK*b-lfK%jh*Hp%Y(eNqA3rp+
hm`T1Y9ka68"Jlf,3ZRfRSPcUq1A1I$kVe1cM!,[[k0BrrI%%K'B+hiqMYLFjU,M
XJ2m#Q"E-p+)T`+!M4V4-%pTJdB@U02PH9VYGG&Kh$X0I@@c32jQkR(-*0fVl+I`
,BRX2rN@ar9D)!Y(jIIbla2CIm9GQ'$+I(V%Ya5A5DU6jA0G&YM1NRYJZaQ@Zf+l
&"BD$lF1il##fIir,MQ,l1LlcaIDr``k-@SdD,a5EU%A"fm@f%THRL@dG,MZ*lA@
il#bfIi(,BV(pQ[3,YYY`FE+6f!5RJRGT@jkpX84XZq1bQpLHM8Z[f%l(KITMHb8
Za-(fdlMX)EChil+Rf(i6Plh%pTpaf9YXrafAIE5YJcfXD02"ZLLdGV#RIdaXTq$
bG,%"jmm3'hR[*cEbALifF&G``pP%L`cB1pMq(*F$Y+f6IAZJf-KjKGLHJmY"BMX
9Pi2&"YiG)VDVF6P8E2p+m!IEEq"bZ0LqJ%ZIf2i8PfGT@i%i3NpKSar)&aXqcaA
EbEJSUKIBh`j2aABj,NH+l5fi(#@f$q'L-&pi%THMa8B0MK(E(EJF+cB8aq1dV8K
XHTlBk)2RLihm`4PXp0p2L1d9Z!M2FEDVF&&F,K*[6K$EVq"bSYJqMFYUXAd0PaH
)lEm*9J1rB-!DXB%"e"mEI8[Zf+JlrBL0qfPL3hm'Pl#"Ibm8fcY`!C1aJApRLJh
mHj(BrJ5A&fYE&c(qRiS06$a,E26j6iU0@Jb)l5*FAL+f0q"bYYM)qk9Lqh9FeSV
Yph"jQGM!SCGV@cHja$PL!a2TGfc8Qel$4[j`'@bEF+(Qf0k+bhPL%ii8e-4'MCA
fGV2[,a$Ehq)#EX[T)4p3"DH(H%FpXG(cbZek@%Hi$,BVF,P%E'r(j9+a#Gm04-,
U)Gj3(fcI`NAH!R"QNE-Tmj[&[#m6'eJ-TQ%$&eiM0QT0[YM!''APXkJJA5NfmUE
IXIdZ,[pFE2m&&f*LqaiZm$ijXmR(0SX0A[&kXB'9p#mfm!*1JBhD[9&Xp25Ea(B
c,Z!rYUrJmQDaI4qADl4Y$VNC[!mE[A@Gf-#YRa%E[3H'Bb-@[BcY"Paq9Qcr%CH
I%pZhFIPjECY,6[X,BS1$JEhBi!P1C4-E1%LIBU2IU#'fAm6PR@,lYlKJarC9A(j
*E$r!j9pUfccbbAH*$Ei%hm%'[X1jX)&"F'TXp-Pla3B[Z9jX[i2,qm6f$9cHVff
)$X'$BJ2l2b!fqZD$BL0AFX%'9[kbf-!&Z!BfqJ&qMHdMZ0"(f$k$#pL)lBpaq9@
ar5pFi!9bGL6I*LBf10P0BS12I94XB$piMSekIdaXe!!X`NB[J3rBm)%2BJ2lEa%
ER10@ECY2c[eaX9&lqK%Eh"AZM!h1TMV5I2)6p!TXB2&[L`fmq+6Bk!di)$E`!rk
&lEZir$YY@d#Y"2d"'rbFhX4'[HNAE1$aCm8'PrJ2BJ2[2LFfHKZZJBdF`'&XD#I
N,QFKHGAYBJ0h2bmf114r%KYmKKl""Pl$)l#"#em8'h9"Rm''E[%(fZBN%6Jq0V$
`bf+$[i,2f-"em!dE(!NY!KXi$LI&"REmSGLSiaq*$G`&0q3mMAS3@JdfHK4ZK3d
H#qr!4RlJ'cEkmTYL!erJ40LS)hPKJcG36cNl%32S(@aS"f!&0[MUR@+$)p(,f-"
PH$3fX!DG!4[pm'GLqjqiS,I)fCNi"rI%KYla&f+$PrbPf1"[m#CXm)6r)6D`L9b
`8GqrdVE&l!Rd""[Kd,Id+he+Im)&i-[8&+i-Ei4M`kh"&(#DIS5$d`2J'I`GlJT
h"p2!'hJKr"e1#"H%qm1j`6fi-hd#EiDc`C2Kah"MF!9q$"DM,p#RB#1pK+i!AS-
GB!CB!8E!%H&lp"@m%$i)c`4AiB2`3(!$(NSIJUrJ&*J%&i3$`RAJI(!p1"lFMPk
&Ip#Mm$Mi'rJ!Ai1R`F[JD(!cX*Rq"ErKC1!cZ!`HJm2SQ2"PX!Yp#-d5R3,0$-d
5V4)X3FX##q!Nk+RS*QLTm"*`"!k0RJVhKi2#@q%mD*S!0hJ)9dDrK'HL9rVA11J
%i+&r4`'r!62K,R!+0!Gi![`!2)82S!ZL"i+KD)&J0*`$l4!Y#Ed"$S[1"HE#Nq!
rD(2`2VJ5HJ3BLaD$"J'r3pY%d`3ciDAJ-VSJHL$k%2SI'LEk+ISIf)eqLQi+j`+
ld8hK*r!c1#Ym!ii+ai(E`P(KTR"5Z$(F&mi!&i@$`MhKR2"+1#Ci$kH%5m)K`@F
i)e`4$Jd(J!["JH!qk$TSH2!&Z"Hk(ESIHKqk(4`ER3jG%(i"2d464%G!)i(ISEf
JZD!TSVHJXk"6S82#&q&"F"#d2$3m1$2F!Jk,[SPQKeD(jZQj*M`&VUBDjq6aqMm
BjI9rm-2Vrr5ferrT6krr8eZ[ri2YA[q(0hMp(elJpApUkl%)R&Ephq'Zk[m12eA
rGlhUAhM4PkVr1mkKqVrV4pAr(EDUrZm`fq[re&(erj!!'+RkIdJm8Idr**kTrKm
5Ke6r$pPRU[q(l%A9rd0b)YArhGX%eIp$pV,Urb%jKHVr)I&)pIq3!2LLqRr)@UV
q(j*rUIiI%Yp8r`r*De6rcl'@U[rR@![9rh2%8GArFm35eIpca!c9rh2NDDVrjmM
K92r2N8HSrZpHkkMqRb0h8rhI[Ae3r6p(,&Ap2mGDU[kI)rG6r6p(6URkIilBTrT
rlNA"HH!&M&$p2mmq92drcrUUrTmRVURqRbI@U[kI*aG8r6p2MUVkIjjF3rAr2$&
'pImmHCVUrhR@6,%a6pkQqRqHI&,erccjTZVr(F3eeImlf,HUrhH`AUVrGa$c9Ir
[)&DVrYp"R&$p[i2F6I9rpmj#pIm1mNr9rcZ)IkVrGj!!TkMqhd'ZS2Tr"hQCk[m
Ga!R9rc[)2eArlb4HUrlI5Da8rEq6f+6kIbHa32Ar6[D9k[qGV+2UrjhNikVrGe)
$82frNca1pIp1mQc9rcYC5pAr1iN6U[ph%Vp9rqmN0eEp[j1BVIUrSa+UraH)ikV
r&eJReIrGQ`l9r`ZXNqVr"GC#pIm#m8$er`*jXZVr"H+Ck[m&iTRUr`AbGpAr#q5
&U[mAb&e9rbq3!-HVrZrHIDMqAk!'S[TrJ4U[k[p&FKM9ri[N"UVr&iQjU[mALB1
UraH*1kVr&pRcU[mAf61UrlYh)UVr&jQRk[p&FQ[9ri[8*&6rGqp(92m[N[ZUrPm
NleAp[dK1U[TrN69@rEp)28Merb*l92Ar)V8eeIp,j'qUrjH)hkVrPeKMeIp,a&R
9rd[%(GAr5kbPk[mPpS2UrbAQSrTrLEU0k[mPkLkUrjI)keAr0cq1-12*Phm6KpH
+d6[*F0qfPpjDrM#If0KmB5KjQJ0GF2IVr2LYpMUViZ`4l0pfr['YGR"RJ+ICkfT
@m%EkVBN!)V6XLRm4riAi,m&r%IlGq-r&I`lq5r(I(Impm0m6rlhLPpa#lhK#QF-
rMrpmr(N@!1dVi&r%IblqXr$[`ApHT-IB-mFHQ2d3-40K+b8SL%l8`RkqD'-A5!D
[M25dq*J`cpJ0J2-%a*X""ll5k'@40ZCZXRCCQBVPqlDIhZ1)IP!qCr6Qc8fGYe1
,HRbUK5A`MRaXYN3fSkA-dMLlARhPRS55p(E'Ic(q[ILMIhVYflmG3FG#,d@I3X0
!Zd"(J(ZL9k#&SC1K2D+"SNe#cY"4d#E4[Y$&d,(3YG!Hd"A3Sp#Hd*R3lY!8d([
3PY&Bd95T)IhThkE3NqJLD%hS41JpD%(d'4S)qJ@k*rSVqMCk0pS5'JGD$2S6ZLk
k$MSI'L$k%$SRqL5F!+d8E3[0dEpr3*0$Gr4D[YG#d6h48p&eiCAS5'KNi!DD0$S
ffJVk0rSU'UlUK8j233Y%Gd*[3UF"@2cE%R4JN!!!c3UY%&d(23Gp#8d124YY%qd
0I4U+JdD',SSfL,B1V0$Qk)Ed0[SMHMUk+9SS@L'k&VSI@L(D(PSSl`V3r0$EdHr
3pH&0D2ISHfK%L)4`@E3QY#3d2p@VIh4bk)pS`SJ"3m-@Y'IkZMDdQqeGR31GZ+l
Zc3c)``)VjCJa-f@X''R5-T0T"1ER0dF3A94H@UmA,d`K%VrM,iiJS[[0K4&%k@b
R5$ma&05NbS&iGe0YF)*0*ldc[KcqGkC26IV,CK`PYZ3j`C605*J#U%hX[9#"pLA
(N!$rSUX6hDU9-J0d[ZVJ-$`dV2HJcY54p[IrSUL!,R$@IXE!P$#,BKTK#kN1@5d
2qGT)eDRE)qfCbMZACNqKVbeM8mTr'5plAi@*)(8cRlXZ6['fmhpL@V#P$kQrchM
#q(VUA'0+Q&hcGN5kF6DjijUbADQBUp2b*VCb'P2X3'CcJ8+@PIH-ImJ%`,pRNK-
c"H8X4B4ar`k!ejKraNE+b$M'!NDjAke2hI&[j5-(k3@C[APL`366l-dkYC&[6pm
d3Sm)AYGV$8aSM-h5!-)YG+#!pAC-f[Fr*X5)G!2J2#SFbGQQL6ARdhZVk1JmQA4
UNjrP&)Y4EU#641L%kZ8FH+(UTPe)"1H4b99bH+[UjPki#%l8[bmY0m"P5!9lr-h
'i!13!,6m[!d0N5([AVG8UZ)`9#NalKE@dMjpN!"@qSph'XE+X5CH!8@pQPU9j@b
KH4@()CSAXa`j'FhMVJNcYm$0b[+j--6!$FR#!6DkME[b'Q6JQc'XQH-lK[rFR"e
ilPff0q+EE,6H`S*qFiR4FI4"Sf0ShCBqXlqRV'ie#l`Ge6jrV6)fBl,NdMpUQlp
*$CYiAjAJ4flqji8GjXC6Dapk4KdmH($b(hlTJHhUc*Nc&rj[`l1[L[f$4ikm&11
KIl1QV9Leh1f(rbfIrR4#3Tlqf"&e"ap'I%d#I,J[Gf012rG[C(GX[T(YlmjpijP
X%bZDVkDpTrA%9RYlC1DrXY@rNpe4j1lBDQ+2rc9lffr#[m9@fcNhlC8cASGfV8C
bDI[9mRS`MiIVpeKq)r@ILYI-Hb61`hhcB-q1jT'pHS`IF!Fj0h!pYf,K-I",2-Z
l@q@fLQQGlBGae,%AZrVdpYZq1qS9iENaA1,Rb(UpYqB%k5,Y*pZq@-5cE-4biZ!
1'0FlJe@NZlcN4VDJYiBTNbqcLME5$!UpI9ZfTI%dH6QYUkbJ(0j2br52eJ+RDSG
Z4fiZp*UC+)U8D$rD*#&0h4GTZDImFU2SUiYZYHj8(,YNDRlQkKZe39,S)#jbKF`
YVaI,$#-[hTIljFTNXY)"kjfL&6KZ$IQ+Y9+U99[&LR'eChqM!$lAhNAQUY8M*[I
E#TS$@S3rlU[J@HeGiNM)FUAS!JRMZX!pm(D@U*mNKlKaMV8@Vh5@V5iYb84ZfQC
LlSfmR@2I5m[UL&G[ElAZHJ(IM`IVV8V&G@XSj[SkFD0r@HDffd*2-Dkfr+*9#Dd
RfAX8lNIk9E8YdpIGhFaKpBB,jM4R2jfQlq+mJ65'Dj!!T#i3lPAjV4I-[M*Ue-T
J6E*hcQZb3*Di%mkDl)6)$j3j1TX0V9PRPIfpYBTNiP'$"R&4HaA[KY,A@*@-Nr#
8*9)E%U$32R&Y%MR[1e@*b#Y1U!*ANDX#RXCaX%Fc4TJjQ&kcHk-8U*+,$cF3GmP
hq3RkaQ4$c'AI#!`J,8QmU%RL%05RMb923S"k429B6V9LHJ#1TSiH-BRSbZTJVeS
`-U`jeaSL*J81U5*-VZ&c4UZLG-3`!!+aeLpk6Mh3$C%iP(1Z42'**MkZ(ZGHLP5
T8ZETZU[Z8Z8e-,ZM0S+h5D#M0ZUHVf$[84Xe+cMEVIPZa8ll`HLJ6mjh,Z)r,lY
KPed,3VY,k-4#*fcei414`bVE'lE&"[kTFrqS(lK9m`IYZqpb[C+[1S[STBX!i"[
,D+)"a0aS&Z`JF'V$[ZTf8*G9U+Lc(MAU9%VQKYf"CrQUbaiF(4kf292($$3Gk!r
C''NkXq`9Yd%RFR)H+@k`+kUhhqbV!a"P![1&C$#1GaeRed,EdBl2pbER$6+&T++
BK&G%Gpe4,Q)rQTA3SA,Z5Ih9RIVl2,'PH5E0JFRRTfKpJ*QeDX1M&R+*fq*!64B
PQl9H5&1$&A'T$c)l5b@(AN+)+,@dXZIXNY[Ckph5hCUl8mhM+ZkJa)PDJK,8R8i
ZHb#h&a'j*,48CmeSR3`,"dPY$9"#6**5"*`(D04aqN6N'Z'cKR,iE!-I%hEb6kS
'fbc(MT[mBmP-HdiAmR-5pVC6QCCV!``ih$TF`ie6Y!@1EED8J`8bcFJ)@Z&$&eJ
YbLDeZXT%f6f8KG6%LiI)T9BF@%0A+`j8XlX9Ka(,2A%F[i9623i2SQG0a`NDF9K
(BNiV(dB0lc!GjmT'(,HbeMeeC,68Xel*1c'`HX@c@h&B"q+jV6LX2A&m('F)'(3
abm)VG8`-V$6aKPBF9U9i8kXqV%,ajZ[jP"[+[9jY2'RG,N#))i5d29'[-M%[qYX
-mmZ&`dE2!NrmVqPrF4hTLikZl-CYa4'Ra$H$TaA`!(4+2)$2qBhiePmJDJE8C"*
Gq0&2*Z(Sa)Gi-XN6ddFUGRqQ*T28iVIcIU`qPAU-a(dJljRT,(IeM4h3Iir&X3r
qichBl09K$!NQNZAQD#&8bcp2[LTr&RkGM6qc)'9[ClE&#'EK2aIr1C1E*XYrS3L
4ISG#[qZMhr(4l`X*Cq9"!H)`Nc(CB`N"f1mTkIFVY"81qI[pQDL(hd2%eia$(DN
RYD2'e0(2-$B1MK5K&rmLrR[J[bIqHq'r0rlli,mVrN[`lmCr0eDY0$NFj2mV&[&
cUL(&iJ&qF(FFqdQj@,T#pL"-CUU0+aFf!(ZZfZp5,UE8KYVp-IEFY)rN292[IkL
(IC!!pf2cc-ClFL4HHaCE,CrQUHGK)QLdNDE0ijlbT'@)X4qEI2qNj8U%G0+bie6
Q33f0"#AE$0J0k,lP#3D2fca(0MdV2h&+hpA'%r%P$YZf2Dm9Kkh@*Tpd54bf8hY
a+ilEiR2Nk9`5Kqh9MQc&36%j-RTb-Icd5la39Cl6LJ2+p53(a%RR(IE*R+6HR1-
ATea2FfVp(1bNmjJbjeHYAKA0BQTikK59KU1Q@bY#0(GZ1&AeMNFcCGl(B%V6qCG
#(Z[@,ZASb2P`qYS$1K-VFkj0fXUmdlPEQ@XkCbYcV3bbDRLQBkdDlUhHUSbmUYB
[QqM9G"lZ,"fG9Hf9C0CA`h0,kC,K1Je(TS)0HJeeDf9L@1DDcJr,A'XcdDTiN8j
)Uda$b3!bpDcLBqTEJFHkSlC"hFrA1mZrLSe0jlL"8fG&aY6(!@2UNH*LUr)+BDP
[$496ja388mm8%e22#L6@(90BUAXhfkQ#KeRK-MJFp"eU*JA$V%%5,+`lMY8X3F+
k(d$BF'TeC`8'8mm8"922'JKQd*!!BU#AUc2mLlfUf"Il9A![GG+#TckqVZ9FUeK
AFiaE-hC8M)[Y$YpLDiTYpBSU$-9q08b,(E2KLYiVaE,BUi*MU91+"kPRV68Uf&8
Z6SCE9Ep'Bj5RP'V4%ka+RBEUNQ"8kJ-qC3lelUVJ8Zb9BP,X9F1MFKZR@*41qFd
!+A1YSP,QA)'QKQFm1V,Qk!YF,8)9U9VHF9GQhSTCQC-$VX`P4DqK(P$dbCaV1*C
jTf#@ZDD)PVPQScGVRY9"R$Ah9Qp98+jD[`cUQXl$RD@J9qf9"2NDRPY+Pf"J`a%
J(23DkYB+*'DZ+5jQVM9`V1*<!!(JqFer'1IdNc5FHe$ZTL)MpI!)eid228h*4
ABbaVbL,66"Y#JbEDF*3m8kG'QM%j5&2-Z*kQPcP*DV&$FkKXTDh5h!EK@"-Fp*3
X-kp'UV8je(@NVJG)`EVZA81)HS!-*1VZ+GlA[5Z3!0pb6U'c&F%2+flkCJ0kaq"
rf$pQ!!hrL!68rG,@VRYAZR[)HE4J[[hVM[FJ3)e(MJ3B+hH&hV5Flfl6K15dI1%
j3iiMlC!!XTfkGdTikYj9!PrhVh$iP[0)+DYbN`lYENSqhV8QqRLr3Fh#ZpB901p
BNiUmAe8XUVM9C*Q+EeQBUAJebeXAM6,2LQ`8HmE#NIHSm5h[9f9FUGYJ-4)ZjPe
D*-ml$iU"9GGQqDSk9m9YT+8bVD[LT@TAkY)SE%hamRjEAL28aUjRhZ8akid(0-I
X,YTk'RQ6IGIb5Th,DG9I(Y5cLJPc,D2BXCa0UZR@-mP)F5fGc,ZF8d1(UbG@arK
DEJdk(+IAiJIe$,2ZDik3!-mL0!E+Crl*H2R-X69X2Qh5C[*TJ%EZUAZ5HZVAbMa
Zk'E@XA-MipJeb6EfD@@DYANch5a#)qI-2dNmFfaPAdH"CJ(U34SeU)G)bP$hE99
LQ"hSdK'$ElhUZ`8dANp0K!$akL''b)3[3rf&cGha@d@S8ipkK!Eem2QR,b6'iVE
b6NR+i,S',C,L%fmSea-C$1q%81-dp4"MR-DASU@PEFfM9C!!&JZU4c()ML%cicT
mkq9&64imGX1-Defhh3BiJc1ZH3e[r4aVBXEe1UX#)[F2GAbLQ'GKKD(!U9R"'qN
rYV(M3cBC#F(3)eQ3!&JpKqFA5aa'88h19jBiM*mD'4)4*bGa'",aR&BFjJf2cRp
1iM$QDh5ZFa+(0Hj(jc8RF4LHF3hRLiQYGbSI9ZlhFD!,Nm-ia)[K'D2cXj-i,-m
h1SmlLF0+ND0cYT-iV2%r1GGCiV"qrmLmjNSGpmEekZYabJ"LRXp0MTH(L4BeXPQ
AKiRAhV*EMKfh2)`FZfCVeiVUaUcH[*lL+km2jL6(`5FbLaYld$I0jjETLBKX
`3"G8GQ2IAm'$mkcN0LbSiN%R'(BSNb0dIlSqf4R58J-)M`I#&m2,H"$[NfLR)8+
#"kaq*(K3RQ#r*X"qTJ0HDA+,dEj`*mdq2%Zdc0$"ii(SLl1dIX##U30"FTZ%N!$
JJ6cl"`rkFUjRFf#AF-6P+p-VNYD3!#("JpRJLceYeaH!A+c(2$ae@1k#VAKYJ$a
@jE,VVmHT,UAE1U[bfHk%J$a1bh3P!p6eT%,rG)EEmMKj`lD"p'"C&Afr3aRr[&r
0f452-#JG#@hTPViH'Alqik%Y,*`+9i&`HELPkXG1ZZ$[m)RbH2TY53&jh&f3!2q
6apf,R[cI21j+C$U2YE[VD[c4IETIEcKER[MU1S2f"8q$afpk+&bAH!QHj*BfPX)
H[Iei'ra[0-C2E$F1[@ePP-Fjrp1[V1AJmVLl2DUl('qTk`8BqfJ%j#',0[qSVUa
3iI-B4k,T2#DH1Y1ZlH2bZ%L9Ch"D0f4f31eGDcM0qXcYA1XV0JmHfF$kiYH+0R(
J(aIkhMA@F&mHEJAFL92G&,Te@%(B"XL$ipE8rY&CMEmblQ5FDIAB(iblXGqmRSF
BpeJHCJ$M2R(pTYFQ2PAhaQiGii1jMeEe)HBqQFIpc(dbMrZCqpBmlQ2Zl6cDc*f
Mc$dm-'pl!J"c(kl(SmapV,$EQ(XlMrZCqh!DMc$hGKi6c&hbQ#6[%A0I1rbrI@p
q-'kf#fqGKaMhD"iF)i"abh$e&F[0aT6dkZRk0Q1521j#KJFBdf3Hpc1GVARFah6
DH6b!j-0j2),Nl6`Q3%rbF%2ef`M4hLBm855fG)MNFIiJYb)F2E,iq'3HAEPVHeL
AFVP-cq[`0hVZ46`C+%mREXeMrDYF8I*BM`(djCR``ahp8RXS)D#Z-j`KjY)6R(`
kMcCb6[4Ch"mEVlEC[DFRA%CJ#mE-#GA(JGTM8*9'9DMQ+DY3Gia&kU-*N!"(ImA
h&5"'!'3d$m&kkKV-k141063"kZ(82K-J$krfMHFaVIDG%e3VkK(X6%JHQmIK[GN
i$IZLR4h'f-Qk1Q)mr26a4rBCKpp(-*(&@qI@i2pDiq(2G4PMcb'Hj[%+GY&B2DE
k6&@@GI8VrBV%iS"S5alX'KG`*EZC[RFUL`R3VdjP-3(bi%4`&RbRVLi2DBrJ4Rq
Fi0CHR9%EjR,j")$4IXbhD912B'lba-Z(rVjlVfK6dI%p0RiFKc%"mPLj`aY+irp
%A@'PGX@EaI(6j%+e8qC#6r9(Q3XpeDpf`&Xaai9Qm!-%2X1T[rB#CkUZpS4bc9&
1p@4GA4i6@d"1jG&qiK@m)rRYMGIiQ@BkYY)EVjPM,,haZU"qPCffkfS4[2+@Yf)
ca`"j+cB-))qm&4Y&DL[JV9KPT(RV&*-RQ,Y4`8a0!15d&C!!DZUd"q8B)*U1i6)
TCr`B"&U-$63TCqBB5j0bTV@BS84-JSNlGafGZ(2AXEFQlV5Ir`GY54A[rqpRF2E
'()%(Q0G`(SmbVl'#E'0Hl6c-LIN)dmaV+"&EB-j#P-IDUhe'%QYp)39EiYJ!M-$
PB8V-IC!!`cBp,&V%[A6XMS8RP4Vjl+8JI[Ph8ql)6&m6$J@f4d&f#l(MhUABF#J
`YCTUqIe5+AUrC-Qp9qP-R(Z[8NL@HpmSI,(RrqS,ljHXZIFUjYal0Q%**rAe$63
M&$EfEjQF(aA1i[EmI[rMcZlHl!EZA+lhhH@qP(I*CD(BpfKNN!"VblQ"klN9ENA
K@#K1'Y!RY,!4-$m(`lCL'8-FjNU3!'kj,q)G18c[Xb5C1A*hmH5qJrM2iehHA#b
4q#k1f(F9ZiXRFBTbprRZe5K+arH`$f4derQMAM'XLLZK42&C&"[4LV-CV9cZJQ6
QbqdU)4AB65VP+LKq[Ec,E+`PM9bkjc%ATZ@Z+eU"JbQYr@k*BjYG!56BcR*Ir00
(eEPcjbEriF,hjj[feYq1HlmfH"+Hd-dA5r-,6V9HX8fLd6+r[,4H,bjTaR-Sj@C
$pa`(L(m(,L**RIji%N+KMX"4@`k$lm!d%`EA&V4RqVSfY*[YACd$RELZlXd-Y#H
V0!$6Irlaj2"DMhQ&&X#*DY%6j49j#,Lk@BKZSTRmCGeipdD`#hrbRSArl-5&[JP
*4,8Q`3rKIa)0cLTR$Ij1,I!1Tq"r$6PYTm&YkQA%TIa2EdDi&RqhK)diY&U5UJp
FhdM%JMRXal+bmrC1rZFf9(khFFkD"IhQ%U2Mk)0'ap#k,AeQIdpCh@S@H$ZUIIj
DC@`q!ChQFfhc0kPKFdYI!j1#P0Pc9#bhTpBqp!aTRc2,2Ic5!pZEp[KIXlIp*[b
E0Ch-Z@Q[R2%kY'XeNN[EVjEAJhNmA,r(mKZTre5mCYiMF4lZQ`GlGL`2-fhAdj2
#r8$G+I9mM0I@$PRIHb'dKIFI1Xbl`E6"`[jleM8h"mc4AYRee29[Y1[TJ$pL`Mr
UeqqHSLjLJZekfX$TeUkR9CbfcAFp04'BZ`fd"p3iFrHkX4h!h'fTA8pRqRklPQ(
AdaXA2399D95&DTkb#[Af`j(kD!,NdGMeY*&(DkI0ULVQ9%-6S"j1l6-"mSKh2Gf
5al6DjrDE2(iXh[8dpjE80YKPep2Fh$['eI1T93I1Cap2QDI1)U6XHMV[br$r4'V
9h[fTZIGd4(Qir5E(kM(9CieG6aYjY(BpVHE4f2AdKr9`+SX*d+p1C6%"mZ"NZjl
qX+iZMh6AdarQXCeSXqZT-6H*-ji6p,@hKj1'$DT*R%X`ZP[R1SR[lHcAh,+pC[,
D*-iD6P[`NcLIC1i@dL41@EXKBZlK&dph*!!`GdYV%ZGNhfrA-NcLr*2II"CXpHm
R$TC9U0f24ZUM#C!!aq161'ZUQ&-06B"k1,A2"-M$UhhMH8bVI9XRF4lkrGqFa(R
SiXZ61-IU-G9RMdrLV1Aaq#61@Kj1C6%"qY@T,#C!(Tc(*R(@kZVbq(q61'YjE#I
D61*NRpKmZ&eXJFXYZaf`RbLb'ACdChLfHT1G`&pZefc2+5Df!B2Ip9QZE%dXH(#
HPGb'"98mk-3Njh#0IU#bCV41VYRABeXPfm-fqIBD(JKI$#rM3EbXZjf'#!NHj#l
MJ9LY0BU3!1""AZ0"HC2V0B&9+ePHDA)GrVjF)@YQeLLRPQ3'$XRZq,1eRR3fa[-
0"-PYNP+#"pdD$rTbVQGhBf#M8-6P+p-VNYD3!#("JcRFrRjbTT&jHQ4-pI8&TeU
[f!2&")$a$$E(-H2HT!NIK"S@8hV6C%'&b1"2q+NS6JlAVPDF2+kP9Ta1A(H2iZ3
B0MjA0Z,`MR,(1%kD6pL))k`f@"M&b9r)Tj*h$kk(6FH*Nj-iXh$YDm@CLqX4V6J
mGIla9T`GF6dqlKrDVY@hmh%Y[0*R5Cb&Z,iTMT2e44*R%DjAAip6EVci[C+9(fH
)RYKeTaYrTLM!kE[`"ch3#cJ3BXJT@hHJ$F$RiHUf`N'Yf'@b*Lr!rb3DI)A@i(p
bdq%8r+m4"`H%Tq&rHM2#YIKI0aP"NPXL43iqJ2pCSD-L+,0ph,aL(jUj&e%%H`0
P4@8`0ZTP&adE$J9-f$G*rGdjJ*rTmLc*M(Z6C0KTaADFAXLajE9MMLA($Cq'rhR
km943#eq4"FS0Aj)&UKkq(J[86RNpGD'JaN@BQX6C+(kAb[e9i[r6FYmNHEaDm[T
R%ZFbbHYbZEp'iPdKm9iVpMI+r8VaHehiZLe3(`jIXePlEb3YML2i&KV'6B")Z8j
'Bek#RU%C#"b"Aj!!G2(d()4i2S6%i8hTV#K1iHAj%"*R9eb2RSi6*bGaH+*j6#[
1EVJH'm8TASKcC5-1Q`f9jea8kjM%f4hAbIN3%QF2A%IRF#4apX4eG2j(%QF[A%I
RIb4apXCeFLk&a0N(emQj&"*R'DlE-`Kc+Db$l'`i4@IlFJ%$V*bc8%4M5`iaQEA
em*ZZUq6q8h,I,2IA4fqqSUPK'm1h9i%D&Ep,j(kTj1[IJ$hkpS[TC1@hAk0[[Zb
"0c&bSYGX%B*@jU94-DT#*DJLPH"GM*qK0LGK!a@SQQm&+Nf&UI4)PHf&+A&4GaX
BEA3%MYYf$J$Uk-TZh&BFF8TjcpfaY4"ZFh8'LXJVR*(6J@iEpcm6R6MUEhUpi(*
aiMF3%r6&lRqCG8qF"kI&@J`RTfDhA9mhFR&belD4CdIl@Uq-ee`V(3PYc@dM`rX
q(YV#`UP`h+r"Y'hNlBp#Mk9IEcKER[MU1S2f"8p$9pVd8"KS#IK'D@1iHhFiIV`
0rMFDibHf'iIHYM,+`dlD0R*L!UcN-ENST'i*HFi-6ZZ@N!!1U,eV$DIYV5dKPA'
2$41f2aLh!E5cYE(!h'fJRDh[CqlKJARE%`#BZrfcXl8YX'[e60mE),Y@RrYbM%G
fV4l1Jf-%-1lfBUjG549lZCS6ql6D%hZRQJ$lSMU%-5Af-qh+I@[VkqL8FVP-cq[
`0hVZ4EaqhBPEmeMr+PH820CE[QpQX2LEV(P@+flFd5qeKa)#kMV$'@)Z2F(*Tr0
S)qG%RmApXI(D8XRhR*j0eLjV"Q2QK1VM31daU%UM+P6cP&@S1mBLpG%%b+1ri[X
+%#-!-TU(B$ee$@CdFUFDQJ$eF'UI#C!!KeIla[1B9[[1#DS9p8KHjl&j(0kEMG1
`,pVCBBbGV+[h'!qhVhjNRh(iI356RE!De!Ei[pCiq0e2'Q22)ClQm3Tfd9JpT[T
-9CCep5[pLXVLJ'K,(QIdjNf9hR-eMkPk1*A&"1KATl+B!(P`)MJ,[P0APiHd4h#
M2dj`Dp-Vk2Z!Uh,j")#04pJZYddpJVR*%bmIq[[Z[D*04FIhf2Ka(-B%b'2P$Qm
SMIm6GB@9'LFEdMXZp&4rP,R38reU"bM1MJ[0i!F)I)C6Iqd&cP4Gl3RPQU1FkXQ
kZMcJ9$2p-EN[cLl*EfqmaXmddl'9hRM0('2TMGId4[*$L4J&Em9QMJ(b9Q`B3"j
j+cD+e&E!@l')ZDqb[H&T8E5B2-(FM3TQDJ)JTkf!9&1R25M(!0&d$*G*1H2()0"
LE+"*162(@*U8-kh&$#9L%@JaGmI3L6Yh(AYViNllqAr3PP6ar[pq"QG[c"&iJ(N
0jr%SmaSVb$EQeFl$R*L2--fmKK+a"HBX4(QX[GTR*,(@&e+`*Bi0`!KF(UE%h!F
h)c5[Ti1l2FM0Z(d$Q5l,Zdf("hh$GXhfR'*L'c$i2HRPfU(ai$`VZ3d,URM3L8R
1i4Vp3'A0D*eFXkr(YNUfjbHT!B6(!q',XSYk(3p%cVM3mK`l33d4%Mc)D6aB'hM
ZAEBhiTZ&`+U9,+m%34a8f,3Q9mLDQ6A+U5@CSB2(!lFr[Y-2cXBiYS%JZ8e#52#
J5q0"Amlel'i-k"11Z(aPHNA5'M)NH-#10Va&F&Zha!&3(@8h[SpX2[$%N!1q&a2
@`#%lml'kKYpL`q2#-ipY2[M*LBRRhTVSKJX,XFj)$4H11eCimN0+$5p2G-1&AT!
!b2*U3K%Z(!JHqDQ*L9qm*G%0&ik5$CXUZ0"2A!M8b)&%0ec3Xjd'-iR6jYf&fiV
$c1eR$HB8(ERcU`#S'#dD2,9R1X,N`3q$SLPX3%`,MCX`"9UZNp&i*Ua()SlRC&I
JJLR6pdQ[EJm`i'41c@kl2XaYFA,A,,HcSlf86bT&!8Sp(q1eYGIdpei)EH(pK`l
cEM$0FYYrclVQ0[Xjf[dfqhkSPfbcchA!(c(K(rAVGdq&1i)B5l2F,)%CE1I-i,6
1B(0!l9eV1'e[c@"6aMdf%YrqB0`'d%4mBi'jfd!6mFHCZeFGl3$QE[p-a*pJlT,
(*(Q2*pR2p,d"-XPqH$Il4bECEpRahJKJh1faTee*&902cBPTTIE%9%m6B"UR3aK
6B[TP9qjE-r@M8mVP-Mf[`prSZ4IaqR8REXeMrDYF8I*J)jAH$"CHNrA'DX@01rU
PpP"#3&eR1%2-T5FiqA3HEH5Fk,1i2cCH'pPpcqRKaLlM'$-R9"p[A2389+94&DT
jbLV8f`p(kU-*N!"(I`@lc%3VcBcQi6H4'GI*R@TS!Y6$UAdQ3"jHl4[2BeVY1bH
S9P4f61HaH4a2ZiUTEE![fYQ4QR[(Z(SqYHV!qHcM+I28@B6F#GMd,IKr)V9Ulrl
8h(XkSMcFTMpMpCMU-e9CeY@[p#X5L`1L,AQi6ApB3@HQljh+BJ,dUe0C6)!m1,U
Kcj0eGAP)H`3hqZ-%YcDpi)F2Z#UA[kDDE6hXA05Q(X(Fj)QA$reppel4TU)cY3@
4ic!Q3"iVGhK$DIbIU#ZXe$MC2m0aSDIkBcX-CZZTi#2p5Ve69IeJLTed3`QF4Eq
U)VJ)pJlkEEMS&h,2jfA`@hI4la68fZ8KqHAr-[CEM$b+qh4q&EpPriJhj2K*IK@
riJ)@j3)2NaTb*aFbBFfE&`klDlpEb*pe0'ci%lJXd(llEB&0pe!1Mq2b&ZehpDr
$TRZ1jilLXP,l(IU[X1Nqdjh[aH8`lAFQ9F5#j(%',V1ehp`"&LMb+l%RRkRphNK
TS#4qEircZq(hB1[5ILX4Vd2mV[S$ePMllr5iIM[2Jke(kV55c42jhISjf'CT[j[
q&!cP1Zhh9ZE-,ZH84HSA[NAl[HJ$F*JMpI[&1,p6PX'QqcMRq*CEqqaM6m#Q8hG
cAf2Xb1rQRi9Y"qfhp'q3!%Y"qrh@6m&"p`$2X`E2eAj(Xhlca3m&3r2i$1B&"25
9XpHANFGAY0q(I`-1#b8H[D9eqK$c@b4qF"kYdk*2`2Bdk9IUpbRYeh-2E$*cJ,2
RlFK[*qhhDjq(`ml5Ppr!j9pV[fr[C'pTIZ$KFZdArJ9XZfLrTi-Lj1CS[bA!6J&
2G`j(23VLppI%P&fehkH"IbXqU[efr6!FPNMHp%&[0I#*VmPmi22Z4-q@UN'Sa#G
qPl'IRPd0+Zj&[`+9pRQ)"qiQITd0[2cQ5YKfNlVbpPlamZ#PV)(krAEFCpGqNBd
GqAAXMI(bmdmaGZ6Ap8+-CaZq$KZB$(k$[iUA#jjKifNp`"h&bpX1XH'eIJPHA[X
JE(Z,Ai+AYcm'fclDl`ASCiqAGj)U,T0ip,(@leA%URh&$hr&birq)@`rT[eqN!#
1mI)pl$9P[[XK*iqAPj,[JIrdaqr(q9ebN!#"0$m`32[XQ(mKCLMZ`Km8jllc!'a
J,1k[Mr(bji"j-SXKkUHVBlcm!,(j!-'*&A%HAb"HkMlPq`-,29i'a$2Ld*ldTGE
Tmm3QHTrfK,Gi2!!,$KBrm&hamRd&f*3T([)c-9jqmlIJF+Mf1i"m5r(bR6r!API
mKJmUAYl%@)GV[b-DH2RY2MMdDEm"i+,(b`eIJF1c0#hCIh1-Pk`E(kb9rK"q%q0
P-[llrF$,`MV"bm4[$h,(J`3[%lpZjZ2a-[(,N3YUIccMcf'MYY6eR6&HIT6ir9c
*Mjl62M[cPeMSb1pJmMI&blF5MhRq$Na4Gm@Ycpi2fj(Dlm$IMI&bkBr$TLpR#ZG
M[0am"$E91I,RBVam$fZS,eXkb#Xd[cri-GL1dAiAIc,'bhp#r&B&ZB2m5H[hbmc
Y1+R696&HlXLk4P1I`VR)fq2PRH4NcpIaMQcJj5CL$2`8Z2j%R&mr-8RIcqe*60)
qZi5iSLqAPM&AaENhN!#,Vp*qa`$[29kqreIJ)2MJqSDF&#p[)aF(@r#$afSHej%
hU1ab,2V$iq@ja0SA5,cVicTYHK3fm*ak-%P2kl54f!!fdTk#hai[IjGmQPkJID4
I29iH6Rk$jJ"XdVZ+P`2-5AJSCmAZ'#ph!GB'@lAI#EmGiq9Yj!(S!(*qjCGM[2`
i1I-,G9qqj!XaAMll'$cS"HU(cZ(aXVb$Hl!I2#mF%la-r*D42`NZ1Va-r!lmZ3C
H*RiKHCAfaaH*"@G+AHN9aFXjj*S[%VrILI[X,H4),pCqcbIr8,cF5&f%RJ+kiCN
HYq#AJ[1Z([5ciZ@lIK)f(F0`)$QCiZ9eId@#SEL1@UYiZ4[a3,@hJiK2QYrPj,Z
UlEf'qTEkl8-G8fIE(%*Xe[TpR4LRcc4AN!"V+PiH4Qi3c8J*ld1H1al@IRp-(U`
[F9m1RZ6amLqSSDKfHp#[aIQpMEQUMVB-rHhll,)AB920E`9c8TbljCpJdhNajk"
Q(LrIJC'3!)(SG`H6abKHRNNY4YqD(%4rcH-Mj,5UkkhlB)bARr`-(-!&mL!RVG-
eR2@MD[M"j#9DTehB`fJTP!8F9,am*R09RA%pp"H2PpF4*e5MhFMk+PjH6%e(*GP
$b"-8,cr*2P#0H4-iYmI,2iF@&Hc5rIF"F$Z2PdZ)SjGU[cp&[6aHRNi0$K`'8Y!
EIP,`8M9"iYd!hD*3&V`Xq`@h8UGiTZ"PiVILq3CHP[ebbcq+pVLX'Ja2kCerMCV
PhPZYqiLAq)8,J!%jPFrk!AJ`Z,**q#JBTMTV*Br,b!0[3Yld888hJNHq5r`5[RX
3GCePiPI'pA!*HqLpiPHT+c``kUGLMPa@RchY3aiFp@ATAFr#*VM"kD4HeU(MICG
k!rR5YZL$,p&qGj+V`&A*$akPq9e",JX'JZ[`J#LriKqcaPF)2`DASra+lk$fK"B
Njh@IL[0l0c840%$bJbGSIZF5RekRr9C5$p$m[NU0"ij2)`J2mrAlG@)k[*KbbBl
k2VrE@"[G9hm&m5(+Vh3cFpXXZ)+IpXHHl#IiSj`LG8E0lfpr(cEi#qR69jVIpmJ
2d,'P(0qQ6Z6a5E9Tr0$NB[dMmIXB03EIpf@rB"AeBSp2LGrP2ir,-`62+[(3!50
qNlH)jB*M)-P5m"l9!r)IBChJBT,haqq,F$HrP"`9VLha,[Ql'(IIc"c4FZ@m'hc
Emk%[N!$E`ChK%q"@a$2b(G6XVT9q+ZYYqIh%[q[%$jkT21C,e0Tq4[Zp"c932T3
I*2H'DmYC6IiAmD(mGQV%D0VNNHMF2b#RdIPUl`Ar9$k8(bDhK"H$SqM4@Zm,b)Q
PrTaqiT(bP3q6irf#lSqR!`18AqB2rLdmk$Xj*HSq%4lN2N1Yp'f#"r#m#!rbEci
0'ca&cY(ND4%2c[F39piKHAmiiX(jGrm*E2!qiX(,PEGG6db%%mNjR,UbmVEIT"D
&$L2RIG6[)Yk@Vr*YJqJ2R)mJ2mrE[[DVa*LSVRXc2q9YId2m3+Z"CU*M4Rf3!%m
6im%PLEF2G"cPEIQ$%fa8j3I`[8Jrb+mPeX#,k9IHC'MpEU5fLfi$Ai&$42T"rSH
Tf9%(i"V1T$cqC[*M0&MkL9iIU2T6HRRi(Z+)pdYi8MqafIXPI1Mjl$2[9m(,5&q
m+#![6RM9[f&r[e2LPIf#&m%MFpm9eLNi36d-(9lLr5&iDAkjpMZ&IF"E$1U"MKE
KFA#!I3-INALc`3Yp(VFbedpVh$d&[-ARm5PUBh"jqKiHTRPmQAP6CmPM6r*1c@-
c-3,G4Pc13(iqMcG3hq@Y#M30(UajR%9Zm9QGamfSQFrM3m4dY(Ga13Zil[2B3)l
i1HPAF%(cq$VI@pbQmrJd--RRm4[%3M4-F9N,(GcRmD[X5l#1pNFVdMaH4Xa#-`G
A`19j9EbU,rFHqGe'cRTVeCUDI*!!+i0IKPShfZ&(U0h`eJDq"6ml@IYpMMSPZV6
iIB[aIeElh8b0kIGd(Z[!(m)flIG#iMGm@IaH!9ccqEfD124&RFFhf#ZDha(8*q#
N%ZpFaYAm[N,0JPc%EcfiKFr[92B5HT(iRBFB2Vp6U@ep@IYYi"X,cHm1kLMS1IM
aGN(cfiPpr&AYGcj`dHFhRlb%(K5r#i$l2Vm$L8eIdhk[C,pTIPrkHpMS,r'lN!$
[3+,mjRf&Edlq52a%Tr6jR8"1b*a3mEX)Z12cqb9LiYHehdEb3Xh[F'SKD2ALGc(
e)DhI#QV-D(Vi56kDhlar)#G%ja5A6`*[FTT[GIrSlm$MQlVaZjP(a%Zk2dYYJMF
Di#jkRrG$[`5Mm%2R8Vr0a)C)N`P[!FjUIMecU('L5B+l[#H*i[9m,h8)p#,mH%I
KrAMrG+IiSAPSIKmNld'INI`q#Th,eqr9j+0`56NVU"0S[&F6#q#`q-&,e1p[L!9
r*[@l*IEE`(F!`Y2*laE`C*rIPkLTd-[3+0i*D,bcb+(4iI&$(eHrlp2R,lAI6H3
EkRF-X9,Hpj(ICi$M2Vr[%`Yi!b*q1j!!2fJI,+(1$AI$$ac82(k#IIaAiNIrUpr
(U-@!$m(r!`!!*)d!!!%!N!0AHJ!!9RS!!!*kEf`l$3N*CR-ZF'&b583J25!UC'P
b1`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"QFbjf8Q9Q6R9Y1`d*#5T
NDA)J25"QFbj`BA**4$X0#3P1B@eP3fp`H5KQFbjZB@eP,'jKE@8T1`d*#3d*#5T
hBA0'EfaNCA*"E'PKFb!p)'Pc4QpXC'9b1`d*#3d*#A*PG(9bEL"bCA0eE(3l$3P
p$3N0#5Th!!!#L%&%3e)$!!-S$9d,iCE!0Qd2b6Z[IH9Ehp5Ue9CEkEAkC*9FPqJ
9+UeD(CpNDpA*@5)i3-Q)R'5k55HY1-"hcYF,r!1f#E,M5[UMC@C+a!jlH+aC@B3
V[%icXLX@fR,DNr0`SMITBMNC8cDC6Z*'D,'pk"KZJpfp@@YN0fce%Me#6X-#1je
1j30JAcZ3!!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*IreFIPcliY(@PE[`Sl'hl8'r
q(IEcAE4D$X)KIUZ@bRMmhLE5"2iFIVC40*TrJM&HU6r)*&aMlDNGr`LGr#[p@MV
J5&qYUk3cVV@a0)lA34GE5X[i1hM(rpDrj$emhrr6A[)FrQmId,[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@eLC8PNBMkcLAbb9
6p2B`aCDaP&9&U@-[5hXk6QI5UA49HN(DD[*0fCDk4QmZA"bhC9*QKDeY8Bq9e54
!3"2#XdXQSE`ZSEJ`S5P3&#J)Y)Ab`R#S$SIkd&B5D'e1lV3f*HZ5PSJk56D-!bP
*#TP!2[bb3,EL8QK,"6+"jSS2"5`IY[4X3MD3!)N6iRa#69)'!*!$,d&%3e)$!!"
@$8X$RHJ'ApX&YA!,!-!YrkSA!!$3@iYDH!'Kj[m$@)8HabqAC[SF!*!'*lp"4%0
5!`!rmJp9$AC'!4!aiqGMIjYcMV()-TE9'U0IM"@MlZFhK%X0M$Q(cV&kM"'6f&`
D[K#b%A#b!`R2br85Na)aK#$0iD9FNLE'pSA*#4a,Z66Aaq24A%Sje-FeP%XTKkD
%BiLe3#RJ!((Ipr[[lr[QCJkplE[hrI`('k5R+%%3*%%52*%"I!+Dpk1@k$81XCK
2KMmBkh)ImdEZFT0$AjL%ESQ#Q[A"f+5lUd1X8%03`%TJXZ0G8#P3K%U%iPa9heD
KjeeZFCT8f%RNL[a%6Xl(Kq@H#NEkblD+H`kJd#!9&R6m19E#N!"@#`8L1LLBQkT
*bA,EbTI8INfUkU#1afYrX(Z[U%d8m(MZKZ%5'MEBDhm3C0iJK)p5BU8akQ"S@![
63Pml6kiTHVpAihr2j32Lf+fkG@ZlZ2qbbrfRcfYiFSC,bG5Y8d[GbakZ`C*!PqQ
bISC,9cUh[kq,Qp3XJ@&0&dqqhqhq(hIamEjq6RGIeV6GIBqpj1,qPhCcdd[G20R
ajrS$`9R3X$UYkqliY"IALYEQ6KjA1h*[iHHed5N0*R[[V!iNhcQ&U81EjPqfE9T
dZ9HB2YR2ihfK63fRECZq21eb,hd!JqT8iV&%8@1[1[8Q"(UmB&C#-Z4L!dNfeDU
T$R9UF**EDh0$am8D%VjcI3Bl(HC)AEh(&bT[R-U`MaT@JphSYKeETNk06r)iPN6
GqD*Sf))1(1bLli`H9iDUf$lE2P[YrafP#h@UQh(Y)eAQU!L"dYE4-rA'5f-6,@j
F-Qe%FM+L3VJ20NjCD2[LY!M#e4HMHX0pp*'1e"CVaQ'`l%aNBCU5(l-J1fM"hCp
L`8$3JXIql3+aM&$4Hci))BmbK)3b8IXe[G)kX8DXmGE#9&M+5leI#B-maQ2H"K3
Xh1,p5L*fe2eSD8VFMHJJ,'U-N9kHY$IM&A@14GXKc1b`Hlka#dE#'"h5B*,%,2(
+4)Bb"DC5Ha+[)UFl$+3fh58MPq2TKVX`,*Ffh(9Z5fmH6'*kV36NJGU[XHe(eBR
)*"IjkhBV*CH*BS&Sc6Z#@4$*j$*aR`5JE-J6C6Ipj21m0$XJhJ(&3pi1JdT0KrX
Q%UFk2KPJ`VB,"cZ,'"TZmZ(lPR9cGr$a4m0KCXk*TNYKFSpYHhhhRQ0,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'NMcebMIHiTM)8,Si3q[-
$J5YPmE@i8MYGLDH6Jc$mLKi'SNEij!B')[YiVD9UbRj-DG01[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$J
5[Le6M#a%jGIcYS$XYr,iXcbdKC(G3Q$fUGmKST5B)N(k2K)L(V39,*!!!15+8"J
+5V)4'G%bL'$'UYdM6b%m8d5NaGX18lL%KTpj[R"peE$L++dDlUXDpMRmUH(c!4,
V(899``%5BijNeA#!4"5Ek8#QP,C5hSp-d"F@e2PQ3jiX'qD,qILjGK$!Liqdl4A
h)l"e`f'%dRF5Ri@14)kbKYZ6L9))T%24-2H,C441`DF(`TLd-03V[S2N*jXYf4T
BBMN+BHf'I'!b,*l%0$(mH0L56,$k(DU3!0%X,G3*FKi3'3YeLhfXH`X4!ZReSrj
d*&f+T!hCc,b%e"8,AcdFFXZ($0qUr8TU),,5NA%NbL0eeYPpif-VZ+Af+erhKBa
,h(,6B%rV$#2G(GkR$akADkj4Q'm00Aid1*MPE@CS`#dU)B%MfRKL9"rjGpSdTkG
cXpSrh,rlMcbZ3rM#[Icq1h-I8)cYQeAAX)Z'ep,`RqlrHXB$1-bMIrd04*+P40V
9dqmDI19Qe$XqG&b0fa&98hY#%r*H3eMH!pBbA*JI[-RpFS8b1T3Rm[kM!mQ%Y5&
2VR!f2iY`XlcRi"PZN[FVaKk`$i"Gl8q%j6)NSrj,XhdJBqqNL3M-`E#mAjV)3ar
TX,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`M
Cd*!!NY(FBc"5`c`)0GZbPa)STi*0K@%EQaHR`18J"F$U,1qYj3MD%YV'R(d4&`*
2fha'CjJYeSN)I&NDf2,@l5jAeR+@H"9KLbGad1mj6#'p21qJ5clY"[$8i&X!3R0
,fekj"JKd!S9(@(+I*hpLKb#T0"ZfJ$8A@EI)qi2-FF0mq33Y*mEFMk('RY#0'lB
!kHb'e835a#CUrkSC*p5Vr@S`UrBd8kSQ*MV!R-X#[jbIa-Frq)kM35QQJ1l3fGX
FE'MQRilk2V6I&$iL03Xrc,ZJ@LN`j25icj!!bJ0NAS6NcUSZiRiS'4Ui"85MIXk
G-2A'r(-JVXF`e(Kp50pIaZ11q*`5CGjfZVBkYU,V0#P2&!lf&6Rp!2AbB,,f0!A
S@`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&6MR6
hT(@f5lHIS!j#*pT%m9"#YpRSp@#k'`"YP%hHb5l9I4$0QTK!Pj'3!)4e&50"baH
c$IHaaF@%Q!k6pbNb,80KjjCZTXUr4U!m9rM-HIU%`m8%a')N&46J&&Y5)!QUD!K
r`R!bj[@`j8m4HI`$&F@j#9e@dZY*63k`XL&FhA#3!),AR"2qFB$`q6m4N!#C3B$
-C@3`P0`D!%)!d(RqL8)"%!+`DYKfr[QdV["5(SNX-6VXK#kq)m8!FQMk)-lNPeE
394+kTlmPG@)5NcmeVI!aPF%%RjBQRj9"M)H%$fRc#p0C%)$c,BQfLL-m0j6l[0Y
@2HE0mmVN$##+kRMZYPTVED+f"HVPIr&1j+l*A@1`-j%'dir8*9YIc"0r8Gj)+1%
mVkSBVKLTbh)JJdD"L"EaGdi@,RGBAY5A[dX(k-blG8jLmffAEGC)AH[bK'iVhk!
[hi@I-P+(b[FDE18l0a6`52QqNESM2Q6hJS!5YF'QM4fZJ!UQ(LkMB6M$',[e'r6
DT-'QM6#Q,'a@5$X'pBf!G!cU*TYVIiGX3pY4+!hjDhm(YjeEdQHdpRFrq&Yh&TC
j62U5%V[TQL9!''Lm#kTIc'(XdQZ0KXAP0EiXTj@TD3R@$&Z"2&Tlj-dDEM%C(5D
i5m#4JlF,kKUIj*b5#--@8ZSTF8MVB&Q!FKTe)V'49$Va"T*mZ&)B`Z,AKY$KbLk
%BEE'S'lD$PH3!-*jZ%bViVU4&p(%D6I$D(!%kZBK8MVAjIVd!aP1AUT9EFHmEpU
d8AkGLQd9@jB3f$L@9SH(3'G+TQN38kmVp1QRD0%l)h9KE'fXPCC%ER,,PKCR+j3
i*hjZN[VVYXN3K*i+Al-J'B9"q4TR`rPEBaLZMj!!NPmjNI'm!9F*D5ZK*$r8Z!c
Cl,F1IfiBcE%IcN@f6@iFma`NKG8qr85'diUK%@QSJSEXrQpL-5ArCkGke%'Gb8)
L0E'3!"Jp2%mJ$M-E('YH(Mr4YJ#,#Z11F4L9jlbS"cKj0)ff%Nh"`SQ-)%+F#1h
HFeJ@&"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*fHH
X'f4UAR-FJr0pa8Kd6bqmH'ZYkMrj"`5YLN$-N!$Q`P%QFe,('K!fr9Mmkli!S*D
hI,h1YqLkkG$K)i1K`h$kDVh'",@i8fhDmFZEK+ba3e)hYic4J3P#P#1CSa#`X6N
#@PT-,(X$aCXI6d2TH0S4AVcaHZh`50hQkHN3LNqKDcU&BA!NR$IkN!"KS#)XmIA
DNiD3!&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$XG8
BcB)"*KTTKhKAk&cMbcUe$80qChXNbE2XSc$**,P&BMMMp2MDZH98$-0qER(5F"B
+ULpNVT%QK!PhMqj#"LAEKbYIe*YV*$2,Rf2,#!"I[ZR1UH'%MTrm[Q[BMF+(Ued
rAf+2NBNk-ClHQRYb%!DpN9I95p6JFFZ`@dQ@VYX-MdKma[ETcqS0!amY%@ZfVB!
4-0mdrj8#8BBE&4PiYYS02TMPmP3-LYc%TNUm3SkPq0JmI'B)(bCZ8PS0cl!P*M$
(l&%-qc'F4+%84T0RZ$r5adf@G&imeQG*pqMAkAN@)pBFlH2qcF2fj$SL'ShN$iU
Q1eH&ckfa2Y-Bh%6rfcBGpcHSprd($2&YVl6aZ+r2p2Y6pGBqbdEFB8F%aM"R()$
2AAF64rId+rQQ''rfjCGUEGfBZKR,G3El4eLZI[TQIRb!ecZL1BTck-fEI$hhj'3
j-eqibGrLL4F+qRY@IBHh1LcS6VjbNhYB+15+ZQViq)9205[+,Skm5eZY-QI$eDi
d1ARah-AIGrhXchB)+ccb`@*bpKc19NCKBPq6d*9p0)cKHDIY5GpTZeA4lUlQkUm
DBI`RYK)$JZNm0[+NHK`CT"(X2FVHfdqF1irf5E%ppra0&'kGrkrREk13!1diG`N
44Ik*dr'ULX*lrh4,T8,&UDZh8,"N2[Gbi5N8$$BE-9KZRA[14SAX3T5S`+8r)-i
M`pKLKcrb$(m9,X$@b$0)mD*1IipH5FEk)Mqr8)+-S+!4Ka-LL[HL!@"EKJmI0Y&
[5G[lT%eEVhjk&1EjBeX5h`Ul)rVaHVXRSKqXYmI`kS2j86rH"mGD##HB0Zi!1MK
+#@e"LJXERGHDd0&4$V'Mr*I5e5kKX9L3!1e-BJPANM3!Gd3ZcaD3!)&lKYh@HMZ
ACmhM6Zh[rd10SR-H3qCNPVmSZK@K))BHRLES%5AdL%hb,,"I&&$4jU'V4Ai@`Bc
f#&kP0[pC[3#JV!3$jXd!B(f@k)*XHjbF&VR(Qk'1JfhY6`i")FY&KLq43h'XhUf
2rG#(%)bp'DqNhImMR4,,e5N4iI0Y(3*%ZMM!'3GDU-I*r@@N%FV*E+!Y%!D1SA!
YiR&#Q+N-eV9-rI3&U0EFbKJmZ4q$SARN5D"V"S%63qM*kFrj@$'pr6%5am#3!"&
$aU#KT#-V4e(mMUbhP5D-F6$'Q`a&-"5K)8T++*3%%A%[%2M6N8BFaMJ3)fQkidc
Q2KJ'%cPjKe2-%l82i5$m`pP)LU,K$b9Re%qCZ[!8#@beZFJ@%F2VkVKp''lT%iP
k"$5MGXmmr98%CFqffC1aqRHA+GTBV%HI'djP'aa$5cS,!NC-I2c"$&,((C`F5N8
MM1iJ#!&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')`qM8P1KE!P'SJ'qVIa(q3G`
64,ajT2%"ZV4VeBMV8q(D%[Pp),HI!GVN)-f2-k)a!,U,$T318MV3#SRiNL$LS(e
IGaAa#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)0
mh&qlp1"a!U,f(c6M$K-F%Jii2G)LFQB2XdRQpBdVXF!``1VT!eK1NmErjYrL%-R
&AGc)A"CR"Y$aT,$Yr@GGUcVkHcXHl1I-p0qRdd9QU%Rh-JTZ9Jp2ZNR*RMMra-Z
N[0EQKXG(1kj`YAGS)YqL&2VmpQM-kLkTd#[q@+Dlj2D1jGcR[fpTYppA#TAL$Gf
S#V(M-[Im5@"4`T&5[Q2lE$-#E&((TXC5'S!,RU[`6PG(GGqUACBf&(453EpU&ip
"K0aFh8fL9+PBlF+`6qSHN3Sp%Y[6eIF5ffDaHJ$$&k4Z45VFNYLDUfm5fcUaqJb
'mk6ZFe,KGY@89k3T#c"F)R9IP!VCM1@'a(+(QC!!"&0p&SbVj1`GSDDjjh8Nekr
$058kV,I#FELRPlS`''[S,Cb"KMiD&*UaEE`MK)XqcJi%(5L,D')8K(0DQG)-pCR
I%04RT4iG1j`80SY')Clb)JTP34aI,T!!K8%BM0lcETYjP[IlJb%%Q'SDEHBjU*!
!mHqDN!"jfRXfmdbB'M#apmE+ii@Gp'(Hllhah['JiH6Cd-BlbPjdPG%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#qa3#"-+qkCUB4#-#kS
BIp5%dF3BC`Q$!$P*Nd2GjX,N[XAQKCF+ZQcQcmUAi,@m[!A(Y!6(Y$5b'+%2MZj
%SKI%mbeBBUk$S28@%pd-l9`DA#J-3Ya"SCdVQE4!BJBEXD3k%k(bkBdZ'%YQNqX
!1F`-3!cJbl"a$"bfb4r$K,)%2p-hf-b9j5eil4-@H,m2BLYC85XJ#aaJSZrLmR5
T(Kb@-)b!B"4J93@5Q""`6qf+VZ2QP8$L([0RH'de,m9,-5rI8'!aQCIJ)f5HMYH
RjKDm$TTRSi1E'r'K0mpL(62a'M(2B4h69*YjTF28H(*5MbS6bC1&h,4"Epkh$8,
)*e-EfXb9kb'XRi"c`!Qpql2(),*[-*42aq"m$#ikdFB'NdN$0k*M550G&SFb#eI
Ed&EH`P"PQ)4AZLc3BbrE5*i+lLrUlcUqmEUL"V%FDFT5ZijBK%-e!*N01"cm,$!
X0YIKCq&JU(bRpbjHqlcAT9"ChE2Cl2L0`L&54RdAl05TdQB'MTB0JXa4bQiNk[P
Z`[4#KM'$3fa!"rYBik0LR"LkEQkCCMk+c6Y+VM4NmV'6dGFBaP#A69i$aU4$l0+
EMkTC,)-4!&8Lj1ip-ZpDTD8%bJ*cN!#$c%%%L(BXB"5b$*!!q-h)5X&N3[&V[$d
NDdJ-&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`1NMDNk0ReFh1P55`eJZ11%H
`aDqLZY&Lmi&E-F1@3Gh$6e)6AIY2[R&lM$SGHBdIiN!2T$)m,F)90F5m854Q)0P
b(0JB(9K#RdCie+YJHC`kiIUE2j!!N8UNf-ATD(8q#[V5jQk$)H'Y"$N,5)P1H5*
PEUN+lMmf8[H,*B)CJE+T41i,#TKUT0!e"50(kM)253I13KqEbJD3!06+f04IPl&
0XkB-416NCRE#%4JQKZT-r#cVkS#"#N(R,TF8d)i5-SJG$"QD,Jc$0(88`D2N)+T
@aGr[+TKilYc,fPKA`GP98bm!S9)NR[E"2%8U+Z6&*C,4dU6Gr'qQLY08mVke)5e
$#CQ-`$1!c"GN"ej6mXZ'qk`KqDEli8'Ul"#5E9)K,48+T3)IY+6!-Ph!346*&-V
bf'%fP8IPPjR4**k18"JrqID&$!6`*C-+NY*T$6EjPPeP6*Q8c$9eVCKl"FGj,i5
CZQSVVM@!+af5c%flYRme`65lp5db"FP*ZP`J'`VC$aR2+Q@mERCaLh4aK9em3(j
CJa!X,[C-eG925B@`9$JM&5b"UeZZXUYEF29kG[91q@8!Ib(iqNAHl9cIqH1[rim
&)h8("ZMkQi`-KHY6drhL-Ph32-T-CCc2&G"YlYbe2(a$B)RH0YP%@IE"K'4QaV*
Y+-VfGPqrIC+51&PM9`'Q4TZ*E$6,RQQbbFJR5G[2GQTEf5Y653U$'fbb6eX2CJ1
3!-dQZi"U0VP$fiIAK&BA3$Yf!$kl"J6Rf$YTBZI3`9j82(#*+j!!*CG4eSJi`iZ
C`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(kekR0R*-aI&(I#F*k%N4a
&9VeKjl-VH*Jre)-LUf##*!9,CX"i5L'fIa5BGQ[j3k`i)bFFk5epp"*9JQbRJAH
T+J008H8fNM`UQ5+,dk4BlF686R+-LT8%9dBCTdT59BN*a,Sl!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&CcbDbG#d*Va1[5iD!
CKQQLl[!dAbr#0dQ3!(p"YV#'&Dl-V'P9cm#XKXD9@iaRHmQF,B![qi4XCh%(VP3
8EJpTTqJB!-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,e0YBR
DiBjI03*Gka`ap5pNd%hmK@@qX,J#BLLbh82A#)`H,),!"'F*XEJ"cLqfT3,*U0D
`@$MiJ3a-9@drFl"Eb-*JU"BbEK3C4qNjfrX'!hNpMQ!XB,3[KcTbE&rJf'UH9*2
8P)9,!S-(&J!B)@RMFR[!P#iH*4@L+Pb(N!$q50e[@aRk0GZMj'3#B`#3!*-E!k)
c*3qNVUcD`kpSG+89bM"6*&G6dM*cfUJqr,RhI2J'Z4M@rKkZ"(rSkCh+U(+FcI+
1qcjdcJjbcMa%$RF`9V$Q3c2*Vb1TQ8Z"369dl-XZrE%[m,0LJfYMYX'fXG9JUmj
"H1N+IMLDT8r`8lmY9$l$e#EZX-GJPDhfYr'R%GVHMm4kEfG)GU#`-[)BjrFFX%8
RG9436*0&%,)3L$!0851@KU0$1R5X!8h,LXXA"@CFe@U,MNS,4V&J)j))bb%JiKN
imY'#"4LiFIN2)hADph`ADF'P#ck!P9FYC%RY)CBCh$39$"aqDBT'harSF#mP`(b
&-D2Ke5jKc+dd$CK,*I)r)PCKdd50!$)H2##!FJDSdCN18G-A[3+8(+2%X%Qc9Sc
YZ*d+B@h!SCC2DqS8@-U4)$RbS%cMN!"+)-$KXV+M-+R5X6&Mm$d(`P``3%&B*b4
mKT!!N!$#V&fpD*`QY$%KmiG$f[VfV'q$(&#[UTV)50fK'YrG2%r%*[j&LbUC`X'
8cjh+`*60T'JI@iiNrdF$'D5XmQ@TTJFErdA$iQ-Vk%#1)6XFqa+&,mM4M5&QK+Q
A%D$,&cf,Mhe"TS)Q6S"@##20$A5e1"9rMb*3'+qAb%@[(Lk#%8-KEiFEB$-pm!$
'A,Kdr3J"Y%-MkABq",!5!![9D!29q1N3I$Gj,%p,46K1)jZ8'`11iD`jY$*MBBf
[%)c9QRBHSkQ%#GK$&)CH+N#9arDAb%@`(P1@![RQ5YN16GK-V`D"VN-V@D0998N
H6IblpMK0kmL%fCK9pFLTFLH%JY@-CS(%Qk6JeTS+[C)VbSpRBikBriD4A#E`F)U
S[CiF'[*H,5aN,Z-!6h!#dB`(h'5C'8GJ(`-lBb,h#c)(1U8VL9pUq%"'X'XY1mL
66PBC(qBm90Hh5`fP4(Bq((Zdq+Pfk+K#*BS,m92'R$fd31SqE`DF+`U%!DT-LF'
eE("ZC$kjlSLI1@G&jM1hRqA1*A!5LpKeM(d[@,r,@0Z&!BQ%L)k$V)-D"Y(1(R4
J1!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!NPbH
fj`L8qceQbUfXQYV*MQjZP6Y5TH$ZJki1iH,Q#MDG4Q#Nbc-(-B3pK5BLjH4$KPl
KD-`,fC+)F'"Q,hdbB$Tp#01S4ArrQS'B&0b0T%@251aAT'R2#CFeRi%lmPkqNic
NJXU(V6R0R+,)l63ARcNS[)e'ZjL#-*,,f0X`3cB2!pA34,mIP"NX%(6L3VBK!5M
PPN0,i3J6F("1`T8QU54lHTAC$Tj#GMP1e345&9LZm3)%!aZq4*8!M`HSm0dTMXI
)E0%M@0[&a)S'Z!R'hB@FUKG4*LL%+f%Fj[Tc)CJ$a*-(Tm6E!,d!S#Z8C6AFe`[
hNRcQ%RI0EN`4h3+95#*k!@5QiHGa,0iABX&@XB+4U`'C&JUl%KRRHVJp'C(`Q@K
k(16%50hqDXdiN33j9#Ak,Ki9Jkj62!9Jmd3'Ueba,0KP1RA9dEP0rNqNR*mGr)0
K04T)"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[eQ8EhBjGG[[km0EjqCj`
HL0+!#N#h*JGZV,aaGCqLCPS&"PXV'+b*6S(K,+Y3iG2R*Epjr4[6RjMa[eZHMlB
E*cmC+PDmhjMZp!pmVUaTAcH+!69qm[0+226KQ`prFVd5MmHi&%[(@B@5-lePc1'
c1Cd&4e#UG$!3MNpNU&NR2rpQb98Z2JQ6qmlYEC*UR2c9k,+Uelq2PJ5lU,0!'Dj
j9Rq1UhpAr`l9YTSk"r&3'ULQb(JNU%A[3&L@QVmX5Zch96AE3*)$DjXfd%!e`C5
`6jG9iA)QVd5RSi,H&@lUj9R*AJ6ik[b'39f-*TK*9@8d+pKNU&3ZjKPX)J`3BUA
2aC4kPm2kpq@VpP520YkBe+H0JcT,Ql!-XYfAh%m$8-jRZQrUbHeX#!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,f
iblCNE8MFEqVI)G+M&S#SR`rT8D89#"ATjj%mDap-@'*P@5iYq`V,P!%D1"ICaiE
m0LJRZpCDKi[FIhrdJ9Q,aCfME3T9NZ(LSh$#4q8e0'fS'VH@UdAZCBpQ0a+,RNM
X+b%#C`Q3!,0S)&[keN@k88Pq9%hf&)1Y!T@8,dD+bDR5&LHP,RQS!)NiA4DZ"bj
*`(i,9CjVX&"c5j2``af0hkYI3iqb@"&m'&Vr6hmB4-cCZSD1C(HTb+iDVlTU(0I
[")[H+B"d&5,NY$@kHm6P0R%rBpj4aEa$h*AFcGZDEN[jPIr[E9NX6[XrfjLKi)h
TC"[6fA4MKYki-6eXBkaA1#TkAh@)MGdDIXAbDe[65aekqkHrP2V2MApVr&YL8Vk
f$%GfR8fiP`(m)GKkqK2p+l),Qbql%[f6c*hfG,D5a%IbG(CLGbFEZTaGGr'5[ki
i$bjh24F&4%QK$!*p*i04a[mCS8cN)KXbjI1cZjh6&@k1NaJV9Z#kILSJG,*lEVC
a,VUV&9kcLbh&idCD$b"4HP)`S*0a3Lk!)D1!URJqQMfT9cbM(ErG)qidR-*MTC!
!m+jC)BSp[4-h)VeCIPYPbN3ZK(l*+-3U58H%"f&XfN80pa@Hcrrk'b5dlXH,eBj
hIq1*ZIm`p*hre&+hffjF@aVT&d@R(pPk&"ArL`SX$mhhp9r+(-5@$4E4BlRiF,K
%DNa1N!$`dY-pm2NA5)5IQ"IX8ZrJ3f"Ufb1rBc992'*UicXD%kMY*(hm8Ip6I"V
BCmP2qM3CK+)D9#9T"f[D*R&aQ0STN!!DbCXXX2`k$a8G2)Pq((mf*6H6qVljh2V
$AQkDiBVdalJ0CLPHTr1EA$[%6VmMXR0arU&Tl+%DpfH[1KBe#89+TXK)D)q4NC!
!YUE(*KHX[kXi09EPDV5)FhYBf#`NP6[a'!Lrm,RU506[Fk&jKfY53PV@9k,K5RX
6GP-9ZfPll&89cYmA'#RlU2S%,S,M2a*Fe4M9ijLD0QQ6me(T$Jri#mim[cbcrFc
cm1+UM"0$aQQKM%,KQ4dL5`VQMZVleYhQ(UTbM+lp,![p&3Zfq@'Q')qdmD+VR"r
GA@eC2kYYeLpMI14GHMJ!&YmBeIHi2(Mi#+m-$*d9KQB&KU#QNI#q6%S`QP-2#VV
rJ4m@#`mZN!!BLjXQ'9Kd)cpV#6,h9$F$MAAG4ee[)"*8BEq+Q$+52dL,NpfScS2
PZpMb(rbdbf1"6iHPdHmT)8@UTlHZpbUA[lJQ2AVXrZbAlNC0E2J)QI5&6&4c,kU
k(K!H##"Abh2N#M%LkX8#SEUl`Klq"A6B)hp*kX&J9J`"9RI*)%mE"GA&('1CX"G
)rVdRCU8UUV-+VAh#eU0bPT'bprm%SP2P#50c54MiI#9Pf[eTUZ`LLEFETb2a+4%
$&D@4h5Y23%'-GYR%LZTjAEh9#j%JUG8V0pJfCPF[-LbZIUpY6r8R9B)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*&GCMbm
m4%&838*RUD!J9b"3)RJ*##45B!ibf'B+-KTJ!N)C8FRrr,[*CZkTSkQM@Bm[2%4
548a#CkQJ)&HJ*5"3iN!N$@!'-KM9Y4!!8FMrq+QM6R8JAc)B0"L`@&I*rrT+3QI
q6[!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`!%51F
a!%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%I1`%K(dSGP#*+#BJ4
%J8je8d"Jj%je!*!$A!#3!i!!!!aB!*!$B!#3!b!!!$mm!!1Tm%&%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@8
J9@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"NDA0
V)(*PE'&dC@3JCA*bEh)J+&i`+5"SBA-JEf0MGA*bC@3Z!*!$6!!#!*!&-3"R!%8
!V33%8A9TG!#3"3S!8!!F!4#)'P9Z8h4eCQCTEQFJGf&c)(0eBf0PFh0QG@`K!*!
&#!!1!#J!,U!#!!%!N!0q!!%!N!96!(-!C`#["!*25`#3"33!53"&!5k)A8&Z)'P
dC@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!0Z!!%!N!9S!(S!I!#
f"!*25`#3"dJ!AJ%PL%j6EfeP)'PdC@ec)(GPFQ8JFfYTF("PC#"LC@0KGA0P)(4
SCANJBA*P)'j[G#"cGA"`Eh*dC@3JBRNJG'KTFb"cC@aQ,@9iG(*KBh4[FLi!N!0
D!!%!N!9G!(!!F3#X"!*25`#3"dS!93%6L$T8D'8JCQPXC5$5AM$6)'eKH5"LC5"
NB@eKCf9N,L!J8'aPBA0P)(9cC5"TG#"hDA4S)'0KGA4TEfiZ!*!$+!!"!*!&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-!p6G(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-e2bQAph[qrELM`EhmbhY8#
5eFlXbH4*f,ilNa'5j9ENLDc)laq42j1IbEcCeRB454B6XMFYb5)S31)(rdjCKT&
84$LS#cYiiLGf)5c5J1e3aD%@GK*H(mq1D3bR6lpC+R)6)mRY[@4[%r6@hmf'R%[
)+8FIZEr5&V,ejRAjaL3*5bPTf0kN&a@6NPGC,a$mi-RK`KFHI%V$*QM4BN6+hFf
qTX2b,*5j55k)jb(*(2h&i)XDJqim&Fee*9$cG*JIMZ6*i#SGjViNe#Xq)@+3!*h
[`af,NK")heX@$ED[(5XhPA-`LA1fRcbNbSE0RBqrZ,m'l)YVm[NQUD!A@)"Ck2@
aqNDT+'b%UlJKdF4%D4j'8D8QKLJRXm5(8JQR40@4X8N6+L,JmB-'82KL!,85ECR
3J#8d%@TbLdfC`eLTT"qR$+aeU)[Di0J#T6DMFe4B`aLflrdNJ-)Z!m3jBTLiESA
mcl%RFHbLl9fAJNh,JDRU`pD$+ZFdM(GdeX@!G"Z$#pDfYBXaSNc2)HBbh"2bA1l
EQ20L2d(0f,[Q&#I)A'ZQ2(KBb@@qIDUNT-rSkShVZbh3b(2j4EE#Hi"%aD`5%YX
K48JPi!JpjfESS#*')G-lpU&Zma9#N6ZP%AF+hP-PhjBJ16hDlDNc*qDmR%1jlK@
TB-cEfPh+FK[jplG1#3aZ,GrmP`rLNbG@J3Mpl)N"@`NmD#E1Ye,'NV,SJ&0-'N"
4lGDH(L15jV)kGQArf*KLjXEBBNT+ilSFVqIQ2L6S6,2!-qdr5A,SM5rZ8%e+qrr
FIEa)TAK+(ePf3"KU9mH96KeiJM&J8-CCH2(UplHlTpQ8&pIV!mfS&!eYS22Y"H5
9K,,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(bC5reTB0Nq+`1N!#ULm1*Sfp
KL@KA(V8&MK(J'6fDpK)ZJ-$X$'lTUd'pQXb1L-Hl60lqhlJ2YkIbbBfVNkBAI5l
bXT26-1CCQI@i%dADZX@J'V("P$45$f-VG@mlh@!+D@pipZKGMr,CUC9ZcXXMqF'
dI'XXGU%XA8IkajQ+#fPh$2Aj@FVRjqVrINKT#[0r9hl1a'Bar[EhjGLF9@FZ6fP
Z&[UQ90aX9RVbi))fT0[hNY60m9Pip++5qIc2PqqBK`c8pE9GaLXRlhFHm(""&mY
9YB2CTqfiUkZ$G385RX(1bd[ERX3qk'4JZaVPpDGj!R%'T["3[!PH+Gc$PhJ`"hH
qIVA3@F0Eeq31!!!",d&%3e)$!!&Z$98,Sa,3(`,[MX0G"i1VS')4Q(4+"CeP@S'
Clmb(SM82Ip(I(*K(D4A2I'$q&[0K9K8c&"2&r$@V5EkTU*K9439&phSP6c(*!"1
aC5A+J0LHE33'eM"R5Q-Af($455FbMP!J*%5L5"VfFJe#ABTbVcRA4B@a96dp+RH
hD`rFF&F@))QYk$RCaCMM3iY@r'%I9"NNRi3H&+6Nb+Ekq,R[CKIQhmVFF$J`VdQ
5m'YemhE`p&D5E6j5(VmrPl$l$k3rXTPHl)!0@&jc$0ZABIP&mp&"JI!#DaENdTM
ml81I`#icTcGeq@6Upd1K&[m+1ImYiqD1UMI2ikh!"rA+h@GFD3IbmLC@e9$jp9!
k6JUl9a2!KP1+'B$U)Bc230$[U!%J"*%91SCK"!!!#4G"4%05!`!1K3jG#k55),i
bhjhrq-jHjTcIRm3X@FlH1F3CSh%X80,b[R0QLXqEJ*aX40@UcFUD#%5Rl(e8Jll
rGqBa*dc)b``NKG+`*T5N3Y"1UPMIThV[djD9N!!b0-6@8G9SS`-*3XV@EJZ,ppf
G(@H&VG9l$HjZ05)#-d3M(d0&9JkT3rK[IJhrMG+c8Cl(B+4U`aFMihF0N!#jkkJ
(bAf)aK,IG)P[ca,IG-NC,*)9Q2S@4ApLIjK&+S'Id[Z4`Ve!C&F!hk33*VJjb0N
B50)-%!X)p`RCp6"I8pTh4UI[+E8`dFID4ZkGr@lA$AQDlbldTY[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-b
hq8GG`NZPN!#-)R+V%99PNPlh36fhm*9bM*6G5(DLl6*[`RRN%1kYe0apJX"08h9
pBpI"UeK@ZP%fDY[@f0f"j$FB'16,"hmb'lqqr(ZIF,[qqr(8P4F2LPmU8Y6lJ@,
C*HD'0C[m5%SlDaYhr0f9c5@RlpTrl%Ba0h%pIrF&([T)hhCPQkhZV!V"p*ICGPY
r00)ATYFTIIZZ+Zh!F'lqJ+RpekRmf5JSrZ#`Jfc9YhilkVTHh9L([6AGJPqp[j5
#5'i#SGl@1!l!f0$([Z4B9)JpbTMr8K%pV8&b'lM9+a*8%hV&U'bb498Z@DQS*MR
Z&3U9S9IX$jNN*bhPP@UI8TA)Arc+eR608jlGh#RG(Y%mCIVZHjY0eR5&1qC1dXc
90emD5,Ej@(eFD1XV&rqi5CRVdF[i&43@eN[fU#"2lpYa(VlC*ZUUNZp0XGNQB,2
*LUI#aR9CrBK0&Sp+b8*6C1J9E63Tqf"5i25flDL4ELQ!0#R1JdB29[1P&-F&`EQ
V34i-5ZXME9iP2CJ#Sq!JM5UKU,HpAUd@9Ujj,Ce3erhrA2Y0)fVEk2m'%q('2UU
C%2HLD&+GqD$mXUXk4$HdCk9'VaEk0mH(e6-fT4pmjRa9e3I09fm)JH',*UjGkCY
BVDUp[eRI+)5dJF4`UL@ija2YP0UeSHUUm2!Y1A!N#i,p%r+mraE)KC!!h)mYI"M
-*-j`h-92m%VhR)6A)GbRK)!S@)q!m3bE39ZF$L3#NlajP54K$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@N
10p%$TmlaarF12*%VqVQP+IbmGAC[Z(*i4%i0ElMdXHT++-Ze+['9N53H0#4Y9,3
%Ib#8d),3L422HK!GJGBFY,LYf`X9ljIeI"9HZ54kVCUF308$Ta+%AGi0FXiSpX5
"dhYD$!,RQ3U0(P3fjfdBeq`NrZ'e,erl6RVGI#'mVR"`phbT-2,3[')Sd$cb3&!
%V`adK&KR!aa2Y%%,Z,h0rNH#iVJi,$5IJe1*KV4GN8AeTLJdhii*%jh+4+0lL-6
G`Gb!1(p'+l"R#Xqlj[FAI)G0QQ+9i'Uh+QCdXfkhYb)Q$Qa("&X5L'&#mPXXm@0
)Ucd%5eJUcINKX48pJ6d%PbS*K&[ci9Z%V*(I3hJPL`MrdJSI3`D53``T(FqmS[E
kqkCA(rKLZIm!-KZ&[1GiTPFGl*ZpSH[blmr0kANl3fU1pr3DII1R0R@Yr)*!qJH
3!1C*GFpaYEH[Hmh&ZN*A@%M6!%pD0diEiCSl$VHQjr`k#`[26@IZ9DI$daI6KAA
2pN(q9D3Y+FMIp2MMdq%6Qblq,Td1hibPQPH&k,ZJH0C&,1fSJfdU0CD1i33[B40
4!YdjT'r8eK+UMqe@Db3GV(dcl%e2@"m1dpJq%Rh(6	H,q%2[!CM`9RLm[r%li
9iPZYi6IUKXJLDiC`*LQ1j@0C1-R3A,AUd"L@,!$X'#)f9Q`GU4qjDTIlE$mqA(M
5%LlfVkUm(4R$6f-Y*2qH0D6p36il*,[YSYC3Ef@,rIqX9*l!Ebf0'B$Bc0CR("A
bR`1@-IY,[Y#8e9pF9R&@mL*83(aXZ8)Z"La%VB`"J[[p584Bj!eI5+Z3!-m'FQl
e8ke"Xl)9E+f!P-EiV3U5Rr1e(UmFZASXGdNpP#jSPS%Mep04%N&XLQ8J!kB+Phf
ShJLZT1Hk&EZ'!AIMZcc23,,Q+,p414k9S,B6,'a82bfhAaYETNrA%56ja02ZG*T
5j4lME!"-qUA2Y$MMJiY4T!6X@Z)k)D`B8d'!AjJ-cVeXTE3(16-(E(Pb4Q#Tj'@
9#%5hl5$Glld`DH2L9KVmeH*EFa9hpIDl1`$QYF(BlY&bTX2dqBA$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[piVX)kEUcG1DPY3V0
$`62A6#EC@@pc!%i&h!kia8UMBYEe3)A945F$!Zi8m+KTci21HV%pT#rHl4bkG*d
El!9mF@EmL(@Qr)X@N!!HQJGM-lYP`%2C`r@*QVC6V('0%["TN!#F,[k0%(eX#hU
3!0aHNqRj@JSe6JF*I04KqTHADUE2Tc,B-J[*j9f1hMkq&-B!U*!!KfX`AB-8B"A
h@IS[4f&li'IQ$1CAe9if%aiqGN!&Q%S4&CiQhDIf@FS1cNUjaA2YaBpQiQbY3i'
CP4mCLmX+L8rILUK3`8dZHmjaV0YkRM[jP2ccRlVip*4Me-qAPMjP-@A,$9P,I85
&#Ulqe@iaGfcqU-aPXh*qlF1-@ZZSlH5C1mA0TJqUQTkf2j&8)5`qd`4i3-FVSVN
)cQ3YT[jL52V`9&+&J$mj!EMGASjQX`p@2&,*6%A`c5D4[Tl00DT3H*AkL5leI''
P)l9im[YlhCrhTp2DG*J[E4#Y4L*[6e`je+K#q,'4%64@!PYK&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!!!!r
J!!!Im!!!2rJ!!(rm!!$rrJ!"rrm!!rrrJ!Irrm!2rrrJ(rrrm$rrrrKrrrrmrj!
$rRrrN!-rrrrq(rrrr!rrrrJ(rrr`!rrri!(rrm!!rrq!!(rr!!!rrJ!!(r`!!!r
i!!!(m!!!!q!!!!(!!*!$J!#3"#!IU5!a16N`,6Nf)%&XB@4ND@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`!8je6Ud!)Q%!!pDTp%j
a5S0Q!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!!1b
K'Li)##S!"J!%C`BJH!+QS"XX+J!%+LS!#"JU!!5Ae*A8)$Vr9U%HCJ!!c#a))$V
r5L)'`VJ$'PK"B3$r8L!krd,!Z!-D3IVr2L#!5S9Q"+%LB!3J4D!RCJ!!Q#T),cV
r!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#KZ!!a(q[jD4IVq@L!
8X**Y"#!5+)"+J'm5)&-LEJ!)SLiJ&0'6NC*`!'!%-$crf8cI(!"1ANje6PEreNM
R%aJX,J!35IVpmN)(S4SY52rQ5Li!#fF')(J#TU!E,c`!!+$m6VS#RLe!rqTB6fF
!!Ai[,[rU6VS"q%S!@%pR"R!"B!!"FNKZrrK)E[rd5'lrlNkk!j)J,[rdS4iY52r
`6qm!$'F!!8JJ,[riS4iY52rmC`!"1LmZrrJ[#%kk!qC+VJ!88%pQ!!#8@Bm[2%0
24%9`!$m!U"mQAb!,ChiJ%h)Bd)%[!%kk!Y`-3!!$@%pQDL!0FLM3J5e!rpSJ%h3
Bd))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+@l
rkJ!-+@lrm!!3+@lrp!!8+@lrr!!B,c`!!+'B6VS"L#e!rpB[2!!!U*p1ZJ&k)Ll
reV#"9X0%!dL$5--T3`!F+8B!)#PZ!!`!*%Kkr*!!2cbJr#mm!!#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%kk!2)S3#!-@%pR5#m
-6VS!8%S!@%pR2#C-,bX!$$mmS2`[2!!!S2a1ZJ#L@)mI!%kk$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!!&Q
22cbSER!"(`"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%jH6R919J!!51FI!$i
Z!!T)abm(6VVraKS!F!!3"3a!!!&B6fB3!NF(rdkkrhb`4fi%F!"J+PQ22cbSRh!
"(`"1ZJl#+"pCMcm((`91ZJkf,"qiKPI$4!0R"(!!B!)J"NcZ!2Mrl%jH6R919J!
!51F4#$iZ!!iJEJ!)+&"f!(!!-"3-J!!!384Q,R!!-#`!!Jb!!!"$8QBJ$%IrrfF
B)#`!"%*!5%$J5#)m!*!$rm+!5-HqJ@B#GJ%3!dcZ%)Mrp%jH6R919J!!F2m[!%K
Z!!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!*!$*2r
d+'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()%6VS
0)R)!-JFAJ"J!F!!`"b"ZrrM3J$''#!"`!$!(%$-)!()"iDRF36!(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'-M
ri%jH6R919[rm51F2'#CZ!!`SEJ!83NCJ$R!!-!E3J%*d#!!`"P*'F!!`"R)!-Li
!%Y+"XS"ZiN*'H!*J!!#D3N9#4h!!-!BJEJ!)jB!YF!J!rraJE(!"`+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!!51F
2'$iZ!!iQEJ!3+'i!#$JZ!"Bk"qC0F!!`"h`(c%"q!(!!-!830!J!l#Kb!")!F!(
!!A)!%J$HJ5!(d)"b!$)c#!!Z!9*'F!!`"R))XS"Q"N*'-!954A!!-!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!"61i3m2r
X6Pj1G8j@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!!`,[rb,`![,[rd6VS)I#m
Zrra`!$!Zrr)[!#mZrr3[,[ri6VVp)Nr[!$"#4f!!!2C+E[r`Cc*`!$!Zrr)[!#m
Zrra`!$!&,`![#dkkrGjm!"`!F!!`"L"Zrr4b!")`#!$D38r[!""J'R!!-!3[!(!
!-!8[!#m,6VVq,M`!fN42l`!-['lrl'B3-!G54h)!-J"#0"J!B!!!MVaZrqjQG%T
Zrr"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"aQ
d#!!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[`#50Em!#$@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#KZrmJYI!!!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!rkjR$#"-)Qlrb#!Zrkk
L,LKZrklCl[r)5'lrXLmZrmJJEJ!)6T!!)#lrXV#ZrlC36f3'F'GJ!!5U(9crah!
!%#lradM!d)"63$e!rqa`!$!Zrqc3J$e!rqiJEJ!3)"$3VJ!-,8$re#mZ!"`[,[r
F5(J"*#m-6VVmG()!-J"+JGR",bi!(#mZrpK)H!%N,blrh%kk"E`[,[rJ5(J"*#m
Zrp`[,[rB6VVkCLmZ!"`[,[rFF!!`,[rX,`![$%kkr#jb!$)!5S(C`5mZ!"`[,[r
BF!!`,[rX,`![,[rF6VS&FLmZrr"`!$!Zrq`[!#mZrp`[,[rB6VVk'(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!rjTR$#"-)Qlrb#!ZrjU
L,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-Bf3Y62qQ,@lrc2qU)!a5J*!
!V[qU,8$rSL!ZrkD3!+lrb#e!rjiJ,[qUN!#ZrkBY32qDC``J6#*ZrmJJ,[qDSLi
SE[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!+l
rb#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#(!"`)AF3(!!-!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-rkBYE[r-rkSJ$&+!N!#
ZrkSY32qL)#lrTT!!V[r),8$rRL!ZrkU3!+lrTLe!rjTR$#"-)Qlrb#!ZrjUL,LK
ZrjVCl[r)5'lrRLmZrmJJEJ!)6T!!)#lrRV#Zrk*36f3'F'GJ!!$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)YLiLCZ!!aJ#L"Zrp"5V[r
3%*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!18ND
mEJ!1C"*`!$!'FJ!b""!d#!#`0"J!CHC64lK(C"*`!$!(FJ!b""!d#!#`0"J!BZL
q4Q0)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-)!(!!-!I3J()!-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!61iBm2rS6Pj1G8j@rra)j`mB+'i
!&!DZ!!!"*!!8*Qi!&%*'B#"`!$!')'i!#()!-JBCX!J!'!"`!$!'d)!hKJJ!-!C
54VaZ!!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)!IML()"`S@#J#i"iSd
`"&0%5N"QkR!!-!E3J()!-M-)!#"Z!"$PJ5'('!!`"P*')#lrr&+ZrrbmEJ!1CB4
-lKM`rq41ANje)PmJAk!P,S"U!N+A6Y%LAa)I-"p+!@F%TdCJ!U0',SK1d5*I%Km
`(b"I5J&R"+C(B!+L4dl4)Pp`!D'B6Y%L,`!%)#m!#%(k!!SbI!!#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)[!!3
J,`!)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!@errm
J!#p!!*!&J[rr!!![XJ#3"!2SrrmJ!$!3!*!%"!(rrb!!-$`!N!@#rrmJ!$"-!*!
&KIrr*!!`A!%#pP`!Krrr)!!`E!#3"BErrb3!-(`"![CB!)$rrb!!-)`!N!@"rrm
J!$#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!*!&J2rr)!"!"J#3"[rr!!"
"#J#3"!C`FQpYF(3)a#"cG@CQDAM(93:
\ No newline at end of file diff --git a/mac/tclMacResource.c b/mac/tclMacResource.c deleted file mode 100644 index 0c1a372..0000000 --- a/mac/tclMacResource.c +++ /dev/null @@ -1,2210 +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.6 1999/04/28 17:06:07 stanton 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; - 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; - Tcl_DString dstr; - - if (strcmp(Tcl_GetString(objv[2]), "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_ExternalToUtfDString(NULL, *pathHandle, pathLength, &dstr); - - Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)); - HUnlock(pathHandle); - DisposeHandle(pathHandle); - Tcl_DStringFree(&dstr); - } - 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: { - Tcl_DString ds, buffer; - char *str, *native; - int length; - - if (!((objc == 3) || (objc == 4))) { - Tcl_WrongNumArgs(interp, 2, objv, "fileName ?permissions?"); - return TCL_ERROR; - } - str = Tcl_GetStringFromObj(objv[2], &length); - if (Tcl_TranslateFileName(interp, str, &buffer) == NULL) { - return TCL_ERROR; - } - native = Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&buffer), - Tcl_DStringLength(&buffer), &ds); - err = FSpLocationFromPath(Tcl_DStringLength(&ds), native, &fileSpec); - Tcl_DStringFree(&ds); - 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 = fsRdWrPerm; - 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 == fsRdWrPerm)) { - /* - * 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_SetByteArrayObj(resultPtr, (unsigned char *) *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 = (char *) Tcl_GetByteArrayFromObj(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_GetIndexFromObj 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 = Tcl_GetStringFromObj(objv[1], &length); - return Tcl_EvalFile(interp, string); - } - - /* - * The following code supports a few older forms of this command - * for backward compatability. - */ - string = Tcl_GetStringFromObj(objv[1], &length); - if (!strcmp(string, "-rsrc") || !strcmp(string, "-rsrcname")) { - rsrcName = Tcl_GetStringFromObj(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 = Tcl_GetStringFromObj(objv[3], &length); - } - return Tcl_MacEvalResource(interp, rsrcName, rsrcID, fileName); - - sourceFmtErr: - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), errStr, "should be \"", - Tcl_GetString(objv[0]), " fileName\" or \"", - Tcl_GetString(objv[0]), " -rsrc name ?fileName?\" or \"", - Tcl_GetString(objv[0]), " -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_GetString(objv[0]), " -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); - } - - if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) { - oldTypePtr->freeIntRepProc(objPtr); - } - - objPtr->internalRep.longValue = newOSType; - objPtr->typePtr = &osType; - - Tcl_InvalidateStringRep(objPtr); -} - -/* - *---------------------------------------------------------------------- - * - * 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 = Tcl_GetStringFromObj(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 f9376db..0000000 --- a/mac/tclMacResource.r +++ /dev/null @@ -1,90 +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.3 1999/04/16 00:47:21 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". - */ - -#include "tclMacTclCode.r" - -/* - * 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 020380f..0000000 --- a/mac/tclMacShLib.exp +++ /dev/null @@ -1,1066 +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 -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 -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_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 d387cb5..0000000 --- a/mac/tclMacSock.c +++ /dev/null @@ -1,2637 +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.4 1999/04/16 00:47:21 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}, -}; - -typedef struct ThreadSpecificData { - /* - * Every open socket has an entry on the following list. - */ - - TcpState *socketList; -} ThreadSpecificData; - -static Tcl_ThreadDataKey dataKey; - -/* - * 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; - ThreadSpecificData *tsdPtr; - - if (! initialized) { - /* - * Do process wide initialization. - */ - - initialized = 1; - - 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); - } - - /* - * Do per-thread initialization. - */ - - tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); - if (tsdPtr == NULL) { - tsdPtr->socketList = NULL; - Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); - Tcl_CreateThreadExitHandler(SocketExitHandler, (ClientData) NULL); - } -} - -/* - *---------------------------------------------------------------------- - * - * 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); */ - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpHasSockets -- - * - * 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 -TclpHasSockets( - Tcl_Interp *interp) /* Interp for error messages. */ -{ - 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 }; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (!(flags & TCL_FILE_EVENTS)) { - return; - } - - /* - * Check to see if there is a ready socket. If so, poll. - */ - - for (statePtr = tsdPtr->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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - 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 = tsdPtr->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_GetChannelHandle 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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - 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 = tsdPtr->socketList; - tsdPtr->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. */ -{ - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (statePtr == tsdPtr->socketList) { - tsdPtr->socketList = statePtr->nextPtr; - } else { - TcpState *p; - for (p = tsdPtr->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 (TclpHasSockets(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 (TclpHasSockets(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 (TclpHasSockets(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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (!(flags & TCL_FILE_EVENTS)) { - return 0; - } - - /* - * Find the specified socket on the socket list. - */ - - for (statePtr = tsdPtr->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 (TclpHasSockets(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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - while (tsdPtr->socketList != NULL) { - statePtr = tsdPtr->socketList; - tsdPtr->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 (TclpHasSockets(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 - * the interp's 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; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - for (statePtr = tsdPtr->socketList; statePtr != NULL; - statePtr = statePtr->nextPtr) { - if (statePtr->flags & TCP_RELEASE) { - SocketFreeProc(statePtr); - return; - } - } -} diff --git a/mac/tclMacTclCode.r b/mac/tclMacTclCode.r deleted file mode 100644 index 1a8f3ca..0000000 --- a/mac/tclMacTclCode.r +++ /dev/null @@ -1,36 +0,0 @@ -/* - * tclMacTclCode.r -- - * - * This file creates resources from the Tcl code that is - * usually stored in the TCL_LiBRARY - * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * SCCS: @(#) tclMacTclCode.r 1.1 98/01/21 22:22:38 - */ - -#include <Types.r> -#include <SysTypes.r> - -#define TCL_LIBRARY_RESOURCES 2000 - -/* - * 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, "Auto", purgeable) "::library:auto.tcl"; -read 'TEXT' (TCL_LIBRARY_RESOURCES + 2, "Package", purgeable,preload) "::library:package.tcl"; -read 'TEXT' (TCL_LIBRARY_RESOURCES + 3, "History", purgeable) "::library:history.tcl"; -read 'TEXT' (TCL_LIBRARY_RESOURCES + 4, "Word", purgeable,preload) "::library:word.tcl"; diff --git a/mac/tclMacTest.c b/mac/tclMacTest.c deleted file mode 100644 index 9598848..0000000 --- a/mac/tclMacTest.c +++ /dev/null @@ -1,213 +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.4 1999/05/11 07:13:36 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; -} diff --git a/mac/tclMacThrd.c b/mac/tclMacThrd.c deleted file mode 100644 index 7790e5f..0000000 --- a/mac/tclMacThrd.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * tclMacThrd.c -- - * - * This file implements the Mac-specific thread support. - * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * SCCS: @(#) tclMacThrd.c 1.2 98/02/23 16:48:07 - */ - -#include "tclInt.h" -#include "tclPort.h" -#include "tclMacInt.h" -#include <Threads.h> -#include <Gestalt.h> - -#define TCL_MAC_THRD_DEFAULT_STACK (256*1024) - - -typedef struct TclMacThrdData { - ThreadID threadID; - VOID *data; - struct TclMacThrdData *next; -} TclMacThrdData; - -/* - * This is an array of the Thread Data Keys. It is a process-wide table. - * Its size is originally set to 32, but it can grow if needed. - */ - -static TclMacThrdData **tclMacDataKeyArray; -#define TCL_MAC_INITIAL_KEYSIZE 32 - -/* - * These two bits of data store the current maximum number of keys - * and the keyCounter (which is the number of occupied slots in the - * KeyData array. - * - */ - -static int maxNumKeys = 0; -static int keyCounter = 0; - -/* - * Prototypes for functions used only in this file - */ - -TclMacThrdData *GetThreadDataStruct(Tcl_ThreadDataKey keyVal); -TclMacThrdData *RemoveThreadDataStruct(Tcl_ThreadDataKey keyVal); - -/* - *---------------------------------------------------------------------- - * - * TclMacHaveThreads -- - * - * Do we have the Thread Manager? - * - * Results: - * 1 if the ThreadManager is present, 0 otherwise. - * - * Side effects: - * If this is the first time this is called, the return is cached. - * - *---------------------------------------------------------------------- - */ - -int -TclMacHaveThreads(void) -{ - static initialized = false; - static int tclMacHaveThreads = false; - long response = 0; - OSErr err = noErr; - - if (!initialized) { - err = Gestalt(gestaltThreadMgrAttr, &response); - if (err == noErr) { - tclMacHaveThreads = response | (1 << gestaltThreadMgrPresent); - } - } - - return tclMacHaveThreads; -} - -/* - *---------------------------------------------------------------------- - * - * TclpThreadCreate -- - * - * This procedure creates a new thread. - * - * Results: - * TCL_OK if the thread could be created. The thread ID is - * returned in a parameter. - * - * Side effects: - * A new thread is created. - * - *---------------------------------------------------------------------- - */ - -int -TclpThreadCreate(idPtr, proc, clientData) - Tcl_ThreadId *idPtr; /* Return, the ID of the thread */ - Tcl_ThreadCreateProc proc; /* Main() function of the thread */ - ClientData clientData; /* The one argument to Main() */ -{ - - if (!TclMacHaveThreads()) { - return TCL_ERROR; - } - -#if TARGET_CPU_68K && TARGET_RT_MAC_CFM - { - ThreadEntryProcPtr entryProc; - entryProc = NewThreadEntryProc(proc); - - NewThread(kCooperativeThread, entryProc, (void *) clientData, - TCL_MAC_THRD_DEFAULT_STACK, kCreateIfNeeded, NULL, (ThreadID *) idPtr); - } -#else - NewThread(kCooperativeThread, proc, (void *) clientData, - TCL_MAC_THRD_DEFAULT_STACK, kCreateIfNeeded, NULL, (ThreadID *) idPtr); -#endif - if ((ThreadID) *idPtr == kNoThreadID) { - return TCL_ERROR; - } else { - return TCL_OK; - } - -} - -/* - *---------------------------------------------------------------------- - * - * TclpThreadExit -- - * - * This procedure terminates the current thread. - * - * Results: - * None. - * - * Side effects: - * This procedure terminates the current thread. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadExit(status) - int status; -{ - ThreadID curThread; - - if (!TclMacHaveThreads()) { - return; - } - - GetCurrentThread(&curThread); - DisposeThread(curThread, NULL, false); -} - - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetCurrentThread -- - * - * This procedure returns the ID of the currently running thread. - * - * Results: - * A thread ID. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_ThreadId -Tcl_GetCurrentThread() -{ -#ifdef TCL_THREADS - ThreadID curThread; - - if (!TclMacHaveThreads()) { - return (Tcl_ThreadId) 0; - } else { - GetCurrentThread(&curThread); - return (Tcl_ThreadId) curThread; - } -#else - return (Tcl_ThreadId) 0; -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpInitLock - * - * This procedure is used to grab a lock that serializes initialization - * and finalization of Tcl. On some platforms this may also initialize - * the mutex used to serialize creation of more mutexes and thread - * local storage keys. - * - * Results: - * None. - * - * Side effects: - * Acquire the initialization mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpInitLock() -{ -#ifdef TCL_THREADS - /* There is nothing to do on the Mac. */; -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpInitUnlock - * - * This procedure is used to release a lock that serializes initialization - * and finalization of Tcl. - * - * Results: - * None. - * - * Side effects: - * Release the initialization mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpInitUnlock() -{ -#ifdef TCL_THREADS - /* There is nothing to do on the Mac */; -#endif -} - -/* - *---------------------------------------------------------------------- - * - * TclpMasterLock - * - * This procedure is used to grab a lock that serializes creation - * and finalization of serialization objects. This interface is - * only needed in finalization; it is hidden during - * creation of the objects. - * - * This lock must be different than the initLock because the - * initLock is held during creation of syncronization objects. - * - * Results: - * None. - * - * Side effects: - * Acquire the master mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpMasterLock() -{ -#ifdef TCL_THREADS - /* There is nothing to do on the Mac */; -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpMasterUnlock - * - * This procedure is used to release a lock that serializes creation - * and finalization of synchronization objects. - * - * Results: - * None. - * - * Side effects: - * Release the master mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpMasterUnlock() -{ -#ifdef TCL_THREADS - /* There is nothing to do on the Mac */ -#endif -} - -#ifdef TCL_THREADS - -/* - *---------------------------------------------------------------------- - * - * Tcl_MutexLock -- - * - * This procedure is invoked to lock a mutex. This procedure - * handles initializing the mutex, if necessary. The caller - * can rely on the fact that Tcl_Mutex is an opaque pointer. - * This routine will change that pointer from NULL after first use. - * - * Results: - * None. - * - * Side effects: - * May block the current thread. The mutex is aquired when - * this returns. Will allocate memory for a pthread_mutex_t - * and initialize this the first time this Tcl_Mutex is used. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_MutexLock(mutexPtr) - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ -{ -/* There is nothing to do on the Mac */ -} - - -/* - *---------------------------------------------------------------------- - * - * TclpMutexUnlock -- - * - * This procedure is invoked to unlock a mutex. The mutex must - * have been locked by Tcl_MutexLock. - * - * Results: - * None. - * - * Side effects: - * The mutex is released when this returns. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_MutexUnlock(mutexPtr) - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ -{ -/* There is nothing to do on the Mac */ -} - - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeMutex -- - * - * This procedure is invoked to clean up one mutex. This is only - * safe to call at the end of time. - * - * This assumes the Master Lock is held. - * - * Results: - * None. - * - * Side effects: - * The mutex list is deallocated. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeMutex(mutexPtr) - Tcl_Mutex *mutexPtr; -{ -/* There is nothing to do on the Mac */ -} - - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeyInit -- - * - * This procedure initializes a thread specific data block key. - * Each thread has table of pointers to thread specific data. - * all threads agree on which table entry is used by each module. - * this is remembered in a "data key", that is just an index into - * this table. To allow self initialization, the interface - * passes a pointer to this key and the first thread to use - * the key fills in the pointer to the key. The key should be - * a process-wide static. - * - * There is no system-wide support for thread specific data on the - * Mac. So we implement this as an array of pointers. The keys are - * allocated sequentially, and each key maps to a slot in the table. - * The table element points to a linked list of the instances of - * the data for each thread. - * - * Results: - * None. - * - * Side effects: - * Will bump the key counter if this is the first time this key - * has been initialized. May grow the DataKeyArray if that is - * necessary. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadDataKeyInit(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ -{ - - if (*keyPtr == NULL) { - keyCounter += 1; - *keyPtr = (Tcl_ThreadDataKey) keyCounter; - if (keyCounter > maxNumKeys) { - TclMacThrdData **newArray; - int i, oldMax = maxNumKeys; - - maxNumKeys = maxNumKeys + TCL_MAC_INITIAL_KEYSIZE; - - newArray = (TclMacThrdData **) - ckalloc(maxNumKeys * sizeof(TclMacThrdData *)); - - for (i = 0; i < oldMax; i++) { - newArray[i] = tclMacDataKeyArray[i]; - } - for (i = oldMax; i < maxNumKeys; i++) { - newArray[i] = NULL; - } - - if (tclMacDataKeyArray != NULL) { - ckfree((char *) tclMacDataKeyArray); - } - tclMacDataKeyArray = newArray; - - } - /* TclRememberDataKey(keyPtr); */ - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeyGet -- - * - * This procedure returns a pointer to a block of thread local storage. - * - * Results: - * A thread-specific pointer to the data structure, or NULL - * if the memory has not been assigned to this key for this thread. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -VOID * -TclpThreadDataKeyGet(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ -{ - TclMacThrdData *dataPtr; - - dataPtr = GetThreadDataStruct(*keyPtr); - - if (dataPtr == NULL) { - return NULL; - } else { - return dataPtr->data; - } -} - - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeySet -- - * - * This procedure sets the pointer to a block of thread local storage. - * - * Results: - * None. - * - * Side effects: - * Sets up the thread so future calls to TclpThreadDataKeyGet with - * this key will return the data pointer. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadDataKeySet(keyPtr, data) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ - VOID *data; /* Thread local storage */ -{ - TclMacThrdData *dataPtr; - ThreadID curThread; - - dataPtr = GetThreadDataStruct(*keyPtr); - - /* - * Is it legal to reset the thread data like this? - * And if so, who owns the memory? - */ - - if (dataPtr != NULL) { - dataPtr->data = data; - } else { - dataPtr = (TclMacThrdData *) ckalloc(sizeof(TclMacThrdData)); - GetCurrentThread(&curThread); - dataPtr->threadID = curThread; - dataPtr->data = data; - dataPtr->next = tclMacDataKeyArray[(int) *keyPtr - 1]; - tclMacDataKeyArray[(int) *keyPtr - 1] = dataPtr; - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeThreadData -- - * - * This procedure cleans up the thread-local storage. This is - * called once for each thread. - * - * Results: - * None. - * - * Side effects: - * Frees up all thread local storage. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeThreadData(keyPtr) - Tcl_ThreadDataKey *keyPtr; -{ - TclMacThrdData *dataPtr; - - if (*keyPtr != NULL) { - dataPtr = RemoveThreadDataStruct(*keyPtr); - - if ((dataPtr != NULL) && (dataPtr->data != NULL)) { - ckfree((char *) dataPtr->data); - ckfree((char *) dataPtr); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeThreadDataKey -- - * - * This procedure is invoked to clean up one key. This is a - * process-wide storage identifier. The thread finalization code - * cleans up the thread local storage itself. - * - * On the Mac, there is really nothing to do here, since the key - * is just an array index. But we set the key to 0 just in case - * someone else is relying on that. - * - * Results: - * None. - * - * Side effects: - * The keyPtr value is set to 0. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeThreadDataKey(keyPtr) - Tcl_ThreadDataKey *keyPtr; -{ - ckfree((char *) tclMacDataKeyArray[(int) *keyPtr - 1]); - tclMacDataKeyArray[(int) *keyPtr - 1] = NULL; - *keyPtr = NULL; -} - - -/* - *---------------------------------------------------------------------- - * - * GetThreadDataStruct -- - * - * This procedure gets the data structure corresponding to - * keyVal for the current process. - * - * Results: - * The requested key data. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -TclMacThrdData * -GetThreadDataStruct(keyVal) - Tcl_ThreadDataKey keyVal; -{ - ThreadID curThread; - TclMacThrdData *dataPtr; - - /* - * The keyPtr will only be greater than keyCounter is someone - * has passed us a key without getting the value from - * TclpInitDataKey. - */ - - if ((int) keyVal <= 0) { - return NULL; - } else if ((int) keyVal > keyCounter) { - panic("illegal data key value"); - } - - GetCurrentThread(&curThread); - - for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1]; dataPtr != NULL; - dataPtr = dataPtr->next) { - if (dataPtr->threadID == curThread) { - break; - } - } - - return dataPtr; -} - - -/* - *---------------------------------------------------------------------- - * - * RemoveThreadDataStruct -- - * - * This procedure removes the data structure corresponding to - * keyVal for the current process from the list kept for keyVal. - * - * Results: - * The requested key data is removed from the list, and a pointer - * to it is returned. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -TclMacThrdData * -RemoveThreadDataStruct(keyVal) - Tcl_ThreadDataKey keyVal; -{ - ThreadID curThread; - TclMacThrdData *dataPtr, *prevPtr; - - - if ((int) keyVal <= 0) { - return NULL; - } else if ((int) keyVal > keyCounter) { - panic("illegal data key value"); - } - - GetCurrentThread(&curThread); - - for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1], prevPtr = NULL; - dataPtr != NULL; - prevPtr = dataPtr, dataPtr = dataPtr->next) { - if (dataPtr->threadID == curThread) { - break; - } - } - - if (dataPtr == NULL) { - /* No body */ - } else if ( prevPtr == NULL) { - tclMacDataKeyArray[(int) keyVal - 1] = dataPtr->next; - } else { - prevPtr->next = dataPtr->next; - } - - return dataPtr; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ConditionWait -- - * - * This procedure is invoked to wait on a condition variable. - * On the Mac, mutexes are no-ops, and we just yield. After - * all, it is the application's job to loop till the condition - * variable is changed... - * - * - * Results: - * None. - * - * Side effects: - * Will block the current thread till someone else yields. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ConditionWait(condPtr, mutexPtr, timePtr) - Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ - Tcl_Time *timePtr; /* Timeout on waiting period */ -{ - if (TclMacHaveThreads()) { - YieldToAnyThread(); - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ConditionNotify -- - * - * This procedure is invoked to signal a condition variable. - * - * The mutex must be held during this call to avoid races, - * but this interface does not enforce that. - * - * Results: - * None. - * - * Side effects: - * May unblock another thread. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ConditionNotify(condPtr) - Tcl_Condition *condPtr; -{ - if (TclMacHaveThreads()) { - YieldToAnyThread(); - } -} - - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeCondition -- - * - * This procedure is invoked to clean up a condition variable. - * This is only safe to call at the end of time. - * - * This assumes the Master Lock is held. - * - * Results: - * None. - * - * Side effects: - * The condition variable is deallocated. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeCondition(condPtr) - Tcl_Condition *condPtr; -{ - /* Nothing to do on the Mac */ -} - - - -#endif /* TCL_THREADS */ - diff --git a/mac/tclMacThrd.h b/mac/tclMacThrd.h deleted file mode 100644 index 22f2c83..0000000 --- a/mac/tclMacThrd.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * tclUnixThrd.h -- - * - * This header file defines things for thread support. - * - * Copyright (c) 1998 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * SCCS: @(#) - */ - -#ifndef _TCLMACTHRD -#define _TCLMACTHRD - -#ifdef TCL_THREADS - -#endif /* TCL_THREADS */ -#endif /* _TCLMACTHRD */ diff --git a/mac/tclMacTime.c b/mac/tclMacTime.c deleted file mode 100644 index 1a2d1ed..0000000 --- a/mac/tclMacTime.c +++ /dev/null @@ -1,313 +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.3 1999/03/10 05:52:51 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( - TclpTime_t time, /* Time struct to fill. */ - int useGMT) /* True if date should reflect GNT time. */ -{ - const time_t *tp = (const time_t *)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 483780c..0000000 --- a/mac/tclMacUnix.c +++ /dev/null @@ -1,425 +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-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: tclMacUnix.c,v 1.3 1999/04/16 00:47:22 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 - - -/* - *---------------------------------------------------------------------- - * - * 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_WriteChars(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_WriteChars(chan, " ", -1); - } - } - Tcl_WriteChars(chan, "\n", -1); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_LsObjCmd -- - * - * 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_LsObjCmd( - ClientData dummy, /* Not used. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument strings. */ -{ -#define STRING_LENGTH 80 -#define CR '\n' - int i, j; - int fieldLength, len = 0, maxLen = 0, perLine; - 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; - char *argv; - Tcl_Obj *newObjv[2], *resultObjPtr; - - /* - * 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 < objc; i++) { - argv = Tcl_GetString(objv[i]); - if (argv[0] != '-') { - break; - } - - if (!strcmp(argv, "-")) { - i++; - break; - } - - for (j = 1 ; argv[j] ; ++j) { - switch(argv[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; - } - } - } - - objv += i; - objc -= i; - - /* - * No file specifications means we search for all files. - * Glob will be doing most of the work. - */ - if (!objc) { - objc = 1; - newObjv[0] = Tcl_NewStringObj("*", -1); - newObjv[1] = NULL; - objv = newObjv; - } - - if (Tcl_GlobObjCmd(NULL, interp, objc + 1, objv - 1) != TCL_OK) { - Tcl_ResetResult(interp); - return TCL_ERROR; - } - - resultObjPtr = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(resultObjPtr); - if (Tcl_ListObjGetElements(interp, resultObjPtr, &objc, &objv) != TCL_OK) { - Tcl_DecrRefCount(resultObjPtr); - return TCL_ERROR; - } - - Tcl_ResetResult(interp); - - /* - * 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; - Tcl_Obj *objPtr; - char *string; - int length; - - /* - * 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 < objc; i++) { - strcpy(theFile, Tcl_GetString(objv[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); - - } - - objPtr = Tcl_GetObjResult(interp); - string = Tcl_GetStringFromObj(objPtr, &length); - if ((length > 0) && (string[length - 1] == '\n')) { - Tcl_SetObjLength(objPtr, length - 1); - } - } 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 < objc; i++) { - argv = Tcl_GetString(objv[i]); - len = strlen(argv); - if (len > maxLen) { - maxLen = len; - } - } - fieldLength = maxLen + 3; - perLine = STRING_LENGTH / fieldLength; - } - - argCount = 0; - linePos = 0; - memset(theLine, ' ', STRING_LENGTH); - while (argCount < objc) { - strcpy(theFile, Tcl_GetString(objv[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); - } - } - } - - Tcl_DecrRefCount(resultObjPtr); - - 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; -} |
