]> granicus.if.org Git - python/commitdiff
second CoreGraphics batch
authorJust van Rossum <just@letterror.com>
Thu, 13 Dec 2001 13:17:20 +0000 (13:17 +0000)
committerJust van Rossum <just@letterror.com>
Thu, 13 Dec 2001 13:17:20 +0000 (13:17 +0000)
Mac/Modules/cg/CFMLateImport.c [new file with mode: 0755]
Mac/Modules/cg/CFMLateImport.h [new file with mode: 0755]
Mac/Modules/cg/CGStubLib [new file with mode: 0755]
Mac/Modules/cg/CGStubLib.exp [new file with mode: 0755]
Mac/Modules/cg/CGStubLib.readme [new file with mode: 0755]
Mac/Modules/cg/_CGmodule.c [new file with mode: 0755]
Mac/Modules/cg/cgscan.py [new file with mode: 0755]
Mac/Modules/cg/cgsupport.py [new file with mode: 0755]

diff --git a/Mac/Modules/cg/CFMLateImport.c b/Mac/Modules/cg/CFMLateImport.c
new file mode 100755 (executable)
index 0000000..bc2976e
--- /dev/null
@@ -0,0 +1,1360 @@
+/*
+       File:           CFMLateImport.c
+
+       Contains:       Implementation of CFM late import library.
+
+       Written by:     Quinn
+
+       Copyright:      Copyright © 1999 by Apple Computer, Inc., all rights reserved.
+
+                               You may incorporate this Apple sample source code into your program(s) without
+                               restriction. This Apple sample source code has been provided "AS IS" and the
+                               responsibility for its operation is yours. You are not permitted to redistribute
+                               this Apple sample source code as "Apple sample source code" after having made
+                               changes. If you're going to re-distribute the source, we require that you make
+                               it clear in the source that the code was descended from Apple sample source
+                               code, but that you've made changes.
+
+       Change History (most recent first):
+
+        <13>     24/9/01    Quinn   Fixes to compile with C++ activated.
+        <12>     21/9/01    Quinn   [2710489] Fix typo in the comments for FragmentLookup.
+        <11>     21/9/01    Quinn   Changes for CWPro7 Mach-O build.
+        <10>     19/9/01    Quinn   Corrected implementation of kPEFRelocSmBySection. Added
+                                    implementations of kPEFRelocSetPosition and kPEFRelocLgByImport
+                                    (from code contributed by Eric Grant, Ned Holbrook, and Steve
+                                    Kalkwarf), although I can't test them yet.
+         <9>     19/9/01    Quinn   We now handle unpacked data sections, courtesy of some code from
+                                    Ned Holbrook.
+         <8>     19/9/01    Quinn   Minor fixes for the previous checkin. Updated some comments and
+                                    killed some dead code.
+         <7>     19/9/01    Quinn   Simplified API and implementation after a suggestion by Eric
+                                    Grant. You no longer have to CFM export a dummy function; you
+                                    can just pass in the address of your fragment's init routine.
+         <6>     15/2/01    Quinn   Modify compile-time warnings to complain if you try to build
+                                    this module into a Mach-O binary.
+         <5>      5/2/01    Quinn   Removed redundant assignment in CFMLateImportCore.
+         <4>    30/11/00    Quinn   Added comment about future of data symbols in CF.
+         <3>    16/11/00    Quinn   Allow symbol finding via a callback and use that to implement
+                                    CFBundle support.
+         <2>    18/10/99    Quinn   Renamed CFMLateImport to CFMLateImportLibrary to allow for
+                                    possible future API expansion.
+         <1>     15/6/99    Quinn   First checked in.
+*/
+
+// To Do List:
+//
+// o get rid of dependence on ANSI "string.h", but how?
+//
+// Done:
+//
+// Ã investigate alternative APIs, like an external lookup routine
+//   renamed CFMLateImport to CFMLateImportLibrary to allow for
+//   future expansion of the APIs for things like CFMLateImportSymbol
+// Ã test with non-zero fragment offset in the file
+// Ã test more with MPW fragments
+// Ã test data imports
+
+/////////////////////////////////////////////////////////////////
+
+// MoreIsBetter Setup
+
+//#include "MoreSetup.h"
+#define MoreAssert(x) (true)
+#define MoreAssertQ(x)
+
+// Mac OS Interfaces
+
+#if ! MORE_FRAMEWORK_INCLUDES
+       #include <CodeFragments.h>
+       #include <PEFBinaryFormat.h>
+#endif
+
+// Standard C Interfaces
+
+#include <string.h>
+
+// MIB Prototypes
+
+//#include "MoreInterfaceLib.h"
+#define MoreBlockZero BlockZero
+
+// Our Prototypes
+
+#include "CFMLateImport.h"
+
+/////////////////////////////////////////////////////////////////
+
+#if TARGET_RT_MAC_MACHO
+       #error CFMLateImport is not suitable for use in a Mach-O project.
+#elif !TARGET_RT_MAC_CFM || !TARGET_CPU_PPC
+       #error CFMLateImport has not been qualified for 68K or CFM-68K use.
+#endif
+
+/////////////////////////////////////////////////////////////////
+#pragma mark ----- Utility Routines -----
+
+static OSStatus FSReadAtOffset(SInt16 refNum, SInt32 offset, SInt32 count, void *buffer)
+       // A convenient wrapper around PBRead which has two advantages
+       // over FSRead.  First, it takes count as a value parameter.
+       // Second, it reads from an arbitrary offset into the file,
+       // which avoids a bunch of SetFPos calls.
+       //
+       // I guess this should go into "MoreFiles.h", but I'm not sure
+       // how we're going to integrate such a concept into MIB yet.
+{
+       ParamBlockRec pb;
+       
+       pb.ioParam.ioRefNum     = refNum;
+       pb.ioParam.ioBuffer     = (Ptr) buffer;
+       pb.ioParam.ioReqCount   = count;
+       pb.ioParam.ioPosMode    = fsFromStart;
+       pb.ioParam.ioPosOffset  = offset;
+       
+       return PBReadSync(&pb);
+}
+
+/////////////////////////////////////////////////////////////////
+#pragma mark ----- Late Import Engine -----
+
+// This structure represents the core data structure of the late import
+// engine.  It basically holds information about the fragment we're going
+// to fix up.  It starts off with the first three fields, which are
+// provided by the client.  Then, as we procede through the operation,
+// we fill out more fields.
+
+struct FragToFixInfo {
+       CFragSystem7DiskFlatLocator     locator;                                // How to find the fragment's container.
+       CFragConnectionID                       connID;                                 // CFM connection to the fragment.
+       CFragInitFunction                       initRoutine;                    // The CFM init routine for the fragment.
+       PEFContainerHeader                      containerHeader;                // The CFM header, read in from the container.
+       PEFSectionHeader                        *sectionHeaders;                // The CFM section headers.  A pointer block containing an array of containerHeader.sectionCount elements.
+       PEFLoaderInfoHeader                     *loaderSection;                 // The entire CFM loader section in a pointer block.
+       SInt16                                          fileRef;                                // A read-only path to the CFM container.  We keep this here because one that one routine needs to read from the container.
+       void                                            *section0Base;                  // The base address of section 0, which we go through hoops to calculate.
+       void                                            *section1Base;                  // The base address of section 1, which we go through hoops to calculate.
+       Boolean                                         disposeSectionPointers; // See below.
+};
+typedef struct FragToFixInfo FragToFixInfo;
+
+// The disposeSectionPointers Boolean is designed for future cool VM
+// support.  If VM is on, the entire code fragment is file mapped into
+// high memory, including the data we're forced to allocate the
+// sectionHeaders and loaderSection memory blocks to maintain.  If
+// we could find the address of the entire file mapped container,
+// we could access the information directly from there and thus
+// we wouldn't need to allocate (or dispose of) the memory blocks
+// for sectionHeaders and loaderSection.
+//
+// I haven't implemented this yet because a) I'm not sure how to do
+// it with documented APIs, and b) I couldn't be bothered, but
+// disposeSectionPointers remains as vestigial support for the concept.
+
+static OSStatus ReadContainerBasics(FragToFixInfo *fragToFix)
+       // Reads some basic information from the container of the
+       // fragment to fix and stores it in various fields of
+       // fragToFix.  This includes:
+       //
+       // o containerHeader -- The contain header itself.
+       // o sectionHeaders  -- The array of section headers (in a newly allocated pointer block).
+       // o loaderSection   -- The entire loader section (in a newly allocated pointer block).
+       //
+       // Also sets disposeSectionPointers to indicate whether
+       // the last two pointers should be disposed of.
+       //
+       // Finally, it leaves the container file open for later
+       // folks who want to read data from it.
+{
+       OSStatus        err;
+       UInt16          sectionIndex;
+       Boolean         found;
+
+       MoreAssertQ(fragToFix != nil);
+       MoreAssertQ(fragToFix->locator.fileSpec != nil);
+       MoreAssertQ(fragToFix->connID != nil);
+       MoreAssertQ(fragToFix->loaderSection == nil);
+       MoreAssertQ(fragToFix->sectionHeaders == nil);
+       MoreAssertQ(fragToFix->fileRef == 0);
+       
+       fragToFix->disposeSectionPointers = true;
+       
+       // Open up the file, read the container head, then read in
+       // all the section headers, then go looking through the
+       // section headers for the loader section (PEF defines
+       // that there can be only one).
+       
+       err = FSpOpenDF(fragToFix->locator.fileSpec, fsRdPerm, &fragToFix->fileRef);
+       if (err == noErr) {
+               err = FSReadAtOffset(fragToFix->fileRef,
+                                                               fragToFix->locator.offset,
+                                                               sizeof(fragToFix->containerHeader),
+                                                               &fragToFix->containerHeader);
+               if (err == noErr) {
+                       if (   fragToFix->containerHeader.tag1 != kPEFTag1
+                               || fragToFix->containerHeader.tag2 != kPEFTag2
+                               || fragToFix->containerHeader.architecture != kCompiledCFragArch
+                               || fragToFix->containerHeader.formatVersion != kPEFVersion) {
+                               err = cfragFragmentFormatErr;
+                       }
+               }
+               if (err == noErr) {
+                       fragToFix->sectionHeaders = (PEFSectionHeader *) NewPtr(fragToFix->containerHeader.sectionCount * sizeof(PEFSectionHeader));
+                       err = MemError();
+               }
+               if (err == noErr) {
+                       err = FSReadAtOffset(fragToFix->fileRef,
+                                                                       fragToFix->locator.offset + sizeof(fragToFix->containerHeader),
+                                                                       fragToFix->containerHeader.sectionCount * sizeof(PEFSectionHeader), 
+                                                                       fragToFix->sectionHeaders);
+               }
+               if (err == noErr) {
+                       sectionIndex = 0;
+                       found = false;
+                       while ( sectionIndex < fragToFix->containerHeader.sectionCount && ! found ) {
+                               found = (fragToFix->sectionHeaders[sectionIndex].sectionKind == kPEFLoaderSection);
+                               if ( ! found ) {
+                                       sectionIndex += 1;
+                               }
+                       }
+               }
+               if (err == noErr && ! found) {
+                       err = cfragNoSectionErr;
+               }
+               
+               // Now read allocate a pointer block and read the loader section into it.
+               
+               if (err == noErr) {
+                       fragToFix->loaderSection = (PEFLoaderInfoHeader *) NewPtr(fragToFix->sectionHeaders[sectionIndex].containerLength);
+                       err = MemError();
+               }
+               if (err == noErr) {
+                       err = FSReadAtOffset(fragToFix->fileRef, 
+                                                                       fragToFix->locator.offset + fragToFix->sectionHeaders[sectionIndex].containerOffset,
+                                                                       fragToFix->sectionHeaders[sectionIndex].containerLength, 
+                                                                       fragToFix->loaderSection);
+               }                               
+       }
+       
+       // No clean up.  The client must init fragToFix to zeros and then
+       // clean up regardless of whether we return an error.
+               
+       return err;
+}
+
+static UInt32 DecodeVCountValue(const UInt8 *start, UInt32 *outCount)
+       // Given a pointer to the start of a variable length PEF value, 
+       // work out the value (in *outCount).  Returns the number of bytes 
+       // consumed by the value.
+{
+       UInt8 *                 bytePtr;
+       UInt8                   byte;
+       UInt32                  count;
+       
+       bytePtr = (UInt8 *)start;
+       
+       // Code taken from "PEFBinaryFormat.h".
+       count = 0;
+       do {
+               byte = *bytePtr++;
+               count = (count << kPEFPkDataVCountShift) | (byte & kPEFPkDataVCountMask);
+       } while ((byte & kPEFPkDataVCountEndMask) != 0);
+       
+       *outCount = count;
+       return bytePtr - start;
+}
+
+static UInt32 DecodeInstrCountValue(const UInt8 *inOpStart, UInt32 *outCount)
+       // Given a pointer to the start of an opcode (inOpStart), work out the 
+       // count argument for that opcode (*outCount).  Returns the number of 
+       // bytes consumed by the opcode and count combination.
+{
+       MoreAssertQ(inOpStart != nil);
+       MoreAssertQ(outCount  != nil);
+       
+       if (PEFPkDataCount5(*inOpStart) != 0)
+       {
+               // Simple case, count encoded in opcode.
+               *outCount = PEFPkDataCount5(*inOpStart);
+               return 1;
+       }
+       else
+       {
+               // Variable-length case.
+               return 1 + DecodeVCountValue(inOpStart + 1, outCount);
+       }
+}
+
+static OSStatus UnpackPEFDataSection(const UInt8 * const packedData,   UInt32 packedSize,
+                                                                          UInt8 * const unpackedData, UInt32 unpackedSize)
+{
+       OSErr                   err;
+       UInt32                  offset;
+       UInt8                   opCode;
+       UInt8 *                 unpackCursor;
+       
+       MoreAssertQ(packedData != nil);
+       MoreAssertQ(unpackedData != nil);
+       MoreAssertQ(unpackedSize >= packedSize);
+
+       // The following asserts assume that the client allocated the memory with NewPtr, 
+       // which may not always be true.  However, the asserts' value in preventing accidental 
+       // memory block overruns outweighs the possible maintenance effort.
+       
+       MoreAssertQ( packedSize   == GetPtrSize( (Ptr) packedData  ) );
+       MoreAssertQ( unpackedSize == GetPtrSize( (Ptr) unpackedData) );
+       
+       err          = noErr;
+       offset       = 0;
+       unpackCursor = unpackedData;
+       while (offset < packedSize) {
+               MoreAssertQ(unpackCursor < &unpackedData[unpackedSize]);
+               
+               opCode = packedData[offset];
+               
+               switch (PEFPkDataOpcode(opCode)) {
+                       case kPEFPkDataZero:
+                               {
+                                       UInt32  count;
+                                       
+                                       offset += DecodeInstrCountValue(&packedData[offset], &count);
+                                       
+                                       MoreBlockZero(unpackCursor, count);
+                                       unpackCursor += count;
+                               }
+                               break;
+                       
+                       case kPEFPkDataBlock:
+                               {
+                                       UInt32  blockSize;
+                                       
+                                       offset += DecodeInstrCountValue(&packedData[offset], &blockSize);
+                                       
+                                       BlockMoveData(&packedData[offset], unpackCursor, blockSize);
+                                       unpackCursor += blockSize;
+                                       offset += blockSize;
+                               }
+                               break;
+                       
+                       case kPEFPkDataRepeat:
+                               {
+                                       UInt32  blockSize;
+                                       UInt32  repeatCount;
+                                       UInt32  loopCounter;
+                                       
+                                       offset += DecodeInstrCountValue(&packedData[offset], &blockSize);
+                                       offset += DecodeVCountValue(&packedData[offset], &repeatCount);
+                                       repeatCount += 1;       // stored value is (repeatCount - 1)
+                                       
+                                       for (loopCounter = 0; loopCounter < repeatCount; loopCounter++) {
+                                               BlockMoveData(&packedData[offset], unpackCursor, blockSize);
+                                               unpackCursor += blockSize;
+                                       }
+                                       offset += blockSize;
+                               }
+                               break;
+                       
+                       case kPEFPkDataRepeatBlock:
+                               {
+                                       UInt32  commonSize;
+                                       UInt32  customSize;
+                                       UInt32  repeatCount;
+                                       const UInt8 *commonData;
+                                       const UInt8 *customData;
+                                       UInt32 loopCounter;
+                                       
+                                       offset += DecodeInstrCountValue(&packedData[offset], &commonSize);
+                                       offset += DecodeVCountValue(&packedData[offset], &customSize);
+                                       offset += DecodeVCountValue(&packedData[offset], &repeatCount);
+                                       
+                                       commonData = &packedData[offset];
+                                       customData = &packedData[offset + commonSize];
+                                       
+                                       for (loopCounter = 0; loopCounter < repeatCount; loopCounter++) {
+                                               BlockMoveData(commonData, unpackCursor, commonSize);
+                                               unpackCursor += commonSize;
+                                               BlockMoveData(customData, unpackCursor, customSize);
+                                               unpackCursor += customSize;
+                                               customData += customSize;
+                                       }
+                                       BlockMoveData(commonData, unpackCursor, commonSize);
+                                       unpackCursor += commonSize;
+                                       offset += (repeatCount * (commonSize + customSize)) + commonSize;
+                               }
+                               break;
+                       
+                       case kPEFPkDataRepeatZero:
+                               {
+                                       UInt32  commonSize;
+                                       UInt32  customSize;
+                                       UInt32  repeatCount;
+                                       const UInt8 *customData;
+                                       UInt32 loopCounter;
+                                       
+                                       offset += DecodeInstrCountValue(&packedData[offset], &commonSize);
+                                       offset += DecodeVCountValue(&packedData[offset], &customSize);
+                                       offset += DecodeVCountValue(&packedData[offset], &repeatCount);
+                                       
+                                       customData = &packedData[offset];
+                                       
+                                       for (loopCounter = 0; loopCounter < repeatCount; loopCounter++) {
+                                               MoreBlockZero(unpackCursor, commonSize);
+                                               unpackCursor += commonSize;
+                                               BlockMoveData(customData, unpackCursor, customSize);
+                                               unpackCursor += customSize;
+                                               customData += customSize;
+                                       }
+                                       MoreBlockZero(unpackCursor, commonSize);
+                                       unpackCursor += commonSize;
+                                       offset += repeatCount * customSize;
+                               }
+                               break;
+                       
+                       default:
+                               #if MORE_DEBUG
+                                       DebugStr("\pUnpackPEFDataSection: Unexpected data opcode");
+                               #endif
+                               err = cfragFragmentCorruptErr;
+                               goto leaveNow;
+                               break;
+               }
+       }
+       
+leaveNow:
+       return err;
+}
+
+/*     SetupSectionBaseAddresses Rationale
+       -----------------------------------
+       
+       OK, here's where things get weird.  In order to run the relocation
+       engine, I need to be able to find the base address of an instantiated
+       section of the fragment we're fixing up given only its section number.
+       This isn't hard for CFM to do because it's the one that instantiated the
+       sections in the first place.  It's surprisingly difficult to do if
+       you're not CFM.  [And you don't have access to the private CFM APis for 
+       doing it.]
+       
+       [Alan Lillich is going to kill me when he reads this!  I should point out
+        that TVector's don't have to contain two words, they can be longer,
+        and that the second word isn't necessarily a TOC pointer, it's
+        just that the calling conventions require that it be put in the
+        TOC register when the code is called.
+        
+        Furthermore, the code section isn't always section 0, and the data
+        section isn't always section 1, and there can be zero to many sections
+        of each type.
+        
+        But these niceties are besides the point: I'm doing something tricky 
+        because I don't have a nice API for getting section base addresses.  
+        If I had a nice API for doing that, none of this code would exist.
+       ]
+
+       The technique is very sneaky (thanks to Eric Grant).  The fragment to 
+       fix necessarily has a CFM init routine (because it needs that routine 
+       in order to capture the fragment location and connection ID).  Thus the 
+       fragment to fix must have a TVector in its data section.  TVectors are 
+       interesting because they're made up of two words.  The first is a pointer 
+       to the code that implements the routine; the second is a pointer to the TOC
+       for the fragment that's exporting the TVector.  How TVectors are
+       created is interesting too.  On disk, a TVector consists of two words,
+       the first being the offset from the start of the code section to the
+       routine, the second being the offset from the start of the data section
+       to the TOC base.  When CFM prepares a TVector, it applies the following
+       transform:
+       
+               tvector.codePtr = tvector.codeOffset + base of code section
+               tvector.tocPtr  = tvector.tocOffset  + base of data section
+               
+       Now, you can reverse these questions to make them:
+       
+               base of code section = tvector.codePtr - tvector.codeOffset
+               base of data section = tvector.dataPtr - tvector.dataOffset
+       
+       So if you can find the relocated contents of the TVector and
+       find the original offsets that made up the TVector, you can then
+       calculate the base address of both the code and data sections.
+       
+       Finding the relocated contents of the TVector is easy; I simply 
+       require the client to pass in a pointer to its init routine. 
+       A routine pointer is a TVector pointer, so you can just cast it 
+       and extract the pair of words.
+
+       Finding the original offsets is a trickier.  My technique is to
+       look up the init routine in the fragment's loader info header.  This
+       yields the section number and offset where the init routine's unrelocated 
+       TVector exists.  Once I have that, I can just read the unrelocated TVector
+       out of the file and extract the offsets.
+*/
+
+struct TVector {
+       void *codePtr;
+       void *tocPtr;
+};
+typedef struct TVector TVector;
+
+static OSStatus SetupSectionBaseAddresses(FragToFixInfo *fragToFix)
+       // This routine initialises the section0Base and section1Base
+       // base fields of fragToFix to the base addresses of the
+       // instantiated fragment represented by the other fields
+       // of fragToFix.  The process works in three states:
+       //
+       // 1.   Find the contents of the relocated TVector of the 
+       //      fragment's initialisation routine, provided to us by 
+       //      the caller.
+       //
+       // 2.   Find the contents of the non-relocated TVector by 
+       //      looking it up in the PEF loader info header and then 
+       //      using that to read the TVector contents from disk.
+       //      This yields the offsets from the section bases for 
+       //      the init routine.
+       //
+       // 3.   Subtract 2 from 3.
+{
+       OSStatus                        err;
+       TVector *                       relocatedExport;
+       SInt32                          initSection;
+       UInt32                          initOffset;
+       PEFSectionHeader *      initSectionHeader;
+       Ptr                                     packedDataSection;
+       Ptr                                     unpackedDataSection;
+       TVector                         originalOffsets;
+
+       packedDataSection   = nil;
+       unpackedDataSection = nil;
+       
+       // Step 1.
+
+       // First find the init routine's TVector, which gives us the relocated 
+       // offsets of the init routine into the data and code sections.
+
+       relocatedExport = (TVector *) fragToFix->initRoutine;
+               
+       // Step 2.
+       
+       // Now find the init routine's TVector's offsets in the data section on 
+       // disk.  This gives us the raw offsets from the data and code section 
+       // of the beginning of the init routine.
+       
+       err = noErr;
+       initSection = fragToFix->loaderSection->initSection;
+       initOffset  = fragToFix->loaderSection->initOffset;
+       if (initSection == -1) {
+               err = cfragFragmentUsageErr;
+       }
+       if (err == noErr) {
+               MoreAssertQ( initSection >= 0 );                // Negative indexes are pseudo-sections which are just not allowed!
+               MoreAssertQ( initSection < fragToFix->containerHeader.sectionCount );
+
+               initSectionHeader = &fragToFix->sectionHeaders[initSection];
+               
+               // If the data section is packed, unpack it to a temporary buffer and then get the 
+               // original offsets from that buffer.  If the data section is unpacked, just read 
+               // the original offsets directly off the disk.
+               
+               if ( initSectionHeader->sectionKind == kPEFPackedDataSection ) {
+
+                       // Allocate space for packed and unpacked copies of the section.
+                       
+                       packedDataSection = NewPtr(initSectionHeader->containerLength);
+                       err = MemError();
+
+                       if (err == noErr) {
+                               unpackedDataSection = NewPtr(initSectionHeader->unpackedLength);
+                               err = MemError();
+                       }
+
+                       // Read the contents of the packed section.
+                       
+                       if (err == noErr) {
+                               err = FSReadAtOffset(   fragToFix->fileRef,
+                                                                               fragToFix->locator.offset
+                                                                               + initSectionHeader->containerOffset,
+                                                                               initSectionHeader->containerLength,
+                                                                               packedDataSection);
+                       }
+                       
+                       // Unpack the data into the unpacked section.
+                       
+                       if (err == noErr) {
+                               err = UnpackPEFDataSection( (UInt8 *) packedDataSection,   initSectionHeader->containerLength,
+                                                                           (UInt8 *) unpackedDataSection, initSectionHeader->unpackedLength);
+                       }
+                       
+                       // Extract the init routine's TVector from the unpacked section.
+                       
+                       if (err == noErr) {
+                               BlockMoveData(unpackedDataSection + initOffset, &originalOffsets, sizeof(TVector));
+                       }
+                       
+               } else {
+                       MoreAssertQ(fragToFix->sectionHeaders[initSection].sectionKind == kPEFUnpackedDataSection);
+                       err = FSReadAtOffset(fragToFix->fileRef, 
+                                                                       fragToFix->locator.offset
+                                                                       + fragToFix->sectionHeaders[initSection].containerOffset
+                                                                       + initOffset,
+                                                                       sizeof(TVector), 
+                                                                       &originalOffsets);
+               }
+       }
+
+       // Step 3.
+               
+       // Do the maths to subtract the unrelocated offsets from the current address 
+       // to get the base address.
+       
+       if (err == noErr) {
+               fragToFix->section0Base = ((char *) relocatedExport->codePtr) - (UInt32) originalOffsets.codePtr;
+               fragToFix->section1Base = ((char *) relocatedExport->tocPtr)  - (UInt32) originalOffsets.tocPtr;
+       }
+       
+       // Clean up.
+       
+       if (packedDataSection != nil) {
+               DisposePtr(packedDataSection);
+               MoreAssertQ( MemError() == noErr );
+       }
+       if (unpackedDataSection != nil) {
+               DisposePtr(unpackedDataSection);
+               MoreAssertQ( MemError() == noErr );
+       }
+       return err;
+}
+
+static void *GetSectionBaseAddress(const FragToFixInfo *fragToFix, UInt16 sectionIndex)
+       // This routine returns the base of the instantiated section
+       // whose index is sectionIndex.  This routine is the evil twin
+       // of SetupSectionBaseAddresses.  It simply returns the values
+       // for section 0 and 1 that we derived in SetupSectionBaseAddresses.
+       // In a real implementation, this routine would call CFM API
+       // to get this information, and SetupSectionBaseAddresses would
+       // not exist, but CFM does not export the necessary APIs to
+       // third parties.
+{
+       void *result;
+       
+       MoreAssertQ(fragToFix != nil);
+       MoreAssertQ(fragToFix->containerHeader.tag1 == kPEFTag1);
+       
+       switch (sectionIndex) {
+               case 0:
+                       result = fragToFix->section0Base;
+                       break;
+               case 1:
+                       result = fragToFix->section1Base;
+                       break;
+               default:
+                       result = nil;
+                       break;
+       }
+       return result;
+}
+
+
+static OSStatus FindImportLibrary(PEFLoaderInfoHeader *loaderSection, const char *libraryName, PEFImportedLibrary **importLibrary)
+       // This routine finds the import library description (PEFImportedLibrary)
+       // for the import library libraryName in the PEF loader section.
+       // It sets *importLibrary to the address of the description.
+{
+       OSStatus                        err;
+       UInt32                          librariesRemaining;
+       PEFImportedLibrary      *thisImportLibrary;
+       Boolean                         found;
+       
+       MoreAssertQ(loaderSection != nil);
+       MoreAssertQ(libraryName != nil);
+       MoreAssertQ(importLibrary != nil);
+       
+       // Loop through each import library looking for a matching name.
+       
+       // Initialise thisImportLibrary to point to the byte after the
+       // end of the loader section's header.
+       
+       thisImportLibrary = (PEFImportedLibrary *) (loaderSection + 1);
+       librariesRemaining = loaderSection->importedLibraryCount;
+       found = false;
+       while ( librariesRemaining > 0 && ! found ) {
+               // PEF defines that import library names will have
+               // a null terminator, so we can just use strcmp.
+               found = (strcmp( libraryName,
+                                               ((char *)loaderSection)
+                                               + loaderSection->loaderStringsOffset 
+                                               + thisImportLibrary->nameOffset) == 0);
+               // *** Remove ANSI strcmp eventually.
+               if ( ! found ) {
+                       thisImportLibrary += 1;
+                       librariesRemaining -= 1;
+               }
+       }
+       
+       if (found) {
+               *importLibrary = thisImportLibrary;
+               err = noErr;
+       } else {
+               *importLibrary = nil;
+               err = cfragNoLibraryErr;
+       }
+       return err;
+}
+
+static OSStatus LookupSymbol(CFMLateImportLookupProc lookup, void *refCon,
+                                                       PEFLoaderInfoHeader *loaderSection,
+                                                       UInt32 symbolIndex,
+                                                       UInt32 *symbolValue)
+       // This routine is used to look up a symbol during relocation.
+       // "lookup" is a client callback and refCon is its argument.
+       // Typically refCon is the CFM connection to the library that is
+       // substituting for the weak linked library.  loaderSection
+       // is a pointer to the loader section of the fragment to fix up.
+       // symbolIndex is the index of the imported symbol in the loader section.
+       // The routine sets the word pointed to by symbolValue to the
+       // value of the symbol.
+       //
+       // The routine works by using symbolIndex to index into the imported
+       // symbol table to find the offset of the symbol's name in the string
+       // table.  It then looks up the symbol by calling the client's "lookup"
+       // function and passes the resulting symbol address back in symbolValue.
+{
+       OSStatus                        err;
+       UInt32                          *importSymbolTable;
+       UInt32                          symbolStringOffset;
+       Boolean                         symbolIsWeak;
+       CFragSymbolClass        symbolClass;
+       char                            *symbolStringAddress;
+       Str255                          symbolString;
+       
+       MoreAssertQ(lookup != nil);
+       MoreAssertQ(loaderSection != nil);
+       MoreAssertQ(symbolIndex < loaderSection->totalImportedSymbolCount);
+       MoreAssertQ(symbolValue != nil);
+       
+       // Find the base of the imported symbol table.
+       
+       importSymbolTable = (UInt32 *)(((char *)(loaderSection + 1)) + (loaderSection->importedLibraryCount * sizeof(PEFImportedLibrary)));
+       
+       // Grab the appropriate entry out of the table and
+       // extract the information from that entry.
+       
+       symbolStringOffset = importSymbolTable[symbolIndex];
+       symbolClass = PEFImportedSymbolClass(symbolStringOffset);
+       symbolIsWeak = ((symbolClass & kPEFWeakImportSymMask) != 0);
+       symbolClass = symbolClass & ~kPEFWeakImportSymMask;
+       symbolStringOffset = PEFImportedSymbolNameOffset(symbolStringOffset);
+       
+       // Find the string for the symbol in the strings table and
+       // extract it from the table into a Pascal string on the stack.
+       
+       symbolStringAddress = ((char *)loaderSection) + loaderSection->loaderStringsOffset + symbolStringOffset;
+       symbolString[0] = strlen(symbolStringAddress);          // *** remove ANSI strlen
+       BlockMoveData(symbolStringAddress, &symbolString[1], symbolString[0]);
+       
+       // Look up the symbol in substitute library.  If it fails, return
+       // a 0 value and check whether the error is fatal (a strong linked
+       // symbol) or benign (a weak linked symbol).
+       
+       err = lookup(symbolString, symbolClass, (void **) symbolValue, refCon);
+       if (err != noErr) {
+               *symbolValue = 0;
+               if (symbolIsWeak) {
+                       err = noErr;
+               }
+       }
+       return err;
+}
+
+// The EngineState structure encapsulates all of the persistent state
+// of the CFM relocation engine virtual machine.  I originally defined
+// this structure so I could pass the state around between routines
+// that implement various virtual opcodes, however I later worked
+// out that the relocation was sufficiently simple that I could put it
+// in in one routine.  Still, I left the state in this structure in
+// case I ever need to reverse that decision.  It's also a convenient
+// instructional design.
+
+struct EngineState {
+       UInt32 currentReloc;            // Index of current relocation opcodes
+       UInt32 terminatingReloc;        // Index of relocation opcodes which terminates relocation
+       UInt32 *sectionBase;            // Start of the section
+       UInt32 *relocAddress;           // Address within the section where the relocations are to be performed
+       UInt32 importIndex;                     // Symbol index, which is used to access an imported symbol's address
+       void  *sectionC;                        // Memory address of an instantiated section within the PEF container; this variable is used by relocation opcodes that relocate section addresses
+       void  *sectionD;                        // Memory address of an instantiated section within the PEF container; this variable is used by relocation opcodes that relocate section addresses
+};
+typedef struct EngineState EngineState;
+
+// Note:
+// If I ever have to support the repeat opcodes, I'll probably
+// have to add a repeat counter to EngineState.
+
+static OSStatus InitEngineState(const FragToFixInfo *fragToFix,
+                                                               UInt16 relocHeaderIndex,
+                                                               EngineState *state)
+       // This routine initialises the engine state suitably for
+       // running the relocation opcodes for the section whose
+       // index is relocHeaderIndex.  relocHeaderIndex is not a
+       // a section number.  See the comment where it's used below
+       // for details.  The routine basically fills out all the fields
+       // in the EngineState structure as described by
+       // "Mac OS Runtime Architectures".
+{
+       OSStatus err;
+       PEFLoaderRelocationHeader *relocHeader;
+       
+       MoreAssertQ(fragToFix != nil);
+       MoreAssertQ(state != nil);
+
+       // This bit is tricky.  relocHeaderIndex is an index into the relocation
+       // header table, starting at relocSectionCount (which is in the loader
+       // section header) for the first relocated section and decrementing
+       // down to 1 for the last relocated section.  I find the relocation
+       // header by using relocHeaderIndex as a index backwards from the
+       // start of the relocation opcodes (ie relocInstrOffset).  If you
+       // look at the diagram of the layout of the container in
+       // "PEFBinaryFormat.h", you'll see that the relocation opcodes
+       // immediately follow the relocation headers.
+       //
+       // I did this because the alternative (starting at the loader
+       // header and stepping past the import library table and the
+       // import symbol table) was a pain.
+
+       relocHeader = (PEFLoaderRelocationHeader *) (((char *) fragToFix->loaderSection) + fragToFix->loaderSection->relocInstrOffset - relocHeaderIndex * sizeof(PEFLoaderRelocationHeader));
+       
+       MoreAssertQ(relocHeader->reservedA == 0);               // PEF spec says it must be; we check to try to catch bugs in calculation of relocHeader
+       
+       state->currentReloc = relocHeader->firstRelocOffset;
+       state->terminatingReloc = relocHeader->firstRelocOffset + relocHeader->relocCount;
+       state->sectionBase = (UInt32 *) GetSectionBaseAddress(fragToFix, relocHeader->sectionIndex);
+       state->relocAddress = state->sectionBase;
+       state->importIndex = 0;
+
+       // From "Mac OS Runtime Architectures":
+       //
+       // The sectionC and sectionD variables actually contain the
+       // memory address of an instantiated section minus the
+       // default address for that section. The default address for a
+       // section is contained in the defaultAddress field of the
+       // section header. However, in almost all cases the default
+       // address should be 0, so the simplified definition suffices.
+       // 
+       // In the debug version, we drop into MacsBug if this weird case
+       // ever executes because it's more likely we made a mistake than
+       // we encountered a section with a default address.
+
+       state->sectionC = GetSectionBaseAddress(fragToFix, 0);
+       if (state->sectionC != nil) {
+               #if MORE_DEBUG
+                       if (fragToFix->sectionHeaders[0].defaultAddress != 0) {
+                               DebugStr("\pInitEngineState: Executing weird case.");
+                       }
+               #endif
+               (char *) state->sectionC -= fragToFix->sectionHeaders[0].defaultAddress;
+       }
+       state->sectionD = GetSectionBaseAddress(fragToFix, 1);
+       if (state->sectionD != nil) {
+               #if MORE_DEBUG
+                       if (fragToFix->sectionHeaders[1].defaultAddress != 0) {
+                               DebugStr("\pInitEngineState: Executing weird case.");
+                       }
+               #endif
+               (char *) state->sectionD -= fragToFix->sectionHeaders[1].defaultAddress;
+       }
+
+       err = noErr;
+       if (state->relocAddress == nil) {
+               err = cfragFragmentUsageErr;
+       }
+       return err;
+}
+
+// kPEFRelocBasicOpcodes is a table that maps the top 7 bits of the opcode
+// to a fundamental action.  It's contents are defined for me in "PEFBinaryFormat.h",
+// which is really convenient.
+
+static UInt8 kPEFRelocBasicOpcodes[kPEFRelocBasicOpcodeRange] = { PEFMaskedBasicOpcodes };
+
+static OSStatus RunRelocationEngine(const FragToFixInfo *fragToFix, 
+                                                                               PEFImportedLibrary  *importLibrary, 
+                                                                               CFMLateImportLookupProc lookup, void *refCon)
+       // This is where the rubber really hits the.  Given a fully
+       // populated fragToFix structure, the import library description
+       // of the weak imported library we're resolving, and a connection
+       // to the library we're going to substitute it, re-execute the
+       // relocation instructions (CFM has already executed them once)
+       // but only *do* instructions (ie store the change to the data section)
+       // that CFM skipped because the weak symbols were missing.
+{
+       OSStatus        err;
+       EngineState     state;
+       UInt16          sectionsLeftToRelocate;
+       UInt32          totalRelocs;
+       UInt16          *relocInstrTable;
+       UInt16          opCode;
+       
+       MoreAssertQ(fragToFix != nil);
+       MoreAssertQ(fragToFix->containerHeader.tag1 == kPEFTag1);
+       MoreAssertQ(fragToFix->sectionHeaders != nil);
+       MoreAssertQ(fragToFix->loaderSection != nil);
+       MoreAssertQ(fragToFix->section0Base != nil);    // Technically, having a nil for these two is not a problem, ...
+       MoreAssertQ(fragToFix->section1Base != nil);    // but in practise it a wildly deviant case and we should know about it.
+       MoreAssertQ(importLibrary != nil);
+       MoreAssertQ(lookup != nil);
+
+       // Before entering the loop, work out some information in advance.
+
+       // totalRelocs is only used for debugging, to make sure our
+       // relocation PC (state.currentReloc) doesn't run wild.
+       
+       totalRelocs = (fragToFix->loaderSection->loaderStringsOffset - fragToFix->loaderSection->relocInstrOffset) / sizeof(UInt16);
+       
+       // relocInstrTable is the base address of the table of relocation
+       // instructions in the fragment to fix.
+       
+       relocInstrTable = (UInt16 *)((char *) fragToFix->loaderSection + fragToFix->loaderSection->relocInstrOffset);
+       
+       // sectionsLeftToRelocate is the loop counter for the outer loop.
+       
+       MoreAssertQ(fragToFix->loaderSection->relocSectionCount <= 0x0FFFF);
+       sectionsLeftToRelocate = fragToFix->loaderSection->relocSectionCount;
+
+       // Now let's run the relocation engine.  We run it once per
+       // section in the table.  Each time around, we init the engine
+       // and then loop again, this time executing individual opcodes.
+       // The opcode loop terminates when the relocation PC
+       // (state.currentReloc) hits the final opcode (state.terminatingReloc).
+       
+       // Note:
+       // One design decision I made was to totally re-init the engine state
+       // for each section.  The CFM spec is unclear as to whether you're supposed
+       // to totally re-init the engine state, or just re-init the section-specific
+       // state (ie currentReloc, terminatingReloc, and relocAddress).  I hope this
+       // is correct, but it's hard to test without having a fragment with multiple
+       // relocated sections, which is difficult to create.
+       
+       // How do I decide which opcodes should be effective (ie make changes to
+       // the section being relocated) and which opcodes should just be executed
+       // for their side effects (ie updated state.relocAddress or state.importIndex)?
+       // The answer is both simple and subtle.  Opcodes whose actions are dependent
+       // on a symbol that was in the weak linked library are effective, those that
+       // an independent of those symbols are not.  The only opcodes that use
+       // symbolic values are kPEFRelocImportRun and kPEFRelocSmByImport, and
+       // these are only if the symbol is in the weak linked library.
+       // All other cases are executed for their side effects only.
+       //
+       // How do I determine if a symbol is in the weak linked library?
+       // Well I know the symbol's index and I know the lower bound and count
+       // of the symbols in the weak linked library, so I just do a simple
+       // bounds test, ie 
+       //
+       //   firstImportedSymbol <= importIndex < firstImportedSymbol + importedSymbolCount
+
+       // From this code, it's relatively easy to see which relocation opcodes
+       // aren't implemented.  If you ever encounter one, you'll find yourself
+       // in MacsBug with a message telling you which opcode was found.  The
+       // two big groups of opcodes I skipped were the large format opcodes
+       // and the repeating opcodes.  I skipped them because:
+       //
+       // a) I haven't got a way to generate them in a PEF container that I can 
+       //    test against. Without that, there's no way I could be assured that
+       //    the code worked.
+       //
+       // b) I'm lazy.
+
+       err = noErr;
+       while ( sectionsLeftToRelocate > 0 ) {
+               err = InitEngineState(fragToFix, sectionsLeftToRelocate, &state);
+               if (err != noErr) {
+                       goto leaveNow;
+               }
+               
+               while ( state.currentReloc != state.terminatingReloc ) {
+                       
+                       MoreAssertQ( state.currentReloc < totalRelocs );
+
+                       opCode = relocInstrTable[state.currentReloc];
+                       switch ( PEFRelocBasicOpcode(opCode) ) {
+                               case kPEFRelocBySectDWithSkip:
+                                       {
+                                               UInt16 skipCount;
+                                               UInt16 relocCount;
+                                               
+                                               skipCount = ((opCode >> 6) & 0x00FF);
+                                               relocCount = (opCode & 0x003F);
+                                               state.relocAddress += skipCount;
+                                               state.relocAddress += relocCount;
+                                       }
+                                       break;
+                               case kPEFRelocBySectC:
+                               case kPEFRelocBySectD:
+                                       {
+                                               UInt16 runLength;
+
+                                               runLength = (opCode & 0x01FF) + 1;
+                                               state.relocAddress += runLength;
+                                       }
+                                       break;
+                               case kPEFRelocTVector12:
+                                       {
+                                               UInt16 runLength;
+
+                                               runLength = (opCode & 0x01FF) + 1;
+                                               state.relocAddress += (runLength * 3);
+                                       }
+                                       break;
+                               case kPEFRelocTVector8:
+                               case kPEFRelocVTable8:
+                                       {
+                                               UInt16 runLength;
+
+                                               runLength = (opCode & 0x01FF) + 1;
+                                               state.relocAddress += (runLength * 2);
+                                       }
+                                       break;
+                               case kPEFRelocImportRun:
+                                       {
+                                               UInt32 symbolValue;
+                                               UInt16 runLength;
+                                               
+                                               runLength = (opCode & 0x01FF) + 1;
+                                               while (runLength > 0) {
+                                                       if ( state.importIndex >= importLibrary->firstImportedSymbol && state.importIndex < (importLibrary->firstImportedSymbol + importLibrary->importedSymbolCount) ) {
+                                                               err = LookupSymbol(lookup, refCon, fragToFix->loaderSection, state.importIndex, &symbolValue);
+                                                               if (err != noErr) {
+                                                                       goto leaveNow;
+                                                               }
+                                                               *(state.relocAddress) += symbolValue;
+                                                       }
+                                                       state.importIndex += 1;
+                                                       state.relocAddress += 1;
+                                                       runLength -= 1;
+                                               }
+                                       }
+                                       break;
+                               case kPEFRelocSmByImport:
+                                       {
+                                               UInt32 symbolValue;
+                                               UInt32 index;
+
+                                               index = (opCode & 0x01FF);
+                                               if ( index >= importLibrary->firstImportedSymbol && index < (importLibrary->firstImportedSymbol + importLibrary->importedSymbolCount) ) {
+                                                       err = LookupSymbol(lookup, refCon, fragToFix->loaderSection, index, &symbolValue);
+                                                       if (err != noErr) {
+                                                               goto leaveNow;
+                                                       }
+                                                       *(state.relocAddress) += symbolValue;
+                                               }
+                                               state.importIndex = index + 1;
+                                               state.relocAddress += 1;
+                                       }
+                                       break;
+                               case kPEFRelocSmSetSectC:
+                                       {
+                                               UInt32 index;
+
+                                               index = (opCode & 0x01FF);
+                                               state.sectionC = GetSectionBaseAddress(fragToFix, index);
+                                               MoreAssertQ(state.sectionC != nil);
+                                       }
+                                       break;
+                               case kPEFRelocSmSetSectD:
+                                       {
+                                               UInt32 index;
+
+                                               index = (opCode & 0x01FF);
+                                               state.sectionD = GetSectionBaseAddress(fragToFix, index);
+                                               MoreAssertQ(state.sectionD != nil);
+                                       }
+                                       break;
+                               case kPEFRelocSmBySection:
+                                       state.relocAddress += 1;
+                                       break;
+                               case kPEFRelocIncrPosition:
+                                       {
+                                               UInt16 offset;
+                                               
+                                               offset = (opCode & 0x0FFF) + 1;
+                                               ((char *) state.relocAddress) += offset;
+                                       }
+                                       break;
+                               case kPEFRelocSmRepeat:
+                                       #if MORE_DEBUG
+                                               DebugStr("\pRunRelocationEngine: kPEFRelocSmRepeat not yet implemented");
+                                       #endif
+                                       err = unimpErr;
+                                       goto leaveNow;
+                                       break;
+                               case kPEFRelocSetPosition:
+                                       {
+                                               UInt32 offset;
+
+                                               // Lot's of folks have tried various interpretations of the description of 
+                                               // this opCode in "Mac OS Runtime Architectures" (which states "This instruction 
+                                               // sets relocAddress to the address of the section offset offset."  *smile*).
+                                               // I eventually dug into the CFM source code to find my interpretation, which 
+                                               // I believe is correct.  The key point is tht the offset is relative to 
+                                               // the start of the section for which these relocations are being performed.
+                                               
+                                               // Skip to next reloc word, which is the second chunk of the offset.
+                                               
+                                               state.currentReloc += 1;
+                                               
+                                               // Extract offset based on the most significant 10 bits in opCode and 
+                                               // the next significant 16 bits in the next reloc word.
+                                               
+                                               offset = PEFRelocSetPosFullOffset(opCode, relocInstrTable[state.currentReloc]);
+
+                                               state.relocAddress = (UInt32 *) ( ((char *) state.sectionBase) + offset);
+                                       }
+                                       break;
+                               case kPEFRelocLgByImport:
+                                       {
+                                               UInt32 symbolValue;
+                                               UInt32 index;
+
+                                               // Get the 26 bit symbol index from the current and next reloc words.
+                                               
+                                               state.currentReloc += 1;
+                                               index = PEFRelocLgByImportFullIndex(opCode, relocInstrTable[state.currentReloc]);
+                                               
+                                               if ( index >= importLibrary->firstImportedSymbol && index < (importLibrary->firstImportedSymbol + importLibrary->importedSymbolCount) ) {
+                                                       err = LookupSymbol(lookup, refCon, fragToFix->loaderSection, index, &symbolValue);
+                                                       if (err != noErr) {
+                                                               goto leaveNow;
+                                                       }
+                                                       *(state.relocAddress) += symbolValue;
+                                               }
+                                               state.importIndex = index + 1;
+                                               state.relocAddress += 1;
+                                       }
+                                       break;
+                               case kPEFRelocLgRepeat:
+                                       #if MORE_DEBUG
+                                               DebugStr("\pRunRelocationEngine: kPEFRelocLgRepeat not yet implemented");
+                                       #endif
+                                       err = unimpErr;
+                                       goto leaveNow;
+                                       break;
+                               case kPEFRelocLgSetOrBySection:
+                                       #if MORE_DEBUG
+                                               DebugStr("\pRunRelocationEngine: kPEFRelocLgSetOrBySection not yet implemented");
+                                       #endif
+                                       err = unimpErr;
+                                       goto leaveNow;
+                                       break;
+                               case kPEFRelocUndefinedOpcode:
+                                       err = cfragFragmentCorruptErr;
+                                       goto leaveNow;
+                                       break;
+                               default:
+                                       MoreAssertQ(false);
+                                       err = cfragFragmentCorruptErr;
+                                       goto leaveNow;
+                                       break;
+                       }
+                       state.currentReloc += 1;
+               }
+               
+               sectionsLeftToRelocate -= 1;
+       }
+
+leaveNow:
+       return err;
+}
+
+extern pascal OSStatus CFMLateImportCore(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFMLateImportLookupProc lookup,
+                                                                               void *refCon)
+       // See comments in interface part.
+{
+       OSStatus err;
+       OSStatus junk;
+       FragToFixInfo fragToFix;
+       PEFImportedLibrary *importLibrary;
+       char weakLinkedLibraryNameCString[256];
+
+       MoreAssertQ(fragToFixLocator != nil);   
+       MoreAssertQ(fragToFixConnID != nil);
+       MoreAssertQ(fragToFixInitRoutine != nil);
+       MoreAssertQ(weakLinkedLibraryName != nil);      
+       MoreAssertQ(lookup != nil);     
+       
+       // Fill out the bits of fragToFix which are passed in
+       // by the client.
+       
+       MoreBlockZero(&fragToFix, sizeof(fragToFix));
+       fragToFix.locator = *fragToFixLocator;
+       fragToFix.connID  = fragToFixConnID;
+       fragToFix.initRoutine = fragToFixInitRoutine;
+       
+       // Make a C string from weakLinkedLibraryName.
+       
+       BlockMoveData(weakLinkedLibraryName + 1, weakLinkedLibraryNameCString, weakLinkedLibraryName[0]);
+       weakLinkedLibraryNameCString[weakLinkedLibraryName[0]] = 0;
+
+       // Get the basic information from the fragment.
+       // Fills out the containerHeader, sectionHeaders, loaderSection and fileRef fields
+       // of fragToFix.
+       
+       err = ReadContainerBasics(&fragToFix);
+
+       // Set up the base address fields in fragToFix (ie section0Base and section1Base)
+       // by looking up our init routine (fragToFix.initRoutine) and subtracting
+       // away the section offsets (which we get from the disk copy of the section)
+       // to derive the bases of the sections themselves.
+       
+       if (err == noErr) {
+               err = SetupSectionBaseAddresses(&fragToFix);
+       }
+       
+       // Look inside the loader section for the import library description
+       // of weakLinkedLibraryName.  We need this to know the range of symbol
+       // indexes we're going to fix up.
+       
+       if (err == noErr) {
+               err = FindImportLibrary(fragToFix.loaderSection, weakLinkedLibraryNameCString, &importLibrary);
+       }
+       
+       // Do a quick check to ensure that the library was actually imported weak.
+       // If it wasn't, it doesn't make much sense to resolve its weak imports
+       // later on.  Resolving them again is likely to be bad.
+       
+       if (err == noErr) {
+               if ((importLibrary->options & kPEFWeakImportLibMask) == 0) {
+                       err = cfragFragmentUsageErr;
+               }
+       }
+       
+       // Now run the main relocation engine.
+       
+       if (err == noErr) {
+               err = RunRelocationEngine(&fragToFix, importLibrary, lookup, refCon);
+       }
+       
+       // Clean up.
+       
+       if (fragToFix.disposeSectionPointers) {
+               if (fragToFix.fileRef != 0) {
+                       junk = FSClose(fragToFix.fileRef);
+                       MoreAssertQ(junk == noErr);
+               }
+               if (fragToFix.loaderSection != nil) {
+                       DisposePtr( (Ptr) fragToFix.loaderSection);
+                       MoreAssertQ(MemError() == noErr);
+               }
+               if (fragToFix.sectionHeaders != nil) {
+                       DisposePtr( (Ptr) fragToFix.sectionHeaders);
+                       MoreAssertQ(MemError() == noErr);
+               }
+       }
+       return err;
+}
+
+static pascal OSStatus FragmentLookup(ConstStr255Param symName, CFragSymbolClass symClass,
+                                                                       void **symAddr, void *refCon)
+       // This is the CFMLateImportLookupProc callback used when 
+       // late importing from a CFM shared library.
+{
+       OSStatus err;
+       CFragConnectionID connIDToImport;
+       CFragSymbolClass  foundSymClass;
+       
+       MoreAssertQ(symName != nil);
+       MoreAssertQ(symAddr != nil);
+       MoreAssertQ(refCon  != nil);
+       
+       connIDToImport = (CFragConnectionID) refCon;
+       
+       // Shame there's no way to validate that connIDToImport is valid.
+
+       err = FindSymbol(connIDToImport, symName, (Ptr *) symAddr, &foundSymClass);
+       if (err == noErr) {
+               // If the symbol isn't of the right class, we act like we didn't 
+               // find it, but also assert in the debug build because weird things 
+               // are afoot.
+               if (foundSymClass != symClass) {
+                       MoreAssertQ(false);
+                       *symAddr = nil;
+                       err = cfragNoSymbolErr;
+               }
+       }
+       return err;
+}
+
+extern pascal OSStatus CFMLateImportLibrary(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFragConnectionID connIDToImport)
+       // See comments in interface part.
+{
+       MoreAssertQ(connIDToImport != nil);
+       return CFMLateImportCore(fragToFixLocator, fragToFixConnID, fragToFixInitRoutine,
+                                                                               weakLinkedLibraryName, FragmentLookup, connIDToImport);
+}
+
+static pascal OSStatus BundleLookup(ConstStr255Param symName, CFragSymbolClass symClass,
+                                                                       void **symAddr, void *refCon)
+       // This is the CFMLateImportLookupProc callback used when 
+       // late importing from a CFBundle.
+{
+       OSStatus        err;
+       CFBundleRef bundleToImport;
+       CFStringRef symNameStr;
+       
+       MoreAssertQ(symName != nil);
+       MoreAssertQ(symAddr != nil);
+       MoreAssertQ(refCon  != nil);
+       
+       symNameStr = nil;
+       
+       bundleToImport = (CFBundleRef) refCon;
+       
+       // Shame there's no way to validate that bundleToImport is really a bundle.
+       
+       // We can only find function pointers because CFBundleGetFunctionPointerForName 
+       // only works for function pointers.  So if the client is asking for something 
+       // other than a function pointer (ie TVector symbol) then we don't even true.
+       // Also assert in the debug build because this shows a certain lack of 
+       // understanding on the part of the client.
+       //
+       // CF is being revise to support accessing data symbols using a new API
+       // (currently this is available to Apple internal developers as 
+       // CFBundleGetDataPointerForName).  When the new API is available in a 
+       // public header file I should revise this code to lift this restriction.
+       
+       err = noErr;
+       if (symClass != kTVectorCFragSymbol) {
+               MoreAssertQ(false);
+               err = cfragNoSymbolErr;
+       }
+       if (err == noErr) {
+               symNameStr = CFStringCreateWithPascalString(kCFAllocatorSystemDefault, 
+                                                                                                       symName, kCFStringEncodingMacRoman);
+               if (symNameStr == nil) {
+                       err = coreFoundationUnknownErr;
+               }
+       }
+       if (err == noErr) {
+               *symAddr = CFBundleGetFunctionPointerForName(bundleToImport, symNameStr);
+               if (*symAddr == nil) {
+                       err = cfragNoSymbolErr;
+               }
+       }
+       if (symNameStr != nil) {
+               CFRelease(symNameStr);
+       }
+       return err;
+}
+
+extern pascal OSStatus CFMLateImportBundle(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFBundleRef bundleToImport)
+       // See comments in interface part.
+{
+       MoreAssertQ(bundleToImport != nil);
+       return CFMLateImportCore(fragToFixLocator, fragToFixConnID, fragToFixInitRoutine,
+                                                                               weakLinkedLibraryName, BundleLookup, bundleToImport);
+}
diff --git a/Mac/Modules/cg/CFMLateImport.h b/Mac/Modules/cg/CFMLateImport.h
new file mode 100755 (executable)
index 0000000..f3a89bc
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+       File:           CFMLateImport.h
+
+       Contains:       Interface to CFM late import library.
+
+       Written by:     Quinn
+
+       Copyright:      Copyright © 1999 by Apple Computer, Inc., all rights reserved.
+
+                               You may incorporate this Apple sample source code into your program(s) without
+                               restriction. This Apple sample source code has been provided "AS IS" and the
+                               responsibility for its operation is yours. You are not permitted to redistribute
+                               this Apple sample source code as "Apple sample source code" after having made
+                               changes. If you're going to re-distribute the source, we require that you make
+                               it clear in the source that the code was descended from Apple sample source
+                               code, but that you've made changes.
+
+       Change History (most recent first):
+
+         <6>     21/9/01    Quinn   Changes for CWPro7 Mach-O build.
+         <5>     19/9/01    Quinn   Change comments to reflect the fact that an unpacked data
+                                    section is no longer required.
+         <4>     19/9/01    Quinn   Simplified API and implementation after a suggestion by Eric
+                                    Grant. You no longer have to CFM export a dummy function; you
+                                    can just pass in the address of your fragment's init routine.
+         <3>    16/11/00    Quinn   Allow symbol finding via a callback and use that to implement
+                                    CFBundle support.
+         <2>    18/10/99    Quinn   Renamed CFMLateImport to CFMLateImportLibrary to allow for
+                                    possible future API expansion.
+         <1>     15/6/99    Quinn   First checked in.
+*/
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////
+
+// MoreIsBetter Setup
+
+//#include "MoreSetup.h"
+
+// Mac OS Interfaces
+
+#if ! MORE_FRAMEWORK_INCLUDES
+       #include <MacTypes.h>
+       #include <CodeFragments.h>
+       #include <Devices.h>
+       #include <CFBundle.h>
+#endif
+
+/////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*     FAQ
+       ---
+       
+       Q:      What does this library do?
+       A:      It allows you to resolve a weak linked library at runtime,
+               by supply a CFM connection to the library that should substitute
+               for the weak linked one.
+       
+       Q:      Does the substituted library have to have the same name as the
+               weak linked library.
+       A:      No.
+       
+       Q:      What's this useful for?
+       A:      The most obvious example of where this is useful is when
+               you rely on shared libraries that the user might delete
+               or move.  To can find the shared library (possibly even
+               using CatSearch), call GetDiskFragment to open a connection
+               to it, late import it using this library, and then the
+               rest of your code can continue to use the shared library
+               as if nothing had happened.  No more defining thousands
+               of stub routines which call through routine pointers.
+               
+               There are, however, numerous less obvious uses.  You can
+               use this code to make a 'self repairing' application.  If
+               the user removes your shared library from the Extensions
+               folder, the startup code for your application can offer
+               tor re-install it.  If the user agrees, you can then
+               re-install your shared library, late import it, and then
+               continue running your application if nothing happened.
+               
+               You can even use this code to free yourself from the
+               Extensions folder entirely.  Say you have a suite of
+               applications that currently installs a dozen shared 
+               libraries in the Extensions folder.  You can move those
+               libraries to another folder entirely and each application's
+               startup code can track down the library (using an alias
+               in the Preferences file) and late import it.
+               
+               An even cooler use is to provide easy abstraction layers.
+               Say you have a network code for both the MacTCP
+               API and the Open Transport API.  Typically, you would be
+               force to do this by having an abstraction layer where every
+               routine contains a switch between MacTCP and OT.  Your
+               OpenSocket routine might look like:
+
+                       static int OpenSocket(void)
+                       {
+                           if (gOTAvailable) {
+                               return OpenSocketOT();
+                           } else {
+                               return OpenSocketMacTCP();
+                           }
+                       }
+               
+               With this code, you can avoid that entirely.  Simply
+               weak link to a shared library that you know is never
+               going to be implemented ("crea;MySocketsDummy") and then, 
+               at runtime, decide whether the system has MacTCP or OT
+               and late import the relevant real implementation
+               ("crea;MySocketsMacTCP" or "crea;MySocketsOT").
+               One benefit of this approach is that only the MacTCP or
+               the OT code is resident in memory on any given system.
+*/
+
+typedef pascal OSStatus (*CFMLateImportLookupProc)(ConstStr255Param symName, CFragSymbolClass symClass,
+                                                                                                       void **symAddr, void *refCon);
+       // CFMLateImportLookupProc defines a callback for CFMLateImportCore.
+       // The routine is expected to look up the address of the symbol named 
+       // symName and return it in *symAddr.  The symbol should be of class 
+       // symClass, although the callback decides whether a class mismatch is 
+       // an error.  refCon is an application defined value that was originally 
+       // passed in to CFMLateImportCore.
+       //
+       // If this routine returns an error, a symbol address of 0 is assumed. 
+       // If the symbol is marked as a weak import, the CFMLateImportCore will 
+       // continue, otherwise the CFMLateImportCore routine will fail with the 
+       // error.
+       
+extern pascal OSStatus CFMLateImportCore(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFMLateImportLookupProc lookup,
+                                                                               void *refCon);
+       // This routine will link you, at runtime, to some library 
+       // that you were weak linked to and wasn't present when your
+       // fragment was prepared.  As well as the obvious functionality
+       // of being able to resolve weak links after prepare time,
+       // this functionality can be put to a number of less obvious uses,
+       // some of which are discussed at the top of this header file.
+       //
+       // To call this routine, you need a number of pieces of information:
+       //
+       // 1. fragToFixLocator, fragToFixConnID:  The location of your own
+       //    code fragment on disk and the CFM connection ID to your own
+       //    code fragment.  Typically you get this information from your 
+       //    fragment's CFM init routine.  You must ensure that
+       //    fragToFixLocator->fileSpec points to an FSSpec of the
+       //    file which holds your code fragment.
+       //
+       //    IMPORTANT:
+       //    The fact that you pass in a CFragSystem7DiskFlatLocator as the
+       //    fragToFixLocator implies that the fragment to be fixed up must
+       //    be in the data fork of a file.  The code could be modified
+       //    to remove this requirement, but on disk code fragments are the most
+       //    common case.
+       //
+       //    IMPORTANT:
+       //    The fragment to fix may have a packed data section.  Packing the 
+       //    data section will reduce the size of your fragment on disk, but it 
+       //    will significantly increase the memory needed by this routine 
+       //    (it increases memory usage by the sum of the sizes of the packed 
+       //    and unpacked data section).  See below for instructions on how to 
+       //    create an unpacked data section.
+       //
+       // 2. fragToFixInitRoutine:  A pointer to your own code fragment's
+       //    fragment initialiser routine.  You necessarily have one of these 
+       //    because you need it to get values for the fragToFixLocator and 
+       //    fragToFixConnID parameters.  Just pass its address in as a parameter 
+       //    as well. 
+       //
+       // 3. weakLinkedLibraryName:  The name of the weak linked library which
+       //    failed to link.  You must have weak linked to this library.
+       //    It is oxymoric for you to pass a strong linked library here,
+       //    because your code would not have prepared if a strong linked
+       //    library failed to prepare, and so you couldn't supply a valid
+       ///   fragToFix.
+       //
+       // 4. lookup, refCon:  A pointer to a callback function that the 
+       //        routine calls to look up the address of a symbol, and a refCon 
+       //    for that callback routine.
+       //
+       // Note:
+       // The fragToFixLocator and fragToFixInitRoutine parameters
+       // are artifacts of the way in which this functionality is implemented.
+       // In an ideal world, where CFM exported decent introspection APIs
+       // to third party developers, these parameters would not be necessary.
+       // If you're using this code inside Apple, you probably should investigate
+       // using the CFM private APIs for getting at the information these
+       // parameters are needed for.  See the comments inside the implementation
+       // for more details.
+       //
+       // Note:
+       // The extra memory taken when you use a packed data section is also an 
+       // artifact of my workaround for the lack of CFM introspection APIs.  In 
+       // my opinion it's better to use an unpacked data section and consume more 
+       // space on disk while saving memory.  In CodeWarrior you can switch to an 
+       // unpacked data section by checking the "Expand Uninitialized Data" 
+       // checkbox in the "PPC PEF" settings panel.  In MPW, specified the
+       // "-packdata off" option to PPCLink.
+       //
+       // When the routine returns, any symbols that you imported from the
+       // library named weakLinkedLibraryName will be resolved to the address
+       // of the symbol provided by the "lookup" callback routine.
+       //
+       // It is possible for an unresolved import to remain unresolved after
+       // this routine returns.  If the symbol import is marked as weak (as
+       // opposed to the library, which *must* be marked as weak) and the symbol
+       // is not found by the "lookup" callback, the routine will simple skip 
+       // that symbol.  If the symbol isn't marked as weak, the routine will fail 
+       // in that case.
+       //
+       // Most of the possible error results are co-opted CFM errors.  These
+       // include:
+       //
+       // cfragFragmentFormatErr  -- The fragment to fix is is an unknown format.
+       // cfragNoSectionErr       -- Could not find the loader section in the fragment to fix.
+       // cfragNoLibraryErr       -- The fragment to fix is not weak linked to weakLinkedLibraryName.
+       // cfragFragmentUsageErr   -- The fragment to fix doesn't have a data section.
+       //                         -- The fragment to fix is strong linked to weakLinkedLibraryName.
+       //                         -- The fragment doesn't have an init routine.
+       // cfragFragmentCorruptErr -- Encountered an undefined relocation opcode.
+       // unimpErr                -- Encountered an unimplement relocation opcode.  The
+       //                            relocation engine only implements a subset of the CFM
+       //                            relocation opcodes, the subset most commonly used by
+       //                            MPW and CodeWarrior PEF containers.  If you encounter
+       //                            this error, you'll probably have to add the weird
+       //                            relocation opcode to the engine, which shouldn't be
+       //                            be too hard.
+       // memFullErr                      -- It's likely that this error is triggered by the memory 
+       //                            needed to unpack your data section.  Either make your 
+       //                            data section smaller, or unpack it (see above).
+       // errors returned by FindSymbol
+       // errors returned by Memory Manager
+       //
+       // The routine needs enough memory to hold the loader section of the fragment
+       // to fix in memory.  It allocates that memory using NewPtr and dispsoses of 
+       // it before it returns.  You may want to change the memory allocator, which
+       // is very simple.
+
+extern pascal OSStatus CFMLateImportLibrary(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFragConnectionID connIDToImport);
+       // A wrapper around CFMLateImportCore that looks up symbols by calling 
+       // FindSymbol on a connection to a CFM library (connIDToImport).
+       // You can get this connection ID through any standard CFM API, for example
+       // GetSharedLibrary, GetDiskFragment, or GetMemFragment.
+       //
+       // IMPORTANT:
+       // The fragment name for connIDToImport *does not* have to match
+       // weakLinkedLibraryName.  This is part of the power of this library.
+
+extern pascal OSStatus CFMLateImportBundle(const CFragSystem7DiskFlatLocator *fragToFixLocator,
+                                                                               CFragConnectionID fragToFixConnID,
+                                                                               CFragInitFunction fragToFixInitRoutine,
+                                                                               ConstStr255Param weakLinkedLibraryName,
+                                                                               CFBundleRef bundleToImport);
+       // A wrapper around CFMLateImportCore that looks up symbols by calling 
+       // CFBundleGetFunctionPointerForName on a reference to a Core Foundation 
+       // bundle (bundleToImport).  You can get this reference through any 
+       // Core Foundation bundle API, for example CFBundleCreate.
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Mac/Modules/cg/CGStubLib b/Mac/Modules/cg/CGStubLib
new file mode 100755 (executable)
index 0000000..74de909
--- /dev/null
@@ -0,0 +1 @@
+(This file must be converted with BinHex 4.0)\r:!!"cG(9L69"6)!#3"!L3!!!!!BUjr%T[H5&`C@CQF(G`B`!!!!'i-rHh!*!0!3#\r3"[q3"!#3$JJm!!!!8!3"!*!1rj!%!*!%rj!%!*!%rj!%!*!A1!!!"2!!!!!$!!!\r!1N0(3fpZG'9iG&0SEhG8CAKd3A43EfPZG%0(3fpZG'9iG&0SEhG8CAKd3dG$Efj\rdCAKd8f9XC@0d4QpZG%0(3fpZG'9iG&0PG&4PH(4%FQ&hD@jR6@pNC80(3fpZG'9\riG%4bBAG3BA4S3dG$EfjdCAKd8f9d6'PZC8T[D@j$4d0[ER4PH(46CA4-D@jP3f&\r`3dG$EfjdCAKd4f9d9'9iG&"[FfPdD@pZ3dG$EfjdCAKd4f9d8'&dD%0eFR*PER4\r3EfPZG%0(3fpZG'9iG&0PG&0SEh9XC%&ZG'PKE'PKFd0(3fpZG'9iG&0jEQ0SFQp\rZDATP3dG$EfjdCAKd4QaeFfK$4d0[ER4PH(4&EQ43B@GP3dG$EfjdCAKd8f9d4Qp\rZG&0THQ9$4d0[ER4PH(4(CA48CAKd6@&dFQPi3dG$EfjdCAKd8f9d9'9iG%eKG(*\rTH%0(3fpZG'9iG&0PG&4PH(43Eh0TG'P[EN0(3fpZG'9iG&0PG%0SBA*KBh4PFP0\r`B@0TEQG$4d0[ER4PH(46CA4$69P,8h4bEfYP3fpXEh*$4d0[ER4PH(46CA4$69P\r,4QPXE%0[E'pb3dG$EfjdCAKd8f9d8NG#8h4bEfYP3fpXEh*$4d0[ER4PH(46CA4\r54d*'D@aX3fpXEh*$4d0[ER4PH(46CA4(FQ&j8h4bEfYP3fpXEh*$4d0[ER4PH(4\r6CA4(FQ&j4QPXE%0[E'pb3dG$EfjdCAKd3faTF&4[8Q9MG%0(3fpZG'9iG%923fa\rTF%0(3fpZG'9iG%0XDA"$4d0[ER4PH(4$E'9KFP*PBh4$4d0[ER4PH(46G(*[Df9\r5C@0d9fPdD&GTC(4S3dG$EfjdCAKd8h4bEfYP8Q9MG%0(3fpZG'9iG%CTE'a5C@0\rd3dG$EfjdCAKd8h4bEfYP8'&dD%0(3fpZG'9iG%924QPXE&"KG'K$4d0[ER4PH(4\r'D@aX8'&dD%0(3fpZG'9iG%GPG&"KG'K#Eh9ZC'PZCd*[H%0(3fpZG'9iG%Pc8'&\rdD%9YF(4j3dG$EfjdCAKd3@4N3A*M9'p3EfPZG%0(3fpZG'9iG%&NC%&bBd0(3fp\rZG'9iG%&NC&*PBh4$4d0[ER4PH(4$E'pcC9"KG'K$4d0[ER4PH(4"C'44G@&N3h9\rbGQ98Ee"[D@jd3dG$EfjdCAKd3@4N3h9bGQ98Ee"[D@jd3dG$EfjdCAKd3@4N6'P\rZC94[8'pTER4$4d0[ER4PH(40EhCP9'p3EfPZG%0(3fpZG'9iG%*PCfPZ8'&dD%0\r(3fpZG'9iG&0PG%&XF'KK3dG$EfjdCAKd8f9d4QaKG'jPFh0$4d0[ER4PH(46CA4\r0DA4PFNaTE@Pd3dG$EfjdCAKd8f9d6'PZC9GTC(4S3dG$EfjdCAKd4f9d3e403dG\r$EfjdCAKd3fpZBf&d3e403dG$EfjdCAKd8QpdBA4P3e403dG$EfjdCAKd9(*KER0\rXBA4P3e403dG$EfjdCAKd8f0KE'9$9%e$4d0[ER4PH(45CA0dEh*P4e0dBA4P3dG\r$EfjdCAKd8f&fC8G6G'&dC80(3fpZG'9iG&*PE'9KFf9$FQ9KG'9$4d0[ER4PH(4\r'Eh*3Eh*d!*!%)!!!!#J!#!!X!")!&!!G!"`!)J!F!#N!(!!`!!`!0`!BrD3!()G\rE!"$KGJ!2F0)!%S6f!"X(8J!@+$m!%Er*!"3)b!!B18%!%TFP!"4133!6*YS!&QJ\rq!"`5j3!6+b8!%FZX!!ijfJ!E40N!%FBC!!pc5`!83A3!%1#[!"BVd!!4bhd!%ab\r3!!!83a!!&Nmd!"S9CJ!B@h8!'pSB!"4$r!!6,PJ!&IIe!"QcA`!6,A)!%S40!"@\r4"!!C[em!(!eJ!"+&B!!B'J8!$h&S!"XE+!!4[r-!%r"c!"BZe`!6,@J!'&Y`!"+\r(m!!0R!B!('d8!"Gd9!!E00d!%142!"3ae3!4bj`!&UJa!J#3"rrq!J!"D!#3"2r\rq!J!$+J#3"2rq!J!$'`#3"2rq!J!#63#3"2rq!J!#eJ#3"2rq!J!"1J#3"2rq!J!\r#a3#3"2rq!J!#m3#3"2rq!J!"dJ#3"2rq!J!%,J#3"2rq!J!!D!#3"2rq!J!!I!#\r3"2rq!J!"*!#3"2rq!J!!T`#3"2rq!J!%I!#3"2rq!J!%93#3"2rq!J!!mJ#3"2r\rq!J!"kJ#3"2rq!J!!9`#3"2rq!J!#-3#3"2rq!J!!hJ#3"2rq!J!"!*!&rri#!!-\r&!*!%rri#!!!B!*!%rri#!!!T!*!%rri#!!21!*!%rri#!!4Q!*!%rri#!!'i!*!\r%rri#!!#2!*!%rri#!!!m!*!%rri#!!%3!*!%rri#!!+b!*!%rri#!!4!!*!%rri\r#!!'I!*!%rri#!!*l!*!%rri#!!3F!*!%rri#!!2i!*!%rri#!!)&!*!%rri#!!*\rI!*!%rri#!!-k!*!%rri#!!0S!*!%rri#!!30!*!%rri#!!$$!*!%rri#!!+1!*!\r%rri#!!)H!*!%rri#!!2L!*!%rri#!!+I!*!%rri#!!&3!*!%rri#!!1V!*!%rri\r#!!*!!*!%rri#!!0-!*!%rri#!!1!!*!%rri#!!'%!*!%rri#!!52!*!%rri#!!1\rA!*!%rri#!!1p!*!%rri#!!5I!*!%rri!N!3E2!!!!3!!!!&B!!!!@!!!!$)!N20\r8!*!,!3#3%`&`Gh"M!*!5!`%!N"%d#80(8h4eBNaTBJ!!!3!!!!&B!!!!@!!!!$*\r66e*8"*B!J!!F!$)!!'0QFQF!!!!+!!$rr`#3#2Ib:\r
\ No newline at end of file
diff --git a/Mac/Modules/cg/CGStubLib.exp b/Mac/Modules/cg/CGStubLib.exp
new file mode 100755 (executable)
index 0000000..4b034b5
--- /dev/null
@@ -0,0 +1,58 @@
+CGContextShowTextAtPoint
+CGContextShowText
+CGContextSelectFont
+CGContextSetTextDrawingMode
+CGContextDrawPath
+CGContextSetLineJoin
+CGContextSetLineCap
+CGContextGetTextPosition
+CGContextGetPathCurrentPoint
+CGContextSetShouldAntialias
+CGContextSynchronize
+CGContextFlush
+CGContextEndPage
+CGContextSetFontSize
+CGContextGetTextMatrix
+CGContextSetTextMatrix
+CGContextSetTextPosition
+CGContextSetCharacterSpacing
+CGContextSetCMYKStrokeColor
+CGContextSetCMYKFillColor
+CGContextSetRGBStrokeColor
+CGContextSetRGBFillColor
+CGContextSetGrayStrokeColor
+CGContextSetGrayFillColor
+CGContextClipToRect
+CGContextEOClip
+CGContextClip
+CGContextClearRect
+CGContextStrokeRectWithWidth
+CGContextStrokeRect
+CGContextFillRect
+CGContextStrokePath
+CGContextEOFillPath
+CGContextFillPath
+CGContextGetPathBoundingBox
+CGContextIsPathEmpty
+CGContextAddArcToPoint
+CGContextAddArc
+CGContextAddRect
+CGContextClosePath
+CGContextAddQuadCurveToPoint
+CGContextAddCurveToPoint
+CGContextAddLineToPoint
+CGContextMoveToPoint
+CGContextBeginPath
+CGContextSetAlpha
+CGContextSetFlatness
+CGContextSetMiterLimit
+CGContextSetLineWidth
+CGContextGetCTM
+CGContextConcatCTM
+CGContextRotateCTM
+CGContextTranslateCTM
+CGContextScaleCTM
+CGContextRestoreGState
+CGContextSaveGState
+CGContextRelease
+CreateCGContextForPort
diff --git a/Mac/Modules/cg/CGStubLib.readme b/Mac/Modules/cg/CGStubLib.readme
new file mode 100755 (executable)
index 0000000..d2c5fa8
--- /dev/null
@@ -0,0 +1,3 @@
+# CGStubLib was created by issuing this command in MPW:
+
+MakeStub CGStubLib.exp -o CGStubLib
diff --git a/Mac/Modules/cg/_CGmodule.c b/Mac/Modules/cg/_CGmodule.c
new file mode 100755 (executable)
index 0000000..6523e71
--- /dev/null
@@ -0,0 +1,1332 @@
+
+/* =========================== Module _CG =========================== */
+
+#include "Python.h"
+
+
+
+#include "macglue.h"
+#include "pymactoolbox.h"
+
+/* Macro to test whether a weak-loaded CFM function exists */
+#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL )  {\
+       PyErr_SetString(PyExc_NotImplementedError, \
+       "Not available in this shared library/OS version"); \
+       return NULL; \
+    }} while(0)
+
+
+#ifdef WITHOUT_FRAMEWORKS
+#include <Quickdraw.h>
+#include <CGContext.h>
+#else
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if !TARGET_API_MAC_OSX
+       /* This code is adapted from the CallMachOFramework demo at:
+       http://developer.apple.com/samplecode/Sample_Code/Runtime_Architecture/CallMachOFramework.htm
+       It allows us to call Mach-O functions from CFM apps. */
+
+       #include <Folders.h>
+       #include "CFMLateImport.h"
+
+       static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr)
+               // This routine finds a the named framework and creates a CFBundle 
+               // object for it.  It looks for the framework in the frameworks folder, 
+               // as defined by the Folder Manager.  Currently this is 
+               // "/System/Library/Frameworks", but we recommend that you avoid hard coded 
+               // paths to ensure future compatibility.
+               //
+               // You might think that you could use CFBundleGetBundleWithIdentifier but 
+               // that only finds bundles that are already loaded into your context. 
+               // That would work in the case of the System framework but it wouldn't 
+               // work if you're using some other, less-obvious, framework.
+       {
+               OSStatus        err;
+               FSRef           frameworksFolderRef;
+               CFURLRef        baseURL;
+               CFURLRef        bundleURL;
+               
+               *bundlePtr = nil;
+               
+               baseURL = nil;
+               bundleURL = nil;
+               
+               // Find the frameworks folder and create a URL for it.
+               
+               err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
+               if (err == noErr) {
+                       baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
+                       if (baseURL == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               
+               // Append the name of the framework to the URL.
+               
+               if (err == noErr) {
+                       bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false);
+                       if (bundleURL == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               
+               // Create a bundle based on that URL and load the bundle into memory.
+               // We never unload the bundle, which is reasonable in this case because 
+               // the sample assumes that you'll be calling functions from this 
+               // framework throughout the life of your application.
+               
+               if (err == noErr) {
+                       *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
+                       if (*bundlePtr == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               if (err == noErr) {
+                   if ( ! CFBundleLoadExecutable( *bundlePtr ) ) {
+                               err = coreFoundationUnknownErr;
+                   }
+               }
+
+               // Clean up.
+               
+               if (err != noErr && *bundlePtr != nil) {
+                       CFRelease(*bundlePtr);
+                       *bundlePtr = nil;
+               }
+               if (bundleURL != nil) {
+                       CFRelease(bundleURL);
+               }       
+               if (baseURL != nil) {
+                       CFRelease(baseURL);
+               }       
+               
+               return err;
+       }
+
+
+
+       // The CFMLateImport approach requires that you define a fragment 
+       // initialisation routine that latches the fragment's connection 
+       // ID and locator.  If your code already has a fragment initialiser 
+       // you will have to integrate the following into it.
+
+       static CFragConnectionID                        gFragToFixConnID;
+       static FSSpec                                           gFragToFixFile;
+       static CFragSystem7DiskFlatLocator      gFragToFixLocator;
+
+       extern OSErr FragmentInit(const CFragInitBlock *initBlock);
+       extern OSErr FragmentInit(const CFragInitBlock *initBlock)
+       {
+               __initialize(initBlock); /* call the "original" initializer */
+               gFragToFixConnID        = (CFragConnectionID) initBlock->closureID;
+               gFragToFixFile          = *(initBlock->fragLocator.u.onDisk.fileSpec);
+               gFragToFixLocator       = initBlock->fragLocator.u.onDisk;
+               gFragToFixLocator.fileSpec = &gFragToFixFile;
+               
+               return noErr;
+       }
+
+#endif
+
+extern int GrafObj_Convert(PyObject *, GrafPtr *);
+
+/*
+** Manual converters
+*/
+
+PyObject *CGPoint_New(CGPoint *itself)
+{
+
+       return Py_BuildValue("(ff)",
+                       itself->x,
+                       itself->y);
+}
+
+int
+CGPoint_Convert(PyObject *v, CGPoint *p_itself)
+{
+       if( !PyArg_Parse(v, "(ff)",
+                       &p_itself->x,
+                       &p_itself->y) )
+               return 0;
+       return 1;
+}
+
+PyObject *CGRect_New(CGRect *itself)
+{
+
+       return Py_BuildValue("(ffff)",
+                       itself->origin.x,
+                       itself->origin.y,
+                       itself->size.width,
+                       itself->size.height);
+}
+
+int
+CGRect_Convert(PyObject *v, CGRect *p_itself)
+{
+       if( !PyArg_Parse(v, "(ffff)",
+                       &p_itself->origin.x,
+                       &p_itself->origin.y,
+                       &p_itself->size.width,
+                       &p_itself->size.height) )
+               return 0;
+       return 1;
+}
+
+PyObject *CGAffineTransform_New(CGAffineTransform *itself)
+{
+
+       return Py_BuildValue("(ffffff)",
+                       itself->a,
+                       itself->b,
+                       itself->c,
+                       itself->d,
+                       itself->tx,
+                       itself->ty);
+}
+
+int
+CGAffineTransform_Convert(PyObject *v, CGAffineTransform *p_itself)
+{
+       if( !PyArg_Parse(v, "(ffffff)",
+                       &p_itself->a,
+                       &p_itself->b,
+                       &p_itself->c,
+                       &p_itself->d,
+                       &p_itself->tx,
+                       &p_itself->ty) )
+               return 0;
+       return 1;
+}
+
+static PyObject *CG_Error;
+
+/* -------------------- Object type CGContextRef -------------------- */
+
+PyTypeObject CGContextRef_Type;
+
+#define CGContextRefObj_Check(x) ((x)->ob_type == &CGContextRef_Type)
+
+typedef struct CGContextRefObject {
+       PyObject_HEAD
+       CGContextRef ob_itself;
+} CGContextRefObject;
+
+PyObject *CGContextRefObj_New(CGContextRef itself)
+{
+       CGContextRefObject *it;
+       it = PyObject_NEW(CGContextRefObject, &CGContextRef_Type);
+       if (it == NULL) return NULL;
+       it->ob_itself = itself;
+       return (PyObject *)it;
+}
+int CGContextRefObj_Convert(PyObject *v, CGContextRef *p_itself)
+{
+       if (!CGContextRefObj_Check(v))
+       {
+               PyErr_SetString(PyExc_TypeError, "CGContextRef required");
+               return 0;
+       }
+       *p_itself = ((CGContextRefObject *)v)->ob_itself;
+       return 1;
+}
+
+static void CGContextRefObj_dealloc(CGContextRefObject *self)
+{
+       CGContextRelease(self->ob_itself);
+       PyMem_DEL(self);
+}
+
+static PyObject *CGContextRefObj_CGContextSaveGState(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextSaveGState(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextRestoreGState(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextRestoreGState(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextScaleCTM(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float sx;
+       float sy;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &sx,
+                             &sy))
+               return NULL;
+       CGContextScaleCTM(_self->ob_itself,
+                         sx,
+                         sy);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextTranslateCTM(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float tx;
+       float ty;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &tx,
+                             &ty))
+               return NULL;
+       CGContextTranslateCTM(_self->ob_itself,
+                             tx,
+                             ty);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextRotateCTM(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float angle;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &angle))
+               return NULL;
+       CGContextRotateCTM(_self->ob_itself,
+                          angle);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextConcatCTM(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGAffineTransform transform;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGAffineTransform_Convert, &transform))
+               return NULL;
+       CGContextConcatCTM(_self->ob_itself,
+                          transform);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextGetCTM(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGAffineTransform _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextGetCTM(_self->ob_itself);
+       _res = Py_BuildValue("O&",
+                            CGAffineTransform_New, &_rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetLineWidth(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float width;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &width))
+               return NULL;
+       CGContextSetLineWidth(_self->ob_itself,
+                             width);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetLineCap(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int cap;
+       if (!PyArg_ParseTuple(_args, "i",
+                             &cap))
+               return NULL;
+       CGContextSetLineCap(_self->ob_itself,
+                           cap);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetLineJoin(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int join;
+       if (!PyArg_ParseTuple(_args, "i",
+                             &join))
+               return NULL;
+       CGContextSetLineJoin(_self->ob_itself,
+                            join);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetMiterLimit(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float limit;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &limit))
+               return NULL;
+       CGContextSetMiterLimit(_self->ob_itself,
+                              limit);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetFlatness(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float flatness;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &flatness))
+               return NULL;
+       CGContextSetFlatness(_self->ob_itself,
+                            flatness);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetAlpha(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &alpha))
+               return NULL;
+       CGContextSetAlpha(_self->ob_itself,
+                         alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextBeginPath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextBeginPath(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextMoveToPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x;
+       float y;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &x,
+                             &y))
+               return NULL;
+       CGContextMoveToPoint(_self->ob_itself,
+                            x,
+                            y);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddLineToPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x;
+       float y;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &x,
+                             &y))
+               return NULL;
+       CGContextAddLineToPoint(_self->ob_itself,
+                               x,
+                               y);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddCurveToPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float cp1x;
+       float cp1y;
+       float cp2x;
+       float cp2y;
+       float x;
+       float y;
+       if (!PyArg_ParseTuple(_args, "ffffff",
+                             &cp1x,
+                             &cp1y,
+                             &cp2x,
+                             &cp2y,
+                             &x,
+                             &y))
+               return NULL;
+       CGContextAddCurveToPoint(_self->ob_itself,
+                                cp1x,
+                                cp1y,
+                                cp2x,
+                                cp2y,
+                                x,
+                                y);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddQuadCurveToPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float cpx;
+       float cpy;
+       float x;
+       float y;
+       if (!PyArg_ParseTuple(_args, "ffff",
+                             &cpx,
+                             &cpy,
+                             &x,
+                             &y))
+               return NULL;
+       CGContextAddQuadCurveToPoint(_self->ob_itself,
+                                    cpx,
+                                    cpy,
+                                    x,
+                                    y);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextClosePath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextClosePath(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddRect(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGRect_Convert, &rect))
+               return NULL;
+       CGContextAddRect(_self->ob_itself,
+                        rect);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddArc(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x;
+       float y;
+       float radius;
+       float startAngle;
+       float endAngle;
+       int clockwise;
+       if (!PyArg_ParseTuple(_args, "fffffi",
+                             &x,
+                             &y,
+                             &radius,
+                             &startAngle,
+                             &endAngle,
+                             &clockwise))
+               return NULL;
+       CGContextAddArc(_self->ob_itself,
+                       x,
+                       y,
+                       radius,
+                       startAngle,
+                       endAngle,
+                       clockwise);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextAddArcToPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x1;
+       float y1;
+       float x2;
+       float y2;
+       float radius;
+       if (!PyArg_ParseTuple(_args, "fffff",
+                             &x1,
+                             &y1,
+                             &x2,
+                             &y2,
+                             &radius))
+               return NULL;
+       CGContextAddArcToPoint(_self->ob_itself,
+                              x1,
+                              y1,
+                              x2,
+                              y2,
+                              radius);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextIsPathEmpty(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextIsPathEmpty(_self->ob_itself);
+       _res = Py_BuildValue("i",
+                            _rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextGetPathCurrentPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGPoint _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextGetPathCurrentPoint(_self->ob_itself);
+       _res = Py_BuildValue("O&",
+                            CGPoint_New, &_rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextGetPathBoundingBox(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextGetPathBoundingBox(_self->ob_itself);
+       _res = Py_BuildValue("O&",
+                            CGRect_New, &_rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextDrawPath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int mode;
+       if (!PyArg_ParseTuple(_args, "i",
+                             &mode))
+               return NULL;
+       CGContextDrawPath(_self->ob_itself,
+                         mode);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextFillPath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextFillPath(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextEOFillPath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextEOFillPath(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextStrokePath(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextStrokePath(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextFillRect(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGRect_Convert, &rect))
+               return NULL;
+       CGContextFillRect(_self->ob_itself,
+                         rect);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextStrokeRect(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGRect_Convert, &rect))
+               return NULL;
+       CGContextStrokeRect(_self->ob_itself,
+                           rect);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextStrokeRectWithWidth(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       float width;
+       if (!PyArg_ParseTuple(_args, "O&f",
+                             CGRect_Convert, &rect,
+                             &width))
+               return NULL;
+       CGContextStrokeRectWithWidth(_self->ob_itself,
+                                    rect,
+                                    width);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextClearRect(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGRect_Convert, &rect))
+               return NULL;
+       CGContextClearRect(_self->ob_itself,
+                          rect);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextClip(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextClip(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextEOClip(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextEOClip(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextClipToRect(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGRect rect;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGRect_Convert, &rect))
+               return NULL;
+       CGContextClipToRect(_self->ob_itself,
+                           rect);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetGrayFillColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float gray;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &gray,
+                             &alpha))
+               return NULL;
+       CGContextSetGrayFillColor(_self->ob_itself,
+                                 gray,
+                                 alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetGrayStrokeColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float gray;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &gray,
+                             &alpha))
+               return NULL;
+       CGContextSetGrayStrokeColor(_self->ob_itself,
+                                   gray,
+                                   alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetRGBFillColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float r;
+       float g;
+       float b;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "ffff",
+                             &r,
+                             &g,
+                             &b,
+                             &alpha))
+               return NULL;
+       CGContextSetRGBFillColor(_self->ob_itself,
+                                r,
+                                g,
+                                b,
+                                alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetRGBStrokeColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float r;
+       float g;
+       float b;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "ffff",
+                             &r,
+                             &g,
+                             &b,
+                             &alpha))
+               return NULL;
+       CGContextSetRGBStrokeColor(_self->ob_itself,
+                                  r,
+                                  g,
+                                  b,
+                                  alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetCMYKFillColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float c;
+       float m;
+       float y;
+       float k;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "fffff",
+                             &c,
+                             &m,
+                             &y,
+                             &k,
+                             &alpha))
+               return NULL;
+       CGContextSetCMYKFillColor(_self->ob_itself,
+                                 c,
+                                 m,
+                                 y,
+                                 k,
+                                 alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetCMYKStrokeColor(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float c;
+       float m;
+       float y;
+       float k;
+       float alpha;
+       if (!PyArg_ParseTuple(_args, "fffff",
+                             &c,
+                             &m,
+                             &y,
+                             &k,
+                             &alpha))
+               return NULL;
+       CGContextSetCMYKStrokeColor(_self->ob_itself,
+                                   c,
+                                   m,
+                                   y,
+                                   k,
+                                   alpha);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetCharacterSpacing(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float spacing;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &spacing))
+               return NULL;
+       CGContextSetCharacterSpacing(_self->ob_itself,
+                                    spacing);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetTextPosition(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x;
+       float y;
+       if (!PyArg_ParseTuple(_args, "ff",
+                             &x,
+                             &y))
+               return NULL;
+       CGContextSetTextPosition(_self->ob_itself,
+                                x,
+                                y);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextGetTextPosition(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGPoint _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextGetTextPosition(_self->ob_itself);
+       _res = Py_BuildValue("O&",
+                            CGPoint_New, &_rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetTextMatrix(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGAffineTransform transform;
+       if (!PyArg_ParseTuple(_args, "O&",
+                             CGAffineTransform_Convert, &transform))
+               return NULL;
+       CGContextSetTextMatrix(_self->ob_itself,
+                              transform);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextGetTextMatrix(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       CGAffineTransform _rv;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _rv = CGContextGetTextMatrix(_self->ob_itself);
+       _res = Py_BuildValue("O&",
+                            CGAffineTransform_New, &_rv);
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetTextDrawingMode(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int mode;
+       if (!PyArg_ParseTuple(_args, "i",
+                             &mode))
+               return NULL;
+       CGContextSetTextDrawingMode(_self->ob_itself,
+                                   mode);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetFontSize(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float size;
+       if (!PyArg_ParseTuple(_args, "f",
+                             &size))
+               return NULL;
+       CGContextSetFontSize(_self->ob_itself,
+                            size);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSelectFont(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       char * name;
+       float size;
+       int textEncoding;
+       if (!PyArg_ParseTuple(_args, "sfi",
+                             &name,
+                             &size,
+                             &textEncoding))
+               return NULL;
+       CGContextSelectFont(_self->ob_itself,
+                           name,
+                           size,
+                           textEncoding);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextShowText(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       char *cstring__in__;
+       long cstring__len__;
+       int cstring__in_len__;
+       if (!PyArg_ParseTuple(_args, "s#",
+                             &cstring__in__, &cstring__in_len__))
+               return NULL;
+       cstring__len__ = cstring__in_len__;
+       CGContextShowText(_self->ob_itself,
+                         cstring__in__, cstring__len__);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextShowTextAtPoint(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       float x;
+       float y;
+       char *cstring__in__;
+       long cstring__len__;
+       int cstring__in_len__;
+       if (!PyArg_ParseTuple(_args, "ffs#",
+                             &x,
+                             &y,
+                             &cstring__in__, &cstring__in_len__))
+               return NULL;
+       cstring__len__ = cstring__in_len__;
+       CGContextShowTextAtPoint(_self->ob_itself,
+                                x,
+                                y,
+                                cstring__in__, cstring__len__);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextEndPage(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextEndPage(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextFlush(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextFlush(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSynchronize(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       CGContextSynchronize(_self->ob_itself);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyObject *CGContextRefObj_CGContextSetShouldAntialias(CGContextRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       int shouldAntialias;
+       if (!PyArg_ParseTuple(_args, "i",
+                             &shouldAntialias))
+               return NULL;
+       CGContextSetShouldAntialias(_self->ob_itself,
+                                   shouldAntialias);
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
+static PyMethodDef CGContextRefObj_methods[] = {
+       {"CGContextSaveGState", (PyCFunction)CGContextRefObj_CGContextSaveGState, 1,
+        "() -> None"},
+       {"CGContextRestoreGState", (PyCFunction)CGContextRefObj_CGContextRestoreGState, 1,
+        "() -> None"},
+       {"CGContextScaleCTM", (PyCFunction)CGContextRefObj_CGContextScaleCTM, 1,
+        "(float sx, float sy) -> None"},
+       {"CGContextTranslateCTM", (PyCFunction)CGContextRefObj_CGContextTranslateCTM, 1,
+        "(float tx, float ty) -> None"},
+       {"CGContextRotateCTM", (PyCFunction)CGContextRefObj_CGContextRotateCTM, 1,
+        "(float angle) -> None"},
+       {"CGContextConcatCTM", (PyCFunction)CGContextRefObj_CGContextConcatCTM, 1,
+        "(CGAffineTransform transform) -> None"},
+       {"CGContextGetCTM", (PyCFunction)CGContextRefObj_CGContextGetCTM, 1,
+        "() -> (CGAffineTransform _rv)"},
+       {"CGContextSetLineWidth", (PyCFunction)CGContextRefObj_CGContextSetLineWidth, 1,
+        "(float width) -> None"},
+       {"CGContextSetLineCap", (PyCFunction)CGContextRefObj_CGContextSetLineCap, 1,
+        "(int cap) -> None"},
+       {"CGContextSetLineJoin", (PyCFunction)CGContextRefObj_CGContextSetLineJoin, 1,
+        "(int join) -> None"},
+       {"CGContextSetMiterLimit", (PyCFunction)CGContextRefObj_CGContextSetMiterLimit, 1,
+        "(float limit) -> None"},
+       {"CGContextSetFlatness", (PyCFunction)CGContextRefObj_CGContextSetFlatness, 1,
+        "(float flatness) -> None"},
+       {"CGContextSetAlpha", (PyCFunction)CGContextRefObj_CGContextSetAlpha, 1,
+        "(float alpha) -> None"},
+       {"CGContextBeginPath", (PyCFunction)CGContextRefObj_CGContextBeginPath, 1,
+        "() -> None"},
+       {"CGContextMoveToPoint", (PyCFunction)CGContextRefObj_CGContextMoveToPoint, 1,
+        "(float x, float y) -> None"},
+       {"CGContextAddLineToPoint", (PyCFunction)CGContextRefObj_CGContextAddLineToPoint, 1,
+        "(float x, float y) -> None"},
+       {"CGContextAddCurveToPoint", (PyCFunction)CGContextRefObj_CGContextAddCurveToPoint, 1,
+        "(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) -> None"},
+       {"CGContextAddQuadCurveToPoint", (PyCFunction)CGContextRefObj_CGContextAddQuadCurveToPoint, 1,
+        "(float cpx, float cpy, float x, float y) -> None"},
+       {"CGContextClosePath", (PyCFunction)CGContextRefObj_CGContextClosePath, 1,
+        "() -> None"},
+       {"CGContextAddRect", (PyCFunction)CGContextRefObj_CGContextAddRect, 1,
+        "(CGRect rect) -> None"},
+       {"CGContextAddArc", (PyCFunction)CGContextRefObj_CGContextAddArc, 1,
+        "(float x, float y, float radius, float startAngle, float endAngle, int clockwise) -> None"},
+       {"CGContextAddArcToPoint", (PyCFunction)CGContextRefObj_CGContextAddArcToPoint, 1,
+        "(float x1, float y1, float x2, float y2, float radius) -> None"},
+       {"CGContextIsPathEmpty", (PyCFunction)CGContextRefObj_CGContextIsPathEmpty, 1,
+        "() -> (int _rv)"},
+       {"CGContextGetPathCurrentPoint", (PyCFunction)CGContextRefObj_CGContextGetPathCurrentPoint, 1,
+        "() -> (CGPoint _rv)"},
+       {"CGContextGetPathBoundingBox", (PyCFunction)CGContextRefObj_CGContextGetPathBoundingBox, 1,
+        "() -> (CGRect _rv)"},
+       {"CGContextDrawPath", (PyCFunction)CGContextRefObj_CGContextDrawPath, 1,
+        "(int mode) -> None"},
+       {"CGContextFillPath", (PyCFunction)CGContextRefObj_CGContextFillPath, 1,
+        "() -> None"},
+       {"CGContextEOFillPath", (PyCFunction)CGContextRefObj_CGContextEOFillPath, 1,
+        "() -> None"},
+       {"CGContextStrokePath", (PyCFunction)CGContextRefObj_CGContextStrokePath, 1,
+        "() -> None"},
+       {"CGContextFillRect", (PyCFunction)CGContextRefObj_CGContextFillRect, 1,
+        "(CGRect rect) -> None"},
+       {"CGContextStrokeRect", (PyCFunction)CGContextRefObj_CGContextStrokeRect, 1,
+        "(CGRect rect) -> None"},
+       {"CGContextStrokeRectWithWidth", (PyCFunction)CGContextRefObj_CGContextStrokeRectWithWidth, 1,
+        "(CGRect rect, float width) -> None"},
+       {"CGContextClearRect", (PyCFunction)CGContextRefObj_CGContextClearRect, 1,
+        "(CGRect rect) -> None"},
+       {"CGContextClip", (PyCFunction)CGContextRefObj_CGContextClip, 1,
+        "() -> None"},
+       {"CGContextEOClip", (PyCFunction)CGContextRefObj_CGContextEOClip, 1,
+        "() -> None"},
+       {"CGContextClipToRect", (PyCFunction)CGContextRefObj_CGContextClipToRect, 1,
+        "(CGRect rect) -> None"},
+       {"CGContextSetGrayFillColor", (PyCFunction)CGContextRefObj_CGContextSetGrayFillColor, 1,
+        "(float gray, float alpha) -> None"},
+       {"CGContextSetGrayStrokeColor", (PyCFunction)CGContextRefObj_CGContextSetGrayStrokeColor, 1,
+        "(float gray, float alpha) -> None"},
+       {"CGContextSetRGBFillColor", (PyCFunction)CGContextRefObj_CGContextSetRGBFillColor, 1,
+        "(float r, float g, float b, float alpha) -> None"},
+       {"CGContextSetRGBStrokeColor", (PyCFunction)CGContextRefObj_CGContextSetRGBStrokeColor, 1,
+        "(float r, float g, float b, float alpha) -> None"},
+       {"CGContextSetCMYKFillColor", (PyCFunction)CGContextRefObj_CGContextSetCMYKFillColor, 1,
+        "(float c, float m, float y, float k, float alpha) -> None"},
+       {"CGContextSetCMYKStrokeColor", (PyCFunction)CGContextRefObj_CGContextSetCMYKStrokeColor, 1,
+        "(float c, float m, float y, float k, float alpha) -> None"},
+       {"CGContextSetCharacterSpacing", (PyCFunction)CGContextRefObj_CGContextSetCharacterSpacing, 1,
+        "(float spacing) -> None"},
+       {"CGContextSetTextPosition", (PyCFunction)CGContextRefObj_CGContextSetTextPosition, 1,
+        "(float x, float y) -> None"},
+       {"CGContextGetTextPosition", (PyCFunction)CGContextRefObj_CGContextGetTextPosition, 1,
+        "() -> (CGPoint _rv)"},
+       {"CGContextSetTextMatrix", (PyCFunction)CGContextRefObj_CGContextSetTextMatrix, 1,
+        "(CGAffineTransform transform) -> None"},
+       {"CGContextGetTextMatrix", (PyCFunction)CGContextRefObj_CGContextGetTextMatrix, 1,
+        "() -> (CGAffineTransform _rv)"},
+       {"CGContextSetTextDrawingMode", (PyCFunction)CGContextRefObj_CGContextSetTextDrawingMode, 1,
+        "(int mode) -> None"},
+       {"CGContextSetFontSize", (PyCFunction)CGContextRefObj_CGContextSetFontSize, 1,
+        "(float size) -> None"},
+       {"CGContextSelectFont", (PyCFunction)CGContextRefObj_CGContextSelectFont, 1,
+        "(char * name, float size, int textEncoding) -> None"},
+       {"CGContextShowText", (PyCFunction)CGContextRefObj_CGContextShowText, 1,
+        "(Buffer cstring) -> None"},
+       {"CGContextShowTextAtPoint", (PyCFunction)CGContextRefObj_CGContextShowTextAtPoint, 1,
+        "(float x, float y, Buffer cstring) -> None"},
+       {"CGContextEndPage", (PyCFunction)CGContextRefObj_CGContextEndPage, 1,
+        "() -> None"},
+       {"CGContextFlush", (PyCFunction)CGContextRefObj_CGContextFlush, 1,
+        "() -> None"},
+       {"CGContextSynchronize", (PyCFunction)CGContextRefObj_CGContextSynchronize, 1,
+        "() -> None"},
+       {"CGContextSetShouldAntialias", (PyCFunction)CGContextRefObj_CGContextSetShouldAntialias, 1,
+        "(int shouldAntialias) -> None"},
+       {NULL, NULL, 0}
+};
+
+PyMethodChain CGContextRefObj_chain = { CGContextRefObj_methods, NULL };
+
+static PyObject *CGContextRefObj_getattr(CGContextRefObject *self, char *name)
+{
+       return Py_FindMethodInChain(&CGContextRefObj_chain, (PyObject *)self, name);
+}
+
+#define CGContextRefObj_setattr NULL
+
+#define CGContextRefObj_compare NULL
+
+#define CGContextRefObj_repr NULL
+
+#define CGContextRefObj_hash NULL
+
+PyTypeObject CGContextRef_Type = {
+       PyObject_HEAD_INIT(NULL)
+       0, /*ob_size*/
+       "_CG.CGContextRef", /*tp_name*/
+       sizeof(CGContextRefObject), /*tp_basicsize*/
+       0, /*tp_itemsize*/
+       /* methods */
+       (destructor) CGContextRefObj_dealloc, /*tp_dealloc*/
+       0, /*tp_print*/
+       (getattrfunc) CGContextRefObj_getattr, /*tp_getattr*/
+       (setattrfunc) CGContextRefObj_setattr, /*tp_setattr*/
+       (cmpfunc) CGContextRefObj_compare, /*tp_compare*/
+       (reprfunc) CGContextRefObj_repr, /*tp_repr*/
+       (PyNumberMethods *)0, /* tp_as_number */
+       (PySequenceMethods *)0, /* tp_as_sequence */
+       (PyMappingMethods *)0, /* tp_as_mapping */
+       (hashfunc) CGContextRefObj_hash, /*tp_hash*/
+};
+
+/* ------------------ End object type CGContextRef ------------------ */
+
+
+static PyObject *CG_CreateCGContextForPort(PyObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+       GrafPtr port;
+       CGContextRef ctx;
+       OSStatus _err;
+
+       if (!PyArg_ParseTuple(_args, "O&", GrafObj_Convert, &port))
+               return NULL;
+
+       _err = CreateCGContextForPort(port, &ctx);
+       if (_err != noErr)
+               if (_err != noErr) return PyMac_Error(_err);
+       _res = Py_BuildValue("O&", CGContextRefObj_New, ctx);
+       return _res;
+
+}
+
+static PyMethodDef CG_methods[] = {
+       {"CreateCGContextForPort", (PyCFunction)CG_CreateCGContextForPort, 1,
+        "(CGrafPtr) -> CGContextRef"},
+       {NULL, NULL, 0}
+};
+
+
+
+
+void init_CG(void)
+{
+       PyObject *m;
+       PyObject *d;
+
+
+
+#if !TARGET_API_MAC_OSX
+       CFBundleRef sysBundle;
+       OSStatus err;
+
+       if (&LoadFrameworkBundle == NULL) {
+               PyErr_SetString(PyExc_ImportError, "CoreCraphics not supported");
+               return;
+       }
+       err = LoadFrameworkBundle(CFSTR("ApplicationServices.framework"), &sysBundle);
+       if (err == noErr)
+               err = CFMLateImportBundle(&gFragToFixLocator, gFragToFixConnID, FragmentInit, "\pCGStubLib", sysBundle);
+       if (err != noErr) {
+               PyErr_SetString(PyExc_ImportError, "CoreCraphics not supported");
+               return;
+       };
+#endif  /* !TARGET_API_MAC_OSX */
+
+
+       m = Py_InitModule("_CG", CG_methods);
+       d = PyModule_GetDict(m);
+       CG_Error = PyMac_GetOSErrException();
+       if (CG_Error == NULL ||
+           PyDict_SetItemString(d, "Error", CG_Error) != 0)
+               return;
+       CGContextRef_Type.ob_type = &PyType_Type;
+       Py_INCREF(&CGContextRef_Type);
+       if (PyDict_SetItemString(d, "CGContextRefType", (PyObject *)&CGContextRef_Type) != 0)
+               Py_FatalError("can't initialize CGContextRefType");
+}
+
+/* ========================= End module _CG ========================= */
+
diff --git a/Mac/Modules/cg/cgscan.py b/Mac/Modules/cg/cgscan.py
new file mode 100755 (executable)
index 0000000..f676470
--- /dev/null
@@ -0,0 +1,83 @@
+# Scan an Apple header file, generating a Python file of generator calls.
+
+import sys
+import os
+BGENDIR=os.path.join(sys.prefix, ':Tools:bgen:bgen')
+sys.path.append(BGENDIR)
+from scantools import Scanner_OSX
+from bgenlocations import TOOLBOXDIR
+
+LONG = "CoreGraphics"
+SHORT = "cg"
+OBJECTS = ("CGContextRef", 
+               )
+# ADD object typenames here
+
+def main():
+       input = [
+               "CGContext.h",
+       ]
+       output = SHORT + "gen.py"
+       defsoutput = TOOLBOXDIR + LONG + ".py"
+       scanner = MyScanner(input, output, defsoutput)
+       scanner.scan()
+       scanner.gentypetest(SHORT+"typetest.py")
+       scanner.close()
+       print "=== Done scanning and generating, now importing the generated code... ==="
+       exec "import " + SHORT + "support"
+       print "=== Done.  It's up to you to compile it now! ==="
+
+class MyScanner(Scanner_OSX):
+
+       def destination(self, type, name, arglist):
+               classname = "Function"
+               listname = "functions"
+               if arglist:
+                       t, n, m = arglist[0]
+                       if t in OBJECTS and m == "InMode":
+                               classname = "Method"
+                               listname = t + "_methods"
+                       # Special case for the silly first AllocatorRef argument
+                       if t == 'CFAllocatorRef' and m == 'InMode' and len(arglist) > 1:
+                               t, n, m = arglist[1]
+                               if t in OBJECTS and m == "InMode":
+                                       classname = "MethodSkipArg1"
+                                       listname = t + "_methods"
+               return classname, listname
+
+       def writeinitialdefs(self):
+               self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
+
+       def makeblacklistnames(self):
+               return [
+                       "CGContextRetain",
+                       "CGContextRelease",
+                       ]
+
+       def makegreylist(self):
+               return []
+
+       def makeblacklisttypes(self):
+               return [
+                       "float_ptr",
+                       "CGRect_ptr",
+                       "CGPoint_ptr",
+                       "CGColorSpaceRef",
+                       "CGColorRenderingIntent",
+                       "CGFontRef",
+#                      "char_ptr",
+                       "CGGlyph_ptr",
+                       "CGImageRef",
+                       "CGPDFDocumentRef",
+                       ]
+
+       def makerepairinstructions(self):
+               return [
+                       ([("char_ptr", "cstring", "InMode"), ("size_t", "length", "InMode")],
+                        [("InBuffer", "*", "*")]),
+#                      ([("char_ptr", "name", "InMode"),],
+#                       [("CCCCC", "*", "*")]),
+                       ]
+                       
+if __name__ == "__main__":
+       main()
diff --git a/Mac/Modules/cg/cgsupport.py b/Mac/Modules/cg/cgsupport.py
new file mode 100755 (executable)
index 0000000..4ec56e4
--- /dev/null
@@ -0,0 +1,305 @@
+# This script generates a Python interface for an Apple Macintosh Manager.
+# It uses the "bgen" package to generate C code.
+# The function specifications are generated by scanning the mamager's header file,
+# using the "scantools" package (customized for this particular manager).
+
+#error missing SetActionFilter
+
+import string
+
+# Declarations that change for each manager
+MODNAME = '_CG'                                # The name of the module
+
+# The following is *usually* unchanged but may still require tuning
+MODPREFIX = 'CG'                       # The prefix for module-wide routines
+INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
+OUTPUTFILE = MODNAME + "module.c"      # The file generated by this program
+
+from macsupport import *
+
+
+# Create the type objects
+
+includestuff = includestuff + """
+#ifdef WITHOUT_FRAMEWORKS
+#include <Quickdraw.h>
+#include <CGContext.h>
+#else
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if !TARGET_API_MAC_OSX
+       /* This code is adapted from the CallMachOFramework demo at:
+       http://developer.apple.com/samplecode/Sample_Code/Runtime_Architecture/CallMachOFramework.htm
+       It allows us to call Mach-O functions from CFM apps. */
+
+       #include <Folders.h>
+       #include "CFMLateImport.h"
+
+       static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr)
+               // This routine finds a the named framework and creates a CFBundle 
+               // object for it.  It looks for the framework in the frameworks folder, 
+               // as defined by the Folder Manager.  Currently this is 
+               // "/System/Library/Frameworks", but we recommend that you avoid hard coded 
+               // paths to ensure future compatibility.
+               //
+               // You might think that you could use CFBundleGetBundleWithIdentifier but 
+               // that only finds bundles that are already loaded into your context. 
+               // That would work in the case of the System framework but it wouldn't 
+               // work if you're using some other, less-obvious, framework.
+       {
+               OSStatus        err;
+               FSRef           frameworksFolderRef;
+               CFURLRef        baseURL;
+               CFURLRef        bundleURL;
+               
+               *bundlePtr = nil;
+               
+               baseURL = nil;
+               bundleURL = nil;
+               
+               // Find the frameworks folder and create a URL for it.
+               
+               err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
+               if (err == noErr) {
+                       baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
+                       if (baseURL == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               
+               // Append the name of the framework to the URL.
+               
+               if (err == noErr) {
+                       bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false);
+                       if (bundleURL == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               
+               // Create a bundle based on that URL and load the bundle into memory.
+               // We never unload the bundle, which is reasonable in this case because 
+               // the sample assumes that you'll be calling functions from this 
+               // framework throughout the life of your application.
+               
+               if (err == noErr) {
+                       *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
+                       if (*bundlePtr == nil) {
+                               err = coreFoundationUnknownErr;
+                       }
+               }
+               if (err == noErr) {
+                   if ( ! CFBundleLoadExecutable( *bundlePtr ) ) {
+                               err = coreFoundationUnknownErr;
+                   }
+               }
+
+               // Clean up.
+               
+               if (err != noErr && *bundlePtr != nil) {
+                       CFRelease(*bundlePtr);
+                       *bundlePtr = nil;
+               }
+               if (bundleURL != nil) {
+                       CFRelease(bundleURL);
+               }       
+               if (baseURL != nil) {
+                       CFRelease(baseURL);
+               }       
+               
+               return err;
+       }
+
+
+
+       // The CFMLateImport approach requires that you define a fragment 
+       // initialisation routine that latches the fragment's connection 
+       // ID and locator.  If your code already has a fragment initialiser 
+       // you will have to integrate the following into it.
+
+       static CFragConnectionID                        gFragToFixConnID;
+       static FSSpec                                           gFragToFixFile;
+       static CFragSystem7DiskFlatLocator      gFragToFixLocator;
+
+       extern OSErr FragmentInit(const CFragInitBlock *initBlock);
+       extern OSErr FragmentInit(const CFragInitBlock *initBlock)
+       {
+               __initialize(initBlock); /* call the "original" initializer */
+               gFragToFixConnID        = (CFragConnectionID) initBlock->closureID;
+               gFragToFixFile          = *(initBlock->fragLocator.u.onDisk.fileSpec);
+               gFragToFixLocator       = initBlock->fragLocator.u.onDisk;
+               gFragToFixLocator.fileSpec = &gFragToFixFile;
+               
+               return noErr;
+       }
+
+#endif
+
+extern int GrafObj_Convert(PyObject *, GrafPtr *);
+
+/*
+** Manual converters
+*/
+
+PyObject *CGPoint_New(CGPoint *itself)
+{
+
+       return Py_BuildValue("(ff)",
+                       itself->x,
+                       itself->y);
+}
+
+int
+CGPoint_Convert(PyObject *v, CGPoint *p_itself)
+{
+       if( !PyArg_Parse(v, "(ff)",
+                       &p_itself->x,
+                       &p_itself->y) )
+               return 0;
+       return 1;
+}
+
+PyObject *CGRect_New(CGRect *itself)
+{
+
+       return Py_BuildValue("(ffff)",
+                       itself->origin.x,
+                       itself->origin.y,
+                       itself->size.width,
+                       itself->size.height);
+}
+
+int
+CGRect_Convert(PyObject *v, CGRect *p_itself)
+{
+       if( !PyArg_Parse(v, "(ffff)",
+                       &p_itself->origin.x,
+                       &p_itself->origin.y,
+                       &p_itself->size.width,
+                       &p_itself->size.height) )
+               return 0;
+       return 1;
+}
+
+PyObject *CGAffineTransform_New(CGAffineTransform *itself)
+{
+
+       return Py_BuildValue("(ffffff)",
+                       itself->a,
+                       itself->b,
+                       itself->c,
+                       itself->d,
+                       itself->tx,
+                       itself->ty);
+}
+
+int
+CGAffineTransform_Convert(PyObject *v, CGAffineTransform *p_itself)
+{
+       if( !PyArg_Parse(v, "(ffffff)",
+                       &p_itself->a,
+                       &p_itself->b,
+                       &p_itself->c,
+                       &p_itself->d,
+                       &p_itself->tx,
+                       &p_itself->ty) )
+               return 0;
+       return 1;
+}
+"""
+
+initstuff = initstuff + """
+#if !TARGET_API_MAC_OSX
+CFBundleRef sysBundle;
+OSStatus err;
+
+if (&LoadFrameworkBundle == NULL) {
+       PyErr_SetString(PyExc_ImportError, "CoreCraphics not supported");
+       return;
+}
+err = LoadFrameworkBundle(CFSTR("ApplicationServices.framework"), &sysBundle);
+if (err == noErr)
+       err = CFMLateImportBundle(&gFragToFixLocator, gFragToFixConnID, FragmentInit, "\pCGStubLib", sysBundle);
+if (err != noErr) {
+       PyErr_SetString(PyExc_ImportError, "CoreCraphics not supported");
+       return;
+};
+#endif  /* !TARGET_API_MAC_OSX */
+"""
+
+class MyOpaqueByValueType(OpaqueByValueType):
+       """Sort of a mix between OpaqueByValueType and OpaqueType."""
+       def mkvalueArgs(self, name):
+               return "%s, &%s" % (self.new, name)
+
+CGPoint = MyOpaqueByValueType('CGPoint', 'CGPoint')
+CGRect = MyOpaqueByValueType('CGRect', 'CGRect')
+CGAffineTransform = MyOpaqueByValueType('CGAffineTransform', 'CGAffineTransform')
+
+char_ptr = Type("char *", "s")
+
+CGTextEncoding = int
+CGLineCap = int
+CGLineJoin = int
+CGTextDrawingMode = int
+CGPathDrawingMode = int
+
+# The real objects
+CGContextRef = OpaqueByValueType("CGContextRef", "CGContextRefObj")
+
+
+class MyObjectDefinition(GlobalObjectDefinition):
+       def outputStructMembers(self):
+               ObjectDefinition.outputStructMembers(self)
+       def outputCleanupStructMembers(self):
+               Output("CGContextRelease(self->ob_itself);")
+
+
+# Create the generator groups and link them
+module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
+
+CGContextRef_object = MyObjectDefinition('CGContextRef', 'CGContextRefObj', 'CGContextRef')
+
+
+# ADD object here
+
+module.addobject(CGContextRef_object)
+
+
+
+Function = FunctionGenerator
+Method = MethodGenerator
+
+CGContextRef_methods = []
+
+# ADD _methods initializer here
+execfile(INPUTFILE)
+
+CreateCGContextForPort_body = """\
+GrafPtr port;
+CGContextRef ctx;
+OSStatus _err;
+
+if (!PyArg_ParseTuple(_args, "O&", GrafObj_Convert, &port))
+       return NULL;
+
+_err = CreateCGContextForPort(port, &ctx);
+if (_err != noErr)
+       if (_err != noErr) return PyMac_Error(_err);
+_res = Py_BuildValue("O&", CGContextRefObj_New, ctx);
+return _res;
+"""
+
+f = ManualGenerator("CreateCGContextForPort", CreateCGContextForPort_body);
+f.docstring = lambda: "(CGrafPtr) -> CGContextRef"
+module.add(f)
+
+
+# ADD add forloop here
+for f in CGContextRef_methods:
+       CGContextRef_object.add(f)
+
+# generate output (open the output file as late as possible)
+SetOutputFileName(OUTPUTFILE)
+module.generate()
+