Skip to content

Commit 8f045e6

Browse files
committed
[General] Add command line flags to configure CDGenerationOptions
1 parent c215b49 commit 8f045e6

File tree

1 file changed

+127
-5
lines changed

1 file changed

+127
-5
lines changed

Sources/classdumpctl/main.m

Lines changed: 127 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ typedef NS_ENUM(NSUInteger, CDOutputColorMode) {
2424
CDOutputColorModeCaseCount
2525
};
2626

27+
typedef NS_ENUM(NSUInteger, CDOptionBoolValue) {
28+
CDOptionBoolValueStripProtocolConformance = 0x100,
29+
CDOptionBoolValueStripOverrides,
30+
CDOptionBoolValueStripDuplicates,
31+
CDOptionBoolValueStripSynthesized,
32+
CDOptionBoolValueStripCtorMethod,
33+
CDOptionBoolValueStripDtorMethod,
34+
CDOptionBoolValueAddSymbolImageComments,
35+
36+
CDOptionBoolValueCaseEnd
37+
};
38+
2739
static void printUsage(const char *progname) {
2840
printf("Usage: %s [options]\n"
2941
"Options:\n"
@@ -51,6 +63,24 @@ static void printUsage(const char *progname) {
5163
" -j <N>, --jobs=<N> Allow N jobs at once\n"
5264
" only applicable when specified with -a/--dyld_shared_cache\n"
5365
" (defaults to number of processing core available)\n"
66+
"\n"
67+
" --strip-protocol-conformance[=flag] Hide properties and methods\n"
68+
" that are required by a protocol the type conforms to\n"
69+
" (defaults to false)\n"
70+
" --strip-overrides[=flag] Hide properties and methods\n"
71+
" that are inherited from the class hierachy\n"
72+
" (defaults to false)\n"
73+
" --strip-duplicates[=flag] Hide duplicate occurrences of a property or method\n"
74+
" (defaults to false)\n"
75+
" --strip-synthesized[=flag] Hide methods and ivars that are synthesized from a property\n"
76+
" (defaults to true)\n"
77+
" --strip-ctor-method[=flag] Hide `.cxx_construct` method\n"
78+
" (defaults to false)\n"
79+
" --strip-dtor-method[=flag] Hide `.cxx_destruct` method\n"
80+
" (defaults to false)\n"
81+
" --add-symbol-comments[=flag] Add comments above each eligible declaration\n"
82+
" with the symbol name and image path the object is found in\n"
83+
" (defaults to false)\n"
5484
"", progname);
5585
}
5686

@@ -245,6 +275,33 @@ static void printUsage(const char *progname) {
245275
return [semanticString string];
246276
}
247277

278+
/// - Returns: `0` if `value` should be handled as `NO`,
279+
/// `1` if `value` should be handled as `YES`,
280+
/// `-1` if there's an error processing `value`
281+
static int parseOptargBool(const char *const value) {
282+
// no value means enable the flag
283+
if (value == NULL) { return 1; }
284+
285+
if (strcmp(value, "0") == 0) { return 0; }
286+
if (strcmp(value, "1") == 0) { return 1; }
287+
if (strcmp(value, "no") == 0) { return 0; }
288+
if (strcmp(value, "yes") == 0) { return 1; }
289+
if (strcmp(value, "NO") == 0) { return 0; }
290+
if (strcmp(value, "YES") == 0) { return 1; }
291+
if (strcmp(value, "N") == 0) { return 0; }
292+
if (strcmp(value, "Y") == 0) { return 1; }
293+
if (strcmp(value, "n") == 0) { return 0; }
294+
if (strcmp(value, "y") == 0) { return 1; }
295+
if (strcmp(value, "off") == 0) { return 0; }
296+
if (strcmp(value, "on") == 0) { return 1; }
297+
if (strcmp(value, "false") == 0) { return 0; }
298+
if (strcmp(value, "true") == 0) { return 1; }
299+
if (strcmp(value, "FALSE") == 0) { return 0; }
300+
if (strcmp(value, "TRUE") == 0) { return 1; }
301+
302+
return -1;
303+
}
304+
248305
int main(int argc, char *argv[]) {
249306
BOOL dyldSharedCacheFlag = NO;
250307
BOOL listFlag = NO;
@@ -255,6 +312,9 @@ int main(int argc, char *argv[]) {
255312
NSMutableArray<NSString *> *requestProtocolList = [NSMutableArray array];
256313
NSUInteger maxJobs = NSProcessInfo.processInfo.processorCount;
257314

315+
CDGenerationOptions *const generationOptions = [CDGenerationOptions new];
316+
generationOptions.stripSynthesized = YES;
317+
258318
struct option const options[] = {
259319
{ "dyld_shared_cache", no_argument, NULL, 'a' },
260320
{ "list", no_argument, NULL, 'l' },
@@ -264,12 +324,77 @@ int main(int argc, char *argv[]) {
264324
{ "class", required_argument, NULL, 'c' },
265325
{ "protocol", required_argument, NULL, 'p' },
266326
{ "jobs", required_argument, NULL, 'j' },
267-
{ NULL, 0, NULL, 0 }
327+
328+
{ "strip-protocol-conformance", optional_argument, NULL, CDOptionBoolValueStripProtocolConformance },
329+
{ "strip-overrides", optional_argument, NULL, CDOptionBoolValueStripOverrides },
330+
{ "strip-duplicates", optional_argument, NULL, CDOptionBoolValueStripDuplicates },
331+
{ "strip-synthesized", optional_argument, NULL, CDOptionBoolValueStripSynthesized },
332+
{ "strip-ctor-method", optional_argument, NULL, CDOptionBoolValueStripCtorMethod },
333+
{ "strip-dtor-method", optional_argument, NULL, CDOptionBoolValueStripDtorMethod },
334+
{ "add-symbol-comments", optional_argument, NULL, CDOptionBoolValueAddSymbolImageComments },
335+
336+
{ NULL, 0, NULL, 0 }
268337
};
269338

339+
int optionIndex = 0;
270340
int ch;
271-
while ((ch = getopt_long(argc, argv, ":alo:m:i:c:p:j:", options, NULL)) != -1) {
341+
while ((ch = getopt_long(argc, argv, ":alo:m:i:c:p:j:", options, &optionIndex)) != -1) {
272342
switch (ch) {
343+
case CDOptionBoolValueStripProtocolConformance:
344+
case CDOptionBoolValueStripOverrides:
345+
case CDOptionBoolValueStripDuplicates:
346+
case CDOptionBoolValueStripSynthesized:
347+
case CDOptionBoolValueStripCtorMethod:
348+
case CDOptionBoolValueStripDtorMethod:
349+
case CDOptionBoolValueAddSymbolImageComments: {
350+
struct option const *const option = options + optionIndex;
351+
// test if we want to consume the next argument.
352+
// `optional_argument` only provides `optarg` if the
353+
// command line paramter is in the format "--name=value",
354+
// this code allows us to consume "--name" "value".
355+
// We have to validate "value", otherwise we might accidently
356+
// consume "--name" "--flag"
357+
if (optarg == NULL && optind < argc) {
358+
int const parse = parseOptargBool(argv[optind]);
359+
// sucessful parse - consume next arg
360+
if (parse >= 0) {
361+
optarg = argv[optind];
362+
optind++;
363+
}
364+
}
365+
int const parse = parseOptargBool(optarg);
366+
if (parse < 0) {
367+
fprintf(stderr, "Unknown value for --%s: '%s', expected 'yes', 'no'\n", option->name, optarg);
368+
return 1;
369+
}
370+
371+
BOOL const flag = (parse != 0);
372+
switch (ch) {
373+
case CDOptionBoolValueStripProtocolConformance:
374+
generationOptions.stripProtocolConformance = flag;
375+
break;
376+
case CDOptionBoolValueStripOverrides:
377+
generationOptions.stripOverrides = flag;
378+
break;
379+
case CDOptionBoolValueStripDuplicates:
380+
generationOptions.stripDuplicates = flag;
381+
break;
382+
case CDOptionBoolValueStripSynthesized:
383+
generationOptions.stripSynthesized = flag;
384+
break;
385+
case CDOptionBoolValueStripCtorMethod:
386+
generationOptions.stripCtorMethod = flag;
387+
break;
388+
case CDOptionBoolValueStripDtorMethod:
389+
generationOptions.stripDtorMethod = flag;
390+
break;
391+
case CDOptionBoolValueAddSymbolImageComments:
392+
generationOptions.addSymbolImageComments = flag;
393+
break;
394+
default:
395+
break;
396+
}
397+
} break;
273398
case 'a':
274399
dyldSharedCacheFlag = YES;
275400
break;
@@ -329,9 +454,6 @@ int main(int argc, char *argv[]) {
329454
return 1;
330455
}
331456

332-
CDGenerationOptions *const generationOptions = [CDGenerationOptions new];
333-
generationOptions.stripSynthesized = YES;
334-
335457
IMP const blankIMP = imp_implementationWithBlock(^{ }); // returns void, takes no parameters
336458

337459
// just doing this once before we potentially delete some class initializers

0 commit comments

Comments
 (0)