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

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

82.28
/libs/core/command_line_handling_local/src/parse_command_line_local.cpp
1
//  Copyright (c) 2007-2023 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#include <hpx/command_line_handling_local/config/defines.hpp>
8
#include <hpx/command_line_handling_local/parse_command_line_local.hpp>
9
#if defined(HPX_COMMAND_LINE_HANDLING_HAVE_JSON_CONFIGURATION_FILES)
10
#include <hpx/command_line_handling_local/json_config_file.hpp>
11
#endif
12
#include <hpx/modules/datastructures.hpp>
13
#include <hpx/modules/errors.hpp>
14
#include <hpx/modules/filesystem.hpp>
15
#include <hpx/modules/ini.hpp>
16

17
#include <cstddef>
18
#include <fstream>
19
#include <iostream>
20
#include <string>
21
#include <utility>
22
#include <vector>
23

24
#if defined(HPX_HAVE_UNISTD_H)
25
#include <unistd.h>
26
#endif
27

28
///////////////////////////////////////////////////////////////////////////////
29
namespace hpx::local::detail {
30

31
    ///////////////////////////////////////////////////////////////////////
32
    std::string trim_whitespace(std::string const& s)
491✔
33
    {
34
        using size_type = std::string::size_type;
35

36
        size_type const first = s.find_first_not_of(" \t");
37
        if (std::string::npos == first)
491✔
38
            return {};
39

40
        size_type const last = s.find_last_not_of(" \t");
41
        return s.substr(first, last - first + 1);
271✔
42
    }
43

44
    ///////////////////////////////////////////////////////////////////////
45
    // Handle aliasing of command line options based on information stored
46
    // in the ini-configuration
47
    std::pair<std::string, std::string> handle_aliasing(
269✔
48
        util::section const& ini, std::string const& option)
49
    {
50
        std::pair<std::string, std::string> result;
51

52
        std::string opt(trim_whitespace(option));
269✔
53
        if (opt.size() < 2 || opt[0] != '-')
269✔
54
            return result;
55

56
        util::section const* sec = ini.get_section("hpx.commandline.aliases");
222✔
57
        if (nullptr == sec)
222✔
58
            return result;    // no alias mappings are defined
59

60
        // we found shortcut option definitions, try to find mapping
61
        std::string expand_to;
62
        std::string::size_type start_at = 2;
63
        bool long_option = false;
64
        if (opt.size() > 2 && opt[1] != '-')
222✔
65
        {
66
            // short option with value: first two letters have to match
67
            expand_to =
68
                trim_whitespace(sec->get_entry(opt.substr(0, start_at), ""));
4✔
69
        }
70
        else
71
        {
72
            // short option (no value) or long option
73
            if (opt[1] == '-')
220✔
74
            {
75
                start_at = opt.find_last_of('=');
76
                long_option = true;
77
            }
78

79
            if (start_at != std::string::npos)
220✔
80
            {
81
                expand_to = trim_whitespace(
220✔
82
                    sec->get_entry(opt.substr(0, start_at), ""));
660✔
83
            }
84
            else
85
            {
86
                expand_to = trim_whitespace(sec->get_entry(opt, ""));
×
87
            }
88
        }
89

90
        if (expand_to.size() < 2 || expand_to.substr(0, 2) != "--")
226✔
91
            return result;    // no sensible alias is defined for this option
92
        expand_to.erase(0, 2);
2✔
93

94
        std::string::size_type p = expand_to.find_first_of('=');
95
        if (p != std::string::npos)
2✔
96
        {
97
            // the option alias defines its own value
98
            std::string o(trim_whitespace(expand_to.substr(0, p)));
×
99
            std::string v(trim_whitespace(expand_to.substr(p + 1)));
×
100
            result = std::make_pair(o, v);
×
101
        }
102
        else if (start_at != std::string::npos && start_at < opt.size())
2✔
103
        {
104
            // extract value from original option
105
            result = std::make_pair(
2✔
106
                expand_to, opt.substr(start_at + (long_option ? 1 : 0)));
6✔
107
        }
108
        else
109
        {
110
            // no value
111
            result = std::make_pair(expand_to, std::string());
×
112
        }
113

114
        return result;
115
    }
2✔
116

117
    ///////////////////////////////////////////////////////////////////////
118
    // Additional command line parser which interprets '@something' as an
119
    // option "options-file" with the value "something". Additionally we
120
    // resolve defined command line option aliases.
121
    option_parser::option_parser(
194✔
122
        util::section const& ini, bool ignore_aliases) noexcept
194✔
123
      : ini_(ini)
194✔
124
      , ignore_aliases_(ignore_aliases)
194✔
125
    {
126
    }
194✔
127

128
    std::pair<std::string, std::string> option_parser::operator()(
504✔
129
        std::string const& s) const
130
    {
131
        // handle special syntax for configuration files @filename
132
        if ('@' == s[0])
504✔
133
        {
134
            return std::make_pair(std::string("hpx:options-file"), s.substr(1));
×
135
        }
136

137
        // handle aliasing, if enabled
138
        if (ini_.get_entry("hpx.commandline.aliasing", "0") == "0" ||
1,008✔
139
            ignore_aliases_)
323✔
140
        {
141
            return std::make_pair(std::string(), std::string());
235✔
142
        }
143

144
        return handle_aliasing(ini_, s);
269✔
145
    }
146

147
    ///////////////////////////////////////////////////////////////////////
148
    hpx::program_options::basic_command_line_parser<char>&
149
    get_commandline_parser(
194✔
150
        hpx::program_options::basic_command_line_parser<char>& p,
151
        util::commandline_error_mode mode)
152
    {
153
        if (as_bool(mode & util::commandline_error_mode::allow_unregistered))
194✔
154
        {
155
            return p.allow_unregistered();
193✔
156
        }
157
        return p;
158
    }
159

160
    ///////////////////////////////////////////////////////////////////////
161
    // Read all options from a given config file
162
    std::vector<std::string> read_config_file_options(
1,746✔
163
        std::string const& filename, util::commandline_error_mode error_mode)
164
    {
165
#if defined(HPX_COMMAND_LINE_HANDLING_HAVE_JSON_CONFIGURATION_FILES)
166
        filesystem::path const cfgfile(filename);
167
        if (cfgfile.extension() == ".json")
168
        {
169
            return read_json_config_file_options(filename, error_mode);
170
        }
171
#endif
172

173
        std::vector<std::string> options;
1,746✔
174
        std::ifstream ifs(filename.c_str());
1,746✔
175
        if (!ifs.is_open())
1,746✔
176
        {
177
            if (as_bool(error_mode &
1,746✔
178
                    util::commandline_error_mode::report_missing_config_file))
179
            {
180
                std::cerr << "hpx::init: command line warning: command line "
181
                             "options file not found ("
182
                          << filename << ")" << std::endl;
183
            }
184
            return options;
185
        }
186

187
        std::string line;
188
        while (std::getline(ifs, line))
×
189
        {
190
            using hpx::local::detail::trim_whitespace;
191

192
            // skip empty lines
193
            std::string::size_type const pos = line.find_first_not_of(" \t");
194
            if (pos == std::string::npos)
×
195
                continue;
×
196

197
            // strip leading and trailing whitespace
198
            line = trim_whitespace(line);
×
199

200
            // skip comment lines
201
            if ('#' != line[0])
×
202
            {
203
                std::string::size_type const p1 = line.find_first_of(" \t");
204
                if (p1 != std::string::npos)
×
205
                {
206
                    // rebuild the line connecting the parts with a '='
207
                    line = trim_whitespace(line.substr(0, p1)) + '=' +
×
208
                        trim_whitespace(line.substr(p1));
×
209
                }
210
                options.push_back(line);
×
211
            }
212
        }
213

214
        return options;
215
    }
1,746✔
216

217
    ///////////////////////////////////////////////////////////////////////////
218
    // Handle all options from a given config file, parse and add them to the
219
    // given variables_map
220
    bool handle_config_file_options(std::vector<std::string> const& options,
873✔
221
        hpx::program_options::options_description const& desc,
222
        hpx::program_options::variables_map& vm, util::section const& rtcfg,
223
        util::commandline_error_mode error_mode)
224
    {
225
        // add options to parsed settings
226
        if (!options.empty())
873✔
227
        {
228
            using hpx::program_options::command_line_parser;
229
            using hpx::program_options::store;
230
            using hpx::program_options::command_line_style::unix_style;
231

232
            util::commandline_error_mode const mode =
233
                error_mode & util::commandline_error_mode::ignore_aliases;
234
            util::commandline_error_mode const notmode =
235
                error_mode & ~util::commandline_error_mode::ignore_aliases;
236

237
            store(get_commandline_parser(
×
238
                      command_line_parser(options)
×
239
                          .options(desc)
240
                          .style(unix_style)
241
                          .extra_parser(option_parser(rtcfg, as_bool(mode))),
×
242
                      notmode)
243
                      .run(),
×
244
                vm);
245
            notify(vm);
×
246
            return true;
×
247
        }
248
        return false;
249
    }
250

251
    // try to find a config file somewhere up the filesystem hierarchy starting
252
    // with the input file path. This allows to use a general <app_name>.cfg
253
    // file for all executables in a certain project.
254
    void handle_generic_config_options(std::string appname,
97✔
255
        hpx::program_options::variables_map& vm,
256
        hpx::program_options::options_description const& desc_cfgfile,
257
        util::section const& ini, util::commandline_error_mode error_mode)
258
    {
259
        if (appname.empty())
97✔
260
            return;
×
261

262
        filesystem::path dir(filesystem::initial_path());
97✔
263
        filesystem::path const app(appname);
97✔
264
        appname = filesystem::basename(app.filename());
194✔
265

266
        // walk up the hierarchy, trying to find a file <appname>.cfg
267
        while (!dir.empty())
873✔
268
        {
269
            filesystem::path filename = dir / (appname + ".cfg");
1,746✔
270
            util::commandline_error_mode const mode = error_mode &
271
                ~util::commandline_error_mode::report_missing_config_file;
272

273
            std::vector<std::string> options =
274
                read_config_file_options(filename.string(), mode);
873✔
275

276
            if (handle_config_file_options(
873✔
277
                    options, desc_cfgfile, vm, ini, mode))
278
            {
279
                break;    // break on the first options file found
280
            }
281

282
            // Boost filesystem and C++17 filesystem behave differently
283
            // here. Boost filesystem returns an empty path for
284
            // "/".parent_path() whereas C++17 filesystem will keep
285
            // returning "/".
286
#if !defined(HPX_FILESYSTEM_HAVE_BOOST_FILESYSTEM_COMPATIBILITY)
287
            auto dir_prev = dir;
873✔
288
            dir = dir.parent_path();    // chop off last directory part
873✔
289
            if (dir_prev == dir)
873✔
290
                break;
291
#else
292
            dir = dir.parent_path();    // chop off last directory part
293
#endif
294
        }
873✔
295
    }
97✔
296

297
    // handle all --options-file found on the command line
298
    void handle_config_options(hpx::program_options::variables_map& vm,
97✔
299
        hpx::program_options::options_description const& desc_cfgfile,
300
        util::section const& ini, util::commandline_error_mode error_mode)
301
    {
302
        using hpx::program_options::options_description;
303
        if (vm.count("hpx:options-file"))
194✔
304
        {
305
            auto const& cfg_files =
306
                vm["hpx:options-file"].as<std::vector<std::string>>();
×
307

308
            for (std::string const& cfg_file : cfg_files)
×
309
            {
310
                // parse a single config file and store the results
311
                std::vector<std::string> options =
312
                    read_config_file_options(cfg_file, error_mode);
×
313

314
                handle_config_file_options(
×
315
                    options, desc_cfgfile, vm, ini, error_mode);
316
            }
×
317
        }
318
    }
97✔
319

320
    void verify_unknown_options(std::vector<std::string> const& opts)
65✔
321
    {
322
        for (auto const& opt : opts)
66✔
323
        {
324
            std::string::size_type const p = opt.find("--hpx:");
325
            if (p != std::string::npos)
1✔
326
            {
327
                throw hpx::detail::command_line_error(
328
                    "Unknown/misspelled HPX command line option found: " + opt);
×
329
            }
330
        }
331
    }
65✔
332

333
    ///////////////////////////////////////////////////////////////////////////
334
    // parse the command line
335
    bool parse_commandline(util::section const& rtcfg, options_map& all_options,
194✔
336
        hpx::program_options::options_description const& app_options,
337
        std::vector<std::string> const& args,
338
        hpx::program_options::variables_map& vm,
339
        util::commandline_error_mode error_mode,
340
        hpx::program_options::options_description* visible,
341
        std::vector<std::string>* unregistered_options)
342
    {
343
        using hpx::program_options::command_line_parser;
344
        using hpx::program_options::options_description;
345
        using hpx::program_options::parsed_options;
346
        using hpx::program_options::positional_options_description;
347
        using hpx::program_options::store;
348
        using hpx::program_options::value;
349
        using namespace hpx::program_options::command_line_style;
350

351
        if (rtcfg.get_entry("hpx.commandline.allow_unknown", "0") == "0")
388✔
352
        {
353
            // clang-format off
354
            options_description positional_options;
137✔
355
            positional_options.add_options()
137✔
356
                ("hpx:positional",
137✔
357
                  value<std::vector<std::string>>(), "positional options")
358
                ;
359
            // clang-format on
360

361
            all_options[options_type::desc_cmdline].add(positional_options);
137✔
362
            all_options[options_type::desc_cfgfile].add(positional_options);
137✔
363

364
            // move all positional options into the hpx:positional option
365
            // group
366
            positional_options_description pd;
367
            pd.add("hpx:positional", -1);
137✔
368

369
            // parse command line, allow for unregistered options this point
370
            util::commandline_error_mode const mode =
371
                error_mode & util::commandline_error_mode::ignore_aliases;
372
            util::commandline_error_mode const notmode =
373
                error_mode & ~util::commandline_error_mode::ignore_aliases;
374

375
            parsed_options const opts(get_commandline_parser(
137✔
376
                command_line_parser(args)
137✔
377
                    .options(all_options[options_type::desc_cmdline])
137✔
378
                    .positional(pd)
379
                    .style(unix_style)
380
                    .extra_parser(option_parser(rtcfg, as_bool(mode))),
274✔
381
                notmode)
382
                    .run());
137✔
383

384
            // collect unregistered options, if needed
385
            if (unregistered_options)
137✔
386
            {
387
                using hpx::program_options::collect_unrecognized;
388
                using hpx::program_options::collect_unrecognized_mode::
389
                    exclude_positional;
390
                *unregistered_options =
46✔
391
                    collect_unrecognized(opts.options, exclude_positional);
392

46✔
393
                verify_unknown_options(*unregistered_options);
394
            }
395

137✔
396
            store(opts, vm);
137✔
397
        }
398
        else
399
        {
400
            // parse command line, allow for unregistered options this point
401
            util::commandline_error_mode const mode =
402
                error_mode & util::commandline_error_mode::ignore_aliases;
403
            util::commandline_error_mode const notmode =
404
                error_mode & ~util::commandline_error_mode::ignore_aliases;
405

57✔
406
            parsed_options const opts(get_commandline_parser(
57✔
407
                command_line_parser(args)
57✔
408
                    .options(all_options[options_type::desc_cmdline])
409
                    .style(unix_style)
114✔
410
                    .extra_parser(option_parser(rtcfg, as_bool(mode))),
411
                notmode)
57✔
412
                    .run());
413

414
            // collect unregistered options, if needed
57✔
415
            if (unregistered_options)
416
            {
417
                using hpx::program_options::collect_unrecognized;
418
                using hpx::program_options::collect_unrecognized_mode::
419
                    include_positional;
19✔
420
                *unregistered_options =
421
                    collect_unrecognized(opts.options, include_positional);
19✔
422

423
                verify_unknown_options(*unregistered_options);
424
            }
57✔
425

426
            store(opts, vm);
427
        }
388✔
428

429
        if (vm.count("hpx:help"))
430
        {
×
431
            // collect help information
432
            if (visible != nullptr)
433
            {
×
434
                (*visible)
×
435
                    .add(app_options)
×
436
                    .add(all_options[options_type::commandline_options])
×
437
                    .add(all_options[options_type::hpx_options])
×
438
                    .add(all_options[options_type::debugging_options])
439
                    .add(all_options[options_type::config_options]);
×
440
            }
441
            return true;
442
        }
194✔
443

444
        notify(vm);
194✔
445

446
        return true;
447
    }
194✔
448

449
    // Special type to be able to enforce an argument value if a parameter
450
    // that should normally be specified only once has been used with the
451
    // --hpx:arg=!value syntax to override any other possibly provided
452
    // argument value.
453
    struct argument_string : std::string
454
    {
194✔
455
        using std::string::string;
456
    };
457

194✔
458
    void validate(hpx::any_nonser& v, std::vector<std::string> const& xs,
194✔
459
        argument_string* t, int)
460
    {
461
        // check whether we should override any existing values
194✔
462
        if (v.has_value())
194✔
463
        {
194✔
464
            // if the previous value has a '!' prepended, then discard the
465
            // current argument
466
            std::string const& arg = any_cast<std::string>(v);
467
            if (!arg.empty() && arg[0] == '!')
468
            {
469
                return;
194✔
470
            }
471

194✔
472
            // if the current argument has a '!' prepended, then we discard the
473
            // previous value
474
            if (!xs[0].empty() && xs[0][0] == '!')
475
            {
194✔
476
                // discard any existing value
194✔
477
                v = hpx::any_nonser();
478
            }
479
        }
480

481
        // do normal validation
482
        program_options::validate(v, xs, static_cast<std::string*>(t), 0);
483
    }
484

194✔
485
    options_map compose_local_options()
486
    {
487
        using hpx::program_options::value;
488

489
        options_map all_options;
490

491
        // clang-format off
492
        all_options.emplace(options_type::commandline_options,
194✔
493
            "HPX options (allowed on command line only)");
494

495
        all_options[options_type::commandline_options].add_options()
496
            ("hpx:help", value<std::string>()->implicit_value("minimal"),
497
                "print out program usage (default: this message), possible "
498
                "values: 'full' (additionally prints options from components)")
499
            ("hpx:version", "print out HPX version and copyright information")
500
            ("hpx:info", "print out HPX configuration information")
194✔
501
            ("hpx:options-file", value<std::vector<std::string> >()->composing(),
502
                "specify a file containing command line options "
503
                "(alternatively: @filepath)")
504
        ;
505
        // clang-format on
506

194✔
507
        all_options.emplace(options_type::hpx_options,
508
            "HPX options (additionally allowed in an options file)");
509
        all_options.emplace(options_type::hidden_options, "Hidden options");
194✔
510

511
        // general options definitions
512
        // clang-format off
194✔
513
        all_options[options_type::hpx_options].add_options()
514
            ("hpx:pu-offset", value<std::size_t>(),
515
                "the first processing unit this instance of HPX should be "
516
                "run on (default: 0), valid for "
194✔
517
                "--hpx:queuing=local, --hpx:queuing=abp-priority, "
518
                "--hpx:queuing=static, --hpx:queuing=static-priority, "
519
                "--hpx:queuing=local-workrequesting-fifo, "
520
                "--hpx:queuing=local-workrequesting-lifo, "
194✔
521
                "--hpx:queuing=local-workrequesting-mc, "
522
                "and --hpx:queuing=local-priority only")
523
            ("hpx:pu-step", value<std::size_t>(),
524
                "the step between used processing unit numbers for this "
525
                "instance of HPX (default: 1), valid for "
526
                "--hpx:queuing=local, --hpx:queuing=abp-priority, "
527
                "--hpx:queuing=static, --hpx:queuing=static-priority "
194✔
528
                "--hpx:queuing=local-workrequesting-fifo, "
529
                "--hpx:queuing=local-workrequesting-lifo, "
530
                "--hpx:queuing=local-workrequesting-mc, "
531
                "and --hpx:queuing=local-priority only")
532
            ("hpx:affinity", value<std::string>(),
533
                "the affinity domain the OS threads will be confined to, "
534
                "possible values: pu, core, numa, machine (default: pu), valid for "
194✔
535
                "--hpx:queuing=local, --hpx:queuing=abp-priority, "
536
                "--hpx:queuing=static, --hpx:queuing=static-priority "
537
                "--hpx:queuing=local-workrequesting-fifo, "
538
                "--hpx:queuing=local-workrequesting-lifo, "
539
                "--hpx:queuing=local-workrequesting-mc, "
540
                " and --hpx:queuing=local-priority only")
541
            ("hpx:bind", value<std::vector<std::string> >()->composing(),
194✔
542
                "the detailed affinity description for the OS threads, see "
543
                "the documentation for a detailed description of possible "
194✔
544
                "values. Do not use with --hpx:pu-step, --hpx:pu-offset, or "
194✔
545
                "--hpx:affinity options. Implies --hpx:numa-sensitive=1"
546
                "(--hpx:bind=none disables defining thread affinities).")
194✔
547
            ("hpx:use-process-mask", "use the process mask to restrict "
548
                "available hardware resources (implies "
194✔
549
                "--hpx:ignore-batch-env)")
550
            ("hpx:print-bind",
551
                "print to the console the bit masks calculated from the "
194✔
552
                "arguments specified to all --hpx:bind options.")
553
            ("hpx:threads", value<std::string>(),
554
                "the number of operating system threads to spawn for this HPX "
194✔
555
                "locality (default: 1, using 'all' will spawn one thread for "
556
                "each processing unit")
194✔
557
            ("hpx:cores", value<std::string>(),
194✔
558
                "the number of cores to utilize for this HPX "
194✔
559
                "locality (default: 'all', i.e. the number of cores is based "
560
                "on the number of total cores in the system)")
194✔
561
            ("hpx:queuing", value<argument_string>(),
562
                "the queue scheduling policy to use, options are "
194✔
563
                "'local', 'local-priority-fifo','local-priority-lifo', "
194✔
564
                "'abp-priority-fifo', 'abp-priority-lifo', 'static', "
565
                "'static-priority', 'local-workrequesting-fifo',"
566
                "'local-workrequesting-lifo', and 'local-workrequesting-mc' "
567
                "(default: 'local-priority'; all option values can be "
388✔
568
                "abbreviated)")
569
            ("hpx:high-priority-threads", value<std::size_t>(),
570
                "the number of operating system threads maintaining a high "
388✔
571
                "priority queue (default: number of OS threads), valid for "
572
                "--hpx:queuing=local-priority,--hpx:queuing=static-priority, "
573
                "--hpx:queuing=local-workrequesting-fifo, "
388✔
574
                "--hpx:queuing=local-workrequesting-lifo, "
575
                "--hpx:queuing=local-workrequesting-mc, "
576
                " and --hpx:queuing=abp-priority only)")
577
            ("hpx:numa-sensitive", value<std::size_t>()->implicit_value(0),
578
                "makes the local-priority scheduler NUMA sensitive ("
194✔
579
                "allowed values: 0 - no NUMA sensitivity, 1 - allow only for "
194✔
580
                "boundary cores to steal across NUMA domains, 2 - "
581
                "no cross boundary stealing is allowed (default value: 0)")
582
        ;
583

194✔
584
        all_options.emplace(options_type::config_options,
585
            "HPX configuration options");
586
        all_options[options_type::config_options].add_options()
194✔
587
            ("hpx:app-config", value<std::string>(),
588
                "load the specified application configuration (ini) file")
589
            ("hpx:config", value<std::string>()->default_value(""),
590
                "load the specified hpx configuration (ini) file")
591
            ("hpx:ini", value<std::vector<std::string> >()->composing(),
194✔
592
                "add a configuration definition to the default runtime "
593
                "configuration")
594
            ("hpx:exit", "exit after configuring the runtime")
194✔
595
        ;
194✔
596

194✔
597
        all_options.emplace(options_type::debugging_options,
194✔
598
            "HPX debugging options");
194✔
599
        all_options[options_type::debugging_options].add_options()
194✔
600
            ("hpx:dump-config-initial", "print the initial runtime configuration")
194✔
601
            ("hpx:dump-config", "print the final runtime configuration")
602
            // enable debug output from command line handling
194✔
603
            ("hpx:debug-clp", "debug command line processing")
604
#if defined(_POSIX_VERSION) || defined(HPX_WINDOWS)
605
            ("hpx:attach-debugger",
194✔
606
                value<std::string>()->implicit_value("startup"),
194✔
607
                "wait for a debugger to be attached, possible values: "
194✔
608
                "off, startup, exception or test-failure (default: startup)")
194✔
609
#endif
194✔
610
            ("hpx:debug-hpx-log", value<std::string>()->implicit_value("cout"),
194✔
611
                "enable all messages on the HPX log channel and send all "
194✔
612
                "HPX logs to the target destination")
613
            ("hpx:debug-timing-log", value<std::string>()->implicit_value("cout"),
97✔
614
                "enable all messages on the timing log channel and send all "
615
                "timing logs to the target destination")
616
            ("hpx:debug-app-log", value<std::string>()->implicit_value("cout"),
617
                "enable all messages on the application log channel and send all "
618
                "application logs to the target destination")
619
            // ("hpx:verbose_bench", "For logging benchmarks in detail")
620
        ;
621

622
        all_options[options_type::hidden_options].add_options()
623
            ("hpx:ignore", "this option will be silently ignored")
97✔
624
        ;
625
        // clang-format on
97✔
626

627
        return all_options;
628
    }
97✔
629

630
    void compose_all_options(
631
        hpx::program_options::options_description const& app_options,
97✔
632
        options_map& all_options)
97✔
633
    {
97✔
634
        // construct the overall options description and parse the command line
194✔
635
        all_options.emplace(options_type::desc_cmdline,
636
            "All HPX options allowed on the command line");
637

638
        all_options[options_type::desc_cmdline]
×
639
            .add(app_options)
640
            .add(all_options[options_type::commandline_options])
×
641
            .add(all_options[options_type::hpx_options])
642
            .add(all_options[options_type::config_options])
×
643
            .add(all_options[options_type::debugging_options])
644
            .add(all_options[options_type::hidden_options]);
×
645

646
        all_options.emplace(options_type::desc_cfgfile,
×
647
            "All HPX options allowed in configuration files");
×
648

649
        all_options[options_type::desc_cfgfile]
650
            .add(app_options)
651
            .add(all_options[options_type::hpx_options])
652
            .add(all_options[options_type::config_options])
653
            .add(all_options[options_type::debugging_options])
33✔
654
            .add(all_options[options_type::hidden_options]);
655
    }
656

33✔
657
    bool parse_commandline(util::section const& rtcfg,
658
        hpx::program_options::options_description const& app_options,
33✔
659
        std::string const& arg0, std::vector<std::string> const& args,
660
        hpx::program_options::variables_map& vm,
661
        util::commandline_error_mode error_mode,
662
        hpx::program_options::options_description* visible,
663
        std::vector<std::string>* unregistered_options)
664
    {
33✔
665
        try
666
        {
667
            options_map all_options = compose_local_options();
668

669
            compose_all_options(app_options, all_options);
670

671
            bool const result =
672
                parse_commandline(rtcfg, all_options, app_options, args, vm,
673
                    error_mode, visible, unregistered_options);
674

675
            handle_generic_config_options(arg0, vm,
66✔
676
                all_options[options_type::desc_cfgfile], rtcfg, error_mode);
677
            handle_config_options(
33✔
678
                vm, all_options[options_type::desc_cfgfile], rtcfg, error_mode);
33✔
679

33✔
680
            return result;
33✔
681
        }
682
        catch (std::exception const& e)
683
        {
205✔
684
            if (as_bool(error_mode &
685
                    util::commandline_error_mode::rethrow_on_error))
686
                throw;
205✔
687

688
            std::cerr << "hpx::init: exception caught: " << e.what()
205✔
689
                      << std::endl;
×
690
        }
691
        return false;
692
    }
693

217✔
694
    ///////////////////////////////////////////////////////////////////////////
695
    namespace detail {
696

434✔
697
        std::string extract_arg0(std::string const& cmdline)
217✔
698
        {
306✔
699
            std::string::size_type const p = cmdline.find_first_of(" \t");
217✔
700
            if (p != std::string::npos)
701
            {
64✔
702
                return cmdline.substr(0, p);
703
            }
704
            return cmdline;
705
        }
302✔
706
    }    // namespace detail
707

708
    bool parse_commandline(util::section const& rtcfg,
238✔
709
        hpx::program_options::options_description const& app_options,
710
        std::string const& cmdline, hpx::program_options::variables_map& vm,
131✔
711
        util::commandline_error_mode error_mode,
262✔
712
        hpx::program_options::options_description* visible,
131✔
713
        std::vector<std::string>* unregistered_options)
714
    {
715
        using namespace hpx::program_options;
107✔
716
#if defined(HPX_WINDOWS)
717
        std::vector<std::string> args = split_winmain(cmdline);
5✔
718
#else
10✔
719
        std::vector<std::string> args = split_unix(cmdline);
5✔
720
#endif
721
        return parse_commandline(rtcfg, app_options,
722
            detail::extract_arg0(cmdline), args, vm, error_mode, visible,
102✔
723
            unregistered_options);
724
    }
7✔
725

14✔
726
    ///////////////////////////////////////////////////////////////////////////
7✔
727
    std::string embed_in_quotes(std::string const& s)
728
    {
729
        char const quote =
95✔
730
            (s.find_first_of('"') != std::string::npos) ? '\'' : '"';
731

732
        if (s.find_first_of("\t ") != std::string::npos)
733
            return quote + s + quote;
138✔
734
        return s;
735
    }
148✔
736

74✔
737
    std::string reconstruct_command_line(int argc, char* argv[])
738
    {
739
        std::string command_line;
740
        for (int i = 0; i != argc; ++i)
741
        {
64✔
742
            if (!command_line.empty())
743
                command_line += " ";
744
            command_line += embed_in_quotes(argv[i]);
745
        }
746
        return command_line;
747
    }
748
}    // namespace hpx::local::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