NAME

enumgen - generate operators and/or translation tables for enum types

SYNOPSIS

enumgen [-M] [-I [-m]] [-B [-a]]
     [-n] [-c source_suffix] [-h header_suffix] [-t type] file...

DESCRIPTION

enumgen generates various types of operators and/or translation tables for C++ enum types. Depending on the options given, enumgen can generate the bitwise operators (with or without the arithmetic operators like '+'), increment and decrement (either with bounds checking or modulo) and an instantiation of the template functions map for the given enum type(s). (See the header file gb/EnumMap.hh.)

When generating the translation tables (explicit specializations of the template functions Gabi::map), two files are generated, a header file, which must be included in order to use the functions, and a source file which must be compiled (using the Gabi library). The names of these files are generated by truncating the filename passed to the generator before the first '.', then appending Map.hh and Map.cc, respectively. (The file type suffixes can be changed by using the -h and -c options.) Thus, given a file E.hh which contains the definition of an enum 'E', the command "enumgen -M E.hh" will generate the files EMap.hh and EMap.cc, the first which must be included, and the second which must be compiled. To translate from an enum value to a string, the code is (supposing that value is a variable of type E):

      Gabi::Fallible< std::string > valueString = Gabi::map( value ) ;
    
Similarly, to translate from a string to the enum type, it is necessary to write:
      Gabi::Fallible< E > value = Gabi::map< E >( valueString ) ;
    
In this case, it is necessary to specify the instantiation type, since it cannot be deduced from the function parameters (which are the same regardless of the enum type).

In both cases, if there is no translation for the value (which can occur in the first case if e.g. operator| has been overloaded for the enum type, and the argument is an | of several values), then the Fallible result will be invalid, see the documentation for Gabi::Fallible.

The generated functions are in namespace Gabi; this is necessary, since they are specializations of a template in namespace Gabi, but this may have some repercutions when argument dependant name lookup is considered, e.g. in the second phase of two phase lookup in a template instantiation.

The incrementation operators (option -I) can only be generated for enum types in which none of the enum values has a user defined value. The code is generated as inline functions in a simple header file, whose name is derived by truncating the source file at the last '.', then appending "Incr.hh", so that "E.hh" results in a file named "EIncr.hh". Both prefix and postfix versions of both operators ++ and -- are generated. If the option -m is given, incrementation and decrementation wrap (modulo arithmetic); otherwise, overflow or underflow will trigger an assertion failure.

The bitwise operators (option -B) can only be generated for enum types where all of the enum values have a user defined value; they make no sense otherwise. (Is this true, or have I simply created an artificial limitation?) For a source file E.hh, the generated file is EBitOps.hh. The operators generated are |, & and ~; if the -a option is given, the binary operators +, -, * and the unary operator - are also generated, with bitwise semantics. (The purpose here is to provide the desired operators with the correct precedence: + implements the same functionality as |, * as &, and - as & ~! They really only make sense if the enum is being used to implement a bitmapped set, where '+ means "add elements to the set", and - means "remove elements from the set".) In addition, the op= assignment operators are generated for each of the binary operator.

By default, all of the operators are generated in the same namespace as the enum, so they will be found by argument dependant name lookup.

OPTIONS

The following options are supported:

-M
Generate the specializations for the mapping functions.
-I
Generate the incrementation and decrementation operators
-m
Use modulo artithmetic in the increment and decrement operators, rather than asserting no overflow. (Only relevant wit the -I option.)
-B
Generate the bitwise operators
-a
Generate overloads for the bitwise operators using the additive operators, for correct precedence. This option is ignored unless -B has also been given.
-n
No namespaces, but all generated operators in the global namespace. (The specializations of Gabi::map still go into the Gabi namespace; specialization doesn't work otherwise.) If this option is used, the operators will not be found in template instantiations.
-c source_suffix
The extention to use for generated source files (default .cc).
-h header_suffix
The extention to use for generated header files (default .hh).
-t type
The underlying type to be used for the bitwise operations. This defaults to unsigned long, which should work in all cases, but may result in less optimal code than something smaler on some machines.

OPERANDS

The following operands are supported:

file
A pathname of an input file. (Note that at least one file operand must be given. The program will not read from standard in, since it generates several different files from its input, and derives their names from the input filename.)

EXIT STATUS

0 no error.
2 One of the input files could not be opened.
3 Hardware error on standard out or read error on input.

BUGS

The -t option is a hack, but I don't know of any way of figuring out the actual underlying type without parsing all of the C++.

It would be nice if the generated code weren't so dependant on the library. (But then, what should I use to replace Fallible?)

The parser is extremely simplisitic, and can easily get confused. It's best to only feed it code which has actually compiled without errors. It also is totally unaware of templates, which means that the code it generates for an enum in a template class will be unusable. And it ignores all pre-processor declarations; any use of the preprocessor, or macros which modify syntax, within an enum definition will confuse beyond hope.