[darwinbuild-changes] [2] trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Oct 4 01:36:23 PDT 2006


Revision: 2
          http://trac.macosforge.org/projects/darwinbuild/changeset/2
Author:   kevin
Date:     2006-10-04 01:36:23 -0700 (Wed, 04 Oct 2006)

Log Message:
-----------
- Initial import of re-factored darwinxref.

Added Paths:
-----------
    trunk/darwinxref/
    trunk/darwinxref/DBDataStore.c
    trunk/darwinxref/DBPlugin.c
    trunk/darwinxref/DBPlugin.h
    trunk/darwinxref/Makefile
    trunk/darwinxref/cfutils.c
    trunk/darwinxref/cfutils.h
    trunk/darwinxref/main.c
    trunk/darwinxref/plugins/
    trunk/darwinxref/plugins/dependencies.c
    trunk/darwinxref/plugins/edit.c
    trunk/darwinxref/plugins/environment.c
    trunk/darwinxref/plugins/exportFiles.c
    trunk/darwinxref/plugins/exportIndex.c
    trunk/darwinxref/plugins/findFile.c
    trunk/darwinxref/plugins/loadDeps.c
    trunk/darwinxref/plugins/loadFiles.c
    trunk/darwinxref/plugins/loadIndex.c
    trunk/darwinxref/plugins/original.c
    trunk/darwinxref/plugins/register.c
    trunk/darwinxref/plugins/resolveDeps.c
    trunk/darwinxref/plugins/source_sites.c
    trunk/darwinxref/plugins/target.c
    trunk/darwinxref/plugins/version.c

