[23417] users/rhwood/Pallet

source_changes at macosforge.org source_changes at macosforge.org
Sat Mar 31 11:15:46 PDT 2007


Revision: 23417
          http://trac.macosforge.org/projects/macports/changeset/23417
Author:   rhwood at macports.org
Date:     2007-03-31 11:15:45 -0700 (Sat, 31 Mar 2007)

Log Message:
-----------
Actually add MPTool code

Added Paths:
-----------
    users/rhwood/Pallet/MPTool/
    users/rhwood/Pallet/MPTool/MPAgent.h
    users/rhwood/Pallet/MPTool/MPAgent.m
    users/rhwood/Pallet/MPTool/MPAgentProtocol.h
    users/rhwood/Pallet/MPTool/MPInterp.h
    users/rhwood/Pallet/MPTool/MPInterp.m
    users/rhwood/Pallet/MPTool/MPObject.h
    users/rhwood/Pallet/MPTool/MPObject.m
    users/rhwood/Pallet/MPTool/main.m

Added: users/rhwood/Pallet/MPTool/MPAgent.h
===================================================================
--- users/rhwood/Pallet/MPTool/MPAgent.h	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPAgent.h	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,54 @@
+I //
+//  MPAgent.h
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <Foundation/Foundation.h>
+
+#import "MPAgentProtocol.h"
+#import "MPInterp.h"
+
+ at interface MPAgent : NSObject <MPAgentProtocol>
+{
+
+    NSConnection 			*_connection;
+    
+    NSLock					*_interpLock;
+    
+    MPInterp 				*_interp;
+    NSMutableDictionary 	*_ports;
+    NSDictionary			*_currentOp;
+}
+
+
+ at end
+
+

