[57383] users/toby/objcports

toby at macports.org toby at macports.org
Thu Sep 10 02:46:02 PDT 2009


Revision: 57383
          http://trac.macports.org/changeset/57383
Author:   toby at macports.org
Date:     2009-09-10 02:46:02 -0700 (Thu, 10 Sep 2009)
Log Message:
-----------
finish converting to C - leaks like crazy though

Modified Paths:
--------------
    users/toby/objcports/MPPort.h
    users/toby/objcports/internal.c
    users/toby/objcports/internal.h
    users/toby/objcports/objcports.xcodeproj/project.pbxproj

Added Paths:
-----------
    users/toby/objcports/MPPort.c
    users/toby/objcports/port.c

Removed Paths:
-------------
    users/toby/objcports/MPPort.m
    users/toby/objcports/port.m

Copied: users/toby/objcports/MPPort.c (from rev 57371, users/toby/objcports/MPPort.m)
===================================================================
--- users/toby/objcports/MPPort.c	                        (rev 0)
+++ users/toby/objcports/MPPort.c	2009-09-10 09:46:02 UTC (rev 57383)
@@ -0,0 +1,641 @@
+#include <CoreFoundation/CoreFoundation.h>
+#include <tcl.h>
+#include <sys/utsname.h>
+#include <mach-o/getsect.h>
+
+#include "MPPort.h"
+#include "MPArrayAdditions.h"
+#include "MPStringAdditions.h"
+#include "internal.h"
+
+struct mp_port_s {
+	CFURLRef _url;
+	
+	CFMutableDictionaryRef _variableInfo;
+	CFMutableDictionaryRef _variables;
+	
+	CFMutableArrayRef _platforms;
+	CFMutableDictionaryRef _variants;
+	
+	Tcl_Interp *_interp;
+};
+
+static CFStringRef kPortVariableType = CFSTR("Type");
+static CFStringRef kPortVariableConstant = CFSTR("Constant");
+static CFStringRef kPortVariableDefault = CFSTR("Default");
+static CFStringRef kPortVariableCallback = CFSTR("Callback");
+
+static void command_create(Tcl_Interp *interp, const char *cmdName, ClientData clientData);
+static char *variable_read(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags);
+static int _nslog(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int _fake_boolean(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+static CFStringRef mp_port_portfile(mp_port_t);
+static CFArrayRef mp_port_targets(mp_port_t);
+static CFArrayRef mp_port_variables(mp_port_t);
+static CFArrayRef mp_port_settable_variables(mp_port_t);
+static CFArrayRef mp_port_settable_array_variables(mp_port_t);
+
+static Boolean mp_port_variable_is_array(mp_port_t, CFStringRef var);
+
+// essentially 'commands' from portutil.tcl
+static void
+add_command_var(CFMutableDictionaryRef varinfo, CFStringRef command)
+{
+	CFDictionaryRef emptydict;
+	CFMutableDictionaryRef arraydict;
+
+	emptydict = CFDictionaryCreate(NULL, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+	arraydict = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+	CFDictionarySetValue(arraydict, kPortVariableType, CFSTR("Array"));
+
+	void (^addcomm_block)(CFStringRef, CFDictionaryRef) = ^(CFStringRef format, CFDictionaryRef dict) {
+		CFStringRef tmp;
+
+		tmp = CFStringCreateWithFormat(NULL, NULL, format, command);
+		CFDictionarySetValue(varinfo, tmp, dict);
+		CFRelease(tmp);
+	};
+
+	addcomm_block(CFSTR("use_%@"), emptydict);
+	addcomm_block(CFSTR("%@.dir"), emptydict);
+	addcomm_block(CFSTR("%@.pre_args"), arraydict);
+	addcomm_block(CFSTR("%@.args"), arraydict);
+	addcomm_block(CFSTR("%@.post_args"), arraydict);
+	addcomm_block(CFSTR("%@.env"), arraydict);
+	addcomm_block(CFSTR("%@.type"), emptydict);
+	addcomm_block(CFSTR("%@.cmd"), arraydict);
+
+	CFRelease(emptydict);
+	CFRelease(arraydict);
+}
+
+mp_port_t
+mp_port_create(CFURLRef url, CFDictionaryRef options)
+{
+	mp_port_t port;
+	char *sectdata;
+	unsigned long sectsize;
+	CFDataRef vdata;
+
+	port = calloc(1, sizeof(struct mp_port_s));
+
+	port->_url = CFRetain(url);
+
+	port->_platforms = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	port->_variants = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+	port->_variables = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+	sectdata = getsectdata("MacPorts", "variables", &sectsize);
+	assert(sectdata);
+	vdata = CFDataCreateWithBytesNoCopy(NULL, (UInt8 *)sectdata, sectsize, kCFAllocatorNull);
+	port->_variableInfo = (CFMutableDictionaryRef)CFPropertyListCreateWithData(NULL, vdata, kCFPropertyListMutableContainersAndLeaves, NULL, NULL);
+	CFRelease(vdata);
+
+	add_command_var(port->_variableInfo, CFSTR("cvs")); // portfetch.tcl
+	add_command_var(port->_variableInfo, CFSTR("svn")); // portfetch.tcl
+	add_command_var(port->_variableInfo, CFSTR("extract")); // portextract.tcl
+	add_command_var(port->_variableInfo, CFSTR("patch")); // portpatch.tcl
+	add_command_var(port->_variableInfo, CFSTR("configure")); // portconfigure.tcl
+	add_command_var(port->_variableInfo, CFSTR("autoreconf")); // portconfigure.tcl
+	add_command_var(port->_variableInfo, CFSTR("automake")); // portconfigure.tcl
+	add_command_var(port->_variableInfo, CFSTR("autoconf")); // portconfigure.tcl
+	add_command_var(port->_variableInfo, CFSTR("xmkmf")); // portconfigure.tcl
+	add_command_var(port->_variableInfo, CFSTR("build")); // portbuild.tcl
+	add_command_var(port->_variableInfo, CFSTR("test")); // porttest.tcl
+	add_command_var(port->_variableInfo, CFSTR("destroot")); // portdestroot.tcl
+
+	port->_interp = Tcl_CreateInterp();
+	Tcl_MakeSafe(port->_interp);
+	Tcl_UnsetVar(port->_interp, "tcl_version", 0);
+	Tcl_UnsetVar(port->_interp, "tcl_patchLevel", 0);
+	Tcl_UnsetVar(port->_interp, "tcl_platform", 0);
+	Tcl_DeleteCommand(port->_interp, "tell");
+	Tcl_DeleteCommand(port->_interp, "eof");
+	// XXX: etc?
+
+	do {
+		Tcl_Preserve(port->_interp);
+		
+		Tcl_CreateObjCommand(port->_interp, "nslog", _nslog, NULL, NULL); // XXX: debugging
+		//Tcl_Eval(_interp, "nslog [info commands]");
+		
+		command_create(port->_interp, "PortSystem", port);
+		command_create(port->_interp, "PortGroup", port);
+		command_create(port->_interp, "platform", port);
+		command_create(port->_interp, "variant", port);
+
+		CFArrayApplyBlock2(mp_port_targets(port), ^(const void *target) {
+			CFStringRef tmp;
+			char *s;
+
+			s = strdup_cf(target);
+			command_create(port->_interp, s, port);
+			free(s);
+
+			tmp = CFStringCreateWithFormat(NULL, NULL, CFSTR("pre-%@"), target);
+			s = strdup_cf(tmp);
+			command_create(port->_interp, s, port);
+			free(s);
+			CFRelease(tmp);
+
+			tmp = CFStringCreateWithFormat(NULL, NULL, CFSTR("post-%@"), target);
+			s = strdup_cf(tmp);
+			command_create(port->_interp, s, port);
+			free(s);
+			CFRelease(tmp);
+		});
+
+		CFArrayApplyBlock2(mp_port_settable_variables(port), ^(const void *opt) {
+			char *s = strdup_cf(opt);
+			command_create(port->_interp, s, port);
+			free(s);
+		});
+
+		CFArrayApplyBlock2(mp_port_settable_array_variables(port), ^(const void *opt) {
+			CFStringRef tmp;
+			char *s;
+
+			tmp = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-append"), opt);
+			s = strdup_cf(tmp);
+			command_create(port->_interp, s, port);
+			free(s);
+			CFRelease(tmp);
+
+			tmp = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@-delete"), opt);
+			s = strdup_cf(tmp);
+			command_create(port->_interp, s, port);
+			free(s);
+			CFRelease(tmp);
+		});
+		
+		CFArrayApplyBlock2(mp_port_variables(port), ^(const void *var) {
+			char *s = strdup_cf(var);
+			Tcl_TraceVar(port->_interp, s, TCL_TRACE_READS, variable_read, port);
+			free(s);
+		});
+		
+		// bogus targets
+		Tcl_CreateObjCommand(port->_interp, "pre-activate", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "post-activate", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "pre-install", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "post-install", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "post-pkg", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "post-mpkg", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "archive", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "install", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "activate", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "unarchive", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "post-clean", _nslog, NULL, NULL); // XXX: debugging
+		
+		// functions we need to provide (?)
+		Tcl_CreateObjCommand(port->_interp, "variant_isset", _fake_boolean, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "variant_set", _fake_boolean, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "tbool", _fake_boolean, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "strsed", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "suffix", _nslog, NULL, NULL); // XXX: debugging
+		Tcl_CreateObjCommand(port->_interp, "include", _nslog, NULL, NULL); // XXX: debugging
+		
+		// variables that should be constant
+		Tcl_CreateObjCommand(port->_interp, "prefix", _nslog, NULL, NULL);
+		
+		char *s = strdup_cf(mp_port_portfile(port));
+		if (Tcl_EvalFile(port->_interp, s) != TCL_OK) {
+			fprintf(stderr, "Tcl_EvalFile(): %s\n", Tcl_GetStringResult(port->_interp));
+			exit(1);
+		}
+		
+		Tcl_Release(port->_interp);
+	} while (0);
+	
+	return port;
+}
+
+void
+mp_port_destroy(mp_port_t port)
+{
+	CFRelease(port->_url);
+	
+	CFRelease(port->_variableInfo);
+	CFRelease(port->_variables);
+	
+	CFRelease(port->_platforms);
+	CFRelease(port->_variants);
+	
+	Tcl_DeleteInterp(port->_interp);
+
+	free(port); // XXX
+}
+
+CFStringRef
+mp_port_variable(mp_port_t port, CFStringRef name)
+{
+	CFDictionaryRef info;
+	CFTypeRef setValue;
+	CFTypeRef defValue;
+	CFTypeRef callback;
+	CFStringRef ret = nil;
+	
+	info = CFDictionaryGetValue(port->_variableInfo, name);
+	if (info != NULL) {
+		if ((setValue = CFDictionaryGetValue(port->_variables, name))) {
+			if (mp_port_variable_is_array(port, name)) {
+				assert(CFGetTypeID(setValue) == CFArrayGetTypeID());
+				ret = CFStringCreateByCombiningStrings(NULL, setValue, CFSTR(" "));
+			} else {
+				assert(CFGetTypeID(setValue) == CFStringGetTypeID());
+				ret = CFRetain(setValue);
+			}
+		} else if ((defValue = CFDictionaryGetValue(info, kPortVariableDefault))) {
+			ret = CFRetain(defValue);
+		} else if ((callback = CFDictionaryGetValue(info, kPortVariableCallback))) {
+			assert(CFGetTypeID(callback) == CFStringGetTypeID());
+			// XXX
+			//ret = [self performSelector:NSSelectorFromString(callback) withObject:name];
+			ret = CFSTR("callback unimplemented");
+		} else {
+			ret = CFSTR("");
+		}
+		char *s = strdup_cf(ret);
+		ret = CFStringCreateWithTclObject(NULL, Tcl_SubstObj(port->_interp, Tcl_NewStringObj(s, -1), TCL_SUBST_VARIABLES));
+		free(s);
+	} else {
+		fprintf_cf(stderr, CFSTR("WARNING: unknown variable %@\n"), name);
+	}
+	return ret;
+}
+
+CFStringRef
+mp_port_portfile(mp_port_t port)
+{
+	CFStringRef path;
+	path = CFURLCopyStrictPath(port->_url, NULL);
+	return CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/Portfile"), path);
+}
+
+CFArrayRef
+mp_port_targets(mp_port_t port)
+{
+	CFMutableArrayRef results;
+
+	results = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	CFArrayAppendValue(results, CFSTR("fetch"));
+	CFArrayAppendValue(results, CFSTR("checksum"));
+	CFArrayAppendValue(results, CFSTR("extract"));
+	CFArrayAppendValue(results, CFSTR("patch"));
+	CFArrayAppendValue(results, CFSTR("configure"));
+	CFArrayAppendValue(results, CFSTR("build"));
+	CFArrayAppendValue(results, CFSTR("test"));
+	CFArrayAppendValue(results, CFSTR("destroot"));
+
+	return results;
+}
+
+static Boolean
+mp_port_is_target(mp_port_t port, CFStringRef target)
+{
+	CFArrayRef tmp;
+
+	if (CFStringHasPrefix(target, CFSTR("pre-"))) {
+		target = CFStringCreateWithSubstring(NULL, target, CFRangeMake(4, CFStringGetLength(target) - 4));
+	} else if (CFStringHasPrefix(target, CFSTR("post-"))) {
+		target = CFStringCreateWithSubstring(NULL, target, CFRangeMake(5, CFStringGetLength(target) - 5));
+	}
+
+	tmp = mp_port_targets(port);
+	return CFArrayContainsValue(tmp, CFRangeMake(0, CFArrayGetCount(tmp)), target);
+}
+
+CFArrayRef
+mp_port_variables(mp_port_t port)
+{
+	CFIndex count = CFDictionaryGetCount(port->_variableInfo);
+	const void *keys[count];
+	CFArrayRef vars;
+
+	CFDictionaryGetKeysAndValues(port->_variableInfo, keys, NULL);
+	vars = CFArrayCreate(NULL, keys, count, &kCFTypeArrayCallBacks);
+
+	return vars;
+}
+
+static Boolean
+mp_port_variable_is_array(mp_port_t port, CFStringRef var)
+{
+	CFStringRef type;
+
+	type = CFDictionaryGetValue(CFDictionaryGetValue(port->_variableInfo, var), kPortVariableType);
+	return type && (CFStringCompare(type, CFSTR("Array"), 0) == kCFCompareEqualTo);
+}
+
+CFArrayRef
+mp_port_settable_variables(mp_port_t port)
+{
+	CFMutableArrayRef ret = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	CFArrayApplyBlock2(mp_port_variables(port), ^(const void *var) {
+		CFNumberRef constant = CFDictionaryGetValue(CFDictionaryGetValue(port->_variableInfo, var), kPortVariableConstant);
+		CFIndex b = 0;
+		if (constant) CFNumberGetValue(constant, kCFNumberCFIndexType, &b);
+
+		if (constant == NULL || b == 0) {
+			CFArrayAppendValue(ret, var);
+		}
+	});
+	return ret;
+}
+
+CFArrayRef
+mp_port_settable_array_variables(mp_port_t port)
+{
+	CFMutableArrayRef ret = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	CFArrayApplyBlock2(mp_port_settable_variables(port), ^(const void *var) {
+		if (mp_port_variable_is_array(port, var)) {
+			CFArrayAppendValue(ret, var);
+		}
+	});
+	return ret;
+}
+
+void
+mp_port_variable_set(mp_port_t port, CFStringRef var, CFArrayRef value)
+{
+	if (mp_port_variable_is_array(port, var)) {
+		CFDictionarySetValue(port->_variables, var, value);
+	} else {
+		CFStringRef str = CFStringCreateByCombiningStrings(NULL, value, CFSTR(" "));
+		CFDictionarySetValue(port->_variables, var, str);
+		CFRelease(str);
+	}
+}
+
+void
+mp_port_variable_append(mp_port_t port, CFStringRef var, CFArrayRef value)
+{
+	CFTypeRef old = CFDictionaryGetValue(port->_variables, var);
+	if (old) {
+		CFMutableArrayRef array;
+
+		assert(CFGetTypeID(old) == CFArrayGetTypeID());
+
+		array = CFArrayCreateMutableCopy(NULL, 0, old);
+		CFArrayAppendArray(array, value, CFRangeMake(0, CFArrayGetCount(value)));
+		CFDictionarySetValue(port->_variables, var, array);
+		CFRelease(array);
+	} else {
+		CFDictionarySetValue(port->_variables, var, value);
+	}
+}
+
+void
+mp_port_variable_delete(mp_port_t port, CFStringRef var, CFArrayRef value)
+{
+	CFTypeRef old;
+	CFMutableArrayRef tmp;
+
+	old = CFDictionaryGetValue(port->_variables, var);
+	if (old == NULL) {
+		return;
+	}
+	assert(CFGetTypeID(old) == CFArrayGetTypeID());
+	tmp = CFArrayCreateMutableCopy(NULL, 0, old);
+	CFArrayApplyBlock2(value, ^(const void *v) {
+		CFArrayRemoveValueAtIndex(tmp, CFArrayGetFirstIndexOfValue(tmp, CFRangeMake(0, CFArrayGetCount(tmp)), v));
+	});
+	CFDictionarySetValue(port->_variables, var, tmp);
+	CFRelease(tmp);
+}
+
+CFArrayRef
+mp_port_defined_platforms(mp_port_t port)
+{
+	CFMutableArrayRef ret = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	CFArrayApplyBlock2(port->_platforms, ^(const void *plat) {
+		CFStringRef tmp = CFStringCreateByCombiningStrings(NULL, plat, CFSTR("_"));
+		CFArrayAppendValue(ret, tmp);
+		CFRelease(tmp);
+	});
+	return ret;
+}
+
+Boolean
+mp_port_test_and_record_platform(mp_port_t port, CFArrayRef platform)
+{
+	struct utsname u;
+	CFStringRef os;
+	CFStringRef release;
+	CFStringRef arch;
+	CFTypeRef tmp;
+	
+	CFArrayAppendValue(port->_platforms, platform);
+	
+	assert(uname(&u) == 0);
+	os = CFStringCreateWithCString(NULL, u.sysname, kCFStringEncodingUTF8);
+	release = CFStringCreateWithCString(NULL, u.release, kCFStringEncodingUTF8);
+	arch = CFStringCreateWithCString(NULL, u.machine, kCFStringEncodingUTF8);
+	
+	tmp = CFArrayGetValueAtIndex(platform, 0);
+	if (tmp != kCFNull && CFStringCompare(tmp, os, kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
+		return FALSE;
+	}
+	
+	tmp = CFArrayGetValueAtIndex(platform, 1);
+	if (tmp != kCFNull && CFStringCompare(tmp, release, kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
+		return FALSE;
+	}
+	
+	tmp = CFArrayGetValueAtIndex(platform, 2);
+	if (tmp != kCFNull && CFStringCompare(tmp, arch, kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
+		return FALSE;
+	}
+	
+	return TRUE;
+}
+
+CFArrayRef
+mp_port_defined_variants(mp_port_t port)
+{
+	CFIndex count = CFDictionaryGetCount(port->_variants);
+	const void *keys[count];
+	CFArrayRef vars;
+	
+	CFDictionaryGetKeysAndValues(port->_variants, keys, NULL);
+	vars = CFArrayCreate(NULL, keys, count, &kCFTypeArrayCallBacks);
+	
+	return vars;
+}
+
+Boolean
+mp_port_test_and_record_variant(mp_port_t port, CFStringRef variant, CFDictionaryRef props)
+{
+	// XXX: check for dupes (w/ platforms too)
+	CFDictionarySetValue(port->_variants, variant, props);
+	// XXX: make sure it's set, like platforms just pretend
+	return TRUE;
+}
+
+void
+mp_port_perform_command(mp_port_t port, CFArrayRef args)
+{
+	CFStringRef command;
+	CFIndex count;
+
+	command = CFArrayGetValueAtIndex(args, 0);
+	count = CFArrayGetCount(args);
+
+	if (CFStringCompare(command, CFSTR("PortSystem"), 0) == kCFCompareEqualTo) {
+		assert(count == 2);
+		assert(CFStringCompare(CFArrayGetValueAtIndex(args, 1), CFSTR("1.0"), 0) == kCFCompareEqualTo);
+	} else if (CFStringCompare(command, CFSTR("PortGroup"), 0) == kCFCompareEqualTo) {
+		fprintf_cf(stderr, CFSTR("ignoring %@, grps r hard m'kay\n"), command);
+		// XXX: this should probably set some state in parent port instance
+		// (ugh, more tcl parsing)
+	} else if (CFStringCompare(command, CFSTR("platform"), 0) == kCFCompareEqualTo) {
+		CFStringRef os = NULL;
+		CFTypeRef release = kCFNull;
+		CFTypeRef arch = kCFNull;
+		
+		if (count < 3 || count > 5) {
+			fprintf(stderr, "bogus platform declaration\n");
+			return;
+		}
+		
+		os = CFArrayGetValueAtIndex(args, 1);
+		
+		if (count == 4) {
+			SInt32 rel = CFStringGetIntValue(CFArrayGetValueAtIndex(args, 2));
+			if (rel != 0) {
+				release = CFNumberCreate(NULL, kCFNumberIntType, &rel);
+			} else {
+				arch = CFArrayGetValueAtIndex(args, 2);
+			}
+		} else if (count == 5) {
+			SInt32 rel = CFStringGetIntValue(CFArrayGetValueAtIndex(args, 2));
+			release = CFNumberCreate(NULL, kCFNumberIntType, &rel);
+			arch = CFArrayGetValueAtIndex(args, 3);
+		}
+		
+		CFMutableArrayRef platform = CFArrayCreateMutable(NULL, 3, &kCFTypeArrayCallBacks);
+		CFArrayAppendValue(platform, os);
+		CFArrayAppendValue(platform, release);
+		CFArrayAppendValue(platform, arch);
+
+		if (mp_port_test_and_record_platform(port, platform)) {
+			char *s = strdup_cf(CFArrayGetValueAtIndex(args, count - 1));
+			Tcl_Eval(port->_interp, s);
+			free(s);
+		}
+	} else if (CFStringCompare(command, CFSTR("variant"), 0) == kCFCompareEqualTo) {
+		CFStringRef name;
+		CFMutableDictionaryRef props;
+		CFIndex i;
+		
+		// variant name [a b c d] {}
+		if (count < 3) {
+			fprintf(stderr, "bogus variant declaration\n");
+			return;
+		}
+		
+		name = CFArrayGetValueAtIndex(args, 1);
+		
+		// this isn't quite right, conflicts can take multiple "arguments"
+		props = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ 		for (i = 2; i < count - 1; i += 2) {
+			CFDictionarySetValue(props, CFArrayGetValueAtIndex(args, i), CFArrayGetValueAtIndex(args, i + 1));
+		}
+		
+		if (mp_port_test_and_record_variant(port, name, props)) {
+			char *s = strdup_cf(CFArrayGetValueAtIndex(args, count - 1));
+			Tcl_Eval(port->_interp, s);
+			free(s);
+		}
+	} else if (mp_port_is_target(port, command)) {
+		// XXX: store for later use...
+	} else {
+		const void *values[count - 1];
+		CFArrayRef foo;
+		CFStringRef tmp;
+
+		CFArrayGetValues(args, CFRangeMake(1, count - 1), values);
+		foo = CFArrayCreate(NULL, values, count - 1, &kCFTypeArrayCallBacks);
+
+		if (CFStringHasSuffix(command, CFSTR("-append"))) {
+			tmp = CFStringCreateWithSubstring(NULL, command, CFRangeMake(0, CFStringGetLength(command) - 7));
+			mp_port_variable_append(port, tmp, foo);
+			CFRelease(tmp);
+		} else if (CFStringHasSuffix(command, CFSTR("-delete"))) {
+			tmp = CFStringCreateWithSubstring(NULL, command, CFRangeMake(0, CFStringGetLength(command) - 7));
+			mp_port_variable_delete(port, tmp, foo);
+			CFRelease(tmp);
+		} else {
+			mp_port_variable_set(port, command, foo);
+		}
+	}
+}
+
+static int
+command_trampoline(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+	CFArrayRef args = CFArrayCreateWithTclObjects(NULL, objv, objc);
+	mp_port_perform_command(clientData, args);
+	CFRelease(args);
+	
+	return TCL_OK;
+}
+
+static void
+command_create(Tcl_Interp *interp, const char *cmdName, ClientData clientData)
+{
+	Tcl_CmdInfo info;
+	if (Tcl_GetCommandInfo(interp, cmdName, &info) != 0) {
+		fprintf(stderr, "Command '%s' already exists, bailing.", cmdName);
+		abort();
+	}
+	Tcl_CreateObjCommand(interp, cmdName, command_trampoline, clientData, NULL);
+}
+
+static char *
+variable_read(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags)
+{
+	CFStringRef tmp, var;
+	char *s;
+
+	tmp = CFStringCreateWithCString(NULL, name1, kCFStringEncodingUTF8);
+	var = mp_port_variable(clientData, tmp);
+	CFRelease(tmp);
+
+	assert(var != nil);
+
+	s = strdup_cf(var);
+	Tcl_SetVar2(interp, name1, name2, s, 0);
+	free(s);
+
+	return NULL;
+}
+
+// debugging
+static int
+_nslog(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+	CFArrayRef args;
+	CFStringRef str;
+
+	args = CFArrayCreateWithTclObjects(NULL, ++objv, --objc);
+	if (args) {
+		str = CFStringCreateByCombiningStrings(NULL, args, CFSTR(" "));
+		if (str) {
+			CFShow(str);
+			CFRelease(str);
+		}
+		CFRelease(args);
+	}
+	
+	return TCL_OK;
+}
+
+static int
+_fake_boolean(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+	return TCL_OK;
+}

Modified: users/toby/objcports/MPPort.h
===================================================================
--- users/toby/objcports/MPPort.h	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/MPPort.h	2009-09-10 09:46:02 UTC (rev 57383)
@@ -1,21 +1,7 @@
- at class MPParser;
+typedef struct mp_port_s *mp_port_t;
 
- at interface MPPort : NSObject
-{
-	NSURL *_url;
-
-	NSMutableDictionary *_variableInfo;
-	NSMutableDictionary *_variables;
-
-	NSMutableArray *_platforms;
-	NSMutableDictionary *_variants;
-
-	Tcl_Interp *_interp;
-}
-
-- (id)initWithPath:(NSString *)url options:(NSDictionary *)options;
-- (NSString *)variable:(NSString *)name;
-- (NSArray *)definedVariants;
-- (NSArray *)definedPlatforms;
-
- at end
+mp_port_t mp_port_create(CFURLRef url, CFDictionaryRef options);
+void mp_port_destroy(mp_port_t port);
+CFStringRef mp_port_variable(mp_port_t port, CFStringRef var);
+CFArrayRef mp_port_defined_variants(mp_port_t port);
+CFArrayRef mp_port_defined_platforms(mp_port_t port);

Deleted: users/toby/objcports/MPPort.m
===================================================================
--- users/toby/objcports/MPPort.m	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/MPPort.m	2009-09-10 09:46:02 UTC (rev 57383)
@@ -1,557 +0,0 @@
-#include <Foundation/Foundation.h>
-#include <tcl.h>
-#include <sys/utsname.h>
-#include <mach-o/getsect.h>
-
-#include "MPPort.h"
-#include "MPArrayAdditions.h"
-#include "MPStringAdditions.h"
-#include "internal.h"
-
-static NSString *kPortVariableType = @"Type";
-static NSString *kPortVariableConstant = @"Constant";
-static NSString *kPortVariableDefault = @"Default";
-static NSString *kPortVariableCallback = @"Callback";
-
-static void command_create(Tcl_Interp *interp, const char *cmdName, ClientData clientData);
-static char *variable_read(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags);
-static int _nslog(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
-static int _fake_boolean(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
-
- at interface MPPort (private)
-- (NSString *)portfile;
-- (NSArray *)targets;
-- (NSArray *)variables;
-- (NSArray *)settableVariables;
-- (NSArray *)settableArrayVariables;
- at end
-
- at implementation MPPort
-
-- (id)initWithURL:(NSURL *)url options:(NSDictionary *)options
-{
-	char *sectdata;
-	unsigned long sectsize;
-	NSData *vdata;
-
-	self = [super init];
-	_url = [url retain];
-
-	_platforms = [[NSMutableArray alloc] initWithCapacity:0];
-	_variants = [[NSMutableDictionary alloc] initWithCapacity:0];
-
-	_variables = [[NSMutableDictionary alloc] initWithCapacity:0];
-
-	//_variableInfo = [[NSMutableDictionary alloc] initWithContentsOfFile:@"variables.plist"];
-	sectdata = getsectdata("MacPorts", "variables", &sectsize);
-	assert(sectdata);
-	vdata = [[NSData alloc] initWithBytesNoCopy:sectdata length:sectsize freeWhenDone:NO];
-	_variableInfo = [[NSPropertyListSerialization propertyListWithData:vdata options:kCFPropertyListMutableContainersAndLeaves format:NULL error:NULL] retain];
-	[vdata release];
-
-	NSArray *commands = [NSArray arrayWithObjects:
-		@"cvs", // portfetch.tcl
-		@"svn", // portfetch.tcl
-		@"extract", // portextract.tcl
-		@"patch", // portpatch.tcl
-		@"configure", // portconfigure.tcl
-		@"autoreconf", // portconfigure.tcl
-		@"automake", // portconfigure.tcl
-		@"autoconf", // portconfigure.tcl
-		@"xmkmf", // portconfigure.tcl
-		@"build", // portbuild.tcl
-		@"test", // porttest.tcl
-		@"destroot", // portdestroot.tcl
-		nil];
-
-	// essentially 'commands' from portutil.tcl
-	for (NSString *command in commands) {
-		[_variableInfo setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"use_%@", command]];
-		[_variableInfo setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"%@.dir", command]];
-		[_variableInfo setObject:[NSDictionary dictionaryWithObject:@"Array" forKey:kPortVariableType] forKey:[NSString stringWithFormat:@"%@.pre_args", command]];
-		[_variableInfo setObject:[NSDictionary dictionaryWithObject:@"Array" forKey:kPortVariableType] forKey:[NSString stringWithFormat:@"%@.args", command]];
-		[_variableInfo setObject:[NSDictionary dictionaryWithObject:@"Array" forKey:kPortVariableType] forKey:[NSString stringWithFormat:@"%@.post_args", command]];
-		[_variableInfo setObject:[NSDictionary dictionaryWithObject:@"Array" forKey:kPortVariableType] forKey:[NSString stringWithFormat:@"%@.env", command]];
-		[_variableInfo setObject:[NSDictionary dictionary] forKey:[NSString stringWithFormat:@"%@.type", command]];
-		[_variableInfo setObject:[NSDictionary dictionaryWithObject:@"Array" forKey:kPortVariableType] forKey:[NSString stringWithFormat:@"%@.cmd", command]];
-	}
-
-	_interp = Tcl_CreateInterp();
-	Tcl_MakeSafe(_interp);
-	Tcl_UnsetVar(_interp, "tcl_version", 0);
-	Tcl_UnsetVar(_interp, "tcl_patchLevel", 0);
-	Tcl_UnsetVar(_interp, "tcl_platform", 0);
-	Tcl_DeleteCommand(_interp, "tell");
-	Tcl_DeleteCommand(_interp, "eof");
-	// XXX: etc?
-	
-	@try {
-		Tcl_Preserve(_interp);
-		
-		Tcl_CreateObjCommand(_interp, "nslog", _nslog, NULL, NULL); // XXX: debugging
-		//Tcl_Eval(_interp, "nslog [info commands]");
-		
-		command_create(_interp, "PortSystem", self);
-		command_create(_interp, "PortGroup", self);
-		command_create(_interp, "platform", self);
-		command_create(_interp, "variant", self);
-		
-		for (NSString *target in [self targets]) {
-			command_create(_interp, [target UTF8String], self);
-			command_create(_interp, [[@"pre-" stringByAppendingString:target] UTF8String], self);
-			command_create(_interp, [[@"post-" stringByAppendingString:target] UTF8String], self);
-		}
-		
-		for (NSString *opt in [self settableVariables]) {
-			command_create(_interp, [opt UTF8String], self);
-		}
-		for (NSString *opt in [self settableArrayVariables]) {
-			command_create(_interp, [[opt stringByAppendingString:@"-append"] UTF8String], self);
-			command_create(_interp, [[opt stringByAppendingString:@"-delete"] UTF8String], self);
-		}
-		
-		for (NSString *var in [self variables]) {
-			Tcl_TraceVar(_interp, [var UTF8String], TCL_TRACE_READS, variable_read, self);
-		}
-		
-		// bogus targets
-		Tcl_CreateObjCommand(_interp, "pre-activate", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "post-activate", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "pre-install", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "post-install", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "post-pkg", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "post-mpkg", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "archive", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "install", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "activate", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "unarchive", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "post-clean", _nslog, NULL, NULL); // XXX: debugging
-		
-		// functions we need to provide (?)
-		Tcl_CreateObjCommand(_interp, "variant_isset", _fake_boolean, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "variant_set", _fake_boolean, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "tbool", _fake_boolean, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "strsed", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "suffix", _nslog, NULL, NULL); // XXX: debugging
-		Tcl_CreateObjCommand(_interp, "include", _nslog, NULL, NULL); // XXX: debugging
-		
-		// variables that should be constant
-		Tcl_CreateObjCommand(_interp, "prefix", _nslog, NULL, NULL);
-		
-		if (Tcl_EvalFile(_interp, [[self portfile] UTF8String]) != TCL_OK) {
-			NSLog(@"Tcl_EvalFile(): %s", Tcl_GetStringResult(_interp));
-			exit(1);
-		}
-		
-		Tcl_Release(_interp);
-	}
-	@catch (NSException *exception) {
-		NSLog(@"%@: %@", [exception name], [exception reason]);
-		[self release];
-		self = nil;
-	}
-
-	for (NSString *vv in _variableInfo) {
-		NSLog(@"%@ -- %@ -- %@", vv, [_variables objectForKey:vv], [self variable:vv]);
-	}
-
-	return self;
-}
-
-- (id)initWithPath:(NSString *)path options:(NSDictionary *)options
-{
-	NSString *standardizedPath;
-	NSURL *url;
-
-	standardizedPath = [path stringByStandardizingPath];
-	url = [NSURL fileURLWithPath:standardizedPath isDirectory:YES];
-	return [self initWithURL:url options:options];
-}
-
-- (void)dealloc
-{
-	[_url release];
-
-	[_variableInfo release];
-	[_variables release];
-
-	[_platforms release];
-	[_variants release];
-
-	Tcl_DeleteInterp(_interp);
-
-	[super dealloc];
-}
-
-- (NSString *)portfile
-{
-	return [[_url path] stringByAppendingPathComponent:@"Portfile"];
-}
-
-- (NSArray *)targets
-{
-	return [NSArray arrayWithObjects:
-		@"fetch",
-		@"checksum",
-		@"extract",
-		@"patch",
-		@"configure",
-		@"build",
-		@"test",
-		@"destroot",
-		nil];
-}
-
-- (BOOL)isTarget:(NSString *)target
-{
-	if ([target hasPrefix:@"pre-"]) {
-		target = [target substringWithRange:NSMakeRange(4, [target length] - 4)];
-	} else if ([target hasPrefix:@"post-"]) {
-		target = [target substringWithRange:NSMakeRange(5, [target length] - 5)];
-	}
-
-	return [[self targets] containsObject:target];
-}
-
-- (NSArray *)variables
-{
-	return [_variableInfo allKeys];
-}
-
-- (BOOL)variableIsArray:(NSString *)var
-{
-	NSString *type = [[_variableInfo objectForKey:var] objectForKey:kPortVariableType];
-	return [type isEqualToString:@"Array"];
-}
-
-- (id)defaultCallback:(NSString *)name
-{
-	return @"";
-}
-
-- (id)osInfo:(NSString *)name
-{
-	NSString *ret = nil;
-	int rc;
-	struct utsname u;
-
-	rc = uname(&u);
-	assert(rc == 0);
-
-	if ([name isEqualToString:@"os.platform"]) {
-		ret = [[NSString stringWithUTF8String:u.sysname] lowercaseString];
-	} else if ([name isEqualToString:@"os.arch"]) {
-		ret = [NSString stringWithUTF8String:u.machine];
-	} else if ([name isEqualToString:@"os.endian"]) {
-#ifdef __BIG_ENDIAN__
-		ret = @"big";
-#else
-		ret = @"little";
-#endif
-	} else if ([name isEqualToString:@"os.major"]) {
-		ret = [[[NSString stringWithUTF8String:u.release] componentsSeparatedByString:@"."] objectAtIndex:0];
-	} else if ([name isEqualToString:@"os.version"]) {
-		ret = [NSString stringWithUTF8String:u.release];
-	} else {
-		abort();
-	}
-
-	return ret;
-}
-
-- (NSString *)variable:(NSString *)name
-{
-	NSDictionary *info;
-	id setValue;
-	id defValue;
-	id callback;
-	NSString *ret = nil;
-
-	info = [_variableInfo objectForKey:name];
-	if (info != nil) {
-		if ((setValue = [_variables objectForKey:name])) {
-			if ([self variableIsArray:name]) {
-				NSLog(@"%@ %@", name, setValue);
-				assert([setValue isKindOfClass:[NSArray class]]);
-				ret = [setValue componentsJoinedByString:@" "];
-			} else {
-				assert([setValue isKindOfClass:[NSString class]]);
-				ret = setValue;
-			}
-		} else if ((defValue = [info objectForKey:kPortVariableDefault])) {
-			ret = defValue;
-		} else if ((callback = [info objectForKey:kPortVariableCallback])) {
-			assert([callback isKindOfClass:[NSString class]]);
-			ret = [self performSelector:NSSelectorFromString(callback) withObject:name];
-		} else {
-			ret = [NSString stringWithUTF8String:""];
-		}
-		ret = [(NSString *)CFStringCreateWithTclObject(NULL, Tcl_SubstObj(_interp, Tcl_NewStringObj([ret UTF8String], -1), TCL_SUBST_VARIABLES)) autorelease];
-	} else {
-		NSLog(@"WARNING: unknown variable %@", name);
-	}
-	return ret;
-}
-
-- (NSArray *)settableVariables
-{
-	NSMutableArray *ret = [NSMutableArray arrayWithCapacity:0];
-	for (NSString *var in [self variables]) {
-		NSNumber *constant = [[_variableInfo objectForKey:var] objectForKey:kPortVariableConstant];
-		if (constant == nil || [constant boolValue] == NO) {
-			[ret addObject:var];
-		}
-	}
-	return ret;
-}
-
-- (void)variable:(NSString *)var set:(NSArray *)value
-{
-	if ([self variableIsArray:var]) {
-		[_variables setObject:value forKey:var];
-	} else {
-		[_variables setObject:[value componentsJoinedByString:@" "] forKey:var];
-	}
-}
-
-- (NSArray *)settableArrayVariables
-{
-	NSMutableArray *ret = [NSMutableArray arrayWithCapacity:0];
-	for (NSString *var in [self settableVariables]) {
-		if ([self variableIsArray:var]) {
-			[ret addObject:var];
-		}
-	}
-	return ret;
-}
-
-- (void)variable:(NSString *)var append:(NSArray *)value
-{
-	id old = [_variables objectForKey:var];
-	if (old) {
-		assert([old isKindOfClass:[NSArray class]]);
-		[_variables setObject:[old arrayByAddingObjectsFromArray:value] forKey:var];
-	} else {
-		[_variables setObject:value forKey:var];
-	}
-}
-
-- (void)variable:(NSString *)var delete:(NSArray *)value
-{
-	id old;
-	NSMutableArray *tmp;
-
-	old = [_variables objectForKey:var];
-	if (old == nil) {
-		return;
-	}
-	assert([old isKindOfClass:[NSArray class]]);
-	tmp = [old mutableCopy];
-	for (NSString *v in value) {
-		[tmp removeObject:v];
-	}
-	[_variables setObject:tmp forKey:var];
-	[tmp release];
-}
-
-- (NSArray *)definedPlatforms
-{
-	NSMutableArray *ret = [NSMutableArray arrayWithCapacity:0];
-	for (NSArray *plat in _platforms) {
-		[ret addObject:[plat componentsJoinedByString:@"_"]];
-	}
-	return ret;
-}
-
-- (BOOL)testAndRecordPlatform:(NSArray *)platform
-{
-	struct utsname u;
-	NSString *os;
-	NSNumber *release;
-	NSString *arch;
-	id tmp;
-
-	[_platforms addObject:platform];
-
-	assert(uname(&u) == 0);
-	os = [[NSString stringWithUTF8String:u.sysname] lowercaseString];
-	release = [NSNumber numberWithInteger:[[NSString stringWithUTF8String:u.release] integerValue]];
-	arch = [NSString stringWithUTF8String:u.machine];
-
-	tmp = [platform objectAtIndex:0];
-	if (tmp != [NSNull null] && ![tmp isEqualToString:os]) {
-		return NO;
-	}
-
-	tmp = [platform objectAtIndex:1];
-	if (tmp != [NSNull null] && ![tmp isEqual:release]) {
-		return NO;
-	}
-
-	tmp = [platform objectAtIndex:2];
-	if (tmp != [NSNull null] && ![tmp isEqual:arch]) {
-		return NO;
-	}
-
-	return YES;
-}
-
-- (NSArray *)definedVariants
-{
-	return [_variants allKeys];
-}
-
-- (BOOL)testAndRecordVariant:(NSString *)variant withProperties:(NSDictionary *)props
-{
-	// XXX: check for dupes (w/ platforms too)
-	[_variants setObject:props forKey:variant];
-	// XXX: make sure it's set, like platforms just pretend
-	return YES;
-}
-
-- (void)performCommand:(NSArray *)args
-{
-	NSString *command;
-
-	command = [args objectAtIndex:0];
-
-	if ([command isEqualToString:@"PortSystem"]) {
-		assert([args count] == 2);
-		assert([[args objectAtIndex:1] isEqualToString:@"1.0"]);
-	} else if ([command isEqualToString:@"PortGroup"]) {
-		NSLog(@"ignoring %@, grps r hard m'kay", command);
-		// XXX: this should probably set some state in parent port instance
-		// (ugh, more tcl parsing)
-	} else if ([command isEqualToString:@"platform"]) {
-		NSUInteger count = [args count];
-		NSString *os = nil;
-		id release = [NSNull null];
-		id arch = [NSNull null];
-		
-		if (count < 3 || count > 5) {
-			NSLog(@"bogus platform declaration");
-			return;
-		}
-		
-		os = [args objectAtIndex:1];
-		
-		if (count == 4) {
-			NSInteger rel = [[args objectAtIndex:2] integerValue];
-			if (rel != 0) {
-				release = [NSNumber numberWithInteger:rel];
-			} else {
-				arch = [args objectAtIndex:2];
-			}
-		} else if (count == 5) {
-			release = [NSNumber numberWithInteger:[[args objectAtIndex:2] integerValue]];
-			arch = [args objectAtIndex:3];
-		}
-		
-		if ([self testAndRecordPlatform:[NSArray arrayWithObjects:os, release, arch, nil]]) {
-			Tcl_Eval(_interp, [[args lastObject] UTF8String]);
-		}
-	} else if ([command isEqualToString:@"variant"]) {
-		NSUInteger count = [args count];
-		NSString *name;
-		NSMutableDictionary *props;
-		NSUInteger i;
-		
-		// variant name [a b c d] {}
-		if (count < 3) {
-			NSLog(@"bogus variant declaration");
-			return;
-		}
-		
-		name = [args objectAtIndex:1];
-		
-		// this isn't quite right, conflicts can take multiple "arguments"
-		props = [NSMutableDictionary dictionaryWithCapacity:count-2];
- 		for (i = 2; i < count - 1; i += 2) {
-			[props setObject:[args objectAtIndex:i+1] forKey:[args objectAtIndex:i]];
-		}
-		
-		if ([self testAndRecordVariant:name withProperties:props]) {
-			Tcl_Eval(_interp, [[args lastObject] UTF8String]);
-		}
-	} else if ([self isTarget:command]) {
-		// XXX: store for later use...
-	} else {
-		NSArray *foo = [args subarrayWithRange:NSMakeRange(1, [args count] - 1)];
-		if ([command hasSuffix:@"-append"]) {
-			[self variable:[command substringWithRange:NSMakeRange(0, [command length] - 7)] append:foo];
-		} else if ([command hasSuffix:@"-delete"]) {
-			[self variable:[command substringWithRange:NSMakeRange(0, [command length] - 7)] delete:foo];
-		} else {
-			[self variable:command set:foo];
-		}
-	}
-}
-
- at end
-
-static int
-command_trampoline(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
-	CFArrayRef args = CFArrayCreateWithTclObjects(NULL, objv, objc);
-	[(MPPort *)clientData performCommand:(NSArray *)args];
-	CFRelease(args);
-	
-	return TCL_OK;
-}
-
-static void
-command_create(Tcl_Interp *interp, const char *cmdName, ClientData clientData)
-{
-	Tcl_CmdInfo info;
-	if (Tcl_GetCommandInfo(interp, cmdName, &info) != 0) {
-		fprintf(stderr, "Command '%s' already exists, bailing.", cmdName);
-		abort();
-	}
-	Tcl_CreateObjCommand(interp, cmdName, command_trampoline, clientData, NULL);
-}
-
-static char *
-variable_read(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags)
-{
-	CFStringRef tmp, var;
-	char *s;
-
-	tmp = CFStringCreateWithCString(NULL, name1, kCFStringEncodingUTF8);
-	var = (CFStringRef)[(MPPort *)clientData variable:(NSString *)tmp];
-	CFRelease(tmp);
-
-	assert(var != nil);
-
-	s = strdup_cf(var);
-	Tcl_SetVar2(interp, name1, name2, s, 0);
-	free(s);
-
-	return NULL;
-}
-
-// debugging
-static int
-_nslog(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
-	CFArrayRef args;
-	CFStringRef str;
-
-	args = CFArrayCreateWithTclObjects(NULL, ++objv, --objc);
-	if (args) {
-		str = CFStringCreateByCombiningStrings(NULL, args, CFSTR(" "));
-		if (str) {
-			CFShow(str);
-			CFRelease(str);
-		}
-		CFRelease(args);
-	}
-	
-	return TCL_OK;
-}
-
-static int
-_fake_boolean(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
-	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
-	return TCL_OK;
-}

Modified: users/toby/objcports/internal.c
===================================================================
--- users/toby/objcports/internal.c	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/internal.c	2009-09-10 09:46:02 UTC (rev 57383)
@@ -1,4 +1,5 @@
 #include <CoreFoundation/CoreFoundation.h>
+#include <dispatch/dispatch.h>
 
 #include "internal.h"
 
@@ -19,3 +20,55 @@
 	}
 	return result;
 }
+
+int
+fprintf_cf(FILE *stream, CFStringRef format, ...)
+{
+	va_list ap;
+	CFStringRef str;
+	char *s;
+	int rc;
+
+	va_start(ap, format);
+	str = CFStringCreateWithFormatAndArguments(NULL, NULL, format, ap);
+	va_end(ap);
+
+	s = strdup_cf(str);
+	rc = fprintf(stream, "%s", s);
+	free(s);
+
+	CFRelease(str);
+
+	return rc;
+}
+
+void
+CFArrayApplyBlock(CFArrayRef theArray, CFRange range, CFArrayApplierBlock applier)
+{
+	dispatch_queue_t apply_queue = dispatch_queue_create("CFArrayApplyBlock", NULL);
+	const void *vals[range.length];
+	CFArrayGetValues(theArray, range, vals);
+	dispatch_apply(range.length, apply_queue, ^(size_t i) {
+		applier(vals[i]);
+	});
+	dispatch_release(apply_queue);
+}
+
+void
+CFArrayApplyBlock2(CFArrayRef theArray, CFArrayApplierBlock applier)
+{
+	CFArrayApplyBlock(theArray, CFRangeMake(0, CFArrayGetCount(theArray)), applier);
+}
+
+void
+CFDictionaryApplyBlock(CFDictionaryRef theDict, CFDictionaryApplierBlock applier)
+{
+	dispatch_queue_t apply_queue = dispatch_queue_create("CFDictionaryApplyBlock", NULL);
+	CFIndex count = CFDictionaryGetCount(theDict);
+	const void *keys[count], *vals[count];
+	CFDictionaryGetKeysAndValues(theDict, keys, vals);
+	dispatch_apply(count, apply_queue, ^(size_t i) {
+		applier(keys[i], vals[i]);
+	});
+	dispatch_release(apply_queue);
+}

Modified: users/toby/objcports/internal.h
===================================================================
--- users/toby/objcports/internal.h	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/internal.h	2009-09-10 09:46:02 UTC (rev 57383)
@@ -1 +1,9 @@
 char *strdup_cf(CFStringRef str);
+int fprintf_cf(FILE *stream, CFStringRef format, ...);
+
+typedef void (^CFArrayApplierBlock)(const void *);
+typedef void (^CFDictionaryApplierBlock)(const void *, const void *);
+
+void CFArrayApplyBlock(CFArrayRef, CFRange, CFArrayApplierBlock);
+void CFArrayApplyBlock2(CFArrayRef, CFArrayApplierBlock);
+void CFDictionaryApplyBlock(CFDictionaryRef, CFDictionaryApplierBlock);

Modified: users/toby/objcports/objcports.xcodeproj/project.pbxproj
===================================================================
--- users/toby/objcports/objcports.xcodeproj/project.pbxproj	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/objcports.xcodeproj/project.pbxproj	2009-09-10 09:46:02 UTC (rev 57383)
@@ -12,9 +12,9 @@
 		DA7AF1BC1058D1E200CF2187 /* internal.c in Sources */ = {isa = PBXBuildFile; fileRef = DA7AF1BB1058D1E200CF2187 /* internal.c */; };
 		DA96BED00F7C9C2500362779 /* MPIndex.c in Sources */ = {isa = PBXBuildFile; fileRef = DA96BECF0F7C9C2500362779 /* MPIndex.c */; };
 		DA96BF4C0F7CA1A700362779 /* MPDictionaryAdditions.c in Sources */ = {isa = PBXBuildFile; fileRef = DA96BF4B0F7CA1A700362779 /* MPDictionaryAdditions.c */; };
-		DAD371710F0280EF0064AFF4 /* port.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD371680F0280EF0064AFF4 /* port.m */; };
+		DAD371710F0280EF0064AFF4 /* port.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD371680F0280EF0064AFF4 /* port.c */; };
 		DAD371720F0280EF0064AFF4 /* MPArrayAdditions.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD3716A0F0280EF0064AFF4 /* MPArrayAdditions.c */; };
-		DAD371740F0280EF0064AFF4 /* MPPort.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD3716E0F0280EF0064AFF4 /* MPPort.m */; };
+		DAD371740F0280EF0064AFF4 /* MPPort.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD3716E0F0280EF0064AFF4 /* MPPort.c */; };
 		DAD371750F0280EF0064AFF4 /* MPStringAdditions.c in Sources */ = {isa = PBXBuildFile; fileRef = DAD371700F0280EF0064AFF4 /* MPStringAdditions.c */; };
 		DAD371950F0281940064AFF4 /* libtcl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD371940F0281940064AFF4 /* libtcl.dylib */; };
 /* End PBXBuildFile section */
