Allow KernelConfigParser to be less restrictive
Rewrite KernelConfigParser::processRemaining() to allow
the following text:
# CONFIG_NOT_SET is not set
CONFIG_ONE=1 # 'tis a one!
CONFIG_TWO=2 #'tis a two!
CONFIG_THREE=3#'tis a three!
CONFIG_233=233#'tis a three!
CONFIG_Y=y
CONFIG_YES=y#YES!
CONFIG_STR=string
CONFIG_HELLO=hello world! #still works
CONFIG_WORLD=hello world!
CONFIG_GOOD = good morning! #comments here
CONFIG_MORNING = good morning!
Test: libvintf_test
Bug: 38324908
Change-Id: I1e8112b8cbf1f1d8a2b6b34daa9a593eff69cff2
diff --git a/KernelConfigParser.cpp b/KernelConfigParser.cpp
index 1d08fca..44cbf07 100644
--- a/KernelConfigParser.cpp
+++ b/KernelConfigParser.cpp
@@ -18,6 +18,13 @@
#include <regex>
+#define KEY "(CONFIG[\\w_]+)"
+#define COMMENT "(?:#.*)"
+
+static const std::regex sKeyValuePattern("^\\s*" KEY "\\s*=\\s*([^#]+)" COMMENT "?$");
+static const std::regex sNotSetPattern("^\\s*#\\s*" KEY " is not set\\s*$");
+static const std::regex sCommentPattern("^\\s*" COMMENT "$");
+
namespace android {
namespace vintf {
@@ -39,43 +46,44 @@
return mConfigs;
}
+// trim spaces between value and #, value and end of line
+std::string trimTrailingSpaces(const std::string& s) {
+ auto r = s.rbegin();
+ for (; r != s.rend() && std::isspace(*r); ++r)
+ ;
+ return std::string{s.begin(), r.base()};
+}
+
status_t KernelConfigParser::processRemaining() {
- static std::regex sCommentPattern("^# (CONFIG[\\w_]+) is not set$");
if (mRemaining.empty()) {
return OK;
}
- if (mRemaining[0] == '#') {
- if (!mProcessComments) {
+ std::smatch match;
+ if (std::regex_match(mRemaining, match, sKeyValuePattern)) {
+ if (mConfigs.emplace(match[1], trimTrailingSpaces(match[2])).second) {
return OK;
}
- std::smatch sm;
- if (!std::regex_match(mRemaining, sm, sCommentPattern)) {
- return OK; // ignore this comment;
- }
- if (!mConfigs.emplace(sm[1], "n").second) {
- mError << "Key " << sm[1] << " is set but commented as not set"
- << "\n";
- return UNKNOWN_ERROR;
- }
+ mError << "Duplicated key in configs: " << match[1] << "\n";
+ return UNKNOWN_ERROR;
+ }
+ if (mProcessComments && std::regex_match(mRemaining, match, sNotSetPattern)) {
+ if (mConfigs.emplace(match[1], "n").second) {
+ return OK;
+ }
+ mError << "Key " << match[1] << " is set but commented as not set"
+ << "\n";
+ return UNKNOWN_ERROR;
+ }
+
+ if (std::regex_match(mRemaining, match, sCommentPattern)) {
return OK;
}
- size_t equalPos = mRemaining.find('=');
- if (equalPos == std::string::npos) {
- mError << "Unrecognized line in configs: " << mRemaining << "\n";
- return UNKNOWN_ERROR;
- }
- std::string key = mRemaining.substr(0, equalPos);
- std::string value = mRemaining.substr(equalPos + 1);
- if (!mConfigs.emplace(std::move(key), std::move(value)).second) {
- mError << "Duplicated key in configs: " << mRemaining.substr(0, equalPos) << "\n";
- return UNKNOWN_ERROR;
- }
-
- return OK;
+ mError << "Unrecognized line in configs: " << mRemaining << "\n";
+ return UNKNOWN_ERROR;
}
status_t KernelConfigParser::process(const char* buf, size_t len) {