File: C:/Ruby27-x64/msys64/usr/share/autogen/optmain.tlib
[= AutoGen5 Template -*- Mode: C -*-
## This file is part of AutoOpts, a companion to AutoGen.
## AutoOpts is free software.
## AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
##
## AutoOpts is available under any one of two licenses. The license
## in use must be one of these two and the choice is under the control
## of the user of the license.
##
## The GNU Lesser General Public License, version 3 or later
## See the files "COPYING.lgplv3" and "COPYING.gplv3"
##
## The Modified Berkeley Software Distribution License
## See the file "COPYING.mbsd"
##
## These files have the following sha256 sums:
##
## 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
## 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
## 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
=][=
(out-push-new) =]
ck_flag_code() {
addon_txt=''
txt1=`[=(. grep-prog)=] -w pOptDesc ${tmp_dir}/flag-code`
test -z "$txt1" && addon_txt=' (void)pOptDesc;\n'
txt2=`[=(. grep-prog)=] -w pOptions ${tmp_dir}/flag-code`
test -z "$txt2" && addon_txt=${addon_txt}' (void)pOptions;\n'
cat ${tmp_dir}/flag-code
test -z "$addon_txt" || printf "\n$addon_txt"
rm -f ${tmp_dir}/flag-code
}[=
(shell (out-pop #t)) =][=
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
BUILD TEST MAIN
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE build-test-main =][=
IF (emit (tpl-file-line extract-fmt))
(define end-test-main-guard "")
guarded-test-main
=]
#if defined([=(set! end-test-main-guard (string-append
"\n#endif /* " main-guard " END-TEST-MAIN-PROCEDURE */"))
main-guard=]) /* TEST-MAIN-PROCEDURE: */[=
ENDIF guarded-test-main =][=
IF (= (get "test-main") "optionParseShell")
=]
extern tOptions genshelloptOptions;
extern void optionParseShell(tOptions*);
extern tOptions* optionParseShellOptions;[=
ELIF (not (exist? "main-text")) =][=
(define option-emitter-proc (get "test-main"))
(if (<= (string-length option-emitter-proc) 3)
(set! option-emitter-proc "optionPutShell"))
=]
extern void [= (. option-emitter-proc) =](tOptions*);[=
ENDIF
=]
/**
* Generated main procedure. This will emit text that a Bourne shell can
* process to handle its command line arguments.
*
* @param[in] argc argument count
* @param[in] argv argument vector
* @returns program exit code
*/
int
main(int argc, char ** argv)
{
int res = [=(. succ-exit-code)=];[=
IF (= (get "test-main") "optionParseShell") =]
/*
* Stash a pointer to the options we are generating.
* `genshellUsage()' will use it.
*/
optionParseShellOptions = &[=(. pname)=]Options;
(void)optionProcess(&genshelloptOptions, argc, argv);
optionParseShell(&[=(. pname)=]Options);[=
ELSE =][=
INVOKE emit-option-code =][=
INVOKE emit-main-text =][=
ENDIF =]
return res;
}[=(. end-test-main-guard) =][=
ENDDEF build-test-main
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
BUILD FOR-EACH MAIN
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE for-each-main =][=
(if (not (==* (get "argument") "[" ))
(error "command line arguments must be optional for a 'for-each' main"))
(if (not (exist? "handler-proc"))
(error "'for-each' mains require a handler proc") )
(define handler-arg-type "")
(tpl-file-line extract-fmt) =][=
INVOKE emit-handler-proc =][=
IF (exist? "handler-type") =][=
INVOKE emit-file-dispatcher =][=
ENDIF handler-type exists =][=
(tpl-file-line extract-fmt)
=][=
IF (not (exist? "stdin-input")) =][=
INVOKE emit-trim-input =][=
ENDIF
=]
/**
* Generated main procedure. This will call the [=(. handler-proc)=] procedure
* for every operand on the command line. If there are no operands, then stdin
* is read for a list of file names to process. stdin must not be a terminal.
* It must be a pipe or a file.
*
* @param[in] argc argument count
* @param[in] argv argument vector
* @returns program exit code
*/
int
main(int argc, char ** argv)
{
int res = 0;
int proc_ct = 0;
int arg_ix = optionProcess(&[=(. pname)=]Options, argc, argv);[=
(if (exist? "main-init") (string-append
"\n " (def-file-line "main-init" extract-fmt) "\n" (get "main-init")))
=][= (tpl-file-line extract-fmt) =]
/*
* IF the input list is from the command line...
*/
if (arg_ix < argc) {
for (; arg_ix < argc; arg_ix++) {
char * arg = argv[arg_ix];[=
IF (exist? "interleaved") =]
if (*arg == '-') {
RESTART_OPT(arg_ix);
arg_ix = optionProcess(&[=(. pname)=]Options, argc, argv) - 1;
continue;
}[=
ENDIF interleaved =]
res |= [= (. handler-proc) =](arg);
proc_ct++;
}[=
IF (exist? "interleaved") =]
if (proc_ct == 0)
fputs(_("[=(. prog-name)
=] Warning: no command operands were processed\n"), stderr);[=
ENDIF interleaved =]
}[=
IF (exist? "stdin-input") =][=
INVOKE stdin-as-input =][=
ELSE =][=
INVOKE files-from-stdin =][=
ENDIF =][=
(if (exist? "main-fini") (string-append
"\n " (def-file-line "main-fini" extract-fmt) "\n" (get "main-fini")))
=]
return res;
}[=
ENDDEF for-each-main
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-file-dispatcher =][=
(tpl-file-line extract-fmt) =]
/**
* validate file name and dispach callout procedure.
* This procedure is generated by AutoOpts.
* It will make sure that the input file name refers to a file[=
CASE handler-type =][=
=* name =]
* that exists.[=
=* file =]
* that exists and has been opened for [=
CASE
(define open-mode (shellf "echo '%s' | sed 's/.*-//'"
(get "handler-type")))
open-mode =][=
*~~* '[rwa]\+' =]reading and writing[=
*~~* [wa] =]writing[=
*~~* r =]reading[=
ESAC =].[=
*=* text =]
* that has been read into memory as text.[=
ESAC =]
*
* @param fname the name of the file to process
* @returns program exit code flag
*/
static [=
(define emit-failing-printf (not (= (get "file-fail-code") "success")))
pname-down =]_exit_code_t
validate_fname(char const * fname)
{
static char const * err_str = NULL;[=
IF (*=* (get "handler-type") "text") =]
char* file_text;
size_t text_size;
int res;[=
ENDIF =]
if (err_str == NULL)
err_str = _("fs error %d (%s) %s-ing %s\n");[=
IF (== (get "handler-type") "file-r") =]
if ((fname[0] == '-') && (fname[1] == '\0'))
return [= handler-proc =](_("standard input"), stdin);[=
ENDIF file-r handler type =]
{
struct stat sb;
if (stat(fname, &sb) < 0) {[=
IF (. emit-failing-printf) =]
fprintf(stderr, err_str, errno, strerror(errno), "stat",
fname);[=
ENDIF =]
return [= (. file-fail-exit-code) =];
}[=
IF (*=* (get "handler-type") "text") =]
if (! S_ISREG(sb.st_mode)) {[=
IF (. emit-failing-printf) =]
fprintf(stderr, err_str, EINVAL, strerror(EINVAL),
_("not regular file:"), fname);[=
ENDIF =]
return [= (. file-fail-exit-code) =];
}[=
IF (=* (get "handler-type") "some-text") =]
if (sb.st_size == 0) {[=
IF (. emit-failing-printf) =]
fprintf(stderr, err_str, EINVAL, strerror(EINVAL),
_("empty file:"), fname);[=
ENDIF =]
return [= (. file-fail-exit-code) =];
}[=
ENDIF =]
text_size = sb.st_size;[=
ENDIF =]
}[=
CASE handler-type =][=
=* name =][= (tpl-file-line extract-fmt) =]
return [= handler-proc =](fname);[=
=* file =][= (tpl-file-line extract-fmt) =]
{
int res;
FILE* fp = fopen(fname, "[=
(shellf "echo '%s' | sed 's/.*-//'"
(get "handler-type")) =]");
if (fp == NULL) {
fprintf(stderr, err_str, errno, strerror(errno), "fopen",
fname);
return [= (. file-fail-exit-code) =];
}
res = [= handler-proc =](fname, fp);
fclose(fp);
return res;
}[=
*=* text =][= (tpl-file-line extract-fmt) =]
file_text = malloc(text_size + 1);
if (file_text == NULL) {
fprintf(stderr, _("cannot allocate %u bytes for %s file text\n"),
(unsigned int)text_size+1, fname);
exit([=(. nomem-exit-code)=]);
}
{
char* pz = file_text;
size_t sz = text_size;
int fd = open(fname, O_RDONLY);
int try_ct = 0;
if (fd < 0) {
fprintf(stderr, err_str, errno, strerror(errno), "open", fname);
free(file_text);
return [= (. file-fail-exit-code) =];
}
while (sz > 0) {
ssize_t rd_ct = read(fd, pz, sz);
/*
* a read count of zero is theoretically okay, but we've already
* checked the file size, so we shoud be reading more.
* For us, a count of zero is an error.
*/
if (rd_ct <= 0) {
/*
* Try retriable errors up to 10 times. Then bomb out.
*/
if ( ((errno == EAGAIN) || (errno == EINTR))
&& (++try_ct < 10) )
continue;
fprintf(stderr, err_str, errno, strerror(errno), "read", fname);
exit([=(. file-fail-exit-code)=]);
}
pz += rd_ct;
sz -= rd_ct;
}
close(fd);
}
/*
* Just in case it is a text file, we have an extra byte to NUL
* terminate the thing.
*/
file_text[ text_size ] = '\0';
res = [= handler-proc =](fname, file_text, text_size);[=
IF (not (exist? "handler-frees")) =]
free(file_text);[=
ENDIF =]
return res;[=
ESAC =]
}[=
ENDDEF emit-file-dispatcher
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE stdin-as-input =][=
IF (=* (get "handler-type") "file-") =]
else
/*
* process standard input as input file
*/
res = [= handler-proc =](_("standard input"), stdin);[=
ELSE =][=
(error "'stdin-input' specified for non-file handler type") =][=
ENDIF =][=
ENDDEF stdin-as-input
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-handler-proc =][=
CASE handler-type =][=
=* name =][= (set! handler-arg-type "char const * fname")
(define handler-proc "validate_fname") =][=
=* file =][=
(set! handler-arg-type "char const * fname, FILE * entry_fp")
(define handler-proc "validate_fname") =][=
*=* text =][=
(set! handler-arg-type
"char const * fname, char * file_text, size_t text_size")
(define handler-proc "validate_fname") =][=
!E =][= (set! handler-arg-type "char const* pz_entry")
(define handler-proc (get "handler-proc")) =][=
* =][= (error) =][=
ESAC =]
[=
IF (set! tmp-text (string-append (get "handler-proc") "-code"))
(exist? tmp-text)
\=]
static int
[= handler-proc =]([=(. handler-arg-type)=])
{
int res = 0;[=
(string-append
(def-file-line tmp-text extract-fmt)
(get tmp-text) ) =]
return res;
}[=
ELSE
\=]
extern int [= handler-proc =]([=(. handler-arg-type)=]);[=
ENDIF
=][=
ENDDEF emit-handler-proc
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-trim-input =]
/**
* strip (destructively) the leading and trailing white space.
* Trailing white space is trimmed with a NUL byte.
* The returned address is that of the first character after the
* leading white space. Characters are not moved.
*
* @param[in,out] pz_s source text pointer
* @returns pointer to the same text buffer, but after skipping over the
* leading white space characters.
*/
static char *
trim_input_line(char * src_str)
{
while ((unsigned int)isspace(*src_str))
src_str++;
{
char * end = src_str + strlen(src_str);
while ((end > src_str) && isspace((unsigned int)end[-1]))
end--;
*end = '\0';
}
switch (*src_str) {
case '\0':[=
(define comment-char (substring (get "comment-char" "#") 0 1))
(if (> (string-length comment-char) 0) (begin
(if (or (== comment-char "\\") (== comment-char "'"))
(set! comment-char (string-append "\\" comment-char)) )
(string-append "\n case '" comment-char "':")
) ) =]
return NULL;
default:
return src_str;
}
}
[=
ENDDEF emit-trim-input
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE files-from-stdin =]
/*
* Input list from tty input
*/
else if (isatty(STDIN_FILENO)) {
fputs(_("[=(. prog-name)=] ERROR: input list is a tty\n"), stderr);
[= (. UP-prefix) =]USAGE([=(. file-fail-exit-code)=]);
/* NOTREACHED */
}
/*
* Input list from a pipe or file or some such
*/
else {
long pg_size = sysconf(_SC_PAGESIZE);
char * buf = malloc((size_t)pg_size);
if (buf == NULL) {
fputs(_("[=(. prog-name)
=] ERROR: no memory for input list\n"), stderr);
return [=(. nomem-exit-code)=];
}
for (;;) {
char * pz = fgets(buf, (ssize_t)pg_size, stdin);
if (pz == NULL)
break;
pz = trim_input_line(pz);
if (pz == NULL)
continue;[=
IF (= (get "handler-type") "file-r") =]
if ((pz[0] == '-') && (pz[1] == '\0'))
continue; /* disallowed when reading operands from stdin */[=
ENDIF file-r handler type =][=
IF (exist? "interleaved") =]
if (*pz == '-') {
optionLoadLine(&[=(. pname)=]Options, pz);
continue;
}[=
ENDIF interleaved =]
res |= [= (. handler-proc) =](pz);
proc_ct++;
}
if (proc_ct == 0)
fputs(_("[=(. prog-name)
=] Warning: no input lines were read\n"), stderr);
free(buf);
}
[=
ENDDEF files-from-stdin
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
BUILD MAIN
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE build-main =][= FOR main[] =][=
CASE main-type =][=
== shell-process =][=
INVOKE build-test-main test-main = "optionPutShell" =][=
== shell-parser =][=
INVOKE build-test-main test-main = "optionParseShell" =][=
== main =][=
INVOKE build-test-main =][=
== include =]
[= INCLUDE tpl =][=
== invoke =][=
INVOKE (get "func") =][=
== for-each =][=
INVOKE for-each-main =][=
* =][=
(error (sprintf "unknown/invalid main-type: '%s'" (get "main-type"))) =][=
ESAC =][= ENDFOR first-main =][=
ENDDEF build-main
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
DECLARE OPTION CALLBACK PROCEDURES
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE decl-callbacks
This is the test for whether or not to emit callback handling code:
=]
/**
* Declare option callback procedures
*/[=
(define undef-proc-names "")
(define decl-type "")
(define extern-proc-list (string-append
(if (exist? "version-proc")
(get "version-proc")
"optionPrintVersion") "\n"
"optionBooleanVal\n"
"optionNestedVal\n"
"optionNumericVal\n"
"optionResetOpt\n"
"optionStackArg\n"
"optionTimeDate\n"
"optionTimeVal\n"
"optionUnstackArg\n"
"optionVendorOption\n"
) )
(define extern-test-list "")
(define emit-decl-list (lambda(txt-var is-extern)
(if (> (string-length txt-var) 1) (begin
(emit (if is-extern "\nextern tOptProc\n" "\nstatic tOptProc\n"))
(set! txt-var (shellf "
(%s -v '^%s$' | sed '/^$/d' | sort -u | \
sed 's@$@,@;$s@,$@;@' ) <<_EOProcs_\n%s_EOProcs_"
egrep-prog
(if is-extern "NULL" "(NULL|optionStackArg|optionUnstackArg)")
txt-var ))
(emit (shellf (if (< (string-length txt-var) 72)
"f='%s' ; echo \" \" $f"
"${CLexe} --spread=1 -I4 <<_EOProcs_\n%s\n_EOProcs_" )
txt-var ))
))
))
(define static-proc-list "doUsageOpt\n")
(define static-test-list static-proc-list)
(define ifdef-fmt (string-append
"\n#if%1$sdef %2$s"
"\n %3$s tOptProc %4$s;"
"\n#else /* not %2$s */"
"\n# define %4$s NULL"
"\n#endif /* def/not %2$s */"))
(define make-proc-decl #t)
(define set-ifdef (lambda(n-or-def ifdef-cb ifdef-name) (begin
(set! decl-type (if (hash-ref is-ext-cb-proc flg-name) "extern" "static"))
(set! make-proc-decl #f)
(ag-fprintf 0 ifdef-fmt n-or-def ifdef-name decl-type ifdef-cb )
)))
(define set-cb-decl (lambda() (begin
(set! make-proc-decl #t)
(set! tmp-val (hash-ref cb-proc-name flg-name))
(if (exist? "ifdef")
(set-ifdef "" tmp-val (get "ifdef"))
(if (exist? "ifndef")
(set-ifdef "n" tmp-val (get "ifndef"))
(if (hash-ref is-ext-cb-proc flg-name)
(set! extern-proc-list (string-append
extern-proc-list tmp-val "\n" ))
(set! static-proc-list (string-append
static-proc-list tmp-val "\n" ))
) ) )
(if guarded-test-main (begin
(set! tmp-val (hash-ref test-proc-name flg-name))
(if (hash-ref is-ext-cb-proc flg-name)
(set! extern-test-list (string-append extern-test-list
tmp-val "\n" ))
(if make-proc-decl
(set! static-test-list
(string-append static-test-list tmp-val "\n") ) ) )
) )
)))
=][=
FOR flag =][=
;; Fill in four strings with names of callout procedures:
;; extern-test-list - external callouts done IFF test main is built
;; static-test-list - static callouts done IFF test main is built
;; extern-proc-list - external callouts for normal compilation
;; static-proc-list - static callouts for normal compilation
;;
;; Anything under the control of "if[n]def" has the declaration or
;; #define to NULL emitted immediately.
;;
(set! flg-name (get "name"))
(if (and (hash-ref have-cb-procs flg-name)
(not (hash-ref is-lib-cb-proc flg-name)) )
(set-cb-decl)
) =][=
ENDFOR flag =][=
IF (. guarded-test-main) =][=
INVOKE emit-testing-defines =][=
ENDIF guarded-test-main =][=
(if (not (exist? "no-libopts"))
(set! extern-proc-list (string-append extern-proc-list
"optionPagedUsage\n")) )
(emit-decl-list extern-proc-list #t)
(emit-decl-list static-proc-list #f)
(set! static-proc-list "") =][=
FOR flag =][=
(set! flg-name (get "name"))
(if (not (= (hash-ref cb-proc-name flg-name)
(hash-ref test-proc-name flg-name)))
(set! static-proc-list (string-append static-proc-list
"#define " (get-up-name "name") "_OPT_PROC "
(hash-ref cb-proc-name flg-name) "\n")) )
=][=
ENDFOR flag =][=
IF (> (string-length static-proc-list) 0) =]
/**
* #define map the "normal" callout procs
*/
[= (. static-proc-list) =][=
ENDIF have some #define mappings
=][=
(if guarded-test-main
(emit "\n#endif /* " main-guard " */") )
undef-proc-names =][=
ENDDEF decl-callbacks
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-testing-defines
=][=
(set! extern-proc-list (string-append extern-proc-list
"optionVersionStderr\n"))
(tpl-file-line extract-fmt) =]
#if defined([=(. main-guard)=])
/*
* Under test, omit argument processing, or call optionStackArg,
* if multiple copies are allowed.
*/[=
(emit-decl-list extern-test-list #t)
(emit-decl-list static-test-list #f)
(set! static-test-list "") =][=
FOR flag =][=
(set! flg-name (get "name"))
(if (not (= (hash-ref cb-proc-name flg-name)
(hash-ref test-proc-name flg-name)))
(set! static-test-list (string-append static-test-list
"#define " (get-up-name "name") "_OPT_PROC "
(hash-ref test-proc-name flg-name) "\n")) )
=][=
ENDFOR flag =][=
IF (> (string-length static-test-list) 0) =]
/*
* #define map the "normal" callout procs to the test ones...
*/
[= (. static-test-list) =][=
ENDIF have some #define mappings
=]
#else /* NOT defined [=(. main-guard)=] */
/*
* When not under test, there are different procs to use
*/[=
ENDDEF emit-testing-defines
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
DEFINE OPTION CALLBACKS
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE callback-proc-header =]
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* Code to handle the [=name=] option[= # */ =][=
IF (exist? "ifdef")
=], when [= ifdef =] is #define-d[=
(define ifdef-text (string-append "\n#ifdef " (get "ifdef")))
(set! endif-test-main (string-append
(sprintf "\n#endif /* defined %s */" (get "ifdef"))
endif-test-main
)) =][=
ELIF (exist? "ifndef")
=], when [= ifndef =] is *not* #define-d[=
(define ifdef-text (string-append "\n#ifndef " (get "ifndef")))
(set! endif-test-main (string-append
(sprintf "\n#endif /* ! defined %s */" (get "ifndef"))
endif-test-main
)) =][=
ELSE unconditional code:
=][= (define ifdef-text "") =][=
ENDIF ifdef / ifndef
=].
[= (prefix " * " (get "doc")) =]
* @param[in] pOptions the [=(. prog-name)=] options data structure
* @param[in,out] pOptDesc the option descriptor for this option.
*/[= (. ifdef-text) =]
static void
doOpt[= (set! endif-test-main (string-append "\n}" endif-test-main))
cap-name =](tOptions* pOptions, tOptDesc* pOptDesc)
{
[=
ENDDEF callback-proc-header
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE reset-clause =][=
(if (exist? "flag-code[0]")
(emit (string-append "\n" (get "flag-code[0]"))))
(if (exist? "resettable") (emit (string-append
"\n if ((pOptDesc->fOptState & OPTST_RESET) != 0)"
"\n return;" )) )
=][=
ENDDEF reset-clause
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE range-option-code
=][=
(define option-arg-type (get "arg-type"))
(define range-count (count "arg-range"))
\=]
static struct {long rmin, rmax;} const rng[[=
(. range-count) =]] = {
[=(out-push-new) =][=
FOR arg-range ",\n" =]{ [=
CASE arg-range =][=
*== "->" =][=
(string-substitute (get "arg-range") "->" "") =], LONG_MAX[=
==* "->" =]LONG_MIN, [=
(string-substitute (get "arg-range") "->" "") =][=
*==* "->" =][=
(string-substitute (get "arg-range") "->" ", ") =][=
~~ -{0,1}[0-9]+ =][=arg-range=], LONG_MIN[=
* =][= (error (string-append "Invalid range spec: ``"
(get "arg-range") "''" )) =][=
ESAC arg-range =] }[=
ENDFOR =][=
(shellf "${CLexe} -I8 --spread=2 <<_EOF_\n%s\n_EOF_"
(out-pop #t)) =] };
int ix;
if (pOptions <= OPTPROC_EMIT_LIMIT)
goto emit_ranges;[=
INVOKE reset-clause =][=
CASE (define leave-ok-code "") (define ok-return-code "")
(if (exist? "flag-code[1]")
(begin
(set! leave-ok-code "goto return_okay")
(set! ok-return-code (string-append
"\n return;\n\nreturn_okay:\n"
(get "flag-code[1]") ))
)
(begin
(set! leave-ok-code "return")
(set! ok-return-code "")
) )
option-arg-type =][=
=* num =]
optionNumericVal(pOptions, pOptDesc);[=
= time-date =][=
(error (string-append "time/date option " low-name
" may not be range limited.")) )
=][=
=* time =]
optionTimeVal(pOptions, pOptDesc);
if (pOptDesc->optArg.argInt == (long)BAD_TIME)
return;[=
* =][=
(error (string-append option-arg-type " option " low-name
" may not be range limited.")) )
=][=
ESAC =]
for (ix = 0; ix < [=(. range-count)=]; ix++) {
if (pOptDesc->optArg.argInt < rng[ix].rmin)
continue; /* ranges need not be ordered. */
if (pOptDesc->optArg.argInt == rng[ix].rmin)
[= (. leave-ok-code) =];
if (rng[ix].rmax == LONG_MIN)
continue;
if (pOptDesc->optArg.argInt <= rng[ix].rmax)
[= (. leave-ok-code) =];
}
option_usage_fp = stderr;
emit_ranges:
optionShowRange(pOptions, pOptDesc, VOIDP(rng), [= (. range-count) =]);[=
(. ok-return-code) =][=
ENDDEF range-option-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE alias-option-code \=]
int res = optionAlias(pOptions, pOptDesc, [=
(string-append INDEX-pfx (get-up-name "aliases")) =]);
if ((res != 0) && ((pOptions->fOptSet & OPTPROC_ERRSTOP) != 0))
[= (. UP-prefix) =]USAGE([=(. usage-err-name)=]);
[=
ENDDEF alias-option-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE keyword-code =][=
(emit (tpl-file-line extract-fmt))
(set! tmp-ct (count "keyword"))
(if (not (exist? "arg-default"))
(begin
(set! tmp-ct (+ 1 tmp-ct))
(emit " static char const zDef[2] = { 0x7F, 0 };\n")
) ) \=]
static char const * const names[[= (. tmp-ct) =]] = {[=
(emit (if (not (exist? "arg-default")) " zDef,\n" "\n"))
(out-push-new) =][=
FOR keyword =][=
(string-table-add-ref opt-strs (get "keyword")) =]
[= ENDFOR =][=
(shell (string-append
"${CLexe} -S, -I8 --spread=1 <<-\\_EOF_\n" (out-pop #t) "_EOF_\nset +x" ))
=] };
if (pOptions <= OPTPROC_EMIT_LIMIT) {
(void) optionEnumerationVal(pOptions, pOptDesc, names, [=
(. tmp-ct)=]);
return; /* protect AutoOpts client code from internal callbacks */
}[=
INVOKE reset-clause =][=
IF (exist? "arg-optional")
=]
if (pOptDesc->optArg.argString == NULL)
pOptDesc->optArg.argEnum = [=
(string-append UP-name "_" (if (> (len "arg-optional") 0)
(get-up-name "arg-optional") (if (exist? "arg-default")
(get-up-name "arg-default")
"UNDEFINED" ))) =];
else
pOptDesc->optArg.argEnum =
optionEnumerationVal(pOptions, pOptDesc, names, [=(. tmp-ct)=]);[=
ELSE
=]
pOptDesc->optArg.argEnum =
optionEnumerationVal(pOptions, pOptDesc, names, [=(. tmp-ct)=]);[=
ENDIF =][=
(if (exist? "flag-code[1]")
(emit (string-append "\n" (get "flag-code[1]"))))
=][=
ENDDEF keyword-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE set-membership-code
=][=
(if (not (exist? "keyword"))
(error "set membership requires keywords"))
(set! tmp-ct (count "keyword"))
(emit (tpl-file-line extract-fmt))
(ag-fprintf 0 " static char const * const names[%d] = {\n" tmp-ct)
(shell (string-append
"${CLexe} -I8 --spread=2 --sep=',' -f'\"%s\"' <<_EOF_\n"
(join "\n" (stack "keyword"))
"\n_EOF_\n" )) =]
};[=
INVOKE reset-clause =]
/*
* This function handles special invalid values for "pOptions"
*/
optionSetMembers(pOptions, pOptDesc, names, [= (. tmp-ct) =]);[=
(if (exist? "flag-code[1]")
(emit (string-append "\n" (get "flag-code[1]"))))
=][=
ENDDEF set-membership-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE file-name-code
\=]
static teOptFileType const type =
[= (set! tmp-val (get "open-file")) =][=
CASE file-exists =][=
== "" =]FTYPE_MODE_MAY_EXIST[=
=* "no" =]FTYPE_MODE_MUST_NOT_EXIST[=
* =]FTYPE_MODE_MUST_EXIST[=
ESAC =] + [= CASE open-file =][=
== "" =]FTYPE_MODE_NO_OPEN[=
=* "desc" =]FTYPE_MODE_OPEN_FD[=
* =]FTYPE_MODE_FOPEN_FP[=
ESAC =];
static tuFileMode mode;
[= IF (or (=* tmp-val "desc") (== tmp-val "")) \=]
[= IF (not (exist? "file-mode")) \=]
#ifndef O_CLOEXEC
# define O_CLOEXEC 0
#endif
[= (define file-mode "O_CLOEXEC") =][=
ELSE =][=
(define file-mode (get "file-mode")) \=]
[= ENDIF \=]
mode.file_flags = [= (. file-mode) =];
[= ELSE \=]
#ifndef FOPEN_BINARY_FLAG
# define FOPEN_BINARY_FLAG
#endif
mode.file_mode = [= (c-string (get "file-mode")) =] FOPEN_BINARY_FLAG;
[= ENDIF =][=
INVOKE reset-clause =]
/*
* This function handles special invalid values for "pOptions"
*/
optionFileCheck(pOptions, pOptDesc, type, mode);[=
(if (exist? "flag-code[1]")
(emit (string-append "\n" (get "flag-code[1]"))))
=][=
ENDDEF file-name-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE requested-code =][=
IF (not (or (exist? "extract-code") (exist? "flag-code")))
=][= RETURN =][=
ENDIF =][=
(if guarded-test-main
(begin
(set! endif-test-main
(sprintf "\n#endif /* defined(%s) */" main-guard))
(emit "\n\n#if ! defined(" main-guard ")")
) ) =][=
INVOKE callback-proc-header =][=
IF (out-push-new (string-append tmp-dir "/flag-code"))
(exist? "flag-code") =][=
IF (exist? "flag-code[0]") \=]
/*
* Be sure the flag-code[0] handles special values for the options pointer
* viz. (poptions <= OPTPROC_EMIT_LIMIT) *and also* the special flag bit
* ((poptdesc->fOptState & OPTST_RESET) != 0) telling the option to
* reset its state.
*/[=
(def-file-line "flag-code[0]" "\n /* extracted from %s, line %d */\n")
=][= flag-code[0] =][=
ENDIF =][=
CASE arg-type =][=
=* bool =]
optionBooleanVal(pOptions, pOptDesc);[=
=* num =]
optionNumericVal(pOptions, pOptDesc);[=
= time-date =]
optionTimeDate(pOptions, pOptDesc);[=
=* time =]
optionTimeVal(pOptions, pOptDesc);[=
~* hier|nest =]
optionNestedVal(pOptions, pOptDesc);[=
ESAC =][=
IF (exist? "flag-code[1]") =]
[= flag-code[1] =][=
ENDIF =][=
ELSE =][=
(extract (string-append (base-name) ".c.save") (string-append
"/* %s =-= " cap-name " Opt Code =-= %s */"))
=][=
ENDIF =][=
(out-pop)
(shell "ck_flag_code") =][=
ENDDEF requested-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE define-option-callbacks =][=
FOR flag =][=
(define flag-index (for-index))
(set-flag-names)
(define endif-test-main "") =][=
# # # # # # # # # # # # # # # # # # =][=
IF (exist? "arg-range") =][=
INVOKE callback-proc-header =][=
INVOKE range-option-code =][=
# # # # # # # # # # # # # # # # # # =][=
ELIF (exist? "aliases") =][=
INVOKE callback-proc-header =][=
INVOKE alias-option-code =][=
# # # # # # # # # # # # # # # # # # =][=
ELSE =][= CASE arg-type =][=
=* key =][=
INVOKE callback-proc-header =][=
INVOKE keyword-code =][=
# # # # # # # # # # # # # # # # # # =][=
=* set =][=
INVOKE callback-proc-header =][=
INVOKE set-membership-code =][=
# # # # # # # # # # # # # # # # # # =][=
=* fil =][=
INVOKE callback-proc-header =][=
INVOKE file-name-code =][=
# # # # # # # # # # # # # # # # # # =][=
* =][=
INVOKE requested-code =][=
ESAC =][=
ENDIF =][=
(. endif-test-main) =][=
ENDFOR flag =][=
ENDDEF define-option-callbacks
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-option-callbacks =]
/*
* Create the static procedure(s) declared above.
*/
/**
* The callout function that invokes the [= (. usage-proc)
=] function.
*
* @param[in] opts the AutoOpts option description structure
* @param[in] od the descriptor for the "help" (usage) option.
* @noreturn
*/
static void
doUsageOpt(tOptions * opts, tOptDesc * od)
{
int ex_code;[=
IF (define od-used #f)
(exist? "resettable") =]
if ((od->fOptState & OPTST_RESET) != 0)
return;[= (set! od-used #t) =][=
ENDIF =][=
IF (exist? "usage-opt") =]
ex_code = (od->optIndex == [= (set! od-used #t) INDEX-pfx =]HELP)
? [=(. succ-exit-code)=] : AO_EXIT_REQ_USAGE;[=
ELSE =]
ex_code = [=(. succ-exit-code)=];[=
ENDIF =][=
(string-append "\n " usage-proc "(&" pname "Options, ex_code);") =]
/* NOTREACHED */
exit([=(. fail-exit-code)=]);
(void)opts;[=
(if od-used "" "\n (void)od;") =]
}[=
INVOKE define-option-callbacks =][=
IF (exist? "main") =][=
INVOKE build-main =][=
ELIF (. guarded-test-main) =][=
INVOKE build-test-main =][=
ENDIF
=][=
(tpl-file-line extract-fmt)
=][=
IF (exist? "usage-message") =]
/**
* Print a usage message with a format and va_list argument.
* The [= (. usage-proc) =] function is then invoked to print
* the error usage text (somewhat abbreviated) and then exit.
*
* @param[in] fmt the message format string
* @param[in] ap the var-arg list.
* @noreturn
*/
[=(. no-return-str)=]vusage_message(char const * fmt, va_list ap)
{
char const * er_leader = _("[= prog-name =] usage error:\n");
fputs(er_leader, stderr);
vfprintf(stderr, fmt, ap);
[= (string-append usage-proc "(&" pname "Options, " usage-err-name ")") =];
/* NOTREACHED, but C11 compilers cannot tell. */
abort();
}
/**
* Print a usage message with a format and a variable argument list.
* [=(. lc-prefix)=]vusage_message() is called to do the work.
*
* @param[in] fmt the message format string
* @param[in] ... the argument list for the message
* @noreturn
*/
[=(. no-return-str)=]usage_message(char const * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
[=(. lc-prefix)=]vusage_message(fmt, ap);
}
[=
ENDIF have usage-message =][=
IF (exist? "die-code")
=]
/**
* Print a fatal error message and die, \a va_list style.
*
* @param[in] exit_code the value to call exit(3) with
* @param[in] fmt the death rattle message
* @param[in] ap the argument list for the message
* @noreturn
*/
[=(. no-return-str)=]vdie(int exit_code, char const * fmt, va_list ap)
{
char const * die_leader = _("[= prog-name =] fatal error:\n");[=
(set! tmp-text (get "die-code"))
(if (> (string-length tmp-text) 1)
(string-append "\n\n" tmp-text "\n"))
=]
fputs(die_leader, stderr);
vfprintf(stderr, fmt, ap);
fflush(stderr);
exit(exit_code);
}
/**
* Print a fatal error message and die, var-arg style.
*
* @param[in] exit_code the value to call exit(3) with
* @param[in] fmt the death rattle message
* @param[in] ... the list of arguments for the message
* @noreturn
*/
[=(. no-return-str)=]die(int exit_code, char const * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vdie(exit_code, fmt, ap);
}
/**
* Print a file system error fatal error message and die.
*
* @param[in] exit_code the value to call exit(3) with.
* @param[in] op the operation that failed.
* @param[in] fname the file name the operation was on.
* @noreturn
*/
[=(. no-return-str)=]fserr(int exit_code, char const * op, char const * fname)
{
char const * fserr_fmt = _("fserr %d (%s) performing '%s' on %s\n");
die(exit_code, fserr_fmt, errno, strerror(errno), op, fname);
}
[=
ENDIF die-code =][=
IF (exist? "warn-code")
=]
/**
* Print a warning message, \a va_list style.
*
* @param[in] fmt the "something awry" message
* @param[in] ap the argument list for the message
*/
void
[=(. lc-prefix)=]vwarning_msg(char const * fmt, va_list ap)
{
char const * warn_leader = _("[= prog-name =] WARNING:\n");[=
(set! tmp-text (get "warn-code"))
(if (> (string-length tmp-text) 1)
(string-append "\n\n" tmp-text "\n"))
=]
fputs(warn_leader, stderr);
vfprintf(stderr, fmt, ap);
fflush(stderr);
}
/**
* Print a warning message, var-arg style.
*
* @param[in] fmt the "something awry" message
* @param[in] ... the list of arguments for the message
*/
void
[=(. lc-prefix)=]warning_msg(char const * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarning_msg(fmt, ap);
va_end(ap);
}
[=
ENDIF have warn-code =][=
ENDDEF emit-option-callbacks
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-option-code =][=
IF (exist? "option-code") =][=
(def-file-line "option-code" extract-fmt) =][=
option-code =][=
ELSE =][=
IF (and (exist? "no-libopts") (not (exist? "autoopts-usage-tlib"))) =]
(void)process_[=(. pname)=]_opts(argc, argv);[=
ELIF (exist? "main-text") =]
{
int ct = optionProcess(&[=(. pname)=]Options, argc, argv);
argc -= ct;
argv += ct;
}[=
ELSE =]
(void)optionProcess(&[=(. pname)=]Options, argc, argv);[=
ENDIF =][=
ENDIF =][=
ENDDEF emit-option-code
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][=
DEFINE emit-main-text =][=
IF (exist? "main-text") =][=
(def-file-line "main-text" extract-fmt) =][=
main-text =][=
ELSE =][=
IF (and (exist? "no-libopts") (not (exist? "autoopts-usage-tlib"))) =]
/* When using AutoOpts with getopt(3C) or getopt_long(3GNU)
the main-text attribute of main _must_ be defined. */
#error autoopts_with_getopt_must_define_main_text_attribute[=
ELSE test-main is not optionParseShell and main-text not exist
Above, we figure out which emitter procedure is to be used.
The default is optionPutShell.
=]
[= (. option-emitter-proc) =](&[=(. pname)=]Options);
res = ferror(stdout);
if (res != 0)
fputs("output error writing to stdout\n", stderr);[=
ENDIF =][=
ENDIF =][=
ENDDEF emit-main-text =]