diff --git a/src/util/OptionDef.hxx b/src/util/OptionDef.hxx
index aa83045f4..ab8b255bf 100644
--- a/src/util/OptionDef.hxx
+++ b/src/util/OptionDef.hxx
@@ -29,6 +29,7 @@ class OptionDef
 {
 	const char *long_option;
 	char short_option;
+	bool has_value = false;
 	const char *desc;
 public:
 	constexpr OptionDef(const char *_long_option, const char *_desc)
@@ -42,8 +43,21 @@ public:
 		  short_option(_short_option),
 		  desc(_desc) { }
 
+	constexpr OptionDef(const char *_long_option,
+			    char _short_option, bool _has_value,
+			    const char *_desc) noexcept
+		:long_option(_long_option),
+		 short_option(_short_option),
+		 has_value(_has_value),
+		 desc(_desc) {}
+
 	constexpr bool HasLongOption() const { return long_option != nullptr; }
 	constexpr bool HasShortOption() const { return short_option != 0; }
+
+	constexpr bool HasValue() const noexcept {
+		return has_value;
+	}
+
 	constexpr bool HasDescription() const { return desc != nullptr; }
 
 	const char *GetLongOption() const {
diff --git a/src/util/OptionParser.cxx b/src/util/OptionParser.cxx
index b48873777..72fb05f7f 100644
--- a/src/util/OptionParser.cxx
+++ b/src/util/OptionParser.cxx
@@ -20,25 +20,56 @@
 #include "OptionParser.hxx"
 #include "OptionDef.hxx"
 #include "util/RuntimeError.hxx"
+#include "util/StringCompare.hxx"
 
 #include <string.h>
 
+inline const char *
+OptionParser::CheckShiftValue(const char *s, const OptionDef &option)
+{
+	if (!option.HasValue())
+		return nullptr;
+
+	if (args.empty())
+		throw FormatRuntimeError("Value expected after %s", s);
+
+	return args.shift();
+}
+
 inline OptionParser::Result
-OptionParser::IdentifyOption(const char *s) const
+OptionParser::IdentifyOption(const char *s)
 {
 	assert(s != nullptr);
 	assert(*s == '-');
 
 	if (s[1] == '-') {
-		for (const auto &i : options)
-			if (i.HasLongOption() &&
-			    strcmp(s + 2, i.GetLongOption()) == 0)
-				return {int(&i - options.data)};
+		for (const auto &i : options) {
+			if (!i.HasLongOption())
+				continue;
+
+			const char *t = StringAfterPrefix(s + 2, i.GetLongOption());
+			if (t == nullptr)
+				continue;
+
+			const char *value;
+
+			if (*t == 0)
+				value = CheckShiftValue(s, i);
+			else if (*t == '=')
+				value = t + 1;
+			else
+				continue;
+
+			return {int(&i - options.data), value};
+		}
 	} else if (s[1] != 0 && s[2] == 0) {
 		const char ch = s[1];
-		for (const auto &i : options)
-			if (i.HasShortOption() && ch == i.GetShortOption())
-				return {int(&i - options.data)};
+		for (const auto &i : options) {
+			if (i.HasShortOption() && ch == i.GetShortOption()) {
+				const char *value = CheckShiftValue(s, i);
+				return {int(&i - options.data), value};
+			}
+		}
 	}
 
 	throw FormatRuntimeError("Unknown option: %s", s);
@@ -55,5 +86,5 @@ OptionParser::Next()
 		*remaining_tail++ = arg;
 	}
 
-	return {-1};
+	return {-1, nullptr};
 }
diff --git a/src/util/OptionParser.hxx b/src/util/OptionParser.hxx
index a7176a4c3..a6a95a325 100644
--- a/src/util/OptionParser.hxx
+++ b/src/util/OptionParser.hxx
@@ -47,6 +47,7 @@ public:
 
 	struct Result {
 		int index;
+		const char *value;
 
 		constexpr operator bool() noexcept {
 			return index >= 0;
@@ -70,7 +71,8 @@ public:
 	}
 
 private:
-	Result IdentifyOption(const char *s) const;
+	const char *CheckShiftValue(const char *s, const OptionDef &option);
+	Result IdentifyOption(const char *s);
 };
 
 #endif