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:

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:

  1. Work out on paper what I wanted it to do, and what command-line options it would need to do that.
  2. Work out on paper the format of the input file.
  3. Work out on paper what genopt's own input file would look like.
  4. Wrote the man page. All of it. (Wheee, documentation-driven design!) It has changed remarkably little.
  5. 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.
  6. Made up test input files, like self_options and exercise_options.
  7. Wrote all the other source...
  8. ...testing it with the exercise.* files.
  9. Repeat steps 7 and 8 until the generated header and source matched the handwritten outfile.* in all essentials.
  10. Incremented the version from 0.0 to 0.1.
  11. 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.