| 1 | // Reads selector names on stdin and prints those no class on this system implements, |
| 2 | // instance or class side: calls a 10.6 binary could make that would raise at run time. |
| 3 | // `strings BINARY` supplies candidates; names that were never selectors print too. |
| 4 | // Method lists are read directly: asking a class resolves methods, which some raise. |
| 5 | #include <dlfcn.h> |
| 6 | #include <objc/runtime.h> |
| 7 | #include <stdio.h> |
| 8 | #include <stdlib.h> |
| 9 | #include <string.h> |
| 10 | |
| 11 | static int compare(const void *a, const void *b) { |
| 12 | return strcmp(*(const char *const *)a, *(const char *const *)b); |
| 13 | } |
| 14 | |
| 15 | int main(void) { |
| 16 | const char *frameworks[] = {"AppKit", "Carbon", "QuartzCore", "Security", "OpenGL"}; |
| 17 | for (size_t i = 0; i < sizeof frameworks / sizeof *frameworks; i++) { |
| 18 | char path[256]; |
| 19 | snprintf(path, sizeof path, "/System/Library/Frameworks/%s.framework/%s", frameworks[i], frameworks[i]); |
| 20 | dlopen(path, RTLD_NOW); |
| 21 | } |
| 22 | int count = objc_getClassList(NULL, 0); |
| 23 | Class *classes = malloc(sizeof(Class) * count); |
| 24 | objc_getClassList(classes, count); |
| 25 | size_t names = 0, capacity = 1 << 16; |
| 26 | const char **known = malloc(sizeof(char *) * capacity); |
| 27 | for (int i = 0; i < count * 2; i++) { |
| 28 | Class cls = i < count ? classes[i] : object_getClass((id)classes[i - count]); |
| 29 | unsigned methods = 0; |
| 30 | Method *list = class_copyMethodList(cls, &methods); |
| 31 | for (unsigned m = 0; m < methods; m++) { |
| 32 | if (names == capacity) known = realloc(known, sizeof(char *) * (capacity *= 2)); |
| 33 | known[names++] = sel_getName(method_getName(list[m])); |
| 34 | } |
| 35 | free(list); |
| 36 | } |
| 37 | qsort(known, names, sizeof(char *), compare); |
| 38 | char line[1024]; |
| 39 | while (fgets(line, sizeof line, stdin)) { |
| 40 | line[strcspn(line, "\n")] = 0; |
| 41 | const char *name = line; |
| 42 | if (!bsearch(&name, known, names, sizeof(char *), compare)) puts(line); |
| 43 | } |
| 44 | return 0; |
| 45 | } |