[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(®ex, "^[[:space:]]*#.*", REG_EXTENDED);
+ if (regexec(®ex, line, 1, matches, 0) == 0) {
+ skip = 1;
+ }
+ regfree(®ex);
+
+ // Look for build numbers in the comments
+ regcomp(®ex, "^[[:space:]]*#[[:space:]]*(BUILD[=[:space:]])?[[:space:]]*([^[:space:]]+)[[:space:]]*.*", REG_EXTENDED | REG_ICASE);
+ if (regexec(®ex, 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(®ex);
+
+ // File
+ regcomp(®ex, "^\t(/.*)$", REG_EXTENDED);
+ if (!skip &&
+ project[0] &&
+ build[0] &&
+ regexec(®ex, 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(®ex);
+
+
+ // New Project
+ regcomp(®ex, "^[[:space:]]*([^-]+).*:[[:space:]]*$", REG_EXTENDED | REG_ICASE);
+ if (!skip &&
+ regexec(®ex, 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(®ex);
+
+
+ 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