Added: users/rhwood/Pallet/MPTool/MPAgent.m
===================================================================
--- users/rhwood/Pallet/MPTool/MPAgent.m	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPAgent.m	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,355 @@
+//
+//  MPAgent.h
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "MPAgent.h"
+#import "MPObject.h"
+
+// package info
+static NSString *MPPackageName = @"darwinports";
+static NSString *MPPackageVersion = @"1.0";
+static NSString *MPPackageInit = @"dportinit";
+
+// commands
+static NSString *MPSearchCommand = @"dportsearch";
+static NSString *MPOpenCommand = @"dportopen";
+static NSString *MPExecCommand = @"dportexec";
+static NSString *MPCloseCommand = @"dportclose";
+
+// arguments
+static NSString *MPAnyPortArgument = @".+";
+
+// results
+static NSString *MPYesResult = @"1";
+static NSString *MPNoResult = @"0";
+
+// ui
+static NSString *MPUIPuts = @"ui_puts";
+static NSString *MPUIConfirm = @"ui_confirm";
+static NSString *MPUIYesNo = @"ui_yesno";
+static NSString *MPUIDisplay = @"ui_display"; 
+
+
+ at implementation MPAgent
+/*
+    Serves as a bridge between the GUI app and the tcl interpreter.   Uses distributed objects to communicate with a delegte (GUI front-end).  All values exposed by the APIs to this class are generic objective-c data-types and not TCL MPObjects... clients talking to this class should not know or care that there's a tcl interpreter hiding underneath.   This class should also be the place to encapsulate all knowledge about the internal structure/constants of the ports system so that clients do not need to know about those details.
+    This class is multi-threaded but all port operations are currently serialized (see more comments on this below)\
+    The agent does not cache any information but rather always calls the tcl engine to talk to the ports collection and get the most recent information.   Caching should (and is) performed in the application front-end.    
+*/
+
+/** Init and clean-up **/
+
+
+- (id) init
+{
+    
+    if (self = [super init])
+    {
+
+        _interpLock = [[NSLock alloc] init];
+        _ports = [[NSMutableDictionary alloc] init];
+        
+        // configure our tcl interpreter
+        _interp = [[MPInterp alloc] init];
+        [_interp loadPackage: MPPackageName version: MPPackageVersion usingCommand: MPPackageInit];
+        [_interp redirectCommand: [MPObject objectWithString: MPUIPuts] toObject: self];
+        [_interp redirectCommand: [MPObject objectWithString: MPUIConfirm] toObject: self];
+        [_interp redirectCommand: [MPObject objectWithString: MPUIYesNo] toObject: self];
+        [_interp redirectCommand: [MPObject objectWithString: MPUIDisplay] toObject: self];
+
+        // configure our d.o. connection
+        _connection = [NSConnection defaultConnection];
+        [_connection setRootObject: self];
+        [_connection enableMultipleThreads];
+        if ([_connection registerName: @"MPAgent"] == NO) 
+        {
+            NSLog(@"Couldn't register server on this host.");
+            exit(0);
+        }
+
+        [[NSNotificationCenter defaultCenter] addObserver:self
+            selector: @selector(connectionDidDie:)
+            name: NSConnectionDidDieNotification
+            object: _connection];
+ 
+    }
+    return self;
+
+}
+
+
+- (void) dealloc
+{
+    [_interp release];
+    [_interpLock release];
+    [super dealloc];
+}
+
+
+/** D.O. connection management **/
+
+
+- (void) connectionDidDie: (id)connection
+{
+    exit(0);
+}
+
+
+- (oneway void) terminate
+{
+    [self performSelector: @selector(connectionDidDie:) withObject: self afterDelay: 0.0];
+}
+
+
+
+/** Port operations **/
+
+
+- (bycopy NSData *) portsData
+/*
+    Returns a serialized property list describing the ports collection
+*/
+{
+    
+    Tcl_Obj **objv;
+    int count = 0, i=0;
+    MPObject *result;
+    NSString *error;
+    NSData *portsData;
+    
+    [_interpLock lock];    
+    
+    [_ports removeAllObjects];
+    result = [_interp evaluateCommand: [MPObject objectWithString: MPSearchCommand] 
+        withObject: [MPObject objectWithString: MPAnyPortArgument]];
+    Tcl_ListObjGetElements(NULL, [result tclObj], &count, &objv);
+
+    while (++i < count) 
+    {	
+
+        NSMutableDictionary *portDict = [NSMutableDictionary dictionary];
+        Tcl_Obj **innerobjs;
+        int innercount = 0, j = 0;    
+        Tcl_ListObjGetElements(NULL, objv[i++], &innercount, &innerobjs);
+
+        while (j < innercount)
+        {
+
+            MPObject *keyObject = [MPObject objectWithTclObj: innerobjs[j++]];
+            MPObject *valueObject = [MPObject objectWithTclObj: innerobjs[j++]];
+            NSString *key = [keyObject stringValue];
+            id value;
+            
+            if ([key isEqualToString: MPCategoriesKey] ||
+                [key isEqualToString: MPMaintainersKey])
+            {
+                NSEnumerator *enm = [[[valueObject stringValue] componentsSeparatedByString: @" "] objectEnumerator];
+                NSString *component;
+                value = [NSMutableArray array];
+                while (component = [enm nextObject])
+                {
+                    if (![value containsObject: component])
+                    {
+                        [value addObject: component];
+                    }
+                }
+    
+            }
+            else if ([key rangeOfString: MPDependsKey].location != NSNotFound)
+            {
+                NSEnumerator *dependencyEnm = [[[valueObject stringValue] componentsSeparatedByString: @" "] objectEnumerator];
+                NSString *component;
+                value = [NSMutableArray array];
+                while (component = [dependencyEnm nextObject])
+                {
+                    NSString *dependencyName = [[component componentsSeparatedByString: @":"] objectAtIndex: 2];
+                    if (![value containsObject: dependencyName])
+                    {
+                        [value addObject: dependencyName];
+                    }
+                }
+                key = MPDependsKey;
+            }
+            else
+            {
+                value = [valueObject stringValue];
+            }
+            [portDict setObject: value forKey: key];
+
+        }
+        [_ports setObject: portDict forKey: [portDict objectForKey: MPNameKey]];
+    }
+    [_interpLock unlock];    
+
+    // we serialize the data before returning it so that we can pass a deep copy of
+    // the entire dictionary back in a single D.O. exchange.   if we just pass
+    // a copy of _ports back then the GUI app is still forced to query objects
+    // stored in the dict via d.o. proxies - which is dirt slow when refreshing
+    // the outline view in the GUI    
+    portsData = [NSPropertyListSerialization dataFromPropertyList: _ports 
+        format: NSPropertyListXMLFormat_v1_0 
+        errorDescription: &error];
+
+    return portsData;
+    
+}
+
+
+- (oneway void) executeTarget: (NSString *)target forPortName: (NSString *)portName
+/*
+    Detaches a new thread to perform the specified target on the specified port... 
+*/
+{
+    NSDictionary *op = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
+        portName, @"portName",
+        [MPObject objectWithString: target], @"target",
+        [MPObject objectWithString: [[_ports objectForKey: portName] objectForKey: MPPortURLKey]], @"url",
+        nil];
+    [NSThread detachNewThreadSelector: sel_getUid("_threadForOperation:") 
+        toTarget: self 
+        withObject: op];
+}
+
+
+/** Execution thread methods */
+
+/*
+    Everything beyond this point code executes in secondary threads.  I've made a conscious effort to not share any objects (except for the _interpLock) between the primary thread and the secondary threads to minimize the need to worry about thread-safe data sharing between threads.
+    Even though we have a separate thread for each operation all operations are currently serialized using the _interpLock.   If we wish to allow multiple simultaneous operations in the future then each thread will have to instantiate it's own interpreter (and the gui will also have to be made more flexible to sort out messages coming back from multiple simultaneous operations).   
+    If we allow multiple truly simultaneous operations we also need to think about situations such as what happens if you start installing Port A and Port B both of which have a dependency on C?  Does C get installed twice?  Or even worse what if you start installing port A which depends on port C and simultaneously start uninstalling C?  etc.   For now easier to sidestep the whole issue by serializing everything.
+*/
+
+
+- (void) _threadForOperation: (NSMutableDictionary *)op
+{
+
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];    
+
+    // establish a separate connection for communication from this thread
+    // back to the PortsManager.app
+    NSConnection *connection = [NSConnection connectionWithRegisteredName: @"PMApp" host: nil];
+    id <MPDelegateProtocol> delegate = [connection rootProxy];
+    [connection enableMultipleThreads];    
+    [(NSDistantObject *)delegate setProtocolForProxy:@protocol(MPDelegateProtocol)];
+    [[NSNotificationCenter defaultCenter] addObserver:self
+        selector: @selector(connectionDidDie:)
+        name: NSConnectionDidDieNotification
+        object: connection];
+    [[[NSThread currentThread] threadDictionary] setObject: delegate forKey: @"delegate"];
+    
+    if ([delegate shouldPerformTarget: [[op objectForKey: @"target"] stringValue] forPortName: [op objectForKey: @"portName"]])
+    {
+        MPObject *result = nil;
+        [delegate willPerformTarget: [[op objectForKey: @"target"] stringValue] forPortName: [op objectForKey: @"portName"]];
+        [_interpLock lock]; // this can block for a long time if another op is in progress
+        _currentOp = op;
+        MPObject *workName = [_interp evaluateCommand: [MPObject objectWithString: MPOpenCommand] 
+            withObject: [op objectForKey: @"url"]];
+        if ([_interp succeeded])
+        {
+            result = [_interp evaluateCommand: [MPObject objectWithString: MPExecCommand] 
+                withObjects: workName : [op objectForKey: @"target"]];
+            if ([_interp succeeded]) 
+            {
+                result = [_interp evaluateCommand: [MPObject objectWithString: MPCloseCommand] withObject: workName];            
+            } 
+        }
+        _currentOp = nil;
+        [_interpLock unlock];
+        [delegate didPerformTarget: [[op objectForKey: @"target"] stringValue] forPortName: [op objectForKey: @"portName"] withResult: [result stringValue]];
+    }
+
+    // Be sure to unregister for NSConnectionDidDieNotification before
+    // auto-releasing the connection object
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+        name: NSConnectionDidDieNotification
+        object: connection];
+
+    [op release];
+    [pool release];
+
+}
+
+
+- (MPObject *) ui_puts: (NSArray *)array 
+{
+    NSString *priority= [[array objectAtIndex: 1] stringValue];
+    NSString *message = [[array objectAtIndex: 2] stringValue];
+    BOOL noNewLine = (([array count] > 3) && [[array objectAtIndex:3] containsString: @"-nonewline"]);    
+    id delegate = [[[NSThread currentThread] threadDictionary] objectForKey: @"delegate"];
+    [delegate displayMessage: [NSString stringWithFormat: @"%@%@", message, (noNewLine ? @"" : @"\n")]
+        withPriority: priority
+        forPortName: [_currentOp objectForKey: @"portName"]];        
+    return [MPObject objectWithString: MPYesResult];
+}
+
+
+- (MPObject *) ui_display:(NSArray *) array
+{
+    NSString *filename = [[array objectAtIndex:1] stringValue];
+    NSString *contents = [NSString stringWithContentsOfFile: filename];
+    if (nil != contents) {
+        id delegate = [[[NSThread currentThread] threadDictionary] objectForKey: @"delegate"];
+        [delegate displayMessage: contents 
+                    withPriority: @"msg"
+                     forPortName: [_currentOp objectForKey: @"portName"]];
+        return [MPObject objectWithString: MPYesResult];
+    }
+    NSLog(@"%@ failed %@: %@", @"ui_display", @"stringWithContentsOfFile", filename);
+    return [MPObject objectWithString: MPNoResult];
+}
+
+
+- (MPObject *) ui_confirm: (NSArray *) array 
+{
+    NSString *message = [[array objectAtIndex: 1] stringValue];
+    id delegate = [[[NSThread currentThread] threadDictionary] objectForKey: @"delegate"];
+    BOOL result = [delegate askMessage: message
+                         needsResponse: YES
+                           forPortName: [_currentOp objectForKey: @"portName"]];
+    return [MPObject objectWithString: (result) ? MPYesResult : MPNoResult];
+}
+
+
+- (MPObject *) ui_yesno:(NSArray *) array 
+{
+    NSString *message = [[array objectAtIndex: 1] stringValue];
+    id delegate = [[[NSThread currentThread] threadDictionary] objectForKey: @"delegate"];
+    BOOL result = [delegate askMessage: message
+                         needsResponse: NO
+                           forPortName: [_currentOp objectForKey: @"portName"]];
+    return [MPObject objectWithString: (result) ? MPYesResult : MPNoResult];
+}
+
+
+
+ at end

