• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #856

28 Dec 2022 02:00AM UTC coverage: 86.602% (+0.05%) from 86.55%
#856

push

StellarBot
Merge #6119

6119: Update CMakeLists.txt r=hkaiser a=khuck

updating the default APEX version


Co-authored-by: Kevin Huck <khuck@cs.uoregon.edu>

174566 of 201573 relevant lines covered (86.6%)

1876093.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.98
/libs/core/program_options/src/cmdline.cpp
1
// Copyright Vladimir Prus 2002-2004.
2
//  SPDX-License-Identifier: BSL-1.0
3
// Distributed under the Boost Software License, Version 1.0.
4
// (See accompanying file LICENSE_1_0.txt
5
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#include <hpx/program_options/config.hpp>
8
#include <hpx/assert.hpp>
9
#include <hpx/program_options/detail/cmdline.hpp>
10
#include <hpx/program_options/errors.hpp>
11
#include <hpx/program_options/options_description.hpp>
12
#include <hpx/program_options/positional_options.hpp>
13
#include <hpx/program_options/value_semantic.hpp>
14

15
#include <cctype>
16
#include <climits>
17
#include <cstddef>
18
#include <cstdio>
19
#include <cstring>
20
#include <functional>
21
#include <string>
22
#include <utility>
23
#include <vector>
24

25
namespace hpx::program_options {
26

27
    using namespace hpx::program_options::command_line_style;
28

29
    std::string invalid_syntax::get_template(kind_t kind)
13✔
30
    {
31
        // Initially, store the message in 'const char*' variable,
32
        // to avoid conversion to string in all cases.
33
        char const* msg;
34
        switch (kind)
13✔
35
        {
36
        case empty_adjacent_parameter:
37
            msg = "the argument for option '%canonical_option%' should follow "
1✔
38
                  "immediately after the equal sign";
39
            break;
1✔
40
        case missing_parameter:
41
            msg = "the required argument for option '%canonical_option%' is "
8✔
42
                  "missing";
43
            break;
8✔
44
        case unrecognized_line:
45
            msg = "the options configuration file contains an invalid line "
×
46
                  "'%invalid_line%'";
47
            break;
×
48
        // none of the following are currently used:
49
        case long_not_allowed:
50
            msg = "the unabbreviated option '%canonical_option%' is not valid";
×
51
            break;
×
52
        case long_adjacent_not_allowed:
53
            msg = "the unabbreviated option '%canonical_option%' does not take "
×
54
                  "any arguments";
55
            break;
×
56
        case short_adjacent_not_allowed:
57
            msg = "the abbreviated option '%canonical_option%' does not take "
×
58
                  "any arguments";
59
            break;
×
60
        case extra_parameter:
61
            msg = "option '%canonical_option%' does not take any arguments";
4✔
62
            break;
4✔
63
        default:
64
            msg = "unknown command line syntax error for '%s'";
×
65
        }
×
66
        return msg;
13✔
67
    }
×
68
}    // namespace hpx::program_options
69

