in libredex/ProguardParser.cpp [883:1162]
void parse(const std::vector<Token>& vec,
ProguardConfiguration* pg_config,
size_t& parse_errors,
size_t& unimplemented,
const std::string& filename) {
bool ok;
TokenIndex idx{vec, vec.begin()};
while (idx.it != idx.vec.end()) {
// Break out if we are at the end of the TokenType stream.
if (idx.type() == TokenType::eof_token) {
break;
}
if (idx.type() == TokenType::comment) {
idx.next();
continue;
}
uint32_t line = idx.line();
if (!idx.it->is_command()) {
std::cerr << "Expecting command but found " << idx.show() << " at line "
<< idx.line() << std::endl
<< idx.show_context(2) << std::endl;
idx.next();
skip_to_next_command(idx);
continue;
}
// Input/Output Options
if (parse_filepath_command(idx,
TokenType::include,
pg_config->basedirectory,
&pg_config->includes)) {
continue;
}
if (parse_single_filepath_command(
idx, TokenType::basedirectory, &pg_config->basedirectory)) {
continue;
}
if (parse_jars(idx,
TokenType::injars,
pg_config->basedirectory,
&pg_config->injars)) {
continue;
}
if (parse_jars(idx,
TokenType::outjars,
pg_config->basedirectory,
&pg_config->outjars)) {
continue;
}
if (parse_jars(idx,
TokenType::libraryjars,
pg_config->basedirectory,
&pg_config->libraryjars)) {
continue;
}
// -skipnonpubliclibraryclasses not supported
if (idx.type() == TokenType::dontskipnonpubliclibraryclasses) {
// Silenty ignore the dontskipnonpubliclibraryclasses option.
idx.next();
continue;
}
// -dontskipnonpubliclibraryclassmembers not supported
if (parse_filepath_command(idx,
TokenType::keepdirectories,
pg_config->basedirectory,
&pg_config->keepdirectories)) {
continue;
}
if (parse_target(idx, &pg_config->target_version)) {
continue;
}
// -forceprocessing not supported
// Keep Options
if (parse_keep(idx,
TokenType::keep,
&pg_config->keep_rules,
true, // mark_classes
false, // mark_conditionally
false, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_keep(idx,
TokenType::keepclassmembers,
&pg_config->keep_rules,
false, // mark_classes
false, // mark_conditionally
false, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_keep(idx,
TokenType::keepclasseswithmembers,
&pg_config->keep_rules,
false, // mark_classes
true, // mark_conditionally
false, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_keep(idx,
TokenType::keepnames,
&pg_config->keep_rules,
true, // mark_classes
false, // mark_conditionally
true, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_keep(idx,
TokenType::keepclassmembernames,
&pg_config->keep_rules,
false, // mark_classes
false, // mark_conditionally
true, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_keep(idx,
TokenType::keepclasseswithmembernames,
&pg_config->keep_rules,
false, // mark_classes
true, // mark_conditionally
true, // allowshrinking
filename,
line,
&ok)) {
if (!ok) {
++parse_errors;
}
continue;
}
if (parse_optional_filepath_command(
idx, TokenType::printseeds, &pg_config->printseeds)) {
continue;
}
// Shrinking Options
if (parse_bool_command(
idx, TokenType::dontshrink, false, &pg_config->shrink)) {
continue;
}
if (parse_optional_filepath_command(
idx, TokenType::printusage, &pg_config->printusage)) {
continue;
}
// Optimization Options
if (parse_boolean_command(
idx, TokenType::dontoptimize, &pg_config->optimize, false)) {
continue;
}
if (parse_filter_list_command(
idx, TokenType::optimizations, &pg_config->optimization_filters)) {
continue;
}
if (parse_optimizationpasses_command(idx)) {
continue;
}
if (parse_keep(idx,
TokenType::assumenosideeffects,
&pg_config->assumenosideeffects_rules,
false, // mark_classes
false, // mark_conditionally
false, // allowshrinking
filename,
line,
&ok)) {
continue;
}
if (parse_keep(idx,
TokenType::whyareyoukeeping,
&pg_config->whyareyoukeeping_rules,
false, // mark_classes
false, // mark_conditionally
false, // allowshrinking
filename,
line,
&ok)) {
continue;
}
// Obfuscation Options
if (idx.type() == TokenType::dontobfuscate) {
pg_config->dontobfuscate = true;
idx.next();
continue;
}
// Redex ignores -dontskipnonpubliclibraryclasses
if (idx.type() == TokenType::dontskipnonpubliclibraryclasses) {
idx.next();
continue;
}
if (parse_optional_filepath_command(
idx, TokenType::printmapping, &pg_config->printmapping)) {
continue;
}
if (parse_optional_filepath_command(idx,
TokenType::printconfiguration,
&pg_config->printconfiguration)) {
continue;
}
if (parse_allowaccessmodification(idx,
&pg_config->allowaccessmodification)) {
continue;
}
if (parse_dontusemixedcaseclassnames(
idx, &pg_config->dontusemixedcaseclassnames)) {
continue;
}
if (parse_filter_list_command(
idx, TokenType::keeppackagenames, &pg_config->keeppackagenames)) {
continue;
}
if (parse_dontpreverify(idx, &pg_config->dontpreverify)) {
continue;
}
if (parse_verbose(idx, &pg_config->verbose)) {
continue;
}
if (parse_repackageclasses(idx)) {
continue;
}
if (parse_filter_list_command(
idx, TokenType::dontwarn, &pg_config->dontwarn)) {
continue;
}
if (parse_filter_list_command(
idx, TokenType::keepattributes, &pg_config->keepattributes)) {
continue;
}
// Skip unknown token.
if (idx.it->is_command()) {
const auto& name = idx.data();
// It is benign to drop -dontnote
if (name != "dontnote") {
std::cerr << "Unimplemented command (skipping): " << idx.show()
<< " at line " << idx.line() << std::endl
<< idx.show_context(2) << std::endl;
++unimplemented;
}
} else {
std::cerr << "Unexpected TokenType " << idx.show() << " at line "
<< idx.line() << std::endl
<< idx.show_context(2) << std::endl;
++parse_errors;
}
idx.next();
skip_to_next_command(idx);
}
}