@@ -42,11 +42,11 @@
 		DA96BECF0F7C9C2500362779 /* MPIndex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MPIndex.c; sourceTree = "<group>"; };
 		DA96BF4A0F7CA1A700362779 /* MPDictionaryAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDictionaryAdditions.h; sourceTree = "<group>"; };
 		DA96BF4B0F7CA1A700362779 /* MPDictionaryAdditions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MPDictionaryAdditions.c; sourceTree = "<group>"; };
-		DAD371680F0280EF0064AFF4 /* port.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = port.m; sourceTree = "<group>"; };
+		DAD371680F0280EF0064AFF4 /* port.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = port.c; sourceTree = "<group>"; };
 		DAD371690F0280EF0064AFF4 /* MPArrayAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPArrayAdditions.h; sourceTree = "<group>"; };
 		DAD3716A0F0280EF0064AFF4 /* MPArrayAdditions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MPArrayAdditions.c; sourceTree = "<group>"; };
 		DAD3716D0F0280EF0064AFF4 /* MPPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPort.h; sourceTree = "<group>"; };
-		DAD3716E0F0280EF0064AFF4 /* MPPort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPort.m; sourceTree = "<group>"; };
+		DAD3716E0F0280EF0064AFF4 /* MPPort.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MPPort.c; sourceTree = "<group>"; };
 		DAD3716F0F0280EF0064AFF4 /* MPStringAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStringAdditions.h; sourceTree = "<group>"; };
 		DAD371700F0280EF0064AFF4 /* MPStringAdditions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MPStringAdditions.c; sourceTree = "<group>"; };
 		DAD371940F0281940064AFF4 /* libtcl.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtcl.dylib; path = /usr/lib/libtcl.dylib; sourceTree = "<absolute>"; };
@@ -80,7 +80,7 @@
 		08FB7795FE84155DC02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
-				DAD371680F0280EF0064AFF4 /* port.m */,
+				DAD371680F0280EF0064AFF4 /* port.c */,
 				DAD371690F0280EF0064AFF4 /* MPArrayAdditions.h */,
 				DAD3716A0F0280EF0064AFF4 /* MPArrayAdditions.c */,
 				DA96BF4A0F7CA1A700362779 /* MPDictionaryAdditions.h */,