70
namespace hpx::program_options::detail {
71

72
    cmdline::cmdline(std::vector<std::string> const& args)
4,390✔
73
    {
74
        init(args);
4,390✔
75
    }
4,390✔
76

77
    cmdline::cmdline(int argc, char const* const* argv)
×
78
    {
79
        init(std::vector<std::string>(argv + 1,
×
80
            argv + static_cast<std::size_t>(argc) +
×
81
                static_cast<std::size_t>(!argc)));
×
82
    }
×
83

84
    void cmdline::init(std::vector<std::string> const& args)
4,390✔
85
    {
86
        this->m_args = args;
4,390✔
87
        m_style = command_line_style::default_style;
4,390✔
88
        m_desc = nullptr;
4,390✔
89
        m_positional = nullptr;
4,390✔
90
        m_allow_unregistered = false;
4,390✔
91
    }
4,390✔
92

93
    void cmdline::style(int style) noexcept
4,341✔
94
    {
95
        if (style == 0)
4,341✔
96
            style = default_style;
17✔
97

98
        check_style(style);
4,341✔
99
        this->m_style = style_t(style);
4,341✔
100
    }
4,341✔
101

102
    void cmdline::allow_unregistered() noexcept
4,273✔
103
    {
104
        this->m_allow_unregistered = true;
4,273✔
105
    }
4,273✔
106

107
    void cmdline::check_style(int style) const
4,341✔
108
    {
109
        bool allow_some_long =
4,341✔
110
            (style & allow_long) || (style & allow_long_disguise);
4,341✔
111

112
        char const* error = nullptr;
4,341✔
113
        if (allow_some_long && !(style & long_allow_adjacent) &&
4,341✔
114
            !(style & long_allow_next))
3✔
115
        {
116
            error =
×
117
                "hpx::program_options misconfiguration: choose one or other of "
118
                "'command_line_style::long_allow_next' (whitespace separated "
119
                "arguments) or 'command_line_style::long_allow_adjacent' ('=' "
120
                "separated arguments) for long options.";
121
        }
×
122

123
        if (!error && (style & allow_short) &&
4,346✔
124
            !(style & short_allow_adjacent) && !(style & short_allow_next))
4,321✔
125
        {
126
            error =
×
127
                "hpx::program_options misconfiguration: choose one or other of "
128
                "'command_line_style::short_allow_next' (whitespace separated "
129
                "arguments) or 'command_line_style::short_allow_adjacent' ('=' "
130
                "separated arguments) for short options.";
131
        }
×
132

133
        if (!error && (style & allow_short) &&
4,348✔
134
            !(style & allow_dash_for_short) && !(style & allow_slash_for_short))
4,321✔
135
        {
136
            error =
×
137
                "hpx::program_options misconfiguration: choose one or other of "
138
                "'command_line_style::allow_slash_for_short' (slashes) or "
139
                "'command_line_style::allow_dash_for_short' (dashes) for short "
140
                "options.";
141
        }
×
142

143
        if (error)
4,341✔
144
            throw invalid_command_line_style(error);
×
145

146
        // Need to check that if guessing and long disguise are enabled -f will
147
        // mean the same as -foo
148
    }
4,341✔
149

150
    bool cmdline::is_style_active(style_t style) const noexcept
94,545✔
151
    {
152
        return ((m_style & style) ? true : false);
94,545✔
153
    }
154

155
    void cmdline::set_options_description(
4,390✔
156
        options_description const& desc) noexcept
157
    {
158
        m_desc = &desc;
4,390✔
159
    }
4,390✔
160

161
    void cmdline::set_positional_options(
3,450✔
162
        positional_options_description const& positional) noexcept
163
    {
164
        m_positional = &positional;
3,450✔
165
    }
3,450✔
166

167
    int cmdline::get_canonical_option_prefix() noexcept
4,352✔
168
    {
169
        if (m_style & allow_long)
4,352✔
170
            return allow_long;
4,344✔
171

172
        if (m_style & allow_long_disguise)
8✔
173
            return allow_long_disguise;
×
174

175
        if ((m_style & allow_short) && (m_style & allow_dash_for_short))
8✔
176
            return allow_dash_for_short;
5✔
177

178
        if ((m_style & allow_short) && (m_style & allow_slash_for_short))
3✔
179
            return allow_slash_for_short;
3✔
180

181
        return 0;
×
182
    }
4,352✔
183

184
    std::vector<option> cmdline::run()
4,390✔
185
    {
186
        // The parsing is done by having a set of 'style parsers' and trying
187
        // then in order. Each parser is passed a vector of unparsed tokens and
188
        // can consume some of them (by removing elements on front) and return a
189
        // vector of options.
190
        //
191
        // We try each style parser in turn, until some input is consumed. The
192
        // returned vector of option may contain the result of just syntactic
193
        // parsing of token, say --foo will be parsed as option with name 'foo',
194
        // and the style parser is not required to care if that option is
195
        // defined, and how many tokens the value may take. So, after vector is
196
        // returned, we validate them.
197
        HPX_ASSERT(m_desc);
4,390✔
198

199
        std::vector<style_parser> style_parsers;
4,390✔
200

201
        if (m_style_parser)
4,390✔
202
            style_parsers.push_back(m_style_parser);
1✔
203

204
        if (m_additional_parser)
4,390✔
205
            style_parsers.emplace_back(
4,268✔
206
                std::bind(&cmdline::handle_additional_parser, this,
4,268✔
207
                    std::placeholders::_1));
208

209
        if (m_style & allow_long)
4,390✔
210
            style_parsers.emplace_back(std::bind(
4,359✔
211
                &cmdline::parse_long_option, this, std::placeholders::_1));
4,359✔
212

213
        if ((m_style & allow_long_disguise))
4,390✔
214
            style_parsers.emplace_back(
13✔
215
                std::bind(&cmdline::parse_disguised_long_option, this,
13✔
216
                    std::placeholders::_1));
217

218
        if ((m_style & allow_short) && (m_style & allow_dash_for_short))
4,390✔
219
            style_parsers.emplace_back(std::bind(
4,363✔
220
                &cmdline::parse_short_option, this, std::placeholders::_1));
4,363✔
221

222
        if ((m_style & allow_short) && (m_style & allow_slash_for_short))
4,390✔
223
            style_parsers.emplace_back(std::bind(
9✔
224
                &cmdline::parse_dos_option, this, std::placeholders::_1));
9✔
225

226
        style_parsers.emplace_back(
4,390✔
227
            std::bind(&cmdline::parse_terminator, this, std::placeholders::_1));
4,390✔
228

229
        std::vector<option> result;
4,390✔
230
        std::vector<std::string>& args = m_args;
4,390✔
231
        while (!args.empty())
19,533✔
232
        {
233
            bool ok = false;
15,173✔
234
            for (std::size_t i = 0; i < style_parsers.size(); ++i)
35,967✔
235
            {
236
                std::size_t current_size = args.size();
34,026✔
237
                std::vector<option> next = style_parsers[i](args);
34,026✔
238

239
                // Check that option names
240
                // are valid, and that all values are in place.
241
                if (!next.empty())
34,024✔
242
                {
243
                    std::vector<std::string> e;
13,230✔
244
                    for (std::size_t k = 0; k < next.size() - 1; ++k)
13,234✔
245
                    {
246
                        finish_option(next[k], e, style_parsers);
4✔
247
                    }
4✔
248
                    // For the last option, pass the unparsed tokens
249
                    // so that they can be added to next.back()'s values
250
                    // if appropriate.
251
                    finish_option(next.back(), args, style_parsers);
13,230✔
252
                    for (auto const& j : next)
26,408✔
253
                        result.push_back(j);
13,206✔
254
                }
13,230✔
255

256
                if (args.size() != current_size)
33,996✔
257
                {
258
                    ok = true;
13,202✔
259
                    break;
13,202✔
260
                }
261
            }
34,024✔
262

263
            if (!ok)
15,143✔
264
            {
265
                option opt;
1,941✔
266
                opt.value.push_back(args[0]);
1,941✔
267
                opt.original_tokens.push_back(args[0]);
1,941✔
268
                result.push_back(opt);
1,941✔
269
                args.erase(args.begin());
1,941✔
270
            }
1,941✔
271
        }
272

273
        /* If an key option is followed by a positional option,
274
           can can consume more tokens (e.g. it's multitoken option),
275
           give those tokens to it.  */
276
        std::vector<option> result2;
4,360✔
277
        for (std::size_t i = 0; i < result.size(); ++i)
19,495✔
278
        {
279
            result2.push_back(result[i]);
15,135✔
280
            option& opt = result2.back();
15,135✔
281

282
            if (opt.string_key.empty())
15,135✔
283
                continue;
1,936✔
284

285
            option_description const* xd = nullptr;
13,199✔
286
            try
287
            {
288
                xd = m_desc->find_nothrow(opt.string_key,
26,398✔
289
                    is_style_active(allow_guessing),
13,199✔
290
                    is_style_active(long_case_insensitive),
13,199✔
291
                    is_style_active(short_case_insensitive));
13,199✔
292
            }
13,199✔
293
            catch (error_with_option_name& e)
294
            {
295
                // add context and rethrow
296
                e.add_context(opt.string_key, opt.original_tokens[0],
×
297
                    get_canonical_option_prefix());
×
298
                throw;
×
299
            }
×
300

301
            if (!xd)
13,199✔
302
                continue;
624✔
303

304
            std::size_t min_tokens = xd->semantic()->min_tokens();
12,575✔
305
            std::size_t max_tokens = xd->semantic()->max_tokens();
12,575✔
306
            if (min_tokens < max_tokens && opt.value.size() < max_tokens)
12,575✔
307
            {
308
                // This option may grab some more tokens.
309
                // We only allow to grab tokens that are not already
310
                // recognized as key options.
311

312
                std::size_t can_take_more = max_tokens - opt.value.size();
19✔
313
                std::size_t j = i + 1;
19✔
314
                for (; can_take_more && j < result.size(); --can_take_more, ++j)
26✔
315
                {
316
                    option& opt2 = result[j];
20✔
317
                    if (!opt2.string_key.empty())
20✔
318
                        break;
12✔
319

320
                    if (opt2.position_key == INT_MAX)
8✔
321
                    {
322
                        // We use INT_MAX to mark positional options that
323
                        // were found after the '--' terminator and therefore
324
                        // should stay positional forever.
325
                        break;
1✔
326
                    }
327

328
                    HPX_ASSERT(opt2.value.size() == 1);
7✔
329

330
                    opt.value.push_back(opt2.value[0]);
7✔
331

332
                    HPX_ASSERT(opt2.original_tokens.size() == 1);
7✔
333

334
                    opt.original_tokens.push_back(opt2.original_tokens[0]);
7✔
335
                }
7✔
336
                i = j - 1;
19✔
337
            }
19✔
338
        }
12,575✔
339
        result.swap(result2);
4,360✔
340

341
        // Assign position keys to positional options.
342
        int position_key = 0;
4,360✔
343
        for (auto& i : result)
19,495✔
344
        {
345
            if (i.string_key.empty())
15,135✔
346
                i.position_key = position_key++;
1,936✔
347
        }
348

349
        if (m_positional)
4,360✔
350
        {
351
            unsigned position = 0;
3,450✔
352
            for (option& opt : result)
14,391✔
353
            {
354
                if (opt.position_key != -1)
10,942✔
355
                {
356
                    if (position >= m_positional->max_total_count())
1,488✔
357
                    {
358
                        throw too_many_positional_options_error();
1✔
359
                    }
360
                    opt.string_key = m_positional->name_for_position(position);
1,487✔
361
                    ++position;
1,487✔
362
                }
1,487✔
363
            }
364
        }
3,449✔
365

366
        // set case sensitive flag
367
        for (auto& i : result)
19,488✔
368
        {
369
            if (i.string_key.size() > 2 ||
15,170✔
370
                (i.string_key.size() > 1 && i.string_key[0] != '-'))
489✔
371
            {
372
                // it is a long option
373
                i.case_insensitive = is_style_active(long_case_insensitive);
14,640✔
374
            }
14,640✔
375
            else
376
            {
377
                // it is a short option
378
                i.case_insensitive = is_style_active(short_case_insensitive);
489✔
379
            }
380
        }
381

382
        return result;
4,359✔
383
    }
4,390✔
384

385
    void cmdline::finish_option(option& opt,
13,234✔
386
        std::vector<std::string>& other_tokens,
387
        std::vector<style_parser> const& style_parsers)
388
    {
389
        if (opt.string_key.empty())
13,234✔
390
            return;
3✔
391

392
        //
393
        // Be defensive:
394
        // will have no original token if option created by handle_additional_parser()
395
        std::string original_token_for_exceptions = opt.string_key;
13,231✔
396
        if (!opt.original_tokens.empty())
13,231✔
397
            original_token_for_exceptions = opt.original_tokens[0];
13,219✔
398

399
        try
400
        {
401
            // First check that the option is valid, and get its description.
402
            option_description const* xd = m_desc->find_nothrow(opt.string_key,
26,462✔
403
                is_style_active(allow_guessing),
13,231✔
404
                is_style_active(long_case_insensitive),
13,231✔
405
                is_style_active(short_case_insensitive));
13,231✔
406

407
            if (!xd)
13,225✔
408
            {
409
                if (m_allow_unregistered)
634✔
410
                {
411
                    opt.unregistered = true;
624✔
412
                    return;
624✔
413
                }
414
                else
415
                {
416
                    throw unknown_option();
10✔
417
                }
418
            }
419
            option_description const& d = *xd;
12,591✔
420

421
            // Canonize the name
422
            opt.string_key = d.key(opt.string_key);
12,591✔
423

424
            // We check that the min/max number of tokens for the option
425
            // agrees with the number of tokens we have. The 'adjacent_value'
426
            // (the value in --foo=1) counts as a separate token, and if present
427
            // must be consumed. The following tokens on the command line may be
428
            // left unconsumed.
429
            unsigned min_tokens = d.semantic()->min_tokens();
12,591✔
430
            unsigned max_tokens = d.semantic()->max_tokens();
12,591✔
431

432
            std::size_t present_tokens = opt.value.size() + other_tokens.size();
12,591✔
433

434
            if (present_tokens >= min_tokens)
12,591✔
435
            {
436
                if (!opt.value.empty() && max_tokens == 0)
12,586✔
437
                {
438
                    throw invalid_command_line_syntax(
4✔
439
                        invalid_command_line_syntax::extra_parameter);
440
                }
441

442
                // Grab min_tokens values from other_tokens, but only if those tokens
443
                // are not recognized as options themselves.
444
                if (opt.value.size() <= min_tokens)
12,582✔
445
                {
446
                    min_tokens -= static_cast<unsigned>(opt.value.size());
8,390✔
447
                }
8,390✔
448
                else
449
                {
450
                    min_tokens = 0;
4,192✔
451
                }
452

453
                // Everything is OK, move the values to the result.
454
                for (; !other_tokens.empty() && min_tokens--;)
12,639✔
455
                {
456
                    // check if extra parameter looks like a known option
457
                    // we use style parsers to check if it is syntactically an option,
458
                    // additionally we check if an option_description exists
459
                    std::vector<option> followed_option;
60✔
460
                    std::vector<std::string> next_token(1, other_tokens[0]);
60✔
461
                    for (std::size_t i = 0;
474✔
462
                         followed_option.empty() && i < style_parsers.size();
237✔
463
                         ++i)
177✔
464
                    {
465
                        followed_option = style_parsers[i](next_token);
177✔
466
                    }
177✔
467
                    if (!followed_option.empty())
60✔
468
                    {
469
                        original_token_for_exceptions = other_tokens[0];
5✔
470
                        option_description const* od = m_desc->find_nothrow(
10✔
471
                            other_tokens[0], is_style_active(allow_guessing),
5✔
472
                            is_style_active(long_case_insensitive),
5✔
473
                            is_style_active(short_case_insensitive));
5✔
474
                        if (od)
5✔
475
                            throw invalid_command_line_syntax(
3✔
476
                                invalid_command_line_syntax::missing_parameter);
477
                    }
2✔
478
                    opt.value.push_back(other_tokens[0]);
57✔
479
                    opt.original_tokens.push_back(other_tokens[0]);
57✔
480
                    other_tokens.erase(other_tokens.begin());
57✔
481
                }
60✔
482
            }
12,579✔
483
            else
484
            {
485
                throw invalid_command_line_syntax(
5✔
486
                    invalid_command_line_syntax::missing_parameter);
487
            }
488
        }
12,607✔
489
        // use only original token for unknown_option / ambiguous_option since
490
        // by definition
491
        //    they are unrecognised / unparsable
492
        catch (error_with_option_name& e)
493
        {
494
            // add context and rethrow
495
            e.add_context(opt.string_key, original_token_for_exceptions,
56✔
496
                get_canonical_option_prefix());
28✔
497
            throw;
28✔
498
        }
28✔
499
    }
13,290✔
500

501
    std::vector<option> cmdline::parse_long_option(
15,180✔
502
        std::vector<std::string>& args)
503
    {
504
        std::vector<option> result;
15,180✔
505
        std::string const& tok = args[0];
15,180✔
506
        if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-')
15,180✔
507
        {
508
            std::string name, adjacent;
13,142✔
509

510
            std::string::size_type p = tok.find('=');
13,142✔
511
            if (p != tok.npos)
13,142✔
512
            {
513
                name = tok.substr(2, p - 2);
13,034✔
514
                adjacent = tok.substr(p + 1);
13,034✔
515
                if (adjacent.empty())
13,034✔
516
                    throw invalid_command_line_syntax(
2✔
517
                        invalid_command_line_syntax::empty_adjacent_parameter,
518
                        name, name, get_canonical_option_prefix());
1✔
519
            }
13,033✔
520
            else
521
            {
522
                name = tok.substr(2);
108✔
523
            }
524
            option opt;
13,141✔
525
            opt.string_key = HPX_MOVE(name);
13,141✔
526
            if (!adjacent.empty())
13,141✔
527
                opt.value.push_back(adjacent);
13,033✔
528
            opt.original_tokens.push_back(tok);
13,141✔
529
            result.push_back(opt);
13,141✔
530
            args.erase(args.begin());
13,141✔
531
        }
13,142✔
532
        return result;
15,179✔
533
    }
15,180✔
534

535
    std::vector<option> cmdline::parse_short_option(
2,068✔
536
        std::vector<std::string>& args)
537
    {
538
        std::string const& tok = args[0];
2,068✔
539
        if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-')
2,068✔
540
        {
541
            std::vector<option> result;
78✔
542

543
            std::string name = tok.substr(0, 2);
78✔
544
            std::string adjacent = tok.substr(2);
78✔
545

546
            // Short options can be 'grouped', so that
547
            // "-d -a" becomes "-da". Loop, processing one
548
            // option at a time. We exit the loop when either
549
            // we've processed all the token, or when the remainder
550
            // of token is considered to be value, not further grouped
551
            // option.
552
            for (;;)
81✔
553
            {
554
                option_description const* d;
555
                try
556
                {
557
                    d = m_desc->find_nothrow(name, false, false,
162✔
558
                        is_style_active(short_case_insensitive));
81✔
559
                }
81✔
560
                catch (error_with_option_name& e)
561
                {
562
                    // add context and rethrow
563
                    e.add_context(name, name, get_canonical_option_prefix());
1✔
564
                    throw;
1✔
565
                }
1✔
566

567
                // FIXME: check for 'allow_sticky'.
568
                if (d && (m_style & allow_sticky) &&
117✔
569
                    d->semantic()->max_tokens() == 0 && !adjacent.empty())
37✔
570
                {
571
                    // 'adjacent' is in fact further option.
572
                    option opt;
3✔
573
                    opt.string_key = name;
3✔
574
                    result.push_back(opt);
3✔
575

576
                    if (adjacent.empty())
3✔
577
                    {
578
                        args.erase(args.begin());
×
579
                        break;
×
580
                    }
581

582
                    name = std::string("-") + adjacent[0];
3✔
583
                    adjacent.erase(adjacent.begin());
3✔
584
                }
3✔
585
                else
586
                {
587
                    option opt;
77✔
588
                    opt.string_key = name;
77✔
589
                    opt.original_tokens.push_back(tok);
77✔
590
                    if (!adjacent.empty())
77✔
591
                        opt.value.push_back(adjacent);
41✔
592
                    result.push_back(opt);
77✔
593
                    args.erase(args.begin());
77✔
594
                    break;
595
                }
77✔
596
            }
597
            return result;
77✔
598
        }
78✔
599
        return std::vector<option>();
1,990✔
600
    }
2,069✔
601

602
    std::vector<option> cmdline::parse_dos_option(
9✔
603
        std::vector<std::string>& args)
604
    {
605
        std::vector<option> result;
9✔
606
        std::string const& tok = args[0];
9✔
607
        if (tok.size() >= 2 && tok[0] == '/')
9✔
608
        {
609
            std::string name = "-" + tok.substr(1, 1);
6✔
610
            std::string adjacent = tok.substr(2);
6✔
611

612
            option opt;
6✔
613
            opt.string_key = HPX_MOVE(name);
6✔
614
            if (!adjacent.empty())
6✔
615
                opt.value.push_back(adjacent);
4✔
616
            opt.original_tokens.push_back(tok);
6✔
617
            result.push_back(opt);
6✔
618
            args.erase(args.begin());
6✔
619
        }
6✔
620
        return result;
9✔
621
    }
9✔
622

623
    std::vector<option> cmdline::parse_disguised_long_option(
13✔
624
        std::vector<std::string>& args)
625
    {
626
        std::string const& tok = args[0];
13✔
627
        if (tok.size() >= 2 &&
15✔
628
            ((tok[0] == '-' && tok[1] != '-') ||
13✔
629
                ((m_style & allow_slash_for_short) && tok[0] == '/')))
5✔
630
        {
631
            try
632
            {
633
                if (m_desc->find_nothrow(tok.substr(1, tok.find('=') - 1),
10✔
634
                        is_style_active(allow_guessing),
10✔
635
                        is_style_active(long_case_insensitive),
10✔
636
                        is_style_active(short_case_insensitive)))
10✔
637
                {
638
                    args[0].insert(0, "-");
5✔
639
                    if (args[0][1] == '/')
5✔
640
                        args[0][1] = '-';
2✔
641
                    return parse_long_option(args);
5✔
642
                }
643
            }
5✔
644
            catch (error_with_option_name& e)
645
            {
646
                // add context and rethrow
647
                e.add_context(tok, tok, get_canonical_option_prefix());
×
648
                throw;
×
649
            }
×
650
        }
5✔
651
        return std::vector<option>();
8✔
652
    }
13✔
653

654
    std::vector<option> cmdline::parse_terminator(
1,999✔
655
        std::vector<std::string>& args)
656
    {
657
        std::vector<option> result;
1,999✔
658
        std::string const& tok = args[0];
1,999✔
659
        if (tok == "--")
1,999✔
660
        {
661
            for (std::size_t i = 1; i < args.size(); ++i)
6✔
662
            {
663
                option opt;
3✔
664
                opt.value.push_back(args[i]);
3✔
665
                opt.original_tokens.push_back(args[i]);
3✔
666
                opt.position_key = INT_MAX;
3✔
667
                result.push_back(opt);
3✔
668
            }
3✔
669
            args.clear();
3✔
670
        }
3✔
671
        return result;
1,999✔
672
    }
1,999✔
673

674
    std::vector<option> cmdline::handle_additional_parser(
14,938✔
675
        std::vector<std::string>& args)
676
    {
677
        std::vector<option> result;
14,938✔
678
        std::pair<std::string, std::string> r = m_additional_parser(args[0]);
14,938✔
679
        if (!r.first.empty())
14,938✔
680
        {
681
            option next;
7✔
682
            next.string_key = r.first;
7✔
683
            if (!r.second.empty())
7✔
684
                next.value.push_back(r.second);
7✔
685
            result.push_back(next);
7✔
686
            args.erase(args.begin());
7✔
687
        }
7✔
688
        return result;
14,938✔
689
    }
14,938✔
690

691
    void cmdline::set_additional_parser(additional_parser p) noexcept
4,281✔
692
    {
693
        m_additional_parser = p;
4,281✔
694
    }
4,281✔
695

696
    void cmdline::extra_style_parser(style_parser s) noexcept
1✔
697
    {
698
        m_style_parser = s;
1✔
699
    }
1✔
700
}    // namespace hpx::program_options::detail
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc