Pedro Delgado Perez
2013-May-10 08:44 UTC
[LLVMdev] CommandLine: using cl::Positional with enum
Hi Daniel, I would like to go deeper with CommandLine and I was asking if you could help me again. Look, following the same example you put in the last message: ./prog <option1> | ( <option2> --arg1 --arg2) | ( <option3> --arg1 ) What I really really want is the same except I don't want the "--" prefix is present in any of the arguments. ./prog <option1> | ( <option2> arg1 arg2) | ( <option3> arg1 ) The problem is clear: in this case, the arguments can't be optional. So I thought to delete all the "cl:opt" and process the arguments before calling: ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); in order to give an error if the arguments provided were not correct. But, if arguments are correct, then the next error is shown: warning: /home/user/clang-llvm/build/arg1: 'linker' input unused error: unable to handle compilation, expected exactly one compiler job in '' Error while processing /home/user/clang-llvm/build/arg1 How can I manage this? I was thinking about not calling the ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); but, I don't know if this would be another problem. In addition, I would have to create my own option --help, isn't it? What do you recommend me to do? Thanks in advance, 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/20130510/c2547af3/attachment.html>
Reasonably Related Threads
- [LLVMdev] CommandLine: using cl::Positional with enum
- [LLVMdev] CommandLine: using cl::Positional with enum
- [LLVMdev] CommandLine: using cl::Positional with enum
- [LLVMdev] CommandLine: using cl::Positional with enum
- [LLVMdev] CommandLine: using cl::Positional with enum