<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jun 9, 2014 at 11:16 AM, Huidae Cho <span dir="ltr"><<a href="mailto:grass4u@gmail.com" target="_blank">grass4u@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Interesting, actually this works better I think.<div><br></div><div><span style="font-family:arial,sans-serif;font-size:13px">#define G_option_exclusive(...) G__option_exclusive(NULL, __VA_ARGS__, NULL)</span><br>
</div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">G_option_exclusive(&opt1, &opt2, &flag1); // no need for the first name and last NULL arguments.</span></div>
</div><div class=""><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jun 9, 2014 at 11:13 AM, Huidae Cho <span dir="ltr"><<a href="mailto:grass4u@gmail.com" target="_blank">grass4u@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Maybe, we can use variadic macros in C99 to remove the first name argument.<div><br>
</div><div>#define G_option_exclusive(...) G__option_exclusive(NULL, __VA_ARGS__)</div>
</div><div><div><div class="gmail_extra"><br></div></div></div></blockquote></div></div></div></div></blockquote><div> <br></div><div>Note that C99 is not what GRASS currently requires. Details:<br><br>[GRASS-dev] C and C++ standards used by GRASS<br>
<a href="http://lists.osgeo.org/pipermail/grass-dev/2014-March/068017.html">http://lists.osgeo.org/pipermail/grass-dev/2014-March/068017.html</a><br><br>> C code is supposed to conform to C89 and POSIX.<br><br>(C89 with POSIX extensions)<br>
<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class=""><div class="h5"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div><div class="gmail_extra">
<div class="gmail_quote">On Mon, Jun 9, 2014 at 10:54 AM, Huidae Cho <span dir="ltr"><<a href="mailto:grass4u@gmail.com" target="_blank">grass4u@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr"><div>I somehow agree with you that my interface can be cryptic and requires some interpretation because information is spread out. I think we can define something like:</div><div><div><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px"> // at most one option from a set</span><br style="font-family:arial,sans-serif;font-size:13px"></div><span style="font-family:arial,sans-serif;font-size:13px"> void G_option_exclusive(const char *name, ...);</span><div>
<br style="font-family:arial,sans-serif;font-size:13px">
<br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px"> // at least one option from a set</span><br style="font-family:arial,sans-serif;font-size:13px"></div>
<span style="font-family:arial,sans-serif;font-size:13px"> void G_option_required(const char *name, ...);</span><div><br style="font-family:arial,sans-serif;font-size:13px">
<br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px"> // if the first option is present, at least one of the other</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px"> // options must also be present</span><br style="font-family:arial,sans-serif;font-size:13px"></div><span style="font-family:arial,sans-serif;font-size:13px"> void G_option_requires(const char *name, ...);</span><br>
</div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">Here, actually, name is not needed, but is there only for stdarg. And we use these functions:</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">G_option_exclusive("format", &opt1, &opt2, &flag1, NULL); // No opt1, opt2, and flag1 at all OR only one of them.</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px">G_option_required("required", &opt1, &opt2, &flag1, NULL); // At least one of opt1, opt2, and flag1 must be given.</span></div><div><span style="font-family:arial,sans-serif;font-size:13px">G_option_requires("group1", &opt1, &opt2, NULL); // opt1 and opt2 must be used together.</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">In each function, we can use the state variable in parser.c (st->first_option and st->first_flag) to find defined options and flags:</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">opt = &st->first_option;</span><br></div><div><font face="arial, sans-serif">while(opt){</font></div>
<div><font face="arial, sans-serif"> struct Option *x; </font></div><div><span style="font-family:arial,sans-serif;font-size:13px"> va_start(ap, name);</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"> while((x = va_arg(ap, struct Option *))){</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"> if (x == opt) {</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"> ...</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"> break;</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"> }</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"> }</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"> va_end(ap);</span></div>
<div><span style="font-family:arial,sans-serif;font-size:13px"> opt = opt->next_opt;</span></div><div><span style="font-family:arial,sans-serif;font-size:13px">}</span></div><div class="gmail_extra"><br></div><div class="gmail_extra">
<div><span style="font-family:arial,sans-serif;font-size:13px">flag = &st->first_flag;</span><br></div><div><font face="arial, sans-serif">while(flag){</font></div><div><span style="font-family:arial,sans-serif;font-size:13px"> similar code here...</span></div>
<div><div>
<div><span style="font-family:arial,sans-serif;font-size:13px">}</span><br></div><br><div class="gmail_quote">On Mon, Jun 9, 2014 at 5:34 AM, Glynn Clements <span dir="ltr"><<a href="mailto:glynn@gclements.plus.com" target="_blank">glynn@gclements.plus.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><br>
Huidae Cho wrote:<br>
<br>
> My implementation of the "exclusive" member, which you reverted, can handle<br>
> all these cases, I think. But since you reverted it, I think you didn't<br>
> agree with my interface or implementation?<br>
<br>
</div>Not really.<br>
<br>
[I also wanted to be able to discuss this starting from a blank slate,<br>
without the temptation to take any specific approach as a "reference<br>
point". But that alone wouldn't have been sufficient for reversion.]<br>
<br>
Mostly, I find the interface to be cryptic. Information which should<br>
(IMHO) be in one place is spread out across the individual options.<br>
<br>
In order to understand the relationships, anyone reading the code<br>
needs to examine all of the options, and collate them into groups<br>
based upon matching group numbers. IOW, mentally replicate the<br>
(non-trivial) algorithms which form the bulk of r60713. The fact that<br>
this was deemed to require several examples (with comments) tends to<br>
suggest that it isn't particularly intuitive.<br>
<br>
Apart from that, declaring "rules" would make the transition more<br>
straightforward, as it mirrors the structure of the existing code<br>
(i.e. the "if (expression) error();" statements).<br>
<br>
By itself, that wouldn't be sufficient reason to prefer a rule-based<br>
approach if it is considered to be inferior on its own merits. But<br>
given the extent of the changes, it might be enough to tip the balance<br>
in the event that the choice between different approaches amounted to<br>
a toss-up.<br>
<div><br>
> IMO, passing option/flag names to G_option_required() has its own<br>
> disadvantage because changing option/flag names takes more effort. If you<br>
> have valid reasoning behind adding functions rather than adding a member,<br>
> just like I did, I would prefer to pass *Option and *Flag pointers to those<br>
> functions. But I guess it can be a little tricky to pass two different<br>
> types of pointers.<br>
<br>
</div>Indeed. I originally considered passing the struct pointers before<br>
realising that approach wouldn't allow both flags and options to be<br>
used interchangeably. At least, not without changing the structures to<br>
carry some kind of type signature, although that wouldn't be<br>
particularly difficult, given that both structures have to be created<br>
via the appropriate functions.<br>
<br>
This issue can be mitigated somewhat by using opt->name in the call<br>
rather than a string literal[1]. We'd still need to use a literal for<br>
flags, though.<br>
<br>
[1] If we do that, modules which use "opt1", "opt2", etc for the<br>
variable names should be changed to use meaningful names. Actually,<br>
that should be done regardless.<br>
<span><font color="#888888"><br>
--<br>
Glynn Clements <<a href="mailto:glynn@gclements.plus.com" target="_blank">glynn@gclements.plus.com</a>><br>
</font></span></blockquote></div><br></div></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
grass-dev mailing list<br>
<a href="mailto:grass-dev@lists.osgeo.org">grass-dev@lists.osgeo.org</a><br>
<a href="http://lists.osgeo.org/mailman/listinfo/grass-dev" target="_blank">http://lists.osgeo.org/mailman/listinfo/grass-dev</a><br></blockquote></div><br></div></div>