Added: trunk/darwinxref/DBDataStore.c
===================================================================
--- trunk/darwinxref/DBDataStore.c	                        (rev 0)
+++ trunk/darwinxref/DBDataStore.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include "cfutils.h"
+#include "sqlite3.h"
+
+extern const void*  DBGetPluginWithName(CFStringRef);
+
+int DBBeginTransaction(void* session);
+int DBRollbackTransaction(void* session);
+int DBCommitTransaction(void* session);
+
+
+//////
+//
+// sqlite3 utility functions
+//
+//////
+
+#define __SQL(db, callback, context, fmt) \
+	va_list args; \
+	char* errmsg; \
+	va_start(args, fmt); \
+	char *query = sqlite3_vmprintf(fmt, args); \
+	res = sqlite3_exec(db, query, callback, context, &errmsg); \
+	if (res != SQLITE_OK) { \
+		fprintf(stderr, "Error: %s (%d)\n  SQL: %s\n", errmsg, res, query); \
+	} \
+	sqlite3_free(query);
+
+int SQL(sqlite3* db, const char* fmt, ...) {
+	int res;
+	__SQL(db, NULL, NULL, fmt);
+	return res;
+}
+
+int SQL_CALLBACK(sqlite3* db, sqlite3_callback callback, void* context, const char* fmt, ...) {
+	int res;
+	__SQL(db, callback, context, fmt);
+	return res;
+}
+
+static int isTrue(void* pArg, int argc, char **argv, char** columnNames) {
+	*(int*)pArg = (strcmp(argv[0], "1") == 0);
+	return 0;
+}
+
+int SQL_BOOLEAN(sqlite3* db, const char* fmt, ...) {
+	int res;
+	int val = 0;
+	__SQL(db, isTrue, &val, fmt);
+	return val;
+}
+
+static int getString(void* pArg, int argc, char **argv, char** columnNames) {
+	if (*(char**)pArg == NULL) {
+		*(char**)pArg = strdup(argv[0]);
+	}
+	return 0;
+}
+
+char* SQL_STRING(sqlite3* db, const char* fmt, ...) {
+	int res;
+	char* str = 0;
+	__SQL(db, getString, &str, fmt);
+	return str;
+}
+
+CFStringRef SQL_CFSTRING(sqlite3* db, const char* fmt, ...) {
+	int res;
+	CFStringRef str = NULL;
+	char* cstr = NULL;
+	__SQL(db, getString, &cstr, fmt);
+	str = cfstr(cstr);
+	if (cstr) free(cstr);
+	return str;
+}
+
+static int sqlAddStringToArray(void* pArg, int argc, char **argv, char** columnNames) {
+	CFMutableArrayRef array = pArg;
+	CFStringRef str = cfstr(argv[0]);
+	if (str) {
+		CFArrayAppendValue(array, str);
+		CFRelease(str);
+	}
+	return 0;
+}
+
+CFArrayRef SQL_CFARRAY(sqlite3* db, const char* fmt, ...) {
+	int res;
+	CFMutableArrayRef array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	__SQL(db, sqlAddStringToArray, array, fmt);
+	return array;
+}
+
+static int sqlAddValueToDictionary(void* pArg, int argc, char **argv, char** columnNames) {
+	CFMutableDictionaryRef dict = pArg;
+	CFStringRef name = cfstr(argv[0]);
+	CFStringRef value = cfstr(argv[1]);
+	if (!value) value = CFRetain(CFSTR(""));
+	if (name) {
+		CFTypeRef cf = CFDictionaryGetValue(dict, name);
+		if (cf == NULL) {
+			CFDictionarySetValue(dict, name, value);
+		} else if (CFGetTypeID(cf) == CFStringGetTypeID()) {
+			CFMutableArrayRef array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+			CFArrayAppendValue(array, cf);
+			CFArrayAppendValue(array, value);
+			CFDictionarySetValue(dict, name, array);
+		} else if (CFGetTypeID(cf) == CFArrayGetTypeID()) {
+			CFArrayAppendValue((CFMutableArrayRef)cf, value);
+		}
+		CFRelease(name);
+	}
+	CFRelease(value);
+	return 0;
+}
+
+CFDictionaryRef SQL_CFDICTIONARY(sqlite3* db, const char* fmt, ...) {
+	int res;
+	CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+	__SQL(db, sqlAddValueToDictionary, dict, fmt);
+	return dict;
+}
+
+void SQL_NOERR(sqlite3* db, char* sql) {
+	char* errmsg;
+	int res = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
+	if (res != SQLITE_OK && res != SQLITE_ERROR) {
+		fprintf(stderr, "Error: %s (%d)\n", errmsg, res);
+	} else {
+		res = 0;
+	}
+}
+
+void* DBDataStoreInitialize(const char* datafile) {
+	sqlite3* db;
+	sqlite3_open(datafile, &db);
+	if (db == NULL) return NULL;
+
+	char* table = "CREATE TABLE properties (build TEXT, project TEXT, property TEXT, key TEXT, value TEXT)";
+	char* index = "CREATE INDEX properties_index ON properties (build, project, property, key, value)";
+	SQL_NOERR(db, table);
+	SQL_NOERR(db, index);
+
+	return db; 
+}
+
+CFArrayRef DBCopyPropNames(void* session, CFStringRef build, CFStringRef project) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* sql;
+	if (project) {
+		sql = "SELECT DISTINCT property FROM properties WHERE build=%Q AND project=%Q ORDER BY property";
+	} else {
+		sql = "SELECT DISTINCT property FROM properties WHERE build=%Q AND project IS NULL ORDER BY property";
+	}
+	CFArrayRef res = SQL_CFARRAY(session, sql, cbuild, cproj);
+	free(cbuild);
+	free(cproj);
+	return res;
+}
+
+CFArrayRef DBCopyProjectNames(void* session, CFStringRef build) {
+	char* cbuild = strdup_cfstr(build);
+	CFArrayRef res = SQL_CFARRAY(session, "SELECT DISTINCT project FROM properties WHERE build=%Q ORDER BY project", cbuild);
+	free(cbuild);
+	return res;
+}
+
+CFTypeID  DBCopyPropType(void* session, CFStringRef property) {
+	CFTypeID type = -1;
+	const DBPropertyPlugin* plugin = DBGetPluginWithName(property);
+	if (plugin && plugin->base.type == kDBPluginPropertyType) {
+		type = plugin->datatype;
+	}
+	return type;
+}
+
+CFTypeRef DBCopyProp(void* session, CFStringRef build, CFStringRef project, CFStringRef property) {
+	CFTypeRef res = NULL;
+	CFTypeID type = DBCopyPropType(session, property);
+	if (type == -1) return NULL;
+
+	if (type == CFStringGetTypeID()) {
+		res = DBCopyPropString(session, build, project, property);
+	} else if (type == CFArrayGetTypeID()) {
+		res = DBCopyPropArray(session, build, project, property);
+	} else if (type == CFDictionaryGetTypeID()) {
+		res = DBCopyPropDictionary(session, build, project, property);
+	}
+	return res;
+}
+
+CFStringRef DBCopyPropString(void* session, CFStringRef build, CFStringRef project, CFStringRef property) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* cprop = strdup_cfstr(property);
+	char* sql;
+	if (project)
+		sql = "SELECT value FROM properties WHERE property=%Q AND build=%Q AND project=%Q";
+	else
+		sql = "SELECT value FROM properties WHERE property=%Q AND build=%Q AND project IS NULL";
+	CFStringRef res = SQL_CFSTRING(session, sql, cprop, cbuild, cproj);
+	free(cproj);
+	free(cprop);
+	free(cbuild);
+	return res;
+}
+
+CFArrayRef DBCopyPropArray(void* session, CFStringRef build, CFStringRef project, CFStringRef property) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* cprop = strdup_cfstr(property);
+	char* sql;
+	if (project)
+		sql = "SELECT value FROM properties WHERE property=%Q AND build=%Q AND project=%Q ORDER BY key";
+	else
+		sql = "SELECT value FROM properties WHERE property=%Q AND build=%Q AND project IS NULL ORDER BY key";
+	CFArrayRef res = SQL_CFARRAY(session, sql, cprop, cbuild, cproj);
+	free(cproj);
+	free(cprop);
+	free(cbuild);
+	return res;
+}
+
+
+
+CFDictionaryRef DBCopyPropDictionary(void* session, CFStringRef build, CFStringRef project, CFStringRef property) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* cprop = strdup_cfstr(property);
+	char* sql;
+	if (project)
+		sql = "SELECT DISTINCT key,value FROM properties WHERE property=%Q AND build=%Q AND project=%Q ORDER BY key";
+	else
+		sql = "SELECT DISTINCT key,value FROM properties WHERE property=%Q AND build=%Q AND project IS NULL ORDER BY key";
+	CFDictionaryRef res = SQL_CFDICTIONARY(session, sql, cprop, cbuild, cproj);
+	free(cbuild);
+	free(cproj);
+	free(cprop);
+	return res;
+}
+
+int DBSetProp(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFTypeRef value) {
+	int res = 0;
+	CFTypeID type = DBCopyPropType(session, property);
+	if (type == -1) {
+		cfprintf(stderr, "Error: unknown property in project \"%@\": %@\n", project, property);
+		return -1;
+	}
+	if (type != CFGetTypeID(value)) {
+		CFStringRef expected = CFCopyTypeIDDescription(type);
+		CFStringRef actual = CFCopyTypeIDDescription(CFGetTypeID(value));
+		cfprintf(stderr, "Error: incorrect type for \"%@\" in project \"%@\": expected %@ but got %@\n", property, project, expected, actual);
+		CFRelease(expected);
+		CFRelease(actual);
+		return -1;
+	}
+
+	if (type == CFStringGetTypeID()) {
+		res = DBSetPropString(session, build, project, property, value);
+	} else if (type == CFArrayGetTypeID()) {
+		res = DBSetPropArray(session, build, project, property, value);
+	} else if (type == CFDictionaryGetTypeID()) {
+		res = DBSetPropDictionary(session, build, project, property, value);
+	}
+	return res;
+}
+
+int DBSetPropString(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFStringRef value) {
+        char* cbuild = strdup_cfstr(build);
+        char* cproj = strdup_cfstr(project);
+        char* cprop = strdup_cfstr(property);
+        char* cvalu = strdup_cfstr(value);
+	if (project) {
+		SQL(session, "DELETE FROM properties WHERE build=%Q AND project=%Q AND property=%Q", cbuild, cproj, cprop);
+		SQL(session, "INSERT INTO properties (build,project,property,value) VALUES (%Q, %Q, %Q, %Q)", cbuild, cproj, cprop, cvalu);
+	} else {
+		SQL(session, "DELETE FROM properties WHERE build=%Q AND project IS NULL AND property=%Q", cbuild, cprop);
+		SQL(session, "INSERT INTO properties (build,property,value) VALUES (%Q, %Q, %Q)", cbuild, cprop, cvalu);
+	}
+	free(cbuild);
+        free(cproj);
+        free(cprop);
+	free(cvalu);
+	return 0;
+}
+
+int DBSetPropArray(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFArrayRef value) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* cprop = strdup_cfstr(property);
+	if (project) {
+		SQL(session, "DELETE FROM properties WHERE build=%Q AND project=%Q AND property=%Q", cbuild, cproj, cprop);
+	} else {
+		SQL(session, "DELETE FROM properties WHERE build=%Q AND project IS NULL AND property=%Q", cbuild, cprop);
+	}
+	CFIndex i, count = CFArrayGetCount(value);
+	for (i = 0; i < count; ++i) {
+		char* cvalu = strdup_cfstr(CFArrayGetValueAtIndex(value, i));
+		if (project) {
+			SQL(session, "INSERT INTO properties (build,project,property,value) VALUES (%Q, %Q, %Q, %Q)", cbuild, cproj, cprop, cvalu);
+		} else {
+			SQL(session, "INSERT INTO properties (build,property,value) VALUES (%Q, %Q, %Q)", cbuild, cprop, cvalu);
+		}
+		free(cvalu);
+	}
+	free(cbuild);
+	free(cproj);
+	free(cprop);
+	return 0;
+}
+
+int DBSetPropDictionary(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFDictionaryRef value) {
+	char* cbuild = strdup_cfstr(build);
+	char* cproj = strdup_cfstr(project);
+	char* cprop = strdup_cfstr(property);
+
+	CFArrayRef keys = dictionaryGetSortedKeys(value);
+	CFIndex i, count = CFArrayGetCount(keys);
+	for (i = 0; i < count; ++i) {
+		CFStringRef key = CFArrayGetValueAtIndex(keys, i);
+		char* ckey = strdup_cfstr(key);
+		CFTypeRef cf = CFDictionaryGetValue(value, key);
+		if (CFGetTypeID(cf) == CFStringGetTypeID()) {
+			char* cvalu = strdup_cfstr(cf);
+			if (project) {
+				SQL(session, "INSERT INTO properties (build,project,property,key,value) VALUES (%Q, %Q, %Q, %Q, %Q)", cbuild, cproj, cprop, ckey, cvalu);
+			} else {
+				SQL(session, "INSERT INTO properties (build,property,key,value) VALUES (%Q, %Q, %Q, %Q)", cbuild, cprop, ckey, cvalu);
+			}
+			free(cvalu);
+		} else if (CFGetTypeID(cf) == CFArrayGetTypeID()) {
+			CFIndex j, count = CFArrayGetCount(cf);
+			for (j = 0; j < count; ++j) {
+				char* cvalu = strdup_cfstr(CFArrayGetValueAtIndex(cf, j));
+				if (project) {
+					SQL(session, "INSERT INTO properties (build,project,property,key,value) VALUES (%Q, %Q, %Q, %Q, %Q)", cbuild, cproj, cprop, ckey, cvalu);
+				} else {
+					SQL(session, "INSERT INTO properties (build,property,key,value) VALUES (%Q, %Q, %Q, %Q)", cbuild, cprop, ckey, cvalu);
+				}
+				free(cvalu);
+			}
+		}
+		free(ckey);
+	}
+	CFRelease(keys);
+	free(cbuild);
+	free(cproj);
+	free(cprop);
+	return 0;
+}
+
+
+CFDictionaryRef DBCopyProjectPlist(void* session, CFStringRef build, CFStringRef project) {
+	CFMutableDictionaryRef res = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+	CFArrayRef props = DBCopyPropNames(session, build, project);
+	CFIndex i, count = CFArrayGetCount(props);
+	for (i = 0; i < count; ++i) {
+		CFStringRef prop = CFArrayGetValueAtIndex(props, i);
+		CFTypeRef value = DBCopyProp(session, build, project, prop);
+		if (value) {
+			CFDictionaryAddValue(res, prop, value);
+			CFRelease(value);
+		}
+	}
+	return res;
+}
+
+
+CFDictionaryRef DBCopyBuildPlist(void* session, CFStringRef build) {
+	CFMutableDictionaryRef plist = (CFMutableDictionaryRef)DBCopyProjectPlist(session, build, NULL);
+	CFMutableDictionaryRef projects = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+	CFArrayRef names = DBCopyProjectNames(session, build);
+	CFIndex i, count = CFArrayGetCount(names);
+	for (i = 0; i < count; ++i) {
+		CFStringRef name = CFArrayGetValueAtIndex(names, i);
+		CFDictionaryRef proj = DBCopyProjectPlist(session, build, name);
+		CFDictionaryAddValue(projects, name, proj);
+		CFRelease(proj);
+	}
+	CFDictionarySetValue(plist, CFSTR("build"), build);
+	CFDictionarySetValue(plist, CFSTR("projects"), projects);
+	return plist;
+}
+
+
+int _DBSetPlist(void* session, CFStringRef buildParam, CFStringRef projectParam, CFPropertyListRef plist) {
+	int res = 0;
+	CFIndex i, count;
+	
+	if (!plist) return -1;
+	if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return -1;
+
+	CFStringRef build = CFDictionaryGetValue(plist, CFSTR("build"));
+	if (!build) build = buildParam;
+	CFStringRef project = CFDictionaryGetValue(plist, CFSTR("name"));
+	if (!project) project = projectParam;
+	CFDictionaryRef projects = CFDictionaryGetValue(plist, CFSTR("projects"));
+		
+	if (projects && CFGetTypeID(projects) != CFDictionaryGetTypeID()) {
+		fprintf(stderr, "Error: projects must be a dictionary.\n");
+		return -1;
+	}
+
+	CFArrayRef props = dictionaryGetSortedKeys(plist);
+
+	//
+	// Delete any properties which may have been removed
+	//
+	CFArrayRef existingProps = DBCopyPropNames(session, build, project);
+	count = CFArrayGetCount(props);
+	CFRange range = CFRangeMake(0, count);
+	CFIndex existingCount = CFArrayGetCount(existingProps);
+	for (i = 0; i < existingCount; ++i) {
+		CFStringRef prop = CFArrayGetValueAtIndex(existingProps, i);
+		if (!CFArrayContainsValue(props, range, prop)) {
+			char* cbuild = strdup_cfstr(build);
+			char* cproj = strdup_cfstr(project);
+			char* cprop = strdup_cfstr(prop);
+			if (project) {
+				char* cproj = strdup_cfstr(project);
+				SQL(session, "DELETE FROM properties WHERE build=%Q AND project=%Q AND property=%Q", cbuild, cproj, cprop);
+				free(cproj);
+			} else {
+				SQL(session, "DELETE FROM properties WHERE build=%Q AND project IS NULL AND property=%Q", cbuild, cprop);
+			}
+			free(cbuild);
+			free(cprop);
+		}
+	}
+	CFRelease(existingProps);
+	
+	count = CFArrayGetCount(props);
+	for (i = 0; i < count; ++i) {
+		CFStringRef prop = CFArrayGetValueAtIndex(props, i);
+		
+		// These are more like pseudo-properties
+		if (CFEqual(prop, CFSTR("build")) || CFEqual(prop, CFSTR("projects"))) continue;
+		
+		CFTypeRef value = CFDictionaryGetValue(plist, prop);
+		res = DBSetProp(session, build, project, prop, value);
+		if (res != 0) break;
+	}
+	
+	if (res == 0 && projects) {
+		CFArrayRef projectNames = dictionaryGetSortedKeys(projects);
+		count = CFArrayGetCount(projectNames);
+		for (i = 0; i < count; ++i ) {
+			CFStringRef project = CFArrayGetValueAtIndex(projectNames, i);
+			CFDictionaryRef subplist = CFDictionaryGetValue(projects, project);
+			res = _DBSetPlist(session, build, project, subplist);
+			if (res != 0) break;
+		}
+		CFRelease(projectNames);
+	}
+	if (props) CFRelease(props);
+	return res;
+}
+
+int DBSetPlist(void* session, CFStringRef buildParam, CFPropertyListRef plist) {
+	int res;
+	res = DBBeginTransaction(session);
+	if (res != 0) return res;
+	res = _DBSetPlist(session, buildParam, NULL, plist);
+	if (res != 0) {
+		DBRollbackTransaction(session);
+		return res;
+	}
+	DBCommitTransaction(session);
+	return res;
+}
+
+
+int DBBeginTransaction(void* session) {
+	return SQL(session, "BEGIN");
+}
+int DBRollbackTransaction(void* session) {
+	return SQL(session, "ROLLBACK");
+}
+int DBCommitTransaction(void* session) {
+	return SQL(session, "COMMIT");
+}
+
+


