#include <libc.h>
#include <err.h>
#include <CoreFoundation/CoreFoundation.h>
void mergeToMaster(const void *key, const void *value, void *context);
void extractBootArgs(const void *key, const void *value, void *context);
CFComparisonResult compareStrings(const void *val1, const void *val2, void *context);
int main(int argc, char *argv[]) {
int i;
CFMutableDictionaryRef masterPlist = NULL;
CFMutableDictionaryRef bootArgs = NULL;
CFIndex count, j;
const void **keys = NULL;
CFArrayRef argArrayTmp = NULL;
CFMutableArrayRef argArray = NULL;
if(argc == 1) {
fprintf(stderr, "Usage: %s plist1 plist2\n", getprogname());
exit(1);
}
masterPlist = CFDictionaryCreateMutable(kCFAllocatorDefault,0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
bootArgs = CFDictionaryCreateMutable(kCFAllocatorDefault,0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
for(i=1; i < argc; i++) {
CFURLRef url = NULL;
CFDataRef data = NULL;
CFDictionaryRef dict = NULL;
CFStringRef errorString = NULL;
SInt32 ecode = 0;
char *file = argv[i];
fprintf(stderr, "Processing %s\n", file);
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(UInt8 *)file,
strlen(file), false);
if(url == NULL) {
warn("CFURLCreateFromFileSystemRepresentation(%s)", file);
continue;
}
if(!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, url,
&data, NULL, NULL,
&ecode)) {
warnx("CFURLCreateDataAndPropertiesFromResource(%s): %d", file,
ecode);
CFRelease(url);
continue;
}
CFRelease(url); url = NULL;
dict = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data,
kCFPropertyListImmutable,
&errorString);
if(dict == NULL) {
warnx("CFPropertyListCreateFromXMLData(%s)", file);
if(errorString) {
CFShow(errorString);
CFRelease(errorString);
}
CFRelease(data);
continue;
}
CFRelease(data); data = NULL;
if(CFGetTypeID(dict) != CFDictionaryGetTypeID()) {
warnx("Wrong plist type for %s", file);
CFRelease(dict);
continue;
}
CFDictionaryApplyFunction(dict, mergeToMaster, masterPlist);
CFRelease(dict); dict = NULL;
}
CFDictionaryApplyFunction(masterPlist, extractBootArgs, bootArgs);
count = CFDictionaryGetCount(bootArgs);
keys = calloc(count, sizeof(void *));
CFDictionaryGetKeysAndValues(bootArgs, keys, NULL);
argArrayTmp = CFArrayCreate(kCFAllocatorDefault, keys, count, &kCFTypeArrayCallBacks);
argArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, count, argArrayTmp);
CFRelease(argArrayTmp);
CFArraySortValues(argArray, CFRangeMake(0, count), compareStrings, NULL);
CFShow(argArray);
printf("const char *preserve_boot_args[] = {\n");
for(j=0; j < count; j++) {
CFStringRef barg = (CFStringRef)CFArrayGetValueAtIndex(argArray,j);
CFStringRef comment = (CFStringRef)CFDictionaryGetValue(bootArgs, barg);
char bargc[1024];
char commentc[1024];
if(!CFStringGetCString(barg,bargc,sizeof(bargc), kCFStringEncodingUTF8)) {
continue;
}
if(!CFStringGetCString(comment,commentc,sizeof(commentc), kCFStringEncodingUTF8)) {
continue;
}
printf("\t\"%s\"%s\t/* %s */\n", bargc, (j < count - 1) ? "," : "",
commentc);
}
printf("};\n");
CFRelease(argArray); argArray = NULL;
CFRelease(masterPlist); masterPlist = NULL;
CFRelease(bootArgs); bootArgs = NULL;
return 0;
}
void mergeToMaster(const void *key, const void *value, void *context)
{
CFMutableDictionaryRef masterDict = (CFMutableDictionaryRef)context;
CFDictionaryAddValue(masterDict, key, value);
}
void extractBootArgs(const void *key, const void *value, void *context)
{
#pragma unused (key, context)
CFMutableDictionaryRef bootArgs = (CFMutableDictionaryRef)context;
CFDictionaryRef argDict = (CFDictionaryRef)value;
CFDictionaryApplyFunction(argDict, mergeToMaster, bootArgs);
}
CFComparisonResult compareStrings(const void *val1, const void *val2, void *context)
{
#pragma unused (context)
CFStringRef a = (CFStringRef)val1;
CFStringRef b = (CFStringRef)val2;
return CFStringCompare(a, b, 0);
}