Added: users/rhwood/Pallet/MPTool/MPAgentProtocol.h
===================================================================
--- users/rhwood/Pallet/MPTool/MPAgentProtocol.h	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPAgentProtocol.h	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,76 @@
+//
+//  MPAgent.h
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// port keys 
+#define MPNameKey				@"name"
+#define MPVersionKey			@"version"
+#define MPPortURLKey			@"porturl"
+#define MPCategoriesKey			@"categories"
+#define MPDependsKey			@"depends_"
+#define MPMaintainersKey		@"maintainers"
+#define MPPlatformsKey			@"platforms"
+#define MPPortDirKey			@"portdir"
+#define MPDescriptionKey		@"description"
+#define MPLongDescriptionKey	@"long_description"
+
+// targets 
+#define MPBuildTarget			@"build"
+#define MPCleanTarget			@"clean"
+#define MPChecksumTarget		@"checksum"
+#define MPConfigureTarget		@"configure"
+#define MPExtractTarget			@"extract"
+#define MPFetchTarget			@"fetch"
+#define MPInstallTarget			@"install"
+#define MPPackageTarget			@"package"
+#define MPPatchTarget			@"patch"
+#define MPUninstallTarget		@"uninstall"
+
+ at protocol MPAgentProtocol
+
+- (bycopy NSData *) portsData;
+- (oneway void) executeTarget: (in bycopy NSString *)target forPortName: (in bycopy NSString *)portName;
+
+ at end
+
+
+ at protocol MPDelegateProtocol
+
+- (oneway void) displayMessage: (in bycopy NSString *)message withPriority: (in bycopy NSString *)priority forPortName: (in bycopy NSString *)portName;
+- (BOOL) askMessage: (in bycopy NSString *)message needsResponse: (in bycopy BOOL)wantsResponse forPortName: (in bycopy NSString *)portName;
+
+- (BOOL) shouldPerformTarget: (in bycopy NSString *)target forPortName: (in bycopy NSString *)portName;
+- (oneway void) willPerformTarget: (in bycopy NSString *)target forPortName: (in bycopy NSString *)portName;
+- (oneway void) didPerformTarget: (in bycopy NSString *)target forPortName: (in bycopy NSString *)portName withResult: (in bycopy NSString *)result;
+
+ at end
+