Property changes on: trunk/darwinxref/DBDataStore.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/DBPlugin.c
===================================================================
--- trunk/darwinxref/DBPlugin.c	                        (rev 0)
+++ trunk/darwinxref/DBPlugin.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <fts.h>
+#include <libgen.h>
+
+#include "cfutils.h"
+#include "DBPlugin.h"
+
+const void* DBGetPluginWithName(CFStringRef name);
+
+CFDictionaryValueCallBacks cfDictionaryPluginValueCallBacks = {
+	0, NULL, NULL, NULL, NULL
+};
+
+static CFMutableDictionaryRef plugins;
+
+int load_plugins(const char* plugin_path) {
+	plugins = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &cfDictionaryPluginValueCallBacks);
+	if (!plugins) return -1;
+	
+	char fullpath[PATH_MAX];
+	realpath(plugin_path, fullpath);
+	
+	const char* path_argv[] = {plugin_path, NULL};
+	FTS* dir = fts_open((char * const *)path_argv, FTS_LOGICAL, NULL);
+	(void)fts_read(dir);
+	FTSENT* ent = fts_children (dir, FTS_NAMEONLY);
+	while (ent != NULL) {
+		if (strstr(ent->fts_name, ".so")) {
+			char* filename;
+			asprintf(&filename, "%s/%s", fullpath, ent->fts_name);
+//			fprintf(stderr, "plugin: loading %s\n", ent->fts_name);
+			void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+			if (handle) {
+				DBPluginInitializeFunc func = dlsym(handle, "initialize");
+				DBPlugin* plugin = (*func)(kDBPluginCurrentVersion);
+				if (plugin) {
+					if (plugin->version == kDBPluginCurrentVersion &&
+						(plugin->type == kDBPluginPropertyType || plugin->type == kDBPluginType)) {
+						CFDictionarySetValue(plugins, plugin->name, plugin);
+					} else {
+						fprintf(stderr, "Unrecognized plugin version and type: %x, %x: %s\n", plugin->version, plugin->type, ent->fts_name);
+					}
+				} else {
+						fprintf(stderr, "Plugin initialize returned null: %s\n", ent->fts_name);
+				}
+				//dlclose(handle);
+			} else {
+				fprintf(stderr, "Could not dlopen plugin: %s\n", ent->fts_name);
+			}
+		}
+		ent = ent->fts_link;
+	}
+	fts_close(dir);
+}
+
+void print_usage(char* progname, int argc, char* argv[]) {
+	progname = basename(progname);
+	if (!plugins) return;
+
+	if (argc >= 1) {
+		CFStringRef name = cfstr(argv[0]);
+		const DBPlugin* plugin = DBGetPluginWithName(name);
+		if (plugin) {
+			CFStringRef usage = plugin->usage(NULL);
+			cfprintf(stderr, "usage: %s [-f db] [-b build] %@ %@\n", progname, name, usage);
+			CFRelease(usage);
+			return;
+		}
+	}
+
+	CFArrayRef pluginNames = dictionaryGetSortedKeys(plugins);
+	CFIndex i, count = CFArrayGetCount(pluginNames);
+	for (i = 0; i < count; ++i) {
+		CFStringRef name = CFArrayGetValueAtIndex(pluginNames, i);
+		const DBPlugin* plugin = DBGetPluginWithName(name);
+		CFStringRef usage = plugin->usage(NULL);
+		cfprintf(stderr, "usage: %s [-f db] [-b build] %@ %@\n", progname, name, usage);
+		CFRelease(usage);
+	}
+}
+
+const void* DBGetPluginWithName(CFStringRef name) {
+	const void* plugin = CFDictionaryGetValue(plugins, name);
+	return plugin;
+}
+
+int run_plugin(void* session, int argc, char* argv[]) {
+	int res, i;
+	if (argc < 1) return -1;
+	CFStringRef name = cfstr(argv[0]);
+	CFMutableArrayRef args = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	for (i = 1; i < argc; ++i) {
+		CFArrayAppendValue(args, cfstr(argv[i]));
+	}
+	const DBPlugin* plugin = DBGetPluginWithName(name);
+	if (plugin) {
+		res = plugin->run(session, args);
+	} else {
+		print_usage("darwinxref", argc, argv);
+	}
+	CFRelease(name);
+	return res;
+}
+
+extern CFDictionaryRef _CFCopySystemVersionDictionary();
+static CFStringRef currentBuild = NULL;
+
+void DBSetCurrentBuild(void* session, char* build) {
+	if (currentBuild) CFRelease(currentBuild);
+	currentBuild = cfstr(build);
+}
+
+CFStringRef DBGetCurrentBuild(void* session) {
+	if (currentBuild) return currentBuild;
+
+	// The following is Private API.
+	// Please don't use this in your programs as it may break.
+	// Notice the careful dance around these symbols as they may
+	// someday disappear entirely, in which case this program
+	// will need to be revved.
+	CFDictionaryRef (*fptr)() = dlsym(RTLD_DEFAULT, "_CFCopySystemVersionDictionary");
+	if (fptr) {
+		CFDictionaryRef dict = fptr();
+		if (dict != NULL) {
+			CFStringRef str = CFDictionaryGetValue(dict, CFSTR("ProductBuildVersion"));
+			currentBuild = CFRetain(str);
+			CFRelease(dict);
+		}
+	}
+	return currentBuild;
+}


Property changes on: trunk/darwinxref/DBPlugin.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/DBPlugin.h
===================================================================
--- trunk/darwinxref/DBPlugin.h	                        (rev 0)
+++ trunk/darwinxref/DBPlugin.h	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#ifndef __DARWINBUILD_PLUGIN_H__
+#define __DARWINBUILD_PLUGIN_H__
+
+#include <CoreFoundation/CoreFoundation.h>
+
+typedef struct DBPlugin DBPlugin;
+
+/*!
+	@typedef DBPluginInitializeFunc
+	Initialization function present in every plugin.
+	@param version The latest plugin version that darwinxref is aware of
+	(kDBPluginCurrentVersion).
+	@result A pointer to an initialized DBPlugin structure describing this
+	plugin.  The structure should be allocated with malloc(3).
+*/
+typedef DBPlugin* (*DBPluginInitializeFunc)(int version);
+
+/*!
+	@typedef DBPluginRunFunc
+	Performs an action when the plugin is invoked from the command line.
+	@param session An opaque session pointer that should be passed to
+	any callbacks from the plugin.
+	@param argv The command line arguments.
+	@result Returns an exit status for darwinxref.
+*/
+typedef int (*DBPluginRunFunc)(void* session, CFArrayRef argv);
+
+/*!
+	@typedef DBPluginUsageFunc
+	Returns the command line usage string for this plugin.
+	@param session An opaque session pointer that should be passed to
+	any callbacks from the plugin.
+	@result The command line usage string.
+*/
+typedef CFStringRef (*DBPluginUsageFunc)(void* session);
+
+
+/*!
+	@constant kDBPluginCurrentVersion
+	Current version of the plugin data structure.
+*/
+enum {
+	kDBPluginCurrentVersion = 0,
+};
+
+/*!
+	@constant kDBPluginType
+	Basic plugin type that extends darwinxref functionality from the
+	command line.
+	@constant kDBPluginPropertyType
+	Plugin which adds a build or project property to the plist file.
+*/
+enum {
+	kDBPluginType = FOUR_CHAR_CODE('plug'),
+	kDBPluginPropertyType = FOUR_CHAR_CODE('prop'),
+};
+
+
+/*!
+	@typedef DBPlugin
+	Basic plugin data structure returned by plugin's initialize function.
+	@field version kDBPluginCurrentVersion (this structure is version 0).
+	@field type kDBPluginType, or kDBPluginPropertyType.
+	@field name The name of the plugin (visible from the command line).
+	@field run The function to call when the plugin is invoked from the
+	command line.
+	@field usage The function that returns the command line usage string
+	for this plugin.
+*/
+struct DBPlugin {
+	UInt32		version;
+	UInt32		type;
+	CFStringRef	name;
+	DBPluginRunFunc		run;
+	DBPluginUsageFunc	usage;
+};
+
+
+/*!
+	@typedef DBPropertyPlugin
+	Extended plugin data structure for the kDBPluginPropertyType.
+	@field base The basic plugin structure
+	@field datatype The datatype of this property
+	(i.e. one of CFStringGetTypeID(), CFArrayGetTypeID(), CFDictionaryGetTypeID())
+*/
+typedef struct {
+	DBPlugin	base;
+	CFTypeID	datatype;
+} DBPropertyPlugin;
+
+// plugin API
+
+CFStringRef DBGetCurrentBuild(void* session);
+
+CFArrayRef DBCopyPropNames(void* session, CFStringRef build, CFStringRef project);
+CFArrayRef DBCopyProjectNames(void* session, CFStringRef build);
+
+CFTypeRef DBCopyProp(void* session, CFStringRef build, CFStringRef project, CFStringRef property);
+CFStringRef DBCopyPropString(void* session, CFStringRef build, CFStringRef project, CFStringRef property);
+CFArrayRef DBCopyPropArray(void* session, CFStringRef build, CFStringRef project, CFStringRef property);
+CFDictionaryRef DBCopyPropDictionary(void* session, CFStringRef build, CFStringRef project, CFStringRef property);
+
+int DBSetProp(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFTypeRef value);
+int DBSetPropString(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFStringRef value);
+int DBSetPropArray(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFArrayRef value);
+int DBSetPropDictionary(void* session, CFStringRef build, CFStringRef project, CFStringRef property, CFDictionaryRef value);
+
+CFDictionaryRef DBCopyProjectPlist(void* session, CFStringRef build, CFStringRef project);
+CFDictionaryRef DBCopyBuildPlist(void* session, CFStringRef build);
+
+int DBSetPlist(void* session, CFStringRef build, CFPropertyListRef plist);
+
+
+#include "cfutils.h"
+
+#endif


