|
i |
|
This is a collection of issues that have come up
and some approaches to solving them.
As I collect more, I'll add some organization, too.
| Question: |
1. | How can I keep the option version consistent with configure?
|
2. | Are there any Finite State Machine examples?
|
3. | Does it work on OS/X?
|
4. | Is there a sample project that uses AutoGen and/or AutoOpts?
|
5. | Can I call optionProcess a second time
with different arguments?
It seems the parser works only once. |
6. | Are option name words separated with '-' or '_'?
|
7. | Why doesn't AutoOpts handle floating point option arguments?
|
8. | How can I create varied combinations and permutations?
After banging my head on a wall with C++ templates and related
compiler incompatibilities I found AutoGen. I have done
RTFM...but I haven't found a straightforward way to generate
combinations/permutations.
An example: implementing routines for graphics composition where
parameters can be either bitmaps or constant colors.
process( bitmap*, bitmap*, bitmap*, bitmap* ); // Bitmap only form
...
process( color, bitmap*, color, color ); // mixed bitmaps and colors
...
process( color, color, color, color ); // all colors
You could do this in the definition file [by laboriously enumerating
the various possibilities, but that does not seem to buy you
anything.]
Any tips? |
How can I keep the option version consistent with configure?
There are several possible approaches. Well, lots of approaches, but
I'll enumerate a few here:
AutoGen definitions can derive their string value from the output of a
shell script. Therefore, you can grep and sed
the `configure.ac' file.
`configure' (`configure.ac') is just a shell script, too.
It can run a script whose purpose is to echo out the version,
so both `configure' and AutoGen can easily use
the same script.
You can make an `configure.ac.tpl' template and generate
`configure.ac' from AutoGen. This would mean, however,
you could not run configure before this.
You can make a `version.def.in' file and create
`version.def' when you run configure. Likewise, this would
mean you would have to configure the product before generating any
files that needed the version from `version.def'.
Are there any Finite State Machine examples?
There is the FSM example page itself, but AutoGen also uses three finite state machines:
agen5/cgi.def | | produces cgi-fsm.c and cgi-fsm.h. These are used to scan CGI script values for conversion into AutoGen definitions. |
pseudo.def | | produces pseudo-fsm.h, which is used in the file loadPseudo.c. That FSM does not produce any code. The table produced is used to parse the pseudo macro at the start of a template. |
defParse.def | | produces defParse-fsm.c and defParse-fsm.h. This code drives the parsing of the definition files. |
Does it work on OS/X?
It should now. Further, the fink project has a package for it.
Is there a sample project that uses AutoGen and/or AutoOpts?
There is now a sample project, blocksort.
This sample integrates the redistributable libopts library source.
For most users, this is likely too much work.
For simple, locally built projects, this is likely to be sufficient:
In your project directory create the option definition file:
``projopts.def'', per instructions in the manual.
Add to Makefile.am (or Makefile):
projopts.c projopts.h : opts-stamp
opts-stamp : projopts.def
autogen projopts.def && touch $@
project.1 : projopts.def
autogen -Tagman1.tpl -b project projopts.def
projinvoke.texi : projopts.def project
autogen -Taginfo.tpl -bprojinvoke -DLEVEL=section projopts.def
And add ``-I${prefix}/include'' to your compiles and
``-L${prefix}/lib -lopts'' to your link, where
``${prefix}'' is the autogen installation prefix.
If you use autoconf and automake, this can be done in an automated
fashion. Place the distributed file "autoopts.m4" in your configure
directory. In your configure.ac file, invoke the AG_PATH_AUTOOPTS macro.
Now back to your Makefile.am. Use the following substitution
values for your compile and link commands.
$(AUTOOPTS_CFLAGS)
$(AUTOOPTS_LDFLAGS)
Can I call optionProcess a second time
with different arguments?
You can parse the options multiple times. First, before calling
optionProcess, call optionSaveState. Then, before calling optionProcess the second time, call optionRestore.
Are option name words separated with '-' or '_'?
Either. Option names are case insensitive and the word separators
can be any of the three characters '-', '_' and even '^'.
(I worked at Tandem for a while.) Consequently, all of these
are equivalent:
--Fumble-bumble
--fumble_Bumble
--Fumble^Bumble
Of course, the leading hyphens must be hyphens.
Why doesn't AutoOpts handle floating point option arguments?
Because handling it yourself is trivial, handling it in a fully
integrated fashion is hard and I don't use floating point myself.
That's the short answer. Here are the details for the first
two parts:
Write your own callback routine.
flag = {
name = something;
value = s;
arg-type = string;
arg-name = float;
descrip = "floating point argument";
doc = "Example of an option with a floating point arg.";
flag-code = <<- EOF
extern double val;
sscanf( pOptDesc->pzLastArg, "%f", &val );
if (validations_fail) {
fprintf( stderr, "bad float for 'something'\n" );
USAGE( EXIT_FAILURE );
}
EOF ;
};
Provide a patch to extend the arg-type handling. :-)
You would probably need to fiddle with the various opt*.tpl files
and the documentation templates (agman1.tpl and aginfo.tpl) and you
would need to add a bit flag to the option descriptor flag bits and
worry about how to save the data (save.c) and even how to keep the
data (since floating point numbers do not fit in void*/char*
buckets).
This would be a fair bit of work, but it would be very nice to have.
I don't use floating point myself (or it would already be done).
The do-it-yourself solution is pretty easy, but, if
you do do this and get it working (or even mostly working), I'll
accept the patch and add first-class support for floating point
option arguments.
How can I create varied combinations and permutations?
cat > process.tpl <<_EOF_
[+ autogen5 template h +]
[+ FOR arg1 in "bitmap*" color \+]
[+ FOR arg2 in "bitmap*" color \+]
[+ FOR arg3 IN "bitmap*" color
+]process( [+arg1+], [+arg2+], [+arg3+] );
[+ ENDFOR \+]
[+ ENDFOR \+]
[+ ENDFOR \+]
_EOF_
autogen -b process --no-defin -Tprocess.tpl
And you wind up with this process.h file:
process( bitmap*, bitmap*, bitmap* );
process( bitmap*, bitmap*, color );
process( bitmap*, color, bitmap* );
process( bitmap*, color, color );
process( color, bitmap*, bitmap* );
process( color, bitmap*, color );
process( color, color, bitmap* );
process( color, color, color );
I'll also take a guess that you would want a similar nested set of
loops for the method implementation code that would convert their
color args to bit maps and invoke the canonical method:
process(bitmap*, bitmap*, bitmap*)
That implementation code can be generated, too.
process(color a, bitmap* b, color c) {
return process( color2bits(a), b, color2bits(c));
}
|