Fixed build with HWASan
[platform/upstream/autogen.git] / doc / auto-opts.tlib
1 [= -*- Mode: texinfo -*-
2
3  AutoGen5 Template
4
5 #  This file is part of AutoGen.
6 #  AutoGen Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
7 #
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.
12 #
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.
17 #
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/>.
20 =]
21
22 @page
23 @node AutoOpts
24 @chapter Automated Option Processing
25 @cindex autoopts
26
27 AutoOpts [=
28 (make-tmp-dir)
29 (out-push-new)
30 =]
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"
36 readonly ag_cmd
37
38 run_ag() {
39     echo ${ag_cmd} "$@" >&2
40     ${ag_cmd} "$@"
41 }
42
43 eval "`egrep '^AO_[A-Z]*=' ${top_srcdir}/VERSION`" 2> /dev/null
44 echo ${AO_CURRENT}.${AO_REVISION}
45 [=
46
47 (shell (out-pop #t))
48
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
55 program as well.
56 [=
57
58 INVOKE  get-text tag = autoopts  =][=
59 (out-push-new (string-append tmp-dir "/check.def" ))
60
61 =]
62 AutoGen Definitions options;
63 prog-name     = check;
64 prog-title    = "Checkout Automated Options";
65 long-opts;
66 gnu-usage;    /* GNU style preferred to default */
67
68 main = { main-type = shell-process; };
69
70 flag = {
71     name      = check-dirs;
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".';
78 };
79
80 flag = {
81     name      = show_defs;
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.';
86 };
87 [= (texi-escape-encode (out-pop #t)) \=]
88 @end example
89
90 @node quick ao build
91 @subsection Build the example options
92
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:[= #
96
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
100 =]
101 @example
102 [=
103
104 (out-push-new (string-append tmp-dir "/mk-check.sh" ))
105
106 \=]
107 base=check
108 BASE=`echo $base | tr '[a-z-]' '[A-Z_]'`
109 cflags="-DTEST_${BASE} `autoopts-config cflags`"
110 ldflags="`autoopts-config ldflags`"
111 autogen ${base}.def
112 cc -o ${base} -g ${cflags} ${base}.c ${ldflags}
113 ./${base} --help
114 [= (texi-escape-encode (out-pop #t)) \=]
115 @end example
116
117 @node quick ao help
118 @subsection Example option help text
119
120 Running the build commands yields:
121
122 @example
123 [= (out-push-new) \=]
124 base=check
125 cd ${tmp_dir}
126 (
127   PS4='>ck> '
128   BASH_XTRACEFD=2
129   exec 2> ${base}-msg.log 1>&2
130   set -x
131
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}
140
141   . ./mk-${base}
142 )
143 test -x ./${base} || {
144   cat mk-${base}
145   printf '\n\nFAILURE LOG:\n\n'
146   cat ${base}-msg.log
147   tar czf /tmp/ck-fail.tgz .
148   die cannot create ${base} program
149 } >&2
150
151 ./${base} --help | sed 's/\t/        /g'
152 [=
153
154 (texi-escape-encode (shell (out-pop #t)))
155
156 =]
157 @end example
158 [=
159
160 INVOKE  get-text tag = autoopts-main
161
162 =]
163 Here is an example program that uses the following set of definitions:
164
165 @example
166 [=
167
168  (out-push-new (string-append tmp-dir "/default-test.def" ))
169
170 =]AutoGen Definitions options;
171
172 prog-name  = default-test;
173 prog-title = 'Default Option Example';
174 homerc     = '$$/../share/default-test', '$HOME', '.';
175 environrc;
176 long-opts;
177 gnu-usage;
178 usage-opt;
179 version    = '1.0';
180 main = {
181   main-type = shell-process;
182 };
183 #define DEBUG_FLAG
184 #define WARN_FLAG
185 #define WARN_LEVEL
186 #define VERBOSE_FLAG
187 #define VERBOSE_ENUM
188 #define DRY_RUN_FLAG
189 #define OUTPUT_FLAG
190 #define INPUT_FLAG
191 #define DIRECTORY_FLAG
192 #define INTERACTIVE_FLAG
193 #include stdoptions.def
194 [=
195
196  (texi-escape-encode (out-pop #t))
197
198 =]@end example
199
200 @noindent
201 Running a few simple commands on that definition file:
202
203 @example
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@}
208 @end example
209
210 @noindent
211 Yields a program which, when run with @file{--help}, prints out:
212
213 @example
214 [= (out-push-new) \=]
215 set -x
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
220
221 {
222   cd ${tmp_dir}
223   chmod 666 *.def
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'
227
228   opts="-o default-test -DTEST_DEFAULT_TEST_OPTS ${INCLUDES}"
229   ${CC:-cc} ${CFLAGS} ${opts} default-test.c ${LIBS} || \
230     rm -f ./default-test
231
232   test -x ./default-test || {
233     exec 2>&7
234     fail_text=`cat $log_file`$'\n\nprogram:\n'`cat default-test.c`
235     die 'NO default-test EXECUTABLE
236         '"$fail_text"'
237         === END FAIL TEXT'
238   }
239 } >&2
240
241 HOME=${tmp_dir} ${tmp_dir}/default-test --help | \
242    sed 's,      ,        ,g;s,\([@{}]\),@\1,g'
243
244 exec 2>&7 7>&-
245 [=
246  (shell (out-pop #t))
247 =]
248 @end example
249 [=
250
251 INVOKE  get-text tag = autoopts-api
252
253 =]
254 [=`
255
256 f=../autoopts/libopts.texi
257 test -f $f || {
258   f=${top_srcdir}/autoopts/libopts.texi
259   test -f $f || die "Cannot locate libopts.texi in $f"
260 }
261 cat $f
262
263 `=]
264 [=
265
266 INVOKE  get-text tag = "autoopts-data"
267
268 =]
269 @noindent
270 Doing so with getdefs' option definitions yields this sample-getdefsrc file.
271 I tend to be wordy in my @code{doc} attributes:
272
273 @example
274 [= (texi-escape-encode (shell "
275   cd ${tmp_dir}
276   run_ag -Trc-sample.tpl ${top_srcdir}/getdefs/opts.def >/dev/null
277   test -f sample-getdefsrc || die did not create sample-getdefsrc
278   cat sample-getdefsrc
279 " )) =]
280 @end example
281 [=
282
283 INVOKE get-text tag = "ao-data1"
284
285 =]
286 @example[=
287 (out-push-new (string-append tmp-dir "/hello.c"))
288
289 \=]
290
291 #include <config.h>
292 #include <sys/types.h>
293 #include <stdio.h>
294 #include <pwd.h>
295 #include <string.h>
296 #ifdef   HAVE_UNISTD_H
297 #include <unistd.h>
298 #endif
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");
304
305   if (pOV != NULL) {
306     const tOptionValue* pGetV = optionGetValue(pOV, "greeting");
307
308     if (  (pGetV != NULL)
309        && (pGetV->valType == OPARG_TYPE_STRING))
310       greeting = strdup(pGetV->v.strVal);
311
312     pGetV = optionGetValue(pOV, "personalize");
313     if (pGetV != NULL) {
314       struct passwd * pwe = getpwuid(getuid());
315       if (pwe != NULL)
316         greeted = strdup(pwe->pw_gecos);
317     }
318
319     optionUnloadNested(pOV); /* deallocate config data */
320   }
321   printf("%s, %s!\n", greeting, greeted);
322   return 0;
323 }
324 [= (texi-escape-encode (out-pop #t)) \=]
325 @end example
326
327 @noindent
328 With that text in a file named ``hello.c'', this short script:
329
330 @example
331 cc -o hello hello.c `autoopts-config cflags ldflags`
332 ./hello
333 echo 'greeting Buzz off' > hello.conf
334 ./hello
335 echo personalize > hello.conf
336 ./hello
337 @end example
338
339 @noindent
340 will produce the following output:
341
342 @example
343 [= (texi-escape-encode (shell "
344 cd ${tmp_dir}
345 ${CC:-cc} -o hello hello.c ${CFLAGS} ${LIBS} ${LDFLAGS} || \
346   die cannot compile hello
347 ./hello
348 echo 'greeting Buzz off' > hello.conf
349 ./hello
350 echo personalize > hello.conf
351 ./hello"
352 )) =]
353 @end example
354 [=
355
356 INVOKE  get-text tag = "ao-data2"
357
358 =]
359 [=
360
361  (out-push-new)
362
363 =](
364     exec 4>&2 2> ${tmp_dir}/err-test-log.txt
365     BASH_XTRACEFD=2
366     PS4='>etl> '
367     set -x
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
374     then
375       exec 2>&4
376       cat ${tmp_dir}/err-test-log.txt >&2
377       die "no error usage in $PWD/errors-testd"
378     fi
379     cat <<-EOF
380
381         Here is the usage output example from AutoOpts error handling
382         tests.  The option definition has argument reordering enabled:
383
384         @example
385 EOF
386
387     ./errors-testd/errors -? | sed 's,  ,        ,g;s,\([@{}]\),@\1,g'
388     cmd='errors operand1 -s first operand2 -X -- -s operand3'
389     cat <<-EOF
390         @end example
391
392         Using the invocation,
393         @example
394           test-${cmd}
395         @end example
396         you get the following output for your shell script to evaluate:
397
398         @example
399         `./errors-testd/${cmd}`
400         @end example
401 EOF
402 )[=
403
404 (shell (out-pop #t))
405
406 =]
407 @node script-parser
408 @subsection Parsing with a Portable Script
409
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:
417
418 @example
419 [= `
420
421 log=${tmp_dir}/../genshellopt.log
422
423 (
424   set -x
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
430   exec 3>&-
431
432   cd ${tmp_dir}
433   HOME='' run_ag -t40 genshellopt.def
434   test $? -eq 0 || die "autogen failed to create genshellopt.c - See ${log}"
435
436   ${CC} ${CFLAGS} ${opts} genshellopt.c ${LIBS}
437   test $? -eq 0 || {
438     head -n 50000 genshellopt.[ch]
439     die "could not compile genshellopt.c - See ${log}"
440   }
441 ) > ${log} 2>&1
442
443 test -x ${tmp_dir}/genshellopt || \
444   die "NO GENSHELLOPT PROGRAM - See ${log}"
445
446 ${tmp_dir}/genshellopt --help > ${tmp_dir}/genshellopt.hlp
447
448 ${tmp_dir}/genshellopt -o ${tmp_dir}/genshellopt.sh || \
449   die cannot create ${tmp_dir}/genshellopt.sh
450
451 sedcmd='s,\t,        ,g;s,\\([@{}]\\),@\\1,g'
452 sed "${sedcmd}" ${tmp_dir}/genshellopt.hlp
453 cat <<- \_EOF_
454         @end example
455
456         @noindent
457         Resulting in the following script:
458         @example
459         _EOF_
460
461 sed "${sedcmd}" ${tmp_dir}/genshellopt.sh
462
463 ` =]
464 @end example
465 [=
466
467 INVOKE  get-text tag = autoinfo
468
469 =]