Property changes on: trunk/darwinxref/DBPlugin.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/Makefile
===================================================================
--- trunk/darwinxref/Makefile	                        (rev 0)
+++ trunk/darwinxref/Makefile	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,18 @@
+SOURCES=$(wildcard *.c)
+PLUGIN_SOURCES=$(wildcard plugins/*.c)
+CFLAGS= -ggdb 
+LDFLAGS=-framework CoreFoundation
+PLUGIN_CFLAGS=$(CFLAGS) -I.
+PLUGIN_LDFLAGS=$(LDFLAGS) -bundle -bundle_loader darwinxref
+
+all: darwinxref $(PLUGIN_SOURCES:c=so)
+
+clean:
+	rm darwinxref
+	rm $(wildcard plugins/*.so)
+
+darwinxref: $(SOURCES)
+	cc -o $@ $(CFLAGS) $(LDFLAGS) -lsqlite3 $(SOURCES)
+
+plugins/%.so: plugins/%.c DBPlugin.h
+	cc -o $@ $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) $^


Property changes on: trunk/darwinxref/Makefile
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/cfutils.c
===================================================================
--- trunk/darwinxref/cfutils.c	                        (rev 0)
+++ trunk/darwinxref/cfutils.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <mach-o/dyld.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "cfutils.h"
+
+char* strdup_cfstr(CFStringRef str) {
+        char* result = NULL;
+        if (str != NULL) {
+                CFIndex length = CFStringGetLength(str);
+                CFIndex size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
+                result = malloc(size+1);
+                if (result != NULL) {
+                        length = CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingUTF8, '?', 0, result, size, NULL);
+                        result[length] = 0;
+                }
+        }
+        return result;
+}
+
+CFStringRef cfstr(const char* str) {
+        CFStringRef result = NULL;
+        if (str) result = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
+        return result;
+}
+
+void perror_cfstr(CFStringRef str) {
+        char* cstr = strdup_cfstr(str);
+        if (cstr) {
+                fprintf(stderr, "%s", cstr);
+                free(cstr);
+        }
+}
+
+CFPropertyListRef read_plist(char* path) {
+        CFPropertyListRef result = NULL;
+        int fd = open(path, O_RDONLY, (mode_t)0);
+        if (fd != -1) {
+                struct stat sb;
+                if (stat(path, &sb) != -1) {
+                        off_t size = sb.st_size;
+                        void* buffer = mmap(NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t)0);
+                        if (buffer != (void*)-1) {
+                                CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, buffer, size, kCFAllocatorNull);
+                                if (data) {
+                                        CFStringRef str = NULL;
+                                        result = CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListMutableContainers, &str);
+                                        if (result == NULL) {
+                                                perror_cfstr(str);
+                                        }
+                                }
+                                munmap(buffer, size);
+                        } else {
+                                perror(path);
+                        }
+                }
+                close(fd);
+        } else {
+                perror(path);
+        }
+        return result;
+}
+
+
+int cfprintf(FILE* file, const char* format, ...) {
+        va_list args;
+        va_start(args, format);
+        CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull);
+        CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args);
+        va_end(args);
+        char* cstr = strdup_cfstr(str);
+        fprintf(file, "%s", cstr);
+        free(cstr);
+        CFRelease(str);
+        CFRelease(formatStr);
+}
+
+CFArrayRef dictionaryGetSortedKeys(CFDictionaryRef dictionary) {
+        CFIndex count = CFDictionaryGetCount(dictionary);
+
+        const void** keys = malloc(sizeof(CFStringRef) * count);
+        CFDictionaryGetKeysAndValues(dictionary, keys, NULL);
+        CFArrayRef keysArray = CFArrayCreate(NULL, keys, count, &kCFTypeArrayCallBacks);
+        CFMutableArrayRef sortedKeys = CFArrayCreateMutableCopy(NULL, count, keysArray);
+        CFRelease(keysArray);
+        free(keys);
+
+        CFArraySortValues(sortedKeys, CFRangeMake(0, count), (CFComparatorFunction)CFStringCompare, 0);
+        return sortedKeys;
+}
+
+int writePlist(FILE* f, CFPropertyListRef p, int tabs) {
+        CFTypeID type = CFGetTypeID(p);
+
+        if (tabs == 0) {
+                fprintf(f, "// !$*UTF8*$!\n");
+        }
+
+        char* t = malloc(tabs+1);
+        int i;
+        for (i = 0; i < tabs; ++i) {
+                t[i] = '\t';
+        }
+        t[tabs] = 0;
+
+        if (type == CFStringGetTypeID()) {
+                char* utf8 = strdup_cfstr(p);
+                // XXX: needs work
+                int quote = 0;
+                for (i = 0 ;; ++i) {
+                        int c = utf8[i];
+                        if (c == 0) break;
+                        if (!((c >= 'A' && c <= 'Z') ||
+                                  (c >= 'a' && c <= 'z') ||
+                                  (c >= '0' && c <= '9') ||
+                                  c == '/' ||
+                                  c == '.' ||
+                                  c == '_' )) {
+                                quote = 1;
+                                break;
+                        }
+                }
+                if (utf8[0] == 0) quote = 1;
+
+                if (quote) fprintf(f, "\"");
+                for (i = 0 ;; ++i) {
+                        int c = utf8[i];
+                        if (c == 0) break;
+                        if (c == '\"' || c == '\\') fprintf(f, "\\");
+                        //if (c == '\n') c = 'n';
+                        fprintf(f, "%c", c);
+                }
+                if (quote) fprintf(f, "\"");
+                free(utf8);
+        } else if (type == CFArrayGetTypeID()) {
+                fprintf(f, "(\n");
+                int count = CFArrayGetCount(p);
+                for (i = 0; i < count; ++i) {
+                        CFTypeRef pp = CFArrayGetValueAtIndex(p, i);
+                        fprintf(f, "%s\t", t);
+                        writePlist(f, pp, tabs+1);
+                        fprintf(f, ",\n");
+                }
+                fprintf(f, "%s)", t);
+        } else if (type == CFDictionaryGetTypeID()) {
+                fprintf(f, "{\n");
+                CFArrayRef keys = dictionaryGetSortedKeys(p);
+                int count = CFArrayGetCount(keys);
+                for (i = 0; i < count; ++i) {
+                        CFStringRef key = CFArrayGetValueAtIndex(keys, i);
+                        char* utf8 = strdup_cfstr(key);
+                        fprintf(f, "%s\t%s = ", t, utf8);
+                        free(utf8);
+                        writePlist(f, CFDictionaryGetValue(p,key), tabs+1);
+                        fprintf(f, ";\n");
+                }
+                CFRelease(keys);
+                fprintf(f, "%s}", t);
+        }
+        if (tabs == 0) fprintf(f, "\n");
+        free(t);
+}
+
+
+CFArrayRef tokenizeString(CFStringRef str) {
+	CFMutableArrayRef result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+	
+	CFCharacterSetRef whitespace = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR(" \t\n\r"));
+
+	CFStringInlineBuffer buf;
+	CFIndex i, length = CFStringGetLength(str);
+	CFIndex start = 0;
+	CFStringInitInlineBuffer(str, &buf, CFRangeMake(0, length));
+	for (i = 0; i < length; ++i) {
+		UniChar c = CFStringGetCharacterFromInlineBuffer(&buf, i);
+		if (CFCharacterSetIsCharacterMember(whitespace, c)) {
+			if (start != kCFNotFound) {
+				CFStringRef sub = CFStringCreateWithSubstring(NULL, str, CFRangeMake(start, i - start));
+				start = kCFNotFound;
+				CFArrayAppendValue(result, sub);
+				CFRelease(sub);
+			}
+		} else if (start == kCFNotFound) {
+			start = i;
+		}
+	}
+	if (start != kCFNotFound) {
+		CFStringRef sub = CFStringCreateWithSubstring(NULL, str, CFRangeMake(start, i - start));
+		CFArrayAppendValue(result, sub);
+		CFRelease(sub);
+	}
+
+	CFRelease(whitespace);
+
+	return result;
+}
+
+void _mergeDictionaries(const void* key, const void* value, void* dst) {
+	CFDictionaryAddValue(dst, key, value);
+}
+
+CFDictionaryRef mergeDictionaries(CFDictionaryRef dst, CFDictionaryRef src) {
+	CFMutableDictionaryRef res = CFDictionaryCreateMutableCopy(NULL, 0, dst);
+	CFDictionaryApplyFunction(src, _mergeDictionaries, res);
+	return res;
+}
+
+//
+// Call backs suitable for adding C strings to a CFArray
+//
+const void* retainCStr(CFAllocatorRef allocator, const void *value) {
+	return strdup(value);
+}
+void releaseCStr(CFAllocatorRef allocator, const void *value) {
+	free((void*)value);
+}
+CFStringRef	copyDescriptionCStr(const void *value) {
+	return cfstr(value);
+}
+Boolean equalCStr(const void *value1, const void *value2) {
+	return (strcmp(value1, value2) == 0);
+}
+CFArrayCallBacks cfArrayCStringCallBacks = {
+	0, retainCStr, releaseCStr, copyDescriptionCStr, equalCStr
+};
+
+/* djb2
+ * This algorithm was first reported by Dan Bernstein
+ * many years ago in comp.lang.c
+ */
+CFHashCode hashCStr(const void *value) {
+	const char* str = (const char*)value;
+	unsigned long hash = 5381;
+	int c; 
+	while (c = *str++) hash = ((hash << 5) + hash) + c; // hash*33 + c
+	return hash;
+}
+CFDictionaryKeyCallBacks cfDictionaryCStringKeyCallBacks = {
+	0, retainCStr, releaseCStr, copyDescriptionCStr, equalCStr, hashCStr
+};
+CFDictionaryValueCallBacks cfDictionaryCStringValueCallBacks = {
+	0, retainCStr, releaseCStr, copyDescriptionCStr, equalCStr
+};


Property changes on: trunk/darwinxref/cfutils.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/cfutils.h
===================================================================
--- trunk/darwinxref/cfutils.h	                        (rev 0)
+++ trunk/darwinxref/cfutils.h	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#ifndef __cfutils_h__
+#define __cfutils_h__
+
+#include <CoreFoundation/CoreFoundation.h>
+
+CFPropertyListRef read_plist(char* path);
+char* strdup_cfstr(CFStringRef str);
+CFStringRef cfstr(const char* str);
+int cfprintf(FILE* file, const char* format, ...);
+CFArrayRef dictionaryGetSortedKeys(CFDictionaryRef dictionary);
+int writePlist(FILE* f, CFPropertyListRef p, int tabs);
+CFArrayRef tokenizeString(CFStringRef str);
+CFDictionaryRef mergeDictionaries(CFDictionaryRef dst, CFDictionaryRef src);
+
+extern CFArrayCallBacks cfArrayCStringCallBacks;
+extern CFDictionaryKeyCallBacks cfDictionaryCStringKeyCallBacks;
+extern CFDictionaryValueCallBacks cfDictionaryCStringValueCallBacks;
+
+#endif // __cfutils_h__


Property changes on: trunk/darwinxref/cfutils.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/main.c
===================================================================
--- trunk/darwinxref/main.c	                        (rev 0)
+++ trunk/darwinxref/main.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+
+extern int load_plugins(const char* plugin_path);
+extern int run_plugin(void* session, int argc, char* argv[]);
+extern void* DBDataStoreInitialize(const char* datafile);
+extern void DBSetCurrentBuild(void* session, char* build);
+
+// getopt globals
+char* optarg;
+int optind;
+int optopt;
+int opterr;
+int optreset;
+
+// user environment global
+extern char** environ;
+
+
+int main(int argc, char* argv[]) {
+	char* progname = argv[0];
+	char* dbfile = "/var/tmp/darwinxref.db";
+	char* build = NULL;
+
+	int ch;
+	while ((ch = getopt(argc, argv, "f:b:")) != -1) {
+		switch (ch) {
+		case 'f':
+			dbfile = optarg;
+			break;
+		case 'b':
+			build = optarg;
+			break;
+		case '?':
+		default:
+			print_usage(progname, argc, argv);
+			exit(1);
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	void* session = DBDataStoreInitialize(dbfile);
+	DBSetCurrentBuild(session, build);
+	load_plugins("plugins");
+	if (run_plugin(session, argc, argv) == -1) {
+		print_usage(progname, argc, argv);
+		exit(1);
+	}
+	return 0;
+}
+


Property changes on: trunk/darwinxref/main.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/dependencies.c
===================================================================
--- trunk/darwinxref/plugins/dependencies.c	                        (rev 0)
+++ trunk/darwinxref/plugins/dependencies.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+void printDependencies(void* session, CFStringRef* types, CFStringRef* recursiveTypes, CFMutableSetRef visited, CFStringRef build, CFStringRef project);
+
+
+static int run(void* session, CFArrayRef argv) {
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 2) return -1;
+
+	CFStringRef project = CFArrayGetValueAtIndex(argv, 1);
+
+	CFStringRef type = CFArrayGetValueAtIndex(argv, 0);
+	if (CFEqual(type, CFSTR("-run"))) {
+		CFStringRef types[] = { CFSTR("lib"), CFSTR("run"), NULL };
+		printDependencies(session, types, types, NULL, DBGetCurrentBuild(session), project);
+	} else if (CFEqual(type, CFSTR("-build"))) {
+		CFStringRef types[] = { CFSTR("lib"), CFSTR("run"), CFSTR("build"), NULL };
+		CFStringRef recursive[] = { CFSTR("lib"), CFSTR("run"), NULL };
+		printDependencies(session, types, recursive, NULL, DBGetCurrentBuild(session), project);
+	} else if (CFEqual(type, CFSTR("-header"))) {
+		CFStringRef types[] = { CFSTR("header"), NULL };
+		printDependencies(session, types, types, NULL, DBGetCurrentBuild(session), project);
+	} else {
+		return -1;
+	}
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("-run | -build | -header <project>"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("dependencies");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFDictionaryGetTypeID();
+
+	return plugin;
+}
+
+
+void printDependencies(void* session, CFStringRef* types, CFStringRef* recursiveTypes, CFMutableSetRef visited, CFStringRef build, CFStringRef project) {
+	if (!visited) visited = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+	CFDictionaryRef dependencies = DBCopyPropDictionary(session, build, project, CFSTR("dependencies"));
+	if (dependencies) {
+		CFStringRef* type = types;
+		while (*type != NULL) {
+			CFArrayRef array = CFDictionaryGetValue(dependencies, *type);
+			if (array) {
+				CFIndex i, count = CFArrayGetCount(array);
+				for (i = 0; i < count; ++i) {
+					CFStringRef newproject = CFArrayGetValueAtIndex(array, i);
+					if (!CFSetContainsValue(visited, newproject)) {
+						cfprintf(stdout, "%@\n", newproject);
+						CFSetAddValue(visited, newproject);
+						printDependencies(session, recursiveTypes, recursiveTypes, visited, build, newproject);
+					}
+				}
+			}
+			++type;
+		}
+	}
+	CFRelease(dependencies);
+}


Property changes on: trunk/darwinxref/plugins/dependencies.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/edit.c
===================================================================
--- trunk/darwinxref/plugins/edit.c	                        (rev 0)
+++ trunk/darwinxref/plugins/edit.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+
+int editPlist(void* session, CFStringRef project);
+static int execEditor(const char* tmpfile);
+
+static int run(void* session, CFArrayRef argv) {
+	CFStringRef project = NULL;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count > 1)  return -1;
+	if (count == 1) {
+		project = CFArrayGetValueAtIndex(argv, 0);
+	}
+	int res = editPlist(session, project);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[<project>]"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("edit");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+static inline int min(int a, int b) {
+        return (a < b) ? a : b;
+}
+
+
+int editPlist(void* session, CFStringRef project) {
+		CFStringRef build = DBGetCurrentBuild(session);
+        struct stat before, after;
+        CFDictionaryRef p = NULL;
+        if (project) {
+                p = DBCopyProjectPlist(session, build, project);
+        } else {
+                p = DBCopyBuildPlist(session, build);
+        }
+
+        ////
+        //// Create a temp file and record the mtime
+        ////
+        char tmpfile[PATH_MAX];
+        strcpy(tmpfile, "/tmp/darwinxref.project.XXXXXX");
+        int fd = mkstemp(tmpfile);
+        FILE* f = fdopen(fd, "w");
+        writePlist(f, p, 0);
+        CFRelease(p);
+        fclose(f);
+        if (stat(tmpfile, &before) == -1) {
+
+                perror(tmpfile);
+                unlink(tmpfile);
+                return -1;
+        }
+
+        int status = execEditor(tmpfile);
+
+        if (status == 0) {
+                // Look at the mtime of the file to see if we should re-import
+                if (stat(tmpfile, &after) == -1) {
+                        perror(tmpfile);
+                        unlink(tmpfile);
+                        return -1;
+                }
+
+                // Change in mtime, so re-import
+                if (before.st_mtimespec.tv_sec != after.st_mtimespec.tv_sec ||
+                        before.st_mtimespec.tv_nsec != after.st_mtimespec.tv_nsec) {
+                        int done = 0;
+
+                        while (!done) {
+                                p = read_plist(tmpfile);
+                                // Check if plist parsed successfully, if so import it
+								if (DBSetPlist(session, build, p) == 0) {
+										done = 1;
+                                        CFRelease(p);
+                                } else {
+                                        for (;;) {
+                                                fprintf(stderr, "Invalid property list\n");
+                                                fprintf(stderr, "e)dit, q)uit\n");
+                                                fprintf(stderr, "Action: (edit) ");
+                                                size_t size;
+                                                char* line = fgetln(stdin, &size);
+                                                if (strncmp(line, "q", min(size, 1)) == 0 || line == NULL) {
+                                                        fprintf(stderr, "darwinxref [edit cancelled]: cancelled by user\n");
+                                                        done = 1;
+                                                        break;
+                                                } else if (strncmp(line, "e", min(size, 1)) == 0 ||
+                                                                        strncmp(line, "\n", min(size, 1)) == 0) {
+                                                        execEditor(tmpfile);
+                                                        break;
+                                                } else {
+                                                       fprintf(stderr, "Unknown input\n\n");
+                                                }
+                                        }
+                                }
+                        }
+                }
+        } else {
+                fprintf(stderr, "darwinxref [edit cancelled]: cancelled by user\n");
+        }        unlink(tmpfile);
+        return 0;
+}
+
+static int execEditor(const char* tmpfile) {
+        pid_t pid = fork();
+        if (pid == -1) {
+                return -1;
+        } else if (pid == 0) {
+                char* editor = getenv("VISUAL");
+                if (!editor) editor = getenv("EDITOR");
+                if (!editor) editor = "vi";
+
+                execlp(editor, editor, tmpfile, NULL);
+                _exit(127);
+                // NOT REACHED
+        }
+        int status = 0;
+        while (wait4(pid, &status, 0, NULL) == -1) {
+                if (errno == EINTR) continue;
+                if (errno == ECHILD) status = -1;
+                if (errno == EFAULT || errno == EINVAL) abort();
+                break;
+        }
+        if (WIFEXITED(status)) {
+                return WEXITSTATUS(status);
+        } else {
+                return -1;
+        }
+}
+


Property changes on: trunk/darwinxref/plugins/edit.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/environment.c
===================================================================
--- trunk/darwinxref/plugins/environment.c	                        (rev 0)
+++ trunk/darwinxref/plugins/environment.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+static int run(void* session, CFArrayRef argv) {
+	if (CFArrayGetCount(argv) > 1)  return -1;
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFStringRef project = NULL;
+	CFDictionaryRef projectEnv = NULL;
+	CFDictionaryRef globalEnv = DBCopyPropDictionary(session, build, NULL, CFSTR("environment"));
+	if (CFArrayGetCount(argv) == 1) {
+		project = CFArrayGetValueAtIndex(argv, 0);
+		projectEnv = DBCopyPropDictionary(session, build, project, CFSTR("environment"));
+	}
+	
+	CFMutableDictionaryRef env = NULL;
+	
+	if (globalEnv && projectEnv) {
+		env = (CFMutableDictionaryRef)mergeDictionaries(projectEnv, globalEnv);
+	} else if (globalEnv) {
+		env = (CFMutableDictionaryRef)globalEnv;
+	} else if (projectEnv) {
+		env = (CFMutableDictionaryRef)projectEnv;
+	} else {
+		return 0;
+	}
+
+	// Auto-generate some variables based on RC_ARCHS and RC_NONARCH_CFLAGS
+	// RC_CFLAGS=$RC_NONARCH_CFLAGS -arch ${arch}
+	// RC_${arch}=YES
+	CFStringRef str = CFDictionaryGetValue(env, CFSTR("RC_NONARCH_CFLAGS"));
+	if (!str) str = CFSTR("");
+	CFMutableStringRef cflags = CFStringCreateMutableCopy(NULL, 0, str);
+	str = CFDictionaryGetValue(env, CFSTR("RC_ARCHS"));
+	if (str) {
+		CFMutableStringRef trimmed = CFStringCreateMutableCopy(NULL, 0, str);
+		CFStringTrimWhitespace(trimmed);
+		CFArrayRef archs = tokenizeString(trimmed);
+		CFIndex i, count = CFArrayGetCount(archs);
+		for (i = 0; i < count; ++i) {
+			CFStringRef arch = CFArrayGetValueAtIndex(archs, i);
+			// -arch ${arch}
+			CFStringAppendFormat(cflags, NULL, CFSTR(" -arch %@"), arch);
+			
+			// RC_${arch}=YES
+			CFStringRef name = CFStringCreateWithFormat(NULL, NULL, CFSTR("RC_%@"), arch);
+			CFDictionarySetValue(env, name, CFSTR("YES"));
+			CFRelease(name);
+		}
+		CFRelease(trimmed);
+	}
+	CFDictionarySetValue(env, CFSTR("RC_CFLAGS"), cflags);
+	
+	// print variables to stdout
+	CFArrayRef keys = dictionaryGetSortedKeys(env);
+	CFIndex i, count = CFArrayGetCount(keys);
+	for (i = 0; i < count; ++i) {
+		CFStringRef name = CFArrayGetValueAtIndex(keys, i);
+		CFStringRef value = CFDictionaryGetValue(env, name);
+		cfprintf(stdout, "%@=%@\n", name, value);
+	}
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[<project>]"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("environment");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFDictionaryGetTypeID();
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/environment.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/exportFiles.c
===================================================================
--- trunk/darwinxref/plugins/exportFiles.c	                        (rev 0)
+++ trunk/darwinxref/plugins/exportFiles.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <stdio.h>
+#include <regex.h>
+
+static int exportFiles(void* db, char* buildparam, char* project);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count > 1)  return -1;
+
+	char* project = NULL;
+	if (count == 1) {
+		project = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));
+	}
+	
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	exportFiles(session, build, project);
+	if (project) free(project);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[<project>]"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("exportFiles");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+int printFiles(void* pArg, int argc, char **argv, char** columnNames) {
+	char* project = ((char**)pArg)[0];
+	if (strcmp(project, argv[0]) != 0) {
+		strncpy(project, argv[0], BUFSIZ);
+		fprintf(stdout, "%s:\n", project);
+	}
+	fprintf(stdout, "\t%s\n", argv[3]);
+	return 0;
+}
+
+static int exportFiles(void* session, char* build, char* project) {
+	int res;
+
+	char* table = "CREATE TABLE files (build text, project text, path text)";
+	char* index = "CREATE INDEX files_index ON files (build, project, path)";
+	SQL_NOERR(session, table);
+	SQL_NOERR(session, index);
+
+	fprintf(stdout, "# BUILD %s\n", build);
+
+	CFArrayRef projects = DBCopyProjectNames(session, DBGetCurrentBuild(session));
+	if (projects) {
+		CFIndex i, count = CFArrayGetCount(projects);
+		for (i = 0; i < count; ++i) {
+			CFStringRef name = CFArrayGetValueAtIndex(projects, i);
+			char projbuf[BUFSIZ];
+			res = SQL_CALLBACK(session, &printFiles, projbuf,
+				"SELECT project,path FROM files WHERE build=%Q AND project=%Q",
+				build, project);
+		}
+		CFRelease(projects);
+	}
+	
+	return 0;
+}