@@ -88,7 +88,7 @@
 				DA96BECE0F7C9C2500362779 /* MPIndex.h */,
 				DA96BECF0F7C9C2500362779 /* MPIndex.c */,
 				DAD3716D0F0280EF0064AFF4 /* MPPort.h */,
-				DAD3716E0F0280EF0064AFF4 /* MPPort.m */,
+				DAD3716E0F0280EF0064AFF4 /* MPPort.c */,
 				DAD3716F0F0280EF0064AFF4 /* MPStringAdditions.h */,
 				DAD371700F0280EF0064AFF4 /* MPStringAdditions.c */,
 				DA138879101AED7000F73A82 /* MPConfig.h */,
@@ -167,11 +167,11 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				DAD371710F0280EF0064AFF4 /* port.m in Sources */,
+				DAD371710F0280EF0064AFF4 /* port.c in Sources */,
 				DAD371720F0280EF0064AFF4 /* MPArrayAdditions.c in Sources */,
 				DAD371750F0280EF0064AFF4 /* MPStringAdditions.c in Sources */,
 				DA96BED00F7C9C2500362779 /* MPIndex.c in Sources */,
-				DAD371740F0280EF0064AFF4 /* MPPort.m in Sources */,
+				DAD371740F0280EF0064AFF4 /* MPPort.c in Sources */,
 				DA96BF4C0F7CA1A700362779 /* MPDictionaryAdditions.c in Sources */,
 				DA13887B101AED7000F73A82 /* MPConfig.c in Sources */,
 				DA7AF1BC1058D1E200CF2187 /* internal.c in Sources */,