Added: users/rhwood/Pallet/MPTool/MPInterp.h
===================================================================
--- users/rhwood/Pallet/MPTool/MPInterp.h	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPInterp.h	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,61 @@
+//
+//  MPInterp.h
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#include <tcl.h>
+
+ at class MPObject;
+
+ at interface MPInterp : NSObject 
+{
+    @private
+    Tcl_Interp	*_interp; 
+    int _status;
+}
+
+- (id) init;
+- (BOOL) loadPackage: (NSString *)packageName version: (NSString *)packageVersion usingCommand: (NSString *)packageInit;
+
+- (MPObject *) setVariable: (MPObject *)variable toValue: (MPObject *)value;
+- (MPObject *) getVariable: (MPObject *)variable;
+
+- (MPObject *) evaluateCommand: (MPObject *)command;
+- (MPObject *) evaluateCommand: (MPObject *)command withObject: (MPObject *)arg;
+- (MPObject *) evaluateCommand: (MPObject *)command withObjects: (MPObject *)arg1 :(MPObject *)arg2;
+- (MPObject *) evaluate: (NSArray *)args;
+
+- (BOOL) succeeded;
+
+- (BOOL) redirectCommand: (MPObject *) command toObject: (id)handler;
+
+ at end

Added: users/rhwood/Pallet/MPTool/MPInterp.m
===================================================================
--- users/rhwood/Pallet/MPTool/MPInterp.m	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPInterp.m	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,197 @@
+//
+//  MPInterp.m
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "MPInterp.h"
+#import "MPObject.h"
+
+#import <objc/objc.h>
+
+#define ALLOC_NTYPE(N, TYPE) ((TYPE*) malloc(N * sizeof(TYPE)))
+
+
+ at implementation MPInterp
+/*
+    A thin objective-c wrapper for the tcl interperter - the intent is that this should be a generic TCL interpreter and should not have any specific knowledge of the ports system.
+*/
+
+
+/** Redirect Handler */
+
+SEL makeSelector(NSString *name) {
+    NSString *methodName = [name stringByAppendingString:@":"];
+    return sel_getUid([methodName cString]);
+}
+
+
+//Tcl_CreateObjCommand(_interp, [command cString], MPCommandHandler, handler, NULL);
+int MPCommandHandler(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]) 
+{
+    id handler = (id) clientData;
+    NSMutableArray *array = [NSMutableArray array];
+    int i=0;
+    for (i=0; i<argc; ++i) {
+        MPObject *object = [MPObject objectWithTclObj:objv[i]];
+        [array addObject:object];
+    }
+
+    SEL selector = makeSelector([[array objectAtIndex:0] stringValue]);
+    if (NULL == selector) return TCL_ERROR;
+    
+    MPObject *result = (MPObject *) [handler performSelector:selector withObject:array];
+    if (nil != result)
+        Tcl_SetResult(interp, (char*) [result cString], TCL_VOLATILE);
+
+    return TCL_OK;
+}
+
+
+/** Initialization */
+
+- (id) init 
+{
+    if (self = [super init])
+    {
+        _interp = Tcl_CreateInterp();
+        Tcl_Init(_interp);
+    }
+    return self;
+}
+
+
+- (void) dealloc 
+{
+    Tcl_DeleteInterp(_interp);
+    [super release];
+}
+
+
+- (BOOL) loadPackage: (NSString *)packageName version: (NSString *)packageVersion usingCommand: (NSString *)packageInit //withArguments:(NSArray *)args
+{
+    char *name = (nil != packageName) ? strdup([packageName cString]) : NULL;
+    char *version = (nil != packageVersion) ? strdup([packageVersion cString]) : NULL;
+
+    Tcl_PkgRequire(_interp, name, version, 0);
+    [self evaluateCommand: [MPObject objectWithString: packageInit]];
+
+    if (name) free(name);
+    if (version) free(version);
+
+    return (TCL_OK == _status);
+}
+
+
+/** Variables */
+
+- (MPObject *) setVariable:(MPObject*) variable toValue:(MPObject*) value 
+{
+    if (nil == variable || nil == value) return nil;
+
+    Tcl_Obj *result = Tcl_ObjSetVar2(_interp, [variable tclObj], NULL, [value tclObj], 0);
+    return (nil != result) ? [MPObject objectWithTclObj: result] : nil;
+}
+
+
+- (MPObject *) getVariable:(MPObject*) variable 
+{
+    if (nil == variable) return nil;
+    Tcl_Obj *value = Tcl_ObjGetVar2(_interp, [variable tclObj], NULL, 0);
+    if (nil == value) return nil;
+    return [MPObject objectWithTclObj: value];
+}
+
+/** Evaluation */
+
+- (MPObject *) evaluateCommand: (MPObject *)command 
+{
+    return [self evaluateCommand:command withObjects:nil :nil];
+}
+
+- (MPObject *) evaluateCommand: (MPObject *)command withObject: (MPObject *) arg 
+{
+    return [self evaluateCommand:command withObjects:arg :nil];
+}
+
+- (MPObject *) evaluateCommand: (MPObject *)command withObjects: (MPObject *)arg1: (MPObject *)arg2 
+{
+    NSArray *array = [NSArray arrayWithObjects:command,arg1,arg2,nil];
+    return [self evaluate:array];
+}
+
+
+- (MPObject *) evaluate: (NSArray*)args 
+{
+    const int count = [args count];
+    Tcl_Obj **objv = ALLOC_NTYPE(count, Tcl_Obj*);
+    NSEnumerator *enumerator = [args objectEnumerator];
+    MPObject * object;
+    int i=0;
+
+    while (object = (MPObject *) [enumerator nextObject]) {
+        if ([object isKindOfClass:[MPObject class]])
+            objv[i++] = [object tclObj];
+        else
+            NSLog(@"evaluate: bad argument type %@", [object class]);
+    }
+    _status = TCL_ERROR;
+    _status = Tcl_EvalObjv(_interp, i, objv, 0);
+    MPObject *result = [MPObject objectWithTclObj: Tcl_GetObjResult(_interp)];
+    if (TCL_OK != _status) 
+    {
+        NSLog(@"failed: %@\n args:\t%@", result, args);
+    }
+    free(objv);
+    return result;
+}
+
+- (BOOL) succeeded 
+{
+    return (TCL_OK == _status);
+}
+
+
+/** Notifications */
+
+
+- (BOOL) redirectCommand: (MPObject *)command toObject: (id)handler
+{
+    SEL selector = makeSelector([command stringValue]);
+    if (NULL == selector || ![handler respondsToSelector:selector])
+        return NO;
+    
+    Tcl_CreateObjCommand(_interp, [command cString], MPCommandHandler, handler, NULL);
+    return YES;
+}
+
+
+
+ at end

