[distcc] Re: yet another C-supporting cmdline scanner

Markus Werle numerical.simulation at web.de
Fri Jul 11 08:36:13 GMT 2003


Martin Pool wrote:

> On 10 Jul 2003, Markus Werle <numerical.simulation at web.de> wrote:
>
> > OTOH if you think about rewriting it in C++ I will certainly
> > give my 2 cent and provide the parsing utility.
>
> Perhaps you can post an outline or sketch of your design in either
> pseudocode or C++.  Then we can discuss it and perhaps adapt it to C.
> The concept and design is more important than the expression

I have a class RunTimeParameters. which stores all options internally

You have member functions for getting and setting the vars,
and some additional features like latex table or restart file output
or consistency check (which allows to check default formulas
and the values coincide, or required options are really set etc.)
and default value, resp. default formula setting.

Legal options can be registrated like this


RunTimeParameters RTP;

RTP
    // a title for the help output
    .add_option<std::string>("", ""       , "\n  Runtime Behaviour:\n")

    .add_option<std::string>("c", "config-file", "read program options from this file")

    .add_option<std::string>("r", "restart-file", "write program options to this file")
    .default_value(std::string("restart.dat"))

    .add_option<double>("t" ,"timestep", "the default timestep to use [1]")
     .required()

    .add_option<std::size_t>("n" ,"number-of-timesteps", "the number of timestep to use").required()

    .add_option<bool>("h", "help", "display this help and exit").default_value(false)

    .add_option<double>("", "E_l"   , "energy in left part of shock tube")

    // formulas with the help of daixtrose.sf.net
    .default_value((ph("p_l") / (ph("gamma") - scalar(1.0)))
                   +
                   ph("rho_l") * (Pow<2>(ph("u_l")) + Pow<2>(ph("v_l"))) / scalar(2.0))

The command line parser (built on top of boost::spirit) is an extra tool.
It only expects a GNU-conventioned command line like

program -t --help --some-value=3.4 -x 3 --some-bool=true
--enable-some-option --disable-someother-option --with-a --without-b

it reads in the command line and checks for syntactical errors only,
while it translates "--with-foo" to "--foo=true".
Similar things happen to --enable and --disable options.

This parser step ends with a table of args (a std::map)

You can then check for option "-f" (or whatever you want)
and if You find it, trigger a read in from config file which has to have
a C-like syntax:

/* some var */
// or a nother comment
var = 2.0;
another_var = "go ahead";

Again keywords true, false and strings are handled appropriately.

The parser then creates a std::map<std::string, boost::any>
which it "sends" to the RunTimeParamters object (let us call it RTP).
RTP handles this, analyses it and is ready for use after the above mentioned
steps (consistency check etc.) have been evoked.

Now, since we have const references in C++, any function which needs
knowledge about runtime parameters has a signature:

void foo([.. some parameters ...], RunTimeParameters const& RTP);

Inside the function body I check the vars using calls like
int x =  RTP.get<int>("number-of-grid-points-in-x");

Also note that most functions are member functions, so I
initialize some of these with a reference to RTP:

SolverT Solver(Grid, RTP);

Then inside the Solver, every memfun has access to RTP_,
which is just a const reference to RTP in main.

-----------

I feel a little bit sorry for anyone who has to do that in C,
but let me propose some things.

1. separate the parser form the argument representation you use

2. For distcc I thing that a struct, containing the 10 char* and some bools
you need to steer the program is sufficient. Also I recommend to avoid
all global vars, but perhaps this is too much of work for a C project.
(rtp below could also be a global var with the well-known consequences)

struct runtime_parms
{
    char * my_own_name;
    char * cflags;
  /* etc */
    bool show_usage;
};



int main(int argc, char **argv)
{
    runtime_parms rtp;

    distcc_parse_cmdline(argc, argv, &rtp); // yields rtp in a correct state

    if (rtp.show_usage) { dcc_show_usage(); exit(0); }
    [...]

    if (rtp.input_file) { /* read in and parse input file,
                                        set unset options in rtp */ }

    if (strstr(rtp.progname, "distcc") != NULL) { ...}
    // etc

     dcc_exit(dcc_build_somewhere_timed(&rtp));
}


Is that a way to go in C?


Markus







More information about the distcc mailing list