Property changes on: trunk/darwinxref/plugins/exportFiles.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/exportIndex.c
===================================================================
--- trunk/darwinxref/plugins/exportIndex.c	                        (rev 0)
+++ trunk/darwinxref/plugins/exportIndex.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <unistd.h>
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count > 1)  return -1;
+	int xml = 0;
+	if (count == 1) {
+		CFStringRef arg = CFArrayGetValueAtIndex(argv, 0);
+		xml = CFEqual(arg, CFSTR("-xml"));
+		// -xml is the only supported option
+		if (!xml) return -1;
+	}
+	
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFPropertyListRef plist = DBCopyBuildPlist(session, build);
+	if (xml) {
+		CFDataRef data = CFPropertyListCreateXMLData(NULL, plist);
+		res = write(STDOUT_FILENO, CFDataGetBytePtr(data), CFDataGetLength(data));
+	} else {
+		res = writePlist(stdout, plist, 0);
+	}
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[-xml]"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("exportIndex");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
\ No newline at end of file


Property changes on: trunk/darwinxref/plugins/exportIndex.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/findFile.c
===================================================================
--- trunk/darwinxref/plugins/findFile.c	                        (rev 0)
+++ trunk/darwinxref/plugins/findFile.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <stdio.h>
+#include <regex.h>
+
+static int findFile(void* db, char* file, char* build);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 1)  return -1;
+
+	char* file = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));	
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	
+	findFile(session, file, build);
+
+	if (file) free(file);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<file>"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("findFile");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+int printFiles(void* pArg, int argc, char **argv, char** columnNames) {
+	char* project = ((char**)pArg)[0];
+	if (strcmp(project, argv[0]) != 0) {
+		strncpy(project, argv[0], BUFSIZ);
+		fprintf(stdout, "%s:\n", project);
+	}
+	fprintf(stdout, "\t%s\n", argv[1]);
+	return 0;
+}
+
+static int findFile(void* db, char* file, char* build) {
+	char* errmsg;
+	char project[BUFSIZ];
+	project[0] = 0;
+	asprintf(&file, "%%%s", file);
+	int res = SQL_CALLBACK(db, &printFiles, project,
+		"SELECT project,path FROM files WHERE build=%Q AND path LIKE %Q ORDER BY project, path",
+		build, file);
+	return 0;
+}


