Genopt
Description
Genopt is a utility to generate portable source code that parses
command-line options. You give the option letter and a short description,
and genopt will create the source to parse that option and display
help messages when things go wrong. It takes most of the repetitive
coding out of the process, because we all know that when programmers
get bored, programmers make mistakes.
The generated source uses the standard getopt(3) library
function to parse the options. Currently, it writes C++ source
(because I'm freakin' sick of char*'s), and does not use the
GNU getopt_long function (because while GCC is good, it's
not always installed or even being used, therefore libiberty isn't
always available). However, plans are in place to optionally generate
C code and long options.
SourceForge lists us as
Software
:: Software Development :: Command-Line Option Generator (if you
didn't already know), and that's the link to the project page. You can jump
back to here, or browse the CVS repository, or download the releases, or
do stuff with mailing lists and surveys and bugtracking and
other buzzwords. (I really would appreciate feedback, though.)
Examples
There are a couple easy examples in the distributed source, such as the
input file used to create some of genopt's own source. Here is a tiny
sample input file, via which I will express my distaste for the typical
slashdot.org poster:
# This reads the options for my k3wl flame-writer for all Slashdot.org posts.
#
# -Anonymous Coward
package "Automatic /. Flame-Generator"
packageversion "11.7" # the version is my age, huh huh huh that's so K3WL
option microsquish flag 'S'
"Disables the automatic appending of Microsoft flames (duh, screw that)."
option portman integer 'p'
"Number of repetitions of sexist immature prepubescent remarks about popular actresses."
default "85" argname "count"
# D00D L1NUCKS RU1Z!!!!11!!!1
option unbalanced_view_of_technology flag 'u'
"Blindly roast anybody who critiques Linux or praises parts of other OSes."
default "true" exclude remindpreview
option remindpreview flag 'd' "Debug reminder to preview comments."
default "false"
|
|
After naming that file "sample" and running
"genopt -o troll -p whacko_ sample" the
generated troll.h file looks like this:
/*
* Automatic /. Flame-Generator 11.7
* troll.h -- Declarations of command-line options.
*
* GENERATED BY GENOPT -- CHANGES WILL BE LOST
*/
#ifndef TROLL_H
#define TROLL_H
// -S Disables the automatic appending of Microsoft flames (duh, screw that).
extern bool whacko_microsquish_option;
// -p Number of repetitions of sexist immature prepubescent remarks about popular actresses.
extern int whacko_portman_option;
// -u Blindly roast anybody who critiques Linux or praises parts of other OSes.
extern bool whacko_unbalanced_view_of_technology_option;
// -d Debug reminder to preview comments.
extern bool whacko_remindpreview_option;
extern int whacko_process_options (int, char**);
#endif /* TROLL_H */
|
|
The generated symbol names are under your control via the -p (prefix)
and -n (namespace) options. The generated troll.cc file is a
bit too large to include in
the homepage directly and not make everything look ugly (IMHO), but it is
sitting over here, renamed to be a bit more
browser-friendly. Compiling it along with a simple main() wrapper
(included in the source)...
g++ -c -I. troll.cc
g++ -c -I. exercise.cc
g++ -o immaturity exercise.o troll.o
./immaturity -h
...results in (among other things) help output looking something like
this (the webpage changes based on which genopt version is current):
Automatic /. Flame-Generator version 11.7
Usage: immaturity [-hv] [-Sud] [-p count]
Options:
-S Disables the automatic appending of Microsoft
flames (duh, screw that).
-p count Number of repetitions of sexist immature
prepubescent remarks about popular actresses.
[default 85]
-u Blindly roast anybody who critiques Linux or
praises parts of other OSes.
[default true]
-d Debug reminder to preview comments.
[default false]
|
|
Features
There were a couple things in particular that I wanted out of a utility
like genopt (see the Design and Implementation Notes in the source for
more). They included:
- Good control over the names of the generation option variables.
- Support for C++ namespaces (goes with the first one).
- The generated code should look good and be easily readable. Genopt
does not try and solve all possible problems for you, but if there's
something in the generated source that you feel you need to tweak
directly, doing so should not be a major undertaking. Comments are
part of the generated source. Most of the "printing"
(e.g., help) is done with string literals that you can adjust without
breaking anything else.
- It should be easy to drop in and use. There is only one function
that you need to call to process everything.
As of version 0.6, genopt fulfills all these requirements. (Now I have
some more requirements. :-)
Bugs
There are a couple of things that need to be done before an 0.7 release:
The print_usage function needs to be made smarter (I just left
that part hang since I was coming down with a cold and just felt crummy),
all documentation needs to agree on the help/version things, and the
write_source_file function is simply a gargantuan piece of hungus.
Tweaking the flag-exclusion code would be helpful, probably.
Some things that need to be implemented in order to reach 1.0:
- Using "-c" to generate C code
- This is likely to remain unimplemented unless one of you does it.
I myself have no need to generate pure C code, and have no interest
in doing so. The write_{header,source}file functions would
need to be split into pieces, probably.
- Using "-l" to support long options
with GNU's libiberty
- One of these days I'll read up on how to use getopt_long
and implement this, maybe. I need very portable code that doesn't
depend on GNU tools being there, so it may be a long time coming.
- Handle --help and --version specially.
- These are really useful to support even if long options aren't used.
Oddities and Interesting Things
If you're curious and desperate, I did a quick
nroff -man genopt.1 | col -b to dump the man page to a
text file. The result looks awful and shouldn't be used as real
documentation, but if you want to get a feel for what genopt does,
the text file is available here.
This is probably not up-to-date.
Roberto Arturo Tena Sanchez (arturo at users.sourceforge.net) independantly
wrote gengetopt(1) some six months earlier, which requires
GNU getopt_long(3) and allows long-format options. The input file
formats are deliberately similar, although genopt was written without
ever having seen the gengetopt source. The gengetopt project homepage
has moved to SourceForge as
http://gengetopt.sourceforge.net/.
Each of our two programs has its pros and cons; you should consider both.
See the Design and Implementation Notes (of the genopt source) for more
(including why I wrote genopt knowing that I was reinventing the wheel).
The way genopt was created might be amusing to some of you:
- Work out on paper what I wanted it to do, and what command-line
options it would need to do that.
- Work out on paper the format of the input file.
- Work out on paper what genopt's own input file would look like.
- Wrote the man page. All of it. (Wheee, documentation-driven
design!) It has changed remarkably little.
- Acting as a "human genopt," I then wrote the
outfile.{h,cc} files, using the names and commenting
conventions that I wanted genopt to eventually produce.
- Made up test input files, like self_options and
exercise_options.
- Wrote all the other source...
- ...testing it with the exercise.* files.
- Repeat steps 7 and 8 until the generated header and source
matched the handwritten outfile.* in all essentials.
- Incremented the version from 0.0 to 0.1.
- Copied the generated source on top of the handwritten source,
performed a few final tweaks, wrote up a better web page, cleaned
up the directory, made the examples directory, added a brief
configure script. Incremented the version to 0.6.
I have no idea what all that mess was with 0.1 to 0.6, but in the man
page I said that genopt would generate its own source after v0.1, so
darn it, the version number waited until then! After all, if genopt
can't even be trusted on a simple program like itself, I wouldn't ask
you to trust it on your code.
Download
Genopt is released under the GNU General Public License version 2, but
no restrictions are placed on the generated source code by the use of
genopt (unless you add such restrictions, duh). The latest release is
genopt-0.6.tar.gz.
Nota Bene: The code is embarassing but perfectly functional.
I encourge you to compile and use this program, but please don't read
the code unless you have made out your will and testament and consulted
with family lawyers.
If you have no location bar displayed, or you haven't been paying
attention, then you probably aren't aware that this project is currently
hosted by the folks at SourceForge.