@@ -201,7 +201,6 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
-				GCC_C_LANGUAGE_STANDARD = c99;
 				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
 				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;

Copied: users/toby/objcports/port.c (from rev 57365, users/toby/objcports/port.m)
===================================================================
--- users/toby/objcports/port.c	                        (rev 0)
+++ users/toby/objcports/port.c	2009-09-10 09:46:02 UTC (rev 57383)
@@ -0,0 +1,81 @@
+#include <CoreFoundation/CoreFoundation.h>
+#include <tcl.h>
+
+#include "MPConfig.h"
+#include "MPIndex.h"
+#include "MPPort.h"
+
+static void
+do_showconfig()
+{
+	CFDictionaryRef config;
+
+	config = MPCopyConfig();
+	CFShow(config);
+	CFRelease(config);
+}
+
+static void
+do_showindex(char *f)
+{
+	CFStringRef filename;
+	CFDictionaryRef index;
+
+	filename = CFStringCreateWithCString(NULL, f, kCFStringEncodingUTF8);
+	index = MPCopyPortIndex(filename);
+	CFShow(index);
+	CFRelease(index);
+	CFRelease(filename);
+}
+
+static void
+do_info(int argc, char *argv[])
+{
+	while (--argc) {
+		CFStringRef path;
+		CFURLRef url;
+		mp_port_t port;
+		CFStringRef tmp;
+
+		path = CFStringCreateWithCString(NULL, *++argv, kCFStringEncodingUTF8);
+		url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, TRUE);
+		port = mp_port_create(url, NULL);
+		fprintf_cf(stdout, CFSTR("%@ @%@ (%@)\n"), mp_port_variable(port, CFSTR("name")), mp_port_variable(port, CFSTR("version")), mp_port_variable(port, CFSTR("categories")));
+		tmp = CFStringCreateByCombiningStrings(NULL, mp_port_defined_variants(port), CFSTR(", "));
+		fprintf_cf(stdout, CFSTR("Variants:             %@\n"), tmp);
+		tmp = CFStringCreateByCombiningStrings(NULL, mp_port_defined_platforms(port), CFSTR(", "));
+		fprintf_cf(stdout, CFSTR("PlatformVariants:     %@\n"), tmp);
+		fprintf_cf(stdout, CFSTR("Brief Description:    %@\n"), mp_port_variable(port, CFSTR("description")));
+		fprintf_cf(stdout, CFSTR("Description:          %@\n"), mp_port_variable(port, CFSTR("long_description")));
+		fprintf_cf(stdout, CFSTR("Homepage:             %@\n"), mp_port_variable(port, CFSTR("homepage")));
+		fprintf_cf(stdout, CFSTR("Build Dependencies:   %@\n"), mp_port_variable(port, CFSTR("depends_build")));
+		fprintf_cf(stdout, CFSTR("Library Dependencies: %@\n"), mp_port_variable(port, CFSTR("depends_lib")));
+		fprintf_cf(stdout, CFSTR("Platforms:            %@\n"), mp_port_variable(port, CFSTR("platforms")));
+		fprintf_cf(stdout, CFSTR("Maintainers:          %@\n"), mp_port_variable(port, CFSTR("maintainers")));
+		mp_port_destroy(port);
+	}
+}
+
+int
+main(int argc, char *argv[])
+{
+
+	if (argc < 2)
+		exit(1);
+
+	if (!strcmp(argv[1], "showconfig")) {
+		do_showconfig();
+	} else {
+		if (argc < 3)
+			exit(1);
+
+		if (!strcmp(argv[1], "showindex")) {
+			do_showindex(argv[2]);
+		} else {
+			do_info(argc - 1, argv + 1);
+		}
+	}
+
+	pause();
+	return 0;
+}

