[57077] users/toby/objcports
toby at macports.org
toby at macports.org
Sun Sep 6 01:06:41 PDT 2009
Revision: 57077
http://trac.macports.org/changeset/57077
Author: toby at macports.org
Date: 2009-09-06 01:06:37 -0700 (Sun, 06 Sep 2009)
Log Message:
-----------
scary stuff
Added Paths:
-----------
users/toby/objcports/misc/
users/toby/objcports/misc/depstree.c
users/toby/objcports/misc/depstree2.c
Added: users/toby/objcports/misc/depstree.c
===================================================================
--- users/toby/objcports/misc/depstree.c (rev 0)
+++ users/toby/objcports/misc/depstree.c 2009-09-06 08:06:37 UTC (rev 57077)
@@ -0,0 +1,270 @@
+#include <CoreFoundation/CoreFoundation.h>
+#include <getopt.h>
+#include <tcl.h>
+
+CFStringRef
+CFStringCreateWithTclObject(CFAllocatorRef allocator, Tcl_Obj *obj)
+{
+ return CFStringCreateWithCString(allocator, Tcl_GetString(obj), kCFStringEncodingUTF8);
+}
+
+CFArrayRef
+CFArrayCreateTcl(CFAllocatorRef allocator, Tcl_Obj **objects, CFIndex count)
+{
+ CFIndex i;
+ CFStringRef array[count];
+ CFArrayRef result;
+
+ for (i = 0; i < count; i++) {
+ array[i] = CFStringCreateWithTclObject(allocator, objects[i]);
+ }
+ result = CFArrayCreate(allocator, (const void **)array, count, &kCFTypeArrayCallBacks);
+ for (i = 0; i < count; i++) {
+ CFRelease(array[i]);
+ }
+ return result;
+}
+
+char *
+strdup_cf(CFStringRef str)
+{
+ CFIndex length, size;
+ char *result = NULL;
+
+ length = CFStringGetLength(str);
+ size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+ result = malloc(size);
+ CFStringGetCString(str, result, size, kCFStringEncodingUTF8);
+
+ return result;
+}
+
+int
+fprintf_cf(FILE *stream, CFStringRef format, ...)
+{
+ va_list ap;
+ CFStringRef str;
+ char *output;
+ int rc = -1;
+
+ va_start(ap, format);
+ str = CFStringCreateWithFormatAndArguments(NULL, NULL, format, ap);
+ va_end(ap);
+
+ output = strdup_cf(str);
+ CFRelease(str);
+ rc = fprintf(stream, "%s", output);
+ free(output);
+
+ return rc;
+}
+
+CFDictionaryRef
+copy_indexentry(Tcl_Interp *interp, Tcl_Obj **objects, CFIndex count)
+{
+ CFDictionaryRef result = NULL;
+ CFIndex i;
+ CFIndex count2 = count / 2;
+ CFStringRef keys[count2];
+ CFTypeRef values[count2];
+
+ for (i = 0; i < count2; i++) {
+ keys[i] = CFStringCreateWithTclObject(NULL, objects[i * 2]);
+ if (CFStringHasPrefix(keys[i], CFSTR("depends_"))) {
+ int objc;
+ Tcl_Obj **objv;
+ Tcl_ListObjGetElements(interp, objects[i * 2 + 1], &objc, &objv);
+ values[i] = CFArrayCreateTcl(NULL, objv, objc);
+ } else {
+ values[i] = CFStringCreateWithTclObject(NULL, objects[i * 2 + 1]);
+ }
+ }
+ result = CFDictionaryCreate(NULL, (const void **)keys, values, count2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (i = 0; i < count2; i++) {
+ CFRelease(keys[i]);
+ CFRelease(values[i]);
+ }
+
+ return result;
+}
+
+CFDictionaryRef
+get_portindex()
+{
+ static CFMutableDictionaryRef dict;
+ Tcl_Interp *interp;
+ Tcl_Channel chan;
+
+ if (dict) {
+ return dict;
+ }
+
+ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ interp = Tcl_CreateInterp();
+ assert(Tcl_SetSystemEncoding(interp, "utf-8") == TCL_OK);
+ chan = Tcl_OpenFileChannel(interp, "/Volumes/data/source/macports/dports/PortIndex", "r", 0);
+ Tcl_RegisterChannel(interp, chan);
+
+ while (1) {
+ int objc;
+ Tcl_Obj **objv;
+ CFTypeRef key, value;
+ CFArrayRef info;
+ Tcl_Obj *line;
+ int len;
+
+ line = Tcl_NewObj();
+ Tcl_IncrRefCount(line);
+
+ /* Read info line. */
+ if (Tcl_GetsObj(chan, line) < 0) {
+ Tcl_DecrRefCount(line);
+ break;
+ }
+ Tcl_ListObjGetElements(interp, line, &objc, &objv);
+ info = CFArrayCreateTcl(NULL, objv, objc);
+ assert(CFArrayGetCount(info) == 2);
+ key = CFRetain(CFArrayGetValueAtIndex(info, 0));
+ len = CFStringGetIntValue(CFArrayGetValueAtIndex(info, 1));
+ CFRelease(info);
+
+ /* Read dictionary. */
+ Tcl_ReadChars(chan, line, len, 0);
+ Tcl_ListObjGetElements(interp, line, &objc, &objv);
+ value = copy_indexentry(interp, objv, objc);
+ assert(value != nil);
+
+ /* Store data. */
+ CFDictionarySetValue(dict, key, value);
+
+ CFRelease(key);
+ CFRelease(value);
+
+ Tcl_DecrRefCount(line);
+ }
+
+ Tcl_UnregisterChannel(interp, chan);
+ Tcl_DeleteInterp(interp);
+
+ return dict;
+}
+
+static CFStringRef deptypes[] = {
+ CFSTR("depends_build"),
+ CFSTR("depends_lib"),
+ CFSTR("depends_run"),
+};
+
+CFArrayRef
+find_deps(CFStringRef port)
+{
+ CFDictionaryRef info;
+ CFMutableArrayRef deps;
+ CFArrayRef tmp, split;
+ CFIndex i, j, count;
+
+ deps = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ info = CFDictionaryGetValue(get_portindex(), port);
+
+ for (i = 0; i < 3; i++) {
+ tmp = CFDictionaryGetValue(info, deptypes[i]);
+ if (!tmp) continue;
+ count = CFArrayGetCount(tmp);
+ for (j = 0; j < count; j++) {
+ split = CFStringCreateArrayBySeparatingStrings(NULL, CFArrayGetValueAtIndex(tmp, j), CFSTR(":"));
+ CFArrayAppendValue(deps, CFArrayGetValueAtIndex(split, CFArrayGetCount(split) - 1));
+ CFRelease(split);
+ }
+ }
+
+ return deps;
+}
+
+static CFTreeRef
+create_port_tree(CFStringRef port)
+{
+ CFTreeRef tree, child;
+ CFTreeContext context;
+ CFArrayRef deps;
+ CFIndex i, count;
+
+ bzero(&context, sizeof(context));
+ context.info = (void *)port;
+ context.retain = CFRetain;
+ context.release = CFRelease;
+ tree = CFTreeCreate(NULL, &context);
+
+ deps = find_deps(port);
+ count = CFArrayGetCount(deps);
+ for (i = 0; i < count; i++) {
+ child = create_port_tree(CFArrayGetValueAtIndex(deps, i));
+ CFTreeAppendChild(tree, child);
+ CFRelease(child);
+ }
+ CFRelease(deps);
+
+ return tree;
+}
+
+static void
+dump_tree(CFTreeRef tree, CFIndex indent)
+{
+ CFIndex i, count;
+ CFMutableStringRef output;
+ CFTreeContext context;
+
+ output = CFStringCreateMutable(NULL, 0);
+ for (i = 0; i < indent; i++) {
+ CFStringAppend(output, CFSTR(" "));
+ }
+
+ CFTreeGetContext(tree, &context);
+ CFStringAppend(output, context.info);
+ fprintf_cf(stdout, indent ? CFSTR("%@\n") : CFSTR("Dependencies of %@:\n"), output);
+ CFRelease(output);
+
+ count = CFTreeGetChildCount(tree);
+ for (i = 0; i < count; i++) {
+ dump_tree(CFTreeGetChildAtIndex(tree, i), indent + 1);
+ }
+}
+
+static void __dead2
+usage(void)
+{
+ fprintf(stderr, "usage: depstree port\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ CFStringRef port;
+ CFTreeRef tree;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ usage();
+ }
+
+ port = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ tree = create_port_tree(port);
+ CFRelease(port);
+ dump_tree(tree, 0);
+ CFRelease(tree);
+
+ return 0;
+}
Added: users/toby/objcports/misc/depstree2.c
===================================================================
--- users/toby/objcports/misc/depstree2.c (rev 0)
+++ users/toby/objcports/misc/depstree2.c 2009-09-06 08:06:37 UTC (rev 57077)
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2009 Toby Peterson <toby at macports.org>. All rights reserved.
+ */
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <tcl.h>
+#include <unistd.h>
+
+CFStringRef
+CFStringCreateWithTclObject(CFAllocatorRef allocator, Tcl_Obj *obj)
+{
+ return CFStringCreateWithCString(allocator, Tcl_GetString(obj), kCFStringEncodingUTF8);
+}
+
+CFArrayRef
+CFArrayCreateTcl(CFAllocatorRef allocator, Tcl_Obj **objects, CFIndex count)
+{
+ CFIndex i;
+ CFStringRef array[count];
+ CFArrayRef result;
+
+ for (i = 0; i < count; i++) {
+ array[i] = CFStringCreateWithTclObject(allocator, objects[i]);
+ }
+ result = CFArrayCreate(allocator, (const void **)array, count, &kCFTypeArrayCallBacks);
+ for (i = 0; i < count; i++) {
+ CFRelease(array[i]);
+ }
+ return result;
+}
+
+char *
+strdup_cf(CFStringRef str)
+{
+ CFIndex length, size;
+ char *result = NULL;
+
+ length = CFStringGetLength(str);
+ size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+ result = malloc(size);
+ CFStringGetCString(str, result, size, kCFStringEncodingUTF8);
+
+ return result;
+}
+
+int
+fprintf_cf(FILE *stream, CFStringRef format, ...)
+{
+ va_list ap;
+ CFStringRef str;
+ char *output;
+ __block int rc = -1;
+
+ static dispatch_once_t once;
+ static dispatch_queue_t pqueue;
+
+ dispatch_once(&once, ^{
+ pqueue = dispatch_queue_create(NULL, NULL);
+ });
+
+ va_start(ap, format);
+ str = CFStringCreateWithFormatAndArguments(NULL, NULL, format, ap);
+ va_end(ap);
+
+ output = strdup_cf(str);
+ CFRelease(str);
+ dispatch_sync(pqueue, ^{
+ rc = fprintf(stream, "%s", output);
+ });
+ free(output);
+
+ return rc;
+}
+
+CFDictionaryRef
+copy_indexentry(Tcl_Interp *interp, Tcl_Obj **objects, CFIndex count)
+{
+ CFDictionaryRef result = NULL;
+ CFIndex i;
+ CFIndex count2 = count / 2;
+ CFStringRef keys[count2];
+ CFTypeRef values[count2];
+
+ for (i = 0; i < count2; i++) {
+ keys[i] = CFStringCreateWithTclObject(NULL, objects[i * 2]);
+ if (CFStringHasPrefix(keys[i], CFSTR("depends_"))) {
+ int objc;
+ Tcl_Obj **objv;
+ Tcl_ListObjGetElements(interp, objects[i * 2 + 1], &objc, &objv);
+ values[i] = CFArrayCreateTcl(NULL, objv, objc);
+ } else {
+ values[i] = CFStringCreateWithTclObject(NULL, objects[i * 2 + 1]);
+ }
+ }
+ result = CFDictionaryCreate(NULL, (const void **)keys, values, count2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (i = 0; i < count2; i++) {
+ CFRelease(keys[i]);
+ CFRelease(values[i]);
+ }
+
+ return result;
+}
+
+CFDictionaryRef
+get_portindex()
+{
+ static CFMutableDictionaryRef dict;
+ Tcl_Interp *interp;
+ Tcl_Channel chan;
+
+ if (dict) {
+ return dict;
+ }
+
+ dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ interp = Tcl_CreateInterp();
+ assert(Tcl_SetSystemEncoding(interp, "utf-8") == TCL_OK);
+ chan = Tcl_OpenFileChannel(interp, "/Volumes/data/source/macports/dports/PortIndex", "r", 0);
+ Tcl_RegisterChannel(interp, chan);
+
+ while (1) {
+ int objc;
+ Tcl_Obj **objv;
+ CFTypeRef key, value;
+ CFArrayRef info;
+ Tcl_Obj *line;
+ int len;
+
+ line = Tcl_NewObj();
+ Tcl_IncrRefCount(line);
+
+ /* Read info line. */
+ if (Tcl_GetsObj(chan, line) < 0) {
+ Tcl_DecrRefCount(line);
+ break;
+ }
+ Tcl_ListObjGetElements(interp, line, &objc, &objv);
+ info = CFArrayCreateTcl(NULL, objv, objc);
+ assert(CFArrayGetCount(info) == 2);
+ key = CFRetain(CFArrayGetValueAtIndex(info, 0));
+ len = CFStringGetIntValue(CFArrayGetValueAtIndex(info, 1));
+ CFRelease(info);
+
+ /* Read dictionary. */
+ Tcl_ReadChars(chan, line, len, 0);
+ Tcl_ListObjGetElements(interp, line, &objc, &objv);
+ value = copy_indexentry(interp, objv, objc);
+ assert(value != nil);
+
+ /* Store data. */
+ CFDictionarySetValue(dict, key, value);
+
+ CFRelease(key);
+ CFRelease(value);
+
+ Tcl_DecrRefCount(line);
+ }
+
+ Tcl_UnregisterChannel(interp, chan);
+ Tcl_DeleteInterp(interp);
+
+ return dict;
+}
+
+static CFStringRef deptypes[] = {
+ CFSTR("depends_build"),
+ CFSTR("depends_lib"),
+ CFSTR("depends_run"),
+};
+
+CFArrayRef
+copy_deps(CFStringRef port)
+{
+ CFDictionaryRef info;
+ CFMutableArrayRef deps;
+ CFArrayRef tmp, split;
+ CFIndex i, j, count;
+
+ deps = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ info = CFDictionaryGetValue(get_portindex(), port);
+
+ for (i = 0; i < 3; i++) {
+ tmp = CFDictionaryGetValue(info, deptypes[i]);
+ if (!tmp) continue;
+ count = CFArrayGetCount(tmp);
+ for (j = 0; j < count; j++) {
+ split = CFStringCreateArrayBySeparatingStrings(NULL, CFArrayGetValueAtIndex(tmp, j), CFSTR(":"));
+ CFArrayAppendValue(deps, CFArrayGetValueAtIndex(split, CFArrayGetCount(split) - 1));
+ CFRelease(split);
+ }
+ }
+
+ return deps;
+}
+
+static Boolean
+skip_port(CFStringRef port, dispatch_group_t *group)
+{
+ static CFMutableDictionaryRef built;
+ static dispatch_queue_t built_queue;
+ static dispatch_once_t once;
+ __block Boolean skip = TRUE;
+
+ dispatch_once(&once, ^{
+ built_queue = dispatch_queue_create(NULL, NULL);
+ dispatch_sync(built_queue, ^{
+ built = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
+ });
+ });
+
+ dispatch_sync(built_queue, ^{
+ if (!CFDictionaryContainsKey(built, port)) {
+ skip = FALSE;
+ *group = dispatch_group_create();
+ CFDictionarySetValue(built, port, *group);
+ } else {
+ skip = TRUE;
+ *group = (dispatch_group_t)CFDictionaryGetValue(built, port);
+ }
+ });
+
+ return skip;
+}
+
+static void
+build_port(CFStringRef port, CFIndex indent)
+{
+ CFMutableStringRef output;
+ CFIndex j;
+ dispatch_group_t group;
+
+ if (skip_port(port, &group)) {
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ return;
+ }
+
+ dispatch_group_enter(group);
+
+ output = CFStringCreateMutable(NULL, 0);
+ for (j = 0; j < indent; j++) {
+ CFStringAppend(output, CFSTR(" "));
+ }
+ CFStringAppend(output, port);
+ fprintf_cf(stdout, CFSTR("building %@\n"), output);
+
+ // fake it
+ usleep(random() / 700);
+
+ fprintf_cf(stdout, CFSTR(" done %@\n"), output);
+
+ CFRelease(output);
+
+ dispatch_group_leave(group);
+ // TODO: leaking this, not sure where to release it
+ //dispatch_release(group);
+}
+
+static void
+build_port_tree(CFStringRef port, CFIndex indent)
+{
+ dispatch_group_t group;
+ CFArrayRef deps;
+ CFIndex count;
+
+ deps = copy_deps(port);
+ count = CFArrayGetCount(deps);
+
+ group = dispatch_group_create();
+
+ if (count) {
+ dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i) {
+ dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
+ build_port_tree(CFArrayGetValueAtIndex(deps, i), indent + 1);
+ });
+ });
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ CFRelease(deps);
+
+ build_port(port, indent);
+ } else {
+ build_port(port, indent);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ CFStringRef port;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: depstree port\n");
+ exit(1);
+ }
+
+ srandom(time(NULL));
+
+ port = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
+ build_port_tree(port, 0);
+ CFRelease(port);
+
+ dispatch_main();
+
+ return 0;
+}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20090906/3ad2c084/attachment-0001.html>
More information about the macports-changes
mailing list