Property changes on: trunk/darwinxref/plugins/findFile.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/loadDeps.c
===================================================================
--- trunk/darwinxref/plugins/loadDeps.c	                        (rev 0)
+++ trunk/darwinxref/plugins/loadDeps.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int loadDeps(void* session, const char* build, const char* project);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 1)  return -1;
+	char* project = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	loadDeps(session, build, project);
+	free(project);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<project>"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("loadDeps");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+static int has_suffix(const char* big, const char* little) {
+	char* found = NULL;
+	while (1) {
+		char* next = strcasestr(found ? found+1 : big, little);
+		if (next) { found = next; } else { break; }
+	}
+	return found ? (strcmp(found, little) == 0) : 0;
+}
+
+static char* canonicalize_path(const char* path) {
+#if 1 // USE_REALPATH
+	char* result = malloc(PATH_MAX);
+	realpath(path, result);
+	return result;
+#else
+	char* result = malloc(strlen(path) + 1);
+	const char* src = path;
+	char* dst = result;
+	
+	while (*src != 0) {
+		// Backtrack to previous /
+		if (strncmp(src, "/../", 4) == 0) {
+			src += 3; // skip to last /, so we can evaluate that below
+			if (dst == result) {
+				*dst = '/';
+				dst += 1;
+			} else {
+				do {
+					dst -= 1;
+				} while (dst != result && *dst != '/');
+			}
+		// Trim /..
+		} else if (strcmp(src, "/..") == 0) {
+			src += 3;
+			if (dst == result) {
+				*dst = '/';
+				dst += 1;
+			} else {
+				do {
+					dst -= 1;
+				} while (dst != result && *dst != '/');
+			}
+		// Compress /./ to /
+		} else if (strncmp(src, "/./", 3) == 0) {
+			src += 2;	// skip to last /, so we can evaluate that below
+		// Trim /.
+		} else if (strcmp(src, "/.") == 0) {
+			*dst = 0;
+			break;
+		// compress slashes, trim trailing slash
+		} else if (*src == '/') {
+			if ((dst == result || dst[-1] != '/') && src[1] != 0) {
+				*dst = '/';
+				dst += 1;
+				src += 1;
+			} else {
+				src += 1;
+			}
+		// default to copying over a single char
+		} else {
+			*dst = *src;
+			dst += 1;
+			src += 1;
+		}
+	}
+	
+	*dst = 0;  // NUL terminate
+	
+	return result;
+#endif
+}
+
+int loadDeps(void* db, const char* build, const char* project) {
+	size_t size;
+	char* line;
+	int count = 0;
+
+	char* table = "CREATE TABLE unresolved_dependencies (build TEXT, project TEXT, type TEXT, dependency TEXT)";
+	char* index = "CREATE INDEX unresolved_dependencies_index ON unresolved_dependencies (build, project, type, dependency)";
+
+	SQL_NOERR(db, table);
+	SQL_NOERR(db, index);
+
+	if (SQL(db, "BEGIN")) { return -1; }
+
+	while ((line = fgetln(stdin, &size)) != NULL) {
+		if (line[size-1] == '\n') line[size-1] = 0; // chomp newline
+		char* tab = memchr(line, '\t', size);
+		if (tab) {
+			char *type, *file;
+			int typesize = (intptr_t)tab - (intptr_t)line;
+			asprintf(&type, "%.*s", typesize, line);
+			asprintf(&file, "%.*s", size - typesize - 1, tab+1);
+			if (strcmp(type, "open") == 0) {
+				free(type);
+				if (has_suffix(file, ".h")) {
+					type = "header";
+				} else if (has_suffix(file, ".a")) {
+					type = "staticlib";
+				} else {
+					type = "build";
+				}
+			} else if (strcmp(type, "execve") == 0) {
+				free(type);
+				type = "build";
+			}
+			char* canonicalized = canonicalize_path(file);
+			
+			struct stat sb;
+			int res = lstat(canonicalized, &sb);
+			// for now, skip if the path points to a directory
+			if (!(res == 0 && (sb.st_mode & S_IFDIR) == S_IFDIR)) {
+				SQL(db, "INSERT INTO unresolved_dependencies (build,project,type,dependency) VALUES (%Q,%Q,%Q,%Q)",
+					build, project, type, canonicalized);
+			}
+			free(canonicalized);
+			free(file);
+		} else {
+			fprintf(stderr, "Error: syntax error in input.  no tab delimiter found.\n");
+		}
+		++count;
+	}
+
+	if (SQL(db, "COMMIT")) { return -1; }
+
+	fprintf(stderr, "loaded %d unresolved dependencies.\n", count);
+}


