We can generate the getopt(3) optstring off the Getopt::Long
option spec array to reduce maintenance overhead.
---
 lib/PublicInbox/Search.pm       | 15 +++++++++++++++
 lib/PublicInbox/XapHelper.pm    | 18 ++----------------
 lib/PublicInbox/XapHelperCxx.pm |  4 +++-
 lib/PublicInbox/xap_helper.h    |  5 +++--
 4 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/lib/PublicInbox/Search.pm b/lib/PublicInbox/Search.pm
index 2e784646..529c0aa4 100644
--- a/lib/PublicInbox/Search.pm
+++ b/lib/PublicInbox/Search.pm
@@ -12,6 +12,21 @@ use List::Util qw(max);
 use POSIX qw(strftime);
 use Carp ();
 
+# only short options for portability in C++ implementation
+our @XH_OPTSPEC = ( # transformed to getopt(3) optstring
+       'a', # ascending sort
+       'c', # code search
+       'd=s@', # shard dirs
+       'k=i', # sort column (like sort(1))
+       'm=i', # maximum number of results
+       'o=i', # offset
+       'r', # 1=relevance then column
+       't', # collapse threads
+       'A=s@', # prefixes
+       'O=s', # eidx_key
+       'T=i', # timeout in seconds
+);
+
 # values for searching, changing the numeric value breaks
 # compatibility with old indices (so don't change them it)
 use constant {
diff --git a/lib/PublicInbox/XapHelper.pm b/lib/PublicInbox/XapHelper.pm
index ef6a47a3..4f157784 100644
--- a/lib/PublicInbox/XapHelper.pm
+++ b/lib/PublicInbox/XapHelper.pm
@@ -15,21 +15,6 @@ my $X = \%PublicInbox::Search::X;
 our (%SRCH, %PIDS, $parent_pid);
 our $stderr = \*STDERR;
 
-# only short options for portability in C++ implementation
-our @SPEC = (
-       'a', # ascending sort
-       'c', # code search
-       'd=s@', # shard dirs
-       'k=i', # sort column (like sort(1))
-       'm=i', # maximum number of results
-       'o=i', # offset
-       'r', # 1=relevance then column
-       't', # collapse threads
-       'A=s@', # prefixes
-       'O=s', # eidx_key
-       'T=i', # timeout in seconds
-);
-
 sub cmd_test_inspect {
        my ($req) = @_;
        print { $req->{0} } "pid=$$ has_threadid=",
@@ -139,7 +124,8 @@ sub cmd_dump_roots {
 sub dispatch {
        my ($req, $cmd, @argv) = @_;
        my $fn = $req->can("cmd_$cmd") or return;
-       $GLP->getoptionsfromarray(\@argv, $req, @SPEC) or return;
+       $GLP->getoptionsfromarray(\@argv, $req,
+                               @PublicInbox::Search::XH_OPTSPEC) or return;
        my $dirs = delete $req->{d} or return warn 'no -d args';
        my $key = join("\0", @$dirs);
        $req->{srch} = $SRCH{$key} //= do {
diff --git a/lib/PublicInbox/XapHelperCxx.pm b/lib/PublicInbox/XapHelperCxx.pm
index 4571676b..bc68c1d2 100644
--- a/lib/PublicInbox/XapHelperCxx.pm
+++ b/lib/PublicInbox/XapHelperCxx.pm
@@ -17,7 +17,9 @@ my @srcs = map { $srcpfx.$_ } qw(xap_helper.h);
 my @pm_dep = map { $srcpfx.$_ } qw(Search.pm CodeSearch.pm);
 my $xflags = ($ENV{CXXFLAGS} // '-Wall -ggdb3 -O0') . ' ' .
        ($ENV{LDFLAGS} // '-Wl,-O1 -Wl,--compress-debug-sections=zlib') .
-       qq{ -DTHREADID=}.PublicInbox::Search::THREADID;
+       qq{ -DTHREADID=}.PublicInbox::Search::THREADID . q{ -DXH_OPTSTRING='"}.
+       join('', map { s/[=:].*\z/:/; $_ } @PublicInbox::Search::XH_OPTSPEC) .
+       q{"'};
 
 sub xflags_chg () {
        open my $fh, '<', "$dir/XFLAGS" or return 1;
diff --git a/lib/PublicInbox/xap_helper.h b/lib/PublicInbox/xap_helper.h
index e10527d1..25b82e57 100644
--- a/lib/PublicInbox/xap_helper.h
+++ b/lib/PublicInbox/xap_helper.h
@@ -736,8 +736,9 @@ static void dispatch(struct req *req)
        opterr = optopt = 0;
        optarg = NULL;
 
-       // keep sync with @PublicInbox::XapHelper::SPEC
-       while ((c = getopt(req->argc, req->argv, "acd:k:m:o:rtA:O:T:")) != -1) {
+       // XH_OPTSTRING is generated in XapHelperCxx.pm off of
+       // @PublicInbox::Search::XH_OPTSPEC
+       while ((c = getopt(req->argc, req->argv, XH_OPTSTRING)) != -1) {
                switch (c) {
                case 'a': req->asc = true; break;
                case 'c': req->code_search = true; break;

Reply via email to