[LLVMdev] CommandLine: using cl::Positional with enum

Pedro Delgado Perez pedro.delgadoperez at mail.uca.es
Wed May 8 10:27:00 PDT 2013


 
Hi Daniel,

Just in the moment you replied my message, I was rewriting it as I hadn't noticed it hadn't a correct format. Sorry for that and thanks for answering it anyway.

> ./prog <option1> | ( <option2> --arg1 --arg2) | ( <option3> --arg1 )
> 
Yes, that is exactly what I need. It's a pity commandLine doesn't implement that possibility. So I will do what you tell, parsing the arguments by myself and extending the help like you propose.

> 
> I don't see why you should really care about the order, i.e. this is
> probably okay.
> 
> ./prog --arg1 <option1>
> 
> So why not make every argument optional (i.e. no positional arguments)
> 
The order is important in our case because I would like not to force the user to use the "-" prefix. In our tool, we have a order established in the input of arguments (these arguments are associated with the first option given).  So I will simply process the arguments directly, I think. 

Thanks for everything,

Pedro.






El dia 08 may 2013 13:56, Daniel Liew <daniel.liew at imperial.ac.uk> escribió:
> Hi,
> 
> Please try and format your e-mails better. Your e-mail is incredibly
> hard to read due to its lack of new lines.
> 
> I don't think the designer of the CommandLine library ever intended for
> cl::Positional to be used with cl::opt<T> where T is an enum.
> 
> e.g.
> 
> enum OptLevel {
> g, O1, O2, O3
> };
> 
> cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
> cl::values(
> clEnumVal(g , "No optimizations, enable debugging"),
> clEnumVal(O1, "Enable trivial optimizations"),
> clEnumVal(O2, "Enable default optimizations"),
> clEnumVal(O3, "Enable expensive optimizations"),
> clEnumValEnd),
> cl::Positional
> );
> 
> int
> main (int argc, char ** argv)
> {
> cl::ParseCommandLineOptions(argc, argv);
> 
> // Easy access in gdb (getValue is inlined!)
> OptLevel* test = &(OptimizationLevel.getValue() );
> }
> 
> It also doesn't make a huge amount of sense (based on the output of
> -help) either because the OptimizationLevel options have the "-" prefix
> which is almost always taken to mean that it is optional and NOT
> positional. -help shows...
> 
> Choose optimization level:
> -g - No optimizations, enable debugging
> -O1 - Enable trivial optimizations
> -O2 - Enable default optimizations
> -O3 - Enable expensive optimizations
> 
> Trying
> 
> $ ./program -O1
> $ ./program O1
> $ ./program -- -O1
> $ ./program -- O1
> 
> does not result in OptimizationLevel being modified by calling
> ParseCommandLineOptions (I tested this in gdb).
> 
> This behaviour is arguably a bug. You're welcome to try and fix it.
> 
> I would like to suggest an alternative though. If I understand you
> correctly you're looking for your command line syntax to be something
> like...
> 
> ./prog <option1> | ( <option2> --arg1 --arg2) | ( <option3> --arg1 )
> 
> I don't see why you should really care about the order, i.e. this is
> probably okay.
> 
> ./prog --arg1 <option1>
> 
> So why not make every argument optional (i.e. no positional arguments)
> 
> then after calling ParseCommandLineOptions you can check the user has
> used the right options by doing something like...
> 
> // Note cl::opt<T> is a type of Option
> Option* NOTValidForOption1[] = { &arg1, &arg2};
> Option* NOTValidForOption3[] = { &arg2 };
> 
> switch(YourOption)
> {
> case Option1:
> for(int I=0; I < sizeof(NOTValidForOption1)/sizeof(Option*);++I)
> {
> if(NotValidForOption1[I]->getNumOccurrences() != 0)
> {
> //Fail
> }
> }
> break;
> 
> case Option2:
> break;
> 
> case Option3:
> // similar to Option1
> }
> 
> ^ Note the above certainly code be coded better, this is just to give
> you an idea.
> 
> You could also make it more obvious in the output of -help that only
> certain options should be used with each other by putting them into
> categories (see cl::cat() in documentation). Note this will only work
> for you if arguments are mutually exclusive as an option may only be in
> one category.
> 
> Hope that helps.
> 
> Dan.
> 
> On 07/05/13 08:58, Pedro Delgado Perez wrote:
> 
>> Hi,I've been trying to code through CommandLine the options I want my tool accepts, but I find quite impossible to achieve robustly what I need .Look, I want the tool accepts a list of arguments in a particular order. For this goal, I know the cl::Positional flag. But, the problem is that *the first argument must be one of a set of options *(like a kind of subcommand of the tool). In my case, only the three next commands are possible:
>> 
>> myTool option1myTool option2 arg1 arg2 myTool option3 arg1and I don't want a different order is possible, for instance, this is not permitted:myTool arg2 option2 arg1So, I thought about using an enum for this first argument:enum OptLevel{option1, option2, option3};cl::opt<OptLevel> OptionsLevel(cl::Positional, cl::desc("Choose one of these options:"),cl::values(clEnumVal(option1, "..."),clEnumVal(option2, "..."),clEnumVal(option3, "..."), clEnumValEnd),);After that, the rest of arguments are also particular of the option selected as the first argument, i.e, the rest of arguments are related with the first one. So I thought I could independently parse these arguments with:cl::list<std::string> Argv (cl::ConsumeAfter, cl::desc("<program arguments>..."));But, doing this when I run:myTool option1 file.cpp --I got the next error:"error - this positional option will never be matched, because it does not Require a value and a cl::ConsumeAfter option is active!"So, I modify "OptionsLeve
>> 
> lOptionsLevel" including the cl::Required flagThe error is now:"option: does not allow a value! option1 specified.option: must be specified at least once!option: must be specified at least once!option: must be specified at least once!"Then, I decided to use cl::PositionalEatsArgs instead of cl::ConsumeAfter. Then, this is the result:"option: does not allow a value! option1 specified."But, this time, the program continues. However, if I run "myTool option3 arg1 file.cpp --" it gives me a different problem:"warning: ../build/arg1: 'linker' input unusederror: unable to handle compilation, expected exactly one compiler job in ' '"But the program still goes on.Is there a way to accomplish what I have explained? I don't want those errors and warnings. Thanks,Pedro.
> 
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu [ http://llvm.cs.uiuc.edu ]
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev [ http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev ]
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130508/db85a990/attachment.html>


More information about the llvm-dev mailing list