Property changes on: trunk/darwinxref/plugins/loadDeps.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/loadFiles.c
===================================================================
--- trunk/darwinxref/plugins/loadFiles.c	                        (rev 0)
+++ trunk/darwinxref/plugins/loadFiles.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <stdio.h>
+#include <regex.h>
+
+static int loadFiles(void* db, const char* buildparam, const char* path);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFStringRef project = NULL;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 1)  return -1;
+	char* filename = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	loadFiles(session, build, filename);
+	free(filename);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<logfile>"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("loadFiles");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+static inline int min(int a, int b) {
+	return (a < b) ? a : b; 
+}
+
+//
+// Loads the specified index file into the sqlite database
+// This way we can do intelligent sql queries on the index
+// data.
+//
+int loadFiles(void* db, const char* buildparam, const char* path) {
+	FILE* fp = fopen(path, "r");
+	int loaded = 0, total = 0;
+	if (fp) {
+		char* errmsg;
+		
+		//
+		// Create the projects table if it does not already exist
+		//
+				
+		if (SQL(db, "BEGIN")) { return -1; }
+
+		char project[PATH_MAX];
+		char build[PATH_MAX];
+		
+		project[0] = 0;
+		strncpy(build, buildparam, PATH_MAX);
+				
+		for (;;) {
+			int skip = 0;
+			size_t size;
+			char *line, *buf = fgetln(fp, &size);
+			if (buf == NULL) break;
+			if (buf[size-1] == '\n') --size;
+			line = malloc(size+1);
+			memcpy(line, buf, size);
+			line[size] = 0;
+						
+			// The parsing state machine works as follows:
+			//
+			// 1. look for project followed by colon newline
+			// 2. look for \t, insert paths with last build and project name, otherwise goto 1.
+			
+			regex_t regex;
+			regmatch_t matches[3];
+
+			// Skip any commented lines (start with #)
+			regcomp(&regex, "^[[:space:]]*#.*", REG_EXTENDED);
+			if (regexec(&regex, line, 1, matches, 0) == 0) {
+				skip = 1;
+			}
+			regfree(&regex);
+
+			// Look for build numbers in the comments
+			regcomp(&regex, "^[[:space:]]*#[[:space:]]*(BUILD[=[:space:]])?[[:space:]]*([^[:space:]]+)[[:space:]]*.*", REG_EXTENDED | REG_ICASE);
+			if (regexec(&regex, line, 3, matches, 0) == 0) {
+				int len = min(matches[2].rm_eo - matches[2].rm_so, PATH_MAX);
+				strncpy(build, line + matches[2].rm_so, len);
+				build[len] = 0;
+				skip = 1;
+			}
+			regfree(&regex);
+
+			// File
+			regcomp(&regex, "^\t(/.*)$", REG_EXTENDED);
+			if (!skip &&
+				project[0] &&
+				build[0] &&
+				regexec(&regex, line, 2, matches, 0) == 0) {
+				char path[PATH_MAX];
+				int len = min(matches[1].rm_eo - matches[1].rm_so, PATH_MAX);
+				strncpy(path, line + matches[1].rm_so, len);
+				path[len] = 0;
+				int res = SQL(db,
+					"INSERT INTO files (build,project,path) VALUES (%Q, %Q, %Q)",
+					build, project, path);
+				if (res != 0) { return res; }
+				++loaded;
+				skip = 1;
+			}
+			regfree(&regex);
+			
+			
+			// New Project
+			regcomp(&regex, "^[[:space:]]*([^-]+).*:[[:space:]]*$", REG_EXTENDED | REG_ICASE);
+			if (!skip &&
+				regexec(&regex, line, 3, matches, 0) == 0) {
+				int len = matches[1].rm_eo - matches[1].rm_so;
+				strncpy(project, line + matches[1].rm_so, len);
+				project[len] = 0;
+				int res = SQL(db,
+					"DELETE FROM files WHERE build=%Q AND project=%Q",
+					build, project);
+				if (res != 0) { return res; }
+				++total;
+				fprintf(stdout, "%s (%s)\n", project, build);
+				skip = 1;
+			}
+			regfree(&regex);
+
+
+			free(line);
+		}
+		fclose(fp);
+
+		if (SQL(db, "COMMIT")) { return -1; }
+
+	} else {
+		perror(path);
+		return 1;
+	}
+	fprintf(stdout, "%d files for %d projects loaded.\n", loaded, total);
+	return 0;
+}


Property changes on: trunk/darwinxref/plugins/loadFiles.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/loadIndex.c
===================================================================
--- trunk/darwinxref/plugins/loadIndex.c	                        (rev 0)
+++ trunk/darwinxref/plugins/loadIndex.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFStringRef project = NULL;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 1)  return -1;
+	char* filename = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));
+	CFPropertyListRef plist = read_plist(filename);
+	if (plist) {
+		res = DBSetPlist(session, NULL, plist);
+	}
+	free(filename);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<plist>"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("loadIndex");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/loadIndex.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/original.c
===================================================================
--- trunk/darwinxref/plugins/original.c	                        (rev 0)
+++ trunk/darwinxref/plugins/original.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+static int run(void* session, CFArrayRef argv) {
+	if (CFArrayGetCount(argv) != 1)  return -1;
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFStringRef project = CFArrayGetValueAtIndex(argv, 0);
+	CFStringRef original = DBCopyPropString(session, build, project, CFSTR("original"));
+	cfprintf(stdout, "%@\n", original);
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<project>"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("original");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFStringGetTypeID();
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/original.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/register.c
===================================================================
--- trunk/darwinxref/plugins/register.c	                        (rev 0)
+++ trunk/darwinxref/plugins/register.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+#include <fcntl.h>
+
+int register_files(void* db, char* build, char* project, char* path);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count != 2)  return -1;
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	char* project = strdup_cfstr(CFArrayGetValueAtIndex(argv, 0));
+	char* dstroot = strdup_cfstr(CFArrayGetValueAtIndex(argv, 1));
+	res = register_files(session, build, project, dstroot);
+	free(build);
+	free(project);
+	free(dstroot);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<project> <dstroot>"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("register");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+static int buildpath(char* path, size_t bufsiz, FTSENT* ent) {
+	if (ent->fts_parent != NULL && ent->fts_level > 1) {
+		bufsiz = buildpath(path, bufsiz, ent->fts_parent);
+	}
+	strncat(path, "/", bufsiz);
+	bufsiz -= 1;
+	if (ent->fts_name) {
+		strncat(path, ent->fts_name, bufsiz);
+		bufsiz -= strlen(ent->fts_name);
+	}
+	return bufsiz;
+}
+
+// If the path points to a Mach-O file, records all dylib
+// link commands as library dependencies in the database.
+// XXX
+// Ideally library dependencies are tracked per-architecture.
+// For now, we're assuming all architectures contain identical images.
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach-o/swap.h>
+
+static int register_mach_header(void* db, char* build, char* project, struct mach_header* mh, int fd) {
+	int swap = 0;
+	if (mh->magic != MH_MAGIC && mh->magic != MH_CIGAM) return 0;
+	if (mh->magic == MH_CIGAM) { 
+		swap = 1;
+		swap_mach_header(mh, NXHostByteOrder());
+	}
+	
+	switch (mh->filetype) {
+		case MH_EXECUTE:
+		case MH_DYLIB:
+		case MH_BUNDLE:
+			break;
+		case MH_OBJECT:
+		default:
+			return 0;
+	}
+	
+	int i;
+	for (i = 0; i < mh->ncmds; ++i) {
+		struct dylib_command lc;
+		int res = read(fd, &lc, sizeof(struct load_command));
+		if (res < sizeof(struct load_command)) { return 0; }
+
+		uint32_t cmd = swap ? NXSwapLong(lc.cmd) : lc.cmd;
+
+		if (cmd == LC_LOAD_DYLIB || cmd == LC_LOAD_WEAK_DYLIB) {
+			res = read(fd, &lc.dylib, sizeof(struct dylib));
+			if (res < sizeof(struct dylib)) { return 0; }
+
+			if (swap) swap_dylib_command(&lc, NXHostByteOrder());
+
+			off_t save = lseek(fd, 0, SEEK_CUR);
+			off_t offset = lc.dylib.name.offset - sizeof(struct dylib_command);
+
+			if (offset > 0) { lseek(fd, offset, SEEK_CUR); }
+			int strsize = lc.cmdsize - sizeof(struct dylib_command);
+
+			char* str = malloc(strsize+1);
+			res = read(fd, str, strsize);
+			if (res < sizeof(strsize)) { return 0; }
+			str[strsize] = 0; // NUL-terminate
+						
+			res = SQL(db,
+			"INSERT INTO unresolved_dependencies (build,project,type,dependency) VALUES (%Q,%Q,%Q,%Q)",
+			build, project, "lib", str);
+			
+			//fprintf(stdout, "\t%s\n", str);
+			free(str);
+			
+			lseek(fd, save - sizeof(struct dylib_command) + lc.cmdsize, SEEK_SET);
+		} else {
+			uint32_t cmdsize = swap ? NXSwapLong(lc.cmdsize) : lc.cmdsize;
+			lseek(fd, cmdsize - sizeof(struct load_command), SEEK_CUR);
+		}
+	}
+	return 0;
+}
+
+int register_libraries(void* db, char* project, char* version, char* path) {
+	int res;
+	int fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		perror(path);
+		return -1;
+	}
+	
+	struct mach_header mh;
+	struct fat_header fh;
+	
+	// The magic logic assumes mh is bigger than fh.
+	assert(sizeof(mh) >= sizeof(fh));
+	res = read(fd, &mh, sizeof(mh));
+	if (res < sizeof(mh)) { goto error_out; }
+	
+	// It's a fat file.  copy mh over to fh, and dereference.
+	if (mh.magic == FAT_MAGIC || mh.magic == FAT_CIGAM) {
+		int swap = 0;
+		memcpy(&fh, &mh, sizeof(fh));
+		if (fh.magic == FAT_CIGAM) {
+			swap = 1;
+			swap_fat_header(&fh, NXHostByteOrder());
+		}
+		lseek(fd, (off_t)sizeof(fh), SEEK_SET);
+
+		int i;
+		for (i = 0; i < fh.nfat_arch; ++i) {
+			struct fat_arch fa;
+			res = read(fd, &fa, sizeof(fa));
+			if (res < sizeof(fa)) { goto error_out; }
+			
+			if (swap) swap_fat_arch(&fa, 1, NXHostByteOrder());
+						
+			off_t save = lseek(fd, 0, SEEK_CUR);
+			lseek(fd, (off_t)fa.offset, SEEK_SET);
+
+			res = read(fd, &mh, sizeof(mh));
+			if (res < sizeof(mh)) { goto error_out; }
+			register_mach_header(db, project, version, &mh, fd);
+			
+			lseek(fd, save, SEEK_SET);
+		}
+	} else {
+		register_mach_header(db, project, version, &mh, fd);
+	}
+error_out:
+	close(fd);
+	return 0;
+}
+
+
+int register_files(void* db, char* build, char* project, char* path) {
+	char* errmsg;
+	int res;
+	int loaded = 0;
+	
+	char* table = "CREATE TABLE files (build text, project text, path text)";
+	char* index = "CREATE INDEX files_index ON files (build, project, path)";
+	SQL_NOERR(db, table);
+	SQL_NOERR(db, index);
+	
+	if (SQL(db, "BEGIN")) { return -1; }
+	
+	res = SQL(db,
+		"DELETE FROM files WHERE build=%Q AND project=%Q",
+		build, project);
+
+	SQL(db,
+		"DELETE FROM unresolved_dependencies WHERE build=%Q AND project=%Q", 
+		build, project);
+
+	//
+	// Enumerate the files in the path (DSTROOT) and associate them
+	// with the project name and version in the sqlite database.
+	// Uses ent->fts_number to mark which files we have and have
+	// not seen before.
+	//
+	// Skip the first result, since that is . of the DSTROOT itself.
+	int skip = 1;
+	char* path_argv[] = { path, NULL };
+	FTS* fts = fts_open(path_argv, FTS_PHYSICAL | FTS_XDEV, NULL);
+	if (fts != NULL) {
+		FTSENT* ent;
+		while (ent = fts_read(fts)) {
+			if (ent->fts_number == 0) {
+				char path[PATH_MAX];
+				path[0] = 0;
+				buildpath(path, PATH_MAX-1, ent);
+
+				// don't bother to store $DSTROOT
+				if (!skip) {
+					printf("%s\n", path);
+					++loaded;
+					res = SQL(db,
+	"INSERT INTO files (build, project, path) VALUES (%Q,%Q,%Q)",
+						build, project, path);
+				} else {
+					skip = 0;
+				}
+
+				ent->fts_number = 1;
+
+				if (ent->fts_info == FTS_F) {
+					res = register_libraries(db, build, project, ent->fts_accpath);
+				}
+			}
+		}
+		fts_close(fts);
+	}
+	
+	if (SQL(db, "COMMIT")) { return -1; }
+
+	fprintf(stdout, "%d files registered.\n", loaded);
+	
+	return res;
+}