Added: users/rhwood/Pallet/MPTool/MPObject.h
===================================================================
--- users/rhwood/Pallet/MPTool/MPObject.h	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPObject.h	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,59 @@
+//
+//  MPObject.h
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#include <tcl.h>
+
+ at interface MPObject : NSObject 
+{
+ at private
+    NSString *_cocoaString;  
+    NSDictionary *_cocoaDictionary;  
+    Tcl_Obj *_tclObj;
+}
+
+/** creation **/
++ (MPObject *) objectWithString: (NSString *)string;
++ (MPObject *) objectWithTclObj: (Tcl_Obj *)tclObj;
+- (id) initWithTclObj: (Tcl_Obj*)tclObject;
+
+/** accessors */
+- (Tcl_Obj *) tclObj;
+- (char *) cString;
+- (NSString *) stringValue;
+
+/** comparisons **/
+- (BOOL) isEqual: (id)object;
+- (BOOL) containsString: (NSString *)substring;
+
+ at end

Added: users/rhwood/Pallet/MPTool/MPObject.m
===================================================================
--- users/rhwood/Pallet/MPTool/MPObject.m	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/MPObject.m	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,145 @@
+//
+//  MPObject.m
+//  DarwinPorts
+//
+/*
+ Copyright (c) 2003 Apple Computer, Inc.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "MPObject.h"
+
+
+ at implementation MPObject
+/*
+    Thin obj-c wrapper for TclObj.  Should not have any specific knowledge of darwinports data-types/structures
+*/
+
+
+/** Creation **/
+
+
++ (MPObject *) objectWithString: (NSString *)string
+{
+    static NSMutableDictionary *cachedObjects;
+    MPObject *object = nil;
+    if (!cachedObjects)
+    {
+        cachedObjects = [[NSMutableDictionary alloc] init];
+    }
+    object = [cachedObjects objectForKey: string];
+    if (!object)
+    {
+        const char *cString = [string cString];
+        Tcl_Obj *tclObj = Tcl_NewStringObj(cString, strlen(cString));
+        object = [[[self alloc] initWithTclObj: tclObj] autorelease];
+        [cachedObjects setObject: object forKey: string];
+    }
+    return object;
+}
+
+
++ (MPObject *) objectWithTclObj: (Tcl_Obj *)tclObj
+{
+    return [[[self alloc] initWithTclObj: tclObj] autorelease];
+}
+
+
+- (id) initWithTclObj: (Tcl_Obj *)tclObj
+{
+    if (self = [super init])
+    {
+        _tclObj = tclObj;
+        Tcl_IncrRefCount(_tclObj);
+    }
+    return self;
+}
+
+
+- (void) dealloc 
+{
+    Tcl_DecrRefCount(_tclObj);
+    [_cocoaString release];
+    [_cocoaDictionary release];
+    [super dealloc];
+}
+
+
+/** Accessors */
+
+
+- (Tcl_Obj *) tclObj
+{
+    return _tclObj;
+}
+
+
+- (char *) cString 
+{
+    return Tcl_GetString(_tclObj);
+}
+
+
+- (NSString*) stringValue 
+{
+    if (nil == _cocoaString)
+    {
+        _cocoaString = [[NSString alloc] initWithCString: [self cString]];
+    }
+    return _cocoaString;
+}
+
+
+- (NSString*) description 
+{
+    return [self stringValue];
+}
+
+
+
+/** Comparisons */
+
+
+- (unsigned) hash 
+{
+    return [[self stringValue] hash];
+}
+
+
+- (BOOL) isEqual: (id)object 
+{
+    return [[self stringValue] isEqualToString: [object stringValue]];
+}
+
+
+- (BOOL) containsString: (NSString *)substring 
+{
+    return ([[self stringValue] rangeOfString: substring].location != NSNotFound);
+}
+
+
+ at end

Added: users/rhwood/Pallet/MPTool/main.m
===================================================================
--- users/rhwood/Pallet/MPTool/main.m	                        (rev 0)
+++ users/rhwood/Pallet/MPTool/main.m	2007-03-31 18:15:45 UTC (rev 23417)
@@ -0,0 +1,22 @@
+#import <Foundation/Foundation.h>
+#import "MPAgent.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, const char *argv[])
+{
+
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+    MPAgent *agent;
+
+    setuid(0);
+    
+    agent = [[MPAgent alloc] init];
+
+    [[NSRunLoop currentRunLoop] run];
+
+    [pool release];
+    return 0;
+        
+}
+

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070331/56962c7d/attachment.html


More information about the macports-changes mailing list