Deleted: users/toby/objcports/port.m
===================================================================
--- users/toby/objcports/port.m	2009-09-10 09:42:07 UTC (rev 57382)
+++ users/toby/objcports/port.m	2009-09-10 09:46:02 UTC (rev 57383)
@@ -1,76 +0,0 @@
-#include <Foundation/Foundation.h>
-#include <tcl.h>
-
-#include "MPConfig.h"
-#include "MPIndex.h"
-#include "MPPort.h"
-
-static void
-do_showconfig()
-{
-	CFDictionaryRef config;
-
-	config = MPCopyConfig();
-	CFShow(config);
-	CFRelease(config);
-}
-
-static void
-do_showindex(char *f)
-{
-	CFStringRef filename;
-	CFDictionaryRef index;
-
-	filename = CFStringCreateWithCString(NULL, f, kCFStringEncodingUTF8);
-	index = MPCopyPortIndex(filename);
-	CFShow(index);
-	CFRelease(index);
-	CFRelease(filename);
-}
-
-static void
-do_info(int argc, char *argv[])
-{
-	printf("%d\n", argc);
-	NSAutoreleasePool *pool = [NSAutoreleasePool new];
-
-	while (--argc) {
-		MPPort *port = [[MPPort alloc] initWithPath:[NSString stringWithUTF8String:*++argv] options:nil];
-		NSLog(@"%@ @%@ (%@)", [port variable:@"name"], [port variable:@"version"], [port variable:@"categories"]);
-		NSLog(@"Variants:             %@", [[port definedVariants] componentsJoinedByString:@", "]);
-		NSLog(@"PlatformVariants:     %@", [[port definedPlatforms] componentsJoinedByString:@", "]);
-		NSLog(@"Brief Description:    %@", [port variable:@"description"]);
-		NSLog(@"Description:          %@", [port variable:@"long_description"]);
-		NSLog(@"Homepage:             %@", [port variable:@"homepage"]);
-		NSLog(@"Build Dependencies:   %@", [port variable:@"depends_build"]);
-		NSLog(@"Library Dependencies: %@", [port variable:@"depends_lib"]);
-		NSLog(@"Platforms:            %@", [port variable:@"platforms"]);
-		NSLog(@"Maintainers:          %@", [port variable:@"maintainers"]);
-		[port release];
-	}
-
-	[pool release];
-}
-
-int
-main(int argc, char *argv[])
-{
-
-	if (argc < 2)
-		exit(1);
-
-	if (!strcmp(argv[1], "showconfig")) {
-		do_showconfig();
-	} else {
-		if (argc < 3)
-			exit(1);
-
-		if (!strcmp(argv[1], "showindex")) {
-			do_showindex(argv[2]);
-		} else {
-			do_info(argc - 1, argv + 1);
-		}
-	}
-
-	return 0;
-}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20090910/3bedddbf/attachment-0001.html>


More information about the macports-changes mailing list