Property changes on: trunk/darwinxref/plugins/register.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/resolveDeps.c
===================================================================
--- trunk/darwinxref/plugins/resolveDeps.c	                        (rev 0)
+++ trunk/darwinxref/plugins/resolveDeps.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int resolve_dependencies(void* session, const char* build, const char* project);
+
+static int run(void* session, CFArrayRef argv) {
+	int res = 0;
+	CFIndex count = CFArrayGetCount(argv);
+	if (count >= 1)  return -1;
+	char* project = (count == 1) ? strdup_cfstr(CFArrayGetValueAtIndex(argv, 0)) : NULL;
+	char* build = strdup_cfstr(DBGetCurrentBuild(session));
+	resolve_dependencies(session, build, project);
+	free(project);
+	return res;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[<project>]"));
+}
+
+DBPlugin* initialize(int version) {
+	DBPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->version = kDBPluginCurrentVersion;
+	plugin->type = kDBPluginType;
+	plugin->name = CFSTR("resolveDeps");
+	plugin->run = &run;
+	plugin->usage = &usage;
+
+	return plugin;
+}
+
+static int addToCStrArrays(void* pArg, int argc, char** argv, char** columnNames) {
+	int i;
+	for (i = 0; i < argc; ++i) {
+		CFMutableArrayRef array = ((CFMutableArrayRef*)pArg)[i];
+		CFArrayAppendValue(array, argv[i]);
+	}
+	return 0;
+}
+
+int resolve_project_dependencies(void* db, const char* build, const char* project, int* resolvedCount, int* unresolvedCount) {
+	CFMutableArrayRef files = CFArrayCreateMutable(NULL, 0, &cfArrayCStringCallBacks);
+	CFMutableArrayRef types = CFArrayCreateMutable(NULL, 0, &cfArrayCStringCallBacks);
+	CFMutableArrayRef params[2] = { files, types };
+
+	if (SQL(db, "BEGIN")) { return -1; }
+
+	SQL_CALLBACK(db, &addToCStrArrays, params,
+		"SELECT DISTINCT dependency,type FROM unresolved_dependencies WHERE build=%Q AND project=%Q",
+		build, project);
+
+	CFIndex i, count = CFArrayGetCount(files);
+	for (i = 0; i < count; ++i) {
+		const char* file = CFArrayGetValueAtIndex(files, i);
+		const char* type = CFArrayGetValueAtIndex(types, i);
+		// XXX
+		// This assumes a 1-to-1 mapping between files and projects.
+		char* dep = (char*)SQL_STRING(db, "SELECT project FROM files WHERE path=%Q", file);
+		if (dep) {
+			// don't add duplicates
+			int exists = SQL_BOOLEAN(db, "SELECT 1 FROM dependencies WHERE build=%Q AND project=%Q AND type=%Q AND dependency=%Q",
+				build, project, type, dep);
+			if (!exists) {
+				SQL(db, "INSERT INTO dependencies (build,project,type,dependency) VALUES (%Q,%Q,%Q,%Q)",
+					build, project, type, dep);
+				*resolvedCount += 1;
+				fprintf(stderr, "\t%s (%s)\n", dep, type);
+			}
+			SQL(db, "DELETE FROM unresolved_dependencies WHERE build=%Q AND project=%Q AND type=%Q AND dependency=%Q",
+				build, project, type, file);
+		} else {
+			*unresolvedCount += 1;
+		}
+	}
+
+	if (SQL(db, "COMMIT")) { return -1; }
+	
+	CFRelease(files);
+	CFRelease(types);
+}
+
+int resolve_dependencies(void* db, const char* build, const char* project) {
+	CFMutableArrayRef builds = CFArrayCreateMutable(NULL, 0, &cfArrayCStringCallBacks);
+	CFMutableArrayRef projects = CFArrayCreateMutable(NULL, 0, &cfArrayCStringCallBacks);
+	int resolvedCount = 0, unresolvedCount = 0;
+	CFMutableArrayRef params[2] = { builds, projects };
+
+	//
+	// If no project, version specified, resolve everything.
+	// Otherwise, resolve only that project or version.
+	//
+	if (build == NULL && project == NULL) {
+		SQL_CALLBACK(db, &addToCStrArrays, params, "SELECT DISTINCT build,project FROM unresolved_dependencies");
+	} else {
+		SQL_CALLBACK(db, &addToCStrArrays, params, "SELECT DISTINCT build,project FROM unresolved_dependencies WHERE project=%Q", project);
+	}
+	CFIndex i, count = CFArrayGetCount(projects);
+	for (i = 0; i < count; ++i) {
+		const char* build = CFArrayGetValueAtIndex(builds, i);
+		const char* project = CFArrayGetValueAtIndex(projects, i);
+		fprintf(stderr, "%s (%s)\n", project, build);
+		resolve_project_dependencies(db, build, project, &resolvedCount, &unresolvedCount);
+	}
+
+	fprintf(stderr, "%d dependencies resolved, %d remaining.\n", resolvedCount, unresolvedCount);
+
+	CFRelease(builds);
+	CFRelease(projects);
+}


Property changes on: trunk/darwinxref/plugins/resolveDeps.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/source_sites.c
===================================================================
--- trunk/darwinxref/plugins/source_sites.c	                        (rev 0)
+++ trunk/darwinxref/plugins/source_sites.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+static int run(void* session, CFArrayRef argv) {
+	CFIndex i, count = CFArrayGetCount(argv);
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFStringRef project = NULL;
+	if (count > 1)  return -1;
+	if (count == 1) {
+		project = CFArrayGetValueAtIndex(argv, 0);
+	}
+	CFArrayRef source_sites = DBCopyPropArray(session, build, project, CFSTR("source_sites"));
+	count = CFArrayGetCount(source_sites);
+	for (i = 0; i < count; ++i) {
+		cfprintf(stdout, "%@\n", CFArrayGetValueAtIndex(source_sites, i));
+	}
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("[<project>]"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("source_sites");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFArrayGetTypeID();
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/source_sites.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/target.c
===================================================================
--- trunk/darwinxref/plugins/target.c	                        (rev 0)
+++ trunk/darwinxref/plugins/target.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+static int run(void* session, CFArrayRef argv) {
+	if (CFArrayGetCount(argv) != 1)  return -1;
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFStringRef project = CFArrayGetValueAtIndex(argv, 0);
+	CFStringRef target = DBCopyPropString(session, build, project, CFSTR("target"));
+	cfprintf(stdout, "%@\n", target);
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<project>"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("target");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFStringGetTypeID();
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/target.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/darwinxref/plugins/version.c
===================================================================
--- trunk/darwinxref/plugins/version.c	                        (rev 0)
+++ trunk/darwinxref/plugins/version.c	2006-10-04 08:36:23 UTC (rev 2)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ * 
+ * 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. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ * 
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "DBPlugin.h"
+
+void printProjectVersion(void* session, CFStringRef project) {
+	CFStringRef build = DBGetCurrentBuild(session);
+	CFStringRef version = DBCopyPropString(session, build, project, CFSTR("version"));
+	if (version == NULL) {
+		CFStringRef original = DBCopyPropString(session, build, project, CFSTR("original"));
+		version = DBCopyPropString(session, build, original, CFSTR("version"));
+	}
+	cfprintf(stdout, "%@-%@\n", project, version);
+}
+
+static int run(void* session, CFArrayRef argv) {
+	if (CFArrayGetCount(argv) != 1)  return -1;
+	CFStringRef project = CFArrayGetValueAtIndex(argv, 0);
+	
+	if (CFEqual(project, CFSTR("*"))) {
+		CFArrayRef projects = DBCopyProjectNames(session, NULL);
+		CFIndex i, count = CFArrayGetCount(projects);
+		for (i = 0; i < count; ++i) {
+			printProjectVersion(session, CFArrayGetValueAtIndex(projects, i));
+		}
+	} else {
+		printProjectVersion(session, project);
+	}
+	
+	return 0;
+}
+
+static CFStringRef usage(void* session) {
+	return CFRetain(CFSTR("<project>"));
+}
+
+DBPropertyPlugin* initialize(int version) {
+	DBPropertyPlugin* plugin = NULL;
+
+	if (version != kDBPluginCurrentVersion) return NULL;
+	
+	plugin = malloc(sizeof(DBPropertyPlugin));
+	if (plugin == NULL) return NULL;
+	
+	plugin->base.version = kDBPluginCurrentVersion;
+	plugin->base.type = kDBPluginPropertyType;
+	plugin->base.name = CFSTR("version");
+	plugin->base.run = &run;
+	plugin->base.usage = &usage;
+	plugin->datatype = CFStringGetTypeID();
+
+	return plugin;
+}


Property changes on: trunk/darwinxref/plugins/version.c
___________________________________________________________________
Name: svn:eol-style
   + native

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20061004/6ecb6480/attachment-0001.html


More information about the darwinbuild-changes mailing list