1 [= -*- Mode: texinfo -*-
5 # This file is part of AutoGen.
6 # AutoGen Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
8 # AutoGen is free software: you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by the
10 # Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # AutoGen is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 # See the GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License along
19 # with this program. If not, see <http://www.gnu.org/licenses/>.
24 @chapter Automated Option Processing
31 test ${#AGexe} -eq 0 -o ${#top_srcdir} -eq 0 -o ${top_builddir} -eq 0 && \
32 die "AGexe, top_srcdir and top_builddir must be set"
33 ag_cmd="${AGexe} -L${top_srcdir}/autoopts/tpl"
34 test "X${top_srcdir}" = "X${top_builddir}" || \
35 ag_cmd="${ag_cmd} -L${top_builddir}/autoopts/tpl"
39 echo ${ag_cmd} "$@" >&2
43 eval "`egrep '^AO_[A-Z]*=' ${top_srcdir}/VERSION`" 2> /dev/null
44 echo ${AO_CURRENT}.${AO_REVISION}
49 =] is bundled with AutoGen. It is a tool that virtually eliminates the
50 hassle of processing options and keeping man pages, info docs and usage text
51 up to date. This package allows you to specify several program attributes,
52 thousands of option types and many option attributes. From this, it then
53 produces all the code necessary to parse and handle the command line and
54 configuration file options, and the documentation that should go with your
58 INVOKE get-text tag = autoopts =][=
59 (out-push-new (string-append tmp-dir "/check.def" ))
62 AutoGen Definitions options;
64 prog-title = "Checkout Automated Options";
66 gnu-usage; /* GNU style preferred to default */
68 main = { main-type = shell-process; };
72 value = L; /* flag style option character */
73 arg-type = string; /* option argument indication */
74 max = NOLIMIT; /* occurrence limit (none) */
75 stack-arg; /* save opt args in a stack */
76 descrip = "Checkout directory list";
77 doc = 'name of each directory that is to be "checked out".';
82 descrip = "Show the definition tree";
83 disable = dont; /* mark as enable/disable type */
84 /* option. Disable as `dont-' */
85 doc = 'disable, if you do not want to see the tree.';
87 [= (texi-escape-encode (out-pop #t)) \=]
91 @subsection Build the example options
93 This program will produce a program that digests its options and
94 writes the values as shell script code to stdout.
95 Run the following short script to produce this program:[= #
97 Developer note: the following only works when AutoGen has been installed.
98 Since this may be being built on a system where it has not been installed,
99 the code below ensures we are running out tools out of the build directory
104 (out-push-new (string-append tmp-dir "/mk-check.sh" ))
108 BASE=`echo $base | tr '[a-z-]' '[A-Z_]'`
109 cflags="-DTEST_${BASE} `autoopts-config cflags`"
110 ldflags="`autoopts-config ldflags`"
112 cc -o ${base} -g ${cflags} ${base}.c ${ldflags}
114 [= (texi-escape-encode (out-pop #t)) \=]
118 @subsection Example option help text
120 Running the build commands yields:
123 [= (out-push-new) \=]
129 exec 2> ${base}-msg.log 1>&2
132 test -f ${base}.def || die "cannot locate ${base}.def"
133 test ! -f ${base} || rm -f ${base}
134 echo "include = '#include \"compat/compat.h\"';" >> ${base}.def
135 f='@="@="'`echo ${INCLUDES} ${CFLAGS}`' @'
136 sed -e "s@^cc @${CC:-cc} -include ${top_builddir}/config.h @" \
137 -e '/^cflags="/s'"${f}" \
138 -e 's@^autogen @run_ag @' \
139 mk-${base}.sh > mk-${base}
143 test -x ./${base} || {
145 printf '\n\nFAILURE LOG:\n\n'
147 tar czf /tmp/ck-fail.tgz .
148 die cannot create ${base} program
151 ./${base} --help | sed 's/\t/ /g'
154 (texi-escape-encode (shell (out-pop #t)))
160 INVOKE get-text tag = autoopts-main
163 Here is an example program that uses the following set of definitions:
168 (out-push-new (string-append tmp-dir "/default-test.def" ))
170 =]AutoGen Definitions options;
172 prog-name = default-test;
173 prog-title = 'Default Option Example';
174 homerc = '$$/../share/default-test', '$HOME', '.';
181 main-type = shell-process;
191 #define DIRECTORY_FLAG
192 #define INTERACTIVE_FLAG
193 #include stdoptions.def
196 (texi-escape-encode (out-pop #t))
201 Running a few simple commands on that definition file:
204 autogen default-test.def
205 copts="-DTEST_DEFAULT_TEST_OPTS `autoopts-config cflags`"
206 lopts="`autoopts-config ldflags`"
207 cc -o default-test $@{copts@} default-test.c $@{lopts@}
211 Yields a program which, when run with @file{--help}, prints out:
214 [= (out-push-new) \=]
216 log_file=${tmp_dir}/ao-doc-log
217 exec 7>&2 ; exec 2>> ${log_file}
218 TOPDIR=`cd ${top_builddir} >/dev/null ; pwd`
219 OPTDIR=${TOPDIR}/autoopts
224 echo 'config-header = "config.h";' >> default-test.def
225 HOME=${tmp_dir} run_ag default-test.def
226 test -f default-test.c || die 'NO default-test.c PROGRAM'
228 opts="-o default-test -DTEST_DEFAULT_TEST_OPTS ${INCLUDES}"
229 ${CC:-cc} ${CFLAGS} ${opts} default-test.c ${LIBS} || \
232 test -x ./default-test || {
234 fail_text=`cat $log_file`$'\n\nprogram:\n'`cat default-test.c`
235 die 'NO default-test EXECUTABLE
241 HOME=${tmp_dir} ${tmp_dir}/default-test --help | \
242 sed 's, , ,g;s,\([@{}]\),@\1,g'
251 INVOKE get-text tag = autoopts-api
256 f=../autoopts/libopts.texi
258 f=${top_srcdir}/autoopts/libopts.texi
259 test -f $f || die "Cannot locate libopts.texi in $f"
266 INVOKE get-text tag = "autoopts-data"
270 Doing so with getdefs' option definitions yields this sample-getdefsrc file.
271 I tend to be wordy in my @code{doc} attributes:
274 [= (texi-escape-encode (shell "
276 run_ag -Trc-sample.tpl ${top_srcdir}/getdefs/opts.def >/dev/null
277 test -f sample-getdefsrc || die did not create sample-getdefsrc
283 INVOKE get-text tag = "ao-data1"
287 (out-push-new (string-append tmp-dir "/hello.c"))
292 #include <sys/types.h>
299 #include <autoopts/options.h>
300 int main(int argc, char ** argv) {
301 char const * greeting = "Hello";
302 char const * greeted = "World";
303 tOptionValue const * pOV = configFileLoad("hello.conf");
306 const tOptionValue* pGetV = optionGetValue(pOV, "greeting");
309 && (pGetV->valType == OPARG_TYPE_STRING))
310 greeting = strdup(pGetV->v.strVal);
312 pGetV = optionGetValue(pOV, "personalize");
314 struct passwd * pwe = getpwuid(getuid());
316 greeted = strdup(pwe->pw_gecos);
319 optionUnloadNested(pOV); /* deallocate config data */
321 printf("%s, %s!\n", greeting, greeted);
324 [= (texi-escape-encode (out-pop #t)) \=]
328 With that text in a file named ``hello.c'', this short script:
331 cc -o hello hello.c `autoopts-config cflags ldflags`
333 echo 'greeting Buzz off' > hello.conf
335 echo personalize > hello.conf
340 will produce the following output:
343 [= (texi-escape-encode (shell "
345 ${CC:-cc} -o hello hello.c ${CFLAGS} ${LIBS} ${LDFLAGS} || \
346 die cannot compile hello
348 echo 'greeting Buzz off' > hello.conf
350 echo personalize > hello.conf
356 INVOKE get-text tag = "ao-data2"
364 exec 4>&2 2> ${tmp_dir}/err-test-log.txt
368 cd ${top_builddir}/autoopts/test || \
369 die "cannot cd into ${top_builddir}/autoopts/test"
370 VERBOSE=true AUTOGEN_TRACE=every AUTOGEN_TRACE_OUT=">>$PWD/ag-log.txt"
371 export VERBOSE AUTOGEN_TRACE AUTOGEN_TRACE_OUT
372 ${MAKE:-make} check TESTS=errors.test 1>&2 || :
373 if test ! -x errors-testd/errors
376 cat ${tmp_dir}/err-test-log.txt >&2
377 die "no error usage in $PWD/errors-testd"
381 Here is the usage output example from AutoOpts error handling
382 tests. The option definition has argument reordering enabled:
387 ./errors-testd/errors -? | sed 's, , ,g;s,\([@{}]\),@\1,g'
388 cmd='errors operand1 -s first operand2 -X -- -s operand3'
392 Using the invocation,
396 you get the following output for your shell script to evaluate:
399 `./errors-testd/${cmd}`
408 @subsection Parsing with a Portable Script
410 If you had used @code{test-main = optionParseShell} instead, then you can,
411 at this point, merely run the program and it will write the parsing
412 script to standard out. You may also provide this program with command
413 line options to specify the shell script file to create or edit, and you
414 may specify the shell program to use on the first shell script line.
415 That program's usage text would look something like the following
416 and the script parser itself would be very verbose:
421 log=${tmp_dir}/../genshellopt.log
425 opts="-o genshellopt -DTEST_GETDEFS_OPTS ${INCLUDES}"
426 exec 3> ${tmp_dir}/genshellopt.def
427 cat ${top_srcdir}/getdefs/opts.def >&3
428 echo "test_main = 'optionParseShell';" >&3
429 echo 'config-header = "config.h";' >&3
433 HOME='' run_ag -t40 genshellopt.def
434 test $? -eq 0 || die "autogen failed to create genshellopt.c - See ${log}"
436 ${CC} ${CFLAGS} ${opts} genshellopt.c ${LIBS}
438 head -n 50000 genshellopt.[ch]
439 die "could not compile genshellopt.c - See ${log}"
443 test -x ${tmp_dir}/genshellopt || \
444 die "NO GENSHELLOPT PROGRAM - See ${log}"
446 ${tmp_dir}/genshellopt --help > ${tmp_dir}/genshellopt.hlp
448 ${tmp_dir}/genshellopt -o ${tmp_dir}/genshellopt.sh || \
449 die cannot create ${tmp_dir}/genshellopt.sh
451 sedcmd='s,\t, ,g;s,\\([@{}]\\),@\\1,g'
452 sed "${sedcmd}" ${tmp_dir}/genshellopt.hlp
457 Resulting in the following script:
461 sed "${sedcmd}" ${tmp_dir}/genshellopt.sh
467 INVOKE get-text tag = autoinfo