diff options
Diffstat (limited to 'autoopts')
141 files changed, 40801 insertions, 0 deletions
diff --git a/autoopts/Makefile.am b/autoopts/Makefile.am new file mode 100644 index 0000000..9a57022 --- /dev/null +++ b/autoopts/Makefile.am @@ -0,0 +1,207 @@ +## -*- Mode: Makefile -*- +## --------------------------------------------------------------------- +## autoopts/Makefile.am +## +## Time-stamp: "2012-04-14 14:22:31 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +SUBDIRS = @OPTS_TESTDIR@ +INCLUDES = @INCLIST@ +libsrc = libopts-@AO_CURRENT@.@AO_REVISION@.@AO_AGE@.tar.gz +LIBOPTS_VER = @AO_CURRENT@:@AO_REVISION@:@AO_AGE@ + +if NEED_PATHFIND +PATHFIND_MAN = pathfind.3 +else +PATHFIND_MAN = +endif + +MAN_STAMP = man3-stamp +GENTEXI = libopts.texi libopts.menu +TEXI_STAMP = texi-stamp +EXTRA_DIST = +GENMAN = $(PATHFIND_MAN) \ + ao_string_tokenize.3 configFileLoad.3 optionFileLoad.3 \ + optionFindNextValue.3 optionFindValue.3 optionFree.3 \ + optionGetValue.3 optionLoadLine.3 optionNextValue.3 \ + optionOnlyUsage.3 optionProcess.3 optionRestore.3 \ + optionSaveFile.3 optionSaveState.3 optionUnloadNested.3 \ + optionVersion.3 strequate.3 streqvcmp.3 \ + streqvmap.3 strneqvcmp.3 strtransform.3 + +nodist_pkgdata_DATA = $(libsrc) \ + tpl/man2man tpl/man2mdoc tpl/man2texi \ + tpl/mdoc2man tpl/mdoc2mdoc tpl/mdoc2texi \ + tpl/texi2man tpl/texi2mdoc tpl/texi2texi \ + tpl/tpl-config.tlib + +pkgdata_DATA = \ + autoopts.m4 tpl/aginfo.tpl tpl/aginfo3.tpl \ + tpl/agman-cmd.tpl tpl/agman.tlib tpl/agman1.tpl \ + tpl/agman3.tpl tpl/agmdoc-cmd.tpl tpl/agpl.lic \ + tpl/agtexi-cmd.tpl tpl/bits.tpl tpl/cmd-doc.tlib \ + tpl/def2pot.tpl tpl/getopt.tpl tpl/gpl.lic \ + tpl/gplv2.lic tpl/lgpl.lic tpl/mbsd.lic \ + tpl/optcode.tlib tpl/opthead.tlib tpl/options.tpl \ + tpl/optlib.tlib tpl/optmain.tlib tpl/rc-sample.tpl \ + tpl/stdoptions.def tpl/strings.tpl tpl/usage.tlib + +EXTRA_DATA = $(pkgdata_DATA) \ + autogen.map autoopts-config.in bootstrap.dir \ + install-hook.sh mk-autoopts-pc.in mk-tpl-config.sh \ + po tpl/man2mdoc.pl tpl/man2texi.sh \ + tpl/mdoc2man.sh tpl/mdoc2texi.pl tpl/texi2man.sh \ + tpl/texi2mdoc.sh tpl/tpl-config-tlib.in tpl/usage-txt.tpl + +GENSCRIPTS = $(srcdir)/funcs.def \ + tpl/man2man tpl/man2mdoc tpl/man2texi tpl/mdoc2man tpl/mdoc2mdoc \ + tpl/mdoc2texi tpl/texi2man tpl/texi2mdoc tpl/texi2texi + +EXTRA_DIST += $(top_srcdir)/config/gendocs.sh +EXTRA_DIST += gettext.h +EXTRA_DIST += parse-duration.c +EXTRA_DIST += parse-duration.h + +GENHDRS = autoopts/options.h autoopts/usage-txt.h genshell.h \ + xat-attribute.h value-type.h ao-strs.h ag-char-map.h +HDRS = $(GENHDRS) autoopts.h project.h proto.h +GEN_SRC = ao-strs.c value-type.c xat-attribute.c + +## The primary source (autoopts.c) must be by itself on the first line after +## "CSRC". 'sed' does some magic here to get the list of source files for the +## documentation. Files without documentation are on the CSRC = line. +## +CSRC = parse-duration.c $(GEN_SRC) \ + autoopts.c \ + alias.c boolean.c check.c configfile.c cook.c \ + enum.c env.c file.c find.c genshell.c \ + load.c makeshell.c nested.c numeric.c pgusage.c \ + putshell.c reset.c restore.c save.c sort.c \ + stack.c streqvcmp.c text_mmap.c time.c tokenize.c \ + usage.c version.c + + +SRC = $(HDRS) $(CSRC) $(GENSRC) +DEF_FILES = genshell.def $(srcdir)/funcs.def ao-strs.def +pkgconfigdir =$(libdir)/pkgconfig + +## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +## +## A U T O M A K E V A R S +## +## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +CLEANFILES = tmp-* libopts.c +DISTCLEANFILES = $(GENMAN) $(GENTEXI) *-stamp +MAINTAINERCLEANFILES = $(GENHDRS) $(GENSRC) $(GENSCRIPTS) +m4datadir = $(datadir)/aclocal + +nodist_libopts_la_SOURCES = libopts.c +libopts_la_SOURCES = $(HDRS) +libopts_la_CFLAGS = -DPKGDATADIR='"$(pkgdatadir)"' +libopts_la_LDFLAGS = -version-info $(LIBOPTS_VER) +libopts_la_LIBADD = $(top_builddir)/snprintfv/libsnprintfv.la + +EXTRA_DIST += $(SRC) $(EXTRA_DATA) $(man_MANS) $(DEF_FILES) + +INST_MANS = autoopts-config.1 $(GENMAN) +INST_PKGCFG = pkgconfig/autoopts.pc +INST_PKGDATA = autoopts.m4 $(TPL_FILES) +INST_LIBS = libopts.la +INST_HDRS = autoopts/options.h autoopts/usage-txt.h +INST_SH = autoopts-config + +man_MANS = $(INST_MANS) +m4data_DATA = autoopts.m4 +nobase_data_DATA = $(INST_PKGCFG) +lib_LTLIBRARIES = $(INST_LIBS) +nobase_include_HEADERS = $(INST_HDRS) +bin_SCRIPTS = $(INST_SH) + +BOOTENV = AGexe="$(AGexe)" GDexe="$(GDexe)" CLexe="$(CLexe)" \ + srcdir="$(srcdir)" top_srcdir="$(top_srcdir)" \ + builddir="$(builddir)" top_builddir="$(top_builddir)" \ + POSIX_SHELL="$(POSIX_SHELL)" + +## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +## +## M A K E F I L E R U L E S +## +## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +libopts.c : tpl-config-stamp +$(GENSCRIPTS) : tpl-config-stamp + +tpl-config-stamp: $(HDRS) $(CSRC) \ + $(top_builddir)/config.h $(srcdir)/mk-tpl-config.sh + $(BOOTENV) \ + $(POSIX_SHELL) $(srcdir)/mk-tpl-config.sh $@ $(HDRS) $(CSRC) + +makeshell.lo : genshell.c +genshell.c : $(srcdir)/genshell.def + $(BOOTENV) \ + $(POSIX_SHELL) $(srcdir)/bootstrap.dir $@ + +strcspn.lo : $(top_srcdir)/compat/strcspn.c + $(LTCOMPILE) -o $@ -c $(top_srcdir)/compat/strcspn.c + +install-data-local : install-man3 + +$(GENMAN) : $(MAN_STAMP) +$(MAN_STAMP) : $(srcdir)/funcs.def + @test -x ../agen5/autogen || exit 0 ; \ + touch tmp-$@ ; \ + opts='-L$(srcdir)/tpl -L$(builddir)/tpl -Tagman3.tpl' ; \ + echo ! $(AGexe) $${opts} $(srcdir)/funcs.def ; \ + $(AGexe) $${opts} $(srcdir)/funcs.def ; \ + mv -f tmp-$@ $@ + +$(GENTEXI) : $(TEXI_STAMP) +$(TEXI_STAMP) : ../agen5/autogen $(srcdir)/funcs.def + @touch tmp-$@ ; \ + opts='-L$(srcdir)/tpl -L$(builddir)/tpl -Taginfo3.tpl' ; \ + cmd="$(AGexe) $${opts} -DLEVEL=subsection -blibopts" ; \ + cmd="$${cmd} -L$(srcdir) $(srcdir)/funcs.def" ; \ + echo ! $$cmd ; $$cmd ; mv -f tmp-$@ $@ + +libsrc : $(libsrc) +$(libsrc) : + @$(BOOTENV) \ + AO_AGE=@AO_AGE@ AO_CURRENT=@AO_CURRENT@ AO_REVISION=@AO_REVISION@ \ + $(POSIX_SHELL) $(top_srcdir)/pkg/libopts/mklibsrc.sh + +pkgconfig/autoopts.pc : mk-autoopts-pc + $(POSIX_SHELL) mk-autoopts-pc $@ + +install-data-hook: + @DESTdestdir='$(DESTDIR)$(includedir)/autoopts' \ + DESTpkgdatadir='$(DESTDIR)$(pkgdatadir)' \ + top_builddir='$(top_builddir)' \ + LIBOPTS_VER='$(LIBOPTS_VER)' \ + POSIX_SHELL='$(POSIX_SHELL)' \ + bindir='$(bindir)' \ + $(POSIX_SHELL) $(srcdir)/install-hook.sh + +.NOTPARALLEL: + +# Makefile.am ends here diff --git a/autoopts/Makefile.in b/autoopts/Makefile.in new file mode 100644 index 0000000..2d35b42 --- /dev/null +++ b/autoopts/Makefile.in @@ -0,0 +1,1193 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = autoopts +DIST_COMMON = $(nobase_include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/autoopts-config.in \ + $(srcdir)/mk-autoopts-pc.in $(top_srcdir)/config/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ag_macros.m4 \ + $(top_srcdir)/config/extensions.m4 \ + $(top_srcdir)/config/libopts.m4 \ + $(top_srcdir)/config/libtool.m4 \ + $(top_srcdir)/config/ltoptions.m4 \ + $(top_srcdir)/config/ltsugar.m4 \ + $(top_srcdir)/config/ltversion.m4 \ + $(top_srcdir)/config/lt~obsolete.m4 \ + $(top_srcdir)/config/onceonly.m4 \ + $(top_srcdir)/config/snprintfv.m4 \ + $(top_srcdir)/config/unlocked-io.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = mk-autoopts-pc autoopts-config +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" \ + "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(datadir)" \ + "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgdatadir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libopts_la_DEPENDENCIES = $(top_builddir)/snprintfv/libsnprintfv.la +am__objects_1 = +am__objects_2 = $(am__objects_1) +am_libopts_la_OBJECTS = $(am__objects_2) +nodist_libopts_la_OBJECTS = libopts_la-libopts.lo +libopts_la_OBJECTS = $(am_libopts_la_OBJECTS) \ + $(nodist_libopts_la_OBJECTS) +libopts_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libopts_la_CFLAGS) \ + $(CFLAGS) $(libopts_la_LDFLAGS) $(LDFLAGS) -o $@ +SCRIPTS = $(bin_SCRIPTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libopts_la_SOURCES) $(nodist_libopts_la_SOURCES) +DIST_SOURCES = $(libopts_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +man1dir = $(mandir)/man1 +man3dir = $(mandir)/man3 +NROFF = nroff +MANS = $(man_MANS) +DATA = $(m4data_DATA) $(nobase_data_DATA) $(nodist_pkgdata_DATA) \ + $(pkgdata_DATA) +HEADERS = $(nobase_include_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AGEN5_TESTS = @AGEN5_TESTS@ +AG_GUILE = @AG_GUILE@ +AG_LDFLAGS = @AG_LDFLAGS@ +AG_MAJOR_VERSION = @AG_MAJOR_VERSION@ +AG_MINOR_VERSION = @AG_MINOR_VERSION@ +AG_TIMEOUT = @AG_TIMEOUT@ +AG_VERSION = @AG_VERSION@ +AG_XML2 = @AG_XML2@ +AGexe = @AGexe@ +AGnam = @AGnam@ +AMTAR = @AMTAR@ +AO_AGE = @AO_AGE@ +AO_CURRENT = @AO_CURRENT@ +AO_REVISION = @AO_REVISION@ +AO_TEMPLATE_VERSION = @AO_TEMPLATE_VERSION@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLexe = @CLexe@ +CLnam = @CLnam@ +CONFIG_SHELL = @CONFIG_SHELL@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_ENABLED = @DEBUG_ENABLED@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNAMIC_AG = @DYNAMIC_AG@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDexe = @GDexe@ +GDnam = @GDnam@ +GO_AGE = @GO_AGE@ +GO_CURRENT = @GO_CURRENT@ +GO_REVISION = @GO_REVISION@ +GREP = @GREP@ +GUILE_VERSION = @GUILE_VERSION@ +INCLIST = @INCLIST@ +INCSNPRINTFV = @INCSNPRINTFV@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBGUILE_CFLAGS = @LIBGUILE_CFLAGS@ +LIBGUILE_LIBS = @LIBGUILE_LIBS@ +LIBGUILE_PATH = @LIBGUILE_PATH@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSNPRINTFV = @LIBSNPRINTFV@ +LIBTOOL = @LIBTOOL@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIBXML2_PATH = @LIBXML2_PATH@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +M4_SRC = @M4_SRC@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPTS_TESTDIR = @OPTS_TESTDIR@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSIX_SHELL = @POSIX_SHELL@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TEXI2HTML = @TEXI2HTML@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_aux_dir = @ac_aux_dir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = @OPTS_TESTDIR@ +INCLUDES = @INCLIST@ +libsrc = libopts-@AO_CURRENT@.@AO_REVISION@.@AO_AGE@.tar.gz +LIBOPTS_VER = @AO_CURRENT@:@AO_REVISION@:@AO_AGE@ +@NEED_PATHFIND_FALSE@PATHFIND_MAN = +@NEED_PATHFIND_TRUE@PATHFIND_MAN = pathfind.3 +MAN_STAMP = man3-stamp +GENTEXI = libopts.texi libopts.menu +TEXI_STAMP = texi-stamp +EXTRA_DIST = $(top_srcdir)/config/gendocs.sh gettext.h \ + parse-duration.c parse-duration.h $(SRC) $(EXTRA_DATA) \ + $(man_MANS) $(DEF_FILES) +GENMAN = $(PATHFIND_MAN) \ + ao_string_tokenize.3 configFileLoad.3 optionFileLoad.3 \ + optionFindNextValue.3 optionFindValue.3 optionFree.3 \ + optionGetValue.3 optionLoadLine.3 optionNextValue.3 \ + optionOnlyUsage.3 optionProcess.3 optionRestore.3 \ + optionSaveFile.3 optionSaveState.3 optionUnloadNested.3 \ + optionVersion.3 strequate.3 streqvcmp.3 \ + streqvmap.3 strneqvcmp.3 strtransform.3 + +nodist_pkgdata_DATA = $(libsrc) \ + tpl/man2man tpl/man2mdoc tpl/man2texi \ + tpl/mdoc2man tpl/mdoc2mdoc tpl/mdoc2texi \ + tpl/texi2man tpl/texi2mdoc tpl/texi2texi \ + tpl/tpl-config.tlib + +pkgdata_DATA = \ + autoopts.m4 tpl/aginfo.tpl tpl/aginfo3.tpl \ + tpl/agman-cmd.tpl tpl/agman.tlib tpl/agman1.tpl \ + tpl/agman3.tpl tpl/agmdoc-cmd.tpl tpl/agpl.lic \ + tpl/agtexi-cmd.tpl tpl/bits.tpl tpl/cmd-doc.tlib \ + tpl/def2pot.tpl tpl/getopt.tpl tpl/gpl.lic \ + tpl/gplv2.lic tpl/lgpl.lic tpl/mbsd.lic \ + tpl/optcode.tlib tpl/opthead.tlib tpl/options.tpl \ + tpl/optlib.tlib tpl/optmain.tlib tpl/rc-sample.tpl \ + tpl/stdoptions.def tpl/strings.tpl tpl/usage.tlib + +EXTRA_DATA = $(pkgdata_DATA) \ + autogen.map autoopts-config.in bootstrap.dir \ + install-hook.sh mk-autoopts-pc.in mk-tpl-config.sh \ + po tpl/man2mdoc.pl tpl/man2texi.sh \ + tpl/mdoc2man.sh tpl/mdoc2texi.pl tpl/texi2man.sh \ + tpl/texi2mdoc.sh tpl/tpl-config-tlib.in tpl/usage-txt.tpl + +GENSCRIPTS = $(srcdir)/funcs.def \ + tpl/man2man tpl/man2mdoc tpl/man2texi tpl/mdoc2man tpl/mdoc2mdoc \ + tpl/mdoc2texi tpl/texi2man tpl/texi2mdoc tpl/texi2texi + +GENHDRS = autoopts/options.h autoopts/usage-txt.h genshell.h \ + xat-attribute.h value-type.h ao-strs.h ag-char-map.h + +HDRS = $(GENHDRS) autoopts.h project.h proto.h +GEN_SRC = ao-strs.c value-type.c xat-attribute.c +CSRC = parse-duration.c $(GEN_SRC) \ + autoopts.c \ + alias.c boolean.c check.c configfile.c cook.c \ + enum.c env.c file.c find.c genshell.c \ + load.c makeshell.c nested.c numeric.c pgusage.c \ + putshell.c reset.c restore.c save.c sort.c \ + stack.c streqvcmp.c text_mmap.c time.c tokenize.c \ + usage.c version.c + +SRC = $(HDRS) $(CSRC) $(GENSRC) +DEF_FILES = genshell.def $(srcdir)/funcs.def ao-strs.def +pkgconfigdir = $(libdir)/pkgconfig +CLEANFILES = tmp-* libopts.c +DISTCLEANFILES = $(GENMAN) $(GENTEXI) *-stamp +MAINTAINERCLEANFILES = $(GENHDRS) $(GENSRC) $(GENSCRIPTS) +m4datadir = $(datadir)/aclocal +nodist_libopts_la_SOURCES = libopts.c +libopts_la_SOURCES = $(HDRS) +libopts_la_CFLAGS = -DPKGDATADIR='"$(pkgdatadir)"' +libopts_la_LDFLAGS = -version-info $(LIBOPTS_VER) +libopts_la_LIBADD = $(top_builddir)/snprintfv/libsnprintfv.la +INST_MANS = autoopts-config.1 $(GENMAN) +INST_PKGCFG = pkgconfig/autoopts.pc +INST_PKGDATA = autoopts.m4 $(TPL_FILES) +INST_LIBS = libopts.la +INST_HDRS = autoopts/options.h autoopts/usage-txt.h +INST_SH = autoopts-config +man_MANS = $(INST_MANS) +m4data_DATA = autoopts.m4 +nobase_data_DATA = $(INST_PKGCFG) +lib_LTLIBRARIES = $(INST_LIBS) +nobase_include_HEADERS = $(INST_HDRS) +bin_SCRIPTS = $(INST_SH) +BOOTENV = AGexe="$(AGexe)" GDexe="$(GDexe)" CLexe="$(CLexe)" \ + srcdir="$(srcdir)" top_srcdir="$(top_srcdir)" \ + builddir="$(builddir)" top_builddir="$(top_builddir)" \ + POSIX_SHELL="$(POSIX_SHELL)" + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu autoopts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu autoopts/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +mk-autoopts-pc: $(top_builddir)/config.status $(srcdir)/mk-autoopts-pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +autoopts-config: $(top_builddir)/config.status $(srcdir)/autoopts-config.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libopts.la: $(libopts_la_OBJECTS) $(libopts_la_DEPENDENCIES) $(EXTRA_libopts_la_DEPENDENCIES) + $(libopts_la_LINK) -rpath $(libdir) $(libopts_la_OBJECTS) $(libopts_la_LIBADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libopts_la-libopts.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libopts_la-libopts.lo: libopts.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libopts_la_CFLAGS) $(CFLAGS) -MT libopts_la-libopts.lo -MD -MP -MF $(DEPDIR)/libopts_la-libopts.Tpo -c -o libopts_la-libopts.lo `test -f 'libopts.c' || echo '$(srcdir)/'`libopts.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libopts_la-libopts.Tpo $(DEPDIR)/libopts_la-libopts.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libopts.c' object='libopts_la-libopts.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libopts_la_CFLAGS) $(CFLAGS) -c -o libopts_la-libopts.lo `test -f 'libopts.c' || echo '$(srcdir)/'`libopts.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man3: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.3[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) +install-m4dataDATA: $(m4data_DATA) + @$(NORMAL_INSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(m4datadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(m4datadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(m4datadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(m4datadir)" || exit $$?; \ + done + +uninstall-m4dataDATA: + @$(NORMAL_UNINSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(m4datadir)'; $(am__uninstall_files_from_dir) +install-nobase_dataDATA: $(nobase_data_DATA) + @$(NORMAL_INSTALL) + @list='$(nobase_data_DATA)'; test -n "$(datadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(datadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(datadir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(datadir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(datadir)/$$dir"; }; \ + echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(datadir)/$$dir'"; \ + $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(datadir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_dataDATA: + @$(NORMAL_UNINSTALL) + @list='$(nobase_data_DATA)'; test -n "$(datadir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(datadir)'; $(am__uninstall_files_from_dir) +install-nodist_pkgdataDATA: $(nodist_pkgdata_DATA) + @$(NORMAL_INSTALL) + @list='$(nodist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + done + +uninstall-nodist_pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(nodist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) +install-pkgdataDATA: $(pkgdata_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + done + +uninstall-pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) +install-nobase_includeHEADERS: $(nobase_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically 'make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(datadir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-data-local install-m4dataDATA install-man \ + install-nobase_dataDATA install-nobase_includeHEADERS \ + install-nodist_pkgdataDATA install-pkgdataDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binSCRIPTS install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: install-man1 install-man3 + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ + uninstall-m4dataDATA uninstall-man uninstall-nobase_dataDATA \ + uninstall-nobase_includeHEADERS uninstall-nodist_pkgdataDATA \ + uninstall-pkgdataDATA + +uninstall-man: uninstall-man1 uninstall-man3 + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am \ + install-data-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist \ + cscopelist-recursive ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binSCRIPTS install-data \ + install-data-am install-data-hook install-data-local \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-m4dataDATA install-man \ + install-man1 install-man3 install-nobase_dataDATA \ + install-nobase_includeHEADERS install-nodist_pkgdataDATA \ + install-pdf install-pdf-am install-pkgdataDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ + uninstall-m4dataDATA uninstall-man uninstall-man1 \ + uninstall-man3 uninstall-nobase_dataDATA \ + uninstall-nobase_includeHEADERS uninstall-nodist_pkgdataDATA \ + uninstall-pkgdataDATA + + +libopts.c : tpl-config-stamp +$(GENSCRIPTS) : tpl-config-stamp + +tpl-config-stamp: $(HDRS) $(CSRC) \ + $(top_builddir)/config.h $(srcdir)/mk-tpl-config.sh + $(BOOTENV) \ + $(POSIX_SHELL) $(srcdir)/mk-tpl-config.sh $@ $(HDRS) $(CSRC) + +makeshell.lo : genshell.c +genshell.c : $(srcdir)/genshell.def + $(BOOTENV) \ + $(POSIX_SHELL) $(srcdir)/bootstrap.dir $@ + +strcspn.lo : $(top_srcdir)/compat/strcspn.c + $(LTCOMPILE) -o $@ -c $(top_srcdir)/compat/strcspn.c + +install-data-local : install-man3 + +$(GENMAN) : $(MAN_STAMP) +$(MAN_STAMP) : $(srcdir)/funcs.def + @test -x ../agen5/autogen || exit 0 ; \ + touch tmp-$@ ; \ + opts='-L$(srcdir)/tpl -L$(builddir)/tpl -Tagman3.tpl' ; \ + echo ! $(AGexe) $${opts} $(srcdir)/funcs.def ; \ + $(AGexe) $${opts} $(srcdir)/funcs.def ; \ + mv -f tmp-$@ $@ + +$(GENTEXI) : $(TEXI_STAMP) +$(TEXI_STAMP) : ../agen5/autogen $(srcdir)/funcs.def + @touch tmp-$@ ; \ + opts='-L$(srcdir)/tpl -L$(builddir)/tpl -Taginfo3.tpl' ; \ + cmd="$(AGexe) $${opts} -DLEVEL=subsection -blibopts" ; \ + cmd="$${cmd} -L$(srcdir) $(srcdir)/funcs.def" ; \ + echo ! $$cmd ; $$cmd ; mv -f tmp-$@ $@ + +libsrc : $(libsrc) +$(libsrc) : + @$(BOOTENV) \ + AO_AGE=@AO_AGE@ AO_CURRENT=@AO_CURRENT@ AO_REVISION=@AO_REVISION@ \ + $(POSIX_SHELL) $(top_srcdir)/pkg/libopts/mklibsrc.sh + +pkgconfig/autoopts.pc : mk-autoopts-pc + $(POSIX_SHELL) mk-autoopts-pc $@ + +install-data-hook: + @DESTdestdir='$(DESTDIR)$(includedir)/autoopts' \ + DESTpkgdatadir='$(DESTDIR)$(pkgdatadir)' \ + top_builddir='$(top_builddir)' \ + LIBOPTS_VER='$(LIBOPTS_VER)' \ + POSIX_SHELL='$(POSIX_SHELL)' \ + bindir='$(bindir)' \ + $(POSIX_SHELL) $(srcdir)/install-hook.sh + +.NOTPARALLEL: + +# Makefile.am ends here + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/autoopts/ag-char-map.h b/autoopts/ag-char-map.h new file mode 100644 index 0000000..0f81225 --- /dev/null +++ b/autoopts/ag-char-map.h @@ -0,0 +1,510 @@ +/* + * 29 bits for 46 character classifications + * generated by char-mapper on 08/11/12 at 09:41:13 + * + * This file contains the character classifications + * used by AutoGen and AutoOpts for identifying tokens. + * The table is static scope, so %guard is empty. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ +#ifndef AG_CHAR_MAP_H_GUARD +#define AG_CHAR_MAP_H_GUARD 1 + +#ifdef HAVE_CONFIG_H +# if defined(HAVE_INTTYPES_H) +# include <inttypes.h> + +# elif defined(HAVE_STDINT_H) +# include <stdint.h> + +# elif !defined(HAVE_UINT32_T) +# if SIZEOF_INT == 4 + typedef unsigned int uint32_t; +# elif SIZEOF_LONG == 4 + typedef unsigned long uint32_t; +# endif +# endif /* HAVE_*INT*_H header */ + +#else /* not HAVE_CONFIG_H -- */ +# include <inttypes.h> +#endif /* HAVE_CONFIG_H */ + +#if 0 /* mapping specification source (from autogen.map) */ +// +// %guard +// %file ag-char-map.h +// %backup +// %optimize +// +// %comment -- see above +// % +// +// newline "\n" +// nul-byte "\x00" +// dir-sep "/\\" +// percent "%" +// comma "," +// colon ":" +// underscore "_" +// plus "+" +// dollar "$" +// option-marker "-" +// +// horiz-white "\t " +// alt-white "\v\f\r\b" +// whitespace +horiz-white +newline +alt-white +// non-nl-white +horiz-white +alt-white +// quote "'\"" +// parentheses "()" +// +// graphic "!-~" +// inversion "~-" +// oct-digit "0-7" +// dec-digit "89" +oct-digit +// hex-digit "a-fA-F" +dec-digit +// lower-case "a-z" +// upper-case "A-Z" +// alphabetic +lower-case +upper-case +// alphanumeric +alphabetic +dec-digit +// var-first +underscore +alphabetic +// variable-name +var-first +dec-digit +// option-name "^-" +variable-name +// value-name +colon +option-name +// name-sep "[.]" +// compound-name +value-name +name-sep +horiz-white +// scheme-note +parentheses +quote +// +// unquotable "!-~" -"#,;<=>[\\]`{}?*" -quote -parentheses +// end-xml-token "/>" +whitespace +// plus-n-space +plus +whitespace +// punctuation "!-~" -alphanumeric -"_" +// suffix "-._" +alphanumeric +// suffix-fmt +percent +suffix +dir-sep +// false-type "nNfF0" +nul-byte +// file-name +dir-sep +suffix +// end-token +nul-byte +whitespace +// end-list-entry +comma +end-token +// set-separator "|+" +end-list-entry +// signed-number +inversion +dec-digit +// make-script +dollar +newline +// load-line-skip +horiz-white +option-marker +// +#endif /* 0 -- mapping spec. source */ + + +typedef uint32_t ag_char_map_mask_t; + +#define IS_NEWLINE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000001) +#define SPN_NEWLINE_CHARS(_s) spn_ag_char_map_chars(_s, 0) +#define BRK_NEWLINE_CHARS(_s) brk_ag_char_map_chars(_s, 0) +#define SPN_NEWLINE_BACK(s,e) spn_ag_char_map_back(s, e, 0) +#define BRK_NEWLINE_BACK(s,e) brk_ag_char_map_back(s, e, 0) +#define IS_NUL_BYTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000002) +#define SPN_NUL_BYTE_CHARS(_s) spn_ag_char_map_chars(_s, 1) +#define BRK_NUL_BYTE_CHARS(_s) brk_ag_char_map_chars(_s, 1) +#define SPN_NUL_BYTE_BACK(s,e) spn_ag_char_map_back(s, e, 1) +#define BRK_NUL_BYTE_BACK(s,e) brk_ag_char_map_back(s, e, 1) +#define IS_DIR_SEP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000004) +#define SPN_DIR_SEP_CHARS(_s) spn_ag_char_map_chars(_s, 2) +#define BRK_DIR_SEP_CHARS(_s) brk_ag_char_map_chars(_s, 2) +#define SPN_DIR_SEP_BACK(s,e) spn_ag_char_map_back(s, e, 2) +#define BRK_DIR_SEP_BACK(s,e) brk_ag_char_map_back(s, e, 2) +#define IS_PERCENT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000008) +#define SPN_PERCENT_CHARS(_s) spn_ag_char_map_chars(_s, 3) +#define BRK_PERCENT_CHARS(_s) brk_ag_char_map_chars(_s, 3) +#define SPN_PERCENT_BACK(s,e) spn_ag_char_map_back(s, e, 3) +#define BRK_PERCENT_BACK(s,e) brk_ag_char_map_back(s, e, 3) +#define IS_COMMA_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000010) +#define SPN_COMMA_CHARS(_s) spn_ag_char_map_chars(_s, 4) +#define BRK_COMMA_CHARS(_s) brk_ag_char_map_chars(_s, 4) +#define SPN_COMMA_BACK(s,e) spn_ag_char_map_back(s, e, 4) +#define BRK_COMMA_BACK(s,e) brk_ag_char_map_back(s, e, 4) +#define IS_COLON_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000020) +#define SPN_COLON_CHARS(_s) spn_ag_char_map_chars(_s, 5) +#define BRK_COLON_CHARS(_s) brk_ag_char_map_chars(_s, 5) +#define SPN_COLON_BACK(s,e) spn_ag_char_map_back(s, e, 5) +#define BRK_COLON_BACK(s,e) brk_ag_char_map_back(s, e, 5) +#define IS_UNDERSCORE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000040) +#define SPN_UNDERSCORE_CHARS(_s) spn_ag_char_map_chars(_s, 6) +#define BRK_UNDERSCORE_CHARS(_s) brk_ag_char_map_chars(_s, 6) +#define SPN_UNDERSCORE_BACK(s,e) spn_ag_char_map_back(s, e, 6) +#define BRK_UNDERSCORE_BACK(s,e) brk_ag_char_map_back(s, e, 6) +#define IS_PLUS_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000080) +#define SPN_PLUS_CHARS(_s) spn_ag_char_map_chars(_s, 7) +#define BRK_PLUS_CHARS(_s) brk_ag_char_map_chars(_s, 7) +#define SPN_PLUS_BACK(s,e) spn_ag_char_map_back(s, e, 7) +#define BRK_PLUS_BACK(s,e) brk_ag_char_map_back(s, e, 7) +#define IS_DOLLAR_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000100) +#define SPN_DOLLAR_CHARS(_s) spn_ag_char_map_chars(_s, 8) +#define BRK_DOLLAR_CHARS(_s) brk_ag_char_map_chars(_s, 8) +#define SPN_DOLLAR_BACK(s,e) spn_ag_char_map_back(s, e, 8) +#define BRK_DOLLAR_BACK(s,e) brk_ag_char_map_back(s, e, 8) +#define IS_OPTION_MARKER_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000200) +#define SPN_OPTION_MARKER_CHARS(_s) spn_ag_char_map_chars(_s, 9) +#define BRK_OPTION_MARKER_CHARS(_s) brk_ag_char_map_chars(_s, 9) +#define SPN_OPTION_MARKER_BACK(s,e) spn_ag_char_map_back(s, e, 9) +#define BRK_OPTION_MARKER_BACK(s,e) brk_ag_char_map_back(s, e, 9) +#define IS_HORIZ_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000400) +#define SPN_HORIZ_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 10) +#define BRK_HORIZ_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 10) +#define SPN_HORIZ_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 10) +#define BRK_HORIZ_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 10) +#define IS_ALT_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000800) +#define SPN_ALT_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 11) +#define BRK_ALT_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 11) +#define SPN_ALT_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 11) +#define BRK_ALT_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 11) +#define IS_WHITESPACE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C01) +#define SPN_WHITESPACE_CHARS(_s) spn_ag_char_map_chars(_s, 12) +#define BRK_WHITESPACE_CHARS(_s) brk_ag_char_map_chars(_s, 12) +#define SPN_WHITESPACE_BACK(s,e) spn_ag_char_map_back(s, e, 12) +#define BRK_WHITESPACE_BACK(s,e) brk_ag_char_map_back(s, e, 12) +#define IS_NON_NL_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C00) +#define SPN_NON_NL_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 13) +#define BRK_NON_NL_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 13) +#define SPN_NON_NL_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 13) +#define BRK_NON_NL_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 13) +#define IS_QUOTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00001000) +#define SPN_QUOTE_CHARS(_s) spn_ag_char_map_chars(_s, 14) +#define BRK_QUOTE_CHARS(_s) brk_ag_char_map_chars(_s, 14) +#define SPN_QUOTE_BACK(s,e) spn_ag_char_map_back(s, e, 14) +#define BRK_QUOTE_BACK(s,e) brk_ag_char_map_back(s, e, 14) +#define IS_PARENTHESES_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00002000) +#define SPN_PARENTHESES_CHARS(_s) spn_ag_char_map_chars(_s, 15) +#define BRK_PARENTHESES_CHARS(_s) brk_ag_char_map_chars(_s, 15) +#define SPN_PARENTHESES_BACK(s,e) spn_ag_char_map_back(s, e, 15) +#define BRK_PARENTHESES_BACK(s,e) brk_ag_char_map_back(s, e, 15) +#define IS_GRAPHIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00004000) +#define SPN_GRAPHIC_CHARS(_s) spn_ag_char_map_chars(_s, 16) +#define BRK_GRAPHIC_CHARS(_s) brk_ag_char_map_chars(_s, 16) +#define SPN_GRAPHIC_BACK(s,e) spn_ag_char_map_back(s, e, 16) +#define BRK_GRAPHIC_BACK(s,e) brk_ag_char_map_back(s, e, 16) +#define IS_INVERSION_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00008000) +#define SPN_INVERSION_CHARS(_s) spn_ag_char_map_chars(_s, 17) +#define BRK_INVERSION_CHARS(_s) brk_ag_char_map_chars(_s, 17) +#define SPN_INVERSION_BACK(s,e) spn_ag_char_map_back(s, e, 17) +#define BRK_INVERSION_BACK(s,e) brk_ag_char_map_back(s, e, 17) +#define IS_OCT_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00010000) +#define SPN_OCT_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 18) +#define BRK_OCT_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 18) +#define SPN_OCT_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 18) +#define BRK_OCT_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 18) +#define IS_DEC_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00030000) +#define SPN_DEC_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 19) +#define BRK_DEC_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 19) +#define SPN_DEC_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 19) +#define BRK_DEC_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 19) +#define IS_HEX_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00070000) +#define SPN_HEX_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 20) +#define BRK_HEX_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 20) +#define SPN_HEX_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 20) +#define BRK_HEX_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 20) +#define IS_LOWER_CASE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00080000) +#define SPN_LOWER_CASE_CHARS(_s) spn_ag_char_map_chars(_s, 21) +#define BRK_LOWER_CASE_CHARS(_s) brk_ag_char_map_chars(_s, 21) +#define SPN_LOWER_CASE_BACK(s,e) spn_ag_char_map_back(s, e, 21) +#define BRK_LOWER_CASE_BACK(s,e) brk_ag_char_map_back(s, e, 21) +#define IS_UPPER_CASE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00100000) +#define SPN_UPPER_CASE_CHARS(_s) spn_ag_char_map_chars(_s, 22) +#define BRK_UPPER_CASE_CHARS(_s) brk_ag_char_map_chars(_s, 22) +#define SPN_UPPER_CASE_BACK(s,e) spn_ag_char_map_back(s, e, 22) +#define BRK_UPPER_CASE_BACK(s,e) brk_ag_char_map_back(s, e, 22) +#define IS_ALPHABETIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00180000) +#define SPN_ALPHABETIC_CHARS(_s) spn_ag_char_map_chars(_s, 23) +#define BRK_ALPHABETIC_CHARS(_s) brk_ag_char_map_chars(_s, 23) +#define SPN_ALPHABETIC_BACK(s,e) spn_ag_char_map_back(s, e, 23) +#define BRK_ALPHABETIC_BACK(s,e) brk_ag_char_map_back(s, e, 23) +#define IS_ALPHANUMERIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x001B0000) +#define SPN_ALPHANUMERIC_CHARS(_s) spn_ag_char_map_chars(_s, 24) +#define BRK_ALPHANUMERIC_CHARS(_s) brk_ag_char_map_chars(_s, 24) +#define SPN_ALPHANUMERIC_BACK(s,e) spn_ag_char_map_back(s, e, 24) +#define BRK_ALPHANUMERIC_BACK(s,e) brk_ag_char_map_back(s, e, 24) +#define IS_VAR_FIRST_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00180040) +#define SPN_VAR_FIRST_CHARS(_s) spn_ag_char_map_chars(_s, 25) +#define BRK_VAR_FIRST_CHARS(_s) brk_ag_char_map_chars(_s, 25) +#define SPN_VAR_FIRST_BACK(s,e) spn_ag_char_map_back(s, e, 25) +#define BRK_VAR_FIRST_BACK(s,e) brk_ag_char_map_back(s, e, 25) +#define IS_VARIABLE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x001B0040) +#define SPN_VARIABLE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 26) +#define BRK_VARIABLE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 26) +#define SPN_VARIABLE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 26) +#define BRK_VARIABLE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 26) +#define IS_OPTION_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x003B0040) +#define SPN_OPTION_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 27) +#define BRK_OPTION_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 27) +#define SPN_OPTION_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 27) +#define BRK_OPTION_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 27) +#define IS_VALUE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x003B0060) +#define SPN_VALUE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 28) +#define BRK_VALUE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 28) +#define SPN_VALUE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 28) +#define BRK_VALUE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 28) +#define IS_NAME_SEP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00400000) +#define SPN_NAME_SEP_CHARS(_s) spn_ag_char_map_chars(_s, 29) +#define BRK_NAME_SEP_CHARS(_s) brk_ag_char_map_chars(_s, 29) +#define SPN_NAME_SEP_BACK(s,e) spn_ag_char_map_back(s, e, 29) +#define BRK_NAME_SEP_BACK(s,e) brk_ag_char_map_back(s, e, 29) +#define IS_COMPOUND_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x007B0460) +#define SPN_COMPOUND_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 30) +#define BRK_COMPOUND_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 30) +#define SPN_COMPOUND_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 30) +#define BRK_COMPOUND_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 30) +#define IS_SCHEME_NOTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00003000) +#define SPN_SCHEME_NOTE_CHARS(_s) spn_ag_char_map_chars(_s, 31) +#define BRK_SCHEME_NOTE_CHARS(_s) brk_ag_char_map_chars(_s, 31) +#define SPN_SCHEME_NOTE_BACK(s,e) spn_ag_char_map_back(s, e, 31) +#define BRK_SCHEME_NOTE_BACK(s,e) brk_ag_char_map_back(s, e, 31) +#define IS_UNQUOTABLE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00800000) +#define SPN_UNQUOTABLE_CHARS(_s) spn_ag_char_map_chars(_s, 32) +#define BRK_UNQUOTABLE_CHARS(_s) brk_ag_char_map_chars(_s, 32) +#define SPN_UNQUOTABLE_BACK(s,e) spn_ag_char_map_back(s, e, 32) +#define BRK_UNQUOTABLE_BACK(s,e) brk_ag_char_map_back(s, e, 32) +#define IS_END_XML_TOKEN_CHAR( _c) is_ag_char_map_char((char)(_c), 0x01000C01) +#define SPN_END_XML_TOKEN_CHARS(_s) spn_ag_char_map_chars(_s, 33) +#define BRK_END_XML_TOKEN_CHARS(_s) brk_ag_char_map_chars(_s, 33) +#define SPN_END_XML_TOKEN_BACK(s,e) spn_ag_char_map_back(s, e, 33) +#define BRK_END_XML_TOKEN_BACK(s,e) brk_ag_char_map_back(s, e, 33) +#define IS_PLUS_N_SPACE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C81) +#define SPN_PLUS_N_SPACE_CHARS(_s) spn_ag_char_map_chars(_s, 34) +#define BRK_PLUS_N_SPACE_CHARS(_s) brk_ag_char_map_chars(_s, 34) +#define SPN_PLUS_N_SPACE_BACK(s,e) spn_ag_char_map_back(s, e, 34) +#define BRK_PLUS_N_SPACE_BACK(s,e) brk_ag_char_map_back(s, e, 34) +#define IS_PUNCTUATION_CHAR( _c) is_ag_char_map_char((char)(_c), 0x02000000) +#define SPN_PUNCTUATION_CHARS(_s) spn_ag_char_map_chars(_s, 35) +#define BRK_PUNCTUATION_CHARS(_s) brk_ag_char_map_chars(_s, 35) +#define SPN_PUNCTUATION_BACK(s,e) spn_ag_char_map_back(s, e, 35) +#define BRK_PUNCTUATION_BACK(s,e) brk_ag_char_map_back(s, e, 35) +#define IS_SUFFIX_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B0000) +#define SPN_SUFFIX_CHARS(_s) spn_ag_char_map_chars(_s, 36) +#define BRK_SUFFIX_CHARS(_s) brk_ag_char_map_chars(_s, 36) +#define SPN_SUFFIX_BACK(s,e) spn_ag_char_map_back(s, e, 36) +#define BRK_SUFFIX_BACK(s,e) brk_ag_char_map_back(s, e, 36) +#define IS_SUFFIX_FMT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B000C) +#define SPN_SUFFIX_FMT_CHARS(_s) spn_ag_char_map_chars(_s, 37) +#define BRK_SUFFIX_FMT_CHARS(_s) brk_ag_char_map_chars(_s, 37) +#define SPN_SUFFIX_FMT_BACK(s,e) spn_ag_char_map_back(s, e, 37) +#define BRK_SUFFIX_FMT_BACK(s,e) brk_ag_char_map_back(s, e, 37) +#define IS_FALSE_TYPE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x08000002) +#define SPN_FALSE_TYPE_CHARS(_s) spn_ag_char_map_chars(_s, 38) +#define BRK_FALSE_TYPE_CHARS(_s) brk_ag_char_map_chars(_s, 38) +#define SPN_FALSE_TYPE_BACK(s,e) spn_ag_char_map_back(s, e, 38) +#define BRK_FALSE_TYPE_BACK(s,e) brk_ag_char_map_back(s, e, 38) +#define IS_FILE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B0004) +#define SPN_FILE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 39) +#define BRK_FILE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 39) +#define SPN_FILE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 39) +#define BRK_FILE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 39) +#define IS_END_TOKEN_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C03) +#define SPN_END_TOKEN_CHARS(_s) spn_ag_char_map_chars(_s, 40) +#define BRK_END_TOKEN_CHARS(_s) brk_ag_char_map_chars(_s, 40) +#define SPN_END_TOKEN_BACK(s,e) spn_ag_char_map_back(s, e, 40) +#define BRK_END_TOKEN_BACK(s,e) brk_ag_char_map_back(s, e, 40) +#define IS_END_LIST_ENTRY_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C13) +#define SPN_END_LIST_ENTRY_CHARS(_s) spn_ag_char_map_chars(_s, 41) +#define BRK_END_LIST_ENTRY_CHARS(_s) brk_ag_char_map_chars(_s, 41) +#define SPN_END_LIST_ENTRY_BACK(s,e) spn_ag_char_map_back(s, e, 41) +#define BRK_END_LIST_ENTRY_BACK(s,e) brk_ag_char_map_back(s, e, 41) +#define IS_SET_SEPARATOR_CHAR( _c) is_ag_char_map_char((char)(_c), 0x10000C13) +#define SPN_SET_SEPARATOR_CHARS(_s) spn_ag_char_map_chars(_s, 42) +#define BRK_SET_SEPARATOR_CHARS(_s) brk_ag_char_map_chars(_s, 42) +#define SPN_SET_SEPARATOR_BACK(s,e) spn_ag_char_map_back(s, e, 42) +#define BRK_SET_SEPARATOR_BACK(s,e) brk_ag_char_map_back(s, e, 42) +#define IS_SIGNED_NUMBER_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00038000) +#define SPN_SIGNED_NUMBER_CHARS(_s) spn_ag_char_map_chars(_s, 43) +#define BRK_SIGNED_NUMBER_CHARS(_s) brk_ag_char_map_chars(_s, 43) +#define SPN_SIGNED_NUMBER_BACK(s,e) spn_ag_char_map_back(s, e, 43) +#define BRK_SIGNED_NUMBER_BACK(s,e) brk_ag_char_map_back(s, e, 43) +#define IS_MAKE_SCRIPT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000101) +#define SPN_MAKE_SCRIPT_CHARS(_s) spn_ag_char_map_chars(_s, 44) +#define BRK_MAKE_SCRIPT_CHARS(_s) brk_ag_char_map_chars(_s, 44) +#define SPN_MAKE_SCRIPT_BACK(s,e) spn_ag_char_map_back(s, e, 44) +#define BRK_MAKE_SCRIPT_BACK(s,e) brk_ag_char_map_back(s, e, 44) +#define IS_LOAD_LINE_SKIP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000600) +#define SPN_LOAD_LINE_SKIP_CHARS(_s) spn_ag_char_map_chars(_s, 45) +#define BRK_LOAD_LINE_SKIP_CHARS(_s) brk_ag_char_map_chars(_s, 45) +#define SPN_LOAD_LINE_SKIP_BACK(s,e) spn_ag_char_map_back(s, e, 45) +#define BRK_LOAD_LINE_SKIP_BACK(s,e) brk_ag_char_map_back(s, e, 45) + +static ag_char_map_mask_t const ag_char_map_table[128] = { + /*NUL*/ 0x00000002, /*x01*/ 0x00000000, /*x02*/ 0x00000000, /*x03*/ 0x00000000, + /*x04*/ 0x00000000, /*x05*/ 0x00000000, /*x06*/ 0x00000000, /*BEL*/ 0x00000000, + /* BS*/ 0x00000800, /* HT*/ 0x00000400, /* NL*/ 0x00000001, /* VT*/ 0x00000800, + /* FF*/ 0x00000800, /* CR*/ 0x00000800, /*x0E*/ 0x00000000, /*x0F*/ 0x00000000, + /*x10*/ 0x00000000, /*x11*/ 0x00000000, /*x12*/ 0x00000000, /*x13*/ 0x00000000, + /*x14*/ 0x00000000, /*x15*/ 0x00000000, /*x16*/ 0x00000000, /*x17*/ 0x00000000, + /*x18*/ 0x00000000, /*x19*/ 0x00000000, /*x1A*/ 0x00000000, /*ESC*/ 0x00000000, + /*x1C*/ 0x00000000, /*x1D*/ 0x00000000, /*x1E*/ 0x00000000, /*x1F*/ 0x00000000, + /* */ 0x00000400, /* ! */ 0x02804000, /* " */ 0x02005000, /* # */ 0x02004000, + /* $ */ 0x02804100, /* % */ 0x02804008, /* & */ 0x02804000, /* ' */ 0x02005000, + /* ( */ 0x02006000, /* ) */ 0x02006000, /* * */ 0x02004000, /* + */ 0x12804080, + /* , */ 0x02004010, /* - */ 0x06A0C200, /* . */ 0x06C04000, /* / */ 0x03804004, + /* 0 */ 0x08814000, /* 1 */ 0x00814000, /* 2 */ 0x00814000, /* 3 */ 0x00814000, + /* 4 */ 0x00814000, /* 5 */ 0x00814000, /* 6 */ 0x00814000, /* 7 */ 0x00814000, + /* 8 */ 0x00824000, /* 9 */ 0x00824000, /* : */ 0x02804020, /* ; */ 0x02004000, + /* < */ 0x02004000, /* = */ 0x02004000, /* > */ 0x03004000, /* ? */ 0x02004000, + /* @ */ 0x02804000, /* A */ 0x00944000, /* B */ 0x00944000, /* C */ 0x00944000, + /* D */ 0x00944000, /* E */ 0x00944000, /* F */ 0x08944000, /* G */ 0x00904000, + /* H */ 0x00904000, /* I */ 0x00904000, /* J */ 0x00904000, /* K */ 0x00904000, + /* L */ 0x00904000, /* M */ 0x00904000, /* N */ 0x08904000, /* O */ 0x00904000, + /* P */ 0x00904000, /* Q */ 0x00904000, /* R */ 0x00904000, /* S */ 0x00904000, + /* T */ 0x00904000, /* U */ 0x00904000, /* V */ 0x00904000, /* W */ 0x00904000, + /* X */ 0x00904000, /* Y */ 0x00904000, /* Z */ 0x00904000, /* [ */ 0x02404000, + /* \ */ 0x02004004, /* ] */ 0x02404000, /* ^ */ 0x02A04000, /* _ */ 0x04804040, + /* ` */ 0x02004000, /* a */ 0x008C4000, /* b */ 0x008C4000, /* c */ 0x008C4000, + /* d */ 0x008C4000, /* e */ 0x008C4000, /* f */ 0x088C4000, /* g */ 0x00884000, + /* h */ 0x00884000, /* i */ 0x00884000, /* j */ 0x00884000, /* k */ 0x00884000, + /* l */ 0x00884000, /* m */ 0x00884000, /* n */ 0x08884000, /* o */ 0x00884000, + /* p */ 0x00884000, /* q */ 0x00884000, /* r */ 0x00884000, /* s */ 0x00884000, + /* t */ 0x00884000, /* u */ 0x00884000, /* v */ 0x00884000, /* w */ 0x00884000, + /* x */ 0x00884000, /* y */ 0x00884000, /* z */ 0x00884000, /* { */ 0x02004000, + /* | */ 0x12804000, /* } */ 0x02004000, /* ~ */ 0x0280C000, /*x7F*/ 0x00000000 +}; + +#include <stdlib.h> +#include <string.h> + +static unsigned char const * ag_char_map_spanners[46]; +/** + * Character category masks. Some categories may have multiple bits, + * if their definition incorporates other character categories. + * This mask array is only used by calc_ag_char_map_spanners(). + */ +static ag_char_map_mask_t const ag_char_map_masks[46] = { + 0x00000001, /* NEWLINE */ + 0x00000002, /* NUL_BYTE */ + 0x00000004, /* DIR_SEP */ + 0x00000008, /* PERCENT */ + 0x00000010, /* COMMA */ + 0x00000020, /* COLON */ + 0x00000040, /* UNDERSCORE */ + 0x00000080, /* PLUS */ + 0x00000100, /* DOLLAR */ + 0x00000200, /* OPTION_MARKER */ + 0x00000400, /* HORIZ_WHITE */ + 0x00000800, /* ALT_WHITE */ + 0x00000C01, /* WHITESPACE */ + 0x00000C00, /* NON_NL_WHITE */ + 0x00001000, /* QUOTE */ + 0x00002000, /* PARENTHESES */ + 0x00004000, /* GRAPHIC */ + 0x00008000, /* INVERSION */ + 0x00010000, /* OCT_DIGIT */ + 0x00030000, /* DEC_DIGIT */ + 0x00070000, /* HEX_DIGIT */ + 0x00080000, /* LOWER_CASE */ + 0x00100000, /* UPPER_CASE */ + 0x00180000, /* ALPHABETIC */ + 0x001B0000, /* ALPHANUMERIC */ + 0x00180040, /* VAR_FIRST */ + 0x001B0040, /* VARIABLE_NAME */ + 0x003B0040, /* OPTION_NAME */ + 0x003B0060, /* VALUE_NAME */ + 0x00400000, /* NAME_SEP */ + 0x007B0460, /* COMPOUND_NAME */ + 0x00003000, /* SCHEME_NOTE */ + 0x00800000, /* UNQUOTABLE */ + 0x01000C01, /* END_XML_TOKEN */ + 0x00000C81, /* PLUS_N_SPACE */ + 0x02000000, /* PUNCTUATION */ + 0x041B0000, /* SUFFIX */ + 0x041B000C, /* SUFFIX_FMT */ + 0x08000002, /* FALSE_TYPE */ + 0x041B0004, /* FILE_NAME */ + 0x00000C03, /* END_TOKEN */ + 0x00000C13, /* END_LIST_ENTRY */ + 0x10000C13, /* SET_SEPARATOR */ + 0x00038000, /* SIGNED_NUMBER */ + 0x00000101, /* MAKE_SCRIPT */ + 0x00000600, /* LOAD_LINE_SKIP */ +}; + +#define lock_ag_char_map_spanners() +#define unlock_ag_char_map_spanners() + +static unsigned char const * +calc_ag_char_map_spanners(unsigned int mask_ix) +{ + lock_ag_char_map_spanners(); + if (ag_char_map_spanners[mask_ix] == NULL) { + int ix = 1; + ag_char_map_mask_t mask = ag_char_map_masks[mask_ix]; + unsigned char * res = malloc(256 /* 1 << NBBY */); + memset(res, 0, 256); + for (; ix < 128; ix++) + if (ag_char_map_table[ix] & mask) + res[ix] = 1; + ag_char_map_spanners[mask_ix] = res; + } + unlock_ag_char_map_spanners(); + return ag_char_map_spanners[mask_ix]; +} +#define ag_char_map_masks POISONED_ag_char_map_masks + +static inline int +is_ag_char_map_char(char ch, ag_char_map_mask_t mask) +{ + unsigned int ix = (unsigned char)ch; + return ((ix < 128) && ((ag_char_map_table[ix] & mask) != 0)); +} + +static inline char * +spn_ag_char_map_chars(char const * p, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + while (v[(unsigned)*p]) p++; + return (char *)(uintptr_t)p; +} + +static inline char * +brk_ag_char_map_chars(char const * p, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + while ((*p != '\0') && (! v[(unsigned)*p])) p++; + return (char *)(uintptr_t)p; +} + +static inline char * +spn_ag_char_map_back(char const * s, char const * e, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + if (s >= e) e = s + strlen(s); + while ((e > s) && v[(unsigned)e[-1]]) e--; + return (char *)(uintptr_t)e; +} + +static inline char * +brk_ag_char_map_back(char const * s, char const * e, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + if (s == e) e += strlen(e); + while ((e > s) && (! v[(unsigned)e[-1]])) e--; + return (char *)(uintptr_t)e; +} +#endif /* AG_CHAR_MAP_H_GUARD */ diff --git a/autoopts/alias.c b/autoopts/alias.c new file mode 100644 index 0000000..f42b619 --- /dev/null +++ b/autoopts/alias.c @@ -0,0 +1,108 @@ + +/** + * \file alias.c + * + * Time-stamp: "2012-08-11 08:15:43 bkorb" + * + * Automated Options Paged Usage module. + * + * This routine will forward an option alias to the correct option code. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionAlias + * private: + * + * what: relay an option to its alias + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * arg: + unsigned int + alias + the aliased-to option index + + * ret-type: int + * + * doc: + * Handle one option as if it had been specified as another. Exactly. + * Returns "-1" if the aliased-to option has appeared too many times. +=*/ +int +optionAlias(tOptions * pOpts, tOptDesc * pOldOD, unsigned int alias) +{ + tOptDesc * pOD; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return 0; + + pOD = pOpts->pOptDesc + alias; + if ((unsigned)pOpts->optCt <= alias) { + fwrite(zAliasRange, strlen (zAliasRange), 1, stderr); + exit(EXIT_FAILURE); + } + + /* + * Copy over the option instance flags + */ + pOD->fOptState &= OPTST_PERSISTENT_MASK; + pOD->fOptState |= (pOldOD->fOptState & ~OPTST_PERSISTENT_MASK); + pOD->optArg.argString = pOldOD->optArg.argString; + + /* + * Keep track of count only for DEFINED (command line) options. + * IF we have too many, build up an error message and bail. + */ + if ( (pOD->fOptState & OPTST_DEFINED) + && (++pOD->optOccCt > pOD->optMaxCt) ) { + + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + char const * pzEqv = + (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil; + + fputs(zErrOnly, stderr); + + if (pOD->optMaxCt > 1) + fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv); + else + fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv); + } + + return -1; + } + + /* + * Clear the state bits and counters + */ + pOldOD->fOptState &= OPTST_PERSISTENT_MASK; + pOldOD->optOccCt = 0; + + /* + * If there is a procedure to call, call it + */ + if (pOD->pOptProc != NULL) + (*pOD->pOptProc)(pOpts, pOD); + return 0; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/alias.c */ diff --git a/autoopts/ao-strs.c b/autoopts/ao-strs.c new file mode 100644 index 0000000..5f16caa --- /dev/null +++ b/autoopts/ao-strs.c @@ -0,0 +1,323 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (ao-strs.c) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:13 AM by AutoGen 5.16.2pre7 + * From the definitions ao-strs.def + * and the template file strings + * + * Copyright (C) 2011-2012 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * Modified (3 clause) Berkeley Software Distribution License + * <http://www.xfree86.org/3.3.6/COPYRIGHT2.html> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * strings IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "ao-strs.h" + +char const ao_strs_strtable[6265] = +/* 0 */ " \t\n" + ":=\0" +/* 6 */ "INVALID-%d\0" +/* 17 */ "*INVALID*\0" +/* 27 */ "none\0" +/* 32 */ " + \0" +/* 36 */ " | \0" +/* 40 */ "%s\n\0" +/* 44 */ "PAGER\0" +/* 50 */ "/tmp/use.%lu\0" +/* 63 */ "more\0" +/* 68 */ " --* )\n\0" +/* 79 */ "%s\n" + " \0" +/* 85 */ " \0" +/* 88 */ " -* )\n\0" +/* 98 */ " ;;\n\n\0" +/* 111 */ "stdout\0" +/* 118 */ "%A %B %e, %Y at %r %Z\0" +/* 140 */ "#! %s\n\0" +/* 147 */ "%s_%s=\0" +/* 154 */ "\n" + "export %s_%s\n\0" +/* 169 */ "''\0" +/* 172 */ "\\'\0" +/* 175 */ "'%s'\0" +/* 180 */ "%s_%s_%d=\0" +/* 190 */ "\n" + "export %s_%s_%d\n\0" +/* 208 */ "set --\0" +/* 215 */ " '%s'\0" +/* 221 */ "'\\''\0" +/* 226 */ "\n" + "OPTION_CT=0\n\0" +/* 240 */ "=%1$lu # 0x%1$lX\n\0" +/* 258 */ "true\0" +/* 263 */ "false\0" +/* 269 */ "VERSION\0" +/* 277 */ "OPT_ARG_NEEDED=OK\0" +/* 295 */ "OPT_ARG_NEEDED=NO\0" +/* 313 */ "OPT_ARG_NEEDED=YES\0" +/* 332 */ "LONGUSAGE\0" +/* 342 */ "flag\0" +/* 347 */ "%s_%s_TEXT='\0" +/* 360 */ "'\n\n\0" +/* 364 */ "option\0" +/* 371 */ "\n" + "env | grep '^%s_'\n\0" +/* 391 */ " -- %s\0" +/* 398 */ "--\0" +/* 401 */ "\t\t\t\t- \0" +/* 408 */ "\t\t\t\t \0" +/* 415 */ "\t\0" +/* 417 */ " * )\n" + " OPT_PROCESS=false\n" + " ;;\n" + " esac\n\0" +/* 474 */ " %s\n\0" +/* 480 */ "%%-%ds\0" +/* 487 */ "%1$s /tmp/use.%2$lu ; rm -f /tmp/use.%2$lu\0" +/* 530 */ "# # # # # # # # # # -- do not modify this marker --\n" + "#\n" + "# DO NOT EDIT THIS SECTION\0" +/* 612 */ "%s OF %s\n" + "#\n" + "# From here to the next `-- do not modify this marker --',\n" + "# the text has been generated %s\n\0" +/* 718 */ "# From the %s option definitions\n" + "#\n\0" +/* 755 */ "\n" + "if test -z \"${%1$s_%2$s}\"\n" + "then\n" + " %1$s_%2$s_CT=0\n" + "else\n" + " %1$s_%2$s_CT=1\n" + " %1$s_%2$s_1=${%1$s_%2$s}\n" + "fi\n" + "export %1$s_%2$s_CT\0" +/* 876 */ "\n" + "%1$s_%2$s=${%1$s_%2$s-'%3$s'}\n" + "%1$s_%2$s_set=false\n" + "export %1$s_%2$s\0" +/* 944 */ "\n" + "%1$s_%2$s=${%1$s_%2$s}\n" + "%1$s_%2$s_set=false\n" + "export %1$s_%2$s\n\0" +/* 1006 */ "\n" + "OPT_PROCESS=true\n" + "OPT_ARG=$1\n" + "while ${OPT_PROCESS} && [ $# -gt 0 ]\n" + "do\n" + " OPT_ELEMENT=''\n" + " OPT_ARG_VAL=''\n\n" + " case \"${OPT_ARG}\" in\n" + " -- )\n" + " OPT_PROCESS=false\n" + " shift\n" + " ;;\n\0" +/* 1200 */ "\n" + "OPT_ARG=$1\n" + "while [ $# -gt 0 ]\n" + "do\n" + " OPT_ELEMENT=''\n" + " OPT_ARG_VAL=''\n" + " OPT_ARG=${1}\n\0" +/* 1290 */ " if [ -n \"${OPT_ARG_VAL}\" ]\n" + " then\n" + " eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n" + " export %1$s_${OPT_NAME}${OPT_ELEMENT}\n" + " fi\n" + "done\n" + "unset OPT_PROCESS || :\n" + "unset OPT_ELEMENT || :\n" + "unset OPT_ARG || :\n" + "unset OPT_ARG_NEEDED || :\n" + "unset OPT_NAME || :\n" + "unset OPT_CODE || :\n" + "unset OPT_ARG_VAL || :\n" + "%2$s\0" +/* 1620 */ "\n" + "# # # # # # # # # #\n" + "#\n" + "# END OF AUTOMATED OPTION PROCESSING\n" + "#\n" + "# # # # # # # # # # -- do not modify this marker --\n\0" +/* 1736 */ " case \"${OPT_CODE}\" in\n\0" +/* 1767 */ " '%s' | \\\n\0" +/* 1785 */ " '%s' )\n\0" +/* 1801 */ " '%c' )\n\0" +/* 1817 */ " ;;\n\n\0" +/* 1834 */ " * )\n" + " echo Unknown %s: \"${OPT_CODE}\" >&2\n" + " echo \"$%s_USAGE_TEXT\"\n" + " exit 1\n" + " ;;\n" + " esac\n\n\0" +/* 1976 */ " echo \"$%s_%s_TEXT\"\n" + " exit 0\n\0" +/* 2027 */ " echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n" + " exit 0\n\0" +/* 2101 */ " %s\n\0" +/* 2117 */ " if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n" + " echo Error: more than %3$d %2$s options >&2\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1 ; fi\n\0" +/* 2296 */ " %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n" + " OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n" + " OPT_NAME='%2$s'\n\0" +/* 2420 */ " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" + " echo Error: duplicate %2$s option >&2\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1 ; fi\n" + " %1$s_%2$s_set=true\n" + " OPT_NAME='%2$s'\n\0" +/* 2667 */ " %1$s_%2$s_CT=0\n" + " OPT_ELEMENT=''\n" + " %1$s_%2$s='%3$s'\n" + " export %1$s_%2$s\n" + " OPT_NAME='%2$s'\n\0" +/* 2808 */ " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" + " echo 'Error: duplicate %2$s option' >&2\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1 ; fi\n" + " %1$s_%2$s_set=true\n" + " %1$s_%2$s='%3$s'\n" + " export %1$s_%2$s\n" + " OPT_NAME='%2$s'\n\0" +/* 3115 */ " eval %1$s_%2$s${OPT_ELEMENT}=true\n" + " export %1$s_%2$s${OPT_ELEMENT}\n" + " OPT_ARG_NEEDED=OK\n\0" +/* 3235 */ " OPT_ARG_NEEDED=YES\n\0" +/* 3267 */ " eval %1$s_%2$s${OPT_ELEMENT}=true\n" + " export %1$s_%2$s${OPT_ELEMENT}\n" + " OPT_ARG_NEEDED=NO\n\0" +/* 3387 */ " OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n" + " shift\n" + " OPT_ARG=$1\n" + " case \"${OPT_CODE}\" in *=* )\n" + " OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n" + " OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\0" +/* 3638 */ " case \"${OPT_ARG_NEEDED}\" in\n" + " NO )\n" + " OPT_ARG_VAL=''\n" + " ;;\n" + " YES )\n" + " if [ -z \"${OPT_ARG_VAL}\" ]\n" + " then\n" + " if [ $# -eq 0 ]\n" + " then\n" + " echo No argument provided for ${OPT_NAME} option >&2\n" + " echo \"$%s_USAGE_TEXT\"\n" + " exit 1\n" + " fi\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1\n" + " fi\n" + " ;;\n" + " OK )\n" + " if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n" + " then\n" + " case \"${OPT_ARG}\" in -* ) ;; * )\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1 ;; esac\n" + " fi\n" + " ;;\n" + " esac\n\0" +/* 4417 */ " OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n" + " OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\0" +/* 4534 */ " case \"${OPT_ARG_NEEDED}\" in\n" + " NO )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG=-${OPT_ARG}\n" + " else\n" + " shift\n" + " OPT_ARG=$1\n" + " fi\n" + " ;;\n" + " YES )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " else\n" + " if [ $# -eq 0 ]\n" + " then\n" + " echo No argument provided for ${OPT_NAME} option >&2\n" + " echo \"$%s_USAGE_TEXT\"\n" + " exit 1\n" + " fi\n" + " shift\n" + " OPT_ARG_VAL=$1\n" + " fi\n" + " shift\n" + " OPT_ARG=$1\n" + " ;;\n" + " OK )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1\n" + " else\n" + " shift\n" + " if [ $# -gt 0 ]\n" + " then\n" + " case \"$1\" in -* ) ;; * )\n" + " OPT_ARG_VAL=$1\n" + " shift ;; esac\n" + " OPT_ARG=$1\n" + " fi\n" + " fi\n" + " ;;\n" + " esac\n\0" +/* 5688 */ "%1$s_%2$s=%3$d # 0x%3$X\n" + "export %1$s_%2$s\n\0" +/* 5730 */ "%1$s_%2$s_CT=%3$d\n" + "export %1$s_%2$s_CT\n\0" +/* 5769 */ "OPTION_CT=%d\n" + "export OPTION_CT\n\0" +/* 5800 */ "%1$s_%2$s=%3$s\n" + "export %1$s_%2$s\n\0" +/* 5833 */ "%1$s_%2$s='%3$s'\n" + "export %1$s_%2$s\n\0" +/* 5868 */ "%1$s_%2$s_MODE='%3$s'\n" + "export %1$s_%2$s_MODE\n\0" +/* 5913 */ "echo 'Warning: Cannot load options files' >&2\0" +/* 5960 */ "echo 'Warning: Cannot save options files' >&2\0" +/* 6007 */ "echo 'Warning: Cannot suppress the loading of options files' >&2\0" +/* 6073 */ "%1$s_%2$s_TEXT='no %2$s text'\n\0" +/* 6104 */ "%s WARNING: cannot save options - \0" +/* 6140 */ "<%s/>\n\0" +/* 6147 */ "<%s>\0" +/* 6152 */ "</%s>\n\0" +/* 6159 */ "<%s type=%s>\0" +/* 6172 */ "<%s type=nested>\n\0" +/* 6190 */ "#x%02X;\0" +/* 6198 */ "<%1$s type=boolean>%2$s</%1$s>\n\0" +/* 6230 */ "<%1$s type=integer>0x%2$lX</%1$s>\n"; + +/* end of ao-strs.c */ diff --git a/autoopts/ao-strs.def b/autoopts/ao-strs.def new file mode 100644 index 0000000..624f872 --- /dev/null +++ b/autoopts/ao-strs.def @@ -0,0 +1,429 @@ +AutoGen Definitions strings; + +string = { nm = ARG_BREAK_STR; str = " \t\n:="; }; +string = { nm = INVALID_FMT; str = "INVALID-%d"; }; +string = { nm = INVALID_STR; str = "*INVALID*"; }; +string = { nm = NONE_STR; str = "none"; }; +string = { nm = PLUS_STR; str = " + "; }; +string = { nm = OR_STR; str = " | "; }; +string = { nm = NLSTR_FMT; str = "%s\n"; }; +string = { nm = PAGER_NAME; str = "PAGER"; }; +string = { nm = TMP_USAGE_FMT; str = "/tmp/use.%lu"; }; +string = { nm = MORE_STR; str = "more"; }; +string = { nm = LONG_OPT_MARK; str = " --* )\n"; }; +string = { nm = NLSTR_SPACE_FMT; str = "%s\n "; }; +string = { nm = TWO_SPACES_STR; str = " "; }; +string = { nm = FLAG_OPT_MARK; str = " -* )\n"; }; +string = { nm = END_OPT_SEL_STR; str = " ;;\n\n"; }; +string = { nm = STDOUT; str = "stdout"; }; +string = { nm = TIME_FMT; str = "%A %B %e, %Y at %r %Z"; }; +string = { nm = SHELL_MAGIC; str = "#! %s\n"; }; +string = { nm = OPT_VAL_FMT; str = "%s_%s="; }; +string = { nm = OPT_END_FMT; str = "\nexport %s_%s\n"; }; +string = { nm = EMPTY_ARG; str = "''"; }; +string = { nm = QUOT_APOS; str = "\\'"; }; +string = { nm = QUOT_ARG_FMT; str = "'%s'"; }; +string = { nm = ARG_BY_NUM_FMT; str = "%s_%s_%d="; }; +string = { nm = EXPORT_ARG_FMT; str = "\nexport %s_%s_%d\n"; }; +string = { nm = set_dash; str = "set --"; }; +string = { nm = arg_fmt; str = " '%s'"; }; +string = { nm = apostrophy; str = "'\\''"; }; +string = { nm = init_optct; str = "\nOPTION_CT=0\n"; }; +string = { nm = SHOW_VAL_FMT; str = "=%1$lu # 0x%1$lX\n"; }; +string = { nm = TRUE_STR; str = "true"; }; +string = { nm = FALSE_STR; str = "false"; }; +string = { nm = VER_STR; str = "VERSION"; }; +string = { nm = OK_NEED_OPT_ARG; str = "OPT_ARG_NEEDED=OK"; }; +string = { nm = NO_ARG_NEEDED; str = "OPT_ARG_NEEDED=NO"; }; +string = { nm = YES_NEED_OPT_ARG; str = "OPT_ARG_NEEDED=YES"; }; +string = { nm = LONG_USE_STR; str = "LONGUSAGE"; }; +string = { nm = FLAG_STR; str = "flag"; }; +string = { nm = SET_TEXT_FMT; str = "%s_%s_TEXT='"; }; +string = { nm = END_SET_TEXT; str = "'\n\n"; }; +string = { nm = OPTION_STR; str = "option"; }; +string = { nm = SHOW_PROG_ENV; str = "\nenv | grep '^%s_'\n"; }; +string = { nm = SET_OFF_FMT; str = " -- %s"; }; +string = { nm = LONG_OPT_MARKER; str = "--"; }; +string = { nm = BULLET_STR; str = "\t\t\t\t- "; }; +string = { nm = DEEP_INDENT_STR; str = "\t\t\t\t "; }; +string = { nm = ONE_TAB_STR; str = "\t"; }; + +string = { nm = NOT_FOUND_STR; + str = <<- _EOStr_ + * ) + OPT_PROCESS=false + ;; + esac + + _EOStr_; +}; + +string = { nm = ENUM_ERR_SEP_LINE_FMT; + str = " %s\n"; }; + +string = { nm = ENUM_ERR_STR_WIDTH_FMT; + str = "%%-%ds"; }; + +string = { nm = PAGE_USAGE_FMT; + str = "%1$s /tmp/use.%2$lu ; rm -f /tmp/use.%2$lu"; }; + +string = { nm = START_MARK; + str = <<- _EOStr_ + # # # # # # # # # # -- do not modify this marker -- + # + # DO NOT EDIT THIS SECTION + _EOStr_; +}; + +string = { nm = PREAMBLE_FMT; + str = <<- _EOStr_ + %s OF %s + # + # From here to the next `-- do not modify this marker --', + # the text has been generated %s + + _EOStr_; +}; + +string = { nm = END_PRE_FMT; + str = "# From the %s option definitions\n#\n"; }; + +string = { nm = MULTI_DEF_FMT; + str = <<- _EOStr_ + + if test -z "${%1$s_%2$s}" + then + %1$s_%2$s_CT=0 + else + %1$s_%2$s_CT=1 + %1$s_%2$s_1=${%1$s_%2$s} + fi + export %1$s_%2$s_CT + _EOStr_; +}; + +string = { nm = SGL_DEF_FMT; + str = <<- _EOStr_ + + %1$s_%2$s=${%1$s_%2$s-'%3$s'} + %1$s_%2$s_set=false + export %1$s_%2$s + _EOStr_; +}; + +string = { nm = SGL_NO_DEF_FMT; + str = <<- _EOStr_ + + %1$s_%2$s=${%1$s_%2$s} + %1$s_%2$s_set=false + export %1$s_%2$s + + _EOStr_; +}; + + +string = { nm = LOOP_STR; + str = <<- _EOStr_ + + OPT_PROCESS=true + OPT_ARG=$1 + while ${OPT_PROCESS} && [ $# -gt 0 ] + do + OPT_ELEMENT='' + OPT_ARG_VAL='' + + case "${OPT_ARG}" in + -- ) + OPT_PROCESS=false + shift + ;; + + _EOStr_; +}; + +string = { nm = ONLY_OPTS_LOOP; + str = <<- _EOStr_ + + OPT_ARG=$1 + while [ $# -gt 0 ] + do + OPT_ELEMENT='' + OPT_ARG_VAL='' + OPT_ARG=${1} + + _EOStr_; +}; + +string = { nm = zLoopEnd; + str = <<- _EOStr_ + if [ -n "${OPT_ARG_VAL}" ] + then + eval %1$s_${OPT_NAME}${OPT_ELEMENT}="'${OPT_ARG_VAL}'" + export %1$s_${OPT_NAME}${OPT_ELEMENT} + fi + done + unset OPT_PROCESS || : + unset OPT_ELEMENT || : + unset OPT_ARG || : + unset OPT_ARG_NEEDED || : + unset OPT_NAME || : + unset OPT_CODE || : + unset OPT_ARG_VAL || : + %2$s + _EOStr_; +}; + +string = { nm = END_MARK; + str = <<- _EOStr_ + + # # # # # # # # # # + # + # END OF AUTOMATED OPTION PROCESSING + # + # # # # # # # # # # -- do not modify this marker -- + + _EOStr_; +}; + +string = { nm = zOptionCase; + str = " case \"${OPT_CODE}\" in\n"; }; + +string = { nm = zOptionPartName; str = " '%s' | \\\n"; }; +string = { nm = zOptionFullName; str = " '%s' )\n"; }; +string = { nm = zOptionFlag; str = " '%c' )\n"; }; +string = { nm = zOptionEndSelect; str = " ;;\n\n"; }; + +string = { nm = UNK_OPT_FMT; + str = +" * )\n" +" echo Unknown %s: \"${OPT_CODE}\" >&2\n" +" echo \"$%s_USAGE_TEXT\"\n" +" exit 1\n" +" ;;\n" +" esac\n\n"; }; + +string = { nm = zTextExit; + str = +" echo \"$%s_%s_TEXT\"\n" +" exit 0\n"; }; + +string = { nm = zPagedUsageExit; + str = +" echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n" +" exit 0\n"; }; + +string = { nm = zCmdFmt; + str = " %s\n"; }; + +string = { nm = zCountTest; + str = +" if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n" +" echo Error: more than %3$d %2$s options >&2\n" +" echo \"$%1$s_USAGE_TEXT\"\n" +" exit 1 ; fi\n"; }; + +string = { nm = MULTI_ARG_FMT; + str = +" %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n" +" OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n" +" OPT_NAME='%2$s'\n"; }; + +string = { nm = SGL_ARG_FMT; + str = +" if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" +" echo Error: duplicate %2$s option >&2\n" +" echo \"$%1$s_USAGE_TEXT\"\n" +" exit 1 ; fi\n" +" %1$s_%2$s_set=true\n" +" OPT_NAME='%2$s'\n"; }; + +string = { nm = NO_MULTI_ARG_FMT; + str = +" %1$s_%2$s_CT=0\n" +" OPT_ELEMENT=''\n" +" %1$s_%2$s='%3$s'\n" +" export %1$s_%2$s\n" +" OPT_NAME='%2$s'\n"; }; + +string = { nm = NO_SGL_ARG_FMT; + str = <<- _EOStr_ + if [ -n "${%1$s_%2$s}" ] && ${%1$s_%2$s_set} ; then + echo 'Error: duplicate %2$s option' >&2 + echo "$%1$s_USAGE_TEXT" + exit 1 ; fi + %1$s_%2$s_set=true + %1$s_%2$s='%3$s' + export %1$s_%2$s + OPT_NAME='%2$s' + + _EOStr_; +}; + +string = { nm = zMayArg; + str = +" eval %1$s_%2$s${OPT_ELEMENT}=true\n" +" export %1$s_%2$s${OPT_ELEMENT}\n" +" OPT_ARG_NEEDED=OK\n"; }; + +string = { nm = zMustArg; + str = " OPT_ARG_NEEDED=YES\n"; }; + +string = { nm = zCantArg; + str = +" eval %1$s_%2$s${OPT_ELEMENT}=true\n" +" export %1$s_%2$s${OPT_ELEMENT}\n" +" OPT_ARG_NEEDED=NO\n"; }; + +string = { nm = INIT_LOPT_STR; + str = <<- _EOStr_ + OPT_CODE=`echo "X${OPT_ARG}"|sed 's/^X-*//'` + shift + OPT_ARG=$1 + case "${OPT_CODE}" in *=* ) + OPT_ARG_VAL=`echo "${OPT_CODE}"|sed 's/^[^=]*=//'` + OPT_CODE=`echo "${OPT_CODE}"|sed 's/=.*$//'` ;; esac + + _EOStr_; }; + +string = { nm = LOPT_ARG_FMT; + str = <<- _EOStr_ + case "${OPT_ARG_NEEDED}" in + NO ) + OPT_ARG_VAL='' + ;; + YES ) + if [ -z "${OPT_ARG_VAL}" ] + then + if [ $# -eq 0 ] + then + echo No argument provided for ${OPT_NAME} option >&2 + echo "$%s_USAGE_TEXT" + exit 1 + fi + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 + fi + ;; + OK ) + if [ -z "${OPT_ARG_VAL}" ] && [ $# -gt 0 ] + then + case "${OPT_ARG}" in -* ) ;; * ) + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 ;; esac + fi + ;; + esac + + _EOStr_; }; + +string = { nm = INIT_OPT_STR; + str = <<- _EOStr_ + OPT_CODE=`echo "X${OPT_ARG}" | sed 's/X-\(.\).*/\1/'` + OPT_ARG=` echo "X${OPT_ARG}" | sed 's/X-.//'` + + _EOStr_; }; + + +string = { nm = OPT_ARG_FMT; + str = <<- _EOStr_ + case "${OPT_ARG_NEEDED}" in + NO ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG=-${OPT_ARG} + else + shift + OPT_ARG=$1 + fi + ;; + YES ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG_VAL=${OPT_ARG} + else + if [ $# -eq 0 ] + then + echo No argument provided for ${OPT_NAME} option >&2 + echo "$%s_USAGE_TEXT" + exit 1 + fi + shift + OPT_ARG_VAL=$1 + fi + shift + OPT_ARG=$1 + ;; + OK ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 + else + shift + if [ $# -gt 0 ] + then + case "$1" in -* ) ;; * ) + OPT_ARG_VAL=$1 + shift ;; esac + OPT_ARG=$1 + fi + fi + ;; + esac + + _EOStr_; }; + +string = { nm = zOptNumFmt; + str = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n"; }; + +string = { nm = zOptCookieCt; + str = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n"; }; + +string = { nm = zOptCtFmt; + str = "OPTION_CT=%d\nexport OPTION_CT\n"; }; + +string = { nm = zOptDisabl; + str = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n"; }; + +string = { nm = zFullOptFmt; + str = "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n"; }; + +string = { nm = zEquivMode; + str = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n"; }; + +string = { nm = NO_LOAD_WARN; + str = "echo 'Warning: Cannot load options files' >&2"; }; + +string = { nm = NO_SAVE_OPTS; + str = "echo 'Warning: Cannot save options files' >&2"; }; + +string = { nm = NO_SUPPRESS_LOAD; + str = "echo 'Warning: Cannot suppress the loading of options files' >&2"; }; + +string = { nm = SET_NO_TEXT_FMT; + str = "%1$s_%2$s_TEXT='no %2$s text'\n"; }; + +string = { nm = SAVE_WARN; + str = "%s WARNING: cannot save options - "; }; + +string = { nm = OPEN_CLOSE_FMT; str = "<%s/>\n"; }; +string = { nm = OPEN_XML_FMT; str = "<%s>"; }; +string = { nm = END_XML_FMT; str = "</%s>\n"; }; +string = { nm = TYPE_ATR_FMT; str = "<%s type=%s>"; }; +string = { nm = NULL_ATR_FMT; str = "<%s/>\n"; }; +string = { nm = NESTED_OPT_FMT; str = "<%s type=nested>\n"; }; +string = { nm = XML_HEX_BYTE_FMT; str = "#x%02X;"; }; + +string = { nm = BOOL_ATR_FMT; + str = "<%1$s type=boolean>%2$s</%1$s>\n"; }; + +string = { nm = NUMB_ATR_FMT; + str = "<%1$s type=integer>0x%2$lX</%1$s>\n"; }; + +#if 0 +string = { nm = ; + str = ; }; +#endif diff --git a/autoopts/ao-strs.h b/autoopts/ao-strs.h new file mode 100644 index 0000000..62d92ff --- /dev/null +++ b/autoopts/ao-strs.h @@ -0,0 +1,250 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (ao-strs.h) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:13 AM by AutoGen 5.16.2pre7 + * From the definitions ao-strs.def + * and the template file strings + * + * Copyright (C) 2011-2012 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * Modified (3 clause) Berkeley Software Distribution License + * <http://www.xfree86.org/3.3.6/COPYRIGHT2.html> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * strings IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef STRINGS_AO_STRS_H_GUARD +#define STRINGS_AO_STRS_H_GUARD 1 +/* + * 102 strings in ao_strs_strtable string table + */ +#define ARG_BREAK_STR (ao_strs_strtable+0) +#define ARG_BREAK_STR_LEN 5 +#define ARG_BY_NUM_FMT (ao_strs_strtable+180) +#define ARG_BY_NUM_FMT_LEN 9 +#define BOOL_ATR_FMT (ao_strs_strtable+6198) +#define BOOL_ATR_FMT_LEN 31 +#define BULLET_STR (ao_strs_strtable+401) +#define BULLET_STR_LEN 6 +#define DEEP_INDENT_STR (ao_strs_strtable+408) +#define DEEP_INDENT_STR_LEN 6 +#define EMPTY_ARG (ao_strs_strtable+169) +#define EMPTY_ARG_LEN 2 +#define END_MARK (ao_strs_strtable+1620) +#define END_MARK_LEN 115 +#define END_OPT_SEL_STR (ao_strs_strtable+98) +#define END_OPT_SEL_STR_LEN 12 +#define END_PRE_FMT (ao_strs_strtable+718) +#define END_PRE_FMT_LEN 36 +#define END_SET_TEXT (ao_strs_strtable+360) +#define END_SET_TEXT_LEN 3 +#define END_XML_FMT (ao_strs_strtable+6152) +#define END_XML_FMT_LEN 6 +#define ENUM_ERR_SEP_LINE_FMT (ao_strs_strtable+474) +#define ENUM_ERR_SEP_LINE_FMT_LEN 5 +#define ENUM_ERR_STR_WIDTH_FMT (ao_strs_strtable+480) +#define ENUM_ERR_STR_WIDTH_FMT_LEN 6 +#define EXPORT_ARG_FMT (ao_strs_strtable+190) +#define EXPORT_ARG_FMT_LEN 17 +#define FALSE_STR (ao_strs_strtable+263) +#define FALSE_STR_LEN 5 +#define FLAG_OPT_MARK (ao_strs_strtable+88) +#define FLAG_OPT_MARK_LEN 9 +#define FLAG_STR (ao_strs_strtable+342) +#define FLAG_STR_LEN 4 +#define INIT_LOPT_STR (ao_strs_strtable+3387) +#define INIT_LOPT_STR_LEN 250 +#define INIT_OPT_STR (ao_strs_strtable+4417) +#define INIT_OPT_STR_LEN 116 +#define INVALID_FMT (ao_strs_strtable+6) +#define INVALID_FMT_LEN 10 +#define INVALID_STR (ao_strs_strtable+17) +#define INVALID_STR_LEN 9 +#define LONG_OPT_MARK (ao_strs_strtable+68) +#define LONG_OPT_MARKER (ao_strs_strtable+398) +#define LONG_OPT_MARKER_LEN 2 +#define LONG_OPT_MARK_LEN 10 +#define LONG_USE_STR (ao_strs_strtable+332) +#define LONG_USE_STR_LEN 9 +#define LOOP_STR (ao_strs_strtable+1006) +#define LOOP_STR_LEN 193 +#define LOPT_ARG_FMT (ao_strs_strtable+3638) +#define LOPT_ARG_FMT_LEN 778 +#define MORE_STR (ao_strs_strtable+63) +#define MORE_STR_LEN 4 +#define MULTI_ARG_FMT (ao_strs_strtable+2296) +#define MULTI_ARG_FMT_LEN 123 +#define MULTI_DEF_FMT (ao_strs_strtable+755) +#define MULTI_DEF_FMT_LEN 120 +#define NESTED_OPT_FMT (ao_strs_strtable+6172) +#define NESTED_OPT_FMT_LEN 17 +#define NLSTR_FMT (ao_strs_strtable+40) +#define NLSTR_FMT_LEN 3 +#define NLSTR_SPACE_FMT (ao_strs_strtable+79) +#define NLSTR_SPACE_FMT_LEN 5 +#define NONE_STR (ao_strs_strtable+27) +#define NONE_STR_LEN 4 +#define NOT_FOUND_STR (ao_strs_strtable+417) +#define NOT_FOUND_STR_LEN 56 +#define NO_ARG_NEEDED (ao_strs_strtable+295) +#define NO_ARG_NEEDED_LEN 17 +#define NO_LOAD_WARN (ao_strs_strtable+5913) +#define NO_LOAD_WARN_LEN 46 +#define NO_MULTI_ARG_FMT (ao_strs_strtable+2667) +#define NO_MULTI_ARG_FMT_LEN 140 +#define NO_SAVE_OPTS (ao_strs_strtable+5960) +#define NO_SAVE_OPTS_LEN 46 +#define NO_SGL_ARG_FMT (ao_strs_strtable+2808) +#define NO_SGL_ARG_FMT_LEN 306 +#define NO_SUPPRESS_LOAD (ao_strs_strtable+6007) +#define NO_SUPPRESS_LOAD_LEN 65 +#define NULL_ATR_FMT (ao_strs_strtable+6140) +#define NULL_ATR_FMT_LEN 6 +#define NUMB_ATR_FMT (ao_strs_strtable+6230) +#define NUMB_ATR_FMT_LEN 34 +#define OK_NEED_OPT_ARG (ao_strs_strtable+277) +#define OK_NEED_OPT_ARG_LEN 17 +#define ONE_TAB_STR (ao_strs_strtable+415) +#define ONE_TAB_STR_LEN 1 +#define ONLY_OPTS_LOOP (ao_strs_strtable+1200) +#define ONLY_OPTS_LOOP_LEN 89 +#define OPEN_CLOSE_FMT (ao_strs_strtable+6140) +#define OPEN_CLOSE_FMT_LEN 6 +#define OPEN_XML_FMT (ao_strs_strtable+6147) +#define OPEN_XML_FMT_LEN 4 +#define OPTION_STR (ao_strs_strtable+364) +#define OPTION_STR_LEN 6 +#define OPT_ARG_FMT (ao_strs_strtable+4534) +#define OPT_ARG_FMT_LEN 1153 +#define OPT_END_FMT (ao_strs_strtable+154) +#define OPT_END_FMT_LEN 14 +#define OPT_VAL_FMT (ao_strs_strtable+147) +#define OPT_VAL_FMT_LEN 6 +#define OR_STR (ao_strs_strtable+36) +#define OR_STR_LEN 3 +#define PAGER_NAME (ao_strs_strtable+44) +#define PAGER_NAME_LEN 5 +#define PAGE_USAGE_FMT (ao_strs_strtable+487) +#define PAGE_USAGE_FMT_LEN 42 +#define PLUS_STR (ao_strs_strtable+32) +#define PLUS_STR_LEN 3 +#define PREAMBLE_FMT (ao_strs_strtable+612) +#define PREAMBLE_FMT_LEN 105 +#define QUOT_APOS (ao_strs_strtable+172) +#define QUOT_APOS_LEN 2 +#define QUOT_ARG_FMT (ao_strs_strtable+175) +#define QUOT_ARG_FMT_LEN 4 +#define SAVE_WARN (ao_strs_strtable+6104) +#define SAVE_WARN_LEN 35 +#define SET_NO_TEXT_FMT (ao_strs_strtable+6073) +#define SET_NO_TEXT_FMT_LEN 30 +#define SET_OFF_FMT (ao_strs_strtable+391) +#define SET_OFF_FMT_LEN 6 +#define SET_TEXT_FMT (ao_strs_strtable+347) +#define SET_TEXT_FMT_LEN 12 +#define SGL_ARG_FMT (ao_strs_strtable+2420) +#define SGL_ARG_FMT_LEN 246 +#define SGL_DEF_FMT (ao_strs_strtable+876) +#define SGL_DEF_FMT_LEN 67 +#define SGL_NO_DEF_FMT (ao_strs_strtable+944) +#define SGL_NO_DEF_FMT_LEN 61 +#define SHELL_MAGIC (ao_strs_strtable+140) +#define SHELL_MAGIC_LEN 6 +#define SHOW_PROG_ENV (ao_strs_strtable+371) +#define SHOW_PROG_ENV_LEN 19 +#define SHOW_VAL_FMT (ao_strs_strtable+240) +#define SHOW_VAL_FMT_LEN 17 +#define START_MARK (ao_strs_strtable+530) +#define START_MARK_LEN 81 +#define STDOUT (ao_strs_strtable+111) +#define STDOUT_LEN 6 +#define TIME_FMT (ao_strs_strtable+118) +#define TIME_FMT_LEN 21 +#define TMP_USAGE_FMT (ao_strs_strtable+50) +#define TMP_USAGE_FMT_LEN 12 +#define TRUE_STR (ao_strs_strtable+258) +#define TRUE_STR_LEN 4 +#define TWO_SPACES_STR (ao_strs_strtable+85) +#define TWO_SPACES_STR_LEN 2 +#define TYPE_ATR_FMT (ao_strs_strtable+6159) +#define TYPE_ATR_FMT_LEN 12 +#define UNK_OPT_FMT (ao_strs_strtable+1834) +#define UNK_OPT_FMT_LEN 141 +#define VER_STR (ao_strs_strtable+269) +#define VER_STR_LEN 7 +#define XML_HEX_BYTE_FMT (ao_strs_strtable+6190) +#define XML_HEX_BYTE_FMT_LEN 7 +#define YES_NEED_OPT_ARG (ao_strs_strtable+313) +#define YES_NEED_OPT_ARG_LEN 18 +#define apostrophy (ao_strs_strtable+221) +#define apostrophy_LEN 4 +#define arg_fmt (ao_strs_strtable+215) +#define arg_fmt_LEN 5 +#define init_optct (ao_strs_strtable+226) +#define init_optct_LEN 13 +#define set_dash (ao_strs_strtable+208) +#define set_dash_LEN 6 +#define zCantArg (ao_strs_strtable+3267) +#define zCantArg_LEN 119 +#define zCmdFmt (ao_strs_strtable+2101) +#define zCmdFmt_LEN 15 +#define zCountTest (ao_strs_strtable+2117) +#define zCountTest_LEN 178 +#define zEquivMode (ao_strs_strtable+5868) +#define zEquivMode_LEN 44 +#define zFullOptFmt (ao_strs_strtable+5833) +#define zFullOptFmt_LEN 34 +#define zLoopEnd (ao_strs_strtable+1290) +#define zLoopEnd_LEN 329 +#define zMayArg (ao_strs_strtable+3115) +#define zMayArg_LEN 119 +#define zMustArg (ao_strs_strtable+3235) +#define zMustArg_LEN 31 +#define zOptCookieCt (ao_strs_strtable+5730) +#define zOptCookieCt_LEN 38 +#define zOptCtFmt (ao_strs_strtable+5769) +#define zOptCtFmt_LEN 30 +#define zOptDisabl (ao_strs_strtable+5800) +#define zOptDisabl_LEN 32 +#define zOptNumFmt (ao_strs_strtable+5688) +#define zOptNumFmt_LEN 41 +#define zOptionCase (ao_strs_strtable+1736) +#define zOptionCase_LEN 30 +#define zOptionEndSelect (ao_strs_strtable+1817) +#define zOptionEndSelect_LEN 16 +#define zOptionFlag (ao_strs_strtable+1801) +#define zOptionFlag_LEN 15 +#define zOptionFullName (ao_strs_strtable+1785) +#define zOptionFullName_LEN 15 +#define zOptionPartName (ao_strs_strtable+1767) +#define zOptionPartName_LEN 17 +#define zPagedUsageExit (ao_strs_strtable+2027) +#define zPagedUsageExit_LEN 73 +#define zTextExit (ao_strs_strtable+1976) +#define zTextExit_LEN 50 +extern char const ao_strs_strtable[6265]; + +#endif /* STRINGS_AO_STRS_H_GUARD */ diff --git a/autoopts/ao_string_tokenize.3 b/autoopts/ao_string_tokenize.3 new file mode 100644 index 0000000..5c3e6a2 --- /dev/null +++ b/autoopts/ao_string_tokenize.3 @@ -0,0 +1,86 @@ +.TH ao_string_tokenize 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (ao_string_tokenize.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +ao_string_tokenize - tokenize an input string +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +token_list_t* \fBao_string_tokenize\fP(char const* \fIstring\fP); +.sp 1 +.SH DESCRIPTION +This function will convert one input string into a list of strings. +The list of strings is derived by separating the input based on +white space separation. However, if the input contains either single +or double quote characters, then the text after that character up to +a matching quote will become the string in the list. + +The returned pointer should be deallocated with \fBfree(3C)\fP when +are done using the data. The data are placed in a single block of +allocated memory. Do not deallocate individual token/strings. + +The structure pointed to will contain at least these two fields: +.sp +.IR "tkn_ct" +The number of tokens found in the input string. +.sp +.IR "tok_list" +An array of \fBtkn_ct + 1\fP pointers to substring tokens, with +the last pointer set to NULL. +.br + +There are two types of quoted strings: single quoted (\fB'\fP) and +double quoted (\fB"\fP). Singly quoted strings are fairly raw in that +escape characters (\fB\\\fP) are simply another character, except when +preceding the following characters: +.nf + \fB\\\fP double backslashes reduce to one + \fB'\fP incorporates the single quote into the string + \fB\n\fP suppresses both the backslash and newline character +.fi + +Double quote strings are formed according to the rules of string +constants in ANSI-C programs. +.TP +.IR string +string to be tokenized +.sp 1 +.SH RETURN VALUE +pointer to a structure that lists each token +.sp 1 +.SH ERRORS +NULL is returned and \fBerrno\fP will be set to indicate the problem: +.sp 1ize @bullet +.sp 1 +\fBEINVAL\fP \- There was an unterminated quoted string. +.sp 1 +\fBENOENT\fP \- The input string was empty. +.sp 1 +\fBENOMEM\fP \- There is not enough memory. +@end itemize +.sp 1 +.SH EXAMPLES +.nf +.in +5 +.nf + #include <stdlib.h> + int ix; + token_list_t* ptl = ao_string_tokenize(some_string) + for (ix = 0; ix < ptl->tkn_ct; ix++) + do_something_with_tkn(ptl->tkn_list[ix]); + free(ptl); +.fi +Note that everything is freed with the one call to \fBfree(3C)\fP. +.in -5 +.fi +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/autogen.map b/autoopts/autogen.map new file mode 100644 index 0000000..f02c868 --- /dev/null +++ b/autoopts/autogen.map @@ -0,0 +1,81 @@ + +%guard +%file ag-char-map.h +%backup +%optimize + +%comment + This file contains the character classifications + used by AutoGen and AutoOpts for identifying tokens. + The table is static scope, so %guard is empty. + + This file is part of AutoOpts, a companion to AutoGen. + AutoOpts is free software. + AutoOpts is Copyright (c) 1992-2012 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 md5sums: + + 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +% + +newline "\n" +nul-byte "\x00" +dir-sep "/\\" +percent "%" +comma "," +colon ":" +underscore "_" +plus "+" +dollar "$" +option-marker "-" + +horiz-white "\t " +alt-white "\v\f\r\b" +whitespace +horiz-white +newline +alt-white +non-nl-white +horiz-white +alt-white +quote "'\"" +parentheses "()" + +graphic "!-~" +inversion "~-" +oct-digit "0-7" +dec-digit "89" +oct-digit +hex-digit "a-fA-F" +dec-digit +lower-case "a-z" +upper-case "A-Z" +alphabetic +lower-case +upper-case +alphanumeric +alphabetic +dec-digit +var-first +underscore +alphabetic +variable-name +var-first +dec-digit +option-name "^-" +variable-name +value-name +colon +option-name +name-sep "[.]" +compound-name +value-name +name-sep +horiz-white +scheme-note +parentheses +quote + +unquotable "!-~" -"#,;<=>[\\]`{}?*" -quote -parentheses +end-xml-token "/>" +whitespace +plus-n-space +plus +whitespace +punctuation "!-~" -alphanumeric -"_" +suffix "-._" +alphanumeric +suffix-fmt +percent +suffix +dir-sep +false-type "nNfF0" +nul-byte +file-name +dir-sep +suffix +end-token +nul-byte +whitespace +end-list-entry +comma +end-token +set-separator "|+" +end-list-entry +signed-number +inversion +dec-digit +make-script +dollar +newline +load-line-skip +horiz-white +option-marker diff --git a/autoopts/autoopts-config.1 b/autoopts/autoopts-config.1 new file mode 100644 index 0000000..f600e3f --- /dev/null +++ b/autoopts/autoopts-config.1 @@ -0,0 +1,161 @@ +\" -*- buffer-read-only: t -*- vi: set ro: +\" +\" DO NOT EDIT THIS FILE (autoopts-config.1) +\" +\" It has been AutoGen-ed August 11, 2012 at 09:41:23 AM by AutoGen 5.16.2pre7 +\" From the definitions aoconf.def +\" and the template file aoconf.tpl +\" +.TH autoopts-config 1 2012-08-11 "" "Programmer's Manual" +.SH NAME +autoopts-config \- script to get information about installed version of +autoopts +.SH SYNOPSIS +.B autoopts-config +.B { <value-name> [...] | everything } +.PP +.SH DESCRIPTION +\fBautoopts-config\fP is a tool that is used by configure to determine +the compile and linker flags that should be used to compile and link +programs that use autoopts. \fIvalue-name\fPs may be preceeded by +one or more hyphens. They are silently ignored. +.SH "VALUE NAMES" +.TP +.BR autogen +.sp +Print the full path name of the autogen executable. +.br +The unconfigured value is: ${bindir}/autogen${exeext} +.TP +.BR bindir +.sp +The destination directory for executable scripts and programs +installed by the \fIautogen\fP package. +.br +The unconfigured value is: @bindir@ +.TP +.BR cflags +.sp +Print the compiler flags that are necessary to compile an autoopts program. +.br +The unconfigured value is: -I${includedir} +.TP +.BR datadir +.sp +The directory for various data directories. +.br +The unconfigured value is: @datadir@ +.TP +.BR datarootdir +.sp +The root directory for various data directories. +In this case, there is only one, "datadir". +.br +The unconfigured value is: @datarootdir@ +.TP +.BR dotver +.sp +Print the currently installed version of autoopts, in dotted format. +.br +The unconfigured value is: @AO_CURRENT@.@AO_REVISION@.@AO_AGE@ +.TP +.BR everything +.sp +Print the list of all names and values, one per line. +.TP +.BR exec_prefix +.sp +The installation root for libraries and executables. +.br +The unconfigured value is: @exec_prefix@ +.TP +.BR exeext +.sp +The executable file extension used for the autogen executable. +.br +The unconfigured value is: @EXEEXT@ +.TP +.BR includedir +.sp +The directory where the AutoOpts headers are stored. +This does not include the "-I" prefix gotten by specifying "cflags". +.br +The unconfigured value is: @includedir@ +.TP +.BR ldflags +.sp +Print the linker flags that are necessary to link an autoopts program +in the default installation mode (static or dynamic). +.br +The unconfigured value is: -L${libdir} -lopts +.TP +.BR ldopts +.sp +The linker options to use when linking a program to libopts. +.br +The unconfigured value is: @AG_LDFLAGS@ +.TP +.BR libdir +.sp +The libopts installation directory. +.br +The unconfigured value is: @libdir@ +.TP +.BR libs +.sp +an alternate spelling of "\fIldflags\fP". +.br +The unconfigured value is: ${ldflags} +.TP +.BR libsrc +.sp +The full path of the redistributable, tear-off libopts library source. +This file is in gzipped-tarball format. +.br +The unconfigured value is: ${pkgdatadir}/libopts-${dotver}.tar.gz +.TP +.BR package +.sp +The name of the package that provides \fBautoopts\fP. This is always +"\fIautogen\fP". +.br +The unconfigured value is: @PACKAGE@ +.TP +.BR pkgdatadir +.sp +The directory containing support files used by autogen. +.br +The unconfigured value is: ${datadir}/${package} +.TP +.BR prefix +.sp +The \fIautogen\fP package installation prefix. +.br +The unconfigured value is: @prefix@ +.TP +.BR static_libs +.sp +The name of the AR archive of the libopts object code. +.br +The unconfigured value is: ${libdir}/libopts.a +.TP +.BR version +.sp +Print the currently installed version of autoopts. +.br +The unconfigured value is: @AO_CURRENT@:@AO_REVISION@:@AO_AGE@ +.SH "SEE ALSO" +.IR Autogen +Info system documentation. +.SH AUTHORS +AutoGen is the work of Bruce Korb <bkorb@gnu.org>. +.br +Bruce Korb <bkorb@gnu.org> and +.br +Luca Filipozzi <lfilipoz@debian.org> +created this manpage. +.PP +AutoOpts is released under either the GNU General Public License with the +Library exception (LGPL), or else the advertising clause free BSD license. +Which license used is at the discretion of the licensee. +\" end of autoopts-config.1 diff --git a/autoopts/autoopts-config.in b/autoopts/autoopts-config.in new file mode 100644 index 0000000..177cdd4 --- /dev/null +++ b/autoopts/autoopts-config.in @@ -0,0 +1,114 @@ +#! @CONFIG_SHELL@ +## --------------------------------------------------------------------- +## autoopts-config.in -- Describe AutoOpts configuration +## +## Autoopts Copyright (c) 1992-2012 by Bruce Korb +## +## DO NOT EDIT THIS FILE (autoopts-config.in) +## +## It has been AutoGen-ed August 11, 2012 at 09:41:23 AM by AutoGen 5.16.2pre7 +## From the definitions aoconf.def +## and the template file aoconf.tpl +## + prefix="@prefix@" + datarootdir="@datarootdir@" + datadir="@datadir@" + package="@PACKAGE@" + includedir="@includedir@" + exec_prefix="@exec_prefix@" + bindir="@bindir@" + libdir="@libdir@" + ldopts="@AG_LDFLAGS@" + exeext="@EXEEXT@" + version="@AO_CURRENT@:@AO_REVISION@:@AO_AGE@" + dotver="@AO_CURRENT@.@AO_REVISION@.@AO_AGE@" + pkgdatadir="${datadir}/${package}" + autogen="${bindir}/autogen${exeext}" + ldflags="-L${libdir} -lopts" + libs="${ldflags}" + libsrc="${pkgdatadir}/libopts-${dotver}.tar.gz" + static_libs="${libdir}/libopts.a" + cflags="-I${includedir}" +test 'X@ENABLE_STATIC@' = Xno && static_libs='' +case "${libdir}" in +/lib | /lib64 | /usr/lib | /usr/lib64 ) + ldopts='' + ldflags=-lopts + ;; + +* ) + test -n "${ldopts}" && \ + ldflags="${ldopts}${libdir} ${ldflags}" + ;; +esac +libs=${ldflags} +test "${includedir}" = "/usr/include" && cflags="" +optlist="\ + autogen bindir cflags datadir datarootdir dotver + everything exec_prefix exeext includedir ldflags ldopts + libdir libs libsrc package pkgdatadir prefix + static_libs version" + +usage() +{ + test $# -gt 0 && { + exec 1>&2 + echo autoopts-config error: "$*" + } + + echo Usage: autoopts-config \<\<OPTION\>\> [ ... ] + echo Options may be one or more of: + + for o in $optlist + do echo " ${o}" + done | sed 's,_,-,g' + echo 'NB: "everything" will print out the list of all names and values.' + exit $# +} + +test $# -gt 0 || usage "No value specified" + +# Figure out what's wanted +# +val='' +for o in "$@" ; do + o=`echo ${o} | sed 's,^-*,,;s/-/_/g'` + case "$o" in + help | h | \? ) usage ;; + *[!a-zA-Z0-9_]* ) usage "Invalid name: ${o}" ;; + + prefix ) val="${val} ${prefix}" ;; + datarootdir ) val="${val} ${datarootdir}" ;; + datadir ) val="${val} ${datadir}" ;; + package ) val="${val} ${package}" ;; + includedir ) val="${val} ${includedir}" ;; + exec_prefix ) val="${val} ${exec_prefix}" ;; + bindir ) val="${val} ${bindir}" ;; + libdir ) val="${val} ${libdir}" ;; + ldopts ) val="${val} ${ldopts}" ;; + exeext ) val="${val} ${exeext}" ;; + version ) val="${val} ${version}" ;; + dotver ) val="${val} ${dotver}" ;; + pkgdatadir ) val="${val} ${pkgdatadir}" ;; + autogen ) val="${val} ${autogen}" ;; + ldflags ) val="${val} ${ldflags}" ;; + libs ) val="${val} ${libs}" ;; + libsrc ) val="${val} ${libsrc}" ;; + static_libs ) val="${val} ${static_libs}" ;; + cflags ) val="${val} ${cflags}" ;; + everything ) + for o in ${optlist} + do test ${o} = everything && continue + eval v=\"\${${o}}\" + test -z "${v}" && echo ${o} || \ + printf "%-12s $v\n" ${o} + done + exit 0 + ;; + + * ) usage "Unknown value name: ${o}" ;; + esac +done + +echo "${val}" +## end of autoopts-config.in diff --git a/autoopts/autoopts.c b/autoopts/autoopts.c new file mode 100644 index 0000000..1eff700 --- /dev/null +++ b/autoopts/autoopts.c @@ -0,0 +1,729 @@ + +/** + * \file autoopts.c + * + * Time-stamp: "2012-03-04 19:44:56 bkorb" + * + * This file contains all of the routines that must be linked into + * an executable to use the generated option processing. The optional + * routines are in separately compiled modules so that they will not + * necessarily be linked in. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +#ifndef PKGDATADIR +# define PKGDATADIR "" +#endif + +static char const zNil[] = ""; +static arg_types_t argTypes = { NULL }; +static char line_fmt_buf[32]; +static bool displayEnum = false; +static char const pkgdatadir_default[] = PKGDATADIR; +static char const * program_pkgdatadir = pkgdatadir_default; +static tOptionLoadMode option_load_mode = OPTION_LOAD_UNCOOKED; +static tePagerState pagerState = PAGER_STATE_INITIAL; + + FILE * option_usage_fp = NULL; + +/* = = = START-STATIC-FORWARD = = = */ +static tSuccess +next_opt_arg_must(tOptions * pOpts, tOptState* pOptState); + +static tSuccess +next_opt_arg_may(tOptions * pOpts, tOptState * pOptState); + +static tSuccess +next_opt_arg_none(tOptions * pOpts, tOptState* pOptState); + +static tSuccess +next_opt(tOptions * pOpts, tOptState * pOptState); + +static tSuccess +doPresets(tOptions * pOpts); +/* = = = END-STATIC-FORWARD = = = */ + +LOCAL void * +ao_malloc(size_t sz) +{ + void * res = malloc(sz); + if (res == NULL) { + fprintf(stderr, zAO_Alloc, (int)sz); + exit(EXIT_FAILURE); + } + return res; +} +#undef malloc +#define malloc(_s) ao_malloc(_s) + +LOCAL void * +ao_realloc(void *p, size_t sz) +{ + void * res = (p == NULL) ? malloc(sz) : realloc(p, sz); + if (res == NULL) { + fprintf(stderr, zAO_Realloc, (int)sz, p); + exit(EXIT_FAILURE); + } + return res; +} +#undef realloc +#define realloc(_p,_s) ao_realloc(_p,_s) + +LOCAL char * +ao_strdup(char const *str) +{ + char * res = strdup(str); + if (res == NULL) { + fprintf(stderr, zAO_Strdup, (int)strlen(str)); + exit(EXIT_FAILURE); + } + return res; +} +#undef strdup +#define strdup(_p) ao_strdup(_p) + +#ifndef HAVE_PATHFIND +# include "compat/pathfind.c" +#endif + +#ifndef HAVE_SNPRINTF +# include "compat/snprintf.c" +#endif + +#ifndef HAVE_STRDUP +# include "compat/strdup.c" +#endif + +#ifndef HAVE_STRCHR +# include "compat/strchr.c" +#endif + +/* + * handle_opt + * + * This routine handles equivalencing, sets the option state flags and + * invokes the handler procedure, if any. + */ +LOCAL tSuccess +handle_opt(tOptions * pOpts, tOptState* pOptState) +{ + /* + * Save a copy of the option procedure pointer. + * If this is an equivalence class option, we still want this proc. + */ + tOptDesc* pOD = pOptState->pOD; + tOptProc* pOP = pOD->pOptProc; + if (pOD->fOptState & OPTST_ALLOC_ARG) + AGFREE(pOD->optArg.argString); + + pOD->optArg.argString = pOptState->pzOptArg; + + /* + * IF we are presetting options, then we will ignore any un-presettable + * options. They are the ones either marked as such. + */ + if ( ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0) + && ((pOD->fOptState & OPTST_NO_INIT) != 0) + ) + return PROBLEM; + + /* + * IF this is an equivalence class option, + * THEN + * Save the option value that got us to this option + * entry. (It may not be pOD->optChar[0], if this is an + * equivalence entry.) + * set the pointer to the equivalence class base + */ + if (pOD->optEquivIndex != NO_EQUIVALENT) { + tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex; + + /* + * IF the current option state has not been defined (set on the + * command line), THEN we will allow continued resetting of + * the value. Once "defined", then it must not change. + */ + if ((pOD->fOptState & OPTST_DEFINED) != 0) { + /* + * The equivalenced-to option has been found on the command + * line before. Make sure new occurrences are the same type. + * + * IF this option has been previously equivalenced and + * it was not the same equivalenced-to option, + * THEN we have a usage problem. + */ + if (p->optActualIndex != pOD->optIndex) { + fprintf(stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name, + (pOpts->pOptDesc + p->optActualIndex)->pz_Name); + return FAILURE; + } + } else { + /* + * Set the equivalenced-to actual option index to no-equivalent + * so that we set all the entries below. This option may either + * never have been selected before, or else it was selected by + * some sort of "presetting" mechanism. + */ + p->optActualIndex = NO_EQUIVALENT; + } + + if (p->optActualIndex != pOD->optIndex) { + /* + * First time through, copy over the state + * and add in the equivalence flag + */ + p->optActualValue = pOD->optValue; + p->optActualIndex = pOD->optIndex; + pOptState->flags |= OPTST_EQUIVALENCE; + } + + /* + * Copy the most recent option argument. set membership state + * is kept in ``p->optCookie''. Do not overwrite. + */ + p->optArg.argString = pOD->optArg.argString; + pOD = p; + + } else { + pOD->optActualValue = pOD->optValue; + pOD->optActualIndex = pOD->optIndex; + } + + pOD->fOptState &= OPTST_PERSISTENT_MASK; + pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT_MASK); + + /* + * Keep track of count only for DEFINED (command line) options. + * IF we have too many, build up an error message and bail. + */ + if ( (pOD->fOptState & OPTST_DEFINED) + && (++pOD->optOccCt > pOD->optMaxCt) ) { + + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + char const * pzEqv = + (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil; + + fputs(zErrOnly, stderr); + + if (pOD->optMaxCt > 1) + fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv); + else + fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv); + } + + return FAILURE; + } + + /* + * If provided a procedure to call, call it + */ + if (pOP != NULL) + (*pOP)(pOpts, pOD); + + return SUCCESS; +} + +static tSuccess +next_opt_arg_must(tOptions * pOpts, tOptState* pOptState) +{ + /* + * An option argument is required. Long options can either have + * a separate command line argument, or an argument attached by + * the '=' character. Figure out which. + */ + switch (pOptState->optType) { + case TOPT_SHORT: + /* + * See if an arg string follows the flag character + */ + if (*++(pOpts->pzCurOpt) == NUL) + pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ]; + pOptState->pzOptArg = pOpts->pzCurOpt; + break; + + case TOPT_LONG: + /* + * See if an arg string has already been assigned (glued on + * with an `=' character) + */ + if (pOptState->pzOptArg == NULL) + pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ]; + break; + + default: +#ifdef DEBUG + fputs("AutoOpts lib error: option type not selected\n", stderr); + exit(EXIT_FAILURE); +#endif + + case TOPT_DEFAULT: + /* + * The option was selected by default. The current token is + * the option argument. + */ + break; + } + + /* + * Make sure we did not overflow the argument list. + */ + if (pOpts->curOptIdx > pOpts->origArgCt) { + fprintf(stderr, zMisArg, pOpts->pzProgPath, pOptState->pOD->pz_Name); + return FAILURE; + } + + pOpts->pzCurOpt = NULL; /* next time advance to next arg */ + return SUCCESS; +} + +/** + * Process an optional option argument. For short options, it looks at the + * character after the option character, or it consumes the next full argument. + * For long options, it looks for an '=' character attachment to the long + * option name before deciding to take the next command line argument. + * + * @param pOpts the option descriptor + * @param pOptState a structure for managing the current processing state + * @returns SUCCESS or does not return + */ +static tSuccess +next_opt_arg_may(tOptions * pOpts, tOptState * pOptState) +{ + /* + * An option argument is optional. + */ + switch (pOptState->optType) { + case TOPT_SHORT: + if (*++pOpts->pzCurOpt != NUL) + pOptState->pzOptArg = pOpts->pzCurOpt; + else { + char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; + + /* + * BECAUSE it is optional, we must make sure + * we did not find another flag and that there + * is such an argument. + */ + if ((pzLA == NULL) || (*pzLA == '-')) + pOptState->pzOptArg = NULL; + else { + pOpts->curOptIdx++; /* argument found */ + pOptState->pzOptArg = pzLA; + } + } + break; + + case TOPT_LONG: + /* + * Look for an argument if we don't already have one (glued on + * with a `=' character) *AND* we are not in named argument mode + */ + if ( (pOptState->pzOptArg == NULL) + && (! NAMED_OPTS(pOpts))) { + char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; + + /* + * BECAUSE it is optional, we must make sure + * we did not find another flag and that there + * is such an argument. + */ + if ((pzLA == NULL) || (*pzLA == '-')) + pOptState->pzOptArg = NULL; + else { + pOpts->curOptIdx++; /* argument found */ + pOptState->pzOptArg = pzLA; + } + } + break; + + default: + case TOPT_DEFAULT: + fputs(zAO_Woops, stderr ); + exit(EX_SOFTWARE); + } + + /* + * After an option with an optional argument, we will + * *always* start with the next option because if there + * were any characters following the option name/flag, + * they would be interpreted as the argument. + */ + pOpts->pzCurOpt = NULL; + return SUCCESS; +} + + +static tSuccess +next_opt_arg_none(tOptions * pOpts, tOptState* pOptState) +{ + /* + * No option argument. Make sure next time around we find + * the correct option flag character for short options + */ + if (pOptState->optType == TOPT_SHORT) + (pOpts->pzCurOpt)++; + + /* + * It is a long option. Make sure there was no ``=xxx'' argument + */ + else if (pOptState->pzOptArg != NULL) { + fprintf(stderr, zNoArg, pOpts->pzProgPath, pOptState->pOD->pz_Name); + return FAILURE; + } + + /* + * It is a long option. Advance to next command line argument. + */ + else + pOpts->pzCurOpt = NULL; + return SUCCESS; +} + +/** + * Find the option descriptor and option argument (if any) for the + * next command line argument. DO NOT modify the descriptor. Put + * all the state in the state argument so that the option can be skipped + * without consequence (side effect). + * + * @param pOpts the program option descriptor + * @param pOptState the state of the next found option + */ +static tSuccess +next_opt(tOptions * pOpts, tOptState * pOptState) +{ + { + tSuccess res = find_opt(pOpts, pOptState); + if (! SUCCESSFUL(res)) + return res; + } + + if ( ((pOptState->flags & OPTST_DEFINED) != 0) + && ((pOptState->pOD->fOptState & OPTST_NO_COMMAND) != 0)) { + fprintf(stderr, zNotCmdOpt, pOptState->pOD->pz_Name); + return FAILURE; + } + + return get_opt_arg(pOpts, pOptState); +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * DO PRESETS + * + * The next several routines do the immediate action pass on the command + * line options, then the environment variables, then the config files in + * reverse order. Once done with that, the order is reversed and all + * the config files and environment variables are processed again, this + * time only processing the non-immediate action options. doPresets() + * will then return for optionProcess() to do the final pass on the command + * line arguments. + */ + +/** + * scan the command line for immediate action options. + * This is only called the first time through. + * While this procedure is active, the OPTPROC_IMMEDIATE is true. + * + * @param pOpts program options descriptor + * @returns SUCCESS or FAILURE + */ +LOCAL tSuccess +immediate_opts(tOptions * pOpts) +{ + tSuccess res; + + pOpts->fOptSet |= OPTPROC_IMMEDIATE; + pOpts->curOptIdx = 1; /* start by skipping program name */ + pOpts->pzCurOpt = NULL; + + /* + * Examine all the options from the start. We process any options that + * are marked for immediate processing. + */ + for (;;) { + tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); + + res = next_opt(pOpts, &opt_st); + switch (res) { + case FAILURE: goto failed_option; + case PROBLEM: res = SUCCESS; goto leave; + case SUCCESS: break; + } + + /* + * IF this is an immediate-attribute option, then do it. + */ + if (! DO_IMMEDIATELY(opt_st.flags)) + continue; + + if (! SUCCESSFUL(handle_opt(pOpts, &opt_st))) + break; + } failed_option:; + + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + +leave: + + pOpts->fOptSet &= ~OPTPROC_IMMEDIATE; + return res; +} + +/** + * Process all the options from our current position onward. (This allows + * interspersed options and arguments for the few non-standard programs that + * require it.) Thus, do not rewind option indexes because some programs + * choose to re-invoke after a non-option. + * + * @param pOpts program options descriptor + * @returns SUCCESS or FAILURE + */ +LOCAL tSuccess +regular_opts(tOptions * pOpts) +{ + /* assert: pOpts->fOptSet & OPTPROC_IMMEDIATE == 0 */ + for (;;) { + tOptState opt_st = OPTSTATE_INITIALIZER(DEFINED); + + switch (next_opt(pOpts, &opt_st)) { + case FAILURE: goto failed_option; + case PROBLEM: return SUCCESS; /* no more args */ + case SUCCESS: break; + } + + /* + * IF this is an immediate action option, + * THEN skip it (unless we are supposed to do it a second time). + */ + if (! DO_NORMALLY(opt_st.flags)) { + if (! DO_SECOND_TIME(opt_st.flags)) + continue; + opt_st.pOD->optOccCt--; /* don't count this repetition */ + } + + if (! SUCCESSFUL(handle_opt(pOpts, &opt_st))) + break; + } failed_option:; + + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + + return FAILURE; +} + + +/** + * check for preset values from a config files or envrionment variables + */ +static tSuccess +doPresets(tOptions * pOpts) +{ + tOptDesc * pOD = NULL; + + if (! SUCCESSFUL(immediate_opts(pOpts))) + return FAILURE; + + /* + * IF this option set has a --save-opts option, then it also + * has a --load-opts option. See if a command line option has disabled + * option presetting. + */ + if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) + && (pOpts->specOptIdx.save_opts != 0)) { + pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1; + if (DISABLED_OPT(pOD)) + return SUCCESS; + } + + /* + * Until we return from this procedure, disable non-presettable opts + */ + pOpts->fOptSet |= OPTPROC_PRESETTING; + /* + * IF there are no config files, + * THEN do any environment presets and leave. + */ + if (pOpts->papzHomeList == NULL) { + env_presets(pOpts, ENV_ALL); + } + else { + env_presets(pOpts, ENV_IMM); + + /* + * Check to see if environment variables have disabled presetting. + */ + if ((pOD != NULL) && ! DISABLED_OPT(pOD)) + intern_file_load(pOpts); + + /* + * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment + * variable options. Only the loading of .rc files. + */ + env_presets(pOpts, ENV_NON_IMM); + } + pOpts->fOptSet &= ~OPTPROC_PRESETTING; + + return SUCCESS; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE + */ +/*=--subblock=arg=arg_type,arg_name,arg_desc =*/ +/*=* + * library: opts + * header: your-opts.h + * + * lib_description: + * + * These are the routines that libopts users may call directly from their + * code. There are several other routines that can be called by code + * generated by the libopts option templates, but they are not to be + * called from any other user code. The @file{options.h} header is + * fairly clear about this, too. +=*/ + +/*=export_func optionProcess + * + * what: this is the main option processing routine + * + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + int + argc + program arg count + + * arg: + char** + argv + program arg vector + + * + * ret_type: int + * ret_desc: the count of the arguments processed + * + * doc: + * + * This is the main entry point for processing options. It is intended + * that this procedure be called once at the beginning of the execution of + * a program. Depending on options selected earlier, it is sometimes + * necessary to stop and restart option processing, or to select completely + * different sets of options. This can be done easily, but you generally + * do not want to do this. + * + * The number of arguments processed always includes the program name. + * If one of the arguments is "--", then it is counted and the processing + * stops. If an error was encountered and errors are to be tolerated, then + * the returned value is the index of the argument causing the error. + * A hyphen by itself ("-") will also cause processing to stop and will + * @emph{not} be counted among the processed arguments. A hyphen by itself + * is treated as an operand. Encountering an operand stops option + * processing. + * + * err: Errors will cause diagnostics to be printed. @code{exit(3)} may + * or may not be called. It depends upon whether or not the options + * were generated with the "allow-errors" attribute, or if the + * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked. +=*/ +int +optionProcess(tOptions * pOpts, int argCt, char ** argVect) +{ + if (! SUCCESSFUL(validate_struct(pOpts, argVect[0]))) + exit(EX_SOFTWARE); + + /* + * Establish the real program name, the program full path, + * and do all the presetting the first time thru only. + */ + if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) { + pOpts->origArgCt = (unsigned int)argCt; + pOpts->origArgVect = argVect; + pOpts->fOptSet |= OPTPROC_INITDONE; + if (HAS_pzPkgDataDir(pOpts)) + program_pkgdatadir = pOpts->pzPkgDataDir; + + if (! SUCCESSFUL(doPresets(pOpts))) + return 0; + + /* + * IF option name conversion was suppressed but it is not suppressed + * for the command line, then it's time to translate option names. + * Usage text will not get retranslated. + */ + if ( ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0) + && (pOpts->pTransProc != NULL) + && ((pOpts->fOptSet & OPTPROC_NO_XLAT_MASK) + == OPTPROC_NXLAT_OPT_CFG) ) { + + pOpts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG; + (*pOpts->pTransProc)(); + } + + if ((pOpts->fOptSet & OPTPROC_REORDER) != 0) + optionSort(pOpts); + + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + } + + /* + * IF we are (re)starting, + * THEN reset option location + */ + else if (pOpts->curOptIdx <= 0) { + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + } + + if (! SUCCESSFUL(regular_opts(pOpts))) + return pOpts->origArgCt; + + /* + * IF there were no errors + * AND we have RC/INI files + * AND there is a request to save the files + * THEN do that now before testing for conflicts. + * (conflicts are ignored in preset options) + */ + if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) + && (pOpts->specOptIdx.save_opts != 0)) { + tOptDesc* pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts; + + if (SELECTED_OPT(pOD)) { + optionSaveFile(pOpts); + exit(EXIT_SUCCESS); + } + } + + /* + * IF we are checking for errors, + * THEN look for too few occurrences of required options + */ + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + if (! is_consistent(pOpts)) + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + } + + return pOpts->curOptIdx; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/autoopts.c */ diff --git a/autoopts/autoopts.h b/autoopts/autoopts.h new file mode 100644 index 0000000..194ea5a --- /dev/null +++ b/autoopts/autoopts.h @@ -0,0 +1,335 @@ + +/* + * \file autoopts.h + * + * Time-stamp: "2012-03-04 19:05:01 bkorb" + * + * This file defines all the global structures and special values + * used in the automated option processing library. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +#ifndef AUTOGEN_AUTOOPTS_H +#define AUTOGEN_AUTOOPTS_H + +#define AO_NAME_LIMIT 127 +#define AO_NAME_SIZE ((size_t)(AO_NAME_LIMIT + 1)) + +#ifndef AG_PATH_MAX +# ifdef PATH_MAX +# define AG_PATH_MAX ((size_t)PATH_MAX) +# else +# define AG_PATH_MAX ((size_t)4096) +# endif +#else +# if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN) +# undef AG_PATH_MAX +# define AG_PATH_MAX ((size_t)PATH_MAX) +# endif +#endif + +#undef EXPORT +#define EXPORT + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define DIRCH '\\' +#else +# define DIRCH '/' +#endif + +#define AO_EXIT_REQ_USAGE 64 +#ifndef EX_NOINPUT + /** + * option state was requested from a file that cannot be loaded. + */ +# define EX_NOINPUT 66 +#endif +#ifndef EX_SOFTWARE + /** + * AutoOpts Software failure. + */ +# define EX_SOFTWARE 70 +#endif + +#define NL '\n' + +/* + * Convert the number to a list usable in a printf call + */ +#define NUM_TO_VER(n) ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F + +#define NAMED_OPTS(po) \ + (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0) + +#define SKIP_OPT(p) (((p)->fOptState & OPTST_IMMUTABLE_MASK) != 0) + +typedef int tDirection; +#define DIRECTION_PRESET -1 +#define DIRECTION_PROCESS 1 +#define DIRECTION_CALLED 0 + +#define PROCESSING(d) ((d)>0) +#define PRESETTING(d) ((d)<0) + +/* + * When loading a line (or block) of text as an option, the value can + * be processed in any of several modes: + * + * @table @samp + * @item keep + * Every part of the value between the delimiters is saved. + * + * @item uncooked + * Even if the value begins with quote characters, do not do quote processing. + * + * @item cooked + * If the value looks like a quoted string, then process it. + * Double quoted strings are processed the way strings are in "C" programs, + * except they are treated as regular characters if the following character + * is not a well-established escape sequence. + * Single quoted strings (quoted with apostrophies) are handled the way + * strings are handled in shell scripts, *except* that backslash escapes + * are honored before backslash escapes and apostrophies. + * @end table + */ +typedef enum { + OPTION_LOAD_COOKED, + OPTION_LOAD_UNCOOKED, + OPTION_LOAD_KEEP +} tOptionLoadMode; + +static tOptionLoadMode option_load_mode; + +/* + * The pager state is used by optionPagedUsage() procedure. + * When it runs, it sets itself up to be called again on exit. + * If, however, a routine needs a child process to do some work + * before it is done, then 'pagerState' must be set to + * 'PAGER_STATE_CHILD' so that optionPagedUsage() will not try + * to run the pager program before its time. + */ +typedef enum { + PAGER_STATE_INITIAL, + PAGER_STATE_READY, + PAGER_STATE_CHILD +} tePagerState; + +typedef enum { + ENV_ALL, + ENV_IMM, + ENV_NON_IMM +} teEnvPresetType; + +typedef enum { + TOPT_UNDEFINED = 0, + TOPT_SHORT, + TOPT_LONG, + TOPT_DEFAULT +} teOptType; + +typedef struct { + tOptDesc* pOD; + tCC* pzOptArg; + tAoUL flags; + teOptType optType; +} tOptState; +#define OPTSTATE_INITIALIZER(st) \ + { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED } + +#define TEXTTO_TABLE \ + _TT_(LONGUSAGE) \ + _TT_(USAGE) \ + _TT_(VERSION) +#define _TT_(n) \ + TT_ ## n , + +typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo; + +#undef _TT_ + +typedef struct { + char const * pzStr; + char const * pzReq; + char const * pzNum; + char const * pzFile; + char const * pzKey; + char const * pzKeyL; + char const * pzBool; + char const * pzNest; + char const * pzOpt; + char const * pzNo; + char const * pzBrk; + char const * pzNoF; + char const * pzSpc; + char const * pzOptFmt; + char const * pzTime; +} arg_types_t; + +#define AGALOC(c, w) ao_malloc((size_t)c) +#define AGREALOC(p, c, w) ao_realloc((void*)p, (size_t)c) +#define AGFREE(_p) free((void *)_p) +#define AGDUPSTR(p, s, w) (p = ao_strdup(s)) + +static void * +ao_malloc(size_t sz); + +static void * +ao_realloc(void *p, size_t sz); + +#define ao_free(_p) free((void *)_p) + +static char * +ao_strdup(char const *str); + +/* + * DO option handling? + * + * Options are examined at two times: at immediate handling time and at + * normal handling time. If an option is disabled, the timing may be + * different from the handling of the undisabled option. The OPTST_DIABLED + * bit indicates the state of the currently discovered option. + * So, here's how it works: + * + * A) handling at "immediate" time, either 1 or 2: + * + * 1. OPTST_DISABLED is not set: + * IMM must be set + * DISABLE_IMM don't care + * TWICE don't care + * DISABLE_TWICE don't care + * 0 -and- 1 x x x + * + * 2. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM must be set + * TWICE don't care + * DISABLE_TWICE don't care + * 1 -and- x 1 x x + */ +#define DO_IMMEDIATELY(_flg) \ + ( (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \ + || ( ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) \ + == (OPTST_DISABLED|OPTST_DISABLE_IMM) )) + +/* B) handling at "regular" time because it was not immediate + * + * 1. OPTST_DISABLED is not set: + * IMM must *NOT* be set + * DISABLE_IMM don't care + * TWICE don't care + * DISABLE_TWICE don't care + * 0 -and- 0 x x x + * + * 2. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM don't care + * TWICE must be set + * DISABLE_TWICE don't care + * 1 -and- x x 1 x + */ +#define DO_NORMALLY(_flg) ( \ + (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == 0) \ + || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) == \ + OPTST_DISABLED) ) + +/* C) handling at "regular" time because it is to be handled twice. + * The immediate bit was already tested and found to be set: + * + * 3. OPTST_DISABLED is not set: + * IMM is set (but don't care) + * DISABLE_IMM don't care + * TWICE must be set + * DISABLE_TWICE don't care + * 0 -and- ? x 1 x + * + * 4. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM is set (but don't care) + * TWICE don't care + * DISABLE_TWICE must be set + * 1 -and- x ? x 1 + */ +#define DO_SECOND_TIME(_flg) ( \ + (((_flg) & (OPTST_DISABLED|OPTST_TWICE)) == \ + OPTST_TWICE) \ + || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE)) == \ + (OPTST_DISABLED|OPTST_DISABLE_TWICE) )) + +/* + * text_mmap structure. Only active on platforms with mmap(2). + */ +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#else +# ifndef PROT_READ +# define PROT_READ 0x01 +# endif +# ifndef PROT_WRITE +# define PROT_WRITE 0x02 +# endif +# ifndef MAP_SHARED +# define MAP_SHARED 0x01 +# endif +# ifndef MAP_PRIVATE +# define MAP_PRIVATE 0x02 +# endif +#endif + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +#ifndef _SC_PAGESIZE +# ifdef _SC_PAGE_SIZE +# define _SC_PAGESIZE _SC_PAGE_SIZE +# endif +#endif + +#ifndef HAVE_STRCHR +extern char* strchr(char const *s, int c); +extern char* strrchr(char const *s, int c); +#endif + +/* + * Define and initialize all the user visible strings. + * We do not do translations. If translations are to be done, then + * the client will provide a callback for that purpose. + */ +#undef DO_TRANSLATIONS +#include "autoopts/usage-txt.h" + +/* + * File pointer for usage output + */ +FILE * option_usage_fp; +static char const * program_pkgdatadir; + +extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt; + +#endif /* AUTOGEN_AUTOOPTS_H */ +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/autoopts.h */ diff --git a/autoopts/autoopts.m4 b/autoopts/autoopts.m4 new file mode 100644 index 0000000..718f497 --- /dev/null +++ b/autoopts/autoopts.m4 @@ -0,0 +1,225 @@ +dnl -*- Mode: M4 -*- +dnl -------------------------------------------------------------------- +dnl autoopts.m4 --- Configure paths for autoopts +dnl +dnl Author: Gary V. Vaughan <gvaughan@localhost> +dnl Time-stamp: "2011-12-13 09:45:03 bkorb" +dnl +dnl This file is part of AutoOpts, a companion to AutoGen. +dnl AutoOpts is free software. +dnl AutoOpts is Copyright (c) 1992-2012 by Bruce Korb - all rights reserved +dnl +dnl AutoOpts is available under any one of two licenses. The license +dnl in use must be one of these two and the choice is under the control +dnl of the user of the license. +dnl +dnl The GNU Lesser General Public License, version 3 or later +dnl See the files "COPYING.lgplv3" and "COPYING.gplv3" +dnl +dnl The Modified Berkeley Software Distribution License +dnl See the file "COPYING.mbsd" +dnl +dnl These files have the following md5sums: +dnl +dnl 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +dnl 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +dnl 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +dnl -------------------------------------------------------------------- +dnl Code: + +# serial 1 + +dnl AG_PATH_AUTOOPTS([MIN-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for AUTOOPTS, and define AUTOGEN, AUTOOPTS_CFLAGS, AUTOGEN_LDFLAGS +dnl and AUTOOPTS_LIBS. +dnl +AC_DEFUN([AG_PATH_AUTOOPTS], +[dnl Get the cflags and libraries from the autoopts-config script +AC_ARG_WITH(opts-prefix, +[ --with-opts-prefix=PFX Prefix where autoopts is installed (optional)]) + +AC_ARG_WITH(opts-exec-prefix, +[ --with-opts-exec-prefix=PFX + Exec prefix where autoopts is installed (optional)]) + +AC_ARG_ENABLE(opts-test, +[ --disable-opts-test Do not try to run a test AutoOpts program]) + + if test x$with_opts_exec_prefix != x ; then + aocfg_args="$aocfg_args --exec-prefix=$with_opts_exec_prefix" + if test x${AUTOOPTS_CONFIG+set} != xset ; then + AUTOOPTS_CONFIG=$with_opts_exec_prefix/bin/autoopts-config + fi + fi + if test x$with_opts_prefix != x ; then + aocfg_args="$aocfg_args --prefix=$with_opts_prefix" + if test x${AUTOOPTS_CONFIG+set} != xset ; then + AUTOOPTS_CONFIG=$with_opts_prefix/bin/autoopts-config + fi + fi + if test -n "$AUTOOPTS_CONFIG"; then + : + else + AC_PATH_PROG(AUTOOPTS_CONFIG, autoopts-config, no) + fi + AC_MSG_CHECKING(for compatible autoopts version)[ + no_autoopts="" + if test "$AUTOOPTS_CONFIG" = "no" ; then + no_autoopts=yes + else + AUTOGEN=`$AUTOOPTS_CONFIG $aocfg_args --autogen` + AUTOOPTS_CFLAGS=`$AUTOOPTS_CONFIG $aocfg_args --cflags` + AUTOGEN_LDFLAGS=`$AUTOOPTS_CONFIG $aocfg_args --pkgdatadir` + AUTOOPTS_LIBS=`$AUTOOPTS_CONFIG $aocfg_args --libs` + aocfg_version=`$AUTOOPTS_CONFIG $aocfg_args --version` + save_IFS=$IFS + IFS=' :' + set -- $aocfg_version + IFS=$save_IFS + aocfg_current=$1 + aocfg_revision=$2 + aocfg_age=$3 + aocfg_currev=$1.$2 + if test "x$enable_opts_test" != "xno" ; then + AC_LANG_SAVE + AC_LANG_C + ac_save_CFLAGS="$CFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $AUTOOPTS_CFLAGS" + LDFLAGS="$LDFLAGS $AUTOOPTS $CFLAGS" + LIBS="$LIBS $AUTOOPTS_LIBS"] + dnl + dnl Now check if the installed AUTOOPTS is sufficiently new. (Also + dnl sanity checks the results of autoopts-config to some extent. + dnl + rm -f confopts.def conf.optstest + AC_TRY_RUN([ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <autoopts/options.h> +#ifndef OPTIONS_VER_TO_NUM +#define OPTIONS_VER_TO_NUM(_v, _r) (((_v) * 4096) + (_r)) +#endif + +static char const zBadVer[] = "\n\\ +*** 'autoopts-config --version' returned $aocfg_version,\n\\ +*** but autoopts returned %d:%d:0\n\\ +*** and the header file says %s\n\\ +*** These should all be consistent.\n\n\\ +*** If autoopts-config was correct, then it is best to remove the old version\n\\ +*** of autoopts. You may also be able to fix the error by modifying your\n\\ +*** LD_LIBRARY_PATH enviroment variable, or by editing /etc/ld.so.conf.\n\\ +*** Make sure you have run ldconfig if that is required on your system.\n\\ +*** Otherwise, set the environment variable AUTOOPTS_CONFIG to point to\n\\ +*** the correct copy of autoopts-config, and remove the file config.cache\n\\ +*** before re-running configure.\n"; + +int +main (int argc, char ** argv) +{ + int current, revision, ct; + char tmp_version[256]; + + system ("touch conf.optstest"); + + /* + * Test liked library against header file + */ + strcpy(tmp_version, optionVersion()); + ct = sscanf(tmp_version, "%d.%d", ¤t, &revision); + if (ct != 2) { + printf("bad version string: -->>%s<<-- != -->>$aocfg_currev<<--\n", + optionVersion()); + return 1; + } + + if (OPTIONS_VER_TO_NUM(current, revision) != OPTIONS_STRUCT_VERSION) { + printf(zBadVer, current, revision, OPTIONS_VERSION_STRING); + return 1; + } + + /* + * Test autoopts-config against header version + */ + if ( OPTIONS_VER_TO_NUM($aocfg_current, $aocfg_revision) + != OPTIONS_STRUCT_VERSION) { + printf("*** autoopts header file version "OPTIONS_VERSION_STRING"\n" + "*** does not match autoopts-config value $aocfg_version\n" + "*** library version is %d:%d\n", current, revision); + return 1; + } + + return 0; +} +],, no_autoopts=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LDFLAGS="$ac_save_LDFLAGS" + LIBS="$ac_save_LIBS" + AC_LANG_RESTORE + fi + fi + + if test "x$no_autoopts" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$AUTOOPTS_CONFIG" = "no" ; then + cat <<- _EOF_ + *** The autoopts-config script installed by AutoGen could not be found + *** If AutoGen was installed in PREFIX, make sure PREFIX/bin is in + *** your path, or set the AUTOOPTS_CONFIG environment variable to the + *** full path to autoopts-config. + _EOF_ + else + if test -f conf.optstest ; then + : + else + echo "*** Could not run autoopts test program, checking why..." + CFLAGS="$CFLAGS $AUTOOPTS_CFLAGS" + LIBS="$LIBS $AUTOOPTS_LIBS" + AC_LANG_SAVE + AC_LANG_C + AC_TRY_LINK([ +#include <autoopts/options.h> +#include <stdio.h> +], [return strcmp("$aocfg_current:$aocfg_revision:$aocfg_age", optionVersion());], + [ cat << _EOF_ +*** The test program compiled, but did not run. This usually means that +*** the run-time linker is not finding libopts or finding the wrong version +*** of libopts. If it is not finding libopts, you'll need to set your +*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point +*** to the installed location Also, make sure you have run ldconfig if that +*** is required on your system +*** +*** If you have an old version installed, it is best to remove it, although +*** you may also be able to get things to work by modifying LD_LIBRARY_PATH +_EOF_ +], [cat << _EOF_ +*** The test program failed to compile or link. See the file config.log for +*** the exact error that occured. This usually means AutoGen was incorrectly +*** installed or that you have moved libopts since it was installed. In the +*** latter case, you may want to edit the autoopts-config script: +*** $AUTOOPTS_CONFIG +_EOF_ +]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + AC_LANG_RESTORE + fi + fi + AUTOGEN=: + AUTOOPTS_CFLAGS="" + AUTOOPTS_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(AUTOGEN) + AC_SUBST(AUTOOPTS_CFLAGS) + AC_SUBST(AUTOGEN_LDFLAGS) + AC_SUBST(AUTOOPTS_LIBS) + rm -f confopts.def conf.optstest +]) +dnl +dnl autoopts.m4 ends here diff --git a/autoopts/autoopts/options.h b/autoopts/autoopts/options.h new file mode 100644 index 0000000..c16d91b --- /dev/null +++ b/autoopts/autoopts/options.h @@ -0,0 +1,1110 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (options.h) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:18 AM by AutoGen 5.16.2pre7 + * From the definitions funcs.def + * and the template file options_h + * + * This file defines all the global structures and special values + * used in the automated option processing library. + * + * Automated Options Copyright (C) 1992-2012 by Bruce Korb + * + * * AutoOpts is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AutoOpts is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>."; + */ +#ifndef AUTOOPTS_OPTIONS_H_GUARD +#define AUTOOPTS_OPTIONS_H_GUARD 1 +#include <sys/types.h> +#include <stdio.h> + +#ifndef COMPAT_H_GUARD +/* + * This is needed for test compilations where the "compat.h" + * header is not usually available. + */ +# if defined(HAVE_STDINT_H) +# include <stdint.h> +# elif defined(HAVE_INTTYPES_H) +# include <inttypes.h> +# endif /* HAVE_STDINT/INTTYPES_H */ + +# if defined(HAVE_LIMITS_H) +# include <limits.h> +# elif defined(HAVE_SYS_LIMITS_H) +# include <sys/limits.h> +# endif /* HAVE_LIMITS/SYS_LIMITS_H */ + +# if defined(HAVE_SYSEXITS_H) +# include <sysexits.h> +# endif /* HAVE_SYSEXITS_H */ + +# if defined(HAVE_STDBOOL_H) +# include <stdbool.h> +# else + typedef enum { false = 0, true = 1 } _Bool; +# define bool _Bool + + /* The other macros must be usable in preprocessor directives. */ +# define false 0 +# define true 1 +# endif /* HAVE_SYSEXITS_H */ +#endif /* COMPAT_H_GUARD */ +// END-CONFIGURED-HEADERS + +/** + * Defined to normal value of EX_USAGE. Used to indicate that paged usage + * was requested. It is used to distinguish a --usage from a --help request. + * --usage is abbreviated and --help gives as much help as possible. + */ +#define AO_EXIT_REQ_USAGE 64 + +/* + * PUBLIC DEFINES + * + * The following defines may be used in applications that need to test the + * state of an option. To test against these masks and values, a pointer + * to an option descriptor must be obtained. There are two ways: + * + * 1. inside an option processing procedure, it is the second argument, + * conventionally "tOptDesc* pOD". + * + * 2. Outside of an option procedure (or to reference a different option + * descriptor), use either "&DESC( opt_name )" or "&pfx_DESC( opt_name )". + * + * See the relevant generated header file to determine which and what + * values for "opt_name" are available. + */ +#define OPTIONS_STRUCT_VERSION 147461 +#define OPTIONS_VERSION_STRING "36:5:11" +#define OPTIONS_MINIMUM_VERSION 102400 +#define OPTIONS_MIN_VER_STRING "25:0:0" +#define OPTIONS_VER_TO_NUM(_v, _r) (((_v) * 4096) + (_r)) + +typedef enum { + OPARG_TYPE_NONE = 0, + OPARG_TYPE_STRING = 1, /* default type/ vanilla string */ + OPARG_TYPE_ENUMERATION = 2, /* opt arg is an enum (keyword list) */ + OPARG_TYPE_BOOLEAN = 3, /* opt arg is boolean-valued */ + OPARG_TYPE_MEMBERSHIP = 4, /* opt arg sets set membership bits */ + OPARG_TYPE_NUMERIC = 5, /* opt arg is a long int */ + OPARG_TYPE_HIERARCHY = 6, /* option arg is hierarchical value */ + OPARG_TYPE_FILE = 7, /* option arg names a file */ + OPARG_TYPE_TIME = 8, /* opt arg is a time duration */ + OPARG_TYPE_FLOAT = 9, /* opt arg is a floating point num */ + OPARG_TYPE_DOUBLE = 10, /* opt arg is a double prec. float */ + OPARG_TYPE_LONG_DOUBLE = 11, /* opt arg is a long double prec. */ + OPARG_TYPE_LONG_LONG = 12 /* opt arg is a long long int */ +} teOptArgType; + +typedef struct optionValue { + teOptArgType valType; + char* pzName; + union { + char strVal[1]; /* OPARG_TYPE_STRING */ + unsigned int enumVal; /* OPARG_TYPE_ENUMERATION */ + unsigned int boolVal; /* OPARG_TYPE_BOOLEAN */ + unsigned long setVal; /* OPARG_TYPE_MEMBERSHIP */ + long longVal; /* OPARG_TYPE_NUMERIC */ + void* nestVal; /* OPARG_TYPE_HIERARCHY */ + } v; +} tOptionValue; + +typedef enum { + FTYPE_MODE_MAY_EXIST = 0x00, + FTYPE_MODE_MUST_EXIST = 0x01, + FTYPE_MODE_MUST_NOT_EXIST = 0x02, + FTYPE_MODE_EXIST_MASK = 0x03, + FTYPE_MODE_NO_OPEN = 0x00, + FTYPE_MODE_OPEN_FD = 0x10, + FTYPE_MODE_FOPEN_FP = 0x20, + FTYPE_MODE_OPEN_MASK = 0x30 +} teOptFileType; + +typedef union { + int file_flags; + char const * file_mode; +} tuFileMode; + +typedef struct argList tArgList; +#define MIN_ARG_ALLOC_CT 6 +#define INCR_ARG_ALLOC_CT 8 +struct argList { + int useCt; + int allocCt; + char const * apzArgs[MIN_ARG_ALLOC_CT]; +}; + +/* + * Bits in the fOptState option descriptor field. + */ +typedef enum { + OPTST_SET_ID = 0, /* Set via the "SET_OPT()" macro */ + OPTST_PRESET_ID = 1, /* Set via an RC/INI file */ + OPTST_DEFINED_ID = 2, /* Set via a command line option */ + OPTST_RESET_ID = 3, /* Reset via command line option */ + OPTST_EQUIVALENCE_ID = 4, /* selected by equiv'ed option */ + OPTST_DISABLED_ID = 5, /* option is in disabled state */ + OPTST_ALLOC_ARG_ID = 6, /* pzOptArg was allocated */ + OPTST_NO_INIT_ID = 8, /* option cannot be preset */ + OPTST_NUMBER_OPT_ID = 9, /* opt value (flag) is any digit */ + OPTST_STACKED_ID = 10, /* opt uses optionStackArg proc */ + OPTST_INITENABLED_ID = 11, /* option defaults to enabled */ + OPTST_ARG_TYPE_1_ID = 12, /* bit 1 of arg type enum */ + OPTST_ARG_TYPE_2_ID = 13, /* bit 2 of arg type enum */ + OPTST_ARG_TYPE_3_ID = 14, /* bit 3 of arg type enum */ + OPTST_ARG_TYPE_4_ID = 15, /* bit 4 of arg type enum */ + OPTST_ARG_OPTIONAL_ID = 16, /* the option arg not required */ + OPTST_IMM_ID = 17, /* process opt on first pass */ + OPTST_DISABLE_IMM_ID = 18, /* process disablement immed. */ + OPTST_OMITTED_ID = 19, /* compiled out of program */ + OPTST_MUST_SET_ID = 20, /* must be set or pre-set */ + OPTST_DOCUMENT_ID = 21, /* opt is for doc only */ + OPTST_TWICE_ID = 22, /* process opt twice - imm + reg */ + OPTST_DISABLE_TWICE_ID = 23, /* process disabled option twice */ + OPTST_SCALED_NUM_ID = 24, /* scaled integer value */ + OPTST_NO_COMMAND_ID = 25, /* disable from cmd line */ + OPTST_DEPRECATED_ID = 26, /* support is being removed */ + OPTST_ALIAS_ID = 27 /* alias for other option */ +} opt_state_enum_t; + +#define OPTST_INIT 0U +#define OPTST_SET (1U << OPTST_SET_ID) +#define OPTST_PRESET (1U << OPTST_PRESET_ID) +#define OPTST_DEFINED (1U << OPTST_DEFINED_ID) +#define OPTST_RESET (1U << OPTST_RESET_ID) +#define OPTST_EQUIVALENCE (1U << OPTST_EQUIVALENCE_ID) +#define OPTST_DISABLED (1U << OPTST_DISABLED_ID) +#define OPTST_ALLOC_ARG (1U << OPTST_ALLOC_ARG_ID) +#define OPTST_NO_INIT (1U << OPTST_NO_INIT_ID) +#define OPTST_NUMBER_OPT (1U << OPTST_NUMBER_OPT_ID) +#define OPTST_STACKED (1U << OPTST_STACKED_ID) +#define OPTST_INITENABLED (1U << OPTST_INITENABLED_ID) +#define OPTST_ARG_TYPE_1 (1U << OPTST_ARG_TYPE_1_ID) +#define OPTST_ARG_TYPE_2 (1U << OPTST_ARG_TYPE_2_ID) +#define OPTST_ARG_TYPE_3 (1U << OPTST_ARG_TYPE_3_ID) +#define OPTST_ARG_TYPE_4 (1U << OPTST_ARG_TYPE_4_ID) +#define OPTST_ARG_OPTIONAL (1U << OPTST_ARG_OPTIONAL_ID) +#define OPTST_IMM (1U << OPTST_IMM_ID) +#define OPTST_DISABLE_IMM (1U << OPTST_DISABLE_IMM_ID) +#define OPTST_OMITTED (1U << OPTST_OMITTED_ID) +#define OPTST_MUST_SET (1U << OPTST_MUST_SET_ID) +#define OPTST_DOCUMENT (1U << OPTST_DOCUMENT_ID) +#define OPTST_TWICE (1U << OPTST_TWICE_ID) +#define OPTST_DISABLE_TWICE (1U << OPTST_DISABLE_TWICE_ID) +#define OPTST_SCALED_NUM (1U << OPTST_SCALED_NUM_ID) +#define OPTST_NO_COMMAND (1U << OPTST_NO_COMMAND_ID) +#define OPTST_DEPRECATED (1U << OPTST_DEPRECATED_ID) +#define OPTST_ALIAS (1U << OPTST_ALIAS_ID) +#define OPT_STATE_MASK 0x0FFFFF7FU + +#define OPTST_SET_MASK ( \ + OPTST_DEFINED | OPTST_PRESET | OPTST_RESET | \ + OPTST_SET \ + /* 0x0000000FU */ ) + +#define OPTST_MUTABLE_MASK ( \ + OPTST_ALLOC_ARG | OPTST_DEFINED | \ + OPTST_DISABLED | OPTST_EQUIVALENCE | \ + OPTST_PRESET | OPTST_RESET | \ + OPTST_SET \ + /* 0x0000007FU */ ) + +#define OPTST_SELECTED_MASK ( \ + OPTST_DEFINED | OPTST_SET \ + /* 0x00000005U */ ) + +#define OPTST_ARG_TYPE_MASK ( \ + OPTST_ARG_TYPE_1 | OPTST_ARG_TYPE_2 | OPTST_ARG_TYPE_3 | \ + OPTST_ARG_TYPE_4 \ + /* 0x0000F000U */ ) + +#define OPTST_NO_USAGE_MASK ( \ + OPTST_DEPRECATED | OPTST_NO_COMMAND | OPTST_OMITTED \ + /* 0x06080000U */ ) + +#define OPTST_IMMUTABLE_MASK ( \ + OPTST_DOCUMENT | OPTST_OMITTED \ + /* 0x00280000U */ ) + +#define OPTST_DO_NOT_SAVE_MASK ( \ + OPTST_DOCUMENT | OPTST_NO_INIT | OPTST_OMITTED \ + /* 0x00280100U */ ) + +#define OPTST_NO_OUTPUT_MASK ( \ + OPTST_ALIAS | OPTST_DOCUMENT | OPTST_OMITTED \ + /* 0x08280000U */ ) + +#ifdef NO_OPTIONAL_OPT_ARGS +# undef OPTST_ARG_OPTIONAL +# define OPTST_ARG_OPTIONAL 0 +#endif + +#define VENDOR_OPTION_VALUE 'W' + +#define OPTST_PERSISTENT_MASK (~OPTST_MUTABLE_MASK) + +#define SELECTED_OPT(_od) ((_od)->fOptState & OPTST_SELECTED_MASK) +#define UNUSED_OPT( _od) (((_od)->fOptState & OPTST_SET_MASK) == 0) +#define DISABLED_OPT(_od) ((_od)->fOptState & OPTST_DISABLED) +#define OPTION_STATE(_od) ((_od)->fOptState) +#define OPTST_SET_ARGTYPE(_n) ((_n) << OPTST_ARG_TYPE_1_ID) +#define OPTST_GET_ARGTYPE(_f) (((_f)&OPTST_ARG_TYPE_MASK)>>OPTST_ARG_TYPE_1_ID) + +/* + * PRIVATE INTERFACES + * + * The following values are used in the generated code to communicate + * with the option library procedures. They are not for public use + * and may be subject to change. + */ + +/* + * Define the processing state flags + */ +typedef enum { + OPTPROC_LONGOPT_ID = 0, /* Process long style options */ + OPTPROC_SHORTOPT_ID = 1, /* Process short style "flags" */ + OPTPROC_ERRSTOP_ID = 2, /* Stop on argument errors */ + OPTPROC_DISABLEDOPT_ID = 3, /* Current option is disabled */ + OPTPROC_NO_REQ_OPT_ID = 4, /* no options are required */ + OPTPROC_NUM_OPT_ID = 5, /* there is a number option */ + OPTPROC_INITDONE_ID = 6, /* have inits been done? */ + OPTPROC_NEGATIONS_ID = 7, /* any negation options? */ + OPTPROC_ENVIRON_ID = 8, /* check environment? */ + OPTPROC_NO_ARGS_ID = 9, /* Disallow remaining arguments */ + OPTPROC_ARGS_REQ_ID = 10, /* Require args after options */ + OPTPROC_REORDER_ID = 11, /* reorder operands after opts */ + OPTPROC_GNUUSAGE_ID = 12, /* emit usage in GNU style */ + OPTPROC_TRANSLATE_ID = 13, /* Translate strings in tOptions */ + OPTPROC_MISUSE_ID = 14, /* no usage on usage error */ + OPTPROC_IMMEDIATE_ID = 15, /* immediate options active */ + OPTPROC_NXLAT_OPT_CFG_ID = 16, /* suppress for config only */ + OPTPROC_NXLAT_OPT_ID = 17, /* suppress xlation always */ + OPTPROC_VENDOR_OPT_ID = 18, /* vendor options active */ + OPTPROC_PRESETTING_ID = 19 /* opt processing in preset state */ +} optproc_state_enum_t; + +#define OPTPROC_NONE 0U +#define OPTPROC_LONGOPT (1U << OPTPROC_LONGOPT_ID) +#define OPTPROC_SHORTOPT (1U << OPTPROC_SHORTOPT_ID) +#define OPTPROC_ERRSTOP (1U << OPTPROC_ERRSTOP_ID) +#define OPTPROC_DISABLEDOPT (1U << OPTPROC_DISABLEDOPT_ID) +#define OPTPROC_NO_REQ_OPT (1U << OPTPROC_NO_REQ_OPT_ID) +#define OPTPROC_NUM_OPT (1U << OPTPROC_NUM_OPT_ID) +#define OPTPROC_INITDONE (1U << OPTPROC_INITDONE_ID) +#define OPTPROC_NEGATIONS (1U << OPTPROC_NEGATIONS_ID) +#define OPTPROC_ENVIRON (1U << OPTPROC_ENVIRON_ID) +#define OPTPROC_NO_ARGS (1U << OPTPROC_NO_ARGS_ID) +#define OPTPROC_ARGS_REQ (1U << OPTPROC_ARGS_REQ_ID) +#define OPTPROC_REORDER (1U << OPTPROC_REORDER_ID) +#define OPTPROC_GNUUSAGE (1U << OPTPROC_GNUUSAGE_ID) +#define OPTPROC_TRANSLATE (1U << OPTPROC_TRANSLATE_ID) +#define OPTPROC_MISUSE (1U << OPTPROC_MISUSE_ID) +#define OPTPROC_IMMEDIATE (1U << OPTPROC_IMMEDIATE_ID) +#define OPTPROC_NXLAT_OPT_CFG (1U << OPTPROC_NXLAT_OPT_CFG_ID) +#define OPTPROC_NXLAT_OPT (1U << OPTPROC_NXLAT_OPT_ID) +#define OPTPROC_VENDOR_OPT (1U << OPTPROC_VENDOR_OPT_ID) +#define OPTPROC_PRESETTING (1U << OPTPROC_PRESETTING_ID) +#define OPTPROC_STATE_MASK 0x000FFFFFU + +#define OPTPROC_NO_XLAT_MASK ( \ + OPTPROC_NXLAT_OPT | OPTPROC_NXLAT_OPT_CFG \ + /* 0x00030000U */ ) + +#define STMTS(s) do { s; } while (false) + +/* + * The following must be #defined instead of typedef-ed + * because "static const" cannot both be applied to a type, + * tho each individually can...so they all are + */ +#define tSCC static char const +#define tCC char const +#define tAoSC static char +#define tAoUC unsigned char +#define tAoUI unsigned int +#define tAoUL unsigned long +#define tAoUS unsigned short + +/* + * It is so disgusting that there must be so many ways + * of specifying TRUE and FALSE. + */ +typedef enum { AG_FALSE = 0, AG_TRUE } ag_bool; + +/* + * Define a structure that describes each option and + * a pointer to the procedure that handles it. + * The argument is the count of this flag previously seen. + */ +typedef struct options tOptions; +typedef struct optDesc tOptDesc; +typedef struct optNames tOptNames; +#define OPTPROC_EMIT_USAGE ((tOptions *)0x01UL) +#define OPTPROC_EMIT_SHELL ((tOptions *)0x02UL) +#define OPTPROC_RETURN_VALNAME ((tOptions *)0x03UL) +#define OPTPROC_EMIT_LIMIT ((tOptions *)0x0FUL) + +/* + * The option procedures do the special processing for each + * option flag that needs it. + */ +typedef void (tOptProc)(tOptions* pOpts, tOptDesc* pOptDesc); +typedef tOptProc* tpOptProc; + +/* + * The usage procedure will never return. It calls "exit(2)" + * with the "exitCode" argument passed to it. + */ +// coverity[+kill] +typedef void (tUsageProc)(tOptions* pOpts, int exitCode); +typedef tUsageProc * tpUsageProc; + +/* + * Special definitions. "NOLIMIT" is the 'max' value to use when + * a flag may appear multiple times without limit. "NO_EQUIVALENT" + * is an illegal value for 'optIndex' (option description index). + */ +#define NOLIMIT USHRT_MAX +#define OPTION_LIMIT SHRT_MAX +#define NO_EQUIVALENT (OPTION_LIMIT+1) + +typedef union { + char const * argString; + uintptr_t argEnum; + uintptr_t argIntptr; + long argInt; + unsigned long argUint; + unsigned int argBool; + FILE * argFp; + int argFd; +} optArgBucket_t; + +#define pzLastArg optArg.argString + +/* + * Descriptor structure for each option. + * Only the fields marked "PUBLIC" are for public use. + */ +struct optDesc { + tAoUS const optIndex; /* PUBLIC */ + tAoUS const optValue; /* PUBLIC */ + tAoUS optActualIndex; /* PUBLIC */ + tAoUS optActualValue; /* PUBLIC */ + + tAoUS const optEquivIndex; /* PUBLIC */ + tAoUS const optMinCt; + tAoUS const optMaxCt; + tAoUS optOccCt; /* PUBLIC */ + + tAoUI fOptState; /* PUBLIC */ + tAoUI reserved; + optArgBucket_t optArg; /* PUBLIC */ + void* optCookie; /* PUBLIC */ + + int const * const pOptMust; + int const * const pOptCant; + tpOptProc const pOptProc; + char const* const pzText; + + char const* const pz_NAME; + char const* const pz_Name; + char const* const pz_DisableName; + char const* const pz_DisablePfx; +}; + +/* + * Some options need special processing, so we store their + * indexes in a known place: + */ +typedef struct optSpecIndex tOptSpecIndex; +struct optSpecIndex { + const tAoUS more_help; + const tAoUS save_opts; + const tAoUS number_option; + const tAoUS default_opt; +}; + +/* + * The procedure generated for translating option text + */ +typedef void (tOptionXlateProc)(void); + +/* + * Everything marked "PUBLIC" is also marked "const". Public access is not + * a license to modify. Other fields are used and modified by the library. + * They are also subject to change without any notice. + * Do not even look at these outside of libopts. + */ +struct options { + int const structVersion; + unsigned int origArgCt; + char** origArgVect; + unsigned int fOptSet; + unsigned int curOptIdx; + char* pzCurOpt; + + char const* const pzProgPath; /* PUBLIC */ + char const* const pzProgName; /* PUBLIC */ + char const* const pzPROGNAME; /* PUBLIC */ + char const* const pzRcName; /* PUBLIC */ + char const* const pzCopyright; /* PUBLIC */ + char const* const pzCopyNotice; /* PUBLIC */ + char const* const pzFullVersion; /* PUBLIC */ + char const* const* const papzHomeList; + char const* const pzUsageTitle; + char const* const pzExplain; + char const* const pzDetail; + tOptDesc* const pOptDesc; /* PUBLIC */ + char const* const pzBugAddr; /* PUBLIC */ + + void* pExtensions; + void* pSavedState; + + // coverity[+kill] + tpUsageProc pUsageProc; + tOptionXlateProc* pTransProc; + + tOptSpecIndex specOptIdx; + int const optCt; + int const presetOptCt; + char const * pzFullUsage; + char const * pzShortUsage; + /* PUBLIC: */ + optArgBucket_t const * const originalOptArgArray; + void * const * const originalOptArgCookie; + char const * const pzPkgDataDir; + char const * const pzPackager; +}; + +/* + * Versions where in various fields first appear: + * ($AO_CURRENT * 4096 + $AO_REVISION, but $AO_REVISION must be zero) + */ +#define originalOptArgArray_STRUCT_VERSION 131072 /* AO_CURRENT = 32 */ +#define HAS_originalOptArgArray(_opt) \ + ((_opt)->structVersion >= originalOptArgArray_STRUCT_VERSION) + +#define pzPkgDataDir_STRUCT_VERSION 139264 /* AO_CURRENT = 34 */ +#define HAS_pzPkgDataDir(_opt) \ + ((_opt)->structVersion >= pzPkgDataDir_STRUCT_VERSION) + +/* + * "token list" structure returned by "string_tokenize()" + */ +typedef struct { + unsigned long tkn_ct; + unsigned char* tkn_list[1]; +} token_list_t; + +/* + * Hide the interface - it pollutes a POSIX claim, but leave it for + * anyone #include-ing this header + */ +#define strneqvcmp option_strneqvcmp +#define streqvcmp option_streqvcmp +#define streqvmap option_streqvmap +#define strequate option_strequate +#define strtransform option_strtransform + +/** + * Everything needed to be known about an mmap-ed file. + * + * This is an output only structure used by text_mmap and text_munmap. + * Clients must not alter the contents and must provide it to both + * the text_mmap and text_munmap procedures. BE ADVISED: if you are + * mapping the file with PROT_WRITE the NUL byte at the end MIGHT NOT + * BE WRITABLE. In any event, that byte is not be written back + * to the source file. ALSO: if "txt_data" is valid and "txt_errno" + * is not zero, then there *may* not be a terminating NUL. + */ +typedef struct { + void * txt_data; /*@< text file data */ + size_t txt_size; /*@< actual file size */ + size_t txt_full_size; /*@< mmaped mem size */ + int txt_fd; /*@< file descriptor */ + int txt_zero_fd; /*@< fd for /dev/zero */ + int txt_errno; /*@< warning code */ + int txt_prot; /*@< "prot" flags */ + int txt_flags; /*@< mapping type */ +} tmap_info_t; + +#define TEXT_MMAP_FAILED_ADDR(a) ((void*)(a) == (void*)MAP_FAILED) + +#ifdef __cplusplus +#define CPLUSPLUS_OPENER extern "C" { +CPLUSPLUS_OPENER +#define CPLUSPLUS_CLOSER } +#else +#define CPLUSPLUS_CLOSER +#endif + +/* + * The following routines may be coded into AutoOpts client code: + */ + +/* From: tokenize.c line 164 + * + * ao_string_tokenize - tokenize an input string + * + * Arguments: + * string string to be tokenized + * + * Returns: token_list_t* - pointer to a structure that lists each token + * + * This function will convert one input string into a list of strings. + * The list of strings is derived by separating the input based on + * white space separation. However, if the input contains either single + * or double quote characters, then the text after that character up to + * a matching quote will become the string in the list. + * + * The returned pointer should be deallocated with @code{free(3C)} when + * are done using the data. The data are placed in a single block of + * allocated memory. Do not deallocate individual token/strings. + * + * The structure pointed to will contain at least these two fields: + * @table @samp + * @item tkn_ct + * The number of tokens found in the input string. + * @item tok_list + * An array of @code{tkn_ct + 1} pointers to substring tokens, with + * the last pointer set to NULL. + * @end table + * + * There are two types of quoted strings: single quoted (@code{'}) and + * double quoted (@code{"}). Singly quoted strings are fairly raw in that + * escape characters (@code{\\}) are simply another character, except when + * preceding the following characters: + * @example + * @code{\\} double backslashes reduce to one + * @code{'} incorporates the single quote into the string + * @code{\n} suppresses both the backslash and newline character + * @end example + * + * Double quote strings are formed according to the rules of string + * constants in ANSI-C programs. + */ +extern token_list_t* ao_string_tokenize(char const*); + + +/* From: configfile.c line 77 + * + * configFileLoad - parse a configuration file + * + * Arguments: + * pzFile the file to load + * + * Returns: const tOptionValue* - An allocated, compound value structure + * + * This routine will load a named configuration file and parse the + * text as a hierarchically valued option. The option descriptor + * created from an option definition file is not used via this interface. + * The returned value is "named" with the input file name and is of + * type "@code{OPARG_TYPE_HIERARCHY}". It may be used in calls to + * @code{optionGetValue()}, @code{optionNextValue()} and + * @code{optionUnloadNested()}. + */ +extern const tOptionValue* configFileLoad(char const*); + + +/* From: configfile.c line 1066 + * + * optionFileLoad - Load the locatable config files, in order + * + * Arguments: + * pOpts program options descriptor + * pzProg program name + * + * Returns: int - 0 -> SUCCESS, -1 -> FAILURE + * + * This function looks in all the specified directories for a configuration + * file ("rc" file or "ini" file) and processes any found twice. The first + * time through, they are processed in reverse order (last file first). At + * that time, only "immediate action" configurables are processed. For + * example, if the last named file specifies not processing any more + * configuration files, then no more configuration files will be processed. + * Such an option in the @strong{first} named directory will have no effect. + * + * Once the immediate action configurables have been handled, then the + * directories are handled in normal, forward order. In that way, later + * config files can override the settings of earlier config files. + * + * See the AutoOpts documentation for a thorough discussion of the + * config file format. + * + * Configuration files not found or not decipherable are simply ignored. + */ +extern int optionFileLoad(tOptions*, char const*); + + +/* From: configfile.c line 211 + * + * optionFindNextValue - find a hierarcicaly valued option instance + * + * Arguments: + * pOptDesc an option with a nested arg type + * pPrevVal the last entry + * name name of value to find + * value the matching value + * + * Returns: const tOptionValue* - a compound value structure + * + * This routine will find the next entry in a nested value option or + * configurable. It will search through the list and return the next entry + * that matches the criteria. + */ +extern const tOptionValue* optionFindNextValue(const tOptDesc*, const tOptionValue*, char const*, char const*); + + +/* From: configfile.c line 137 + * + * optionFindValue - find a hierarcicaly valued option instance + * + * Arguments: + * pOptDesc an option with a nested arg type + * name name of value to find + * value the matching value + * + * Returns: const tOptionValue* - a compound value structure + * + * This routine will find an entry in a nested value option or configurable. + * It will search through the list and return a matching entry. + */ +extern const tOptionValue* optionFindValue(const tOptDesc*, char const*, char const*); + + +/* From: restore.c line 166 + * + * optionFree - free allocated option processing memory + * + * Arguments: + * pOpts program options descriptor + * + * AutoOpts sometimes allocates memory and puts pointers to it in the + * option state structures. This routine deallocates all such memory. + */ +extern void optionFree(tOptions*); + + +/* From: configfile.c line 280 + * + * optionGetValue - get a specific value from a hierarcical list + * + * Arguments: + * pOptValue a hierarchcal value + * valueName name of value to get + * + * Returns: const tOptionValue* - a compound value structure + * + * This routine will find an entry in a nested value option or configurable. + * If "valueName" is NULL, then the first entry is returned. Otherwise, + * the first entry with a name that exactly matches the argument will be + * returned. If there is no matching value, NULL is returned and errno is + * set to ENOENT. If the provided option value is not a hierarchical value, + * NULL is also returned and errno is set to EINVAL. + */ +extern const tOptionValue* optionGetValue(const tOptionValue*, char const*); + + +/* From: load.c line 478 + * + * optionLoadLine - process a string for an option name and value + * + * Arguments: + * opts program options descriptor + * line NUL-terminated text + * + * This is a client program callable routine for setting options from, for + * example, the contents of a file that they read in. Only one option may + * appear in the text. It will be treated as a normal (non-preset) option. + * + * When passed a pointer to the option struct and a string, it will find + * the option named by the first token on the string and set the option + * argument to the remainder of the string. The caller must NUL terminate + * the string. The caller need not skip over any introductory hyphens. + * Any embedded new lines will be included in the option + * argument. If the input looks like one or more quoted strings, then the + * input will be "cooked". The "cooking" is identical to the string + * formation used in AutoGen definition files (@pxref{basic expression}), + * except that you may not use backquotes. + */ +extern void optionLoadLine(tOptions*, char const*); + + +/* From: configfile.c line 340 + * + * optionNextValue - get the next value from a hierarchical list + * + * Arguments: + * pOptValue a hierarchcal list value + * pOldValue a value from this list + * + * Returns: const tOptionValue* - a compound value structure + * + * This routine will return the next entry after the entry passed in. At the + * end of the list, NULL will be returned. If the entry is not found on the + * list, NULL will be returned and "@var{errno}" will be set to EINVAL. + * The "@var{pOldValue}" must have been gotten from a prior call to this + * routine or to "@code{opitonGetValue()}". + */ +extern const tOptionValue* optionNextValue(const tOptionValue*, const tOptionValue*); + + +/* From: usage.c line 201 + * + * optionOnlyUsage - Print usage text for just the options + * + * Arguments: + * pOpts program options descriptor + * ex_code exit code for calling exit(3) + * + * This routine will print only the usage for each option. + * This function may be used when the emitted usage must incorporate + * information not available to AutoOpts. + */ +extern void optionOnlyUsage(tOptions*, int); + + +/* From: autoopts.c line 607 + * + * optionProcess - this is the main option processing routine + * + * Arguments: + * pOpts program options descriptor + * argc program arg count + * argv program arg vector + * + * Returns: int - the count of the arguments processed + * + * This is the main entry point for processing options. It is intended + * that this procedure be called once at the beginning of the execution of + * a program. Depending on options selected earlier, it is sometimes + * necessary to stop and restart option processing, or to select completely + * different sets of options. This can be done easily, but you generally + * do not want to do this. + * + * The number of arguments processed always includes the program name. + * If one of the arguments is "--", then it is counted and the processing + * stops. If an error was encountered and errors are to be tolerated, then + * the returned value is the index of the argument causing the error. + * A hyphen by itself ("-") will also cause processing to stop and will + * @emph{not} be counted among the processed arguments. A hyphen by itself + * is treated as an operand. Encountering an operand stops option + * processing. + */ +extern int optionProcess(tOptions*, int, char**); + + +/* From: restore.c line 123 + * + * optionRestore - restore option state from memory copy + * + * Arguments: + * pOpts program options descriptor + * + * Copy back the option state from saved memory. + * The allocated memory is left intact, so this routine can be + * called repeatedly without having to call optionSaveState again. + * If you are restoring a state that was saved before the first call + * to optionProcess(3AO), then you may change the contents of the + * argc/argv parameters to optionProcess. + */ +extern void optionRestore(tOptions*); + + +/* From: save.c line 648 + * + * optionSaveFile - saves the option state to a file + * + * Arguments: + * pOpts program options descriptor + * + * This routine will save the state of option processing to a file. The name + * of that file can be specified with the argument to the @code{--save-opts} + * option, or by appending the @code{rcfile} attribute to the last + * @code{homerc} attribute. If no @code{rcfile} attribute was specified, it + * will default to @code{.@i{programname}rc}. If you wish to specify another + * file, you should invoke the @code{SET_OPT_SAVE_OPTS(@i{filename})} macro. + * + * The recommend usage is as follows: + * @example + * optionProcess(&progOptions, argc, argv); + * if (i_want_a_non_standard_place_for_this) + * SET_OPT_SAVE_OPTS("myfilename"); + * optionSaveFile(&progOptions); + * @end example + */ +extern void optionSaveFile(tOptions*); + + +/* From: restore.c line 71 + * + * optionSaveState - saves the option state to memory + * + * Arguments: + * pOpts program options descriptor + * + * This routine will allocate enough memory to save the current option + * processing state. If this routine has been called before, that memory + * will be reused. You may only save one copy of the option state. This + * routine may be called before optionProcess(3AO). If you do call it + * before the first call to optionProcess, then you may also change the + * contents of argc/argv after you call optionRestore(3AO) + * + * In fact, more strongly put: it is safest to only use this function + * before having processed any options. In particular, the saving and + * restoring of stacked string arguments and hierarchical values is + * disabled. The values are not saved. + */ +extern void optionSaveState(tOptions*); + + +/* From: nested.c line 563 + * + * optionUnloadNested - Deallocate the memory for a nested value + * + * Arguments: + * pOptVal the hierarchical value + * + * A nested value needs to be deallocated. The pointer passed in should + * have been gotten from a call to @code{configFileLoad()} (See + * @pxref{libopts-configFileLoad}). + */ +extern void optionUnloadNested(tOptionValue const *); + + +/* From: version.c line 31 + * + * optionVersion - return the compiled AutoOpts version number + * + * Returns: char const* - the version string in constant memory + * + * Returns the full version string compiled into the library. + * The returned string cannot be modified. + */ +extern char const* optionVersion(void); + + +/* From: ../compat/pathfind.c line 29 + * + * pathfind - fild a file in a list of directories + * + * Arguments: + * path colon separated list of search directories + * file the name of the file to look for + * mode the mode bits that must be set to match + * + * Returns: char* - the path to the located file + * + * the pathfind function is available only if HAVE_PATHFIND is not defined + * + * pathfind looks for a a file with name "FILE" and "MODE" access + * along colon delimited "PATH", and returns the full pathname as a + * string, or NULL if not found. If "FILE" contains a slash, then + * it is treated as a relative or absolute path and "PATH" is ignored. + * + * @strong{NOTE}: this function is compiled into @file{libopts} only if + * it is not natively supplied. + * + * The "MODE" argument is a string of option letters chosen from the + * list below: + * @example + * Letter Meaning + * r readable + * w writable + * x executable + * f normal file (NOT IMPLEMENTED) + * b block special (NOT IMPLEMENTED) + * c character special (NOT IMPLEMENTED) + * d directory (NOT IMPLEMENTED) + * p FIFO (pipe) (NOT IMPLEMENTED) + * u set user ID bit (NOT IMPLEMENTED) + * g set group ID bit (NOT IMPLEMENTED) + * k sticky bit (NOT IMPLEMENTED) + * s size nonzero (NOT IMPLEMENTED) + * @end example + */ +#ifndef HAVE_PATHFIND +extern char* pathfind(char const*, char const*, char const*); +#endif /* HAVE_PATHFIND */ + + +/* From: streqvcmp.c line 209 + * + * strequate - map a list of characters to the same value + * + * Arguments: + * ch_list characters to equivalence + * + * Each character in the input string get mapped to the first character + * in the string. + * This function name is mapped to option_strequate so as to not conflict + * with the POSIX name space. + */ +extern void strequate(char const*); + + +/* From: streqvcmp.c line 119 + * + * streqvcmp - compare two strings with an equivalence mapping + * + * Arguments: + * str1 first string + * str2 second string + * + * Returns: int - the difference between two differing characters + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * This function name is mapped to option_streqvcmp so as to not conflict + * with the POSIX name space. + */ +extern int streqvcmp(char const*, char const*); + + +/* From: streqvcmp.c line 156 + * + * streqvmap - Set the character mappings for the streqv functions + * + * Arguments: + * From Input character + * To Mapped-to character + * ct compare length + * + * Set the character mapping. If the count (@code{ct}) is set to zero, then + * the map is cleared by setting all entries in the map to their index + * value. Otherwise, the "@code{From}" character is mapped to the "@code{To}" + * character. If @code{ct} is greater than 1, then @code{From} and @code{To} + * are incremented and the process repeated until @code{ct} entries have been + * set. For example, + * @example + * streqvmap('a', 'A', 26); + * @end example + * @noindent + * will alter the mapping so that all English lower case letters + * will map to upper case. + * + * This function name is mapped to option_streqvmap so as to not conflict + * with the POSIX name space. + */ +extern void streqvmap(char, char, int); + + +/* From: streqvcmp.c line 78 + * + * strneqvcmp - compare two strings with an equivalence mapping + * + * Arguments: + * str1 first string + * str2 second string + * ct compare length + * + * Returns: int - the difference between two differing characters + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * The comparison is limited to @code{ct} bytes. + * This function name is mapped to option_strneqvcmp so as to not conflict + * with the POSIX name space. + */ +extern int strneqvcmp(char const*, char const*, int); + + +/* From: streqvcmp.c line 235 + * + * strtransform - convert a string into its mapped-to value + * + * Arguments: + * dest output string + * src input string + * + * Each character in the input string is mapped and the mapped-to + * character is put into the output. + * This function name is mapped to option_strtransform so as to not conflict + * with the POSIX name space. + * + * The source and destination may be the same. + */ +extern void strtransform(char*, char const*); + +/* AutoOpts PRIVATE FUNCTIONS: */ +tOptProc optionStackArg, optionUnstackArg, optionBooleanVal, optionNumericVal; + +extern char* ao_string_cook(char*, int*); + +extern unsigned int ao_string_cook_escape_char(char const*, char*, unsigned int); + +extern void genshelloptUsage(tOptions*, int); + +extern int optionAlias(tOptions*, tOptDesc*, unsigned int); + +extern void optionBooleanVal(tOptions*, tOptDesc*); + +extern uintptr_t optionEnumerationVal(tOptions*, tOptDesc*, char const * const *, unsigned int); + +extern void optionFileCheck(tOptions*, tOptDesc*, teOptFileType, tuFileMode); + +extern char const * optionKeywordName(tOptDesc*, unsigned int); + +extern void optionLoadOpt(tOptions*, tOptDesc*); + +extern bool optionMakePath(char*, int, char const*, char const*); + +extern void optionNestedVal(tOptions*, tOptDesc*); + +extern void optionNumericVal(tOptions*, tOptDesc*); + +extern void optionPagedUsage(tOptions*, tOptDesc*); + +extern void optionParseShell(tOptions*); + +extern void optionPrintVersion(tOptions*, tOptDesc*); + +extern void optionPutShell(tOptions*); + +extern void optionResetOpt(tOptions*, tOptDesc*); + +extern void optionSetMembers(tOptions*, tOptDesc*, char const * const *, unsigned int); + +extern void optionShowRange(tOptions*, tOptDesc*, void *, int); + +extern void optionStackArg(tOptions*, tOptDesc*); + +extern void optionTimeDate(tOptions*, tOptDesc*); + +extern void optionTimeVal(tOptions*, tOptDesc*); + +extern void optionUnstackArg(tOptions*, tOptDesc*); + +extern void optionUsage(tOptions*, int); + +extern void optionVendorOption(tOptions *, tOptDesc *); + +extern void optionVersionStderr(tOptions*, tOptDesc*); + +extern void* text_mmap(char const*, int, int, tmap_info_t*); + +extern int text_munmap(tmap_info_t*); + +CPLUSPLUS_CLOSER +#endif /* AUTOOPTS_OPTIONS_H_GUARD */ +/* + * Local Variables: + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * options.h ends here */ diff --git a/autoopts/autoopts/usage-txt.h b/autoopts/autoopts/usage-txt.h new file mode 100644 index 0000000..0200b84 --- /dev/null +++ b/autoopts/autoopts/usage-txt.h @@ -0,0 +1,435 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (usage-txt.h) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:15 AM by AutoGen 5.16.2pre7 + * From the definitions usage-txt.def + * and the template file usage-txt.tpl + * + * This file handles all the bookkeeping required for tracking all the little + * tiny strings used by the AutoOpts library. There are 146 + * of them. This is not versioned because it is entirely internal to the + * library and accessed by client code only in a very well-controlled way: + * they may substitute translated strings using a procedure that steps through + * all the string pointers. + * + * Copyright (C) 1992-2012 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * GNU Lesser General Public License, version 3 or later + * <http://gnu.org/licenses/lgpl.html> + * + * AutoOpts is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AutoOpts is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>."; + */ +#ifndef AUTOOPTS_USAGE_TXT_H_GUARD +#define AUTOOPTS_USAGE_TXT_H_GUARD 1 + +#undef cch_t +#define cch_t char const + +/* + * One structure to hold all the pointers to all the stringlets. + */ +typedef struct { + int field_ct; + char* utpz_GnuBoolArg; + char* utpz_GnuKeyArg; + char* utpz_GnuFileArg; + char* utpz_GnuKeyLArg; + char* utpz_GnuTimeArg; + char* utpz_GnuNumArg; + char* utpz_GnuStrArg; + cch_t* apz_str[ 139 ]; +} usage_text_t; + +/* + * Declare the global structure with all the pointers to translated + * strings. This is then used by the usage generation procedure. + */ +extern usage_text_t option_usage_text; + +#if defined(AUTOOPTS_INTERNAL) /* DEFINE ALL THE STRINGS = = = = = */ +/* + * Provide a mapping from a short name to fields in this structure. + */ +#define zAO_Alloc (option_usage_text.apz_str[ 0]) +#define zAO_Bad (option_usage_text.apz_str[ 1]) +#define zAO_Big (option_usage_text.apz_str[ 2]) +#define zAO_Err (option_usage_text.apz_str[ 3]) +#define zAO_Realloc (option_usage_text.apz_str[ 4]) +#define zAO_Sml (option_usage_text.apz_str[ 5]) +#define zAO_Strdup (option_usage_text.apz_str[ 6]) +#define zAO_Ver (option_usage_text.apz_str[ 7]) +#define zAO_Woops (option_usage_text.apz_str[ 8]) +#define zAliasRange (option_usage_text.apz_str[ 9]) +#define zAll (option_usage_text.apz_str[ 10]) +#define zAlt (option_usage_text.apz_str[ 11]) +#define zAmbigKey (option_usage_text.apz_str[ 12]) +#define zAmbigList (option_usage_text.apz_str[ 13]) +#define zAmbigOptStr (option_usage_text.apz_str[ 14]) +#define zAmbiguous (option_usage_text.apz_str[ 15]) +#define zArgsMust (option_usage_text.apz_str[ 16]) +#define zAtMost (option_usage_text.apz_str[ 17]) +#define zAuto (option_usage_text.apz_str[ 18]) +#define zBadPipe (option_usage_text.apz_str[ 19]) +#define zBadVerArg (option_usage_text.apz_str[ 20]) +#define zCantFmt (option_usage_text.apz_str[ 21]) +#define zCantSave (option_usage_text.apz_str[ 22]) +#define zCfgAO_Flags (option_usage_text.apz_str[ 23]) +#define zCfgProg (option_usage_text.apz_str[ 24]) +#define zDefaultOpt (option_usage_text.apz_str[ 25]) +#define zDis (option_usage_text.apz_str[ 26]) +#define zDisabledErr (option_usage_text.apz_str[ 27]) +#define zDisabledOpt (option_usage_text.apz_str[ 28]) +#define zDisabledWhy (option_usage_text.apz_str[ 29]) +#define zEnab (option_usage_text.apz_str[ 30]) +#define zEquiv (option_usage_text.apz_str[ 31]) +#define zErrOnly (option_usage_text.apz_str[ 32]) +#define zExamineFmt (option_usage_text.apz_str[ 33]) +#define zFiveSpaces (option_usage_text.apz_str[ 34]) +#define zFlagOkay (option_usage_text.apz_str[ 35]) +#define zFmtFmt (option_usage_text.apz_str[ 36]) +#define zForkFail (option_usage_text.apz_str[ 37]) +#define zFreopenFail (option_usage_text.apz_str[ 38]) +#define zFSErrOptLoad (option_usage_text.apz_str[ 39]) +#define zFSErrReadFile (option_usage_text.apz_str[ 40]) +#define zFSOptError (option_usage_text.apz_str[ 41]) +#define zFSOptErrMayExist (option_usage_text.apz_str[ 42]) +#define zFSOptErrMustExist (option_usage_text.apz_str[ 43]) +#define zFSOptErrNoExist (option_usage_text.apz_str[ 44]) +#define zFSOptErrOpen (option_usage_text.apz_str[ 45]) +#define zFSOptErrFopen (option_usage_text.apz_str[ 46]) +#define zFileCannotExist (option_usage_text.apz_str[ 47]) +#define zFileMustExist (option_usage_text.apz_str[ 48]) +#define zGenshell (option_usage_text.apz_str[ 49]) +#define zGnuBoolArg (option_usage_text.utpz_GnuBoolArg) +#define zGnuBreak (option_usage_text.apz_str[ 50]) +#define zGnuKeyArg (option_usage_text.utpz_GnuKeyArg) +#define zGnuFileArg (option_usage_text.utpz_GnuFileArg) +#define zGnuKeyLArg (option_usage_text.utpz_GnuKeyLArg) +#define zGnuTimeArg (option_usage_text.utpz_GnuTimeArg) +#define zGnuNestArg (option_usage_text.apz_str[ 51]) +#define zGnuNumArg (option_usage_text.utpz_GnuNumArg) +#define zGnuOptArg (option_usage_text.apz_str[ 52]) +#define zGnuOptFmt (option_usage_text.apz_str[ 53]) +#define zGnuStrArg (option_usage_text.utpz_GnuStrArg) +#define zIllOptChr (option_usage_text.apz_str[ 54]) +#define zIllOptStr (option_usage_text.apz_str[ 55]) +#define zIllVendOptStr (option_usage_text.apz_str[ 56]) +#define zIntRange (option_usage_text.apz_str[ 57]) +#define zInvalOptDesc (option_usage_text.apz_str[ 58]) +#define zInvalOptName (option_usage_text.apz_str[ 59]) +#define zLowerBits (option_usage_text.apz_str[ 60]) +#define zMembers (option_usage_text.apz_str[ 61]) +#define zMisArg (option_usage_text.apz_str[ 62]) +#define zMultiEquiv (option_usage_text.apz_str[ 63]) +#define zMust (option_usage_text.apz_str[ 64]) +#define zNeedOne (option_usage_text.apz_str[ 65]) +#define zNoArg (option_usage_text.apz_str[ 66]) +#define zNoArgs (option_usage_text.apz_str[ 67]) +#define zNoCreat (option_usage_text.apz_str[ 68]) +#define zNoFlags (option_usage_text.apz_str[ 69]) +#define zNoKey (option_usage_text.apz_str[ 70]) +#define zNoLim (option_usage_text.apz_str[ 71]) +#define zNoPreset (option_usage_text.apz_str[ 72]) +#define zNoResetArg (option_usage_text.apz_str[ 73]) +#define zNoRq_NoShrtTtl (option_usage_text.apz_str[ 74]) +#define zNoRq_ShrtTtl (option_usage_text.apz_str[ 75]) +#define zNoStat (option_usage_text.apz_str[ 76]) +#define zNoState (option_usage_text.apz_str[ 77]) +#define zNone (option_usage_text.apz_str[ 78]) +#define zNotDef (option_usage_text.apz_str[ 79]) +#define zNotCmdOpt (option_usage_text.apz_str[ 80]) +#define zNotEnough (option_usage_text.apz_str[ 81]) +#define zNotFile (option_usage_text.apz_str[ 82]) +#define zNotNumber (option_usage_text.apz_str[ 83]) +#define zNotDate (option_usage_text.apz_str[ 84]) +#define zNotDuration (option_usage_text.apz_str[ 85]) +#define zNrmOptFmt (option_usage_text.apz_str[ 86]) +#define zNumberOpt (option_usage_text.apz_str[ 87]) +#define zOnlyOne (option_usage_text.apz_str[ 88]) +#define zOptsOnly (option_usage_text.apz_str[ 89]) +#define zOutputFail (option_usage_text.apz_str[ 90]) +#define zPathFmt (option_usage_text.apz_str[ 91]) +#define zPlsSendBugs (option_usage_text.apz_str[ 92]) +#define zPreset (option_usage_text.apz_str[ 93]) +#define zPresetFile (option_usage_text.apz_str[ 94]) +#define zPresetIntro (option_usage_text.apz_str[ 95]) +#define zProhib (option_usage_text.apz_str[ 96]) +#define zReorder (option_usage_text.apz_str[ 97]) +#define zRange (option_usage_text.apz_str[ 98]) +#define zRangeAbove (option_usage_text.apz_str[ 99]) +#define zRangeLie (option_usage_text.apz_str[100]) +#define zRangeOnly (option_usage_text.apz_str[101]) +#define zRangeOr (option_usage_text.apz_str[102]) +#define zRangeErr (option_usage_text.apz_str[103]) +#define zRangeExact (option_usage_text.apz_str[104]) +#define zRangeScaled (option_usage_text.apz_str[105]) +#define zRangeUpto (option_usage_text.apz_str[106]) +#define zResetNotConfig (option_usage_text.apz_str[107]) +#define zReqFmt (option_usage_text.apz_str[108]) +#define zReqOptFmt (option_usage_text.apz_str[109]) +#define zReqThese (option_usage_text.apz_str[110]) +#define zReq_NoShrtTtl (option_usage_text.apz_str[111]) +#define zReq_ShrtTtl (option_usage_text.apz_str[112]) +#define zSepChars (option_usage_text.apz_str[113]) +#define zSetMemberSettings (option_usage_text.apz_str[114]) +#define zShrtGnuOptFmt (option_usage_text.apz_str[115]) +#define zSixSpaces (option_usage_text.apz_str[116]) +#define zStdBoolArg (option_usage_text.apz_str[117]) +#define zStdBreak (option_usage_text.apz_str[118]) +#define zStdFileArg (option_usage_text.apz_str[119]) +#define zStdKeyArg (option_usage_text.apz_str[120]) +#define zStdKeyLArg (option_usage_text.apz_str[121]) +#define zStdTimeArg (option_usage_text.apz_str[122]) +#define zStdNestArg (option_usage_text.apz_str[123]) +#define zStdNoArg (option_usage_text.apz_str[124]) +#define zStdNumArg (option_usage_text.apz_str[125]) +#define zStdOptArg (option_usage_text.apz_str[126]) +#define zStdReqArg (option_usage_text.apz_str[127]) +#define zStdStrArg (option_usage_text.apz_str[128]) +#define zTabHyp (option_usage_text.apz_str[129]) +#define zTabHypAnd (option_usage_text.apz_str[130]) +#define zTabout (option_usage_text.apz_str[131]) +#define zThreeSpaces (option_usage_text.apz_str[132]) +#define zTooLarge (option_usage_text.apz_str[133]) +#define zTwoSpaces (option_usage_text.apz_str[134]) +#define zUpTo (option_usage_text.apz_str[135]) +#define zValidKeys (option_usage_text.apz_str[136]) +#define zVendOptsAre (option_usage_text.apz_str[137]) +#define zVendIntro (option_usage_text.apz_str[138]) + + /* + * First, set up the strings. Some of these are writable. These are all in + * English. This gets compiled into libopts and is distributed here so that + * xgettext (or equivalents) can extract these strings for translation. + */ + + static char eng_zGnuBoolArg[] = "=T/F"; + static char eng_zGnuKeyArg[] = "=KWd"; + static char eng_zGnuFileArg[] = "=file"; + static char eng_zGnuKeyLArg[] = "=Mbr"; + static char eng_zGnuTimeArg[] = "=Tim"; + static char eng_zGnuNumArg[] = "=num"; + static char eng_zGnuStrArg[] = "=str"; +static char const usage_txt[4660] = +/* 0 */ "malloc of %d bytes failed\n\0" +/* 27 */ "AutoOpts function called without option descriptor\n\0" +/* 79 */ "\tThis exceeds the compiled library version: \0" +/* 125 */ "Automated Options Processing Error!\n" + "\t%s called AutoOpts function with structure version %d:%d:%d.\n\0" +/* 224 */ "realloc of %d bytes at 0x%p failed\n\0" +/* 260 */ "\tThis is less than the minimum library version: \0" +/* 310 */ "strdup of %d byte string failed\n\0" +/* 343 */ "Automated Options version %s\n" + "\tcopyright (c) 1999-2012 by Bruce Korb - all rights reserved\n\0" +/* 434 */ "AutoOpts lib error: defaulted to option with optional arg\n\0" +/* 493 */ "(AutoOpts bug): Aliasing option is out of range.\0" +/* 543 */ "all\0" +/* 547 */ "\t\t\t\t- an alternate for %s\n\0" +/* 574 */ "%s error: the keyword `%s' is ambiguous for %s\n\0" +/* 623 */ " The following options match:\n\0" +/* 655 */ "%s: ambiguous option name: %s (matches %d options)\n\0" +/* 707 */ " %s%s\n\0" +/* 715 */ "%s: Command line arguments required\n\0" +/* 752 */ "%d %s%s options allowed\n\0" +/* 777 */ "version, usage and configuration options:\0" +/* 819 */ "Error %d (%s) from the pipe(2) syscall\n\0" +/* 859 */ "ERROR: version option argument '%c' invalid. Use:\n" + "\t'v' - version only\n" + "\t'c' - version and copyright\n" + "\t'n' - version and copyright notice\n\0" +/* 996 */ "ERROR: %s option conflicts with the %s option\n\0" +/* 1044 */ "%s(optionSaveState): error: cannot allocate %d bytes\n\0" +/* 1098 */ "auto-options\0" +/* 1111 */ "program\0" +/* 1119 */ "\t\t\t\t- default option for unnamed options\n\0" +/* 1161 */ "\t\t\t\t- disabled as --%s\n\0" +/* 1185 */ "%s: The ``%s'' option has been disabled\0" +/* 1225 */ " --- %-14s %s\n\0" +/* 1240 */ "This option has been disabled\0" +/* 1270 */ "\t\t\t\t- enabled by default\n\0" +/* 1296 */ "-equivalence\0" +/* 1309 */ "ERROR: only \0" +/* 1323 */ " - examining environment variables named %s_*\n\0" +/* 1370 */ " \0" +/* 1376 */ "Options are specified by doubled hyphens and their name or by a single\n" + "hyphen and the flag character.\n\0" +/* 1479 */ "%%-%ds %%s\n\0" +/* 1491 */ "fs error %d (%s) on fork - cannot obtain %s usage\n\0" +/* 1542 */ "fs error %d (%s) on freopen\n\0" +/* 1571 */ "File error %d (%s) opening %s for loading options\n\0" +/* 1622 */ "fs error %d (%s) reading file %s\n\0" +/* 1656 */ "fs error %d (%s) on %s %s for option %s\n\0" +/* 1697 */ "stat-ing for directory\0" +/* 1720 */ "stat-ing for regular file\0" +/* 1746 */ "stat-ing for non-existant file\0" +/* 1777 */ "open-ing file\0" +/* 1791 */ "fopen-ing file\0" +/* 1806 */ "\t\t\t\t- file must not pre-exist\n\0" +/* 1837 */ "\t\t\t\t- file must pre-exist\n\0" +/* 1864 */ "\n" + "= = = = = = = =\n\n" + "This incarnation of genshell will produce\n" + "a shell script to parse the options for %s:\n\n\0" +/* 1970 */ "\n" + "%s\n\n\0" +/* 1976 */ "=Cplx\0" +/* 1982 */ "[=arg]\0" +/* 1989 */ "--%2$s%1$s\0" +/* 2000 */ "%s: illegal option -- %c\n\0" +/* 2026 */ "%s: illegal option -- %s\n\0" +/* 2052 */ "%s: unknown vendor extension option -- %s\n\0" +/* 2095 */ " or an integer from %d through %d\n\0" +/* 2131 */ "AutoOpts ERROR: invalid option descriptor for %s\n\0" +/* 2182 */ "%s: invalid option name: %s\n\0" +/* 2211 */ " or an integer mask with any of the lower %d bits set\n\0" +/* 2267 */ "\t\t\t\t- is a set membership option\n\0" +/* 2301 */ "%s: option `%s' requires an argument\n\0" +/* 2339 */ "Equivalenced option '%s' was equivalenced to both\n" + "\t'%s' and '%s'\0" +/* 2404 */ "\t\t\t\t- must appear between %d and %d times\n\0" +/* 2447 */ "ERROR: The %s option is required\n\0" +/* 2482 */ "%s: option `%s' cannot have an argument\n\0" +/* 2523 */ "%s: Command line arguments not allowed\n\0" +/* 2563 */ "error %d (%s) creating %s\n\0" +/* 2590 */ "Options are specified by single or double hyphens and their name.\n\0" +/* 2657 */ "%s error: `%s' does not match any %s keywords\n\0" +/* 2705 */ "\t\t\t\t- may appear multiple times\n\0" +/* 2738 */ "\t\t\t\t- may not be preset\n\0" +/* 2763 */ "The 'reset-option' option requires an argument\n\0" +/* 2811 */ " Arg Option-Name Description\n\0" +/* 2846 */ " Flg Arg Option-Name Description\n\0" +/* 2884 */ "error %d (%s) stat-ing %s\n\0" +/* 2911 */ "%s(optionRestore): error: no saved option state\n\0" +/* 2960 */ "none\0" +/* 2965 */ "'%s' not defined\n\0" +/* 2983 */ "'%s' is not a command line option\n\0" +/* 3018 */ "ERROR: The %s option must appear %d times\n\0" +/* 3062 */ "error: cannot load options from non-regular file %s\n\0" +/* 3116 */ "%s error: `%s' is not a recognizable number\n\0" +/* 3162 */ "%s error: `%s' is not a recognizable date/time\n\0" +/* 3211 */ "%s error: `%s' is not a recognizable time duration\n\0" +/* 3264 */ " %3s %s\0" +/* 3272 */ "The '-#<number>' option may omit the hash char\n\0" +/* 3320 */ "one %s%s option allowed\n\0" +/* 3345 */ "All arguments are named options.\n\0" +/* 3379 */ "Write failure to output file\0" +/* 3408 */ " - reading file %s\0" +/* 3427 */ "\n" + "please send bug reports to: %s\n\0" +/* 3461 */ "\t\t\t\t- may NOT appear - preset only\n\0" +/* 3497 */ "# preset/initialization file\n" + "# %s#\n\0" +/* 3535 */ "\n" + "The following option preset mechanisms are supported:\n\0" +/* 3591 */ "prohibits these options:\n\0" +/* 3617 */ "Operands and options may be intermixed. They will be reordered.\n\0" +/* 3683 */ "%s%ld to %ld\0" +/* 3696 */ "%sgreater than or equal to %ld\0" +/* 3727 */ "%sIt must lie in one of the ranges:\n\0" +/* 3764 */ "%sIt must be in the range:\n\0" +/* 3792 */ ", or\n\0" +/* 3798 */ "%s error: %s option value %ld is out of range.\n\0" +/* 3847 */ "%s%ld exactly\0" +/* 3861 */ "%sis scalable with a suffix: k/K/m/M/g/G/t/T\n\0" +/* 3907 */ "%sless than or equal to %ld\0" +/* 3935 */ "The --reset-option has not been configured.\n\0" +/* 3980 */ "ERROR: %s option requires the %s option\n\0" +/* 4022 */ " %3s %-14s %s\0" +/* 4036 */ "requires these options:\n\0" +/* 4061 */ " Arg Option-Name Req? Description\n\0" +/* 4101 */ " Flg Arg Option-Name Req? Description\n\0" +/* 4144 */ "-_^\0" +/* 4148 */ "or you may use a numeric representation. Preceding these with a '!' will\n" + "clear the bits, specifying 'none' will clear all bits, and 'all' will set them\n" + "all. Multiple entries may be passed as an option argument list.\n\0" +/* 4367 */ "%s\0" +/* 4370 */ " \0" +/* 4377 */ "T/F\0" +/* 4381 */ "\n" + "%s\n\n" + "%s\0" +/* 4389 */ "Fil\0" +/* 4393 */ "KWd\0" +/* 4397 */ "Mbr\0" +/* 4401 */ "Tim\0" +/* 4405 */ "Cpx\0" +/* 4409 */ "no \0" +/* 4413 */ "Num\0" +/* 4417 */ "opt\0" +/* 4421 */ "YES\0" +/* 4425 */ "Str\0" +/* 4429 */ "\t\t\t\t- \0" +/* 4436 */ "\t\t\t\t-- and \0" +/* 4448 */ "\t\t\t\t%s\n\0" +/* 4456 */ " \0" +/* 4460 */ "%s error: %s exceeds %s keyword count\n\0" +/* 4500 */ " \0" +/* 4503 */ "\t\t\t\t- may appear up to %d times\n\0" +/* 4536 */ "The valid \"%s\" option keywords are:\n\0" +/* 4573 */ "These additional options are:\0" +/* 4603 */ "The next option supports vendor supported extra options:"; + + + /* + * Now, define (and initialize) the structure that contains + * the pointers to all these strings. + * Aren't you glad you don't maintain this by hand? + */ + usage_text_t option_usage_text = { + 146, + eng_zGnuBoolArg, eng_zGnuKeyArg, eng_zGnuFileArg, eng_zGnuKeyLArg, + eng_zGnuTimeArg, eng_zGnuNumArg, eng_zGnuStrArg, + { + usage_txt + 0, usage_txt + 27, usage_txt + 79, usage_txt + 125, + usage_txt + 224, usage_txt + 260, usage_txt + 310, usage_txt + 343, + usage_txt + 434, usage_txt + 493, usage_txt + 543, usage_txt + 547, + usage_txt + 574, usage_txt + 623, usage_txt + 655, usage_txt + 707, + usage_txt + 715, usage_txt + 752, usage_txt + 777, usage_txt + 819, + usage_txt + 859, usage_txt + 996, usage_txt +1044, usage_txt +1098, + usage_txt +1111, usage_txt +1119, usage_txt +1161, usage_txt +1185, + usage_txt +1225, usage_txt +1240, usage_txt +1270, usage_txt +1296, + usage_txt +1309, usage_txt +1323, usage_txt +1370, usage_txt +1376, + usage_txt +1479, usage_txt +1491, usage_txt +1542, usage_txt +1571, + usage_txt +1622, usage_txt +1656, usage_txt +1697, usage_txt +1720, + usage_txt +1746, usage_txt +1777, usage_txt +1791, usage_txt +1806, + usage_txt +1837, usage_txt +1864, usage_txt +1970, usage_txt +1976, + usage_txt +1982, usage_txt +1989, usage_txt +2000, usage_txt +2026, + usage_txt +2052, usage_txt +2095, usage_txt +2131, usage_txt +2182, + usage_txt +2211, usage_txt +2267, usage_txt +2301, usage_txt +2339, + usage_txt +2404, usage_txt +2447, usage_txt +2482, usage_txt +2523, + usage_txt +2563, usage_txt +2590, usage_txt +2657, usage_txt +2705, + usage_txt +2738, usage_txt +2763, usage_txt +2811, usage_txt +2846, + usage_txt +2884, usage_txt +2911, usage_txt +2960, usage_txt +2965, + usage_txt +2983, usage_txt +3018, usage_txt +3062, usage_txt +3116, + usage_txt +3162, usage_txt +3211, usage_txt +3264, usage_txt +3272, + usage_txt +3320, usage_txt +3345, usage_txt +3379, usage_txt +3408, + usage_txt +3427, usage_txt +3461, usage_txt +3497, usage_txt +3535, + usage_txt +3591, usage_txt +3617, usage_txt +3683, usage_txt +3696, + usage_txt +3727, usage_txt +3764, usage_txt +3792, usage_txt +3798, + usage_txt +3847, usage_txt +3861, usage_txt +3907, usage_txt +3935, + usage_txt +3980, usage_txt +4022, usage_txt +4036, usage_txt +4061, + usage_txt +4101, usage_txt +4144, usage_txt +4148, usage_txt +4367, + usage_txt +4370, usage_txt +4377, usage_txt +4381, usage_txt +4389, + usage_txt +4393, usage_txt +4397, usage_txt +4401, usage_txt +4405, + usage_txt +4409, usage_txt +4413, usage_txt +4417, usage_txt +4421, + usage_txt +4425, usage_txt +4429, usage_txt +4436, usage_txt +4448, + usage_txt +4456, usage_txt +4460, usage_txt +4500, usage_txt +4503, + usage_txt +4536, usage_txt +4573, usage_txt +4603 + } + }; + +#endif /* DO_TRANSLATIONS */ +#endif /* AUTOOPTS_USAGE_TXT_H_GUARD */ diff --git a/autoopts/boolean.c b/autoopts/boolean.c new file mode 100644 index 0000000..c463778 --- /dev/null +++ b/autoopts/boolean.c @@ -0,0 +1,97 @@ + +/** + * \file boolean.c + * + * Time-stamp: "2012-08-11 08:34:39 bkorb" + * + * Automated Options Paged Usage module. + * + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionBooleanVal + * private: + * + * what: Decipher a boolean value + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Decipher a true or false value for a boolean valued option argument. + * The value is true, unless it starts with 'n' or 'f' or "#f" or + * it is an empty string or it is a number that evaluates to zero. +=*/ +void +optionBooleanVal(tOptions * pOpts, tOptDesc * pOD ) +{ + char* pz; + bool res = true; + + (void)pOpts; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + if (pOD->optArg.argString == NULL) { + pOD->optArg.argBool = false; + return; + } + + switch (*(pOD->optArg.argString)) { + case '0': + { + long val = strtol( pOD->optArg.argString, &pz, 0 ); + if ((val != 0) || (*pz != NUL)) + break; + /* FALLTHROUGH */ + } + case 'N': + case 'n': + case 'F': + case 'f': + case NUL: + res = false; + break; + case '#': + if (pOD->optArg.argString[1] != 'f') + break; + res = false; + } + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + pOD->optArg.argBool = res; +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/boolean.c */ diff --git a/autoopts/bootstrap.dir b/autoopts/bootstrap.dir new file mode 100644 index 0000000..d86a9aa --- /dev/null +++ b/autoopts/bootstrap.dir @@ -0,0 +1,232 @@ +#! /bin/echo This_file_must_be_sourced,_not_executed +# Time-stamp: "2012-04-14 14:12:20 bkorb" +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +burn_aover() { + agvars=$(egrep '^A[GO]_' ../VERSION) + eval "${agvars}" + vers_curr=$(expr '(' $AO_CURRENT '*' 4096 ')' + $AO_REVISION) + + cd tpl + for f in *.sh *.pl + do g=${f%.sh} ; g=${g%.pl} + cat $f > $g + chmod +x $g + done + cd - +} + +add_files_to_mf() { + # Regenerate the "genshell.h" 'cuz we just altered the template to + # contain the header version number. + # + ${AGexe} -Tagman3.tpl funcs.def || \ + die "FAILED: ${AGexe} -Tagman3.tpl funcs.def" + + local tmpl=$( + ndst="" + sfil='' + + for f in man mdoc texi + do + for g in man mdoc texi + do + sfil=${sfil}tpl/${f}2${g}${nl} + test -f tpl/${f}2${g}.sh || \ + ndst=${ndst}tpl/${f}2${g}${nl} + done + done + + pdta="autoopts.m4${nl}tpl/usage.tlib${nl}" + edta="bootstrap.dir${nl}autoopts-config.in${nl}autogen.map${nl}" + edta="${edta}mk-tpl-config.sh${nl}mk-autoopts-pc.in${nl}" + edta="${edta}install-hook.sh${nl}po${nl}tpl/usage-txt.tpl${nl}" + + for f in tpl/*.* + do + case $f in + ( *.in | *.pl | *.sh ) + g=$(echo $f | sed 's/\...$//;s/-tlib$/.tlib/') + ndst=${ndst}${g}${nl} # installed file + edta=${edta}${f}${nl} # distributed file + ;; + + ( *tpl-config.tlib | *tpl/usage* ) : ;; + + ( *.tlib | *.tpl | *.def | *.lic ) + pdta=${pdta}${f}${nl} ;; # installed & distributed file + esac + done + + echo "local ndst='${ndst%${nl}}'" + echo "local pdta='${pdta%${nl}}'" + echo "local edta='${edta%${nl}}'" + echo "local sfil='${sfil%${nl}}'" + ) + + eval "$tmpl" + + { + ls -1 *.3 | \ + sed '/^pathfind.3$/d' | \ + columns -I4 --spread=1 --line=' \' + + printf '\nnodist_pkgdata_DATA = $(libsrc) \\\n' + echo "${ndst}" | sort -u | columns -I4 --spread=1 --line=' \' + + printf '\npkgdata_DATA = \\\n' + echo "${pdta}" | sort -u | columns -I4 --spread=1 --line=' \' + + printf '\nEXTRA_DATA = $(pkgdata_DATA) \\\n' + echo "${edta}" | sort -u | columns -I4 --spread=1 --line=' \' + + printf '\nGENSCRIPTS = $(srcdir)/funcs.def \\\n' + echo "${sfil}" | columns -I4 --spread=1 --line=' \' + echo + + sed -n '/^## begin/,/^## end/{ + s/^##.*// + /^$/d + p + }' gnulib.mk + + } > Makefile.lists + + sed '/^GENMAN /r Makefile.lists' Makefile.am > Makefile.tmp + mv -f Makefile.tmp Makefile.am + + rm -f Makefile.lists gnulib.mk *.3 +} + +make_funcs_def() +{ + $noag && exit 1 + s2enum=`which mk-str2enum` 2>/dev/null || : + test -x "${s2enum}" || \ + s2enum="bash ${top_srcdir}/add-on/char-mapper/mk-str2enum.sh" + + ${char_mapper:-char-mapper} autogen.map || die "FAILED: char-mapper" + ${AGexe} ao-strs.def || die "cannot make strings - exited $?" + + ${s2enum} --base-name=xat-attribute -n \ + type words members cooked uncooked keep || \ + die "FAILED: ${s2enum} --base-name=xat-attribute" + + ${s2enum} --base-name=value-type --prefix=vtp -n string integer \ + boolean bool keyword set set-membership nested hierarchy || \ + die "FAILED: ${s2enum} --base-name=value-type" + burn_aover + + test -d autoopts || mkdir autoopts + test -d po || mkdir po + ${AGexe} genshell.def || \ + die "FAILED: ${AGexe} genshell.def" + ${AGexe} usage-txt.def || \ + die "FAILED: ${AGexe} usage-txt.def" + mv usage-txt.h autoopts/. + mv usage-txt.pot po/. + + files=$(sed -n '/^CSRC/,/\.c$/p' Makefile.am | \ + sed '/^CSRC/d;s/[=\\]//' + echo ../compat/pathfind.c) + getdefs linenum srcfile template=options_h output=funcs.def $files + chmod u+w funcs.def + vers_min=$( expr '(' $AO_CURRENT - $AO_AGE ')' '*' 4096) + cat >> funcs.def <<- _END_VERS_INFO_ + vers-curr = "${vers_curr}"; + vers-min = "${vers_min}"; + vers-min-str = "$(expr $AO_CURRENT - $AO_AGE):0:0"; + vers-sovers = "${AO_SOVERS}"; + library = opts; + + /* + * THIS FILE IS DISTRIBUTED + * + * This file is used to construct options.h + doc files. Because it is + * such a nuisance to get the build ordering correct, we distribute + * this. It should be constructed after all binaries are built. + */ + _END_VERS_INFO_ + ${AGexe} funcs.def || die "FAILED: ${AGexe} funcs.def" + test -f options.h || die "options.h not created" + mv options.h autoopts/. + cp project.h autoopts/. + add_files_to_mf + make_proto + + ${AGexe} aoconf.def || die "FAILED: ${AGexe} aoconf.def" +} + +test "X${mainpid}" = X && { + \cd ${top_srcdir-..} + top_srcdir=`pwd` + . config/bootstrap.shlib + cd autoopts + free_trap=true +} || { + free_trap=false +} + +export AGexe=${AGexe-autogen}\ -L${top_srcdir}/autoopts/tpl +noag=`${AGexe} -v > /dev/null 2>&1 && echo false || echo true` +nl=$'\n' + +case "$1" in +*genshell.c ) + if ${noag} + then + test -f ${top_srcdir}/autoopts/genshell.c || \ + die "No autogen for building genshell.c" + else + ${AGexe} genshell.def || \ + die "FAILED: ${AGexe} genshell.def" + fi + ;; + +*libopts.texi ) + if ${noag} + then + test -f ${top_srcdir}/autoopts/libopts.texi || \ + die "No autogen for building libopts.texi" + else + agopts='-Taginfo3.tpl -DLEVEL=subsection -blibopts funcs.def' + ${AGexe} ${agopts} || \ + die "FAILED: ${AGexe} ${agopts}" + fi + ;; + +aoconf ) + make_funcs_def + ;; +esac + +${free_trap} && trap '' 0 +true + +# Local Variables: +# mode:shell-script +# sh-indentation:4 +# sh-basic-offset:4 +# indent-tabs-mode: nil +# End: + +# bootstrap.dir ends here diff --git a/autoopts/check.c b/autoopts/check.c new file mode 100644 index 0000000..019a235 --- /dev/null +++ b/autoopts/check.c @@ -0,0 +1,166 @@ +/** + * @file check.c + * + * @brief consistency checks. + * + * Time-stamp: "2012-03-31 13:46:35 bkorb" + * + * This file contains the routines that deal with processing quoted strings + * into an internal format. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/** + * Check for conflicts based on "must" and "cannot" attributes. + */ +static bool +has_conflict(tOptions * pOpts, tOptDesc * pOD) +{ + if (pOD->pOptMust != NULL) { + int const * pMust = pOD->pOptMust; + + while (*pMust != NO_EQUIVALENT) { + tOptDesc * p = pOpts->pOptDesc + *(pMust++); + if (UNUSED_OPT(p)) { + const tOptDesc * pN = pOpts->pOptDesc + pMust[-1]; + fprintf(stderr, zReqFmt, pOD->pz_Name, pN->pz_Name); + return true; + } + } + } + + if (pOD->pOptCant != NULL) { + int const * pCant = pOD->pOptCant; + + while (*pCant != NO_EQUIVALENT) { + tOptDesc * p = pOpts->pOptDesc + *(pCant++); + if (SELECTED_OPT(p)) { + const tOptDesc* pN = pOpts->pOptDesc + pCant[-1]; + fprintf(stderr, zCantFmt, pOD->pz_Name, pN->pz_Name); + return true; + } + } + } + + return false; +} + +/** + * Check that the option occurs often enough. Too often is already checked. + */ +static bool +occurs_enough(tOptions * pOpts, tOptDesc * pOD) +{ + (void)pOpts; + + /* + * IF the occurrence counts have been satisfied, + * THEN there is no problem. + */ + if (pOD->optOccCt >= pOD->optMinCt) + return true; + + /* + * IF MUST_SET means SET and PRESET are okay, + * so min occurrence count doesn't count + */ + if ( (pOD->fOptState & OPTST_MUST_SET) + && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) ) + return true; + + if (pOD->optMinCt > 1) + fprintf(stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt); + else fprintf(stderr, zNeedOne, pOD->pz_Name); + return false; +} + +/** + * Verify option consistency. + * + * Make sure that the argument list passes our consistency tests. + */ +LOCAL bool +is_consistent(tOptions * pOpts) +{ + tOptDesc * pOD = pOpts->pOptDesc; + int oCt = pOpts->presetOptCt; + + /* + * FOR each of "oCt" options, ... + */ + for (;;) { + /* + * IF the current option was provided on the command line + * THEN ensure that any "MUST" requirements are not + * "DEFAULT" (unspecified) *AND* ensure that any + * "CANT" options have not been SET or DEFINED. + */ + if (SELECTED_OPT(pOD)) { + if (has_conflict(pOpts, pOD)) + return false; + } + + /* + * IF this option is not equivalenced to another, + * OR it is equivalenced to itself (is the equiv. root) + * THEN we need to make sure it occurs often enough. + */ + if ( (pOD->optEquivIndex == NO_EQUIVALENT) + || (pOD->optEquivIndex == pOD->optIndex) ) + + if (! occurs_enough(pOpts, pOD)) + return false; + + if (--oCt <= 0) + break; + pOD++; + } + + /* + * IF we are stopping on errors, check to see if any remaining + * arguments are required to be there or prohibited from being there. + */ + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + + /* + * Check for prohibition + */ + if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) { + if (pOpts->origArgCt > pOpts->curOptIdx) { + fprintf(stderr, zNoArgs, pOpts->pzProgName); + return false; + } + } + + /* + * ELSE not prohibited, check for being required + */ + else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) { + if (pOpts->origArgCt <= pOpts->curOptIdx) { + fprintf(stderr, zArgsMust, pOpts->pzProgName); + return false; + } + } + } + + return true; +} diff --git a/autoopts/configFileLoad.3 b/autoopts/configFileLoad.3 new file mode 100644 index 0000000..83c3d7e --- /dev/null +++ b/autoopts/configFileLoad.3 @@ -0,0 +1,50 @@ +.TH configFileLoad 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (configFileLoad.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +configFileLoad - parse a configuration file +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +const tOptionValue* \fBconfigFileLoad\fP(char const* \fIpzFile\fP); +.sp 1 +.SH DESCRIPTION +This routine will load a named configuration file and parse the +text as a hierarchically valued option. The option descriptor +created from an option definition file is not used via this interface. +The returned value is "named" with the input file name and is of +type "\fBOPARG_TYPE_HIERARCHY\fP". It may be used in calls to +\fBoptionGetValue()\fP, \fBoptionNextValue()\fP and +\fBoptionUnloadNested()\fP. +.TP +.IR pzFile +the file to load +.sp 1 +.SH RETURN VALUE +An allocated, compound value structure +.sp 1 +.SH ERRORS +If the file cannot be loaded or processed, \fBNULL\fP is returned and +\fBerrno\fP is set. It may be set by a call to either \fBopen(2)\fP +\fBmmap(2)\fP or other file system calls, or it may be: +.sp 1ize @bullet +.sp 1 +\fBENOENT\fP \- the file was not found. +.sp 1 +\fBENOMSG\fP \- the file was empty. +.sp 1 +\fBEINVAL\fP \- the file contents are invalid \-- not properly formed. +.sp 1 +\fBENOMEM\fP \- not enough memory to allocate the needed structures. +@end itemize +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/configfile.c b/autoopts/configfile.c new file mode 100644 index 0000000..3f98e31 --- /dev/null +++ b/autoopts/configfile.c @@ -0,0 +1,1433 @@ +/** + * \file configfile.c + * + * Time-stamp: "2012-08-11 08:34:55 bkorb" + * + * configuration/rc/ini file handling. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static void +file_preset(tOptions * opts, char const * fname, int dir); + +static char* +handle_comment(char* pzText); + +static char * +handle_cfg(tOptions * pOpts, tOptState * pOS, char * pzText, int dir); + +static char * +handle_directive(tOptions * pOpts, char * pzText); + +static char * +aoflags_directive(tOptions * pOpts, char * pzText); + +static char * +program_directive(tOptions * pOpts, char * pzText); + +static char * +handle_section(tOptions * pOpts, char * pzText); + +static int +parse_xml_encoding(char ** ppz); + +static char * +trim_xml_text(char * intxt, char const * pznm, tOptionLoadMode mode); + +static void +cook_xml_text(char * pzData); + +static char * +handle_struct(tOptions * pOpts, tOptState * pOS, char * pzText, int dir); + +static char* +parse_keyword(tOptions * pOpts, char * pzText, tOptionValue * pType); + +static char* +parse_set_mem(tOptions * pOpts, char * pzText, tOptionValue * pType); + +static char * +parse_value(char * pzText, tOptionValue * pType); + +static char * +skip_unkn(char* pzText); +/* = = = END-STATIC-FORWARD = = = */ + + +/*=export_func configFileLoad + * + * what: parse a configuration file + * arg: + char const* + pzFile + the file to load + + * + * ret_type: const tOptionValue* + * ret_desc: An allocated, compound value structure + * + * doc: + * This routine will load a named configuration file and parse the + * text as a hierarchically valued option. The option descriptor + * created from an option definition file is not used via this interface. + * The returned value is "named" with the input file name and is of + * type "@code{OPARG_TYPE_HIERARCHY}". It may be used in calls to + * @code{optionGetValue()}, @code{optionNextValue()} and + * @code{optionUnloadNested()}. + * + * err: + * If the file cannot be loaded or processed, @code{NULL} is returned and + * @var{errno} is set. It may be set by a call to either @code{open(2)} + * @code{mmap(2)} or other file system calls, or it may be: + * @itemize @bullet + * @item + * @code{ENOENT} - the file was not found. + * @item + * @code{ENOMSG} - the file was empty. + * @item + * @code{EINVAL} - the file contents are invalid -- not properly formed. + * @item + * @code{ENOMEM} - not enough memory to allocate the needed structures. + * @end itemize +=*/ +const tOptionValue* +configFileLoad(char const* pzFile) +{ + tmap_info_t cfgfile; + tOptionValue* pRes = NULL; + tOptionLoadMode save_mode = option_load_mode; + + char* pzText = + text_mmap(pzFile, PROT_READ, MAP_PRIVATE, &cfgfile); + + if (TEXT_MMAP_FAILED_ADDR(pzText)) + return NULL; /* errno is set */ + + option_load_mode = OPTION_LOAD_COOKED; + pRes = optionLoadNested(pzText, pzFile, strlen(pzFile)); + + if (pRes == NULL) { + int err = errno; + text_munmap(&cfgfile); + errno = err; + } else + text_munmap(&cfgfile); + + option_load_mode = save_mode; + return pRes; +} + + +/*=export_func optionFindValue + * + * what: find a hierarcicaly valued option instance + * arg: + const tOptDesc* + pOptDesc + an option with a nested arg type + + * arg: + char const* + name + name of value to find + + * arg: + char const* + value + the matching value + + * + * ret_type: const tOptionValue* + * ret_desc: a compound value structure + * + * doc: + * This routine will find an entry in a nested value option or configurable. + * It will search through the list and return a matching entry. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +const tOptionValue* +optionFindValue(const tOptDesc* pOptDesc, char const* pzName, + char const* pzVal) +{ + const tOptionValue* pRes = NULL; + + if ( (pOptDesc == NULL) + || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + } + + else if (pOptDesc->optCookie == NULL) { + errno = ENOENT; + } + + else do { + tArgList* pAL = pOptDesc->optCookie; + int ct = pAL->useCt; + void** ppOV = (void**)(pAL->apzArgs); + + if (ct == 0) { + errno = ENOENT; + break; + } + + if (pzName == NULL) { + pRes = (tOptionValue*)*ppOV; + break; + } + + while (--ct >= 0) { + const tOptionValue* pOV = *(ppOV++); + const tOptionValue* pRV = optionGetValue(pOV, pzName); + + if (pRV == NULL) + continue; + + if (pzVal == NULL) { + pRes = pOV; + break; + } + } + if (pRes == NULL) + errno = ENOENT; + } while (false); + + return pRes; +} + + +/*=export_func optionFindNextValue + * + * FIXME: the handling of 'pzName' and 'pzVal' is just wrong. + * + * what: find a hierarcicaly valued option instance + * arg: + const tOptDesc* + pOptDesc + an option with a nested arg type + + * arg: + const tOptionValue* + pPrevVal + the last entry + + * arg: + char const* + name + name of value to find + + * arg: + char const* + value + the matching value + + * + * ret_type: const tOptionValue* + * ret_desc: a compound value structure + * + * doc: + * This routine will find the next entry in a nested value option or + * configurable. It will search through the list and return the next entry + * that matches the criteria. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +tOptionValue const * +optionFindNextValue(const tOptDesc * pOptDesc, const tOptionValue * pPrevVal, + char const * pzName, char const * pzVal) +{ + bool old_found = false; + tOptionValue* pRes = NULL; + + (void)pzName; + (void)pzVal; + + if ( (pOptDesc == NULL) + || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + } + + else if (pOptDesc->optCookie == NULL) { + errno = ENOENT; + } + + else do { + tArgList* pAL = pOptDesc->optCookie; + int ct = pAL->useCt; + void** ppOV = (void**)pAL->apzArgs; + + while (--ct >= 0) { + tOptionValue* pOV = *(ppOV++); + if (old_found) { + pRes = pOV; + break; + } + if (pOV == pPrevVal) + old_found = true; + } + if (pRes == NULL) + errno = ENOENT; + } while (false); + + return pRes; +} + + +/*=export_func optionGetValue + * + * what: get a specific value from a hierarcical list + * arg: + const tOptionValue* + pOptValue + a hierarchcal value + + * arg: + char const* + valueName + name of value to get + + * + * ret_type: const tOptionValue* + * ret_desc: a compound value structure + * + * doc: + * This routine will find an entry in a nested value option or configurable. + * If "valueName" is NULL, then the first entry is returned. Otherwise, + * the first entry with a name that exactly matches the argument will be + * returned. If there is no matching value, NULL is returned and errno is + * set to ENOENT. If the provided option value is not a hierarchical value, + * NULL is also returned and errno is set to EINVAL. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +const tOptionValue* +optionGetValue(tOptionValue const * pOld, char const * pzValName) +{ + tArgList * pAL; + tOptionValue * pRes = NULL; + + if ((pOld == NULL) || (pOld->valType != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + return pRes; + } + pAL = pOld->v.nestVal; + + if (pAL->useCt > 0) { + int ct = pAL->useCt; + void ** papOV = (void**)(pAL->apzArgs); + + if (pzValName == NULL) { + pRes = (tOptionValue*)*papOV; + + } else do { + tOptionValue * pOV = *(papOV++); + if (strcmp(pOV->pzName, pzValName) == 0) { + pRes = pOV; + break; + } + } while (--ct > 0); + } + if (pRes == NULL) + errno = ENOENT; + return pRes; +} + + +/*=export_func optionNextValue + * + * what: get the next value from a hierarchical list + * arg: + const tOptionValue* + pOptValue + a hierarchcal list value + + * arg: + const tOptionValue* + pOldValue + a value from this list + + * + * ret_type: const tOptionValue* + * ret_desc: a compound value structure + * + * doc: + * This routine will return the next entry after the entry passed in. At the + * end of the list, NULL will be returned. If the entry is not found on the + * list, NULL will be returned and "@var{errno}" will be set to EINVAL. + * The "@var{pOldValue}" must have been gotten from a prior call to this + * routine or to "@code{opitonGetValue()}". + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value or @code{pOldValue} does not point to a + * member of that option value. + * @item + * @code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry. + * @end itemize +=*/ +tOptionValue const * +optionNextValue(tOptionValue const * pOVList,tOptionValue const * pOldOV ) +{ + tArgList* pAL; + tOptionValue* pRes = NULL; + int err = EINVAL; + + if ((pOVList == NULL) || (pOVList->valType != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + return NULL; + } + pAL = pOVList->v.nestVal; + { + int ct = pAL->useCt; + void** papNV = (void**)(pAL->apzArgs); + + while (ct-- > 0) { + tOptionValue* pNV = *(papNV++); + if (pNV == pOldOV) { + if (ct == 0) { + err = ENOENT; + + } else { + err = 0; + pRes = (tOptionValue*)*papNV; + } + break; + } + } + } + if (err != 0) + errno = err; + return pRes; +} + + +/** + * Load a file containing presetting information (a configuration file). + */ +static void +file_preset(tOptions * opts, char const * fname, int dir) +{ + tmap_info_t cfgfile; + tOptState optst = OPTSTATE_INITIALIZER(PRESET); + unsigned long st_flags = optst.flags; + char * ftext = + text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile); + + if (TEXT_MMAP_FAILED_ADDR(ftext)) + return; + + if (dir == DIRECTION_CALLED) { + st_flags = OPTST_DEFINED; + dir = DIRECTION_PROCESS; + } + + /* + * IF this is called via "optionProcess", then we are presetting. + * This is the default and the PRESETTING bit will be set. + * If this is called via "optionFileLoad", then the bit is not set + * and we consider stuff set herein to be "set" by the client program. + */ + if ((opts->fOptSet & OPTPROC_PRESETTING) == 0) + st_flags = OPTST_SET; + + do { + optst.flags = st_flags; + ftext = SPN_WHITESPACE_CHARS(ftext); + + if (IS_VAR_FIRST_CHAR(*ftext)) { + ftext = handle_cfg(opts, &optst, ftext, dir); + + } else switch (*ftext) { + case '<': + if (IS_VAR_FIRST_CHAR(ftext[1])) + ftext = handle_struct(opts, &optst, ftext, dir); + + else switch (ftext[1]) { + case '?': + ftext = handle_directive(opts, ftext); + break; + + case '!': + ftext = handle_comment(ftext); + break; + + case '/': + ftext = strchr(ftext + 2, '>'); + if (ftext++ != NULL) + break; + + default: + goto all_done; + } + break; + + case '[': + ftext = handle_section(opts, ftext); + break; + + case '#': + ftext = strchr(ftext + 1, NL); + break; + + default: + goto all_done; /* invalid format */ + } + } while (ftext != NULL); + +all_done: + text_munmap(&cfgfile); +} + + +/** + * "pzText" points to a "<!" sequence. + * Theoretically, we should ensure that it begins with "<!--", + * but actually I don't care that much. It ends with "-->". + */ +static char* +handle_comment(char* pzText) +{ + char* pz = strstr(pzText, "-->"); + if (pz != NULL) + pz += 3; + return pz; +} + + +/** + * "pzText" points to the start of some value name. + * The end of the entry is the end of the line that is not preceded by + * a backslash escape character. The string value is always processed + * in "cooked" mode. + */ +static char * +handle_cfg(tOptions * pOpts, tOptState * pOS, char * pzText, int dir) +{ + char* pzName = pzText++; + char* pzEnd = strchr(pzText, NL); + + if (pzEnd == NULL) + return pzText + strlen(pzText); + + pzText = SPN_VALUE_NAME_CHARS(pzText); + pzText = SPN_WHITESPACE_CHARS(pzText); + if (pzText > pzEnd) { + name_only: + *pzEnd++ = NUL; + loadOptionLine(pOpts, pOS, pzName, dir, OPTION_LOAD_UNCOOKED); + return pzEnd; + } + + /* + * Either the first character after the name is a ':' or '=', + * or else we must have skipped over white space. Anything else + * is an invalid format and we give up parsing the text. + */ + if ((*pzText == '=') || (*pzText == ':')) { + pzText = SPN_WHITESPACE_CHARS(pzText+1); + if (pzText > pzEnd) + goto name_only; + } else if (! IS_WHITESPACE_CHAR(pzText[-1])) + return NULL; + + /* + * IF the value is continued, remove the backslash escape and push "pzEnd" + * on to a newline *not* preceded by a backslash. + */ + if (pzEnd[-1] == '\\') { + char* pcD = pzEnd-1; + char* pcS = pzEnd; + + for (;;) { + char ch = *(pcS++); + switch (ch) { + case NUL: + pcS = NULL; + /* FALLTHROUGH */ + + case NL: + *pcD = NUL; + pzEnd = pcS; + goto copy_done; + + case '\\': + if (*pcS == NL) + ch = *(pcS++); + /* FALLTHROUGH */ + default: + *(pcD++) = ch; + } + } copy_done:; + + } else { + /* + * The newline was not preceded by a backslash. NUL it out + */ + *(pzEnd++) = NUL; + } + + /* + * "pzName" points to what looks like text for one option/configurable. + * It is NUL terminated. Process it. + */ + loadOptionLine(pOpts, pOS, pzName, dir, OPTION_LOAD_UNCOOKED); + + return pzEnd; +} + + +/** + * "pzText" points to a "<?" sequence. + * We handle "<?program" and "<?auto-options" directives. + * All others are treated as comments. + */ +static char * +handle_directive(tOptions * pOpts, char * pzText) +{ +# define DIRECTIVE_TABLE \ + _dt_(zCfgProg, program_directive) \ + _dt_(zCfgAO_Flags, aoflags_directive) + + typedef char * (directive_func_t)(tOptions *, char *); +# define _dt_(_s, _fn) _fn, + static directive_func_t * dir_disp[] = { + DIRECTIVE_TABLE + }; +# undef _dt_ + +# define _dt_(_s, _fn) 1 + + static int const dir_ct = DIRECTIVE_TABLE 0; + static char const * dir_names[DIRECTIVE_TABLE 0]; +# undef _dt_ + + int ix; + + if (dir_names[0] == NULL) { + ix = 0; +# define _dt_(_s, _fn) dir_names[ix++] = _s; + DIRECTIVE_TABLE; +# undef _dt_ + } + + for (ix = 0; ix < dir_ct; ix++) { + size_t len = strlen(dir_names[ix]); + if ( (strncmp(pzText + 2, dir_names[ix], len) == 0) + && (! IS_VALUE_NAME_CHAR(pzText[len+2])) ) + return dir_disp[ix](pOpts, pzText + len + 2); + } + + /* + * We don't know what this is. Skip it. + */ + pzText = strchr(pzText+2, '>'); + if (pzText != NULL) + pzText++; + return pzText; +} + +/** + * handle AutoOpts mode flags + */ +static char * +aoflags_directive(tOptions * pOpts, char * pzText) +{ + char * pz; + + pz = SPN_WHITESPACE_CHARS(pzText+1); + pzText = strchr(pz, '>'); + if (pzText != NULL) { + + size_t len = pzText - pz; + char * ftxt = AGALOC(len + 1, "aoflags"); + + memcpy(ftxt, pz, len); + ftxt[len] = NUL; + set_usage_flags(pOpts, ftxt); + AGFREE(ftxt); + + pzText++; + } + + return pzText; +} + +/** + * handle program segmentation of config file. + */ +static char * +program_directive(tOptions * pOpts, char * pzText) +{ + static char const ttlfmt[] = "<?"; + size_t ttl_len = sizeof(ttlfmt) + strlen(zCfgProg); + char * ttl = AGALOC(ttl_len, "prog title"); + size_t name_len = strlen(pOpts->pzProgName); + + memcpy(ttl, ttlfmt, sizeof(ttlfmt) - 1); + memcpy(ttl + sizeof(ttlfmt) - 1, zCfgProg, ttl_len - (sizeof(ttlfmt) - 1)); + + do { + pzText = SPN_WHITESPACE_CHARS(pzText+1); + + if ( (strneqvcmp(pzText, pOpts->pzProgName, (int)name_len) == 0) + && (IS_END_XML_TOKEN_CHAR(pzText[name_len])) ) { + pzText += name_len; + break; + } + + pzText = strstr(pzText, ttl); + } while (pzText != NULL); + + AGFREE(ttl); + if (pzText != NULL) + for (;;) { + if (*pzText == NUL) { + pzText = NULL; + break; + } + if (*(pzText++) == '>') + break; + } + + return pzText; +} + + +/** + * "pzText" points to a '[' character. + * The "traditional" [PROG_NAME] segmentation of the config file. + * Do not ever mix with the "<?program prog-name>" variation. + */ +static char * +handle_section(tOptions * pOpts, char * pzText) +{ + size_t len = strlen(pOpts->pzPROGNAME); + if ( (strncmp(pzText+1, pOpts->pzPROGNAME, len) == 0) + && (pzText[len+1] == ']')) + return strchr(pzText + len + 2, NL); + + if (len > 16) + return NULL; + + { + char z[24]; + sprintf(z, "[%s]", pOpts->pzPROGNAME); + pzText = strstr(pzText, z); + } + + if (pzText != NULL) + pzText = strchr(pzText, NL); + return pzText; +} + +/** + * parse XML encodings + */ +static int +parse_xml_encoding(char ** ppz) +{ +# define XMLTABLE \ + _xmlNm_(amp, '&') \ + _xmlNm_(lt, '<') \ + _xmlNm_(gt, '>') \ + _xmlNm_(ff, '\f') \ + _xmlNm_(ht, '\t') \ + _xmlNm_(cr, '\r') \ + _xmlNm_(vt, '\v') \ + _xmlNm_(bel, '\a') \ + _xmlNm_(nl, NL) \ + _xmlNm_(space, ' ') \ + _xmlNm_(quot, '"') \ + _xmlNm_(apos, '\'') + + static struct { + char const * const nm_str; + unsigned short nm_len; + short nm_val; + } const xml_names[] = { +# define _xmlNm_(_n, _v) { #_n ";", sizeof(#_n), _v }, + XMLTABLE +# undef _xmlNm_ +# undef XMLTABLE + }; + + static int const nm_ct = sizeof(xml_names) / sizeof(xml_names[0]); + int base = 10; + + char * pz = *ppz; + + if (*pz == '#') { + pz++; + goto parse_number; + } + + if (IS_DEC_DIGIT_CHAR(*pz)) { + unsigned long v; + + parse_number: + switch (*pz) { + case 'x': case 'X': + /* + * Some forms specify hex with: &#xNN; + */ + base = 16; + pz++; + break; + + case '0': + /* + *  is hex and  is decimal. Cool. + * Ya gotta love it. + */ + if (pz[1] == '0') + base = 16; + break; + } + + v = strtoul(pz, &pz, base); + if ((*pz != ';') || (v > 0x7F)) + return NUL; + *ppz = pz + 1; + return (int)v; + } + + { + int ix = 0; + do { + if (strncmp(pz, xml_names[ix].nm_str, xml_names[ix].nm_len) + == 0) { + *ppz = pz + xml_names[ix].nm_len; + return xml_names[ix].nm_val; + } + } while (++ix < nm_ct); + } + + return NUL; +} + +/** + * Find the end marker for the named section of XML. + * Trim that text there, trimming trailing white space for all modes + * except for OPTION_LOAD_UNCOOKED. + */ +static char * +trim_xml_text(char * intxt, char const * pznm, tOptionLoadMode mode) +{ + static char const fmt[] = "</%s>"; + size_t len = strlen(pznm) + sizeof(fmt) - 2 /* for %s */; + char * etext; + + { + char z[64], *pz = z; + if (len >= sizeof(z)) + pz = AGALOC(len, "scan name"); + + len = sprintf(pz, fmt, pznm); + *intxt = ' '; + etext = strstr(intxt, pz); + if (pz != z) AGFREE(pz); + } + + if (etext == NULL) + return etext; + + { + char * result = etext + len; + + if (mode != OPTION_LOAD_UNCOOKED) + etext = SPN_WHITESPACE_BACK(intxt, etext); + + *etext = NUL; + return result; + } +} + +/** + */ +static void +cook_xml_text(char * pzData) +{ + char * pzs = pzData; + char * pzd = pzData; + char bf[4]; + bf[2] = NUL; + + for (;;) { + int ch = ((int)*(pzs++)) & 0xFF; + switch (ch) { + case NUL: + *pzd = NUL; + return; + + case '&': + ch = parse_xml_encoding(&pzs); + *(pzd++) = (char)ch; + if (ch == NUL) + return; + break; + + case '%': + bf[0] = *(pzs++); + bf[1] = *(pzs++); + if ((bf[0] == NUL) || (bf[1] == NUL)) { + *pzd = NUL; + return; + } + + ch = strtoul(bf, NULL, 16); + /* FALLTHROUGH */ + + default: + *(pzd++) = (char)ch; + } + } +} + +/** + * "pzText" points to a '<' character, followed by an alpha. + * The end of the entry is either the "/>" following the name, or else a + * "</name>" string. + */ +static char * +handle_struct(tOptions * pOpts, tOptState * pOS, char * pzText, int dir) +{ + tOptionLoadMode mode = option_load_mode; + tOptionValue valu; + + char* pzName = ++pzText; + char* pzData; + char* pcNulPoint; + + pzText = SPN_VALUE_NAME_CHARS(pzText); + pcNulPoint = pzText; + valu.valType = OPARG_TYPE_STRING; + + switch (*pzText) { + case ' ': + case '\t': + pzText = parse_attrs(pOpts, pzText, &mode, &valu); + if (*pzText == '>') + break; + if (*pzText != '/') + return NULL; + /* FALLTHROUGH */ + + case '/': + if (pzText[1] != '>') + return NULL; + *pzText = NUL; + pzText += 2; + loadOptionLine(pOpts, pOS, pzName, dir, mode); + return pzText; + + case '>': + break; + + default: + pzText = strchr(pzText, '>'); + if (pzText != NULL) + pzText++; + return pzText; + } + + /* + * If we are here, we have a value. "pzText" points to a closing angle + * bracket. Separate the name from the value for a moment. + */ + *pcNulPoint = NUL; + pzData = ++pzText; + pzText = trim_xml_text(pzText, pzName, mode); + if (pzText == NULL) + return pzText; + + /* + * Rejoin the name and value for parsing by "loadOptionLine()". + * Erase any attributes parsed by "parse_attrs()". + */ + memset(pcNulPoint, ' ', pzData - pcNulPoint); + + /* + * If we are getting a "string" value that is to be cooked, + * then process the XML-ish &xx; XML-ish and %XX hex characters. + */ + if ( (valu.valType == OPARG_TYPE_STRING) + && (mode == OPTION_LOAD_COOKED)) + cook_xml_text(pzData); + + /* + * "pzName" points to what looks like text for one option/configurable. + * It is NUL terminated. Process it. + */ + loadOptionLine(pOpts, pOS, pzName, dir, mode); + + return pzText; +} + + +/** + * Load a configuration file. This may be invoked either from + * scanning the "homerc" list, or from a specific file request. + * (see "optionFileLoad()", the implementation for --load-opts) + */ +LOCAL void +intern_file_load(tOptions* pOpts) +{ + uint32_t svfl; + int idx; + int inc; + char zFileName[ AG_PATH_MAX+1 ]; + + if (pOpts->papzHomeList == NULL) + return; + + svfl = pOpts->fOptSet; + inc = DIRECTION_PRESET; + + /* + * Never stop on errors in config files. + */ + pOpts->fOptSet &= ~OPTPROC_ERRSTOP; + + /* + * Find the last RC entry (highest priority entry) + */ + for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx) ; + + /* + * For every path in the home list, ... *TWICE* We start at the last + * (highest priority) entry, work our way down to the lowest priority, + * handling the immediate options. + * Then we go back up, doing the normal options. + */ + for (;;) { + struct stat StatBuf; + cch_t* pzPath; + + /* + * IF we've reached the bottom end, change direction + */ + if (idx < 0) { + inc = DIRECTION_PROCESS; + idx = 0; + } + + pzPath = pOpts->papzHomeList[ idx ]; + + /* + * IF we've reached the top end, bail out + */ + if (pzPath == NULL) + break; + + idx += inc; + + if (! optionMakePath(zFileName, (int)sizeof(zFileName), + pzPath, pOpts->pzProgPath)) + continue; + + /* + * IF the file name we constructed is a directory, + * THEN append the Resource Configuration file name + * ELSE we must have the complete file name + */ + if (stat(zFileName, &StatBuf) != 0) + continue; /* bogus name - skip the home list entry */ + + if (S_ISDIR(StatBuf.st_mode)) { + size_t len = strlen(zFileName); + size_t nln = strlen(pOpts->pzRcName) + 1; + char * pz = zFileName + len; + + if (len + 1 + nln >= sizeof(zFileName)) + continue; + + if (pz[-1] != DIRCH) + *(pz++) = DIRCH; + memcpy(pz, pOpts->pzRcName, nln); + } + + file_preset(pOpts, zFileName, inc); + + /* + * IF we are now to skip config files AND we are presetting, + * THEN change direction. We must go the other way. + */ + { + tOptDesc * pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts+1; + if (DISABLED_OPT(pOD) && PRESETTING(inc)) { + idx -= inc; /* go back and reprocess current file */ + inc = DIRECTION_PROCESS; + } + } + } /* twice for every path in the home list, ... */ + + pOpts->fOptSet = svfl; +} + + +/*=export_func optionFileLoad + * + * what: Load the locatable config files, in order + * + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + char const* + pzProg + program name + + * + * ret_type: int + * ret_desc: 0 -> SUCCESS, -1 -> FAILURE + * + * doc: + * + * This function looks in all the specified directories for a configuration + * file ("rc" file or "ini" file) and processes any found twice. The first + * time through, they are processed in reverse order (last file first). At + * that time, only "immediate action" configurables are processed. For + * example, if the last named file specifies not processing any more + * configuration files, then no more configuration files will be processed. + * Such an option in the @strong{first} named directory will have no effect. + * + * Once the immediate action configurables have been handled, then the + * directories are handled in normal, forward order. In that way, later + * config files can override the settings of earlier config files. + * + * See the AutoOpts documentation for a thorough discussion of the + * config file format. + * + * Configuration files not found or not decipherable are simply ignored. + * + * err: Returns the value, "-1" if the program options descriptor + * is out of date or indecipherable. Otherwise, the value "0" will + * always be returned. +=*/ +int +optionFileLoad(tOptions * pOpts, char const * pzProgram) +{ + if (! SUCCESSFUL(validate_struct(pOpts, pzProgram))) + return -1; + + { + char const ** pp = + (char const **)(void *)&(pOpts->pzProgName); + *pp = pzProgram; + } + + intern_file_load(pOpts); + return 0; +} + + +/*=export_func optionLoadOpt + * private: + * + * what: Load an option rc/ini file + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Processes the options found in the file named with + * pOptDesc->optArg.argString. +=*/ +void +optionLoadOpt(tOptions * pOpts, tOptDesc * pOptDesc) +{ + struct stat sb; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + /* + * IF the option is not being disabled, THEN load the file. There must + * be a file. (If it is being disabled, then the disablement processing + * already took place. It must be done to suppress preloading of ini/rc + * files.) + */ + if ( DISABLED_OPT(pOptDesc) + || ((pOptDesc->fOptState & OPTST_RESET) != 0)) + return; + + if (stat(pOptDesc->optArg.argString, &sb) != 0) { + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0) + return; + + fprintf(stderr, zFSErrOptLoad, errno, strerror(errno), + pOptDesc->optArg.argString); + exit(EX_NOINPUT); + /* NOT REACHED */ + } + + if (! S_ISREG(sb.st_mode)) { + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0) + return; + + fprintf(stderr, zNotFile, pOptDesc->optArg.argString); + exit(EX_NOINPUT); + /* NOT REACHED */ + } + + file_preset(pOpts, pOptDesc->optArg.argString, DIRECTION_CALLED); +} + + +/** + * Parse the various attributes of an XML-styled config file entry + */ +LOCAL char* +parse_attrs(tOptions * pOpts, char * pzText, tOptionLoadMode * pMode, + tOptionValue * pType) +{ + size_t len; + + do { + if (! IS_WHITESPACE_CHAR(*pzText)) + switch (*pzText) { + case '/': pType->valType = OPARG_TYPE_NONE; + /* FALLTHROUGH */ + case '>': return pzText; + + default: + case NUL: return NULL; + } + + pzText = SPN_WHITESPACE_CHARS(pzText+1); + len = SPN_LOWER_CASE_CHARS(pzText) - pzText; + + switch (find_xat_attribute_id(pzText, len)) { + case XAT_KWD_TYPE: + pzText = parse_value(pzText+len, pType); + break; + + case XAT_KWD_WORDS: + pzText = parse_keyword(pOpts, pzText+len, pType); + break; + + case XAT_KWD_MEMBERS: + pzText = parse_set_mem(pOpts, pzText+len, pType); + break; + + case XAT_KWD_COOKED: + pzText += len; + if (! IS_END_XML_TOKEN_CHAR(*pzText)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_COOKED; + break; + + case XAT_KWD_UNCOOKED: + pzText += len; + if (! IS_END_XML_TOKEN_CHAR(*pzText)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_UNCOOKED; + break; + + case XAT_KWD_KEEP: + pzText += len; + if (! IS_END_XML_TOKEN_CHAR(*pzText)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_KEEP; + break; + + default: + case XAT_KWD_INVALID: + invalid_kwd: + pType->valType = OPARG_TYPE_NONE; + return skip_unkn(pzText); + } + } while (pzText != NULL); + + return pzText; +} + + +/** + * "pzText" points to the character after "words=". + * What should follow is a name of a keyword (enumeration) list. + */ +static char* +parse_keyword(tOptions * pOpts, char * pzText, tOptionValue * pType) +{ + (void)pOpts; + (void)pType; + + return skip_unkn(pzText); +} + + +/** + * "pzText" points to the character after "members=" + * What should follow is a name of a "set membership". + * A collection of bit flags. + */ +static char* +parse_set_mem(tOptions * pOpts, char * pzText, tOptionValue * pType) +{ + (void)pOpts; + (void)pType; + + return skip_unkn(pzText); +} + + +/** + * "pzText" points to the character after "type=" + */ +static char * +parse_value(char * pzText, tOptionValue * pType) +{ + size_t len = 0; + + if (*(pzText++) != '=') + goto woops; + + len = SPN_OPTION_NAME_CHARS(pzText) - pzText; + + if ((len == 0) || (! IS_END_XML_TOKEN_CHAR(pzText[len]))) { + woops: + pType->valType = OPARG_TYPE_NONE; + return skip_unkn(pzText + len); + } + + switch (find_value_type_id(pzText, len)) { + default: + case VTP_KWD_INVALID: goto woops; + + case VTP_KWD_STRING: + pType->valType = OPARG_TYPE_STRING; + break; + + case VTP_KWD_INTEGER: + pType->valType = OPARG_TYPE_NUMERIC; + break; + + case VTP_KWD_BOOL: + case VTP_KWD_BOOLEAN: + pType->valType = OPARG_TYPE_BOOLEAN; + break; + + case VTP_KWD_KEYWORD: + pType->valType = OPARG_TYPE_ENUMERATION; + break; + + case VTP_KWD_SET: + case VTP_KWD_SET_MEMBERSHIP: + pType->valType = OPARG_TYPE_MEMBERSHIP; + break; + + case VTP_KWD_NESTED: + case VTP_KWD_HIERARCHY: + pType->valType = OPARG_TYPE_HIERARCHY; + } + + return pzText + len; +} + + +/** + * Skip over some unknown attribute + */ +static char * +skip_unkn(char* pzText) +{ + for (;; pzText++) { + if (IS_END_XML_TOKEN_CHAR(*pzText)) return pzText; + if (*pzText == NUL) return NULL; + } +} + + +/** + * Make sure the option descriptor is there and that we understand it. + * This should be called from any user entry point where one needs to + * worry about validity. (Some entry points are free to assume that + * the call is not the first to the library and, thus, that this has + * already been called.) + * + * Upon successful completion, pzProgName and pzProgPath are set. + * + * @param pOpts program options descriptor + * @param pzProgram name of program, from argv[] + * @returns SUCCESS or FAILURE + */ +LOCAL tSuccess +validate_struct(tOptions * pOpts, char const * pzProgram) +{ + if (pOpts == NULL) { + fputs(zAO_Bad, stderr); + return FAILURE; + } + + /* + * IF the client has enabled translation and the translation procedure + * is available, then go do it. + */ + if ( ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0) + && (pOpts->pTransProc != NULL) ) { + /* + * If option names are not to be translated at all, then do not do + * it for configuration parsing either. (That is the bit that really + * gets tested anyway.) + */ + if ((pOpts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT) + pOpts->fOptSet |= OPTPROC_NXLAT_OPT_CFG; + (*pOpts->pTransProc)(); + pOpts->fOptSet &= ~OPTPROC_TRANSLATE; + } + + /* + * IF the struct version is not the current, and also + * either too large (?!) or too small, + * THEN emit error message and fail-exit + */ + if ( ( pOpts->structVersion != OPTIONS_STRUCT_VERSION ) + && ( (pOpts->structVersion > OPTIONS_STRUCT_VERSION ) + || (pOpts->structVersion < OPTIONS_MINIMUM_VERSION ) + ) ) { + static char const aover[] = + STR(AO_CURRENT)":"STR(AO_REVISION)":"STR(AO_AGE)"\n"; + + fprintf(stderr, zAO_Err, pzProgram, NUM_TO_VER(pOpts->structVersion)); + if (pOpts->structVersion > OPTIONS_STRUCT_VERSION ) + fputs(zAO_Big, stderr); + else + fputs(zAO_Sml, stderr); + + fwrite(aover, sizeof(aover) - 1, 1, stderr); + return FAILURE; + } + + /* + * If the program name hasn't been set, then set the name and the path + * and the set of equivalent characters. + */ + if (pOpts->pzProgName == NULL) { + char const * pz = strrchr(pzProgram, DIRCH); + char const ** pp = + (char const **)(void **)&(pOpts->pzProgName); + + if (pz != NULL) { + *pp = pz+1; + } else { + *pp = pzProgram; + pz = pathfind(getenv("PATH"), (char *)pzProgram, "rx"); + if (pz != NULL) + pzProgram = (void *)pz; + } + + pp = (char const **)(void **)&(pOpts->pzProgPath); + *pp = pzProgram; + + /* + * when comparing long names, these are equivalent + */ + strequate(zSepChars); + } + + return SUCCESS; +} + + +/** + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/configfile.c */ diff --git a/autoopts/cook.c b/autoopts/cook.c new file mode 100644 index 0000000..f34a6ed --- /dev/null +++ b/autoopts/cook.c @@ -0,0 +1,311 @@ +/** + * \file cook.c + * + * Time-stamp: "2012-02-28 19:40:47 bkorb" + * + * This file contains the routines that deal with processing quoted strings + * into an internal format. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static bool +contiguous_quote(char ** pps, char * pq, int * lnct_p); +/* = = = END-STATIC-FORWARD = = = */ + +/*=export_func ao_string_cook_escape_char + * private: + * + * what: escape-process a string fragment + * arg: + char const* + pzScan + points to character after the escape + + * arg: + char* + pRes + Where to put the result byte + + * arg: + unsigned int + nl_ch + replacement char if scanned char is \n + + * + * ret-type: unsigned int + * ret-desc: The number of bytes consumed processing the escaped character. + * + * doc: + * + * This function converts "t" into "\t" and all your other favorite + * escapes, including numeric ones: hex and ocatal, too. + * The returned result tells the caller how far to advance the + * scan pointer (passed in). The default is to just pass through the + * escaped character and advance the scan by one. + * + * Some applications need to keep an escaped newline, others need to + * suppress it. This is accomplished by supplying a '\n' replacement + * character that is different from \n, if need be. For example, use + * 0x7F and never emit a 0x7F. + * + * err: @code{NULL} is returned if the string is mal-formed. +=*/ +unsigned int +ao_string_cook_escape_char(char const* pzIn, char* pRes, uint_t nl) +{ + unsigned int res = 1; + + switch (*pRes = *pzIn++) { + case NUL: /* NUL - end of input string */ + return 0; + case '\r': + if (*pzIn != NL) + return 1; + res++; + /* FALLTHROUGH */ + case NL: /* NL - emit newline */ + *pRes = (char)nl; + return res; + + case 'a': *pRes = '\a'; break; + case 'b': *pRes = '\b'; break; + case 'f': *pRes = '\f'; break; + case 'n': *pRes = NL; break; + case 'r': *pRes = '\r'; break; + case 't': *pRes = '\t'; break; + case 'v': *pRes = '\v'; break; + + case 'x': + case 'X': /* HEX Escape */ + if (IS_HEX_DIGIT_CHAR(*pzIn)) { + char z[4], *pz = z; + + do *(pz++) = *(pzIn++); + while (IS_HEX_DIGIT_CHAR(*pzIn) && (pz < z + 2)); + *pz = NUL; + *pRes = (unsigned char)strtoul(z, NULL, 16); + res += pz - z; + } + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + /* + * IF the character copied was an octal digit, + * THEN set the output character to an octal value + */ + char z[4], *pz = z + 1; + unsigned long val; + z[0] = *pRes; + + while (IS_OCT_DIGIT_CHAR(*pzIn) && (pz < z + 3)) + *(pz++) = *(pzIn++); + *pz = NUL; + val = strtoul(z, NULL, 8); + if (val > 0xFF) + val = 0xFF; + *pRes = (unsigned char)val; + res = pz - z; + break; + } + + default: ; + } + + return res; +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * A quoted string has been found. + * Find the end of it and compress any escape sequences. + */ +static bool +contiguous_quote(char ** pps, char * pq, int * lnct_p) +{ + char * ps = *pps + 1; + + for (;;) { + while (IS_WHITESPACE_CHAR(*ps)) + if (*(ps++) == NL) + (*lnct_p)++; + + /* + * IF the next character is a quote character, + * THEN we will concatenate the strings. + */ + switch (*ps) { + case '"': + case '\'': + *pq = *(ps++); /* assign new quote character and return */ + *pps = ps; + return true; + + case '/': + /* + * Allow for a comment embedded in the concatenated string. + */ + switch (ps[1]) { + default: + *pps = NULL; + return false; + + case '/': + /* + * Skip to end of line + */ + ps = strchr(ps, NL); + if (ps == NULL) { + *pps = NULL; + return false; + } + break; + + case '*': + { + char* p = strstr( ps+2, "*/" ); + /* + * Skip to terminating star slash + */ + if (p == NULL) { + *pps = NULL; + return false; + } + + while (ps < p) { + if (*(ps++) == NL) + (*lnct_p)++; + } + + ps = p + 2; + } + } + continue; + + default: + /* + * The next non-whitespace character is not a quote. + * The series of quoted strings has come to an end. + */ + *pps = ps; + return false; + } + } +} + +/*=export_func ao_string_cook + * private: + * + * what: concatenate and escape-process strings + * arg: + char* + pzScan + The *MODIFIABLE* input buffer + + * arg: + int* + lnct_p + The (possibly NULL) pointer to a line count + + * + * ret-type: char* + * ret-desc: The address of the text following the processed strings. + * The return value is NULL if the strings are ill-formed. + * + * doc: + * + * A series of one or more quoted strings are concatenated together. + * If they are quoted with double quotes (@code{"}), then backslash + * escapes are processed per the C programming language. If they are + * single quote strings, then the backslashes are honored only when they + * precede another backslash or a single quote character. + * + * err: @code{NULL} is returned if the string(s) is/are mal-formed. +=*/ +char * +ao_string_cook(char * pzScan, int * lnct_p) +{ + int l = 0; + char q = *pzScan; + + /* + * It is a quoted string. Process the escape sequence characters + * (in the set "abfnrtv") and make sure we find a closing quote. + */ + char* pzD = pzScan++; + char* pzS = pzScan; + + if (lnct_p == NULL) + lnct_p = &l; + + for (;;) { + /* + * IF the next character is the quote character, THEN we may end the + * string. We end it unless the next non-blank character *after* the + * string happens to also be a quote. If it is, then we will change + * our quote character to the new quote character and continue + * condensing text. + */ + while (*pzS == q) { + *pzD = NUL; /* This is probably the end of the line */ + if (! contiguous_quote(&pzS, &q, lnct_p)) + return pzS; + } + + /* + * We are inside a quoted string. Copy text. + */ + switch (*(pzD++) = *(pzS++)) { + case NUL: + return NULL; + + case NL: + (*lnct_p)++; + break; + + case '\\': + /* + * IF we are escaping a new line, + * THEN drop both the escape and the newline from + * the result string. + */ + if (*pzS == NL) { + pzS++; + pzD--; + (*lnct_p)++; + } + + /* + * ELSE IF the quote character is '"' or '`', + * THEN we do the full escape character processing + */ + else if (q != '\'') { + int ct = ao_string_cook_escape_char(pzS, pzD-1, (uint_t)NL); + if (ct == 0) + return NULL; + + pzS += ct; + } /* if (q != '\'') */ + + /* + * OTHERWISE, we only process "\\", "\'" and "\#" sequences. + * The latter only to easily hide preprocessing directives. + */ + else switch (*pzS) { + case '\\': + case '\'': + case '#': + pzD[-1] = *pzS++; + } + } /* switch (*(pzD++) = *(pzS++)) */ + } /* for (;;) */ +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/cook.c */ diff --git a/autoopts/enum.c b/autoopts/enum.c new file mode 100644 index 0000000..dff5df8 --- /dev/null +++ b/autoopts/enum.c @@ -0,0 +1,546 @@ + +/** + * \file enumeration.c + * + * Time-stamp: "2012-08-11 08:12:58 bkorb" + * + * Automated Options Paged Usage module. + * + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +static char const * pz_enum_err_fmt; + +/* = = = START-STATIC-FORWARD = = = */ +static void +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct); + +static uintptr_t +find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct); + +static void +set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct); + +static void +set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct); + +static void +set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct); +/* = = = END-STATIC-FORWARD = = = */ + +static void +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct) +{ + size_t max_len = 0; + size_t ttl_len = 0; + int ct_down = name_ct; + int hidden = 0; + + /* + * A real "pOpts" pointer means someone messed up. Give a real error. + */ + if (pOpts > OPTPROC_EMIT_LIMIT) + fprintf(option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName, + pOD->optArg.argString, pOD->pz_Name); + + fprintf(option_usage_fp, zValidKeys, pOD->pz_Name); + + /* + * If the first name starts with this funny character, then we have + * a first value with an unspellable name. You cannot specify it. + * So, we don't list it either. + */ + if (**paz_names == 0x7F) { + paz_names++; + hidden = 1; + ct_down = --name_ct; + } + + /* + * Figure out the maximum length of any name, plus the total length + * of all the names. + */ + { + char const * const * paz = paz_names; + + do { + size_t len = strlen(*(paz++)) + 1; + if (len > max_len) + max_len = len; + ttl_len += len; + } while (--ct_down > 0); + + ct_down = name_ct; + } + + /* + * IF any one entry is about 1/2 line or longer, print one per line + */ + if (max_len > 35) { + do { + fprintf(option_usage_fp, ENUM_ERR_SEP_LINE_FMT, *(paz_names++)); + } while (--ct_down > 0); + } + + /* + * ELSE IF they all fit on one line, then do so. + */ + else if (ttl_len < 76) { + fputc(' ', option_usage_fp); + do { + fputc(' ', option_usage_fp); + fputs(*(paz_names++), option_usage_fp); + } while (--ct_down > 0); + fputc(NL, option_usage_fp); + } + + /* + * Otherwise, columnize the output + */ + else { + unsigned int ent_no = 0; + char zFmt[16]; /* format for all-but-last entries on a line */ + + sprintf(zFmt, ENUM_ERR_STR_WIDTH_FMT, (int)max_len); + max_len = 78 / max_len; /* max_len is now max entries on a line */ + fputs(TWO_SPACES_STR, option_usage_fp); + + /* + * Loop through all but the last entry + */ + ct_down = name_ct; + while (--ct_down > 0) { + if (++ent_no == max_len) { + /* + * Last entry on a line. Start next line, too. + */ + fprintf(option_usage_fp, NLSTR_SPACE_FMT, *(paz_names++)); + ent_no = 0; + } + + else + fprintf(option_usage_fp, zFmt, *(paz_names++) ); + } + fprintf(option_usage_fp, NLSTR_FMT, *paz_names); + } + + if (pOpts > OPTPROC_EMIT_LIMIT) { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { + fprintf(option_usage_fp, zLowerBits, name_ct); + fputs(zSetMemberSettings, option_usage_fp); + } else { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + } +} + +/** + * Convert a name or number into a binary number. + * "~0" and "-1" will be converted to the largest value in the enumeration. + * + * @param pzName the keyword name (number) to convert + * @param pOpts the program's option descriptor + * @param pOD the option descriptor for this option + * @param paz_names the list of keywords for this option + * @param name_ct the count of keywords + */ +static uintptr_t +find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) +{ + /* + * Return the matching index as a pointer sized integer. + * The result gets stashed in a char* pointer. + */ + uintptr_t res = name_ct; + size_t len = strlen((char*)pzName); + uintptr_t idx; + + if (IS_DEC_DIGIT_CHAR(*pzName)) { + char * pz = (char *)(void *)pzName; + unsigned long val = strtoul(pz, &pz, 0); + if ((*pz == NUL) && (val < name_ct)) + return (uintptr_t)val; + pz_enum_err_fmt = zTooLarge; + option_usage_fp = stderr; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; + } + + if (IS_INVERSION_CHAR(*pzName) && (pzName[2] == NUL)) { + if ( ((pzName[0] == '~') && (pzName[1] == '0')) + || ((pzName[0] == '-') && (pzName[1] == '1'))) + return (uintptr_t)(name_ct - 1); + goto oops; + } + + /* + * Look for an exact match, but remember any partial matches. + * Multiple partial matches means we have an ambiguous match. + */ + for (idx = 0; idx < name_ct; idx++) { + if (strncmp((char*)paz_names[idx], (char*)pzName, len) == 0) { + if (paz_names[idx][len] == NUL) + return idx; /* full match */ + + if (res == name_ct) + res = idx; /* save partial match */ + else + res = ~0; /* may yet find full match */ + } + } + + if (res < name_ct) + return res; /* partial match */ + +oops: + + pz_enum_err_fmt = (res == name_ct) ? zNoKey : zAmbigKey; + option_usage_fp = stderr; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; +} + + +/*=export_func optionKeywordName + * what: Convert between enumeration values and strings + * private: + * + * arg: tOptDesc*, pOD, enumeration option description + * arg: unsigned int, enum_val, the enumeration value to map + * + * ret_type: char const * + * ret_desc: the enumeration name from const memory + * + * doc: This converts an enumeration value into the matching string. +=*/ +char const * +optionKeywordName(tOptDesc * pOD, unsigned int enum_val) +{ + tOptDesc od = { + .optArg.argEnum = enum_val }; + + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, &od ); + return od.optArg.argString; +} + + +/*=export_func optionEnumerationVal + * what: Convert from a string to an enumeration value + * private: + * + * arg: tOptions*, pOpts, the program options descriptor + * arg: tOptDesc*, pOD, enumeration option description + * arg: char const * const *, paz_names, list of enumeration names + * arg: unsigned int, name_ct, number of names in list + * + * ret_type: uintptr_t + * ret_desc: the enumeration value + * + * doc: This converts the optArg.argString string from the option description + * into the index corresponding to an entry in the name list. + * This will match the generated enumeration value. + * Full matches are always accepted. Partial matches are accepted + * if there is only one partial match. +=*/ +uintptr_t +optionEnumerationVal(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) +{ + uintptr_t res = 0UL; + + /* + * IF the program option descriptor pointer is invalid, + * then it is some sort of special request. + */ + switch ((uintptr_t)pOpts) { + case (uintptr_t)OPTPROC_EMIT_USAGE: + /* + * print the list of enumeration names. + */ + enum_err(pOpts, pOD, paz_names, (int)name_ct); + break; + + case (uintptr_t)OPTPROC_EMIT_SHELL: + { + unsigned int ix = pOD->optArg.argEnum; + /* + * print the name string. + */ + if (ix >= name_ct) + printf(INVALID_FMT, ix); + else + fputs(paz_names[ ix ], stdout); + + break; + } + + case (uintptr_t)OPTPROC_RETURN_VALNAME: + { + unsigned int ix = pOD->optArg.argEnum; + /* + * Replace the enumeration value with the name string. + */ + if (ix >= name_ct) + return (uintptr_t)INVALID_STR; + + pOD->optArg.argString = paz_names[ix]; + break; + } + + default: + if ((pOD->fOptState & OPTST_RESET) != 0) + break; + + res = find_name(pOD->optArg.argString, pOpts, pOD, paz_names, name_ct); + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + pOD->optArg.argString = NULL; + } + } + + return res; +} + +static void +set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + /* + * print the list of enumeration names. + */ + (void)pOpts; + enum_err(OPTPROC_EMIT_USAGE, pOD, paz_names, (int)name_ct ); +} + +static void +set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + /* + * print the name string. + */ + unsigned int ix = 0; + uintptr_t bits = (uintptr_t)pOD->optCookie; + size_t len = 0; + + (void)pOpts; + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + + while (bits != 0) { + if (bits & 1) { + if (len++ > 0) fputs(OR_STR, stdout); + fputs(paz_names[ix], stdout); + } + if (++ix >= name_ct) break; + bits >>= 1; + } +} + +static void +set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + char * pz; + uintptr_t bits = (uintptr_t)pOD->optCookie; + unsigned int ix = 0; + size_t len = NONE_STR_LEN + 1; + + (void)pOpts; + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + + /* + * Replace the enumeration value with the name string. + * First, determine the needed length, then allocate and fill in. + */ + while (bits != 0) { + if (bits & 1) + len += strlen(paz_names[ix]) + PLUS_STR_LEN + 1; + if (++ix >= name_ct) break; + bits >>= 1; + } + + pOD->optArg.argString = pz = AGALOC(len, "enum"); + + /* + * Start by clearing all the bits. We want to turn off any defaults + * because we will be restoring to current state, not adding to + * the default set of bits. + */ + memcpy(pz, NONE_STR, NONE_STR_LEN); + pz += NONE_STR_LEN; + bits = (uintptr_t)pOD->optCookie; + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + ix = 0; + + while (bits != 0) { + if (bits & 1) { + size_t nln = strlen(paz_names[ix]); + memcpy(pz, PLUS_STR, PLUS_STR_LEN); + memcpy(pz+PLUS_STR_LEN, paz_names[ix], nln); + pz += nln + PLUS_STR_LEN; + } + if (++ix >= name_ct) break; + bits >>= 1; + } + *pz = NUL; +} + +/*=export_func optionSetMembers + * what: Convert between bit flag values and strings + * private: + * + * arg: tOptions*, pOpts, the program options descriptor + * arg: tOptDesc*, pOD, enumeration option description + * arg: char const * const *, + * paz_names, list of enumeration names + * arg: unsigned int, name_ct, number of names in list + * + * doc: This converts the optArg.argString string from the option description + * into the index corresponding to an entry in the name list. + * This will match the generated enumeration value. + * Full matches are always accepted. Partial matches are accepted + * if there is only one partial match. +=*/ +void +optionSetMembers(tOptions * pOpts, tOptDesc * pOD, + char const* const * paz_names, unsigned int name_ct) +{ + /* + * IF the program option descriptor pointer is invalid, + * then it is some sort of special request. + */ + switch ((uintptr_t)pOpts) { + case (uintptr_t)OPTPROC_EMIT_USAGE: + set_memb_usage(pOpts, pOD, paz_names, name_ct); + return; + + case (uintptr_t)OPTPROC_EMIT_SHELL: + set_memb_shell(pOpts, pOD, paz_names, name_ct); + return; + + case (uintptr_t)OPTPROC_RETURN_VALNAME: + set_memb_names(pOpts, pOD, paz_names, name_ct); + return; + + default: + break; + } + + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + { + char const * pzArg = pOD->optArg.argString; + uintptr_t res; + if ((pzArg == NULL) || (*pzArg == NUL)) { + pOD->optCookie = (void*)0; + return; + } + + res = (uintptr_t)pOD->optCookie; + for (;;) { + int iv, len; + + pzArg = SPN_SET_SEPARATOR_CHARS(pzArg); + iv = (*pzArg == '!'); + if (iv) + pzArg = SPN_WHITESPACE_CHARS(pzArg+1); + + len = BRK_SET_SEPARATOR_CHARS(pzArg) - pzArg; + if (len == 0) + break; + + if ((len == 3) && (strncmp(pzArg, zAll, 3) == 0)) { + if (iv) + res = 0; + else res = ~0UL; + } + else if ((len == 4) && (strncmp(pzArg, zNone, 4) == 0)) { + if (! iv) + res = 0; + } + else do { + char* pz; + uintptr_t bit = strtoul(pzArg, &pz, 0); + + if (pz != pzArg + len) { + char z[ AO_NAME_SIZE ]; + char const* p; + unsigned int shift_ct; + + if (*pz != NUL) { + if (len >= AO_NAME_LIMIT) + break; + memcpy(z, pzArg, (size_t)len); + z[len] = NUL; + p = z; + } else { + p = pzArg; + } + + shift_ct = find_name(p, pOpts, pOD, paz_names, name_ct); + if (shift_ct >= name_ct) { + pOD->optCookie = (void*)0; + return; + } + bit = 1UL << shift_ct; + } + if (iv) + res &= ~bit; + else res |= bit; + } while (false); + + if (pzArg[len] == NUL) + break; + pzArg += len + 1; + } + if (name_ct < (8 * sizeof(uintptr_t))) { + res &= (1UL << name_ct) - 1UL; + } + + pOD->optCookie = (void*)res; + } +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/enumeration.c */ diff --git a/autoopts/env.c b/autoopts/env.c new file mode 100644 index 0000000..2b55137 --- /dev/null +++ b/autoopts/env.c @@ -0,0 +1,264 @@ + +/** + * \file environment.c + * + * Time-stamp: "2012-08-11 08:18:25 bkorb" + * + * This file contains all of the routines that must be linked into + * an executable to use the generated option processing. The optional + * routines are in separately compiled modules so that they will not + * necessarily be linked in. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static void +do_env_opt(tOptState * os, char * env_name, + tOptions * pOpts, teEnvPresetType type); +/* = = = END-STATIC-FORWARD = = = */ + +/* + * doPrognameEnv - check for preset values from the ${PROGNAME} + * environment variable. This is accomplished by parsing the text into + * tokens, temporarily replacing the arg vector and calling + * immediate_opts and/or regular_opts. + */ +LOCAL void +doPrognameEnv(tOptions * pOpts, teEnvPresetType type) +{ + char const * pczOptStr = getenv(pOpts->pzPROGNAME); + token_list_t* pTL; + int sv_argc; + tAoUI sv_flag; + char ** sv_argv; + + /* + * No such beast? Then bail now. + */ + if (pczOptStr == NULL) + return; + + /* + * Tokenize the string. If there's nothing of interest, we'll bail + * here immediately. + */ + pTL = ao_string_tokenize(pczOptStr); + if (pTL == NULL) + return; + + /* + * Substitute our $PROGNAME argument list for the real one + */ + sv_argc = pOpts->origArgCt; + sv_argv = pOpts->origArgVect; + sv_flag = pOpts->fOptSet; + + /* + * We add a bogus pointer to the start of the list. The program name + * has already been pulled from "argv", so it won't get dereferenced. + * The option scanning code will skip the "program name" at the start + * of this list of tokens, so we accommodate this way .... + */ + { + uintptr_t v = (uintptr_t)(pTL->tkn_list); + pOpts->origArgVect = (void *)(v - sizeof(char *)); + } + pOpts->origArgCt = pTL->tkn_ct + 1; + pOpts->fOptSet &= ~OPTPROC_ERRSTOP; + + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + + switch (type) { + case ENV_IMM: + (void)immediate_opts(pOpts); + break; + + case ENV_ALL: + (void)immediate_opts(pOpts); + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + /* FALLTHROUGH */ + + case ENV_NON_IMM: + (void)regular_opts(pOpts); + } + + /* + * Free up the temporary arg vector and restore the original program args. + */ + free(pTL); + pOpts->origArgVect = sv_argv; + pOpts->origArgCt = sv_argc; + pOpts->fOptSet = sv_flag; +} + +static void +do_env_opt(tOptState * os, char * env_name, + tOptions * pOpts, teEnvPresetType type) +{ + os->pzOptArg = getenv(env_name); + if (os->pzOptArg == NULL) + return; + + os->flags = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState; + os->optType = TOPT_UNDEFINED; + + if ( (os->pOD->pz_DisablePfx != NULL) + && (streqvcmp(os->pzOptArg, os->pOD->pz_DisablePfx) == 0)) { + os->flags |= OPTST_DISABLED; + os->pzOptArg = NULL; + handle_opt(pOpts, os); + return; + } + + switch (type) { + case ENV_IMM: + /* + * Process only immediate actions + */ + if (DO_IMMEDIATELY(os->flags)) + break; + return; + + case ENV_NON_IMM: + /* + * Process only NON immediate actions + */ + if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags)) + break; + return; + + default: /* process everything */ + break; + } + + /* + * Make sure the option value string is persistent and consistent. + * + * The interpretation of the option value depends + * on the type of value argument the option takes + */ + if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) { + /* + * Ignore any value. + */ + os->pzOptArg = NULL; + + } else if (os->pzOptArg[0] == NUL) { + /* + * If the argument is the empty string and the argument is + * optional, then treat it as if the option was not specified. + */ + if ((os->pOD->fOptState & OPTST_ARG_OPTIONAL) == 0) + return; + os->pzOptArg = NULL; + + } else { + AGDUPSTR(os->pzOptArg, os->pzOptArg, "option argument"); + os->flags |= OPTST_ALLOC_ARG; + } + + handle_opt(pOpts, os); +} + +/* + * env_presets - check for preset values from the envrionment + * This routine should process in all, immediate or normal modes.... + */ +LOCAL void +env_presets(tOptions * pOpts, teEnvPresetType type) +{ + int ct; + tOptState st; + char* pzFlagName; + size_t spaceLeft; + char zEnvName[ AO_NAME_SIZE ]; + + /* + * Finally, see if we are to look at the environment + * variables for initial values. + */ + if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0) + return; + + doPrognameEnv(pOpts, type); + + ct = pOpts->presetOptCt; + st.pOD = pOpts->pOptDesc; + + pzFlagName = zEnvName + + snprintf(zEnvName, sizeof(zEnvName), "%s_", pOpts->pzPROGNAME); + spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1; + + for (;ct-- > 0; st.pOD++) { + size_t nln; + + /* + * If presetting is disallowed, then skip this entry + */ + if ( ((st.pOD->fOptState & OPTST_NO_INIT) != 0) + || (st.pOD->optEquivIndex != NO_EQUIVALENT) ) + continue; + + /* + * IF there is no such environment variable, + * THEN skip this entry, too. + */ + nln = strlen(st.pOD->pz_NAME) + 1; + if (nln <= spaceLeft) { + /* + * Set up the option state + */ + memcpy(pzFlagName, st.pOD->pz_NAME, nln); + do_env_opt(&st, zEnvName, pOpts, type); + } + } + + /* + * Special handling for ${PROGNAME_LOAD_OPTS} + */ + if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) + && (pOpts->specOptIdx.save_opts != 0)) { + size_t nln; + st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1; + + if (st.pOD->pz_NAME == NULL) + return; + + nln = strlen(st.pOD->pz_NAME) + 1; + + if (nln > spaceLeft) + return; + + memcpy(pzFlagName, st.pOD->pz_NAME, nln); + do_env_opt(&st, zEnvName, pOpts, type); + } +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/environment.c */ diff --git a/autoopts/file.c b/autoopts/file.c new file mode 100644 index 0000000..5a5b3eb --- /dev/null +++ b/autoopts/file.c @@ -0,0 +1,208 @@ + +/** + * \file file.c + * + * Time-stamp: "2011-08-06 08:49:35 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/** + * Make sure the directory containing the subject file exists and that + * the file exists or does not exist, per the option requirements. + * + * @param ftype file existence type flags + * @param pOpts program option descriptor + * @param pOD the option descriptor + */ +static void +check_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD) +{ + char const * fname = pOD->optArg.argString; + struct stat sb; + + errno = 0; + + switch (ftype & FTYPE_MODE_EXIST_MASK) { + case FTYPE_MODE_MUST_NOT_EXIST: + if ((stat(fname, &sb) == 0) || (errno != ENOENT)) { + if (errno == 0) + errno = EINVAL; + fprintf(stderr, zFSOptError, errno, strerror(errno), + zFSOptErrNoExist, fname, pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + /* FALLTHROUGH */ + + default: + case FTYPE_MODE_MAY_EXIST: + { + char * p = strrchr(fname, DIRCH); + size_t l; + + if (p == NULL) + /* + * The file may or may not exist and its directory is ".". + * Assume that "." exists. + */ + break; + + l = p - fname; + p = AGALOC(l + 1, "fname"); + memcpy(p, fname, l); + p[l] = NUL; + + if ((stat(p, &sb) != 0) || (errno = EINVAL, ! S_ISDIR(sb.st_mode))) { + fprintf(stderr, zFSOptError, errno, strerror(errno), + zFSOptErrMayExist, fname, pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + AGFREE(p); + break; + } + + case FTYPE_MODE_MUST_EXIST: + if ( (stat(fname, &sb) != 0) + || (errno = EINVAL, ! S_ISREG(sb.st_mode)) ) { + fprintf(stderr, zFSOptError, errno, strerror(errno), + zFSOptErrMustExist, fname, + pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + break; + } +} + +/** + * Open the specified file with open(2) and save the FD. + * + * @param pOpts program option descriptor + * @param pOD the option descriptor + * @param mode the open mode (uses int flags value) + */ +static void +open_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode) +{ + int fd = open(pOD->optArg.argString, mode.file_flags); + if (fd < 0) { + fprintf(stderr, zFSOptError, errno, strerror(errno), + zFSOptErrOpen, pOD->optArg.argString, pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + + if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0) + pOD->optCookie = (void *)pOD->optArg.argString; + else + AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name"); + + pOD->optArg.argFd = fd; + pOD->fOptState &= ~OPTST_ALLOC_ARG; +} + +/** + * Open the specified file with open(2) and save the FD. + * + * @param pOpts program option descriptor + * @param pOD the option descriptor + * @param mode the open mode (uses "char *" mode value) + */ +static void +fopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode) +{ + FILE* fp = fopen(pOD->optArg.argString, mode.file_mode); + if (fp == NULL) { + fprintf(stderr, zFSOptError, errno, strerror(errno), + zFSOptErrFopen, pOD->optArg.argString, pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + + if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0) + pOD->optCookie = (void *)pOD->optArg.argString; + else + AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name"); + + pOD->optArg.argFp = fp; + pOD->fOptState &= ~OPTST_ALLOC_ARG; +} + +/*=export_func optionFileCheck + * private: + * + * what: Decipher a boolean value + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * arg: + teOptFileType + ftype + File handling type + + * arg: + tuFileMode + mode + file open mode (if needed) + + * + * doc: + * Make sure the named file conforms with the file type mode. + * The mode specifies if the file must exist, must not exist or may + * (or may not) exist. The mode may also specify opening the + * file: don't, open just the descriptor (fd), or open as a stream + * (FILE* pointer). +=*/ +void +optionFileCheck(tOptions * pOpts, tOptDesc * pOD, + teOptFileType ftype, tuFileMode mode) +{ + if (pOpts <= OPTPROC_EMIT_LIMIT) { + if (pOpts != OPTPROC_EMIT_USAGE) + return; + + switch (ftype & FTYPE_MODE_EXIST_MASK) { + case FTYPE_MODE_MUST_NOT_EXIST: + fputs(zFileCannotExist, option_usage_fp); + break; + + case FTYPE_MODE_MUST_EXIST: + fputs(zFileMustExist, option_usage_fp); + break; + } + return; + } + + if ((pOD->fOptState & OPTST_RESET) != 0) { + if (pOD->optCookie != NULL) + AGFREE(pOD->optCookie); + return; + } + + check_existence(ftype, pOpts, pOD); + + switch (ftype & FTYPE_MODE_OPEN_MASK) { + default: + case FTYPE_MODE_NO_OPEN: break; + case FTYPE_MODE_OPEN_FD: open_file_fd( pOpts, pOD, mode); break; + case FTYPE_MODE_FOPEN_FP: fopen_file_fp(pOpts, pOD, mode); break; + } +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/file.c */ diff --git a/autoopts/find.c b/autoopts/find.c new file mode 100644 index 0000000..b9e88d5 --- /dev/null +++ b/autoopts/find.c @@ -0,0 +1,579 @@ +/** + * @file check.c + * + * @brief Hunt for options in the option descriptor list + * + * Time-stamp: "2012-08-11 08:36:11 bkorb" + * + * This file contains the routines that deal with processing quoted strings + * into an internal format. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/** + * find the name and name length we are looking for + */ +static int +parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz) +{ + int res = 0; + char const * p = *nm_pp; + *arg_pp = NULL; + + for (;;) { + switch (*(p++)) { + case NUL: return res; + + case '=': + memcpy(buf, *nm_pp, res); + + buf[res] = NUL; + *nm_pp = buf; + *arg_pp = (char *)p; + return res; + + default: + if (++res >= (int)bufsz) + return -1; + } + } +} + +/** + * print out the options that match the given name. + * + * @param pOpts option data + * @param opt_name name of option to look for + */ +static void +opt_ambiguities(tOptions * opts, char const * name, int nm_len) +{ + char const * const hyph = + NAMED_OPTS(opts) ? "" : LONG_OPT_MARKER; + + tOptDesc * pOD = opts->pOptDesc; + int idx = 0; + + fputs(zAmbigList, stderr); + do { + if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) + fprintf(stderr, zAmbiguous, hyph, pOD->pz_Name); + + else if ( (pOD->pz_DisableName != NULL) + && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) + ) + fprintf(stderr, zAmbiguous, hyph, pOD->pz_DisableName); + } while (pOD++, (++idx < opts->optCt)); +} + +/** + * Determine the number of options that match the name + * + * @param pOpts option data + * @param opt_name name of option to look for + * @param nm_len length of provided name + * @param index pointer to int for option index + * @param disable pointer to bool to mark disabled option + * @return count of options that match + */ +static int +opt_match_ct(tOptions * opts, char const * name, int nm_len, + int * ixp, bool * disable) +{ + int matchCt = 0; + int idx = 0; + int idxLim = opts->optCt; + tOptDesc * pOD = opts->pOptDesc; + + do { + /* + * If option disabled or a doc option, skip to next + */ + if (pOD->pz_Name == NULL) + continue; + + if ( SKIP_OPT(pOD) + && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) + continue; + + if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) { + /* + * IF we have a complete match + * THEN it takes priority over any already located partial + */ + if (pOD->pz_Name[ nm_len ] == NUL) { + *ixp = idx; + return 1; + } + } + + /* + * IF there is a disable name + * *AND* the option name matches the disable name + * THEN ... + */ + else if ( (pOD->pz_DisableName != NULL) + && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) + ) { + *disable = true; + + /* + * IF we have a complete match + * THEN it takes priority over any already located partial + */ + if (pOD->pz_DisableName[ nm_len ] == NUL) { + *ixp = idx; + return 1; + } + } + + else + continue; /* does not match any option */ + + /* + * We found a full or partial match, either regular or disabling. + * Remember the index for later. + */ + *ixp = idx; + ++matchCt; + + } while (pOD++, (++idx < idxLim)); + + return matchCt; +} + +/** + * Set the option to the indicated option number. + * + * @param opts option data + * @param arg option argument (if glued to name) + * @param idx option index + * @param disable mark disabled option + * @param st state about current option + */ +static tSuccess +opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st) +{ + tOptDesc * pOD = opts->pOptDesc + idx; + + if (SKIP_OPT(pOD)) { + if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) + return FAILURE; + + fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name); + if (pOD->pzText != NULL) + fprintf(stderr, SET_OFF_FMT, pOD->pzText); + fputc(NL, stderr); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + /* + * IF we found a disablement name, + * THEN set the bit in the callers' flag word + */ + if (disable) + st->flags |= OPTST_DISABLED; + + st->pOD = pOD; + st->pzOptArg = arg; + st->optType = TOPT_LONG; + + return SUCCESS; +} + +/** + * An option was not found. Check for default option and set it + * if there is one. Otherwise, handle the error. + * + * @param opts option data + * @param name name of option to look for + * @param arg option argument + * @param st state about current option + * + * @return success status + */ +static tSuccess +opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st) +{ + /* + * IF there is no equal sign + * *AND* we are using named arguments + * *AND* there is a default named option, + * THEN return that option. + */ + if ( (arg == NULL) + && NAMED_OPTS(opts) + && (opts->specOptIdx.default_opt != NO_EQUIVALENT)) { + + st->pOD = opts->pOptDesc + opts->specOptIdx.default_opt; + st->pzOptArg = name; + st->optType = TOPT_DEFAULT; + return SUCCESS; + } + + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zIllOptStr, opts->pzProgPath, name); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + return FAILURE; +} + +/** + * Several options match the provided name. + * + * @param opts option data + * @param name name of option to look for + * @param match_ct number of matching options + * + * @return success status (always FAILURE, if it returns) + */ +static tSuccess +opt_ambiguous(tOptions * opts, char const * name, int match_ct) +{ + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zAmbigOptStr, opts->pzProgPath, name, match_ct); + if (match_ct <= 4) + opt_ambiguities(opts, name, strlen(name)); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + return FAILURE; +} + +/*=export_func optionVendorOption + * private: + * + * what: Process a vendor option + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + + * + * doc: + * For POSIX specified utilities, the options are constrained to the options, + * @xref{config attributes, Program Configuration}. AutoOpts clients should + * never specify this directly. It gets referenced when the option + * definitions contain a "vendor-opt" attribute. +=*/ +void +optionVendorOption(tOptions * pOpts, tOptDesc * pOD) +{ + tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); + char const * vopt_str = pOD->optArg.argString; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + if ((pOD->fOptState & OPTPROC_IMMEDIATE) == 0) + opt_st.flags = OPTST_DEFINED; + + if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) == 0) + || ! SUCCESSFUL(opt_find_long(pOpts, vopt_str, &opt_st)) + || ! SUCCESSFUL(get_opt_arg(pOpts, &opt_st)) ) + { + fprintf(stderr, zIllVendOptStr, pOpts->pzProgName, vopt_str); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + /* + * See if we are in immediate handling state. + */ + if (pOpts->fOptSet & OPTPROC_IMMEDIATE) { + /* + * See if the enclosed option is okay with that state. + */ + if (DO_IMMEDIATELY(opt_st.flags)) + (void)handle_opt(pOpts, &opt_st); + + } else { + /* + * non-immediate direction. + * See if the enclosed option is okay with that state. + */ + if (DO_NORMALLY(opt_st.flags) || DO_SECOND_TIME(opt_st.flags)) + (void)handle_opt(pOpts, &opt_st); + } +} + +/** + * Find the option descriptor by full name. + * + * @param opts option data + * @param opt_name name of option to look for + * @param state state about current option + * + * @return success status + */ +LOCAL tSuccess +opt_find_long(tOptions * opts, char const * opt_name, tOptState * state) +{ + char name_buf[128]; + char * opt_arg; + int nm_len = parse_opt(&opt_name, &opt_arg, name_buf, sizeof(name_buf)); + + int idx = 0; + bool disable = false; + int ct; + + if (nm_len <= 0) { + fprintf(stderr, zInvalOptName, opts->pzProgName, opt_name); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + ct = opt_match_ct(opts, opt_name, nm_len, &idx, &disable); + + /* + * See if we found one match, no matches or multiple matches. + */ + switch (ct) { + case 1: return opt_set(opts, opt_arg, idx, disable, state); + case 0: return opt_unknown(opts, opt_name, opt_arg, state); + default: return opt_ambiguous(opts, opt_name, ct); + } +} + + +/** + * Find the short option descriptor for the current option + * + * @param pOpts option data + * @param optValue option flag character + * @param pOptState state about current option + */ +LOCAL tSuccess +opt_find_short(tOptions* pOpts, uint_t optValue, tOptState* pOptState) +{ + tOptDesc* pRes = pOpts->pOptDesc; + int ct = pOpts->optCt; + + /* + * Search the option list + */ + do { + if (optValue != pRes->optValue) + continue; + + if (SKIP_OPT(pRes)) { + if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) + && (pRes->pz_Name != NULL)) { + fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name); + if (pRes->pzText != NULL) + fprintf(stderr, SET_OFF_FMT, pRes->pzText); + fputc(NL, stderr); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + goto short_opt_error; + } + + pOptState->pOD = pRes; + pOptState->optType = TOPT_SHORT; + return SUCCESS; + + } while (pRes++, --ct > 0); + + /* + * IF the character value is a digit + * AND there is a special number option ("-n") + * THEN the result is the "option" itself and the + * option is the specially marked "number" option. + */ + if ( IS_DEC_DIGIT_CHAR(optValue) + && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) { + pOptState->pOD = \ + pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option; + (pOpts->pzCurOpt)--; + pOptState->optType = TOPT_SHORT; + return SUCCESS; + } + +short_opt_error: + + /* + * IF we are to stop on errors (the default, actually) + * THEN call the usage procedure. + */ + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + return FAILURE; +} + +LOCAL tSuccess +get_opt_arg(tOptions * pOpts, tOptState * pOptState) +{ + pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT_MASK); + + /* + * Figure out what to do about option arguments. An argument may be + * required, not associated with the option, or be optional. We detect the + * latter by examining for an option marker on the next possible argument. + * Disabled mode option selection also disables option arguments. + */ + { + enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE; + tSuccess res; + + if ((pOptState->flags & OPTST_DISABLED) != 0) + arg_type = ARG_NONE; + + else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE) + arg_type = ARG_NONE; + + else if (pOptState->flags & OPTST_ARG_OPTIONAL) + arg_type = ARG_MAY; + + else + arg_type = ARG_MUST; + + switch (arg_type) { + case ARG_MUST: res = next_opt_arg_must(pOpts, pOptState); break; + case ARG_MAY: res = next_opt_arg_may( pOpts, pOptState); break; + case ARG_NONE: res = next_opt_arg_none(pOpts, pOptState); break; + } + + return res; + } +} + +/** + * Find the option descriptor for the current option + */ +LOCAL tSuccess +find_opt(tOptions * pOpts, tOptState * pOptState) +{ + /* + * IF we are continuing a short option list (e.g. -xyz...) + * THEN continue a single flag option. + * OTHERWISE see if there is room to advance and then do so. + */ + if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL)) + return opt_find_short(pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState); + + if (pOpts->curOptIdx >= pOpts->origArgCt) + return PROBLEM; /* NORMAL COMPLETION */ + + pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ]; + + /* + * IF all arguments must be named options, ... + */ + if (NAMED_OPTS(pOpts)) { + char * pz = pOpts->pzCurOpt; + int def; + tSuccess res; + tAoUS * def_opt; + + pOpts->curOptIdx++; + + if (*pz != '-') + return opt_find_long(pOpts, pz, pOptState); + + /* + * The name is prefixed with one or more hyphens. Strip them off + * and disable the "default_opt" setting. Use heavy recasting to + * strip off the "const" quality of the "default_opt" field. + */ + while (*(++pz) == '-') ; + def_opt = (void *)&(pOpts->specOptIdx.default_opt); + def = *def_opt; + *def_opt = NO_EQUIVALENT; + res = opt_find_long(pOpts, pz, pOptState); + *def_opt = def; + return res; + } + + /* + * Note the kind of flag/option marker + */ + if (*((pOpts->pzCurOpt)++) != '-') + return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ + + /* + * Special hack for a hyphen by itself + */ + if (*(pOpts->pzCurOpt) == NUL) + return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ + + /* + * The current argument is to be processed as an option argument + */ + pOpts->curOptIdx++; + + /* + * We have an option marker. + * Test the next character for long option indication + */ + if (pOpts->pzCurOpt[0] == '-') { + if (*++(pOpts->pzCurOpt) == NUL) + /* + * NORMAL COMPLETION - NOT this arg, but rest are operands + */ + return PROBLEM; + + /* + * We do not allow the hyphen to be used as a flag value. + * Therefore, if long options are not to be accepted, we punt. + */ + if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) { + fprintf(stderr, zIllOptStr, pOpts->pzProgPath, + pOpts->pzCurOpt-2); + return FAILURE; + } + + return opt_find_long(pOpts, pOpts->pzCurOpt, pOptState); + } + + /* + * If short options are not allowed, then do long + * option processing. Otherwise the character must be a + * short (i.e. single character) option. + */ + if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0) + return opt_find_short(pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState); + + return opt_find_long(pOpts, pOpts->pzCurOpt, pOptState); +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/find.c */ diff --git a/autoopts/funcs.def b/autoopts/funcs.def new file mode 100644 index 0000000..3696339 --- /dev/null +++ b/autoopts/funcs.def @@ -0,0 +1,1620 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * + * DO NOT EDIT THIS FILE (funcs.def) + * + * It has been extracted by getdefs from the following files: + * + * autoopts.c + * alias.c + * boolean.c + * check.c + * configfile.c + * cook.c + * enum.c + * env.c + * file.c + * find.c + * genshell.c + * load.c + * makeshell.c + * nested.c + * numeric.c + * pgusage.c + * putshell.c + * reset.c + * restore.c + * save.c + * sort.c + * stack.c + * streqvcmp.c + * text_mmap.c + * time.c + * tokenize.c + * usage.c + * version.c + * ../compat/pathfind.c + */ +autogen definitions options_h; + +/* GLOBALDEFS */ + +#line 594 "autoopts.c" + library = 'opts'; + header = 'your-opts.h'; + lib_description = +'These are the routines that libopts users may call directly from their +code. There are several other routines that can be called by code +generated by the libopts option templates, but they are not to be +called from any other user code. The @file{options.h} header is +fairly clear about this, too.'; + + +#line 206 "cook.c" +export_func = { + name = 'ao_string_cook'; + private; + what = 'concatenate and escape-process strings'; + arg = { + arg_type = 'char*'; + arg_name = 'pzScan'; + arg_desc = 'The *MODIFIABLE* input buffer'; + }; + arg = { + arg_type = 'int*'; + arg_name = 'lnct_p'; + arg_desc = 'The (possibly NULL) pointer to a line count'; + }; + ret-type = 'char*'; + ret-desc = 'The address of the text following the processed strings. +The return value is NULL if the strings are ill-formed.'; + doc = +'A series of one or more quoted strings are concatenated together. +If they are quoted with double quotes (@code{"}), then backslash +escapes are processed per the C programming language. If they are +single quote strings, then the backslashes are honored only when they +precede another backslash or a single quote character.'; + err = '@code{NULL} is returned if the string(s) is/are mal-formed.'; + srcfile = 'cook.c'; + linenum = '206'; +}; + + +#line 35 "cook.c" +export_func = { + name = 'ao_string_cook_escape_char'; + private; + what = 'escape-process a string fragment'; + arg = { + arg_type = 'char const*'; + arg_name = 'pzScan'; + arg_desc = 'points to character after the escape'; + }; + arg = { + arg_type = 'char*'; + arg_name = 'pRes'; + arg_desc = 'Where to put the result byte'; + }; + arg = { + arg_type = 'unsigned int'; + arg_name = 'nl_ch'; + arg_desc = 'replacement char if scanned char is \n'; + }; + ret-type = 'unsigned int'; + ret-desc = 'The number of bytes consumed processing the escaped character.'; + doc = +'This function converts "t" into "\\t" and all your other favorite +escapes, including numeric ones: hex and ocatal, too. +The returned result tells the caller how far to advance the +scan pointer (passed in). The default is to just pass through the +escaped character and advance the scan by one. + +Some applications need to keep an escaped newline, others need to +suppress it. This is accomplished by supplying a \'\\n\' replacement +character that is different from \\n, if need be. For example, use +0x7F and never emit a 0x7F.'; + err = '@code{NULL} is returned if the string is mal-formed.'; + srcfile = 'cook.c'; + linenum = '35'; +}; + + +#line 164 "tokenize.c" +export_func = { + name = 'ao_string_tokenize'; + what = 'tokenize an input string'; + arg = { + arg_type = 'char const*'; + arg_name = 'string'; + arg_desc = 'string to be tokenized'; + }; + ret_type = 'token_list_t*'; + ret_desc = 'pointer to a structure that lists each token'; + doc = +'This function will convert one input string into a list of strings. +The list of strings is derived by separating the input based on +white space separation. However, if the input contains either single +or double quote characters, then the text after that character up to +a matching quote will become the string in the list. + +The returned pointer should be deallocated with @code{free(3C)} when +are done using the data. The data are placed in a single block of +allocated memory. Do not deallocate individual token/strings. + +The structure pointed to will contain at least these two fields: +@table @samp +@item tkn_ct +The number of tokens found in the input string. +@item tok_list +An array of @code{tkn_ct + 1} pointers to substring tokens, with +the last pointer set to NULL. +@end table + +There are two types of quoted strings: single quoted (@code{\'}) and +double quoted (@code{"}). Singly quoted strings are fairly raw in that +escape characters (@code{\\\\}) are simply another character, except when +preceding the following characters: +@example +@code{\\\\} double backslashes reduce to one +@code{\'} incorporates the single quote into the string +@code{\\n} suppresses both the backslash and newline character +@end example + +Double quote strings are formed according to the rules of string +constants in ANSI-C programs.'; + example = +'@example +#include <stdlib.h> +int ix; +token_list_t* ptl = ao_string_tokenize(some_string) +for (ix = 0; ix < ptl->tkn_ct; ix++) +do_something_with_tkn(ptl->tkn_list[ix]); +free(ptl); +@end example +Note that everything is freed with the one call to @code{free(3C)}.'; + err = +'NULL is returned and @code{errno} will be set to indicate the problem: +@itemize @bullet +@item +@code{EINVAL} - There was an unterminated quoted string. +@item +@code{ENOENT} - The input string was empty. +@item +@code{ENOMEM} - There is not enough memory. +@end itemize'; + srcfile = 'tokenize.c'; + linenum = '164'; +}; + + +#line 77 "configfile.c" +export_func = { + name = 'configFileLoad'; + what = 'parse a configuration file'; + arg = { + arg_type = 'char const*'; + arg_name = 'pzFile'; + arg_desc = 'the file to load'; + }; + ret_type = 'const tOptionValue*'; + ret_desc = 'An allocated, compound value structure'; + doc = +'This routine will load a named configuration file and parse the +text as a hierarchically valued option. The option descriptor +created from an option definition file is not used via this interface. +The returned value is "named" with the input file name and is of +type "@code{OPARG_TYPE_HIERARCHY}". It may be used in calls to +@code{optionGetValue()}, @code{optionNextValue()} and +@code{optionUnloadNested()}.'; + err = +'If the file cannot be loaded or processed, @code{NULL} is returned and +@var{errno} is set. It may be set by a call to either @code{open(2)} +@code{mmap(2)} or other file system calls, or it may be: +@itemize @bullet +@item +@code{ENOENT} - the file was not found. +@item +@code{ENOMSG} - the file was empty. +@item +@code{EINVAL} - the file contents are invalid -- not properly formed. +@item +@code{ENOMEM} - not enough memory to allocate the needed structures. +@end itemize'; + srcfile = 'configfile.c'; + linenum = '77'; +}; + + +#line 765 "makeshell.c" +export_func = { + name = 'genshelloptUsage'; + private; + what = 'The usage function for the genshellopt generated program'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'int'; + arg_name = 'exitCode'; + arg_desc = 'usage text type to produce'; + }; + doc = +'This function is used to create the usage strings for the option +processing shell script code. Two child processes are spawned +each emitting the usage text in either the short (error exit) +style or the long style. The generated program will capture this +and create shell script variables containing the two types of text.'; + srcfile = 'makeshell.c'; + linenum = '765'; +}; + + +#line 32 "alias.c" +export_func = { + name = 'optionAlias'; + private; + what = 'relay an option to its alias'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + arg = { + arg_type = 'unsigned int'; + arg_name = 'alias'; + arg_desc = 'the aliased-to option index'; + }; + ret-type = 'int'; + doc = +'Handle one option as if it had been specified as another. Exactly. +Returns "-1" if the aliased-to option has appeared too many times.'; + srcfile = 'alias.c'; + linenum = '32'; +}; + + +#line 33 "boolean.c" +export_func = { + name = 'optionBooleanVal'; + private; + what = 'Decipher a boolean value'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Decipher a true or false value for a boolean valued option argument. +The value is true, unless it starts with \'n\' or \'f\' or "#f" or +it is an empty string or it is a number that evaluates to zero.'; + srcfile = 'boolean.c'; + linenum = '33'; +}; + + +#line 260 "enum.c" +export_func = { + name = 'optionEnumerationVal'; + what = 'Convert from a string to an enumeration value'; + private; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'the program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOD'; + arg_desc = 'enumeration option description'; + }; + arg = { + arg_type = 'char const * const *'; + arg_name = 'paz_names'; + arg_desc = 'list of enumeration names'; + }; + arg = { + arg_type = 'unsigned int'; + arg_name = 'name_ct'; + arg_desc = 'number of names in list'; + }; + ret_type = 'uintptr_t'; + ret_desc = 'the enumeration value'; + doc = 'This converts the optArg.argString string from the option description +into the index corresponding to an entry in the name list. +This will match the generated enumeration value. +Full matches are always accepted. Partial matches are accepted +if there is only one partial match.'; + srcfile = 'enum.c'; + linenum = '260'; +}; + + +#line 151 "file.c" +export_func = { + name = 'optionFileCheck'; + private; + what = 'Decipher a boolean value'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + arg = { + arg_type = 'teOptFileType'; + arg_name = 'ftype'; + arg_desc = 'File handling type'; + }; + arg = { + arg_type = 'tuFileMode'; + arg_name = 'mode'; + arg_desc = 'file open mode (if needed)'; + }; + doc = +'Make sure the named file conforms with the file type mode. +The mode specifies if the file must exist, must not exist or may +(or may not) exist. The mode may also specify opening the'; + file = 'don\'t, open just the descriptor (fd), or open as a stream +(FILE* pointer).'; + srcfile = 'file.c'; + linenum = '151'; +}; + + +#line 1066 "configfile.c" +export_func = { + name = 'optionFileLoad'; + what = 'Load the locatable config files, in order'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'pzProg'; + arg_desc = 'program name'; + }; + ret_type = 'int'; + ret_desc = '0 -> SUCCESS, -1 -> FAILURE'; + doc = +'This function looks in all the specified directories for a configuration +file ("rc" file or "ini" file) and processes any found twice. The first +time through, they are processed in reverse order (last file first). At +that time, only "immediate action" configurables are processed. For +example, if the last named file specifies not processing any more +configuration files, then no more configuration files will be processed. +Such an option in the @strong{first} named directory will have no effect. + +Once the immediate action configurables have been handled, then the +directories are handled in normal, forward order. In that way, later +config files can override the settings of earlier config files. + +See the AutoOpts documentation for a thorough discussion of the +config file format. + +Configuration files not found or not decipherable are simply ignored.'; + err = 'Returns the value, "-1" if the program options descriptor +is out of date or indecipherable. Otherwise, the value "0" will +always be returned.'; + srcfile = 'configfile.c'; + linenum = '1066'; +}; + + +#line 211 "configfile.c" +export_func = { + name = 'optionFindNextValue'; + FIXME = 'the handling of \'pzName\' and \'pzVal\' is just wrong.'; + what = 'find a hierarcicaly valued option instance'; + arg = { + arg_type = 'const tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'an option with a nested arg type'; + }; + arg = { + arg_type = 'const tOptionValue*'; + arg_name = 'pPrevVal'; + arg_desc = 'the last entry'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'name'; + arg_desc = 'name of value to find'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'value'; + arg_desc = 'the matching value'; + }; + ret_type = 'const tOptionValue*'; + ret_desc = 'a compound value structure'; + doc = +'This routine will find the next entry in a nested value option or +configurable. It will search through the list and return the next entry +that matches the criteria.'; + err = +'The returned result is NULL and errno is set: +@itemize @bullet +@item +@code{EINVAL} - the @code{pOptValue} does not point to a valid +hierarchical option value. +@item +@code{ENOENT} - no entry matched the given name. +@end itemize'; + srcfile = 'configfile.c'; + linenum = '211'; +}; + + +#line 137 "configfile.c" +export_func = { + name = 'optionFindValue'; + what = 'find a hierarcicaly valued option instance'; + arg = { + arg_type = 'const tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'an option with a nested arg type'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'name'; + arg_desc = 'name of value to find'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'value'; + arg_desc = 'the matching value'; + }; + ret_type = 'const tOptionValue*'; + ret_desc = 'a compound value structure'; + doc = +'This routine will find an entry in a nested value option or configurable. +It will search through the list and return a matching entry.'; + err = +'The returned result is NULL and errno is set: +@itemize @bullet +@item +@code{EINVAL} - the @code{pOptValue} does not point to a valid +hierarchical option value. +@item +@code{ENOENT} - no entry matched the given name. +@end itemize'; + srcfile = 'configfile.c'; + linenum = '137'; +}; + + +#line 166 "restore.c" +export_func = { + name = 'optionFree'; + what = 'free allocated option processing memory'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + doc = 'AutoOpts sometimes allocates memory and puts pointers to it in the +option state structures. This routine deallocates all such memory.'; + err = 'As long as memory has not been corrupted, +this routine is always successful.'; + srcfile = 'restore.c'; + linenum = '166'; +}; + + +#line 280 "configfile.c" +export_func = { + name = 'optionGetValue'; + what = 'get a specific value from a hierarcical list'; + arg = { + arg_type = 'const tOptionValue*'; + arg_name = 'pOptValue'; + arg_desc = 'a hierarchcal value'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'valueName'; + arg_desc = 'name of value to get'; + }; + ret_type = 'const tOptionValue*'; + ret_desc = 'a compound value structure'; + doc = +'This routine will find an entry in a nested value option or configurable. +If "valueName" is NULL, then the first entry is returned. Otherwise, +the first entry with a name that exactly matches the argument will be +returned. If there is no matching value, NULL is returned and errno is +set to ENOENT. If the provided option value is not a hierarchical value, +NULL is also returned and errno is set to EINVAL.'; + err = +'The returned result is NULL and errno is set: +@itemize @bullet +@item +@code{EINVAL} - the @code{pOptValue} does not point to a valid +hierarchical option value. +@item +@code{ENOENT} - no entry matched the given name. +@end itemize'; + srcfile = 'configfile.c'; + linenum = '280'; +}; + + +#line 237 "enum.c" +export_func = { + name = 'optionKeywordName'; + what = 'Convert between enumeration values and strings'; + private; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOD'; + arg_desc = 'enumeration option description'; + }; + arg = { + arg_type = 'unsigned int'; + arg_name = 'enum_val'; + arg_desc = 'the enumeration value to map'; + }; + ret_type = 'char const *'; + ret_desc = 'the enumeration name from const memory'; + doc = 'This converts an enumeration value into the matching string.'; + srcfile = 'enum.c'; + linenum = '237'; +}; + + +#line 478 "load.c" +export_func = { + name = 'optionLoadLine'; + what = 'process a string for an option name and value'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'opts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'line'; + arg_desc = 'NUL-terminated text'; + }; + doc = +'This is a client program callable routine for setting options from, for +example, the contents of a file that they read in. Only one option may +appear in the text. It will be treated as a normal (non-preset) option. + +When passed a pointer to the option struct and a string, it will find +the option named by the first token on the string and set the option +argument to the remainder of the string. The caller must NUL terminate +the string. The caller need not skip over any introductory hyphens. +Any embedded new lines will be included in the option +argument. If the input looks like one or more quoted strings, then the +input will be "cooked". The "cooking" is identical to the string +formation used in AutoGen definition files (@pxref{basic expression}), +except that you may not use backquotes.'; + err = 'Invalid options are silently ignored. Invalid option arguments +will cause a warning to print, but the function should return.'; + srcfile = 'load.c'; + linenum = '478'; +}; + + +#line 1116 "configfile.c" +export_func = { + name = 'optionLoadOpt'; + private; + what = 'Load an option rc/ini file'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Processes the options found in the file named with +pOptDesc->optArg.argString.'; + srcfile = 'configfile.c'; + linenum = '1116'; +}; + + +#line 43 "load.c" +export_func = { + name = 'optionMakePath'; + private; + what = 'translate and construct a path'; + arg = { + arg_type = 'char*'; + arg_name = 'pzBuf'; + arg_desc = 'The result buffer'; + }; + arg = { + arg_type = 'int'; + arg_name = 'bufSize'; + arg_desc = 'The size of this buffer'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'pzName'; + arg_desc = 'The input name'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'pzProgPath'; + arg_desc = 'The full path of the current program'; + }; + ret-type = 'bool'; + ret-desc = 'true if the name was handled, otherwise false. +If the name does not start with ``$\'\', then it is handled +simply by copying the input name to the output buffer and +resolving the name with either +@code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}.'; + doc = +'This routine will copy the @code{pzName} input name into the +@code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the +first character of the input name is a @code{\'$\'} character, then there +is special handling: +@* +@code{$$} is replaced with the directory name of the @code{pzProgPath}, +searching @code{$PATH} if necessary. +@* +@code{$@} is replaced with the AutoGen package data installation directory +(aka @code{pkgdatadir}). +@* +@code{$NAME} is replaced by the contents of the @code{NAME} environment +variable. If not found, the search fails. + +Please note: both @code{$$} and @code{$NAME} must be at the start of the +@code{pzName} string and must either be the entire string or be followed +by the @code{\'/\'} (backslash on windows) character.'; + err = '@code{false} is returned if: +@* +@bullet{} The input name exceeds @code{bufSize} bytes. +@* +@bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string +and the next character is not \'/\'. +@* +@bullet{} libopts was built without PKGDATADIR defined and @code{$@@} +was specified. +@* +@bullet{} @code{NAME} is not a known environment variable +@* +@bullet{} @code{canonicalize_file_name} or @code{realpath} return +errors (cannot resolve the resulting path).'; + srcfile = 'load.c'; + linenum = '43'; +}; + + +#line 727 "nested.c" +export_func = { + name = 'optionNestedVal'; + private; + what = 'parse a hierarchical option argument'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Nested value was found on the command line'; + srcfile = 'nested.c'; + linenum = '727'; +}; + + +#line 340 "configfile.c" +export_func = { + name = 'optionNextValue'; + what = 'get the next value from a hierarchical list'; + arg = { + arg_type = 'const tOptionValue*'; + arg_name = 'pOptValue'; + arg_desc = 'a hierarchcal list value'; + }; + arg = { + arg_type = 'const tOptionValue*'; + arg_name = 'pOldValue'; + arg_desc = 'a value from this list'; + }; + ret_type = 'const tOptionValue*'; + ret_desc = 'a compound value structure'; + doc = +'This routine will return the next entry after the entry passed in. At the +end of the list, NULL will be returned. If the entry is not found on the +list, NULL will be returned and "@var{errno}" will be set to EINVAL. +The "@var{pOldValue}" must have been gotten from a prior call to this +routine or to "@code{opitonGetValue()}".'; + err = +'The returned result is NULL and errno is set: +@itemize @bullet +@item +@code{EINVAL} - the @code{pOptValue} does not point to a valid +hierarchical option value or @code{pOldValue} does not point to a +member of that option value. +@item +@code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry. +@end itemize'; + srcfile = 'configfile.c'; + linenum = '340'; +}; + + +#line 90 "numeric.c" +export_func = { + name = 'optionNumericVal'; + private; + what = 'process an option with a numeric value.'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Decipher a numeric value.'; + srcfile = 'numeric.c'; + linenum = '90'; +}; + + +#line 201 "usage.c" +export_func = { + name = 'optionOnlyUsage'; + what = 'Print usage text for just the options'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'int'; + arg_name = 'ex_code'; + arg_desc = 'exit code for calling exit(3)'; + }; + doc = +'This routine will print only the usage for each option. +This function may be used when the emitted usage must incorporate +information not available to AutoOpts.'; + srcfile = 'usage.c'; + linenum = '201'; +}; + + +#line 33 "pgusage.c" +export_func = { + name = 'optionPagedUsage'; + private; + what = 'Decipher a boolean value'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Run the usage output through a pager. +This is very handy if it is very long. +This is disabled on platforms without a working fork() function.'; + srcfile = 'pgusage.c'; + linenum = '33'; +}; + + +#line 73 "makeshell.c" +export_func = { + name = 'optionParseShell'; + private; + what = 'Decipher a boolean value'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + doc = +'Emit a shell script that will parse the command line options.'; + srcfile = 'makeshell.c'; + linenum = '73'; +}; + + +#line 176 "version.c" +export_func = { + name = 'optionPrintVersion'; + private; + what = 'Print the program version'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'opts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'od'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'This routine will print the version to stdout.'; + srcfile = 'version.c'; + linenum = '176'; +}; + + +#line 607 "autoopts.c" +export_func = { + name = 'optionProcess'; + what = 'this is the main option processing routine'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'int'; + arg_name = 'argc'; + arg_desc = 'program arg count'; + }; + arg = { + arg_type = 'char**'; + arg_name = 'argv'; + arg_desc = 'program arg vector'; + }; + ret_type = 'int'; + ret_desc = 'the count of the arguments processed'; + doc = +'This is the main entry point for processing options. It is intended +that this procedure be called once at the beginning of the execution of +a program. Depending on options selected earlier, it is sometimes +necessary to stop and restart option processing, or to select completely +different sets of options. This can be done easily, but you generally +do not want to do this. + +The number of arguments processed always includes the program name. +If one of the arguments is "--", then it is counted and the processing +stops. If an error was encountered and errors are to be tolerated, then +the returned value is the index of the argument causing the error. +A hyphen by itself ("-") will also cause processing to stop and will +@emph{not} be counted among the processed arguments. A hyphen by itself +is treated as an operand. Encountering an operand stops option +processing.'; + err = 'Errors will cause diagnostics to be printed. @code{exit(3)} may +or may not be called. It depends upon whether or not the options +were generated with the "allow-errors" attribute, or if the +ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.'; + srcfile = 'autoopts.c'; + linenum = '607'; +}; + + +#line 214 "putshell.c" +export_func = { + name = 'optionPutShell'; + what = 'write a portable shell script to parse options'; + private; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'the program options descriptor'; + }; + doc = 'This routine will emit portable shell script text for parsing +the options described in the option definitions.'; + srcfile = 'putshell.c'; + linenum = '214'; +}; + + +#line 58 "reset.c" +export_func = { + name = 'optionResetOpt'; + private; + what = 'Reset the value of an option'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'This code will cause another option to be reset to its initial state. +For example, --reset=foo will cause the --foo option to be reset.'; + srcfile = 'reset.c'; + linenum = '58'; +}; + + +#line 123 "restore.c" +export_func = { + name = 'optionRestore'; + what = 'restore option state from memory copy'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + doc = 'Copy back the option state from saved memory. +The allocated memory is left intact, so this routine can be +called repeatedly without having to call optionSaveState again. +If you are restoring a state that was saved before the first call +to optionProcess(3AO), then you may change the contents of the +argc/argv parameters to optionProcess.'; + err = 'If you have not called @code{optionSaveState} before, a diagnostic is +printed to @code{stderr} and exit is called.'; + srcfile = 'restore.c'; + linenum = '123'; +}; + + +#line 648 "save.c" +export_func = { + name = 'optionSaveFile'; + what = 'saves the option state to a file'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + doc = +'This routine will save the state of option processing to a file. The name +of that file can be specified with the argument to the @code{--save-opts} +option, or by appending the @code{rcfile} attribute to the last +@code{homerc} attribute. If no @code{rcfile} attribute was specified, it +will default to @code{.@i{programname}rc}. If you wish to specify another +file, you should invoke the @code{SET_OPT_SAVE_OPTS(@i{filename})} macro. + +The recommend usage is as follows: +@example +optionProcess(&progOptions, argc, argv); +if (i_want_a_non_standard_place_for_this) +SET_OPT_SAVE_OPTS("myfilename"); +optionSaveFile(&progOptions); +@end example'; + err = +'If no @code{homerc} file was specified, this routine will silently return +and do nothing. If the output file cannot be created or updated, a message +will be printed to @code{stderr} and the routine will return.'; + srcfile = 'save.c'; + linenum = '648'; +}; + + +#line 71 "restore.c" +export_func = { + name = 'optionSaveState'; + what = 'saves the option state to memory'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + doc = +'This routine will allocate enough memory to save the current option +processing state. If this routine has been called before, that memory +will be reused. You may only save one copy of the option state. This +routine may be called before optionProcess(3AO). If you do call it +before the first call to optionProcess, then you may also change the +contents of argc/argv after you call optionRestore(3AO) + +In fact, more strongly put: it is safest to only use this function +before having processed any options. In particular, the saving and +restoring of stacked string arguments and hierarchical values is +disabled. The values are not saved.'; + err = 'If it fails to allocate the memory, +it will print a message to stderr and exit. +Otherwise, it will always succeed.'; + srcfile = 'restore.c'; + linenum = '71'; +}; + + +#line 423 "enum.c" +export_func = { + name = 'optionSetMembers'; + what = 'Convert between bit flag values and strings'; + private; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'the program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOD'; + arg_desc = 'enumeration option description'; + }; + arg = { + arg_type = 'char const * const *'; + arg_name = 'paz_names'; + arg_desc = 'list of enumeration names'; + }; + arg = { + arg_type = 'unsigned int'; + arg_name = 'name_ct'; + arg_desc = 'number of names in list'; + }; + doc = 'This converts the optArg.argString string from the option description +into the index corresponding to an entry in the name list. +This will match the generated enumeration value. +Full matches are always accepted. Partial matches are accepted +if there is only one partial match.'; + srcfile = 'enum.c'; + linenum = '423'; +}; + + +#line 28 "numeric.c" +export_func = { + name = 'optionShowRange'; + private; + what; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + arg = { + arg_type = 'void *'; + arg_name = 'rng_table'; + arg_desc = 'the value range tables'; + }; + arg = { + arg_type = 'int'; + arg_name = 'rng_count'; + arg_desc = 'the number of entries'; + }; + doc = +'Show information about a numeric option with range constraints.'; + srcfile = 'numeric.c'; + linenum = '28'; +}; + + +#line 226 "stack.c" +export_func = { + name = 'optionStackArg'; + private; + what = 'put option args on a stack'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Keep an entry-ordered list of option arguments.'; + srcfile = 'stack.c'; + linenum = '226'; +}; + + +#line 64 "time.c" +export_func = { + name = 'optionTimeDate'; + private; + what = 'process an option with a time and date.'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Decipher a time and date value.'; + srcfile = 'time.c'; + linenum = '64'; +}; + + +#line 28 "time.c" +export_func = { + name = 'optionTimeVal'; + private; + what = 'process an option with a time duration.'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Decipher a time duration value.'; + srcfile = 'time.c'; + linenum = '28'; +}; + + +#line 563 "nested.c" +export_func = { + name = 'optionUnloadNested'; + what = 'Deallocate the memory for a nested value'; + arg = { + arg_type = 'tOptionValue const *'; + arg_name = 'pOptVal'; + arg_desc = 'the hierarchical value'; + }; + doc = +'A nested value needs to be deallocated. The pointer passed in should +have been gotten from a call to @code{configFileLoad()} (See +@pxref{libopts-configFileLoad}).'; + srcfile = 'nested.c'; + linenum = '563'; +}; + + +#line 35 "stack.c" +export_func = { + name = 'optionUnstackArg'; + private; + what = 'Remove option args from a stack'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'Invoked for options that are equivalenced to stacked options.'; + srcfile = 'stack.c'; + linenum = '35'; +}; + + +#line 315 "usage.c" +export_func = { + name = 'optionUsage'; + private; + what = 'Print usage text'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'pOptions'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'int'; + arg_name = 'exitCode'; + arg_desc = 'exit code for calling exit(3)'; + }; + doc = +'This routine will print usage in both GNU-standard and AutoOpts-expanded +formats. The descriptor specifies the default, but AUTOOPTS_USAGE will +over-ride this, providing the value of it is set to either "gnu" or +"autoopts". This routine will @strong{not} return. + +If "exitCode" is "AO_EXIT_REQ_USAGE" (normally 64), then output will to +to stdout and the actual exit code will be "EXIT_SUCCESS".'; + srcfile = 'usage.c'; + linenum = '315'; +}; + + +#line 268 "find.c" +export_func = { + name = 'optionVendorOption'; + private; + what = 'Process a vendor option'; + arg = { + arg_type = 'tOptions *'; + arg_name = 'pOpts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc *'; + arg_name = 'pOptDesc'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'For POSIX specified utilities, the options are constrained to the options, +@xref{config attributes, Program Configuration}. AutoOpts clients should +never specify this directly. It gets referenced when the option +definitions contain a "vendor-opt" attribute.'; + srcfile = 'find.c'; + linenum = '268'; +}; + + +#line 31 "version.c" +export_func = { + name = 'optionVersion'; + what = 'return the compiled AutoOpts version number'; + ret_type = 'char const*'; + ret_desc = 'the version string in constant memory'; + doc = +'Returns the full version string compiled into the library. +The returned string cannot be modified.'; + srcfile = 'version.c'; + linenum = '31'; +}; + + +#line 192 "version.c" +export_func = { + name = 'optionVersionStderr'; + private; + what = 'Print the program version to stderr'; + arg = { + arg_type = 'tOptions*'; + arg_name = 'opts'; + arg_desc = 'program options descriptor'; + }; + arg = { + arg_type = 'tOptDesc*'; + arg_name = 'od'; + arg_desc = 'the descriptor for this arg'; + }; + doc = +'This routine will print the version to stderr.'; + srcfile = 'version.c'; + linenum = '192'; +}; + + +#line 29 "../compat/pathfind.c" +export_func = { + name = 'pathfind'; + what = 'fild a file in a list of directories'; + ifndef = 'HAVE_PATHFIND'; + arg = { + arg_type = 'char const*'; + arg_name = 'path'; + arg_desc = 'colon separated list of search directories'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'file'; + arg_desc = 'the name of the file to look for'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'mode'; + arg_desc = 'the mode bits that must be set to match'; + }; + ret_type = 'char*'; + ret_desc = 'the path to the located file'; + doc = +'pathfind looks for a a file with name "FILE" and "MODE" access +along colon delimited "PATH", and returns the full pathname as a +string, or NULL if not found. If "FILE" contains a slash, then +it is treated as a relative or absolute path and "PATH" is ignored. + +@strong{NOTE}: this function is compiled into @file{libopts} only if +it is not natively supplied. + +The "MODE" argument is a string of option letters chosen from the +list below: +@example +Letter Meaning +r readable +w writable +x executable +f normal file (NOT IMPLEMENTED) +b block special (NOT IMPLEMENTED) +c character special (NOT IMPLEMENTED) +d directory (NOT IMPLEMENTED) +p FIFO (pipe) (NOT IMPLEMENTED) +u set user ID bit (NOT IMPLEMENTED) +g set group ID bit (NOT IMPLEMENTED) +k sticky bit (NOT IMPLEMENTED) +s size nonzero (NOT IMPLEMENTED) +@end example'; + example = +'To find the "ls" command using the "PATH" environment variable: +@example +#include <stdlib.h> +char* pz_ls = pathfind( getenv("PATH"), "ls", "rx" ); +<<do whatever with pz_ls>> +free( pz_ls ); +@end example +The path is allocated with @code{malloc(3C)}, so you must @code{free(3C)} +the result. Also, do not use unimplemented file modes. :-)'; + err = 'returns NULL if the file is not found.'; + srcfile = '../compat/pathfind.c'; + linenum = '29'; +}; + + +#line 209 "streqvcmp.c" +export_func = { + name = 'strequate'; + what = 'map a list of characters to the same value'; + arg = { + arg_type = 'char const*'; + arg_name = 'ch_list'; + arg_desc = 'characters to equivalence'; + }; + doc = +'Each character in the input string get mapped to the first character +in the string. +This function name is mapped to option_strequate so as to not conflict +with the POSIX name space.'; + err = 'none.'; + srcfile = 'streqvcmp.c'; + linenum = '209'; +}; + + +#line 119 "streqvcmp.c" +export_func = { + name = 'streqvcmp'; + what = 'compare two strings with an equivalence mapping'; + arg = { + arg_type = 'char const*'; + arg_name = 'str1'; + arg_desc = 'first string'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'str2'; + arg_desc = 'second string'; + }; + ret_type = 'int'; + ret_desc = 'the difference between two differing characters'; + doc = +'Using a character mapping, two strings are compared for "equivalence". +Each input character is mapped to a comparison character and the +mapped-to characters are compared for the two NUL terminated input strings. +This function name is mapped to option_streqvcmp so as to not conflict +with the POSIX name space.'; + err = 'none checked. Caller responsible for seg faults.'; + srcfile = 'streqvcmp.c'; + linenum = '119'; +}; + + +#line 156 "streqvcmp.c" +export_func = { + name = 'streqvmap'; + what = 'Set the character mappings for the streqv functions'; + arg = { + arg_type = 'char'; + arg_name = 'From'; + arg_desc = 'Input character'; + }; + arg = { + arg_type = 'char'; + arg_name = 'To'; + arg_desc = 'Mapped-to character'; + }; + arg = { + arg_type = 'int'; + arg_name = 'ct'; + arg_desc = 'compare length'; + }; + doc = +'Set the character mapping. If the count (@code{ct}) is set to zero, then +the map is cleared by setting all entries in the map to their index +value. Otherwise, the "@code{From}" character is mapped to the "@code{To}" +character. If @code{ct} is greater than 1, then @code{From} and @code{To} +are incremented and the process repeated until @code{ct} entries have been +set. For example, +@example +streqvmap(\'a\', \'A\', 26); +@end example +@noindent +will alter the mapping so that all English lower case letters +will map to upper case. + +This function name is mapped to option_streqvmap so as to not conflict +with the POSIX name space.'; + err = 'none.'; + srcfile = 'streqvcmp.c'; + linenum = '156'; +}; + + +#line 78 "streqvcmp.c" +export_func = { + name = 'strneqvcmp'; + what = 'compare two strings with an equivalence mapping'; + arg = { + arg_type = 'char const*'; + arg_name = 'str1'; + arg_desc = 'first string'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'str2'; + arg_desc = 'second string'; + }; + arg = { + arg_type = 'int'; + arg_name = 'ct'; + arg_desc = 'compare length'; + }; + ret_type = 'int'; + ret_desc = 'the difference between two differing characters'; + doc = +'Using a character mapping, two strings are compared for "equivalence". +Each input character is mapped to a comparison character and the +mapped-to characters are compared for the two NUL terminated input strings. +The comparison is limited to @code{ct} bytes. +This function name is mapped to option_strneqvcmp so as to not conflict +with the POSIX name space.'; + err = 'none checked. Caller responsible for seg faults.'; + srcfile = 'streqvcmp.c'; + linenum = '78'; +}; + + +#line 235 "streqvcmp.c" +export_func = { + name = 'strtransform'; + what = 'convert a string into its mapped-to value'; + arg = { + arg_type = 'char*'; + arg_name = 'dest'; + arg_desc = 'output string'; + }; + arg = { + arg_type = 'char const*'; + arg_name = 'src'; + arg_desc = 'input string'; + }; + doc = +'Each character in the input string is mapped and the mapped-to +character is put into the output. +This function name is mapped to option_strtransform so as to not conflict +with the POSIX name space. + +The source and destination may be the same.'; + err = 'none.'; + srcfile = 'streqvcmp.c'; + linenum = '235'; +}; + + +#line 244 "text_mmap.c" +export_func = { + name = 'text_mmap'; + private; + what = 'map a text file with terminating NUL'; + arg = { + arg_type = 'char const*'; + arg_name = 'pzFile'; + arg_desc = 'name of the file to map'; + }; + arg = { + arg_type = 'int'; + arg_name = 'prot'; + arg_desc = 'mmap protections (see mmap(2))'; + }; + arg = { + arg_type = 'int'; + arg_name = 'flags'; + arg_desc = 'mmap flags (see mmap(2))'; + }; + arg = { + arg_type = 'tmap_info_t*'; + arg_name = 'mapinfo'; + arg_desc = 'returned info about the mapping'; + }; + ret-type = 'void*'; + ret-desc = 'The mmaped data address'; + doc = +'This routine will mmap a file into memory ensuring that there is at least +one @file{NUL} character following the file data. It will return the +address where the file contents have been mapped into memory. If there is a +problem, then it will return @code{MAP_FAILED} and set @code{errno} +appropriately. + +The named file does not exist, @code{stat(2)} will set @code{errno} as it +will. If the file is not a regular file, @code{errno} will be +@code{EINVAL}. At that point, @code{open(2)} is attempted with the access +bits set appropriately for the requested @code{mmap(2)} protections and flag +bits. On failure, @code{errno} will be set according to the documentation +for @code{open(2)}. If @code{mmap(2)} fails, @code{errno} will be set as +that routine sets it. If @code{text_mmap} works to this point, a valid +address will be returned, but there may still be ``issues\'\'. + +If the file size is not an even multiple of the system page size, then +@code{text_map} will return at this point and @code{errno} will be zero. +Otherwise, an anonymous map is attempted. If not available, then an attempt +is made to @code{mmap(2)} @file{/dev/zero}. If any of these fail, the +address of the file\'s data is returned, bug @code{no} @file{NUL} characters +are mapped after the end of the data.'; + see = 'mmap(2), open(2), stat(2)'; + err = 'Any error code issued by mmap(2), open(2), stat(2) is possible. +Additionally, if the specified file is not a regular file, then +errno will be set to @code{EINVAL}.'; + example = +'#include <mylib.h> +tmap_info_t mi; +int no_nul; +void* data = text_mmap("file", PROT_WRITE, MAP_PRIVATE, &mi); +if (data == MAP_FAILED) return; +no_nul = (mi.txt_size == mi.txt_full_size); +<< use the data >> +text_munmap(&mi);'; + srcfile = 'text_mmap.c'; + linenum = '244'; +}; + + +#line 317 "text_mmap.c" +export_func = { + name = 'text_munmap'; + private; + what = 'unmap the data mapped in by text_mmap'; + arg = { + arg_type = 'tmap_info_t*'; + arg_name = 'mapinfo'; + arg_desc = 'info about the mapping'; + }; + ret-type = 'int'; + ret-desc = '-1 or 0. @code{errno} will have the error code.'; + doc = +'This routine will unmap the data mapped in with @code{text_mmap} and close +the associated file descriptors opened by that function.'; + see = 'munmap(2), close(2)'; + err = 'Any error code issued by munmap(2) or close(2) is possible.'; + srcfile = 'text_mmap.c'; + linenum = '317'; +}; +vers-curr = "147461"; +vers-min = "102400"; +vers-min-str = "25:0:0"; +vers-sovers = "36:5:11"; +library = opts; + +/* + * THIS FILE IS DISTRIBUTED + * + * This file is used to construct options.h + doc files. Because it is + * such a nuisance to get the build ordering correct, we distribute + * this. It should be constructed after all binaries are built. + */ diff --git a/autoopts/genshell.c b/autoopts/genshell.c new file mode 100644 index 0000000..2762088 --- /dev/null +++ b/autoopts/genshell.c @@ -0,0 +1,452 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (genshell.c) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:14 AM by AutoGen 5.16.2pre7 + * From the definitions genshell.def + * and the template file options + * + * Generated from AutoOpts 36:5:11 templates. + * + * AutoOpts is a copyrighted work. This source file is not encumbered + * by AutoOpts licensing, but is provided under the licensing terms chosen + * by the genshellopt author or copyright holder. AutoOpts is + * licensed under the terms of the LGPL. The redistributable library + * (``libopts'') is licensed under the terms of either the LGPL or, at the + * users discretion, the BSD license. See the AutoOpts and/or libopts sources + * for details. + * + * The genshellopt program is copyrighted and licensed + * under the following terms: + * + * Copyright (C) 1999-2012 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * GNU General Public License, version 3 or later + * <http://gnu.org/licenses/gpl.html> + * + * genshellopt is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * genshellopt is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __doxygen__ +#define OPTION_CODE_COMPILE 1 +#include "genshell.h" +#include <sys/types.h> + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif +extern FILE * option_usage_fp; + +/* TRANSLATORS: choose the translation for option names wisely because you + cannot ever change your mind. */ +#define zCopyright (genshellopt_opt_strs+0) +#define zLicenseDescrip (genshellopt_opt_strs+260) + +extern tUsageProc genshelloptUsage; + +#ifndef NULL +# define NULL 0 +#endif + +/* + * genshellopt option static const strings + */ +static char const genshellopt_opt_strs[1690] = +/* 0 */ "genshellopt 1\n" + "Copyright (C) 1999-2012 Bruce Korb, all rights reserved.\n" + "This is free software. It is licensed for use, modification and\n" + "redistribution under the terms of the\n" + "GNU General Public License, version 3 or later\n" + " <http://gnu.org/licenses/gpl.html>\n\0" +/* 260 */ "genshellopt is free software: you can redistribute it and/or modify it\n" + "under the terms of the GNU General Public License as published by the Free\n" + "Software Foundation, either version 3 of the License, or (at your option)\n" + "any later version.\n\n" + "genshellopt is distributed in the hope that it will be useful, but WITHOUT\n" + "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n" + "FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n" + "more details.\n\n" + "You should have received a copy of the GNU General Public License along\n" + "with this program. If not, see <http://www.gnu.org/licenses/>.\n\0" +/* 871 */ "Output Script File\0" +/* 890 */ "SCRIPT\0" +/* 897 */ "script\0" +/* 904 */ "Shell name (follows \"#!\" magic)\0" +/* 936 */ "SHELL\0" +/* 942 */ "no-shell\0" +/* 951 */ "no\0" +/* 954 */ "Display extended usage information and exit\0" +/* 998 */ "help\0" +/* 1003 */ "Extended usage information passed thru pager\0" +/* 1048 */ "more-help\0" +/* 1058 */ "Output version information and exit\0" +/* 1094 */ "version\0" +/* 1102 */ "GENSHELLOPT\0" +/* 1114 */ "genshellopt - Generate Shell Option Processing Script - Ver. 1\n" + "USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0" +/* 1235 */ "autogen-users@lists.sourceforge.net\0" +/* 1271 */ "\n" + "Note that ``shell'' is only useful if the output file does not already\n" + "exist. If it does, then the shell name and optional first argument will be\n" + "extracted from the script file.\n\0" +/* 1452 */ "\n" + "If the script file already exists and contains Automated Option Processing\n" + "text, the second line of the file through the ending tag will be replaced\n" + "by the newly generated text. The first ``#!'' line will be regenerated.\n\0" +/* 1676 */ "genshellopt 1"; + +/* + * script option description: + */ +#define SCRIPT_DESC (genshellopt_opt_strs+871) +#define SCRIPT_NAME (genshellopt_opt_strs+890) +#define SCRIPT_name (genshellopt_opt_strs+897) +#define SCRIPT_FLAGS (OPTST_DISABLED \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)) + +/* + * shell option description: + */ +#define SHELL_DESC (genshellopt_opt_strs+904) +#define SHELL_NAME (genshellopt_opt_strs+936) +#define NOT_SHELL_name (genshellopt_opt_strs+942) +#define NOT_SHELL_PFX (genshellopt_opt_strs+951) +#define SHELL_name (NOT_SHELL_name + 3) +#define SHELL_FLAGS (OPTST_INITENABLED \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)) + +/* + * Help/More_Help/Version option descriptions: + */ +#define HELP_DESC (genshellopt_opt_strs+954) +#define HELP_name (genshellopt_opt_strs+998) +#ifdef HAVE_WORKING_FORK +#define MORE_HELP_DESC (genshellopt_opt_strs+1003) +#define MORE_HELP_name (genshellopt_opt_strs+1048) +#define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +#define MORE_HELP_DESC NULL +#define MORE_HELP_name NULL +#define MORE_HELP_FLAGS (OPTST_OMITTED | OPTST_NO_INIT) +#endif +#ifdef NO_OPTIONAL_OPT_ARGS +# define VER_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +# define VER_FLAGS (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \ + OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT) +#endif +#define VER_DESC (genshellopt_opt_strs+1058) +#define VER_name (genshellopt_opt_strs+1094) +/* + * Declare option callback procedures + */ +extern tOptProc + optionBooleanVal, optionNestedVal, optionNumericVal, + optionPagedUsage, optionPrintVersion, optionResetOpt, + optionStackArg, optionTimeDate, optionTimeVal, + optionUnstackArg, optionVendorOption; +static tOptProc + doUsageOpt; +#define VER_PROC optionPrintVersion + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Define the genshellopt Option Descriptions. + * This is an array of GENSHELL_OPTION_CT entries, one for each + * option that the genshellopt program responds to. + */ +static tOptDesc optDesc[GENSHELL_OPTION_CT] = { + { /* entry idx, value */ 0, VALUE_GENSHELL_OPT_SCRIPT, + /* equiv idx, value */ 0, VALUE_GENSHELL_OPT_SCRIPT, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ SCRIPT_FLAGS, 0, + /* last opt argumnt */ { NULL }, /* --script */ + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ NULL, + /* desc, NAME, name */ SCRIPT_DESC, SCRIPT_NAME, SCRIPT_name, + /* disablement strs */ NULL, NULL }, + + { /* entry idx, value */ 1, VALUE_GENSHELL_OPT_SHELL, + /* equiv idx, value */ 1, VALUE_GENSHELL_OPT_SHELL, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ SHELL_FLAGS, 0, + /* last opt argumnt */ { NULL }, /* --shell */ + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ NULL, + /* desc, NAME, name */ SHELL_DESC, SHELL_NAME, SHELL_name, + /* disablement strs */ NOT_SHELL_name, NOT_SHELL_PFX }, + + { /* entry idx, value */ INDEX_GENSHELL_OPT_VERSION, VALUE_GENSHELL_OPT_VERSION, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_VERSION, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ VER_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ VER_PROC, + /* desc, NAME, name */ VER_DESC, NULL, VER_name, + /* disablement strs */ NULL, NULL }, + + + + { /* entry idx, value */ INDEX_GENSHELL_OPT_HELP, VALUE_GENSHELL_OPT_HELP, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ doUsageOpt, + /* desc, NAME, name */ HELP_DESC, NULL, HELP_name, + /* disablement strs */ NULL, NULL }, + + { /* entry idx, value */ INDEX_GENSHELL_OPT_MORE_HELP, VALUE_GENSHELL_OPT_MORE_HELP, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_MORE_HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ MORE_HELP_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionPagedUsage, + /* desc, NAME, name */ MORE_HELP_DESC, NULL, MORE_HELP_name, + /* disablement strs */ NULL, NULL } +}; + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Define the genshellopt Option Environment + */ +#define zPROGNAME (genshellopt_opt_strs+1102) +#define zUsageTitle (genshellopt_opt_strs+1114) +#define zRcName NULL +#define apzHomeList NULL +#define zBugsAddr (genshellopt_opt_strs+1235) +#define zExplain (genshellopt_opt_strs+1271) +#define zDetail (genshellopt_opt_strs+1452) +#define zFullVersion (genshellopt_opt_strs+1676) +/* extracted from optcode.tlib near line 350 */ + +#if defined(ENABLE_NLS) +# define OPTPROC_BASE OPTPROC_TRANSLATE + static tOptionXlateProc translate_option_strings; +#else +# define OPTPROC_BASE OPTPROC_NONE +# define translate_option_strings NULL +#endif /* ENABLE_NLS */ + + +#define genshellopt_full_usage (NULL) + +#define genshellopt_short_usage (NULL) + +#endif /* not defined __doxygen__ */ + +/* + * Create the static procedure(s) declared above. + */ +/** + * The callout function that invokes the genshelloptUsage function. + * + * @param pOptions the AutoOpts option description structure + * @param pOptDesc the descriptor for the "help" (usage) option. + * @noreturn + */ +static void +doUsageOpt(tOptions * pOptions, tOptDesc * pOptDesc) +{ + genshelloptUsage(&genshelloptOptions, GENSHELLOPT_EXIT_SUCCESS); + /* NOTREACHED */ + (void)pOptDesc; + (void)pOptions; +} +/* extracted from optmain.tlib near line 1146 */ + +/** + * The directory containing the data associated with genshellopt. + */ +#ifndef PKGDATADIR +# define PKGDATADIR "" +#endif + +/** + * Information about the person or institution that packaged genshellopt + * for the current distribution. + */ +#ifndef WITH_PACKAGER +# define genshellopt_packager_info NULL +#else +static char const genshellopt_packager_info[] = + "Packaged by " WITH_PACKAGER + +# ifdef WITH_PACKAGER_VERSION + " ("WITH_PACKAGER_VERSION")" +# endif + +# ifdef WITH_PACKAGER_BUG_REPORTS + "\nReport genshellopt bugs to " WITH_PACKAGER_BUG_REPORTS +# endif + "\n"; +#endif +#ifndef __doxygen__ + +#endif /* __doxygen__ */ +/** + * The option definitions for genshellopt. The one structure that + * binds them all. + */ +tOptions genshelloptOptions = { + OPTIONS_STRUCT_VERSION, + 0, NULL, /* original argc + argv */ + ( OPTPROC_BASE + + OPTPROC_ERRSTOP + + OPTPROC_SHORTOPT + + OPTPROC_LONGOPT + + OPTPROC_NO_REQ_OPT + + OPTPROC_NEGATIONS + + OPTPROC_NO_ARGS ), + 0, NULL, /* current option index, current option */ + NULL, NULL, zPROGNAME, + zRcName, zCopyright, zLicenseDescrip, + zFullVersion, apzHomeList, zUsageTitle, + zExplain, zDetail, optDesc, + zBugsAddr, /* address to send bugs to */ + NULL, NULL, /* extensions/saved state */ + genshelloptUsage, /* usage procedure */ + translate_option_strings, /* translation procedure */ + /* + * Indexes to special options + */ + { INDEX_GENSHELL_OPT_MORE_HELP, /* more-help option index */ + NO_EQUIVALENT, /* save option index */ + NO_EQUIVALENT, /* '-#' option index */ + NO_EQUIVALENT /* index of default opt */ + }, + 5 /* full option count */, 2 /* user option count */, + genshellopt_full_usage, genshellopt_short_usage, + NULL, NULL, + PKGDATADIR, genshellopt_packager_info +}; + +#if ENABLE_NLS +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <autoopts/usage-txt.h> + +static char* AO_gettext(char const* pz); +static void coerce_it(void** s); + +/** + * AutoGen specific wrapper function for gettext. + * It relies on the macro _() to convert from English to the target + * language, then strdup-duplicates the result string. + * + * @param[in] pz the input text used as a lookup key. + * @returns the translated text (if there is one), + * or the original text (if not). + */ +static char * +AO_gettext(char const* pz) +{ + char* pzRes; + if (pz == NULL) + return NULL; + pzRes = _(pz); + if (pzRes == pz) + return pzRes; + pzRes = strdup(pzRes); + if (pzRes == NULL) { + fputs(_("No memory for duping translated strings\n"), stderr); + exit(GENSHELLOPT_EXIT_FAILURE); + } + return pzRes; +} + +static void coerce_it(void** s) { *s = AO_gettext(*s); +} + +/** + * Translate all the translatable strings in the genshelloptOptions + * structure defined above. This is done only once. + */ +static void +translate_option_strings(void) +{ + tOptions * const pOpt = &genshelloptOptions; + + /* + * Guard against re-translation. It won't work. The strings will have + * been changed by the first pass through this code. One shot only. + */ + if (option_usage_text.field_ct != 0) { + /* + * Do the translations. The first pointer follows the field count + * field. The field count field is the size of a pointer. + */ + tOptDesc * pOD = pOpt->pOptDesc; + char ** ppz = (char**)(void*)&(option_usage_text); + int ix = option_usage_text.field_ct; + + do { + ppz++; + *ppz = AO_gettext(*ppz); + } while (--ix > 0); + + coerce_it((void*)&(pOpt->pzCopyright)); + coerce_it((void*)&(pOpt->pzCopyNotice)); + coerce_it((void*)&(pOpt->pzFullVersion)); + coerce_it((void*)&(pOpt->pzUsageTitle)); + coerce_it((void*)&(pOpt->pzExplain)); + coerce_it((void*)&(pOpt->pzDetail)); + coerce_it((void*)&(pOpt->pzPackager)); + option_usage_text.field_ct = 0; + + for (ix = pOpt->optCt; ix > 0; ix--, pOD++) + coerce_it((void*)&(pOD->pzText)); + } + + if ((pOpt->fOptSet & OPTPROC_NXLAT_OPT_CFG) == 0) { + tOptDesc * pOD = pOpt->pOptDesc; + int ix; + + for (ix = pOpt->optCt; ix > 0; ix--, pOD++) { + coerce_it((void*)&(pOD->pz_Name)); + coerce_it((void*)&(pOD->pz_DisableName)); + coerce_it((void*)&(pOD->pz_DisablePfx)); + } + /* prevent re-translation */ + genshelloptOptions.fOptSet |= OPTPROC_NXLAT_OPT_CFG | OPTPROC_NXLAT_OPT; + } +} + +#endif /* ENABLE_NLS */ + +#ifdef __cplusplus +} +#endif +/* genshell.c ends here */ diff --git a/autoopts/genshell.def b/autoopts/genshell.def new file mode 100644 index 0000000..e679b5f --- /dev/null +++ b/autoopts/genshell.def @@ -0,0 +1,79 @@ + +autogen definitions options; + +/** + * \file genshell.def + * + * Time-stamp: "2012-01-29 13:32:43 bkorb" + * + * This module generates shell scripts with AutoOpts supported command line + * option processing. This program is licensed separately from the AutoOpts + * library and is _only_ available under the terms of the GNU General + * Public License. + * + * Genshell Copyright (c) 1999-2012 by Bruce Korb - all rights reserved + * Genshell is free software. + * This file is part of AutoGen. + * + * AutoGen copyright (c) 1992-2012 by Bruce Korb - all rights reserved + * + * AutoGen is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AutoGen is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +copyright = { + date = "1999-2012"; + owner = "Bruce Korb"; + eaddr = "autogen-users@lists.sourceforge.net"; + type = gpl; +}; + +owner = "Bruce Korb"; +prog-name = "genshellopt"; +prog-title = "Generate Shell Option Processing Script"; +long-opts; +usage = genshelloptUsage; +prefix = genshell; + +version = 1; + +flag = { + name = script; + value = o; + arg-type = string; + descrip = "Output Script File"; +}; + +flag = { + name = shell; + disable = no; + enabled; + value = s; + arg-type = string; + descrip = 'Shell name (follows "#!" magic)'; +}; + +option-doc-format = texi; + +explain =<<- _EOF_ + Note that @code{shell} is only useful if the output file does not + already exist. If it does, then the shell name and optional first + argument will be extracted from the script file. + _EOF_; + +detail =<<- _EOF_ + If the script file already exists and contains Automated Option + Processing text, the second line of the file through the ending tag + will be replaced by the newly generated text. The first @code{#!} + line will be regenerated. + _EOF_; diff --git a/autoopts/genshell.h b/autoopts/genshell.h new file mode 100644 index 0000000..2b28efb --- /dev/null +++ b/autoopts/genshell.h @@ -0,0 +1,184 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (genshell.h) + * + * It has been AutoGen-ed August 11, 2012 at 09:41:14 AM by AutoGen 5.16.2pre7 + * From the definitions genshell.def + * and the template file options + * + * Generated from AutoOpts 36:5:11 templates. + * + * AutoOpts is a copyrighted work. This header file is not encumbered + * by AutoOpts licensing, but is provided under the licensing terms chosen + * by the genshellopt author or copyright holder. AutoOpts is + * licensed under the terms of the LGPL. The redistributable library + * (``libopts'') is licensed under the terms of either the LGPL or, at the + * users discretion, the BSD license. See the AutoOpts and/or libopts sources + * for details. + * + * The genshellopt program is copyrighted and licensed + * under the following terms: + * + * Copyright (C) 1999-2012 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * GNU General Public License, version 3 or later + * <http://gnu.org/licenses/gpl.html> + * + * genshellopt is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * genshellopt is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file contains the programmatic interface to the Automated + * Options generated for the genshellopt program. + * These macros are documented in the AutoGen info file in the + * "AutoOpts" chapter. Please refer to that doc for usage help. + */ +#ifndef AUTOOPTS_GENSHELL_H_GUARD +#define AUTOOPTS_GENSHELL_H_GUARD 1 +#include <autoopts/options.h> + +/* + * Ensure that the library used for compiling this generated header is at + * least as new as the version current when the header template was released + * (not counting patch version increments). Also ensure that the oldest + * tolerable version is at least as old as what was current when the header + * template was released. + */ +#define AO_TEMPLATE_VERSION 147461 +#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \ + || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION) +# error option template version mismatches autoopts/options.h header + Choke Me. +#endif + +/* + * Enumeration of each option: + */ +typedef enum { + INDEX_GENSHELL_OPT_SCRIPT = 0, + INDEX_GENSHELL_OPT_SHELL = 1, + INDEX_GENSHELL_OPT_VERSION = 2, + INDEX_GENSHELL_OPT_HELP = 3, + INDEX_GENSHELL_OPT_MORE_HELP = 4 +} teGenshell_OptIndex; + +#define GENSHELL_OPTION_CT 5 +#define GENSHELLOPT_VERSION "1" +#define GENSHELLOPT_FULL_VERSION "genshellopt 1" + +/* + * Interface defines for all options. Replace "n" with the UPPER_CASED + * option name (as in the teGenshell_OptIndex enumeration above). + * e.g. HAVE_GENSHELL_OPT(SCRIPT) + */ +#define GENSHELL_DESC(n) (genshelloptOptions.pOptDesc[INDEX_GENSHELL_OPT_## n]) +#define HAVE_GENSHELL_OPT(n) (! UNUSED_OPT(& GENSHELL_DESC(n))) +#define GENSHELL_OPT_ARG(n) (GENSHELL_DESC(n).optArg.argString) +#define STATE_GENSHELL_OPT(n) (GENSHELL_DESC(n).fOptState & OPTST_SET_MASK) +#define COUNT_GENSHELL_OPT(n) (GENSHELL_DESC(n).optOccCt) +#define ISSEL_GENSHELL_OPT(n) (SELECTED_OPT(&GENSHELL_DESC(n))) +#define ISUNUSED_GENSHELL_OPT(n) (UNUSED_OPT(& GENSHELL_DESC(n))) +#define ENABLED_GENSHELL_OPT(n) (! DISABLED_OPT(& GENSHELL_DESC(n))) +#define STACKCT_GENSHELL_OPT(n) (((tArgList*)(GENSHELL_DESC(n).optCookie))->useCt) +#define STACKLST_GENSHELL_OPT(n) (((tArgList*)(GENSHELL_DESC(n).optCookie))->apzArgs) +#define CLEAR_GENSHELL_OPT(n) STMTS( \ + GENSHELL_DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \ + if ((GENSHELL_DESC(n).fOptState & OPTST_INITENABLED) == 0) \ + GENSHELL_DESC(n).fOptState |= OPTST_DISABLED; \ + GENSHELL_DESC(n).optCookie = NULL ) + +/* * * * * * + * + * Enumeration of genshellopt exit codes + */ +typedef enum { + GENSHELLOPT_EXIT_SUCCESS = 0, + GENSHELLOPT_EXIT_FAILURE = 1, + GENSHELLOPT_EXIT_LIBOPTS_FAILURE = 70 +} genshellopt_exit_code_t; +/* * * * * * + * + * Interface defines for specific options. + */ +#define VALUE_GENSHELL_OPT_SCRIPT 'o' +#define VALUE_GENSHELL_OPT_SHELL 's' +#define VALUE_GENSHELL_OPT_HELP '?' +#define VALUE_GENSHELL_OPT_MORE_HELP '!' +#define VALUE_GENSHELL_OPT_VERSION 'v' +/* + * Interface defines not associated with particular options + */ +#define ERRSKIP_GENSHELL_OPTERR STMTS(genshelloptOptions.fOptSet &= ~OPTPROC_ERRSTOP) +#define ERRSTOP_GENSHELL_OPTERR STMTS(genshelloptOptions.fOptSet |= OPTPROC_ERRSTOP) +#define RESTART_GENSHELL_OPT(n) STMTS( \ + genshelloptOptions.curOptIdx = (n); \ + genshelloptOptions.pzCurOpt = NULL ) +#define START_GENSHELL_OPT RESTART_GENSHELL_OPT(1) +#define GENSHELL_USAGE(c) (*genshelloptOptions.pUsageProc)(&genshelloptOptions, c) +/* extracted from opthead.tlib near line 484 */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* * * * * * + * + * Declare the genshellopt option descriptor. + */ +extern tOptions genshelloptOptions; + +#if defined(ENABLE_NLS) +# ifndef _ +# include <stdio.h> +# ifndef HAVE_GETTEXT + extern char * gettext(char const *); +# else +# include <libintl.h> +# endif + +static inline char* aoGetsText(char const* pz) { + if (pz == NULL) return NULL; + return (char*)gettext(pz); +} +# define _(s) aoGetsText(s) +# endif /* _() */ + +# define OPT_NO_XLAT_CFG_NAMES STMTS(genshelloptOptions.fOptSet |= \ + OPTPROC_NXLAT_OPT_CFG;) +# define OPT_NO_XLAT_OPT_NAMES STMTS(genshelloptOptions.fOptSet |= \ + OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG;) + +# define OPT_XLAT_CFG_NAMES STMTS(genshelloptOptions.fOptSet &= \ + ~(OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG);) +# define OPT_XLAT_OPT_NAMES STMTS(genshelloptOptions.fOptSet &= \ + ~OPTPROC_NXLAT_OPT;) + +#else /* ENABLE_NLS */ +# define OPT_NO_XLAT_CFG_NAMES +# define OPT_NO_XLAT_OPT_NAMES + +# define OPT_XLAT_CFG_NAMES +# define OPT_XLAT_OPT_NAMES + +# ifndef _ +# define _(_s) _s +# endif +#endif /* ENABLE_NLS */ + +#ifdef __cplusplus +} +#endif +#endif /* AUTOOPTS_GENSHELL_H_GUARD */ +/* genshell.h ends here */ diff --git a/autoopts/gettext.h b/autoopts/gettext.h new file mode 100644 index 0000000..151ba4f --- /dev/null +++ b/autoopts/gettext.h @@ -0,0 +1,288 @@ +/* Convenience header for conditional use of GNU <libintl.h>. + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2012 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along + with this program; if not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include <libintl.h> + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is OK. */ +#if defined(__sun) +# include <locale.h> +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + <libintl.h>, which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of <libintl.h> a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include <cstdlib> +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include <libintl.h> +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include <string.h> + +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || __STDC_VERSION__ >= 199901L */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include <stdlib.h> +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (translation != msg_ctxt_id) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (!(translation == msg_ctxt_id || translation == msgid_plural)) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/autoopts/install-hook.sh b/autoopts/install-hook.sh new file mode 100644 index 0000000..a987b7b --- /dev/null +++ b/autoopts/install-hook.sh @@ -0,0 +1,124 @@ +#! /bin/sh + +# Time-stamp: "2012-08-11 08:13:30 bkorb" +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 by Bruce Korb - all rights reserved +## +## AutoOpts is available under either 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +egrep '#undef +AUTOOPTS_ENABLED' ${top_builddir}/config.h >/dev/null && \ + exit 0 + +srcdir=`dirname $0` +srcdir=`cd ${srcdir} ; pwd` + +. ${top_builddir}/autoopts/test/defs + +test -z "${POSIX_SHELL}" && exit 1 + +rm -f ${DESTdestdir}/options.h +opthdrsrc=${srcdir}/autoopts/options.h +cfgf=${top_builddir}/config.h + +{ + sed '/^#include <stdio/q' ${opthdrsrc} + + if ${EGREP} 'define +HAVE_STDINT_H' ${cfgf} >/dev/null + then echo '#include <stdint.h>' + else echo '#include <inttypes.h>' ; fi + + if ${EGREP} 'define +HAVE_LIMITS_H' ${cfgf} >/dev/null + then echo '#include <limits.h>' + else echo '#include <sys/limits.h>' ; fi + + if ${EGREP} 'define +HAVE_STDBOOL_H' ${cfgf} >/dev/null + then echo '#include <stdbool.h>' + else cat <<- _EOF_ + typedef enum { false = 0, true = 1 } _Bool; + #define bool _Bool + #define true 1 + #define false 0 + _EOF_ + fi + + ${EGREP} 'define +NO_OPTIONAL_OPT_ARGS' ${cfgf} + + if ${EGREP} 'define +HAVE_INTPTR_T' ${cfgf} >/dev/null + then : + else + sizeof_charp=`${EGREP} 'define +SIZEOF_CHARP ' ${cfgf} | \ + sed 's/.*SIZEOF_CHARP *//'` + sizeof_long=` ${EGREP} 'define +SIZEOF_LONG ' ${cfgf} | \ + sed 's/.*SIZEOF_LONG *//'` + if test "X${sizeof_charp}" = "X${sizeof_long}" + then ptrtype=long + else ptrtype=int + fi + cat <<- _EOF_ + #ifndef HAVE_UINTPTR_T + #define HAVE_UINTPTR_T 1 + #define HAVE_INTPTR_T 1 + typedef $ptrtype intptr_t; + typedef unsigned $ptrtype uintptr_t; + #endif /* HAVE_UINTPTR_T */ + _EOF_ + fi + + sedcmd='1,/END-CONFIGURED-HEADERS/d' + + if ${EGREP} 'define +HAVE_PATHFIND' ${cfgf} >/dev/null + then nopathfind='/From:.*pathfind\.c/,/#endif.*HAVE_PATHFIND/d' + else nopathfind='/HAVE_PATHFIND/d' ; fi + + sed "${sedcmd};${nopathfind}" ${opthdrsrc} +} > ${DESTdestdir}/options.h + +test -d "${DESTpkgdatadir}" && { + rmbuild='/# *START-BUILDTREE-ISMS/,/# *END-BUILDTREE-ISMS/d + /# *END-INSTALL-ONLY-CODE/d + /^##/d' + + cd ${DESTpkgdatadir} + for f in * + do case "$f" in + optlib.tlib | getopt.tpl | usage.tlib | cmd-doc.tlib | \ + agtexi-cmd.tpl | agman1.tpl | aginfo.tpl ) + sed "${rmbuild}" $f > $f.tmp + mv -f $f.tmp $f + ;; + + *.* ) : ;; + * ) + chmod a+x $f + ;; + esac + done +} + +## Local Variables: +## Mode: shell-script +## indent-tabs-mode: nil +## sh-basic-offset: 4 +## sh-indent-after-do: 4 +## sh-indentation: 4 +## sh-indent-for-case-label: 0 +## sh-indent-for-case-alt: 4 +## End: + +# end of install-hook.sh diff --git a/autoopts/load.c b/autoopts/load.c new file mode 100644 index 0000000..06b0079 --- /dev/null +++ b/autoopts/load.c @@ -0,0 +1,519 @@ + +/** + * \file load.c + * Time-stamp: "2012-08-11 08:20:09 bkorb" + * + * This file contains the routines that deal with processing text strings + * for options, either from a NUL-terminated string passed in or from an + * rc/ini file. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static bool +add_prog_path(char * pzBuf, int bufSize, char const * pzName, + char const * pzProgPath); + +static bool +add_env_val(char * buf, int buf_sz, char const * name); + +static char * +assemble_arg_val(char * txt, tOptionLoadMode mode); +/* = = = END-STATIC-FORWARD = = = */ + +/*=export_func optionMakePath + * private: + * + * what: translate and construct a path + * arg: + char* + pzBuf + The result buffer + + * arg: + int + bufSize + The size of this buffer + + * arg: + char const* + pzName + The input name + + * arg: + char const* + pzProgPath + The full path of the current program + + * + * ret-type: bool + * ret-desc: true if the name was handled, otherwise false. + * If the name does not start with ``$'', then it is handled + * simply by copying the input name to the output buffer and + * resolving the name with either + * @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}. + * + * doc: + * + * This routine will copy the @code{pzName} input name into the + * @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the + * first character of the input name is a @code{'$'} character, then there + * is special handling: + * @* + * @code{$$} is replaced with the directory name of the @code{pzProgPath}, + * searching @code{$PATH} if necessary. + * @* + * @code{$@} is replaced with the AutoGen package data installation directory + * (aka @code{pkgdatadir}). + * @* + * @code{$NAME} is replaced by the contents of the @code{NAME} environment + * variable. If not found, the search fails. + * + * Please note: both @code{$$} and @code{$NAME} must be at the start of the + * @code{pzName} string and must either be the entire string or be followed + * by the @code{'/'} (backslash on windows) character. + * + * err: @code{false} is returned if: + * @* + * @bullet{} The input name exceeds @code{bufSize} bytes. + * @* + * @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string + * and the next character is not '/'. + * @* + * @bullet{} libopts was built without PKGDATADIR defined and @code{$@@} + * was specified. + * @* + * @bullet{} @code{NAME} is not a known environment variable + * @* + * @bullet{} @code{canonicalize_file_name} or @code{realpath} return + * errors (cannot resolve the resulting path). +=*/ +bool +optionMakePath(char * pzBuf, int bufSize, char const * pzName, + char const * pzProgPath) +{ + size_t name_len = strlen(pzName); + + if (((size_t)bufSize <= name_len) || (name_len == 0)) + return false; + + /* + * IF not an environment variable, just copy the data + */ + if (*pzName != '$') { + char const* pzS = pzName; + char* pzD = pzBuf; + int ct = bufSize; + + for (;;) { + if ( (*(pzD++) = *(pzS++)) == NUL) + break; + if (--ct <= 0) + return false; + } + } + + /* + * IF the name starts with "$$", then it must be "$$" or + * it must start with "$$/". In either event, replace the "$$" + * with the path to the executable and append a "/" character. + */ + else switch (pzName[1]) { + case NUL: + return false; + + case '$': + if (! add_prog_path(pzBuf, bufSize, pzName, pzProgPath)) + return false; + break; + + case '@': + if (program_pkgdatadir[0] == NUL) + return false; + + if (snprintf(pzBuf, bufSize, "%s%s", program_pkgdatadir, pzName + 2) + >= bufSize) + return false; + break; + + default: + if (! add_env_val(pzBuf, bufSize, pzName)) + return false; + } + +#if defined(HAVE_CANONICALIZE_FILE_NAME) + { + char * pz = canonicalize_file_name(pzBuf); + if (pz == NULL) + return false; + + name_len = strlen(pz); + if (name_len >= (size_t)bufSize) { + free(pz); + return false; + } + + memcpy(pzBuf, pz, name_len + 1); + free(pz); + } + +#elif defined(HAVE_REALPATH) + { + char z[PATH_MAX+1]; + + if (realpath(pzBuf, z) == NULL) + return false; + + name_len = strlen(z); + if (name_len >= bufSize) + return false; + + memcpy(pzBuf, z, name_len + 1); + } +#endif + + return true; +} + +static bool +add_prog_path(char * pzBuf, int bufSize, char const * pzName, + char const * pzProgPath) +{ + char const* pzPath; + char const* pz; + int skip = 2; + + switch (pzName[2]) { + case DIRCH: + skip = 3; + case NUL: + break; + default: + return false; + } + + /* + * See if the path is included in the program name. + * If it is, we're done. Otherwise, we have to hunt + * for the program using "pathfind". + */ + if (strchr(pzProgPath, DIRCH) != NULL) + pzPath = pzProgPath; + else { + pzPath = pathfind(getenv("PATH"), (char*)pzProgPath, "rx"); + + if (pzPath == NULL) + return false; + } + + pz = strrchr(pzPath, DIRCH); + + /* + * IF we cannot find a directory name separator, + * THEN we do not have a path name to our executable file. + */ + if (pz == NULL) + return false; + + pzName += skip; + + /* + * Concatenate the file name to the end of the executable path. + * The result may be either a file or a directory. + */ + if ((pz - pzPath)+1 + strlen(pzName) >= (unsigned)bufSize) + return false; + + memcpy(pzBuf, pzPath, (size_t)((pz - pzPath)+1)); + strcpy(pzBuf + (pz - pzPath) + 1, pzName); + + /* + * If the "pzPath" path was gotten from "pathfind()", then it was + * allocated and we need to deallocate it. + */ + if (pzPath != pzProgPath) + AGFREE(pzPath); + return true; +} + +static bool +add_env_val(char * buf, int buf_sz, char const * name) +{ + char * dir_part = buf; + + for (;;) { + int ch = (int)*++name; + if (! IS_VALUE_NAME_CHAR(ch)) + break; + *(dir_part++) = (char)ch; + } + + if (dir_part == buf) + return false; + + *dir_part = NUL; + + dir_part = getenv(buf); + + /* + * Environment value not found -- skip the home list entry + */ + if (dir_part == NULL) + return false; + + if (strlen(dir_part) + 1 + strlen(name) >= (unsigned)buf_sz) + return false; + + sprintf(buf, "%s%s", dir_part, name); + return true; +} + +LOCAL void +mungeString(char * txt, tOptionLoadMode mode) +{ + char * pzE; + + if (mode == OPTION_LOAD_KEEP) + return; + + if (IS_WHITESPACE_CHAR(*txt)) { + char * pzS = SPN_WHITESPACE_CHARS(txt+1); + size_t l = strlen(pzS) + 1; + memmove(txt, pzS, l); + pzE = txt + l - 1; + + } else + pzE = txt + strlen(txt); + + pzE = SPN_WHITESPACE_BACK(txt, pzE); + *pzE = NUL; + + if (mode == OPTION_LOAD_UNCOOKED) + return; + + switch (*txt) { + default: return; + case '"': + case '\'': break; + } + + switch (pzE[-1]) { + default: return; + case '"': + case '\'': break; + } + + (void)ao_string_cook(txt, NULL); +} + +static char * +assemble_arg_val(char * txt, tOptionLoadMode mode) +{ + char* pzEnd = strpbrk(txt, ARG_BREAK_STR); + int space_break; + + /* + * Not having an argument to a configurable name is okay. + */ + if (pzEnd == NULL) + return txt + strlen(txt); + + /* + * If we are keeping all whitespace, then the modevalue starts with the + * character that follows the end of the configurable name, regardless + * of which character caused it. + */ + if (mode == OPTION_LOAD_KEEP) { + *(pzEnd++) = NUL; + return pzEnd; + } + + /* + * If the name ended on a white space character, remember that + * because we'll have to skip over an immediately following ':' or '=' + * (and the white space following *that*). + */ + space_break = IS_WHITESPACE_CHAR(*pzEnd); + *(pzEnd++) = NUL; + + pzEnd = SPN_WHITESPACE_CHARS(pzEnd); + if (space_break && ((*pzEnd == ':') || (*pzEnd == '='))) + pzEnd = SPN_WHITESPACE_CHARS(pzEnd+1); + + return pzEnd; +} + +/** + * Load an option from a block of text. The text must start with the + * configurable/option name and be followed by its associated value. + * That value may be processed in any of several ways. See "tOptionLoadMode" + * in autoopts.h. + * + * @param[in,out] opts program options descriptor + * @param[in,out] opt_state option processing state + * @param[in,out] line source line with long option name in it + * @param[in] direction current processing direction (preset or not) + * @param[in] load_mode option loading mode (OPTION_LOAD_*) + */ +LOCAL void +loadOptionLine( + tOptions * opts, + tOptState * opt_state, + char * line, + tDirection direction, + tOptionLoadMode load_mode ) +{ + line = SPN_LOAD_LINE_SKIP_CHARS(line); + + { + char * arg = assemble_arg_val(line, load_mode); + + if (! SUCCESSFUL(opt_find_long(opts, line, opt_state))) + return; + + if (opt_state->flags & OPTST_NO_INIT) + return; + + opt_state->pzOptArg = arg; + } + + switch (opt_state->flags & (OPTST_IMM|OPTST_DISABLE_IMM)) { + case 0: + /* + * The selected option has no immediate action. + * THEREFORE, if the direction is PRESETTING + * THEN we skip this option. + */ + if (PRESETTING(direction)) + return; + break; + + case OPTST_IMM: + if (PRESETTING(direction)) { + /* + * We are in the presetting direction with an option we handle + * immediately for enablement, but normally for disablement. + * Therefore, skip if disabled. + */ + if ((opt_state->flags & OPTST_DISABLED) == 0) + return; + } else { + /* + * We are in the processing direction with an option we handle + * immediately for enablement, but normally for disablement. + * Therefore, skip if NOT disabled. + */ + if ((opt_state->flags & OPTST_DISABLED) != 0) + return; + } + break; + + case OPTST_DISABLE_IMM: + if (PRESETTING(direction)) { + /* + * We are in the presetting direction with an option we handle + * immediately for disablement, but normally for disablement. + * Therefore, skip if NOT disabled. + */ + if ((opt_state->flags & OPTST_DISABLED) != 0) + return; + } else { + /* + * We are in the processing direction with an option we handle + * immediately for disablement, but normally for disablement. + * Therefore, skip if disabled. + */ + if ((opt_state->flags & OPTST_DISABLED) == 0) + return; + } + break; + + case OPTST_IMM|OPTST_DISABLE_IMM: + /* + * The selected option is always for immediate action. + * THEREFORE, if the direction is PROCESSING + * THEN we skip this option. + */ + if (PROCESSING(direction)) + return; + break; + } + + /* + * Fix up the args. + */ + if (OPTST_GET_ARGTYPE(opt_state->pOD->fOptState) == OPARG_TYPE_NONE) { + if (*opt_state->pzOptArg != NUL) + return; + opt_state->pzOptArg = NULL; + + } else if (opt_state->pOD->fOptState & OPTST_ARG_OPTIONAL) { + if (*opt_state->pzOptArg == NUL) + opt_state->pzOptArg = NULL; + else { + AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); + opt_state->flags |= OPTST_ALLOC_ARG; + } + + } else { + if (*opt_state->pzOptArg == NUL) + opt_state->pzOptArg = zNil; + else { + AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); + opt_state->flags |= OPTST_ALLOC_ARG; + } + } + + { + tOptionLoadMode sv = option_load_mode; + option_load_mode = load_mode; + handle_opt(opts, opt_state); + option_load_mode = sv; + } +} + +/*=export_func optionLoadLine + * + * what: process a string for an option name and value + * + * arg: tOptions*, opts, program options descriptor + * arg: char const*, line, NUL-terminated text + * + * doc: + * + * This is a client program callable routine for setting options from, for + * example, the contents of a file that they read in. Only one option may + * appear in the text. It will be treated as a normal (non-preset) option. + * + * When passed a pointer to the option struct and a string, it will find + * the option named by the first token on the string and set the option + * argument to the remainder of the string. The caller must NUL terminate + * the string. The caller need not skip over any introductory hyphens. + * Any embedded new lines will be included in the option + * argument. If the input looks like one or more quoted strings, then the + * input will be "cooked". The "cooking" is identical to the string + * formation used in AutoGen definition files (@pxref{basic expression}), + * except that you may not use backquotes. + * + * err: Invalid options are silently ignored. Invalid option arguments + * will cause a warning to print, but the function should return. +=*/ +void +optionLoadLine(tOptions * opts, char const * line) +{ + tOptState st = OPTSTATE_INITIALIZER(SET); + char* pz; + AGDUPSTR(pz, line, "user option line"); + loadOptionLine(opts, &st, pz, DIRECTION_PROCESS, OPTION_LOAD_COOKED); + AGFREE(pz); +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/load.c */ diff --git a/autoopts/makeshell.c b/autoopts/makeshell.c new file mode 100644 index 0000000..5ba949d --- /dev/null +++ b/autoopts/makeshell.c @@ -0,0 +1,873 @@ + +/** + * \file makeshell.c + * + * Time-stamp: "2012-08-11 08:51:32 bkorb" + * + * This module will interpret the options set in the tOptions + * structure and create a Bourne shell script capable of parsing them. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +tOptions * optionParseShellOptions = NULL; + +static char const * shell_prog = NULL; +static char * script_leader = NULL; +static char * script_trailer = NULL; +static char * script_text = NULL; + +/* = = = START-STATIC-FORWARD = = = */ +static void +emit_var_text(char const * prog, char const * var, int fdin); + +static void +text_to_var(tOptions * pOpts, teTextTo whichVar, tOptDesc * pOD); + +static void +emit_usage(tOptions * pOpts); + +static void +emit_setup(tOptions * pOpts); + +static void +emit_action(tOptions * pOpts, tOptDesc* pOptDesc); + +static void +emit_inaction(tOptions * pOpts, tOptDesc* pOptDesc); + +static void +emit_flag(tOptions * pOpts); + +static void +emit_match_expr(char const * pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts); + +static void +emit_long(tOptions * pOpts); + +static char * +load_old_output(char const * fname); + +static void +open_out(char const * fname); +/* = = = END-STATIC-FORWARD = = = */ + +/*=export_func optionParseShell + * private: + * + * what: Decipher a boolean value + * arg: + tOptions* + pOpts + program options descriptor + + * + * doc: + * Emit a shell script that will parse the command line options. +=*/ +void +optionParseShell(tOptions * pOpts) +{ + /* + * Check for our SHELL option now. + * IF the output file contains the "#!" magic marker, + * it will override anything we do here. + */ + if (HAVE_GENSHELL_OPT(SHELL)) + shell_prog = GENSHELL_OPT_ARG(SHELL); + + else if (! ENABLED_GENSHELL_OPT(SHELL)) + shell_prog = NULL; + + else if ((shell_prog = getenv("SHELL")), + shell_prog == NULL) + + shell_prog = POSIX_SHELL; + + /* + * Check for a specified output file + */ + if (HAVE_GENSHELL_OPT(SCRIPT)) + open_out(GENSHELL_OPT_ARG(SCRIPT)); + + emit_usage(pOpts); + emit_setup(pOpts); + + /* + * There are four modes of option processing. + */ + switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) { + case OPTPROC_LONGOPT: + fputs(LOOP_STR, stdout); + + fputs(LONG_OPT_MARK, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(pOpts); + printf(LOPT_ARG_FMT, pOpts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + + case 0: + fputs(ONLY_OPTS_LOOP, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(pOpts); + printf(LOPT_ARG_FMT, pOpts->pzPROGNAME); + break; + + case OPTPROC_SHORTOPT: + fputs(LOOP_STR, stdout); + + fputs(FLAG_OPT_MARK, stdout); + fputs(INIT_OPT_STR, stdout); + emit_flag(pOpts); + printf(OPT_ARG_FMT, pOpts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + + case OPTPROC_LONGOPT|OPTPROC_SHORTOPT: + fputs(LOOP_STR, stdout); + + fputs(LONG_OPT_MARK, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(pOpts); + printf(LOPT_ARG_FMT, pOpts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(FLAG_OPT_MARK, stdout); + fputs(INIT_OPT_STR, stdout); + emit_flag(pOpts); + printf(OPT_ARG_FMT, pOpts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + } + + printf(zLoopEnd, pOpts->pzPROGNAME, END_MARK); + if ((script_trailer != NULL) && (*script_trailer != NUL)) + fputs(script_trailer, stdout); + else if (ENABLED_GENSHELL_OPT(SHELL)) + printf(SHOW_PROG_ENV, pOpts->pzPROGNAME); + +#ifdef HAVE_FCHMOD + fchmod(STDOUT_FILENO, 0755); +#endif + fclose(stdout); + + if (ferror(stdout)) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } + + AGFREE(script_text); + script_leader = NULL; + script_trailer = NULL; + script_text = NULL; +} + +#ifdef HAVE_WORKING_FORK +static void +emit_var_text(char const * prog, char const * var, int fdin) +{ + FILE * fp = fdopen(fdin, "r" FOPEN_BINARY_FLAG); + int nlct = 0; /* defer newlines and skip trailing ones */ + + printf(SET_TEXT_FMT, prog, var); + if (fp == NULL) + goto skip_text; + + for (;;) { + int ch = fgetc(fp); + switch (ch) { + + case NL: + nlct++; + break; + + case '\'': + while (nlct > 0) { + fputc(NL, stdout); + nlct--; + } + fputs(apostrophy, stdout); + break; + + case EOF: + goto endCharLoop; + + default: + while (nlct > 0) { + fputc(NL, stdout); + nlct--; + } + fputc(ch, stdout); + break; + } + } endCharLoop:; + + fclose(fp); + +skip_text: + + fputs(END_SET_TEXT, stdout); +} + +#endif + +/* + * The purpose of this function is to assign "long usage", short usage + * and version information to a shell variable. Rather than wind our + * way through all the logic necessary to emit the text directly, we + * fork(), have our child process emit the text the normal way and + * capture the output in the parent process. + */ +static void +text_to_var(tOptions * pOpts, teTextTo whichVar, tOptDesc * pOD) +{ +# define _TT_(n) static char const z ## n [] = #n; + TEXTTO_TABLE +# undef _TT_ +# define _TT_(n) z ## n , + static char const * apzTTNames[] = { TEXTTO_TABLE }; +# undef _TT_ + +#if ! defined(HAVE_WORKING_FORK) + printf(SET_NO_TEXT_FMT, pOpts->pzPROGNAME, apzTTNames[ whichVar]); +#else + int pipeFd[2]; + + fflush(stdout); + fflush(stderr); + + if (pipe(pipeFd) != 0) { + fprintf(stderr, zBadPipe, errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + switch (fork()) { + case -1: + fprintf(stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName); + exit(EXIT_FAILURE); + break; + + case 0: + /* + * Send both stderr and stdout to the pipe. No matter which + * descriptor is used, we capture the output on the read end. + */ + dup2(pipeFd[1], STDERR_FILENO); + dup2(pipeFd[1], STDOUT_FILENO); + close(pipeFd[0]); + + switch (whichVar) { + case TT_LONGUSAGE: + (*(pOpts->pUsageProc))(pOpts, EXIT_SUCCESS); + /* NOTREACHED */ + + case TT_USAGE: + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + + case TT_VERSION: + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + pOD->optArg.argString = "c"; + optionPrintVersion(pOpts, pOD); + /* NOTREACHED */ + + default: + exit(EXIT_FAILURE); + } + + default: + close(pipeFd[1]); + } + + emit_var_text(pOpts->pzPROGNAME, apzTTNames[whichVar], pipeFd[0]); +#endif +} + + +static void +emit_usage(tOptions * pOpts) +{ + char zTimeBuf[AO_NAME_SIZE]; + + /* + * First, switch stdout to the output file name. + * Then, change the program name to the one defined + * by the definitions (rather than the current + * executable name). Down case the upper cased name. + */ + if (script_leader != NULL) + fputs(script_leader, stdout); + + { + char const * out_nm; + + { + time_t c_tim = time(NULL); + struct tm * ptm = localtime(&c_tim); + strftime(zTimeBuf, AO_NAME_SIZE, TIME_FMT, ptm ); + } + + if (HAVE_GENSHELL_OPT(SCRIPT)) + out_nm = GENSHELL_OPT_ARG(SCRIPT); + else out_nm = STDOUT; + + if ((script_leader == NULL) && (shell_prog != NULL)) + printf(SHELL_MAGIC, shell_prog); + + printf(PREAMBLE_FMT, START_MARK, out_nm, zTimeBuf); + } + + printf(END_PRE_FMT, pOpts->pzPROGNAME); + + /* + * Get a copy of the original program name in lower case and + * fill in an approximation of the program name from it. + */ + { + char * pzPN = zTimeBuf; + char const * pz = pOpts->pzPROGNAME; + char ** pp; + + for (;;) { + if ((*pzPN++ = (char)tolower(*pz++)) == NUL) + break; + } + + pp = (char **)(void *)&(pOpts->pzProgPath); + *pp = zTimeBuf; + pp = (char **)(void *)&(pOpts->pzProgName); + *pp = zTimeBuf; + } + + text_to_var(pOpts, TT_LONGUSAGE, NULL); + text_to_var(pOpts, TT_USAGE, NULL); + + { + tOptDesc* pOptDesc = pOpts->pOptDesc; + int optionCt = pOpts->optCt; + + for (;;) { + if (pOptDesc->pOptProc == optionPrintVersion) { + text_to_var(pOpts, TT_VERSION, pOptDesc); + break; + } + + if (--optionCt <= 0) + break; + pOptDesc++; + } + } +} + + +static void +emit_setup(tOptions * pOpts) +{ + tOptDesc * pOptDesc = pOpts->pOptDesc; + int optionCt = pOpts->presetOptCt; + char const * pzFmt; + char const * pzDefault; + + for (;optionCt > 0; pOptDesc++, --optionCt) { + char zVal[32]; + + /* + * Options that are either usage documentation or are compiled out + * are not to be processed. + */ + if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL)) + continue; + + if (pOptDesc->optMaxCt > 1) + pzFmt = MULTI_DEF_FMT; + else pzFmt = SGL_DEF_FMT; + + /* + * IF this is an enumeration/bitmask option, then convert the value + * to a string before printing the default value. + */ + switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) { + case OPARG_TYPE_ENUMERATION: + (*(pOptDesc->pOptProc))(OPTPROC_EMIT_SHELL, pOptDesc ); + pzDefault = pOptDesc->optArg.argString; + break; + + /* + * Numeric and membership bit options are just printed as a number. + */ + case OPARG_TYPE_NUMERIC: + snprintf(zVal, sizeof(zVal), "%d", + (int)pOptDesc->optArg.argInt); + pzDefault = zVal; + break; + + case OPARG_TYPE_MEMBERSHIP: + snprintf(zVal, sizeof(zVal), "%lu", + (unsigned long)pOptDesc->optArg.argIntptr); + pzDefault = zVal; + break; + + case OPARG_TYPE_BOOLEAN: + pzDefault = (pOptDesc->optArg.argBool) ? TRUE_STR : FALSE_STR; + break; + + default: + if (pOptDesc->optArg.argString == NULL) { + if (pzFmt == SGL_DEF_FMT) + pzFmt = SGL_NO_DEF_FMT; + pzDefault = NULL; + } + else + pzDefault = pOptDesc->optArg.argString; + } + + printf(pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault); + } +} + +static void +emit_action(tOptions * pOpts, tOptDesc* pOptDesc) +{ + if (pOptDesc->pOptProc == optionPrintVersion) + printf(zTextExit, pOpts->pzPROGNAME, VER_STR); + + else if (pOptDesc->pOptProc == optionPagedUsage) + printf(zPagedUsageExit, pOpts->pzPROGNAME); + + else if (pOptDesc->pOptProc == optionLoadOpt) { + printf(zCmdFmt, NO_LOAD_WARN); + printf(zCmdFmt, YES_NEED_OPT_ARG); + + } else if (pOptDesc->pz_NAME == NULL) { + + if (pOptDesc->pOptProc == NULL) { + printf(zCmdFmt, NO_SAVE_OPTS); + printf(zCmdFmt, OK_NEED_OPT_ARG); + } else + printf(zTextExit, pOpts->pzPROGNAME, LONG_USE_STR); + + } else { + if (pOptDesc->optMaxCt == 1) + printf(SGL_ARG_FMT, pOpts->pzPROGNAME, pOptDesc->pz_NAME); + else { + if ((unsigned)pOptDesc->optMaxCt < NOLIMIT) + printf(zCountTest, pOpts->pzPROGNAME, + pOptDesc->pz_NAME, pOptDesc->optMaxCt); + + printf(MULTI_ARG_FMT, pOpts->pzPROGNAME, pOptDesc->pz_NAME); + } + + /* + * Fix up the args. + */ + if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) { + printf(zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME); + + } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) { + printf(zMayArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME); + + } else { + fputs(zMustArg, stdout); + } + } + fputs(zOptionEndSelect, stdout); +} + + +static void +emit_inaction(tOptions * pOpts, tOptDesc* pOptDesc) +{ + if (pOptDesc->pOptProc == optionLoadOpt) { + printf(zCmdFmt, NO_SUPPRESS_LOAD); + + } else if (pOptDesc->optMaxCt == 1) + printf(NO_SGL_ARG_FMT, pOpts->pzPROGNAME, + pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx); + else + printf(NO_MULTI_ARG_FMT, pOpts->pzPROGNAME, + pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx); + + printf(zCmdFmt, NO_ARG_NEEDED); + fputs(zOptionEndSelect, stdout); +} + + +static void +emit_flag(tOptions * pOpts) +{ + tOptDesc* pOptDesc = pOpts->pOptDesc; + int optionCt = pOpts->optCt; + + fputs(zOptionCase, stdout); + + for (;optionCt > 0; pOptDesc++, --optionCt) { + + if (SKIP_OPT(pOptDesc)) + continue; + + if (IS_GRAPHIC_CHAR(pOptDesc->optValue)) { + printf(zOptionFlag, pOptDesc->optValue); + emit_action(pOpts, pOptDesc); + } + } + printf(UNK_OPT_FMT, FLAG_STR, pOpts->pzPROGNAME); +} + + +/* + * Emit the match text for a long option + */ +static void +emit_match_expr(char const * pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts) +{ + tOptDesc* pOD = pOpts->pOptDesc; + int oCt = pOpts->optCt; + int min = 1; + char zName[ 256 ]; + char* pz = zName; + + for (;;) { + int matchCt = 0; + + /* + * Omit the current option, Documentation opts and compiled out opts. + */ + if ((pOD == pCurOpt) || SKIP_OPT(pOD)){ + if (--oCt <= 0) + break; + pOD++; + continue; + } + + /* + * Check each character of the name case insensitively. + * They must not be the same. They cannot be, because it would + * not compile correctly if they were. + */ + while ( toupper(pOD->pz_Name[matchCt]) + == toupper(pzMatchName[matchCt])) + matchCt++; + + if (matchCt > min) + min = matchCt; + + /* + * Check the disablement name, too. + */ + if (pOD->pz_DisableName != NULL) { + matchCt = 0; + while ( toupper(pOD->pz_DisableName[matchCt]) + == toupper(pzMatchName[matchCt])) + matchCt++; + if (matchCt > min) + min = matchCt; + } + if (--oCt <= 0) + break; + pOD++; + } + + /* + * IF the 'min' is all or one short of the name length, + * THEN the entire string must be matched. + */ + if ( (pzMatchName[min ] == NUL) + || (pzMatchName[min+1] == NUL) ) + printf(zOptionFullName, pzMatchName); + + else { + int matchCt = 0; + for (; matchCt <= min; matchCt++) + *pz++ = pzMatchName[matchCt]; + + for (;;) { + *pz = NUL; + printf(zOptionPartName, zName); + *pz++ = pzMatchName[matchCt++]; + if (pzMatchName[matchCt] == NUL) { + *pz = NUL; + printf(zOptionFullName, zName); + break; + } + } + } +} + + +/** + * Emit GNU-standard long option handling code. + */ +static void +emit_long(tOptions * pOpts) +{ + tOptDesc* pOD = pOpts->pOptDesc; + int ct = pOpts->optCt; + + fputs(zOptionCase, stdout); + + /* + * do each option, ... + */ + do { + /* + * Documentation & compiled-out options + */ + if (SKIP_OPT(pOD)) + continue; + + emit_match_expr(pOD->pz_Name, pOD, pOpts); + emit_action(pOpts, pOD); + + /* + * Now, do the same thing for the disablement version of the option. + */ + if (pOD->pz_DisableName != NULL) { + emit_match_expr(pOD->pz_DisableName, pOD, pOpts); + emit_inaction(pOpts, pOD); + } + } while (pOD++, --ct > 0); + + printf(UNK_OPT_FMT, OPTION_STR, pOpts->pzPROGNAME); +} + +/** + * Load the previous shell script output file. We need to preserve any + * hand-edited additions outside of the START_MARK and END_MARKs. + * + * @param[in] fname the output file name + */ +static char * +load_old_output(char const * fname) +{ + /* + * IF we cannot stat the file, + * THEN assume we are creating a new file. + * Skip the loading of the old data. + */ + FILE * fp = fopen(fname, "r" FOPEN_BINARY_FLAG); + struct stat stbf; + char * text; + char * scan; + + if (fp == NULL) + return NULL; + + /* + * If we opened it, we should be able to stat it and it needs + * to be a regular file + */ + if ((fstat(fileno(fp), &stbf) != 0) || (! S_ISREG(stbf.st_mode))) { + fprintf(stderr, zNotFile, fname); + exit(EXIT_FAILURE); + } + + scan = text = AGALOC(stbf.st_size + 1, "f data"); + + /* + * Read in all the data as fast as our OS will let us. + */ + for (;;) { + int inct = fread((void*)scan, (size_t)1, stbf.st_size, fp); + if (inct == 0) + break; + + stbf.st_size -= inct; + + if (stbf.st_size == 0) + break; + + scan += inct; + } + + *scan = NUL; + fclose(fp); + + return text; +} + +/** + * Open the specified output file. If it already exists, load its + * contents and save the non-generated (hand edited) portions. + * If a "start mark" is found, everything before it is preserved leader. + * If not, the entire thing is a trailer. Assuming the start is found, + * then everything after the end marker is the trailer. If the end + * mark is not found, the file is actually corrupt, but we take the + * remainder to be the trailer. + * + * @param[in] fname the output file name + */ +static void +open_out(char const * fname) +{ + + do { + char * txt = script_text = load_old_output(fname); + char * scn; + + if (txt == NULL) + break; + + scn = strstr(txt, START_MARK); + if (scn == NULL) { + script_trailer = txt; + break; + } + + *(scn++) = NUL; + scn = strstr(scn, END_MARK); + if (scn == NULL) { + /* + * The file is corrupt. + */ + script_trailer = txt + strlen(txt) + START_MARK_LEN + 1; + break; + } + + /* + * Check to see if the data contains our marker. + * If it does, then we will skip over it + */ + script_trailer = scn + END_MARK_LEN; + script_leader = txt; + } while (false); + + if (freopen(fname, "w" FOPEN_BINARY_FLAG, stdout) != stdout) { + fprintf(stderr, zFreopenFail, errno, strerror(errno)); + exit(EXIT_FAILURE); + } +} + + +/*=export_func genshelloptUsage + * private: + * what: The usage function for the genshellopt generated program + * + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + int + exitCode + usage text type to produce + + * + * doc: + * This function is used to create the usage strings for the option + * processing shell script code. Two child processes are spawned + * each emitting the usage text in either the short (error exit) + * style or the long style. The generated program will capture this + * and create shell script variables containing the two types of text. +=*/ +void +genshelloptUsage(tOptions * pOpts, int exitCode) +{ +#if ! defined(HAVE_WORKING_FORK) + optionUsage(pOpts, exitCode); +#else + /* + * IF not EXIT_SUCCESS, + * THEN emit the short form of usage. + */ + if (exitCode != EXIT_SUCCESS) + optionUsage(pOpts, exitCode); + fflush(stderr); + fflush(stdout); + if (ferror(stdout) || ferror(stderr)) + exit(EXIT_FAILURE); + + option_usage_fp = stdout; + + /* + * First, print our usage + */ + switch (fork()) { + case -1: + optionUsage(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + + case 0: + pagerState = PAGER_STATE_CHILD; + optionUsage(pOpts, EXIT_SUCCESS); + /* NOTREACHED */ + _exit(EXIT_FAILURE); + + default: + { + int sts; + wait(&sts); + } + } + + /* + * Generate the pzProgName, since optionProcess() normally + * gets it from the command line + */ + { + char * pz; + char ** pp = (char **)(void *)&(optionParseShellOptions->pzProgName); + AGDUPSTR(pz, optionParseShellOptions->pzPROGNAME, "prog name"); + *pp = pz; + while (*pz != NUL) { + *pz = tolower(*pz); + pz++; + } + } + + /* + * Separate the makeshell usage from the client usage + */ + fprintf(option_usage_fp, zGenshell, optionParseShellOptions->pzProgName); + fflush(option_usage_fp); + + /* + * Now, print the client usage. + */ + switch (fork()) { + case 0: + pagerState = PAGER_STATE_CHILD; + /*FALLTHROUGH*/ + case -1: + optionUsage(optionParseShellOptions, EXIT_FAILURE); + + default: + { + int sts; + wait(&sts); + } + } + + fflush(stdout); + if (ferror(stdout)) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +#endif +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/makeshell.c */ diff --git a/autoopts/mk-autoopts-pc.in b/autoopts/mk-autoopts-pc.in new file mode 100644 index 0000000..e14d396 --- /dev/null +++ b/autoopts/mk-autoopts-pc.in @@ -0,0 +1,78 @@ +#! @CONFIG_SHELL@ +## --------------------------------------------------------------------- +## mk-autoopts-pc.in -- Describe AutoOpts configuration +## +## Autoopts Copyright (c) 1992-2012 by Bruce Korb +## +## DO NOT EDIT THIS FILE (mk-autoopts-pc.in) +## +## It has been AutoGen-ed August 11, 2012 at 09:41:23 AM by AutoGen 5.16.2pre7 +## From the definitions aoconf.def +## and the template file aoconf.tpl +## + prefix="@prefix@" + datarootdir="@datarootdir@" + datadir="@datadir@" + package="@PACKAGE@" + includedir="@includedir@" + exec_prefix="@exec_prefix@" + bindir="@bindir@" + libdir="@libdir@" + ldopts="@AG_LDFLAGS@" + exeext="@EXEEXT@" + version="@AO_CURRENT@:@AO_REVISION@:@AO_AGE@" + dotver="@AO_CURRENT@.@AO_REVISION@.@AO_AGE@" + pkgdatadir="${datadir}/${package}" + autogen="${bindir}/autogen${exeext}" + ldflags="-L${libdir} -lopts" + libs="${ldflags}" + libsrc="${pkgdatadir}/libopts-${dotver}.tar.gz" + static_libs="${libdir}/libopts.a" + cflags="-I${includedir}" +test 'X@ENABLE_STATIC@' = Xno && static_libs='' +case "${libdir}" in +/lib | /lib64 | /usr/lib | /usr/lib64 ) + ldopts='' + ldflags=-lopts + ;; + +* ) + test -n "${ldopts}" && \ + ldflags="${ldopts}${libdir} ${ldflags}" + ;; +esac +libs=${ldflags} +test "${includedir}" = "/usr/include" && cflags="" +PS4='>mk-aopc> ' +dirname=`dirname ${1}` +test -d ${dirname} || mkdir -p ${dirname} || exit 1 + +cat > ${1} <<- _EOF_ + # pkg-config information for AutoOpts ${dotver} + # + prefix="${prefix}" + datarootdir="${datarootdir}" + datadir="${datadir}" + package="${package}" + includedir="${includedir}" + exec_prefix="${exec_prefix}" + bindir="${bindir}" + libdir="${libdir}" + ldopts="${ldopts}" + exeext="${exeext}" + version="${version}" + dotver="${dotver}" + pkgdatadir="${pkgdatadir}" + autogen="${autogen}" + libs="${libs}" + libsrc="${libsrc}" + static_libs="${static_libs}" + + Name: AutoOpts + Description: A semi-automated generated/library option parser + URL: http://www.gnu.org/software/autogen + Version: ${dotver} + Libs: ${ldflags} + Cflags: ${cflags} + _EOF_ +## end of mk-autoopts-pc.in diff --git a/autoopts/mk-tpl-config.sh b/autoopts/mk-tpl-config.sh new file mode 100755 index 0000000..5c37b29 --- /dev/null +++ b/autoopts/mk-tpl-config.sh @@ -0,0 +1,140 @@ +#! /bin/sh + +prog=`basename $0 .sh` + +die() { + echo "$prog failure: $*" + kill -TERM $progpid + sleep 1 + exit 1 +} + +init() { + PS4='>tpc-${FUNCNAME}> ' + set -e + progpid=$$ + prog=`basename $0` + progdir=`\cd \`dirname $0\` >/dev/null ; pwd` + readonly progpid progdir prog + + for d in top_srcdir srcdir top_builddir builddir + do + eval v=\${$d} + test -d "$v" || die "$d does not reference a directory" + v=`cd $v >/dev/null && pwd` + eval ${d}=${v} + done + . ${top_builddir}/config/shdefs +} + +collect_src() { + exec 8>&1 1>&2 + cd ${builddir} + sentinel_file=${1} ; shift + cat 1>&8 <<- _EOF_ + #define AUTOOPTS_INTERNAL 1 + #include "autoopts/project.h" + #define LOCAL static + #include "ao-strs.h" + _EOF_ + + for f in "$@" + do test "X$f" = "Xproject.h" || \ + printf '#include "%s"\n' $f + done 1>&8 +} + +extension_defines() { + cd ${builddir}/tpl + + test -f tpl-config.tlib || die "tpl-config.tlib not configured" + test -f ${top_builddir}/config.h || die "config.h missing" + ${GREP} 'extension-defines' tpl-config.tlib >/dev/null && return + + txt=`sed -n '/POSIX.*SOURCE/,/does not conform to ANSI C/{ + /^#/p + } + /does not conform to ANSI C/q' ${top_builddir}/config.h` + + { + sed '/define *top-build-dir/d;/^;;;/d' tpl-config.tlib + cat <<- _EOF_ + (define top-build-dir "`cd ${top_builddir} >/dev/null + pwd`") + (define top-src-dir "`cd ${top_srcdir} >/dev/null + pwd`") + (define extension-defines + "${txt}") \\=] + _EOF_ + } > tpl-config.$$ + mv -f tpl-config.$$ tpl-config.tlib +} + +set_shell_prog() { + case `uname -s` in + SunOS ) + while : ; do + POSIX_SHELL=`which bash` + test -x "${POSIX_SHELL}" && break + POSIX_SHELL=/usr/xpg4/bin/sh + test -x "${POSIX_SHELL}" && break + die "You are hosed. You are on Solaris and have no usable shell." + done + ;; + esac + + for f in ${srcdir}/tpl/*.sh ${srcdir}/tpl/*.pl + do + d=`basename $f | sed 's/\.[sp][hl]$//'` + st=`sed 1q $f` + + case "$st" in + *perl ) echo '#!' `which perl` + sed 1d $f + ;; + + */sh ) echo '#!' ${POSIX_SHELL} + sed 1d $f + ;; + + * ) die "Invalid script type: $st" + ;; + esac > $d + chmod 755 $d + done +} + +set_cat_prog() { + while : + do + \unalias -a + unset -f command cat which + POSIX_CAT=`which cat` + test -x "$POSIX_CAT" && break + POSIX_CAT=` + PATH=\`command -p getconf CS_PATH\` + command -v cat ` + test -x "${POSIX_CAT}" && break + die "cannot locate 'cat' command" + done + + formats='man mdoc texi' + for f in $formats + do + for g in $formats + do + test -f ${f}2${g} || { + printf "#! ${POSIX_SHELL}\nexec ${POSIX_CAT} "'${1+"$@"}\n' \ + > ${f}2${g} + chmod 755 ${f}2${g} + } + done + done +} + +init +collect_src "$@" > ${builddir}/libopts.c +extension_defines +set_shell_prog +set_cat_prog +touch ${sentinel_file} diff --git a/autoopts/nested.c b/autoopts/nested.c new file mode 100644 index 0000000..ed23fd2 --- /dev/null +++ b/autoopts/nested.c @@ -0,0 +1,849 @@ + +/** + * \file nested.c + * + * Time-stamp: "2012-03-04 13:30:07 bkorb" + * + * Automated Options Nested Values module. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +typedef struct { + int xml_ch; + int xml_len; + char xml_txt[8]; +} xml_xlate_t; + +static xml_xlate_t const xml_xlate[] = { + { '&', 4, "amp;" }, + { '<', 3, "lt;" }, + { '>', 3, "gt;" }, + { '"', 5, "quot;" }, + { '\'',5, "apos;" } +}; + +#ifndef ENOMSG +#define ENOMSG ENOENT +#endif + +/* = = = START-STATIC-FORWARD = = = */ +static void +remove_continuation(char* pzSrc); + +static char const* +scan_q_str(char const* pzTxt); + +static tOptionValue * +add_string(void ** pp, char const * pzName, size_t nameLen, + char const* pzValue, size_t dataLen); + +static tOptionValue * +add_bool(void ** pp, char const * pzName, size_t nameLen, + char const* pzValue, size_t dataLen); + +static tOptionValue* +add_number(void** pp, char const* pzName, size_t nameLen, + char const* pzValue, size_t dataLen); + +static tOptionValue* +add_nested(void** pp, char const* pzName, size_t nameLen, + char* pzValue, size_t dataLen); + +static char const * +scan_name(char const* pzName, tOptionValue* pRes); + +static char const* +scan_xml(char const* pzName, tOptionValue* pRes); + +static void +sort_list(tArgList* pAL); +/* = = = END-STATIC-FORWARD = = = */ + +/** + * Backslashes are used for line continuations. We keep the newline + * characters, but trim out the backslash: + */ +static void +remove_continuation(char* pzSrc) +{ + char* pzD; + + do { + while (*pzSrc == NL) pzSrc++; + pzD = strchr(pzSrc, NL); + if (pzD == NULL) + return; + + /* + * pzD has skipped at least one non-newline character and now + * points to a newline character. It now becomes the source and + * pzD goes to the previous character. + */ + pzSrc = pzD--; + if (*pzD != '\\') + pzD++; + } while (pzD == pzSrc); + + /* + * Start shifting text. + */ + for (;;) { + char ch = ((*pzD++) = *(pzSrc++)); + switch (ch) { + case NUL: return; + case '\\': + if (*pzSrc == NL) + --pzD; /* rewrite on next iteration */ + } + } +} + +/** + * Find the end of a quoted string, skipping escaped quote characters. + */ +static char const* +scan_q_str(char const* pzTxt) +{ + char q = *(pzTxt++); /* remember the type of quote */ + + for (;;) { + char ch = *(pzTxt++); + if (ch == NUL) + return pzTxt-1; + + if (ch == q) + return pzTxt; + + if (ch == '\\') { + ch = *(pzTxt++); + /* + * IF the next character is NUL, drop the backslash, too. + */ + if (ch == NUL) + return pzTxt - 2; + + /* + * IF the quote character or the escape character were escaped, + * then skip both, as long as the string does not end. + */ + if ((ch == q) || (ch == '\\')) { + if (*(pzTxt++) == NUL) + return pzTxt-1; + } + } + } +} + + +/** + * Associate a name with either a string or no value. + */ +static tOptionValue * +add_string(void ** pp, char const * pzName, size_t nameLen, + char const* pzValue, size_t dataLen) +{ + tOptionValue* pNV; + size_t sz = nameLen + dataLen + sizeof(*pNV); + + pNV = AGALOC(sz, "option name/str value pair"); + if (pNV == NULL) + return NULL; + + if (pzValue == NULL) { + pNV->valType = OPARG_TYPE_NONE; + pNV->pzName = pNV->v.strVal; + + } else { + pNV->valType = OPARG_TYPE_STRING; + if (dataLen > 0) { + char const * pzSrc = pzValue; + char * pzDst = pNV->v.strVal; + int ct = dataLen; + do { + int ch = *(pzSrc++) & 0xFF; + if (ch == NUL) goto data_copy_done; + if (ch == '&') + ch = get_special_char(&pzSrc, &ct); + *(pzDst++) = (char)ch; + } while (--ct > 0); + data_copy_done: + *pzDst = NUL; + + } else { + pNV->v.strVal[0] = NUL; + } + + pNV->pzName = pNV->v.strVal + dataLen + 1; + } + + memcpy(pNV->pzName, pzName, nameLen); + pNV->pzName[ nameLen ] = NUL; + addArgListEntry(pp, pNV); + return pNV; +} + +/** + * Associate a name with either a string or no value. + */ +static tOptionValue * +add_bool(void ** pp, char const * pzName, size_t nameLen, + char const* pzValue, size_t dataLen) +{ + tOptionValue * pNV; + + { + size_t sz = nameLen + sizeof(tOptionValue) + 1; + pNV = AGALOC(sz, "name/bool value"); + } + + { + char * p = SPN_WHITESPACE_CHARS(pzValue); + dataLen -= p - pzValue; + pzValue = p; + } + + if (dataLen == 0) + pNV->v.boolVal = 0; + + else if (IS_DEC_DIGIT_CHAR(*pzValue)) + pNV->v.boolVal = atoi(pzValue); + + else pNV->v.boolVal = ! IS_FALSE_TYPE_CHAR(*pzValue); + + pNV->valType = OPARG_TYPE_BOOLEAN; + pNV->pzName = (char*)(pNV + 1); + memcpy(pNV->pzName, pzName, nameLen); + pNV->pzName[ nameLen ] = NUL; + addArgListEntry(pp, pNV); + return pNV; +} + +/** + * Associate a name with either a string or no value. + */ +static tOptionValue* +add_number(void** pp, char const* pzName, size_t nameLen, + char const* pzValue, size_t dataLen) +{ + tOptionValue* pNV; + size_t sz = nameLen + sizeof(*pNV) + 1; + + pNV = AGALOC(sz, "option name/bool value pair"); + if (pNV == NULL) + return NULL; + while (IS_WHITESPACE_CHAR(*pzValue) && (dataLen > 0)) { + dataLen--; pzValue++; + } + if (dataLen == 0) + pNV->v.longVal = 0; + else + pNV->v.longVal = strtol(pzValue, 0, 0); + + pNV->valType = OPARG_TYPE_NUMERIC; + pNV->pzName = (char*)(pNV + 1); + memcpy(pNV->pzName, pzName, nameLen); + pNV->pzName[ nameLen ] = NUL; + addArgListEntry(pp, pNV); + return pNV; +} + +/** + * Associate a name with either a string or no value. + */ +static tOptionValue* +add_nested(void** pp, char const* pzName, size_t nameLen, + char* pzValue, size_t dataLen) +{ + tOptionValue* pNV; + + if (dataLen == 0) { + size_t sz = nameLen + sizeof(*pNV) + 1; + pNV = AGALOC(sz, "empty nested value pair"); + if (pNV == NULL) + return NULL; + pNV->v.nestVal = NULL; + pNV->valType = OPARG_TYPE_HIERARCHY; + pNV->pzName = (char*)(pNV + 1); + memcpy(pNV->pzName, pzName, nameLen); + pNV->pzName[ nameLen ] = NUL; + + } else { + pNV = optionLoadNested(pzValue, pzName, nameLen); + } + + if (pNV != NULL) + addArgListEntry(pp, pNV); + + return pNV; +} + +/** + * We have an entry that starts with a name. Find the end of it, cook it + * (if called for) and create the name/value association. + */ +static char const * +scan_name(char const* pzName, tOptionValue* pRes) +{ + tOptionValue* pNV; + char const * pzScan = pzName+1; /* we know first char is a name char */ + char const * pzVal; + size_t nameLen = 1; + size_t dataLen = 0; + + /* + * Scan over characters that name a value. These names may not end + * with a colon, but they may contain colons. + */ + pzScan = SPN_VALUE_NAME_CHARS(pzName + 1); + if (pzScan[-1] == ':') + pzScan--; + nameLen = pzScan - pzName; + + pzScan = SPN_HORIZ_WHITE_CHARS(pzScan); + + re_switch: + + switch (*pzScan) { + case '=': + case ':': + pzScan = SPN_HORIZ_WHITE_CHARS(pzScan + 1); + if ((*pzScan == '=') || (*pzScan == ':')) + goto default_char; + goto re_switch; + + case NL: + case ',': + pzScan++; + /* FALLTHROUGH */ + + case NUL: + add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0); + break; + + case '"': + case '\'': + pzVal = pzScan; + pzScan = scan_q_str(pzScan); + dataLen = pzScan - pzVal; + pNV = add_string(&(pRes->v.nestVal), pzName, nameLen, pzVal, + dataLen); + if ((pNV != NULL) && (option_load_mode == OPTION_LOAD_COOKED)) + ao_string_cook(pNV->v.strVal, NULL); + break; + + default: + default_char: + /* + * We have found some strange text value. It ends with a newline + * or a comma. + */ + pzVal = pzScan; + for (;;) { + char ch = *(pzScan++); + switch (ch) { + case NUL: + pzScan--; + dataLen = pzScan - pzVal; + goto string_done; + /* FALLTHROUGH */ + + case NL: + if ( (pzScan > pzVal + 2) + && (pzScan[-2] == '\\') + && (pzScan[ 0] != NUL)) + continue; + /* FALLTHROUGH */ + + case ',': + dataLen = (pzScan - pzVal) - 1; + string_done: + pNV = add_string(&(pRes->v.nestVal), pzName, nameLen, + pzVal, dataLen); + if (pNV != NULL) + remove_continuation(pNV->v.strVal); + goto leave_scan_name; + } + } + break; + } leave_scan_name:; + + return pzScan; +} + +/** + * We've found a '<' character. We ignore this if it is a comment or a + * directive. If it is something else, then whatever it is we are looking + * at is bogus. Returning NULL stops processing. + */ +static char const* +scan_xml(char const* pzName, tOptionValue* pRes) +{ + size_t nameLen; + size_t valLen; + char const* pzScan = ++pzName; + char const* pzVal; + tOptionValue valu; + tOptionValue* pNewVal; + tOptionLoadMode save_mode = option_load_mode; + + if (! IS_VAR_FIRST_CHAR(*pzName)) { + switch (*pzName) { + default: + pzName = NULL; + break; + + case '!': + pzName = strstr(pzName, "-->"); + if (pzName != NULL) + pzName += 3; + break; + + case '?': + pzName = strchr(pzName, '>'); + if (pzName != NULL) + pzName++; + break; + } + return pzName; + } + + pzScan = SPN_VALUE_NAME_CHARS(pzName+1); + nameLen = pzScan - pzName; + if (nameLen > 64) + return NULL; + valu.valType = OPARG_TYPE_STRING; + + switch (*pzScan) { + case ' ': + case '\t': + pzScan = parse_attrs( + NULL, (char*)pzScan, &option_load_mode, &valu ); + if (*pzScan == '>') { + pzScan++; + break; + } + + if (*pzScan != '/') { + option_load_mode = save_mode; + return NULL; + } + /* FALLTHROUGH */ + + case '/': + if (*++pzScan != '>') { + option_load_mode = save_mode; + return NULL; + } + add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0); + option_load_mode = save_mode; + return pzScan+1; + + default: + option_load_mode = save_mode; + return NULL; + + case '>': + pzScan++; + break; + } + + pzVal = pzScan; + + { + char z[68]; + char* pzD = z; + int ct = nameLen; + char const* pzS = pzName; + + *(pzD++) = '<'; + *(pzD++) = '/'; + + do { + *(pzD++) = *(pzS++); + } while (--ct > 0); + *(pzD++) = '>'; + *pzD = NUL; + + pzScan = strstr(pzScan, z); + if (pzScan == NULL) { + option_load_mode = save_mode; + return NULL; + } + valLen = (pzScan - pzVal); + pzScan += nameLen + 3; + pzScan = SPN_WHITESPACE_CHARS(pzScan); + } + + switch (valu.valType) { + case OPARG_TYPE_NONE: + add_string(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0); + break; + + case OPARG_TYPE_STRING: + pNewVal = add_string( + &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen); + + if (option_load_mode == OPTION_LOAD_KEEP) + break; + mungeString(pNewVal->v.strVal, option_load_mode); + break; + + case OPARG_TYPE_BOOLEAN: + add_bool(&(pRes->v.nestVal), pzName, nameLen, pzVal, valLen); + break; + + case OPARG_TYPE_NUMERIC: + add_number(&(pRes->v.nestVal), pzName, nameLen, pzVal, valLen); + break; + + case OPARG_TYPE_HIERARCHY: + { + char* pz = AGALOC(valLen+1, "hierarchical scan"); + if (pz == NULL) + break; + memcpy(pz, pzVal, valLen); + pz[valLen] = NUL; + add_nested(&(pRes->v.nestVal), pzName, nameLen, pz, valLen); + AGFREE(pz); + break; + } + + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + default: + break; + } + + option_load_mode = save_mode; + return pzScan; +} + + +/** + * Deallocate a list of option arguments. This must have been gotten from + * a hierarchical option argument, not a stacked list of strings. It is + * an internal call, so it is not validated. The caller is responsible for + * knowing what they are doing. + */ +LOCAL void +unload_arg_list(tArgList* pAL) +{ + int ct = pAL->useCt; + tCC** ppNV = pAL->apzArgs; + + while (ct-- > 0) { + tOptionValue* pNV = (tOptionValue*)(void*)*(ppNV++); + if (pNV->valType == OPARG_TYPE_HIERARCHY) + unload_arg_list(pNV->v.nestVal); + AGFREE(pNV); + } + + AGFREE((void*)pAL); +} + +/*=export_func optionUnloadNested + * + * what: Deallocate the memory for a nested value + * arg: + tOptionValue const * + pOptVal + the hierarchical value + + * + * doc: + * A nested value needs to be deallocated. The pointer passed in should + * have been gotten from a call to @code{configFileLoad()} (See + * @pxref{libopts-configFileLoad}). +=*/ +void +optionUnloadNested(tOptionValue const * pOV) +{ + if (pOV == NULL) return; + if (pOV->valType != OPARG_TYPE_HIERARCHY) { + errno = EINVAL; + return; + } + + unload_arg_list(pOV->v.nestVal); + + AGFREE((void*)pOV); +} + +/** + * This is a _stable_ sort. The entries are sorted alphabetically, + * but within entries of the same name the ordering is unchanged. + * Typically, we also hope the input is sorted. + */ +static void +sort_list(tArgList* pAL) +{ + int ix; + int lm = pAL->useCt; + + /* + * This loop iterates "useCt" - 1 times. + */ + for (ix = 0; ++ix < lm;) { + int iy = ix-1; + tOptionValue* pNewNV = (tOptionValue*)(void*)(pAL->apzArgs[ix]); + tOptionValue* pOldNV = (tOptionValue*)(void*)(pAL->apzArgs[iy]); + + /* + * For as long as the new entry precedes the "old" entry, + * move the old pointer. Stop before trying to extract the + * "-1" entry. + */ + while (strcmp(pOldNV->pzName, pNewNV->pzName) > 0) { + pAL->apzArgs[iy+1] = (void*)pOldNV; + pOldNV = (tOptionValue*)(void*)(pAL->apzArgs[--iy]); + if (iy < 0) + break; + } + + /* + * Always store the pointer. Sometimes it is redundant, + * but the redundancy is cheaper than a test and branch sequence. + */ + pAL->apzArgs[iy+1] = (void*)pNewNV; + } +} + +/*= + * private: + * + * what: parse a hierarchical option argument + * arg: + char const* + pzTxt + the text to scan + + * arg: + char const* + pzName + the name for the text + + * arg: + size_t + nameLen + the length of "name" + + * + * ret_type: tOptionValue* + * ret_desc: An allocated, compound value structure + * + * doc: + * A block of text represents a series of values. It may be an + * entire configuration file, or it may be an argument to an + * option that takes a hierarchical value. + * + * If NULL is returned, errno will be set: + * @itemize @bullet + * @item + * @code{EINVAL} the input text was NULL. + * @item + * @code{ENOMEM} the storage structures could not be allocated + * @item + * @code{ENOMSG} no configuration values were found + * @end itemize +=*/ +LOCAL tOptionValue* +optionLoadNested(char const* pzTxt, char const* pzName, size_t nameLen) +{ + tOptionValue* pRes; + + /* + * Make sure we have some data and we have space to put what we find. + */ + if (pzTxt == NULL) { + errno = EINVAL; + return NULL; + } + pzTxt = SPN_WHITESPACE_CHARS(pzTxt); + if (*pzTxt == NUL) { + errno = ENOMSG; + return NULL; + } + pRes = AGALOC(sizeof(*pRes) + nameLen + 1, "nested args"); + if (pRes == NULL) { + errno = ENOMEM; + return NULL; + } + pRes->valType = OPARG_TYPE_HIERARCHY; + pRes->pzName = (char*)(pRes + 1); + memcpy(pRes->pzName, pzName, nameLen); + pRes->pzName[nameLen] = NUL; + + { + tArgList * pAL = AGALOC(sizeof(*pAL), "nested arg list"); + if (pAL == NULL) { + AGFREE(pRes); + return NULL; + } + + pRes->v.nestVal = pAL; + pAL->useCt = 0; + pAL->allocCt = MIN_ARG_ALLOC_CT; + } + + /* + * Scan until we hit a NUL. + */ + do { + pzTxt = SPN_WHITESPACE_CHARS(pzTxt); + if (IS_VAR_FIRST_CHAR(*pzTxt)) + pzTxt = scan_name(pzTxt, pRes); + + else switch (*pzTxt) { + case NUL: goto scan_done; + case '<': pzTxt = scan_xml(pzTxt, pRes); + if (pzTxt == NULL) goto woops; + if (*pzTxt == ',') pzTxt++; break; + case '#': pzTxt = strchr(pzTxt, NL); break; + default: goto woops; + } + } while (pzTxt != NULL); scan_done:; + + { + tArgList * al = pRes->v.nestVal; + if (al->useCt == 0) { + errno = ENOMSG; + goto woops; + } + if (al->useCt > 1) + sort_list(al); + } + + return pRes; + + woops: + AGFREE(pRes->v.nestVal); + AGFREE(pRes); + return NULL; +} + +/*=export_func optionNestedVal + * private: + * + * what: parse a hierarchical option argument + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Nested value was found on the command line +=*/ +void +optionNestedVal(tOptions* pOpts, tOptDesc* pOD) +{ + if (pOpts < OPTPROC_EMIT_LIMIT) + return; + + if (pOD->fOptState & OPTST_RESET) { + tArgList* pAL = pOD->optCookie; + int ct; + tCC ** av; + + if (pAL == NULL) + return; + ct = pAL->useCt; + av = pAL->apzArgs; + + while (--ct >= 0) { + void * p = (void *)*(av++); + optionUnloadNested((tOptionValue const *)p); + } + + AGFREE(pOD->optCookie); + + } else { + tOptionValue* pOV = optionLoadNested( + pOD->optArg.argString, pOD->pz_Name, strlen(pOD->pz_Name)); + + if (pOV != NULL) + addArgListEntry(&(pOD->optCookie), (void*)pOV); + } +} + +/* + * get_special_char + */ +LOCAL int +get_special_char(char const ** ppz, int * ct) +{ + char const * pz = *ppz; + + if (*ct < 3) + return '&'; + + if (*pz == '#') { + int base = 10; + int retch; + + pz++; + if (*pz == 'x') { + base = 16; + pz++; + } + retch = (int)strtoul(pz, (char **)&pz, base); + if (*pz != ';') + return '&'; + base = ++pz - *ppz; + if (base > *ct) + return '&'; + + *ct -= base; + *ppz = pz; + return retch; + } + + { + int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]); + xml_xlate_t const * xlatp = xml_xlate; + + for (;;) { + if ( (*ct >= xlatp->xml_len) + && (strncmp(pz, xlatp->xml_txt, xlatp->xml_len) == 0)) { + *ppz += xlatp->xml_len; + *ct -= xlatp->xml_len; + return xlatp->xml_ch; + } + + if (--ctr <= 0) + break; + xlatp++; + } + } + return '&'; +} + +/* + * emit_special_char + */ +LOCAL void +emit_special_char(FILE * fp, int ch) +{ + int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]); + xml_xlate_t const * xlatp = xml_xlate; + + putc('&', fp); + for (;;) { + if (ch == xlatp->xml_ch) { + fputs(xlatp->xml_txt, fp); + return; + } + if (--ctr <= 0) + break; + xlatp++; + } + fprintf(fp, XML_HEX_BYTE_FMT, (ch & 0xFF)); +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/nested.c */ diff --git a/autoopts/numeric.c b/autoopts/numeric.c new file mode 100644 index 0000000..b709d07 --- /dev/null +++ b/autoopts/numeric.c @@ -0,0 +1,165 @@ + +/** + * \file numeric.c + * + * Time-stamp: "2012-02-25 12:54:32 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionShowRange + * private: + * + * what: + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * arg: + void * + rng_table + the value range tables + + * arg: + int + rng_count + the number of entries + + * + * doc: + * Show information about a numeric option with range constraints. +=*/ +void +optionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct) +{ + const struct {long const rmin, rmax;} * rng = rng_table; + + char const * pz_indent = BULLET_STR; + + /* + * The range is shown only for full usage requests and an error + * in this particular option. + */ + if (pOpts != OPTPROC_EMIT_USAGE) { + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + pz_indent = ONE_TAB_STR; + + fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName, + pOD->pz_Name, pOD->optArg.argInt); + pz_indent = ""; + } + + if (pOD->fOptState & OPTST_SCALED_NUM) + fprintf(option_usage_fp, zRangeScaled, pz_indent); + + fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent); + pz_indent = (pOpts != OPTPROC_EMIT_USAGE) ? ONE_TAB_STR : DEEP_INDENT_STR; + + for (;;) { + if (rng->rmax == LONG_MIN) + fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin); + else if (rng->rmin == LONG_MIN) + fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax); + else if (rng->rmax == LONG_MAX) + fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin); + else + fprintf(option_usage_fp, zRange, pz_indent, rng->rmin, + rng->rmax); + + if (--rng_ct <= 0) { + fputc(NL, option_usage_fp); + break; + } + fputs(zRangeOr, option_usage_fp); + rng++; + } + + if (pOpts > OPTPROC_EMIT_LIMIT) + pOpts->pUsageProc(pOpts, EXIT_FAILURE); +} + +/*=export_func optionNumericVal + * private: + * + * what: process an option with a numeric value. + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Decipher a numeric value. +=*/ +void +optionNumericVal(tOptions* pOpts, tOptDesc* pOD ) +{ + char* pz; + long val; + + /* + * Numeric options may have a range associated with it. + * If it does, the usage procedure requests that it be + * emitted by passing a NULL pOD pointer. Also bail out + * if there is no option argument or if we are being reset. + */ + if ( (pOD == NULL) + || (pOD->optArg.argString == NULL) + || ((pOD->fOptState & OPTST_RESET) != 0)) + return; + + errno = 0; + val = strtol(pOD->optArg.argString, &pz, 0); + if ((pz == pOD->optArg.argString) || (errno != 0)) + goto bad_number; + + if ((pOD->fOptState & OPTST_SCALED_NUM) != 0) + switch (*(pz++)) { + case NUL: pz--; break; + case 't': val *= 1000; + case 'g': val *= 1000; + case 'm': val *= 1000; + case 'k': val *= 1000; break; + + case 'T': val *= 1024; + case 'G': val *= 1024; + case 'M': val *= 1024; + case 'K': val *= 1024; break; + + default: goto bad_number; + } + + if (*pz != NUL) + goto bad_number; + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + + pOD->optArg.argInt = val; + return; + + bad_number: + + fprintf( stderr, zNotNumber, pOpts->pzProgName, pOD->optArg.argString ); + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + + errno = EINVAL; + pOD->optArg.argInt = ~0; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/numeric.c */ diff --git a/autoopts/optionFileLoad.3 b/autoopts/optionFileLoad.3 new file mode 100644 index 0000000..4e30fa5 --- /dev/null +++ b/autoopts/optionFileLoad.3 @@ -0,0 +1,52 @@ +.TH optionFileLoad 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionFileLoad.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionFileLoad - Load the locatable config files, in order +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +int \fBoptionFileLoad\fP(tOptions* \fIpOpts\fP, char const* \fIpzProg\fP); +.sp 1 +.SH DESCRIPTION +This function looks in all the specified directories for a configuration +file ("rc" file or "ini" file) and processes any found twice. The first +time through, they are processed in reverse order (last file first). At +that time, only "immediate action" configurables are processed. For +example, if the last named file specifies not processing any more +configuration files, then no more configuration files will be processed. +Such an option in the \fBfirst\fP named directory will have no effect. + +Once the immediate action configurables have been handled, then the +directories are handled in normal, forward order. In that way, later +config files can override the settings of earlier config files. + +See the AutoOpts documentation for a thorough discussion of the +config file format. + +Configuration files not found or not decipherable are simply ignored. +.TP +.IR pOpts +program options descriptor +.TP +.IR pzProg +program name +.sp 1 +.SH RETURN VALUE +0 \-> SUCCESS, \-1 \-> FAILURE +.sp 1 +.SH ERRORS +Returns the value, "-1" if the program options descriptor +is out of date or indecipherable. Otherwise, the value "0" will +always be returned. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionFindNextValue.3 b/autoopts/optionFindNextValue.3 new file mode 100644 index 0000000..1a51859 --- /dev/null +++ b/autoopts/optionFindNextValue.3 @@ -0,0 +1,50 @@ +.TH optionFindNextValue 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionFindNextValue.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionFindNextValue - find a hierarcicaly valued option instance +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +const tOptionValue* \fBoptionFindNextValue\fP(const tOptDesc* \fIpOptDesc\fP, const tOptionValue* \fIpPrevVal\fP, char const* \fIname\fP, char const* \fIvalue\fP); +.sp 1 +.SH DESCRIPTION +This routine will find the next entry in a nested value option or +configurable. It will search through the list and return the next entry +that matches the criteria. +.TP +.IR pOptDesc +an option with a nested arg type +.TP +.IR pPrevVal +the last entry +.TP +.IR name +name of value to find +.TP +.IR value +the matching value +.sp 1 +.SH RETURN VALUE +a compound value structure +.sp 1 +.SH ERRORS +The returned result is NULL and errno is set: +.sp 1ize @bullet +.sp 1 +\fBEINVAL\fP \- the \fBpOptValue\fP does not point to a valid +hierarchical option value. +.sp 1 +\fBENOENT\fP \- no entry matched the given name. +@end itemize +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionFindValue.3 b/autoopts/optionFindValue.3 new file mode 100644 index 0000000..2c729f2 --- /dev/null +++ b/autoopts/optionFindValue.3 @@ -0,0 +1,46 @@ +.TH optionFindValue 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionFindValue.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionFindValue - find a hierarcicaly valued option instance +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +const tOptionValue* \fBoptionFindValue\fP(const tOptDesc* \fIpOptDesc\fP, char const* \fIname\fP, char const* \fIvalue\fP); +.sp 1 +.SH DESCRIPTION +This routine will find an entry in a nested value option or configurable. +It will search through the list and return a matching entry. +.TP +.IR pOptDesc +an option with a nested arg type +.TP +.IR name +name of value to find +.TP +.IR value +the matching value +.sp 1 +.SH RETURN VALUE +a compound value structure +.sp 1 +.SH ERRORS +The returned result is NULL and errno is set: +.sp 1ize @bullet +.sp 1 +\fBEINVAL\fP \- the \fBpOptValue\fP does not point to a valid +hierarchical option value. +.sp 1 +\fBENOENT\fP \- no entry matched the given name. +@end itemize +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionFree.3 b/autoopts/optionFree.3 new file mode 100644 index 0000000..a8ea0cb --- /dev/null +++ b/autoopts/optionFree.3 @@ -0,0 +1,31 @@ +.TH optionFree 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionFree.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionFree - free allocated option processing memory +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionFree\fP(tOptions* \fIpOpts\fP); +.sp 1 +.SH DESCRIPTION +AutoOpts sometimes allocates memory and puts pointers to it in the +option state structures. This routine deallocates all such memory. +.TP +.IR pOpts +program options descriptor +.sp 1 +.SH ERRORS +As long as memory has not been corrupted, +this routine is always successful. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionGetValue.3 b/autoopts/optionGetValue.3 new file mode 100644 index 0000000..3a908b8 --- /dev/null +++ b/autoopts/optionGetValue.3 @@ -0,0 +1,47 @@ +.TH optionGetValue 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionGetValue.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionGetValue - get a specific value from a hierarcical list +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +const tOptionValue* \fBoptionGetValue\fP(const tOptionValue* \fIpOptValue\fP, char const* \fIvalueName\fP); +.sp 1 +.SH DESCRIPTION +This routine will find an entry in a nested value option or configurable. +If "valueName" is NULL, then the first entry is returned. Otherwise, +the first entry with a name that exactly matches the argument will be +returned. If there is no matching value, NULL is returned and errno is +set to ENOENT. If the provided option value is not a hierarchical value, +NULL is also returned and errno is set to EINVAL. +.TP +.IR pOptValue +a hierarchcal value +.TP +.IR valueName +name of value to get +.sp 1 +.SH RETURN VALUE +a compound value structure +.sp 1 +.SH ERRORS +The returned result is NULL and errno is set: +.sp 1ize @bullet +.sp 1 +\fBEINVAL\fP \- the \fBpOptValue\fP does not point to a valid +hierarchical option value. +.sp 1 +\fBENOENT\fP \- no entry matched the given name. +@end itemize +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionLoadLine.3 b/autoopts/optionLoadLine.3 new file mode 100644 index 0000000..83556a7 --- /dev/null +++ b/autoopts/optionLoadLine.3 @@ -0,0 +1,45 @@ +.TH optionLoadLine 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionLoadLine.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionLoadLine - process a string for an option name and value +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionLoadLine\fP(tOptions* \fIopts\fP, char const* \fIline\fP); +.sp 1 +.SH DESCRIPTION +This is a client program callable routine for setting options from, for +example, the contents of a file that they read in. Only one option may +appear in the text. It will be treated as a normal (non-preset) option. + +When passed a pointer to the option struct and a string, it will find +the option named by the first token on the string and set the option +argument to the remainder of the string. The caller must NUL terminate +the string. The caller need not skip over any introductory hyphens. +Any embedded new lines will be included in the option +argument. If the input looks like one or more quoted strings, then the +input will be "cooked". The "cooking" is identical to the string +formation used in AutoGen definition files (@pxref{basic expression}), +except that you may not use backquotes. +.TP +.IR opts +program options descriptor +.TP +.IR line +NUL-terminated text +.sp 1 +.SH ERRORS +Invalid options are silently ignored. Invalid option arguments +will cause a warning to print, but the function should return. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionNextValue.3 b/autoopts/optionNextValue.3 new file mode 100644 index 0000000..7b332a1 --- /dev/null +++ b/autoopts/optionNextValue.3 @@ -0,0 +1,47 @@ +.TH optionNextValue 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionNextValue.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionNextValue - get the next value from a hierarchical list +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +const tOptionValue* \fBoptionNextValue\fP(const tOptionValue* \fIpOptValue\fP, const tOptionValue* \fIpOldValue\fP); +.sp 1 +.SH DESCRIPTION +This routine will return the next entry after the entry passed in. At the +end of the list, NULL will be returned. If the entry is not found on the +list, NULL will be returned and "\fBerrno\fP" will be set to EINVAL. +The "\fBpOldValue\fP" must have been gotten from a prior call to this +routine or to "\fBopitonGetValue()\fP". +.TP +.IR pOptValue +a hierarchcal list value +.TP +.IR pOldValue +a value from this list +.sp 1 +.SH RETURN VALUE +a compound value structure +.sp 1 +.SH ERRORS +The returned result is NULL and errno is set: +.sp 1ize @bullet +.sp 1 +\fBEINVAL\fP \- the \fBpOptValue\fP does not point to a valid +hierarchical option value or \fBpOldValue\fP does not point to a +member of that option value. +.sp 1 +\fBENOENT\fP \- the supplied \fBpOldValue\fP pointed to the last entry. +@end itemize +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionOnlyUsage.3 b/autoopts/optionOnlyUsage.3 new file mode 100644 index 0000000..a48ddb5 --- /dev/null +++ b/autoopts/optionOnlyUsage.3 @@ -0,0 +1,31 @@ +.TH optionOnlyUsage 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionOnlyUsage.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionOnlyUsage - Print usage text for just the options +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionOnlyUsage\fP(tOptions* \fIpOpts\fP, int \fIex_code\fP); +.sp 1 +.SH DESCRIPTION +This routine will print only the usage for each option. +This function may be used when the emitted usage must incorporate +information not available to AutoOpts. +.TP +.IR pOpts +program options descriptor +.TP +.IR ex_code +exit code for calling exit(3) +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionProcess.3 b/autoopts/optionProcess.3 new file mode 100644 index 0000000..f0d047d --- /dev/null +++ b/autoopts/optionProcess.3 @@ -0,0 +1,55 @@ +.TH optionProcess 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionProcess.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionProcess - this is the main option processing routine +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +int \fBoptionProcess\fP(tOptions* \fIpOpts\fP, int \fIargc\fP, char** \fIargv\fP); +.sp 1 +.SH DESCRIPTION +This is the main entry point for processing options. It is intended +that this procedure be called once at the beginning of the execution of +a program. Depending on options selected earlier, it is sometimes +necessary to stop and restart option processing, or to select completely +different sets of options. This can be done easily, but you generally +do not want to do this. + +The number of arguments processed always includes the program name. +If one of the arguments is "--", then it is counted and the processing +stops. If an error was encountered and errors are to be tolerated, then +the returned value is the index of the argument causing the error. +A hyphen by itself ("-") will also cause processing to stop and will +\fInot\fP be counted among the processed arguments. A hyphen by itself +is treated as an operand. Encountering an operand stops option +processing. +.TP +.IR pOpts +program options descriptor +.TP +.IR argc +program arg count +.TP +.IR argv +program arg vector +.sp 1 +.SH RETURN VALUE +the count of the arguments processed +.sp 1 +.SH ERRORS +Errors will cause diagnostics to be printed. \fBexit(3)\fP may +or may not be called. It depends upon whether or not the options +were generated with the "allow-errors" attribute, or if the +ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionRestore.3 b/autoopts/optionRestore.3 new file mode 100644 index 0000000..0e21e50 --- /dev/null +++ b/autoopts/optionRestore.3 @@ -0,0 +1,35 @@ +.TH optionRestore 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionRestore.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionRestore - restore option state from memory copy +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionRestore\fP(tOptions* \fIpOpts\fP); +.sp 1 +.SH DESCRIPTION +Copy back the option state from saved memory. +The allocated memory is left intact, so this routine can be +called repeatedly without having to call optionSaveState again. +If you are restoring a state that was saved before the first call +to optionProcess(3AO), then you may change the contents of the +argc/argv parameters to optionProcess. +.TP +.IR pOpts +program options descriptor +.sp 1 +.SH ERRORS +If you have not called \fBoptionSaveState\fP before, a diagnostic is +printed to \fBstderr\fP and exit is called. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionSaveFile.3 b/autoopts/optionSaveFile.3 new file mode 100644 index 0000000..b443471 --- /dev/null +++ b/autoopts/optionSaveFile.3 @@ -0,0 +1,44 @@ +.TH optionSaveFile 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionSaveFile.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionSaveFile - saves the option state to a file +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionSaveFile\fP(tOptions* \fIpOpts\fP); +.sp 1 +.SH DESCRIPTION +This routine will save the state of option processing to a file. The name +of that file can be specified with the argument to the \fB--save-opts\fP +option, or by appending the \fBrcfile\fP attribute to the last +\fBhomerc\fP attribute. If no \fBrcfile\fP attribute was specified, it +will default to \fB.\fIprogramname\fPrc\fP. If you wish to specify another +file, you should invoke the \fBSET_OPT_SAVE_OPTS(\fIfilename\fP)\fP macro. + +The recommend usage is as follows: +.nf + optionProcess(&progOptions, argc, argv); + if (i_want_a_non_standard_place_for_this) + SET_OPT_SAVE_OPTS("myfilename"); + optionSaveFile(&progOptions); +.fi +.TP +.IR pOpts +program options descriptor +.sp 1 +.SH ERRORS +If no \fBhomerc\fP file was specified, this routine will silently return +and do nothing. If the output file cannot be created or updated, a message +will be printed to \fBstderr\fP and the routine will return. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionSaveState.3 b/autoopts/optionSaveState.3 new file mode 100644 index 0000000..57567db --- /dev/null +++ b/autoopts/optionSaveState.3 @@ -0,0 +1,41 @@ +.TH optionSaveState 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionSaveState.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionSaveState - saves the option state to memory +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionSaveState\fP(tOptions* \fIpOpts\fP); +.sp 1 +.SH DESCRIPTION +This routine will allocate enough memory to save the current option +processing state. If this routine has been called before, that memory +will be reused. You may only save one copy of the option state. This +routine may be called before optionProcess(3AO). If you do call it +before the first call to optionProcess, then you may also change the +contents of argc/argv after you call optionRestore(3AO) + +In fact, more strongly put: it is safest to only use this function +before having processed any options. In particular, the saving and +restoring of stacked string arguments and hierarchical values is +disabled. The values are not saved. +.TP +.IR pOpts +program options descriptor +.sp 1 +.SH ERRORS +If it fails to allocate the memory, +it will print a message to stderr and exit. +Otherwise, it will always succeed. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionUnloadNested.3 b/autoopts/optionUnloadNested.3 new file mode 100644 index 0000000..ffa30c8 --- /dev/null +++ b/autoopts/optionUnloadNested.3 @@ -0,0 +1,28 @@ +.TH optionUnloadNested 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionUnloadNested.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionUnloadNested - Deallocate the memory for a nested value +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBoptionUnloadNested\fP(tOptionValue const * \fIpOptVal\fP); +.sp 1 +.SH DESCRIPTION +A nested value needs to be deallocated. The pointer passed in should +have been gotten from a call to \fBconfigFileLoad()\fP (See +@pxref{libopts-configFileLoad}). +.TP +.IR pOptVal +the hierarchical value +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/optionVersion.3 b/autoopts/optionVersion.3 new file mode 100644 index 0000000..9de5a36 --- /dev/null +++ b/autoopts/optionVersion.3 @@ -0,0 +1,27 @@ +.TH optionVersion 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (optionVersion.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +optionVersion - return the compiled AutoOpts version number +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +char const* \fBoptionVersion\fP(void); +.sp 1 +.SH DESCRIPTION +Returns the full version string compiled into the library. +The returned string cannot be modified. +.sp 1 +.SH RETURN VALUE +the version string in constant memory +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/parse-duration.c b/autoopts/parse-duration.c new file mode 100644 index 0000000..7f1fb49 --- /dev/null +++ b/autoopts/parse-duration.c @@ -0,0 +1,601 @@ +/* Parse a time duration and return a seconds count + Copyright (C) 2008-2012 Free Software Foundation, Inc. + Written by Bruce Korb <bkorb@gnu.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "parse-duration.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef NUL +#define NUL '\0' +#endif + +#define cch_t char const + +typedef enum { + NOTHING_IS_DONE, + YEAR_IS_DONE, + MONTH_IS_DONE, + WEEK_IS_DONE, + DAY_IS_DONE, + HOUR_IS_DONE, + MINUTE_IS_DONE, + SECOND_IS_DONE +} whats_done_t; + +#define SEC_PER_MIN 60 +#define SEC_PER_HR (SEC_PER_MIN * 60) +#define SEC_PER_DAY (SEC_PER_HR * 24) +#define SEC_PER_WEEK (SEC_PER_DAY * 7) +#define SEC_PER_MONTH (SEC_PER_DAY * 30) +#define SEC_PER_YEAR (SEC_PER_DAY * 365) + +#define TIME_MAX 0x7FFFFFFF + +/* Wrapper around strtoul that does not require a cast. */ +static unsigned long inline +str_const_to_ul (cch_t * str, cch_t ** ppz, int base) +{ + return strtoul (str, (char **)ppz, base); +} + +/* Wrapper around strtol that does not require a cast. */ +static long inline +str_const_to_l (cch_t * str, cch_t ** ppz, int base) +{ + return strtol (str, (char **)ppz, base); +} + +/* Returns BASE + VAL * SCALE, interpreting BASE = BAD_TIME + with errno set as an error situation, and returning BAD_TIME + with errno set in an error situation. */ +static time_t inline +scale_n_add (time_t base, time_t val, int scale) +{ + if (base == BAD_TIME) + { + if (errno == 0) + errno = EINVAL; + return BAD_TIME; + } + + if (val > TIME_MAX / scale) + { + errno = ERANGE; + return BAD_TIME; + } + + val *= scale; + if (base > TIME_MAX - val) + { + errno = ERANGE; + return BAD_TIME; + } + + return base + val; +} + +/* After a number HH has been parsed, parse subsequent :MM or :MM:SS. */ +static time_t +parse_hr_min_sec (time_t start, cch_t * pz) +{ + int lpct = 0; + + errno = 0; + + /* For as long as our scanner pointer points to a colon *AND* + we've not looped before, then keep looping. (two iterations max) */ + while ((*pz == ':') && (lpct++ <= 1)) + { + unsigned long v = str_const_to_ul (pz+1, &pz, 10); + + if (errno != 0) + return BAD_TIME; + + start = scale_n_add (v, start, 60); + + if (errno != 0) + return BAD_TIME; + } + + /* allow for trailing spaces */ + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return start; +} + +/* Parses a value and returns BASE + value * SCALE, interpreting + BASE = BAD_TIME with errno set as an error situation, and returning + BAD_TIME with errno set in an error situation. */ +static time_t +parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) +{ + cch_t * pz = *ppz; + time_t val; + + if (base == BAD_TIME) + return base; + + errno = 0; + val = str_const_to_ul (pz, &pz, 10); + if (errno != 0) + return BAD_TIME; + while (isspace ((unsigned char)*pz)) + pz++; + if (pz != endp) + { + errno = EINVAL; + return BAD_TIME; + } + + *ppz = pz; + return scale_n_add (base, val, scale); +} + +/* Parses the syntax YEAR-MONTH-DAY. + PS points into the string, after "YEAR", before "-MONTH-DAY". */ +static time_t +parse_year_month_day (cch_t * pz, cch_t * ps) +{ + time_t res = 0; + + res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); + + pz++; /* over the first '-' */ + ps = strchr (pz, '-'); + if (ps == NULL) + { + errno = EINVAL; + return BAD_TIME; + } + res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); + + pz++; /* over the second '-' */ + ps = pz + strlen (pz); + return parse_scaled_value (res, &pz, ps, SEC_PER_DAY); +} + +/* Parses the syntax YYYYMMDD. */ +static time_t +parse_yearmonthday (cch_t * in_pz) +{ + time_t res = 0; + char buf[8]; + cch_t * pz; + + if (strlen (in_pz) != 8) + { + errno = EINVAL; + return BAD_TIME; + } + + memcpy (buf, in_pz, 4); + buf[4] = NUL; + pz = buf; + res = parse_scaled_value (0, &pz, buf + 4, SEC_PER_YEAR); + + memcpy (buf, in_pz + 4, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MONTH); + + memcpy (buf, in_pz + 6, 2); + buf[2] = NUL; + pz = buf; + return parse_scaled_value (res, &pz, buf + 2, SEC_PER_DAY); +} + +/* Parses the syntax yy Y mm M ww W dd D. */ +static time_t +parse_YMWD (cch_t * pz) +{ + time_t res = 0; + cch_t * ps = strchr (pz, 'Y'); + if (ps != NULL) + { + res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); + pz++; + } + + ps = strchr (pz, 'M'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); + pz++; + } + + ps = strchr (pz, 'W'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_WEEK); + pz++; + } + + ps = strchr (pz, 'D'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_DAY); + pz++; + } + + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return res; +} + +/* Parses the syntax HH:MM:SS. + PS points into the string, after "HH", before ":MM:SS". */ +static time_t +parse_hour_minute_second (cch_t * pz, cch_t * ps) +{ + time_t res = 0; + + res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); + + pz++; + ps = strchr (pz, ':'); + if (ps == NULL) + { + errno = EINVAL; + return BAD_TIME; + } + + res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); + + pz++; + ps = pz + strlen (pz); + return parse_scaled_value (res, &pz, ps, 1); +} + +/* Parses the syntax HHMMSS. */ +static time_t +parse_hourminutesecond (cch_t * in_pz) +{ + time_t res = 0; + char buf[4]; + cch_t * pz; + + if (strlen (in_pz) != 6) + { + errno = EINVAL; + return BAD_TIME; + } + + memcpy (buf, in_pz, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (0, &pz, buf + 2, SEC_PER_HR); + + memcpy (buf, in_pz + 2, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MIN); + + memcpy (buf, in_pz + 4, 2); + buf[2] = NUL; + pz = buf; + return parse_scaled_value (res, &pz, buf + 2, 1); +} + +/* Parses the syntax hh H mm M ss S. */ +static time_t +parse_HMS (cch_t * pz) +{ + time_t res = 0; + cch_t * ps = strchr (pz, 'H'); + if (ps != NULL) + { + res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); + pz++; + } + + ps = strchr (pz, 'M'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); + pz++; + } + + ps = strchr (pz, 'S'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, 1); + pz++; + } + + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return res; +} + +/* Parses a time (hours, minutes, seconds) specification in either syntax. */ +static time_t +parse_time (cch_t * pz) +{ + cch_t * ps; + time_t res = 0; + + /* + * Scan for a hyphen + */ + ps = strchr (pz, ':'); + if (ps != NULL) + { + res = parse_hour_minute_second (pz, ps); + } + + /* + * Try for a 'H', 'M' or 'S' suffix + */ + else if (ps = strpbrk (pz, "HMS"), + ps == NULL) + { + /* Its a YYYYMMDD format: */ + res = parse_hourminutesecond (pz); + } + + else + res = parse_HMS (pz); + + return res; +} + +/* Returns a substring of the given string, with spaces at the beginning and at + the end destructively removed, per SNOBOL. */ +static char * +trim (char * pz) +{ + /* trim leading white space */ + while (isspace ((unsigned char)*pz)) + pz++; + + /* trim trailing white space */ + { + char * pe = pz + strlen (pz); + while ((pe > pz) && isspace ((unsigned char)pe[-1])) + pe--; + *pe = NUL; + } + + return pz; +} + +/* + * Parse the year/months/days of a time period + */ +static time_t +parse_period (cch_t * in_pz) +{ + char * pT; + char * ps; + char * pz = strdup (in_pz); + void * fptr = pz; + time_t res = 0; + + if (pz == NULL) + { + errno = ENOMEM; + return BAD_TIME; + } + + pT = strchr (pz, 'T'); + if (pT != NULL) + { + *(pT++) = NUL; + pz = trim (pz); + pT = trim (pT); + } + + /* + * Scan for a hyphen + */ + ps = strchr (pz, '-'); + if (ps != NULL) + { + res = parse_year_month_day (pz, ps); + } + + /* + * Try for a 'Y', 'M' or 'D' suffix + */ + else if (ps = strpbrk (pz, "YMWD"), + ps == NULL) + { + /* Its a YYYYMMDD format: */ + res = parse_yearmonthday (pz); + } + + else + res = parse_YMWD (pz); + + if ((errno == 0) && (pT != NULL)) + { + time_t val = parse_time (pT); + res = scale_n_add (res, val, 1); + } + + free (fptr); + return res; +} + +static time_t +parse_non_iso8601 (cch_t * pz) +{ + whats_done_t whatd_we_do = NOTHING_IS_DONE; + + time_t res = 0; + + do { + time_t val; + + errno = 0; + val = str_const_to_l (pz, &pz, 10); + if (errno != 0) + goto bad_time; + + /* IF we find a colon, then we're going to have a seconds value. + We will not loop here any more. We cannot already have parsed + a minute value and if we've parsed an hour value, then the result + value has to be less than an hour. */ + if (*pz == ':') + { + if (whatd_we_do >= MINUTE_IS_DONE) + break; + + val = parse_hr_min_sec (val, pz); + + if ((whatd_we_do == HOUR_IS_DONE) && (val >= SEC_PER_HR)) + break; + + return scale_n_add (res, val, 1); + } + + { + unsigned int mult; + + /* Skip over white space following the number we just parsed. */ + while (isspace ((unsigned char)*pz)) + pz++; + + switch (*pz) + { + default: goto bad_time; + case NUL: + return scale_n_add (res, val, 1); + + case 'y': case 'Y': + if (whatd_we_do >= YEAR_IS_DONE) + goto bad_time; + mult = SEC_PER_YEAR; + whatd_we_do = YEAR_IS_DONE; + break; + + case 'M': + if (whatd_we_do >= MONTH_IS_DONE) + goto bad_time; + mult = SEC_PER_MONTH; + whatd_we_do = MONTH_IS_DONE; + break; + + case 'W': + if (whatd_we_do >= WEEK_IS_DONE) + goto bad_time; + mult = SEC_PER_WEEK; + whatd_we_do = WEEK_IS_DONE; + break; + + case 'd': case 'D': + if (whatd_we_do >= DAY_IS_DONE) + goto bad_time; + mult = SEC_PER_DAY; + whatd_we_do = DAY_IS_DONE; + break; + + case 'h': + if (whatd_we_do >= HOUR_IS_DONE) + goto bad_time; + mult = SEC_PER_HR; + whatd_we_do = HOUR_IS_DONE; + break; + + case 'm': + if (whatd_we_do >= MINUTE_IS_DONE) + goto bad_time; + mult = SEC_PER_MIN; + whatd_we_do = MINUTE_IS_DONE; + break; + + case 's': + mult = 1; + whatd_we_do = SECOND_IS_DONE; + break; + } + + res = scale_n_add (res, val, mult); + + pz++; + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz == NUL) + return res; + + if (! isdigit ((unsigned char)*pz)) + break; + } + + } while (whatd_we_do < SECOND_IS_DONE); + + bad_time: + errno = EINVAL; + return BAD_TIME; +} + +time_t +parse_duration (char const * pz) +{ + while (isspace ((unsigned char)*pz)) + pz++; + + switch (*pz) + { + case 'P': + return parse_period (pz + 1); + + case 'T': + return parse_time (pz + 1); + + default: + if (isdigit ((unsigned char)*pz)) + return parse_non_iso8601 (pz); + + errno = EINVAL; + return BAD_TIME; + } +} + +/* + * Local Variables: + * mode: C + * c-file-style: "gnu" + * indent-tabs-mode: nil + * End: + * end of parse-duration.c */ diff --git a/autoopts/parse-duration.h b/autoopts/parse-duration.h new file mode 100644 index 0000000..05570a0 --- /dev/null +++ b/autoopts/parse-duration.h @@ -0,0 +1,90 @@ +/* Parse a time duration and return a seconds count + Copyright (C) 2008-2012 Free Software Foundation, Inc. + Written by Bruce Korb <bkorb@gnu.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* + + Readers and users of this function are referred to the ISO-8601 + specification, with particular attention to "Durations". + + At the time of writing, this worked: + + http://en.wikipedia.org/wiki/ISO_8601#Durations + + The string must start with a 'P', 'T' or a digit. + + ==== if it is a digit + + the string may contain: NNN Y NNN M NNN W NNN d NNN h NNN m NNN s + This represents NNN years, NNN months, NNN weeks, NNN days, NNN hours, + NNN minutes and NNN seconds. + The embedded white space is optional. + These terms must appear in this order. + Case is significant: 'M' is months and 'm' is minutes. + The final "s" is optional. + All of the terms ("NNN" plus designator) are optional. + Minutes and seconds may optionally be represented as NNN:NNN. + Also, hours, minute and seconds may be represented as NNN:NNN:NNN. + There is no limitation on the value of any of the terms, except + that the final result must fit in a time_t value. + + ==== if it is a 'P' or 'T', please see ISO-8601 for a rigorous definition. + + The 'P' term may be followed by any of three formats: + yyyymmdd + yy-mm-dd + yy Y mm M ww W dd D + + or it may be empty and followed by a 'T'. The "yyyymmdd" must be eight + digits long. + + NOTE! Months are always 30 days and years are always 365 days long. + 5 years is always 1825 days, not 1826 or 1827 depending on leap year + considerations. 3 months is always 90 days. There is no consideration + for how many days are in the current, next or previous months. + + For the final format: + * Embedded white space is allowed, but it is optional. + * All of the terms are optional. Any or all-but-one may be omitted. + * The meanings are yy years, mm months, ww weeks and dd days. + * The terms must appear in this order. + + ==== The 'T' term may be followed by any of these formats: + + hhmmss + hh:mm:ss + hh H mm M ss S + + For the final format: + * Embedded white space is allowed, but it is optional. + * All of the terms are optional. Any or all-but-one may be omitted. + * The terms must appear in this order. + + */ +#ifndef GNULIB_PARSE_DURATION_H +#define GNULIB_PARSE_DURATION_H + +#include <time.h> + +/* Return value when a valid duration cannot be parsed. */ +#define BAD_TIME ((time_t)~0) + +/* Parses the given string. If it has the syntax of a valid duration, + this duration is returned. Otherwise, the return value is BAD_TIME, + and errno is set to either EINVAL (bad syntax) or ERANGE (out of range). */ +extern time_t parse_duration (char const * in_pz); + +#endif /* GNULIB_PARSE_DURATION_H */ diff --git a/autoopts/pgusage.c b/autoopts/pgusage.c new file mode 100644 index 0000000..7eae2b0 --- /dev/null +++ b/autoopts/pgusage.c @@ -0,0 +1,132 @@ + +/** + * \file pgusage.c + * + * Time-stamp: "2012-02-28 19:49:32 bkorb" + * + * Automated Options Paged Usage module. + * + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionPagedUsage + * private: + * + * what: Decipher a boolean value + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Run the usage output through a pager. + * This is very handy if it is very long. + * This is disabled on platforms without a working fork() function. +=*/ +void +optionPagedUsage(tOptions * pOptions, tOptDesc * pOD) +{ +#if ! defined(HAVE_WORKING_FORK) + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + (*pOptions->pUsageProc)(pOptions, EXIT_SUCCESS); +#else + static pid_t my_pid; + char zPageUsage[ 1024 ]; + + /* + * IF we are being called after the usage proc is done + * (and thus has called "exit(2)") + * THEN invoke the pager to page through the usage file we created. + */ + switch (pagerState) { + case PAGER_STATE_INITIAL: + { + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + my_pid = getpid(); + snprintf(zPageUsage, sizeof(zPageUsage), TMP_USAGE_FMT, (tAoUL)my_pid); + unlink(zPageUsage); + + /* + * Set usage output to this temporary file + */ + option_usage_fp = fopen(zPageUsage, "w" FOPEN_BINARY_FLAG); + if (option_usage_fp == NULL) + _exit(EXIT_FAILURE); + + pagerState = PAGER_STATE_READY; + + /* + * Set up so this routine gets called during the exit logic + */ + atexit((void(*)(void))optionPagedUsage); + + /* + * The usage procedure will now put the usage information into + * the temporary file we created above. + */ + (*pOptions->pUsageProc)(pOptions, EXIT_SUCCESS); + + /* NOTREACHED */ + _exit(EXIT_FAILURE); + } + + case PAGER_STATE_READY: + { + tCC* pzPager = (tCC*)getenv(PAGER_NAME); + + /* + * Use the "more(1)" program if "PAGER" has not been defined + */ + if (pzPager == NULL) + pzPager = MORE_STR; + + /* + * Page the file and remove it when done. + */ + snprintf(zPageUsage, sizeof(zPageUsage), PAGE_USAGE_FMT, pzPager, + (tAoUL)my_pid); + fclose(stderr); + dup2(STDOUT_FILENO, STDERR_FILENO); + + (void)system(zPageUsage); + } + + case PAGER_STATE_CHILD: + /* + * This is a child process used in creating shell script usage. + */ + break; + } +#endif +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/pgusage.c */ diff --git a/autoopts/po/usage-txt.pot b/autoopts/po/usage-txt.pot new file mode 100644 index 0000000..0b2fe6c --- /dev/null +++ b/autoopts/po/usage-txt.pot @@ -0,0 +1,474 @@ +# Automated Option parsing usage text. +# copyright (c) 1999-2012 by Bruce Korb - all rights reserved +# This file is distributed under the same license as the AutoOpts package. +# Bruce Korb <bkorb@gnu.org> 2012 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: autogen 5.16.2\n" +"Report-Msgid-Bugs-To: autogen-users@lists.sourceforge.net\n" +"POT-Creation-Date: 2012-08-11 09:41-0700\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: autoopts.c:70 +msgid "malloc of %d bytes failed\n" + +#: configfile.c:1353 +msgid "AutoOpts function called without option descriptor\n" + +#: configfile.c:1388 +msgid "\tThis exceeds the compiled library version: " + +#: configfile.c:1386 +msgid "Automated Options Processing Error!\n" + "\t%s called AutoOpts function with structure version %d:%d:%d.\n" + +#: autoopts.c:83 +msgid "realloc of %d bytes at 0x%p failed\n" + +#: configfile.c:1390 +msgid "\tThis is less than the minimum library version: " + +#: autoopts.c:96 +msgid "strdup of %d byte string failed\n" + +#: version.c:124 +msgid "Automated Options version %s\n" + "\tcopyright (c) 1999-2012 by Bruce Korb - all rights reserved\n" + +#: autoopts.c:360 +msgid "AutoOpts lib error: defaulted to option with optional arg\n" + +#: alias.c:55 +msgid "(AutoOpts bug): Aliasing option is out of range." + +#: enum.c:488 +msgid "all" + +#: usage.c:607 +msgid "\t\t\t\t- an alternate for %s\n" + +#: enum.c:230 +msgid "%s error: the keyword `%s' is ambiguous for %s\n" + +#: find.c:76 +msgid " The following options match:\n" + +#: find.c:258 +msgid "%s: ambiguous option name: %s (matches %d options)\n" + +#: find.c:79 find.c:84 +msgid " %s%s\n" + +#: check.c:159 +msgid "%s: Command line arguments required\n" + +#: alias.c:80 autoopts.c:228 +msgid "%d %s%s options allowed\n" + +#: usage.c:867 +msgid "version, usage and configuration options:" + +#: makeshell.c:261 +msgid "Error %d (%s) from the pipe(2) syscall\n" + +#: version.c:164 +msgid "ERROR: version option argument '%c' invalid. Use:\n" + "\t'v' - version only\n" + "\t'c' - version and copyright\n" + "\t'n' - version and copyright notice\n" + +#: check.c:58 +msgid "ERROR: %s option conflicts with the %s option\n" + +#: restore.c:109 +msgid "%s(optionSaveState): error: cannot allocate %d bytes\n" + +#: configfile.c:588 +msgid "auto-options" + +#: configfile.c:587 configfile.c:660 configfile.c:665 +msgid "program" + +#: usage.c:656 +msgid "\t\t\t\t- default option for unnamed options\n" + +#: usage.c:571 +msgid "\t\t\t\t- disabled as --%s\n" + +#: find.c:182 find.c:389 +msgid "%s: The ``%s'' option has been disabled" + +#: usage.c:836 +msgid " --- %-14s %s\n" + +#: usage.c:834 +msgid "This option has been disabled" + +#: usage.c:598 +msgid "\t\t\t\t- enabled by default\n" + +#: alias.c:75 autoopts.c:223 +msgid "-equivalence" + +#: alias.c:77 autoopts.c:225 +msgid "ERROR: only " + +#: usage.c:911 +msgid " - examining environment variables named %s_*\n" + +#: usage.c:1015 +msgid " " + +#: usage.c:275 +msgid "Options are specified by doubled hyphens and their name or by a single\n" + "hyphen and the flag character.\n" + +#: usage.c:250 usage.c:255 +msgid "%%-%ds %%s\n" + +#: makeshell.c:267 +msgid "fs error %d (%s) on fork - cannot obtain %s usage\n" + +#: makeshell.c:759 +msgid "fs error %d (%s) on freopen\n" + +#: configfile.c:1149 +msgid "File error %d (%s) opening %s for loading options\n" + +#: text_mmap.c:100 +msgid "fs error %d (%s) reading file %s\n" + +#: file.c:49 file.c:75 file.c:87 file.c:109 file.c:136 +msgid "fs error %d (%s) on %s %s for option %s\n" + +#: file.c:76 +msgid "stat-ing for directory" + +#: file.c:88 +msgid "stat-ing for regular file" + +#: file.c:50 +msgid "stat-ing for non-existant file" + +#: file.c:110 +msgid "open-ing file" + +#: file.c:137 +msgid "fopen-ing file" + +#: file.c:177 +msgid "\t\t\t\t- file must not pre-exist\n" + +#: file.c:181 +msgid "\t\t\t\t- file must pre-exist\n" + +#: makeshell.c:837 +msgid "\n" + "= = = = = = = =\n\n" + "This incarnation of genshell will produce\n" + "a shell script to parse the options for %s:\n\n" + +#: usage.c:971 usage.c:985 +msgid "=T/F" + +#: usage.c:975 +msgid "\n" + "%s\n\n" + +#: usage.c:967 usage.c:985 +msgid "=KWd" + +#: usage.c:970 +msgid "=file" + +#: usage.c:968 +msgid "=Mbr" + +#: usage.c:969 +msgid "=Tim" + +#: usage.c:972 +msgid "=Cplx" + +#: usage.c:966 usage.c:985 +msgid "=num" + +#: usage.c:973 +msgid "[=arg]" + +#: usage.c:980 usage.c:981 usage.c:982 +msgid "--%2$s%1$s" + +#: usage.c:964 usage.c:985 +msgid "=str" + +#: find.c:428 reset.c:108 +msgid "%s: illegal option -- %c\n" + +#: find.c:236 find.c:554 reset.c:116 +msgid "%s: illegal option -- %s\n" + +#: find.c:300 +msgid "%s: unknown vendor extension option -- %s\n" + +#: enum.c:155 enum.c:165 +msgid " or an integer from %d through %d\n" + +#: usage.c:486 usage.c:800 +msgid "AutoOpts ERROR: invalid option descriptor for %s\n" + +#: find.c:347 +msgid "%s: invalid option name: %s\n" + +#: enum.c:162 +msgid " or an integer mask with any of the lower %d bits set\n" + +#: usage.c:631 +msgid "\t\t\t\t- is a set membership option\n" + +#: autoopts.c:290 +msgid "%s: option `%s' requires an argument\n" + +#: autoopts.c:175 +msgid "Equivalenced option '%s' was equivalenced to both\n" + "\t'%s' and '%s'" + +#: usage.c:651 +msgid "\t\t\t\t- must appear between %d and %d times\n" + +#: check.c:92 +msgid "ERROR: The %s option is required\n" + +#: autoopts.c:389 +msgid "%s: option `%s' cannot have an argument\n" + +#: check.c:149 +msgid "%s: Command line arguments not allowed\n" + +#: save.c:512 +msgid "error %d (%s) creating %s\n" + +#: usage.c:277 +msgid "Options are specified by single or double hyphens and their name.\n" + +#: enum.c:230 +msgid "%s error: `%s' does not match any %s keywords\n" + +#: usage.c:638 +msgid "\t\t\t\t- may appear multiple times\n" + +#: usage.c:625 +msgid "\t\t\t\t- may not be preset\n" + +#: reset.c:91 +msgid "The 'reset-option' option requires an argument\n" + +#: usage.c:1026 +msgid " Arg Option-Name Description\n" + +#: usage.c:962 usage.c:1020 +msgid " Flg Arg Option-Name Description\n" + +#: save.c:179 save.c:233 +msgid "error %d (%s) stat-ing %s\n" + +#: restore.c:150 +msgid "%s(optionRestore): error: no saved option state\n" + +#: enum.c:493 +msgid "none" + +#: save.c:128 +msgid "'%s' not defined\n" + +#: autoopts.c:421 +msgid "'%s' is not a command line option\n" + +#: check.c:91 +msgid "ERROR: The %s option must appear %d times\n" + +#: configfile.c:1159 makeshell.c:684 save.c:252 +msgid "error: cannot load options from non-regular file %s\n" + +#: numeric.c:151 +msgid "%s error: `%s' is not a recognizable number\n" + +#: time.c:112 +msgid "%s error: `%s' is not a recognizable date/time\n" + +#: time.c:51 +msgid "%s error: `%s' is not a recognizable time duration\n" + +#: usage.c:1021 usage.c:1027 +msgid " %3s %s" + +#: usage.c:282 +msgid "The '-#<number>' option may omit the hash char\n" + +#: alias.c:82 autoopts.c:230 +msgid "one %s%s option allowed\n" + +#: usage.c:278 +msgid "All arguments are named options.\n" + +#: makeshell.c:176 makeshell.c:859 usage.c:234 usage.c:309 version.c:170 +msgid "Write failure to output file" + +#: usage.c:703 +msgid " - reading file %s" + +#: usage.c:304 version.c:108 version.c:130 +msgid "\n" + "please send bug reports to: %s\n" + +#: usage.c:637 +msgid "\t\t\t\t- may NOT appear - preset only\n" + +#: save.c:532 +msgid "# preset/initialization file\n" + "# %s#\n" + +#: usage.c:675 usage.c:909 +msgid "\n" + "The following option preset mechanisms are supported:\n" + +#: usage.c:421 +msgid "prohibits these options:\n" + +#: usage.c:285 +msgid "Operands and options may be intermixed. They will be reordered.\n" + +#: numeric.c:75 +msgid "%s%ld to %ld" + +#: numeric.c:73 +msgid "%sgreater than or equal to %ld" + +#: numeric.c:64 +msgid "%sIt must lie in one of the ranges:\n" + +#: numeric.c:64 +msgid "%sIt must be in the range:\n" + +#: numeric.c:82 +msgid ", or\n" + +#: numeric.c:56 +msgid "%s error: %s option value %ld is out of range.\n" + +#: numeric.c:69 +msgid "%s%ld exactly" + +#: numeric.c:62 +msgid "%sis scalable with a suffix: k/K/m/M/g/G/t/T\n" + +#: numeric.c:71 +msgid "%sless than or equal to %ld" + +#: reset.c:86 +msgid "The --reset-option has not been configured.\n" + +#: check.c:45 +msgid "ERROR: %s option requires the %s option\n" + +#: usage.c:1033 usage.c:1039 +msgid " %3s %-14s %s" + +#: usage.c:403 +msgid "requires these options:\n" + +#: usage.c:1038 +msgid " Arg Option-Name Req? Description\n" + +#: usage.c:1032 +msgid " Flg Arg Option-Name Req? Description\n" + +#: configfile.c:1420 +msgid "-_^" + +#: enum.c:163 +msgid "or you may use a numeric representation. Preceding these with a '!' will\n" + "clear the bits, specifying 'none' will clear all bits, and 'all' will set them\n" + "all. Multiple entries may be passed as an option argument list.\n" + +#: usage.c:984 +msgid "%s" + +#: usage.c:976 +msgid " " + +#: usage.c:1010 +msgid "T/F" + +#: usage.c:1014 +msgid "\n" + "%s\n\n" + "%s" + +#: usage.c:1009 +msgid "Fil" + +#: usage.c:1006 +msgid "KWd" + +#: usage.c:1007 +msgid "Mbr" + +#: usage.c:1008 +msgid "Tim" + +#: usage.c:1011 +msgid "Cpx" + +#: usage.c:1013 +msgid "no " + +#: usage.c:1005 +msgid "Num" + +#: usage.c:1012 +msgid "opt" + +#: usage.c:1004 +msgid "YES" + +#: usage.c:1003 +msgid "Str" + +#: usage.c:395 +msgid "\t\t\t\t- " + +#: usage.c:412 +msgid "\t\t\t\t-- and " + +#: usage.c:405 usage.c:423 usage.c:514 +msgid "\t\t\t\t%s\n" + +#: usage.c:977 +msgid " " + +#: enum.c:196 +msgid "%s error: %s exceeds %s keyword count\n" + +#: usage.c:1016 +msgid " " + +#: usage.c:643 +msgid "\t\t\t\t- may appear up to %d times\n" + +#: enum.c:73 +msgid "The valid \"%s\" option keywords are:\n" + +#: usage.c:514 +msgid "These additional options are:" + +#: usage.c:871 +msgid "The next option supports vendor supported extra options:" + diff --git a/autoopts/project.h b/autoopts/project.h new file mode 100644 index 0000000..c0df391 --- /dev/null +++ b/autoopts/project.h @@ -0,0 +1,50 @@ + +#ifndef AUTOGEN_PROJECT_H +#define AUTOGEN_PROJECT_H + +#include "config.h" +#include "compat/compat.h" +#include "ag-char-map.h" + +/* + * Procedure success codes + * + * USAGE: define procedures to return "tSuccess". Test their results + * with the SUCCEEDED, FAILED and HADGLITCH macros. + * + * Microsoft sticks its nose into user space here, so for Windows' sake, + * make sure all of these are undefined. + */ +#undef SUCCESS +#undef FAILURE +#undef PROBLEM +#undef SUCCEEDED +#undef SUCCESSFUL +#undef FAILED +#undef HADGLITCH + +#define SUCCESS ((tSuccess) 0) +#define FAILURE ((tSuccess)-1) +#define PROBLEM ((tSuccess) 1) + +typedef int tSuccess; + +#define SUCCEEDED(p) ((p) == SUCCESS) +#define SUCCESSFUL(p) SUCCEEDED(p) +#define FAILED(p) ((p) < SUCCESS) +#define HADGLITCH(p) ((p) > SUCCESS) + +#ifndef STR +# define __STR(s) #s +# define STR(s) __STR(s) +#endif + +#ifdef DEFINING +# define VALUE(s) = s +# define MODE +#else +# define VALUE(s) +# define MODE extern +#endif + +#endif /* AUTOGEN_PROJECT_H */ diff --git a/autoopts/proto.h b/autoopts/proto.h new file mode 100644 index 0000000..f52c74a --- /dev/null +++ b/autoopts/proto.h @@ -0,0 +1,130 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * Prototypes for autoopts + * Generated Sat Aug 11 09:41:23 PDT 2012 + */ +#ifndef AUTOOPTS_PROTO_H_GUARD +#define AUTOOPTS_PROTO_H_GUARD 1 + +#ifndef LOCAL +# define LOCAL extern +# define REDEF_LOCAL 1 +#else +# undef REDEF_LOCAL +#endif +/* + * Extracted from autoopts.c + */ +LOCAL void * +ao_malloc(size_t sz); + +LOCAL void * +ao_realloc(void *p, size_t sz); + +LOCAL char * +ao_strdup(char const *str); + +LOCAL tSuccess +handle_opt(tOptions * pOpts, tOptState* pOptState); + +LOCAL tSuccess +immediate_opts(tOptions * pOpts); + +LOCAL tSuccess +regular_opts(tOptions * pOpts); + +/* + * Extracted from check.c + */ +LOCAL bool +is_consistent(tOptions * pOpts); + +/* + * Extracted from configfile.c + */ +LOCAL void +intern_file_load(tOptions* pOpts); + +LOCAL char* +parse_attrs(tOptions * pOpts, char * pzText, tOptionLoadMode * pMode, + tOptionValue * pType); + +LOCAL tSuccess +validate_struct(tOptions * pOpts, char const * pzProgram); + +/* + * Extracted from env.c + */ +LOCAL void +doPrognameEnv(tOptions * pOpts, teEnvPresetType type); + +LOCAL void +env_presets(tOptions * pOpts, teEnvPresetType type); + +/* + * Extracted from find.c + */ +LOCAL tSuccess +opt_find_long(tOptions * opts, char const * opt_name, tOptState * state); + +LOCAL tSuccess +opt_find_short(tOptions* pOpts, uint_t optValue, tOptState* pOptState); + +LOCAL tSuccess +get_opt_arg(tOptions * pOpts, tOptState * pOptState); + +LOCAL tSuccess +find_opt(tOptions * pOpts, tOptState * pOptState); + +/* + * Extracted from load.c + */ +LOCAL void +mungeString(char * txt, tOptionLoadMode mode); + +LOCAL void +loadOptionLine( + tOptions * opts, + tOptState * opt_state, + char * line, + tDirection direction, + tOptionLoadMode load_mode ); + +/* + * Extracted from nested.c + */ +LOCAL void +unload_arg_list(tArgList* pAL); + +LOCAL tOptionValue* +optionLoadNested(char const* pzTxt, char const* pzName, size_t nameLen); + +LOCAL int +get_special_char(char const ** ppz, int * ct); + +LOCAL void +emit_special_char(FILE * fp, int ch); + +/* + * Extracted from sort.c + */ +LOCAL void +optionSort(tOptions* pOpts); + +/* + * Extracted from stack.c + */ +LOCAL void +addArgListEntry(void** ppAL, void* entry); + +/* + * Extracted from usage.c + */ +LOCAL void +set_usage_flags(tOptions * opts, char const * flg_txt); + +#ifdef REDEF_LOCAL +# undef LOCAL +# define LOCAL +#endif +#endif /* AUTOOPTS_PROTO_H_GUARD */ diff --git a/autoopts/putshell.c b/autoopts/putshell.c new file mode 100644 index 0000000..d8e2d91 --- /dev/null +++ b/autoopts/putshell.c @@ -0,0 +1,361 @@ + +/** + * \file putshell.c + * + * Time-stamp: "2012-03-31 13:14:18 bkorb" + * + * This module will interpret the options set in the tOptions + * structure and print them to standard out in a fashion that + * will allow them to be interpreted by the Bourne or Korn shells. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static void +print_quot_str(char const * pzStr); + +static void +print_enumeration(tOptions * pOpts, tOptDesc * pOD); + +static void +print_membership(tOptions * pOpts, tOptDesc * pOD); + +static void +print_stacked_arg(tOptions * pOpts, tOptDesc * pOD); + +static void +print_reordering(tOptions * pOpts); +/* = = = END-STATIC-FORWARD = = = */ + +/* + * Make sure embedded single quotes come out okay. The initial quote has + * been emitted and the closing quote will be upon return. + */ +static void +print_quot_str(char const * pzStr) +{ + /* + * Handle empty strings to make the rest of the logic simpler. + */ + if ((pzStr == NULL) || (*pzStr == NUL)) { + fputs(EMPTY_ARG, stdout); + return; + } + + /* + * Emit any single quotes/apostrophes at the start of the string and + * bail if that is all we need to do. + */ + while (*pzStr == '\'') { + fputs(QUOT_APOS, stdout); + pzStr++; + } + if (*pzStr == NUL) + return; + + /* + * Start the single quote string + */ + fputc('\'', stdout); + for (;;) { + char const * pz = strchr(pzStr, '\''); + if (pz == NULL) + break; + + /* + * Emit the string up to the single quote (apostrophe) we just found. + */ + (void)fwrite(pzStr, (size_t)(pz - pzStr), (size_t)1, stdout); + fputc('\'', stdout); + pzStr = pz; + + /* + * Emit an escaped apostrophe for every one we find. + * If that ends the string, do not re-open the single quotes. + */ + while (*++pzStr == '\'') fputs("\\'", stdout); + if (*pzStr == NUL) + return; + + fputc('\'', stdout); + } + + /* + * If we broke out of the loop, we must still emit the remaining text + * and then close the single quote string. + */ + fputs(pzStr, stdout); + fputc('\'', stdout); +} + +static void +print_enumeration(tOptions * pOpts, tOptDesc * pOD) +{ + uintptr_t e_val = pOD->optArg.argEnum; + printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + + /* + * Convert value to string, print that and restore numeric value. + */ + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + printf(QUOT_ARG_FMT, pOD->optArg.argString); + if (pOD->fOptState & OPTST_ALLOC_ARG) + AGFREE(pOD->optArg.argString); + pOD->optArg.argEnum = e_val; + + printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); +} + +static void +print_membership(tOptions * pOpts, tOptDesc * pOD) +{ + char const * pz; + uintptr_t val = 1; + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (int)(uintptr_t)(pOD->optCookie)); + pOD->optCookie = (void*)(uintptr_t)~0UL; + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + + /* + * We are building the typeset list. The list returned starts with + * 'none + ' for use by option saving stuff. We must ignore that. + */ + pz = pOD->optArg.argString + 7; + while (*pz != NUL) { + printf("typeset -x -i %s_", pOD->pz_NAME); + pz = SPN_PLUS_N_SPACE_CHARS(pz); + + for (;;) { + int ch = *(pz++); + if (IS_LOWER_CASE_CHAR(ch)) fputc(toupper(ch), stdout); + else if (IS_UPPER_CASE_CHAR(ch)) fputc(ch, stdout); + else if (IS_PLUS_N_SPACE_CHAR(ch)) goto name_done; + else if (ch == NUL) { pz--; goto name_done; } + else fputc('_', stdout); + } name_done:; + printf(SHOW_VAL_FMT, (unsigned long)val); + val <<= 1; + } + + AGFREE(pOD->optArg.argString); + pOD->optArg.argString = NULL; + pOD->fOptState &= ~OPTST_ALLOC_ARG; +} + +static void +print_stacked_arg(tOptions * pOpts, tOptDesc * pOD) +{ + tArgList* pAL = (tArgList*)pOD->optCookie; + tCC** ppz = pAL->apzArgs; + int ct = pAL->useCt; + + printf(zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct); + + while (--ct >= 0) { + printf(ARG_BY_NUM_FMT, pOpts->pzPROGNAME, pOD->pz_NAME, + pAL->useCt - ct); + print_quot_str(*(ppz++)); + printf(EXPORT_ARG_FMT, pOpts->pzPROGNAME, pOD->pz_NAME, + pAL->useCt - ct); + } +} + +static void +print_reordering(tOptions * pOpts) +{ + unsigned int optIx; + + fputs(set_dash, stdout); + + for (optIx = pOpts->curOptIdx; + optIx < pOpts->origArgCt; + optIx++) { + + char* pzArg = pOpts->origArgVect[ optIx ]; + + if (strchr(pzArg, '\'') == NULL) + printf(arg_fmt, pzArg); + + else { + fputs(" '", stdout); + for (;;) { + char ch = *(pzArg++); + switch (ch) { + case '\'': fputs(apostrophy, stdout); break; + case NUL: goto arg_done; + default: fputc(ch, stdout); break; + } + } arg_done:; + fputc('\'', stdout); + } + } + fputs(init_optct, stdout); +} + +/*=export_func optionPutShell + * what: write a portable shell script to parse options + * private: + * arg: tOptions*, pOpts, the program options descriptor + * doc: This routine will emit portable shell script text for parsing + * the options described in the option definitions. +=*/ +void +optionPutShell(tOptions* pOpts) +{ + int optIx = 0; + + printf(zOptCtFmt, pOpts->curOptIdx-1); + + do { + tOptDesc* pOD = pOpts->pOptDesc + optIx; + + if ((pOD->fOptState & OPTST_NO_OUTPUT_MASK) != 0) + continue; + + /* + * Equivalence classes are hard to deal with. Where the + * option data wind up kind of squishes around. For the purposes + * of emitting shell state, they are not recommended, but we'll + * do something. I guess we'll emit the equivalenced-to option + * at the point in time when the base option is found. + */ + if (pOD->optEquivIndex != NO_EQUIVALENT) + continue; /* equivalence to a different option */ + + /* + * Equivalenced to a different option. Process the current option + * as the equivalenced-to option. Keep the persistent state bits, + * but copy over the set-state bits. + */ + if (pOD->optActualIndex != optIx) { + tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex; + p->optArg = pOD->optArg; + p->fOptState &= OPTST_PERSISTENT_MASK; + p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK; + printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME); + pOD = p; + } + + /* + * If the argument type is a set membership bitmask, then we always + * emit the thing. We do this because it will always have some sort + * of bitmask value and we need to emit the bit values. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { + print_membership(pOpts, pOD); + continue; + } + + /* + * IF the option was either specified or it wakes up enabled, + * then we will emit information. Otherwise, skip it. + * The idea is that if someone defines an option to initialize + * enabled, we should tell our shell script that it is enabled. + */ + if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) + continue; + + /* + * Handle stacked arguments + */ + if ( (pOD->fOptState & OPTST_STACKED) + && (pOD->optCookie != NULL) ) { + print_stacked_arg(pOpts, pOD); + continue; + } + + /* + * If the argument has been disabled, + * Then set its value to the disablement string + */ + if ((pOD->fOptState & OPTST_DISABLED) != 0) { + printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME, + (pOD->pz_DisablePfx != NULL) + ? pOD->pz_DisablePfx : "false"); + continue; + } + + /* + * If the argument type is numeric, the last arg pointer + * is really the VALUE of the string that was pointed to. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) { + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (int)pOD->optArg.argInt); + continue; + } + + /* + * If the argument type is an enumeration, then it is much + * like a text value, except we call the callback function + * to emit the value corresponding to the "optArg" number. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) { + print_enumeration(pOpts, pOD); + continue; + } + + /* + * If the argument type is numeric, the last arg pointer + * is really the VALUE of the string that was pointed to. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) { + printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (pOD->optArg.argBool == 0) ? "false" : "true"); + continue; + } + + /* + * IF the option has an empty value, + * THEN we set the argument to the occurrence count. + */ + if ( (pOD->optArg.argString == NULL) + || (pOD->optArg.argString[0] == NUL) ) { + + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + pOD->optOccCt); + continue; + } + + /* + * This option has a text value + */ + printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + print_quot_str(pOD->optArg.argString); + printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + + } while (++optIx < pOpts->presetOptCt ); + + if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0) + && (pOpts->curOptIdx < pOpts->origArgCt)) + print_reordering(pOpts); + + fflush(stdout); +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/putshell.c */ diff --git a/autoopts/reset.c b/autoopts/reset.c new file mode 100644 index 0000000..ba61d12 --- /dev/null +++ b/autoopts/reset.c @@ -0,0 +1,138 @@ + +/** + * \file reset.c + * + * Time-stamp: "2012-08-11 08:35:11 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +static void +optionReset( tOptions* pOpts, tOptDesc* pOD ) +{ + pOD->fOptState &= OPTST_PERSISTENT_MASK; + pOD->fOptState |= OPTST_RESET; + if (pOD->pOptProc != NULL) + pOD->pOptProc(pOpts, pOD); + pOD->optArg.argString = + pOpts->originalOptArgArray[ pOD->optIndex ].argString; + pOD->optCookie = pOpts->originalOptArgCookie[ pOD->optIndex ]; + pOD->fOptState &= OPTST_PERSISTENT_MASK; +} + + +static void +optionResetEverything(tOptions * pOpts) +{ + tOptDesc * pOD = pOpts->pOptDesc; + int ct = pOpts->presetOptCt; + + for (;;) { + optionReset(pOpts, pOD); + + if (--ct <= 0) + break; + pOD++; + } +} + + +/*=export_func optionResetOpt + * private: + * + * what: Reset the value of an option + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * This code will cause another option to be reset to its initial state. + * For example, --reset=foo will cause the --foo option to be reset. +=*/ +void +optionResetOpt( tOptions* pOpts, tOptDesc* pOD ) +{ + static bool reset_active = false; + + tOptState opt_state = OPTSTATE_INITIALIZER(DEFINED); + char const * pzArg = pOD->optArg.argString; + tSuccess succ; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if (reset_active) + return; + + if ( (! HAS_originalOptArgArray(pOpts)) + || (pOpts->originalOptArgCookie == NULL)) { + fputs(zResetNotConfig, stderr); + _exit(EX_SOFTWARE); + } + + if ((pzArg == NULL) || (*pzArg == NUL)) { + fputs(zNoResetArg, stderr); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + + reset_active = true; + + if (pzArg[1] == NUL) { + if (*pzArg == '*') { + optionResetEverything(pOpts); + reset_active = false; + return; + } + + succ = opt_find_short(pOpts, (tAoUC)*pzArg, &opt_state); + if (! SUCCESSFUL(succ)) { + fprintf(stderr, zIllOptChr, pOpts->pzProgPath, *pzArg); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + } else { + succ = opt_find_long(pOpts, (char *)pzArg, &opt_state); + if (! SUCCESSFUL(succ)) { + fprintf(stderr, zIllOptStr, pOpts->pzProgPath, pzArg); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + } + + /* + * We've found the indicated option. Turn off all non-persistent + * flags because we're forcing the option back to its initialized state. + * Call any callout procedure to handle whatever it needs to. + * Finally, clear the reset flag, too. + */ + optionReset(pOpts, opt_state.pOD); + reset_active = false; +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/reset.c */ diff --git a/autoopts/restore.c b/autoopts/restore.c new file mode 100644 index 0000000..4fd76f8 --- /dev/null +++ b/autoopts/restore.c @@ -0,0 +1,228 @@ + +/* + * \file restore.c + * + * Time-stamp: "2010-08-22 11:04:00 bkorb" + * + * This module's routines will save the current option state to memory + * and restore it. If saved prior to the initial optionProcess call, + * then the initial state will be restored. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* + * optionFixupSavedOpts Really, it just wipes out option state for + * options that are troublesome to copy. viz., stacked strings and + * hierarcicaly valued option args. We do duplicate string args that + * have been marked as allocated though. + */ +static void +fixupSavedOptionArgs(tOptions* pOpts) +{ + tOptions* p = pOpts->pSavedState; + tOptDesc* pOD = pOpts->pOptDesc; + int ct = pOpts->optCt; + + /* + * Make sure that allocated stuff is only referenced in the + * archived copy of the data. + */ + for (; ct-- > 0; pOD++) { + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_STRING: + if (pOD->fOptState & OPTST_STACKED) { + tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); + q->optCookie = NULL; + } + if (pOD->fOptState & OPTST_ALLOC_ARG) { + tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); + AGDUPSTR(q->optArg.argString, pOD->optArg.argString, "arg"); + } + break; + + case OPARG_TYPE_HIERARCHY: + { + tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc); + q->optCookie = NULL; + } + } + } +} + +/*=export_func optionSaveState + * + * what: saves the option state to memory + * arg: tOptions*, pOpts, program options descriptor + * + * doc: + * + * This routine will allocate enough memory to save the current option + * processing state. If this routine has been called before, that memory + * will be reused. You may only save one copy of the option state. This + * routine may be called before optionProcess(3AO). If you do call it + * before the first call to optionProcess, then you may also change the + * contents of argc/argv after you call optionRestore(3AO) + * + * In fact, more strongly put: it is safest to only use this function + * before having processed any options. In particular, the saving and + * restoring of stacked string arguments and hierarchical values is + * disabled. The values are not saved. + * + * err: If it fails to allocate the memory, + * it will print a message to stderr and exit. + * Otherwise, it will always succeed. +=*/ +void +optionSaveState(tOptions* pOpts) +{ + tOptions* p = (tOptions*)pOpts->pSavedState; + + if (p == NULL) { + size_t sz = sizeof(*pOpts) + (pOpts->optCt * sizeof(tOptDesc)); + p = AGALOC(sz, "saved option state"); + if (p == NULL) { + tCC* pzName = pOpts->pzProgName; + if (pzName == NULL) { + pzName = pOpts->pzPROGNAME; + if (pzName == NULL) + pzName = zNil; + } + fprintf(stderr, zCantSave, pzName, sz); + exit(EXIT_FAILURE); + } + + pOpts->pSavedState = p; + } + + memcpy(p, pOpts, sizeof(*p)); + memcpy(p + 1, pOpts->pOptDesc, p->optCt * sizeof(tOptDesc)); + + fixupSavedOptionArgs(pOpts); +} + + +/*=export_func optionRestore + * + * what: restore option state from memory copy + * arg: tOptions*, pOpts, program options descriptor + * + * doc: Copy back the option state from saved memory. + * The allocated memory is left intact, so this routine can be + * called repeatedly without having to call optionSaveState again. + * If you are restoring a state that was saved before the first call + * to optionProcess(3AO), then you may change the contents of the + * argc/argv parameters to optionProcess. + * + * err: If you have not called @code{optionSaveState} before, a diagnostic is + * printed to @code{stderr} and exit is called. +=*/ +void +optionRestore(tOptions* pOpts) +{ + tOptions* p = (tOptions*)pOpts->pSavedState; + + if (p == NULL) { + tCC* pzName = pOpts->pzProgName; + if (pzName == NULL) { + pzName = pOpts->pzPROGNAME; + if (pzName == NULL) + pzName = zNil; + } + fprintf(stderr, zNoState, pzName); + exit(EXIT_FAILURE); + } + + pOpts->pSavedState = NULL; + optionFree(pOpts); + + memcpy(pOpts, p, sizeof(*p)); + memcpy(pOpts->pOptDesc, p+1, p->optCt * sizeof(tOptDesc)); + pOpts->pSavedState = p; + + fixupSavedOptionArgs(pOpts); +} + +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + +/*=export_func optionFree + * + * what: free allocated option processing memory + * arg: tOptions*, pOpts, program options descriptor + * + * doc: AutoOpts sometimes allocates memory and puts pointers to it in the + * option state structures. This routine deallocates all such memory. + * + * err: As long as memory has not been corrupted, + * this routine is always successful. +=*/ +void +optionFree(tOptions* pOpts) +{ + free_saved_state: + { + tOptDesc* p = pOpts->pOptDesc; + int ct = pOpts->optCt; + do { + if (p->fOptState & OPTST_ALLOC_ARG) { + AGFREE(p->optArg.argString); + p->optArg.argString = NULL; + p->fOptState &= ~OPTST_ALLOC_ARG; + } + + switch (OPTST_GET_ARGTYPE(p->fOptState)) { + case OPARG_TYPE_STRING: +#ifdef WITH_LIBREGEX + if ( (p->fOptState & OPTST_STACKED) + && (p->optCookie != NULL)) { + p->optArg.argString = ".*"; + optionUnstackArg(pOpts, p); + } +#else + /* leak memory */; +#endif + break; + + case OPARG_TYPE_HIERARCHY: + if (p->optCookie != NULL) + unload_arg_list(p->optCookie); + break; + } + + p->optCookie = NULL; + } while (p++, --ct > 0); + } + if (pOpts->pSavedState != NULL) { + tOptions * p = (tOptions*)pOpts->pSavedState; + memcpy(pOpts, p, sizeof(*p)); + memcpy(pOpts->pOptDesc, p+1, p->optCt * sizeof(tOptDesc)); + AGFREE(pOpts->pSavedState); + pOpts->pSavedState = NULL; + goto free_saved_state; + } +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/restore.c */ diff --git a/autoopts/save.c b/autoopts/save.c new file mode 100644 index 0000000..9e95056 --- /dev/null +++ b/autoopts/save.c @@ -0,0 +1,768 @@ + +/* + * \file save.c + * + * Time-stamp: "2012-03-31 13:15:19 bkorb" + * + * This module's routines will take the currently set options and + * store them into an ".rc" file for re-interpretation the next + * time the invoking program is run. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static char const * +find_dir_name(tOptions * pOpts, int * p_free); + +static char const * +find_file_name(tOptions * pOpts, int * p_free_name); + +static void +prt_entry(FILE * fp, tOptDesc * p, char const * pzLA); + +static void +prt_value(FILE * fp, int depth, tOptDesc * pOD, tOptionValue const * ovp); + +static void +prt_string(FILE * fp, char const * name, char const * pz); + +static void +prt_val_list(FILE * fp, char const * name, tArgList * al); + +static void +prt_nested(FILE * fp, tOptDesc * p); + +static FILE * +open_sv_file(tOptions* pOpts); + +static void +prt_no_arg_opt(FILE * fp, tOptDesc * p, tOptDesc * pOD); + +static void +prt_str_arg(FILE * fp, tOptDesc * pOD); + +static void +prt_enum_arg(FILE * fp, tOptDesc * pOD); + +static void +prt_set_arg(FILE * fp, tOptDesc * pOD); + +static void +prt_file_arg(FILE * fp, tOptDesc * pOD, tOptions* pOpts); +/* = = = END-STATIC-FORWARD = = = */ + +static char const * +find_dir_name(tOptions * pOpts, int * p_free) +{ + char const * pzDir; + + if ( (pOpts->specOptIdx.save_opts == NO_EQUIVALENT) + || (pOpts->specOptIdx.save_opts == 0)) + return NULL; + + pzDir = pOpts->pOptDesc[ pOpts->specOptIdx.save_opts ].optArg.argString; + if ((pzDir != NULL) && (*pzDir != NUL)) + return pzDir; + + /* + * This function only works if there is a directory where + * we can stash the RC (INI) file. + */ + { + char const * const* papz = pOpts->papzHomeList; + if (papz == NULL) + return NULL; + + while (papz[1] != NULL) papz++; + pzDir = *papz; + } + + /* + * IF it does not require deciphering an env value, then just copy it + */ + if (*pzDir != '$') + return pzDir; + + { + char const * pzEndDir = strchr(++pzDir, DIRCH); + char * pzFileName; + char * pzEnv; + + if (pzEndDir != NULL) { + char z[ AO_NAME_SIZE ]; + if ((pzEndDir - pzDir) > AO_NAME_LIMIT ) + return NULL; + memcpy(z, pzDir, (size_t)(pzEndDir - pzDir)); + z[pzEndDir - pzDir] = NUL; + pzEnv = getenv(z); + } else { + + /* + * Make sure we can get the env value (after stripping off + * any trailing directory or file names) + */ + pzEnv = getenv(pzDir); + } + + if (pzEnv == NULL) { + fprintf(stderr, SAVE_WARN, pOpts->pzProgName); + fprintf(stderr, zNotDef, pzDir); + return NULL; + } + + if (pzEndDir == NULL) + return pzEnv; + + { + size_t sz = strlen(pzEnv) + strlen(pzEndDir) + 2; + pzFileName = (char*)AGALOC(sz, "dir name"); + } + + if (pzFileName == NULL) + return NULL; + + *p_free = 1; + /* + * Glue together the full name into the allocated memory. + * FIXME: We lose track of this memory. + */ + sprintf(pzFileName, "%s/%s", pzEnv, pzEndDir); + return pzFileName; + } +} + + +static char const * +find_file_name(tOptions * pOpts, int * p_free_name) +{ + struct stat stBuf; + int free_dir_name = 0; + + char const * pzDir = find_dir_name(pOpts, &free_dir_name); + if (pzDir == NULL) + return NULL; + + /* + * See if we can find the specified directory. We use a once-only loop + * structure so we can bail out early. + */ + if (stat(pzDir, &stBuf) != 0) do { + char z[AG_PATH_MAX]; + char * dirchp; + + /* + * IF we could not, check to see if we got a full + * path to a file name that has not been created yet. + */ + if (errno != ENOENT) { + bogus_name: + fprintf(stderr, SAVE_WARN, pOpts->pzProgName); + fprintf(stderr, zNoStat, errno, strerror(errno), pzDir); + if (free_dir_name) + AGFREE((void*)pzDir); + return NULL; + } + + /* + * Strip off the last component, stat the remaining string and + * that string must name a directory + */ + dirchp = strrchr(pzDir, DIRCH); + if (dirchp == NULL) { + stBuf.st_mode = S_IFREG; + break; /* found directory -- viz., "." */ + } + + if ((size_t)(dirchp - pzDir) >= sizeof(z)) + goto bogus_name; + + memcpy(z, pzDir, (size_t)(dirchp - pzDir)); + z[dirchp - pzDir] = NUL; + + if ((stat(z, &stBuf) != 0) || ! S_ISDIR(stBuf.st_mode)) + goto bogus_name; + stBuf.st_mode = S_IFREG; /* file within this directory */ + } while (false); + + /* + * IF what we found was a directory, + * THEN tack on the config file name + */ + if (S_ISDIR(stBuf.st_mode)) { + size_t sz = strlen(pzDir) + strlen(pOpts->pzRcName) + 2; + + { + char * pzPath = (char*)AGALOC(sz, "file name"); +#ifdef HAVE_SNPRINTF + snprintf(pzPath, sz, "%s/%s", pzDir, pOpts->pzRcName); +#else + sprintf(pzPath, "%s/%s", pzDir, pOpts->pzRcName); +#endif + if (free_dir_name) + AGFREE((void*)pzDir); + pzDir = pzPath; + free_dir_name = 1; + } + + /* + * IF we cannot stat the object for any reason other than + * it does not exist, then we bail out + */ + if (stat(pzDir, &stBuf) != 0) { + if (errno != ENOENT) { + fprintf(stderr, SAVE_WARN, pOpts->pzProgName); + fprintf(stderr, zNoStat, errno, strerror(errno), + pzDir); + AGFREE((void*)pzDir); + return NULL; + } + + /* + * It does not exist yet, but it will be a regular file + */ + stBuf.st_mode = S_IFREG; + } + } + + /* + * Make sure that whatever we ultimately found, that it either is + * or will soon be a file. + */ + if (! S_ISREG(stBuf.st_mode)) { + fprintf(stderr, SAVE_WARN, pOpts->pzProgName); + fprintf(stderr, zNotFile, pzDir); + if (free_dir_name) + AGFREE((void*)pzDir); + return NULL; + } + + /* + * Get rid of the old file + */ + unlink(pzDir); + *p_free_name = free_dir_name; + return pzDir; +} + + +static void +prt_entry(FILE * fp, tOptDesc * p, char const * pzLA) +{ + /* + * There is an argument. Pad the name so values line up. + * Not disabled *OR* this got equivalenced to another opt, + * then use current option name. + * Otherwise, there must be a disablement name. + */ + { + char const * pz; + if (! DISABLED_OPT(p) || (p->optEquivIndex != NO_EQUIVALENT)) + pz = p->pz_Name; + else + pz = p->pz_DisableName; + + fprintf(fp, "%-18s", pz); + } + /* + * IF the option is numeric only, + * THEN the char pointer is really the number + */ + if (OPTST_GET_ARGTYPE(p->fOptState) == OPARG_TYPE_NUMERIC) + fprintf(fp, " %d\n", (int)(t_word)pzLA); + + /* + * OTHERWISE, FOR each line of the value text, ... + */ + else if (pzLA == NULL) + fputc(NL, fp); + + else { + fputc(' ', fp); fputc(' ', fp); + for (;;) { + char const * pzNl = strchr(pzLA, NL); + + /* + * IF this is the last line + * THEN bail and print it + */ + if (pzNl == NULL) + break; + + /* + * Print the continuation and the text from the current line + */ + (void)fwrite(pzLA, (size_t)(pzNl - pzLA), (size_t)1, fp); + pzLA = pzNl+1; /* advance the Last Arg pointer */ + fputs("\\\n", fp); + } + + /* + * Terminate the entry + */ + fputs(pzLA, fp); + fputc(NL, fp); + } +} + + +static void +prt_value(FILE * fp, int depth, tOptDesc * pOD, tOptionValue const * ovp) +{ + while (--depth >= 0) + putc(' ', fp), putc(' ', fp); + + switch (ovp->valType) { + default: + case OPARG_TYPE_NONE: + fprintf(fp, NULL_ATR_FMT, ovp->pzName); + break; + + case OPARG_TYPE_STRING: + prt_string(fp, ovp->pzName, ovp->v.strVal); + break; + + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + if (pOD != NULL) { + tAoUI opt_state = pOD->fOptState; + uintptr_t val = pOD->optArg.argEnum; + char const * typ = (ovp->valType == OPARG_TYPE_ENUMERATION) + ? "keyword" : "set-membership"; + + fprintf(fp, TYPE_ATR_FMT, ovp->pzName, typ); + + /* + * This is a magic incantation that will convert the + * bit flag values back into a string suitable for printing. + */ + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD ); + if (pOD->optArg.argString != NULL) { + fputs(pOD->optArg.argString, fp); + + if (ovp->valType != OPARG_TYPE_ENUMERATION) { + /* + * set membership strings get allocated + */ + AGFREE((void*)pOD->optArg.argString); + } + } + + pOD->optArg.argEnum = val; + pOD->fOptState = opt_state; + fprintf(fp, END_XML_FMT, ovp->pzName); + break; + } + /* FALLTHROUGH */ + + case OPARG_TYPE_NUMERIC: + fprintf(fp, NUMB_ATR_FMT, ovp->pzName, ovp->v.longVal); + break; + + case OPARG_TYPE_BOOLEAN: + fprintf(fp, BOOL_ATR_FMT, ovp->pzName, + ovp->v.boolVal ? "true" : "false"); + break; + + case OPARG_TYPE_HIERARCHY: + prt_val_list(fp, ovp->pzName, ovp->v.nestVal); + break; + } +} + + +static void +prt_string(FILE * fp, char const * name, char const * pz) +{ + fprintf(fp, OPEN_XML_FMT, name); + for (;;) { + int ch = ((int)*(pz++)) & 0xFF; + + switch (ch) { + case NUL: goto string_done; + + case '&': + case '<': + case '>': +#if __GNUC__ >= 4 + case 1 ... (' ' - 1): + case ('~' + 1) ... 0xFF: +#endif + emit_special_char(fp, ch); + break; + + default: +#if __GNUC__ < 4 + if ( ((ch >= 1) && (ch <= (' ' - 1))) + || ((ch >= ('~' + 1)) && (ch <= 0xFF)) ) { + emit_special_char(fp, ch); + break; + } +#endif + putc(ch, fp); + } + } string_done:; + fprintf(fp, END_XML_FMT, name); +} + + +static void +prt_val_list(FILE * fp, char const * name, tArgList * al) +{ + static int depth = 1; + + int sp_ct; + int opt_ct; + void ** opt_list; + + if (al == NULL) + return; + opt_ct = al->useCt; + opt_list = (void **)al->apzArgs; + + if (opt_ct <= 0) { + fprintf(fp, OPEN_CLOSE_FMT, name); + return; + } + + fprintf(fp, NESTED_OPT_FMT, name); + + depth++; + while (--opt_ct >= 0) { + tOptionValue const * ovp = *(opt_list++); + + prt_value(fp, depth, NULL, ovp); + } + depth--; + + for (sp_ct = depth; --sp_ct >= 0;) + putc(' ', fp), putc(' ', fp); + fprintf(fp, "</%s>\n", name); +} + + +static void +prt_nested(FILE * fp, tOptDesc * p) +{ + int opt_ct; + tArgList * al = p->optCookie; + void ** opt_list; + + if (al == NULL) + return; + + opt_ct = al->useCt; + opt_list = (void **)al->apzArgs; + + if (opt_ct <= 0) + return; + + do { + tOptionValue const * base = *(opt_list++); + tOptionValue const * ovp = optionGetValue(base, NULL); + + if (ovp == NULL) + continue; + + fprintf(fp, NESTED_OPT_FMT, p->pz_Name); + + do { + prt_value(fp, 1, p, ovp); + + } while (ovp = optionNextValue(base, ovp), + ovp != NULL); + + fprintf(fp, "</%s>\n", p->pz_Name); + } while (--opt_ct > 0); +} + + +static FILE * +open_sv_file(tOptions* pOpts) +{ + FILE * fp; + + { + int free_name = 0; + char const * pzFName = find_file_name(pOpts, &free_name); + if (pzFName == NULL) + return NULL; + + fp = fopen(pzFName, "w" FOPEN_BINARY_FLAG); + if (fp == NULL) { + fprintf(stderr, SAVE_WARN, pOpts->pzProgName); + fprintf(stderr, zNoCreat, errno, strerror(errno), pzFName); + if (free_name) + AGFREE((void*) pzFName ); + return fp; + } + + if (free_name) + AGFREE((void*)pzFName); + } + + { + char const * pz = pOpts->pzUsageTitle; + fputs("# ", fp); + do { fputc(*pz, fp); } while (*(pz++) != NL); + } + + { + time_t timeVal = time(NULL); + char * pzTime = ctime(&timeVal); + + fprintf(fp, zPresetFile, pzTime); +#ifdef HAVE_ALLOCATED_CTIME + /* + * The return values for ctime(), localtime(), and gmtime() + * normally point to static data that is overwritten by each call. + * The test to detect allocated ctime, so we leak the memory. + */ + AGFREE((void*)pzTime); +#endif + } + + return fp; +} + +static void +prt_no_arg_opt(FILE * fp, tOptDesc * p, tOptDesc * pOD) +{ + /* + * The aliased to argument indicates whether or not the option + * is "disabled". However, the original option has the name + * string, so we get that there, not with "p". + */ + char const * pznm = + (DISABLED_OPT(p)) ? pOD->pz_DisableName : pOD->pz_Name; + /* + * If the option was disabled and the disablement name is NULL, + * then the disablement was caused by aliasing. + * Use the name as the string to emit. + */ + if (pznm == NULL) + pznm = pOD->pz_Name; + + fprintf(fp, "%s\n", pznm); +} + +static void +prt_str_arg(FILE * fp, tOptDesc * pOD) +{ + if (pOD->fOptState & OPTST_STACKED) { + tArgList * pAL = (tArgList*)pOD->optCookie; + int uct = pAL->useCt; + char const ** ppz = pAL->apzArgs; + + /* + * un-disable multiple copies of disabled options. + */ + if (uct > 1) + pOD->fOptState &= ~OPTST_DISABLED; + + while (uct-- > 0) + prt_entry(fp, pOD, *(ppz++)); + } else { + prt_entry(fp, pOD, pOD->optArg.argString); + } +} + +static void +prt_enum_arg(FILE * fp, tOptDesc * pOD) +{ + uintptr_t val = pOD->optArg.argEnum; + + /* + * This is a magic incantation that will convert the + * bit flag values back into a string suitable for printing. + */ + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + prt_entry(fp, pOD, (void*)(pOD->optArg.argString)); + + pOD->optArg.argEnum = val; +} + +static void +prt_set_arg(FILE * fp, tOptDesc * pOD) +{ + uintptr_t val = pOD->optArg.argEnum; + + /* + * This is a magic incantation that will convert the + * bit flag values back into a string suitable for printing. + */ + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + prt_entry(fp, pOD, (void*)(pOD->optArg.argString)); + + if (pOD->optArg.argString != NULL) { + /* + * set membership strings get allocated + */ + AGFREE((void*)pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + + pOD->optArg.argEnum = val; +} + +static void +prt_file_arg(FILE * fp, tOptDesc * pOD, tOptions* pOpts) +{ + /* + * If the cookie is not NULL, then it has the file name, period. + * Otherwise, if we have a non-NULL string argument, then.... + */ + if (pOD->optCookie != NULL) + prt_entry(fp, pOD, pOD->optCookie); + + else if (HAS_originalOptArgArray(pOpts)) { + char const * orig = + pOpts->originalOptArgArray[pOD->optIndex].argString; + + if (pOD->optArg.argString == orig) + return; + + prt_entry(fp, pOD, pOD->optArg.argString); + } +} + + +/*=export_func optionSaveFile + * + * what: saves the option state to a file + * + * arg: tOptions*, pOpts, program options descriptor + * + * doc: + * + * This routine will save the state of option processing to a file. The name + * of that file can be specified with the argument to the @code{--save-opts} + * option, or by appending the @code{rcfile} attribute to the last + * @code{homerc} attribute. If no @code{rcfile} attribute was specified, it + * will default to @code{.@i{programname}rc}. If you wish to specify another + * file, you should invoke the @code{SET_OPT_SAVE_OPTS(@i{filename})} macro. + * + * The recommend usage is as follows: + * @example + * optionProcess(&progOptions, argc, argv); + * if (i_want_a_non_standard_place_for_this) + * SET_OPT_SAVE_OPTS("myfilename"); + * optionSaveFile(&progOptions); + * @end example + * + * err: + * + * If no @code{homerc} file was specified, this routine will silently return + * and do nothing. If the output file cannot be created or updated, a message + * will be printed to @code{stderr} and the routine will return. +=*/ +void +optionSaveFile(tOptions* pOpts) +{ + tOptDesc* pOD; + int ct; + FILE * fp = open_sv_file(pOpts); + + if (fp == NULL) + return; + + /* + * FOR each of the defined options, ... + */ + ct = pOpts->presetOptCt; + pOD = pOpts->pOptDesc; + do { + tOptDesc * p; + + /* + * IF the option has not been defined + * OR it does not take an initialization value + * OR it is equivalenced to another option + * THEN continue (ignore it) + * + * Equivalenced options get picked up when the equivalenced-to + * option is processed. + */ + if (UNUSED_OPT(pOD)) + continue; + + if ((pOD->fOptState & OPTST_DO_NOT_SAVE_MASK) != 0) + continue; + + if ( (pOD->optEquivIndex != NO_EQUIVALENT) + && (pOD->optEquivIndex != pOD->optIndex)) + continue; + + /* + * The option argument data are found at the equivalenced-to option, + * but the actual option argument type comes from the original + * option descriptor. Be careful! + */ + p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0) + ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD; + + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NONE: + prt_no_arg_opt(fp, p, pOD); + break; + + case OPARG_TYPE_NUMERIC: + prt_entry(fp, p, (void*)(p->optArg.argInt)); + break; + + case OPARG_TYPE_STRING: + prt_str_arg(fp, p); + break; + + case OPARG_TYPE_ENUMERATION: + prt_enum_arg(fp, p); + break; + + case OPARG_TYPE_MEMBERSHIP: + prt_set_arg(fp, p); + break; + + case OPARG_TYPE_BOOLEAN: + prt_entry(fp, p, p->optArg.argBool ? "true" : "false"); + break; + + case OPARG_TYPE_HIERARCHY: + prt_nested(fp, p); + break; + + case OPARG_TYPE_FILE: + prt_file_arg(fp, p, pOpts); + break; + + default: + break; /* cannot handle - skip it */ + } + } while (pOD++, (--ct > 0)); + + fclose(fp); +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/save.c */ diff --git a/autoopts/sort.c b/autoopts/sort.c new file mode 100644 index 0000000..a05588d --- /dev/null +++ b/autoopts/sort.c @@ -0,0 +1,336 @@ + +/* + * \file sort.c + * + * Time-stamp: "2011-05-24 18:07:14 bkorb" + * + * This module implements argument sorting. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/* = = = START-STATIC-FORWARD = = = */ +static tSuccess +mustHandleArg(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx); + +static tSuccess +mayHandleArg(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx); + +static tSuccess +checkShortOpts(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx); +/* = = = END-STATIC-FORWARD = = = */ + +/* + * "mustHandleArg" and "mayHandleArg" are really similar. The biggest + * difference is that "may" will consume the next argument only if it + * does not start with a hyphen and "must" will consume it, hyphen or not. + */ +static tSuccess +mustHandleArg(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx) +{ + /* + * An option argument is required. Long options can either have + * a separate command line argument, or an argument attached by + * the '=' character. Figure out which. + */ + switch (pOS->optType) { + case TOPT_SHORT: + /* + * See if an arg string follows the flag character. If not, + * the next arg must be the option argument. + */ + if (*pzArg != NUL) + return SUCCESS; + break; + + case TOPT_LONG: + /* + * See if an arg string has already been assigned (glued on + * with an `=' character). If not, the next is the opt arg. + */ + if (pOS->pzOptArg != NULL) + return SUCCESS; + break; + + default: + return FAILURE; + } + if (pOpts->curOptIdx >= pOpts->origArgCt) + return FAILURE; + + ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + return SUCCESS; +} + +static tSuccess +mayHandleArg(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx) +{ + /* + * An option argument is optional. + */ + switch (pOS->optType) { + case TOPT_SHORT: + /* + * IF nothing is glued on after the current flag character, + * THEN see if there is another argument. If so and if it + * does *NOT* start with a hyphen, then it is the option arg. + */ + if (*pzArg != NUL) + return SUCCESS; + break; + + case TOPT_LONG: + /* + * Look for an argument if we don't already have one (glued on + * with a `=' character) + */ + if (pOS->pzOptArg != NULL) + return SUCCESS; + break; + + default: + return FAILURE; + } + if (pOpts->curOptIdx >= pOpts->origArgCt) + return PROBLEM; + + pzArg = pOpts->origArgVect[ pOpts->curOptIdx ]; + if (*pzArg != '-') + ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + return SUCCESS; +} + +/* + * Process a string of short options glued together. If the last one + * does or may take an argument, the do the argument processing and leave. + */ +static tSuccess +checkShortOpts(tOptions* pOpts, char* pzArg, tOptState* pOS, + char** ppzOpts, int* pOptsIdx) +{ + while (*pzArg != NUL) { + if (FAILED(opt_find_short(pOpts, (tAoUC)*pzArg, pOS))) + return FAILURE; + + /* + * See if we can have an arg. + */ + if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) { + pzArg++; + + } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) { + /* + * Take an argument if it is not attached and it does not + * start with a hyphen. + */ + if (pzArg[1] != NUL) + return SUCCESS; + + pzArg = pOpts->origArgVect[ pOpts->curOptIdx ]; + if (*pzArg != '-') + ppzOpts[ (*pOptsIdx)++ ] = + pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + return SUCCESS; + + } else { + /* + * IF we need another argument, be sure it is there and + * take it. + */ + if (pzArg[1] == NUL) { + if (pOpts->curOptIdx >= pOpts->origArgCt) + return FAILURE; + ppzOpts[ (*pOptsIdx)++ ] = + pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + } + return SUCCESS; + } + } + return SUCCESS; +} + +/* + * If the program wants sorted options (separated operands and options), + * then this routine will to the trick. + */ +LOCAL void +optionSort(tOptions* pOpts) +{ + char** ppzOpts; + char** ppzOpds; + int optsIdx = 0; + int opdsIdx = 0; + + tOptState os = OPTSTATE_INITIALIZER(DEFINED); + + /* + * Disable for POSIX conformance, or if there are no operands. + */ + if ( (getenv("POSIXLY_CORRECT") != NULL) + || NAMED_OPTS(pOpts)) + return; + + /* + * Make sure we can allocate two full-sized arg vectors. + */ + ppzOpts = malloc(pOpts->origArgCt * sizeof(char*)); + if (ppzOpts == NULL) + goto exit_no_mem; + + ppzOpds = malloc(pOpts->origArgCt * sizeof(char*)); + if (ppzOpds == NULL) { + free(ppzOpts); + goto exit_no_mem; + } + + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + + /* + * Now, process all the options from our current position onward. + * (This allows interspersed options and arguments for the few + * non-standard programs that require it.) + */ + for (;;) { + char* pzArg; + tSuccess res; + + /* + * If we're out of arguments, we're done. Join the option and + * operand lists into the original argument vector. + */ + if (pOpts->curOptIdx >= pOpts->origArgCt) { + errno = 0; + goto joinLists; + } + + pzArg = pOpts->origArgVect[ pOpts->curOptIdx ]; + if (*pzArg != '-') { + ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + continue; + } + + switch (pzArg[1]) { + case NUL: + /* + * A single hyphen is an operand. + */ + ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + continue; + + case '-': + /* + * Two consecutive hypens. Put them on the options list and then + * _always_ force the remainder of the arguments to be operands. + */ + if (pzArg[2] == NUL) { + ppzOpts[ optsIdx++ ] = + pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + goto restOperands; + } + res = opt_find_long(pOpts, pzArg+2, &os); + break; + + default: + /* + * If short options are not allowed, then do long + * option processing. Otherwise the character must be a + * short (i.e. single character) option. + */ + if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) { + res = opt_find_long(pOpts, pzArg+1, &os); + } else { + res = opt_find_short(pOpts, (tAoUC)pzArg[1], &os); + } + break; + } + if (FAILED(res)) { + errno = EINVAL; + goto freeTemps; + } + + /* + * We've found an option. Add the argument to the option list. + * Next, we have to see if we need to pull another argument to be + * used as the option argument. + */ + ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + + if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) { + /* + * No option argument. If we have a short option here, + * then scan for short options until we get to the end + * of the argument string. + */ + if ( (os.optType == TOPT_SHORT) + && FAILED(checkShortOpts(pOpts, pzArg+2, &os, ppzOpts, + &optsIdx)) ) { + errno = EINVAL; + goto freeTemps; + } + + } else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) { + switch (mayHandleArg(pOpts, pzArg+2, &os, ppzOpts, &optsIdx)) { + case FAILURE: errno = EIO; goto freeTemps; + case PROBLEM: errno = 0; goto joinLists; + } + + } else { + switch (mustHandleArg(pOpts, pzArg+2, &os, ppzOpts, &optsIdx)) { + case PROBLEM: + case FAILURE: errno = EIO; goto freeTemps; + } + } + } /* for (;;) */ + + restOperands: + while (pOpts->curOptIdx < pOpts->origArgCt) + ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ]; + + joinLists: + if (optsIdx > 0) + memcpy(pOpts->origArgVect + 1, ppzOpts, optsIdx * sizeof(char*)); + if (opdsIdx > 0) + memcpy(pOpts->origArgVect + 1 + optsIdx, ppzOpds, + opdsIdx * sizeof(char*)); + + freeTemps: + free(ppzOpts); + free(ppzOpds); + return; + + exit_no_mem: + errno = ENOMEM; + return; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/sort.c */ diff --git a/autoopts/stack.c b/autoopts/stack.c new file mode 100644 index 0000000..ecf52ab --- /dev/null +++ b/autoopts/stack.c @@ -0,0 +1,269 @@ + +/** + * \file stack.c + * + * Time-stamp: "2012-08-11 08:35:28 bkorb" + * + * This is a special option processing routine that will save the + * argument to an option in a FIFO queue. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +#ifdef WITH_LIBREGEX +# include REGEX_HEADER +#endif + +/*=export_func optionUnstackArg + * private: + * + * what: Remove option args from a stack + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Invoked for options that are equivalenced to stacked options. +=*/ +void +optionUnstackArg(tOptions * pOpts, tOptDesc * pOptDesc) +{ + tArgList * pAL; + + (void)pOpts; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOptDesc->fOptState & OPTST_RESET) != 0) + return; + + pAL = (tArgList*)pOptDesc->optCookie; + + /* + * IF we don't have any stacked options, + * THEN indicate that we don't have any of these options + */ + if (pAL == NULL) { + pOptDesc->fOptState &= OPTST_PERSISTENT_MASK; + if ((pOptDesc->fOptState & OPTST_INITENABLED) == 0) + pOptDesc->fOptState |= OPTST_DISABLED; + return; + } + +#ifdef WITH_LIBREGEX + { + regex_t re; + int i, ct, dIdx; + + if (regcomp(&re, pOptDesc->optArg.argString, REG_NOSUB) != 0) + return; + + /* + * search the list for the entry(s) to remove. Entries that + * are removed are *not* copied into the result. The source + * index is incremented every time. The destination only when + * we are keeping a define. + */ + for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) { + char const * pzSrc = pAL->apzArgs[ i ]; + char * pzEq = strchr(pzSrc, '='); + int res; + + + if (pzEq != NULL) + *pzEq = NUL; + + res = regexec(&re, pzSrc, (size_t)0, NULL, 0); + switch (res) { + case 0: + /* + * Remove this entry by reducing the in-use count + * and *not* putting the string pointer back into + * the list. + */ + AGFREE(pzSrc); + pAL->useCt--; + break; + + default: + case REG_NOMATCH: + if (pzEq != NULL) + *pzEq = '='; + + /* + * IF we have dropped an entry + * THEN we have to move the current one. + */ + if (dIdx != i) + pAL->apzArgs[ dIdx ] = pzSrc; + dIdx++; + } + } + + regfree(&re); + } +#else /* not WITH_LIBREGEX */ + { + int i, ct, dIdx; + + /* + * search the list for the entry(s) to remove. Entries that + * are removed are *not* copied into the result. The source + * index is incremented every time. The destination only when + * we are keeping a define. + */ + for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) { + tCC* pzSrc = pAL->apzArgs[ i ]; + char* pzEq = strchr(pzSrc, '='); + + if (pzEq != NULL) + *pzEq = NUL; + + if (strcmp(pzSrc, pOptDesc->optArg.argString) == 0) { + /* + * Remove this entry by reducing the in-use count + * and *not* putting the string pointer back into + * the list. + */ + AGFREE(pzSrc); + pAL->useCt--; + } else { + if (pzEq != NULL) + *pzEq = '='; + + /* + * IF we have dropped an entry + * THEN we have to move the current one. + */ + if (dIdx != i) + pAL->apzArgs[ dIdx ] = pzSrc; + dIdx++; + } + } + } +#endif /* WITH_LIBREGEX */ + /* + * IF we have unstacked everything, + * THEN indicate that we don't have any of these options + */ + if (pAL->useCt == 0) { + pOptDesc->fOptState &= OPTST_PERSISTENT_MASK; + if ((pOptDesc->fOptState & OPTST_INITENABLED) == 0) + pOptDesc->fOptState |= OPTST_DISABLED; + AGFREE((void*)pAL); + pOptDesc->optCookie = NULL; + } +} + + +/* + * Put an entry into an argument list. The first argument points to + * a pointer to the argument list structure. It gets passed around + * as an opaque address. + */ +LOCAL void +addArgListEntry(void** ppAL, void* entry) +{ + tArgList* pAL = *(void**)ppAL; + + /* + * IF we have never allocated one of these, + * THEN allocate one now + */ + if (pAL == NULL) { + pAL = (tArgList*)AGALOC(sizeof(*pAL), "new option arg stack"); + if (pAL == NULL) + return; + pAL->useCt = 0; + pAL->allocCt = MIN_ARG_ALLOC_CT; + *ppAL = (void*)pAL; + } + + /* + * ELSE if we are out of room + * THEN make it bigger + */ + else if (pAL->useCt >= pAL->allocCt) { + size_t sz = sizeof(*pAL); + pAL->allocCt += INCR_ARG_ALLOC_CT; + + /* + * The base structure contains space for MIN_ARG_ALLOC_CT + * pointers. We subtract it off to find our augment size. + */ + sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT); + pAL = (tArgList*)AGREALOC((void*)pAL, sz, "expanded opt arg stack"); + if (pAL == NULL) + return; + *ppAL = (void*)pAL; + } + + /* + * Insert the new argument into the list + */ + pAL->apzArgs[ (pAL->useCt)++ ] = entry; +} + + +/*=export_func optionStackArg + * private: + * + * what: put option args on a stack + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Keep an entry-ordered list of option arguments. +=*/ +void +optionStackArg(tOptions * pOpts, tOptDesc * pOD) +{ + char * pz; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOD->fOptState & OPTST_RESET) != 0) { + tArgList* pAL = (void*)pOD->optCookie; + int ix; + if (pAL == NULL) + return; + + ix = pAL->useCt; + while (--ix >= 0) + AGFREE(pAL->apzArgs[ix]); + AGFREE(pAL); + + } else { + if (pOD->optArg.argString == NULL) + return; + + AGDUPSTR(pz, pOD->optArg.argString, "stack arg"); + addArgListEntry(&(pOD->optCookie), (void*)pz); + } +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/stack.c */ diff --git a/autoopts/strequate.3 b/autoopts/strequate.3 new file mode 100644 index 0000000..fee20a1 --- /dev/null +++ b/autoopts/strequate.3 @@ -0,0 +1,32 @@ +.TH strequate 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (strequate.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +strequate - map a list of characters to the same value +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBstrequate\fP(char const* \fIch_list\fP); +.sp 1 +.SH DESCRIPTION +Each character in the input string get mapped to the first character +in the string. +This function name is mapped to option_strequate so as to not conflict +with the POSIX name space. +.TP +.IR ch_list +characters to equivalence +.sp 1 +.SH ERRORS +none. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/streqvcmp.3 b/autoopts/streqvcmp.3 new file mode 100644 index 0000000..5e8077f --- /dev/null +++ b/autoopts/streqvcmp.3 @@ -0,0 +1,39 @@ +.TH streqvcmp 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (streqvcmp.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +streqvcmp - compare two strings with an equivalence mapping +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +int \fBstreqvcmp\fP(char const* \fIstr1\fP, char const* \fIstr2\fP); +.sp 1 +.SH DESCRIPTION +Using a character mapping, two strings are compared for "equivalence". +Each input character is mapped to a comparison character and the +mapped-to characters are compared for the two NUL terminated input strings. +This function name is mapped to option_streqvcmp so as to not conflict +with the POSIX name space. +.TP +.IR str1 +first string +.TP +.IR str2 +second string +.sp 1 +.SH RETURN VALUE +the difference between two differing characters +.sp 1 +.SH ERRORS +none checked. Caller responsible for seg faults. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvmap(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/streqvcmp.c b/autoopts/streqvcmp.c new file mode 100644 index 0000000..54a063a --- /dev/null +++ b/autoopts/streqvcmp.c @@ -0,0 +1,267 @@ + +/** + * \file streqvcmp.c + * + * Time-stamp: "2012-03-31 13:17:39 bkorb" + * + * String Equivalence Comparison + * + * These routines allow any character to be mapped to any other + * character before comparison. In processing long option names, + * the characters "-", "_" and "^" all need to be equivalent + * (because they are treated so by different development environments). + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + * + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static unsigned char charmap[] = { + NUL, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, '\a', + '\b', '\t', NL, '\v', '\f', '\r', 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, + + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +}; + + +/*=export_func strneqvcmp + * + * what: compare two strings with an equivalence mapping + * + * arg: + char const* + str1 + first string + + * arg: + char const* + str2 + second string + + * arg: + int + ct + compare length + + * + * ret_type: int + * ret_desc: the difference between two differing characters + * + * doc: + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * The comparison is limited to @code{ct} bytes. + * This function name is mapped to option_strneqvcmp so as to not conflict + * with the POSIX name space. + * + * err: none checked. Caller responsible for seg faults. +=*/ +int +strneqvcmp(tCC* s1, tCC* s2, int ct) +{ + for (; ct > 0; --ct) { + unsigned char u1 = (unsigned char) *s1++; + unsigned char u2 = (unsigned char) *s2++; + int dif = charmap[ u1 ] - charmap[ u2 ]; + + if (dif != 0) + return dif; + + if (u1 == NUL) + return 0; + } + + return 0; +} + + +/*=export_func streqvcmp + * + * what: compare two strings with an equivalence mapping + * + * arg: + char const* + str1 + first string + + * arg: + char const* + str2 + second string + + * + * ret_type: int + * ret_desc: the difference between two differing characters + * + * doc: + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * This function name is mapped to option_streqvcmp so as to not conflict + * with the POSIX name space. + * + * err: none checked. Caller responsible for seg faults. +=*/ +int +streqvcmp(tCC* s1, tCC* s2) +{ + for (;;) { + unsigned char u1 = (unsigned char) *s1++; + unsigned char u2 = (unsigned char) *s2++; + int dif = charmap[ u1 ] - charmap[ u2 ]; + + if (dif != 0) + return dif; + + if (u1 == NUL) + return 0; + } +} + + +/*=export_func streqvmap + * + * what: Set the character mappings for the streqv functions + * + * arg: + char + From + Input character + + * arg: + char + To + Mapped-to character + + * arg: + int + ct + compare length + + * + * doc: + * + * Set the character mapping. If the count (@code{ct}) is set to zero, then + * the map is cleared by setting all entries in the map to their index + * value. Otherwise, the "@code{From}" character is mapped to the "@code{To}" + * character. If @code{ct} is greater than 1, then @code{From} and @code{To} + * are incremented and the process repeated until @code{ct} entries have been + * set. For example, + * @example + * streqvmap('a', 'A', 26); + * @end example + * @noindent + * will alter the mapping so that all English lower case letters + * will map to upper case. + * + * This function name is mapped to option_streqvmap so as to not conflict + * with the POSIX name space. + * + * err: none. +=*/ +void +streqvmap(char From, char To, int ct) +{ + if (ct == 0) { + ct = sizeof(charmap) - 1; + do { + charmap[ct] = (unsigned char)ct; + } while (--ct >= 0); + } + + else { + unsigned int chTo = (int)To & 0xFF; + unsigned int chFrom = (int)From & 0xFF; + + do { + charmap[chFrom] = (unsigned char)chTo; + chFrom++; + chTo++; + if ((chFrom >= sizeof(charmap)) || (chTo >= sizeof(charmap))) + break; + } while (--ct > 0); + } +} + + +/*=export_func strequate + * + * what: map a list of characters to the same value + * + * arg: + char const* + ch_list + characters to equivalence + + * + * doc: + * + * Each character in the input string get mapped to the first character + * in the string. + * This function name is mapped to option_strequate so as to not conflict + * with the POSIX name space. + * + * err: none. +=*/ +void +strequate(char const* s) +{ + if ((s != NULL) && (*s != NUL)) { + unsigned char equiv = (unsigned)*s; + while (*s != NUL) + charmap[ (unsigned)*(s++) ] = equiv; + } +} + + +/*=export_func strtransform + * + * what: convert a string into its mapped-to value + * + * arg: + char* + dest + output string + + * arg: + char const* + src + input string + + * + * doc: + * + * Each character in the input string is mapped and the mapped-to + * character is put into the output. + * This function name is mapped to option_strtransform so as to not conflict + * with the POSIX name space. + * + * The source and destination may be the same. + * + * err: none. +=*/ +void +strtransform(char* d, char const* s) +{ + do { + *(d++) = (char)charmap[ (unsigned)*s ]; + } while (*(s++) != NUL); +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/streqvcmp.c */ diff --git a/autoopts/streqvmap.3 b/autoopts/streqvmap.3 new file mode 100644 index 0000000..a4c3518 --- /dev/null +++ b/autoopts/streqvmap.3 @@ -0,0 +1,48 @@ +.TH streqvmap 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (streqvmap.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +streqvmap - Set the character mappings for the streqv functions +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBstreqvmap\fP(char \fIFrom\fP, char \fITo\fP, int \fIct\fP); +.sp 1 +.SH DESCRIPTION +Set the character mapping. If the count (\fBct\fP) is set to zero, then +the map is cleared by setting all entries in the map to their index +value. Otherwise, the "\fBFrom\fP" character is mapped to the "\fBTo\fP" +character. If \fBct\fP is greater than 1, then \fBFrom\fP and \fBTo\fP +are incremented and the process repeated until \fBct\fP entries have been +set. For example, +.nf + streqvmap('a', 'A', 26); +.fi +will alter the mapping so that all English lower case letters +will map to upper case. + +This function name is mapped to option_streqvmap so as to not conflict +with the POSIX name space. +.TP +.IR From +Input character +.TP +.IR To +Mapped-to character +.TP +.IR ct +compare length +.sp 1 +.SH ERRORS +none. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), strneqvcmp(3), strtransform(3), diff --git a/autoopts/strneqvcmp.3 b/autoopts/strneqvcmp.3 new file mode 100644 index 0000000..9433439 --- /dev/null +++ b/autoopts/strneqvcmp.3 @@ -0,0 +1,43 @@ +.TH strneqvcmp 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (strneqvcmp.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +strneqvcmp - compare two strings with an equivalence mapping +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +int \fBstrneqvcmp\fP(char const* \fIstr1\fP, char const* \fIstr2\fP, int \fIct\fP); +.sp 1 +.SH DESCRIPTION +Using a character mapping, two strings are compared for "equivalence". +Each input character is mapped to a comparison character and the +mapped-to characters are compared for the two NUL terminated input strings. +The comparison is limited to \fBct\fP bytes. +This function name is mapped to option_strneqvcmp so as to not conflict +with the POSIX name space. +.TP +.IR str1 +first string +.TP +.IR str2 +second string +.TP +.IR ct +compare length +.sp 1 +.SH RETURN VALUE +the difference between two differing characters +.sp 1 +.SH ERRORS +none checked. Caller responsible for seg faults. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strtransform(3), diff --git a/autoopts/strtransform.3 b/autoopts/strtransform.3 new file mode 100644 index 0000000..6a89b1b --- /dev/null +++ b/autoopts/strtransform.3 @@ -0,0 +1,37 @@ +.TH strtransform 3 2012-08-11 "" "Programmer's Manual" +.\" DO NOT EDIT THIS FILE (strtransform.3) +.\" +.\" It has been AutoGen-ed August 11, 2012 at 09:44:56 AM by AutoGen 5.16.2 +.\" From the definitions ./funcs.def +.\" and the template file agman3.tpl +.SH NAME +strtransform - convert a string into its mapped-to value +.sp 1 +.SH SYNOPSIS + +#include <\fIyour-opts.h\fP> +.br +cc [...] -o outfile infile.c -l\fBopts\fP [...] +.sp 1 +void \fBstrtransform\fP(char* \fIdest\fP, char const* \fIsrc\fP); +.sp 1 +.SH DESCRIPTION +Each character in the input string is mapped and the mapped-to +character is put into the output. +This function name is mapped to option_strtransform so as to not conflict +with the POSIX name space. + +The source and destination may be the same. +.TP +.IR dest +output string +.TP +.IR src +input string +.sp 1 +.SH ERRORS +none. +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fIopts\fP library. +.br +ao_string_tokenize(3), configFileLoad(3), optionFileLoad(3), optionFindNextValue(3), optionFindValue(3), optionFree(3), optionGetValue(3), optionLoadLine(3), optionNextValue(3), optionOnlyUsage(3), optionProcess(3), optionRestore(3), optionSaveFile(3), optionSaveState(3), optionUnloadNested(3), optionVersion(3), pathfind(3), strequate(3), streqvcmp(3), streqvmap(3), strneqvcmp(3), diff --git a/autoopts/test/Makefile.am b/autoopts/test/Makefile.am new file mode 100644 index 0000000..ce8ea2d --- /dev/null +++ b/autoopts/test/Makefile.am @@ -0,0 +1,53 @@ +## -*- Mode: Makefile -*- +## +## Makefile.am +## +## Time-stamp: "2012-05-13 16:02:42 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +EXTRA_DIST = defs.in stdopts.def $(TESTS) +TESTS = \ + alias.test argument.test cfg-edit.test cond.test \ + config.test doc.test enums.test equiv.test \ + errors.test getopt.test handler.test immediate.test \ + keyword.test library.test main.test nested.test \ + nls.test rc.test shell.test stdopts.test \ + time.test usage.test vendor.test vers.test + +testsubdir = ./testdir + +TESTS_ENVIRONMENT = TERM='' top_builddir="$(top_builddir)" + +distclean-local: + -rm -rf $(testsubdir) FAILURES + +check : perm-stamp + +perm-stamp : + @-cd $(srcdir) ; chmod +x *.test 2>/dev/null + +verbose : + rm -rf FAILURES testdir ; VERBOSE=true ; export VERBOSE ; \ + $(MAKE) check TESTS="$(TESTS)" + +# Makefile.am ends here diff --git a/autoopts/test/Makefile.in b/autoopts/test/Makefile.in new file mode 100644 index 0000000..a5a0d5b --- /dev/null +++ b/autoopts/test/Makefile.in @@ -0,0 +1,560 @@ +# Makefile.in generated by automake 1.12.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = autoopts/test +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/defs.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ag_macros.m4 \ + $(top_srcdir)/config/extensions.m4 \ + $(top_srcdir)/config/libopts.m4 \ + $(top_srcdir)/config/libtool.m4 \ + $(top_srcdir)/config/ltoptions.m4 \ + $(top_srcdir)/config/ltsugar.m4 \ + $(top_srcdir)/config/ltversion.m4 \ + $(top_srcdir)/config/lt~obsolete.m4 \ + $(top_srcdir)/config/onceonly.m4 \ + $(top_srcdir)/config/snprintfv.m4 \ + $(top_srcdir)/config/unlocked-io.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = defs +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = $(am__tty_colors_dummy) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AGEN5_TESTS = @AGEN5_TESTS@ +AG_GUILE = @AG_GUILE@ +AG_LDFLAGS = @AG_LDFLAGS@ +AG_MAJOR_VERSION = @AG_MAJOR_VERSION@ +AG_MINOR_VERSION = @AG_MINOR_VERSION@ +AG_TIMEOUT = @AG_TIMEOUT@ +AG_VERSION = @AG_VERSION@ +AG_XML2 = @AG_XML2@ +AGexe = @AGexe@ +AGnam = @AGnam@ +AMTAR = @AMTAR@ +AO_AGE = @AO_AGE@ +AO_CURRENT = @AO_CURRENT@ +AO_REVISION = @AO_REVISION@ +AO_TEMPLATE_VERSION = @AO_TEMPLATE_VERSION@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLexe = @CLexe@ +CLnam = @CLnam@ +CONFIG_SHELL = @CONFIG_SHELL@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_ENABLED = @DEBUG_ENABLED@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNAMIC_AG = @DYNAMIC_AG@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDexe = @GDexe@ +GDnam = @GDnam@ +GO_AGE = @GO_AGE@ +GO_CURRENT = @GO_CURRENT@ +GO_REVISION = @GO_REVISION@ +GREP = @GREP@ +GUILE_VERSION = @GUILE_VERSION@ +INCLIST = @INCLIST@ +INCSNPRINTFV = @INCSNPRINTFV@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBGUILE_CFLAGS = @LIBGUILE_CFLAGS@ +LIBGUILE_LIBS = @LIBGUILE_LIBS@ +LIBGUILE_PATH = @LIBGUILE_PATH@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSNPRINTFV = @LIBSNPRINTFV@ +LIBTOOL = @LIBTOOL@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIBXML2_PATH = @LIBXML2_PATH@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +M4_SRC = @M4_SRC@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPTS_TESTDIR = @OPTS_TESTDIR@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSIX_SHELL = @POSIX_SHELL@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TEXI2HTML = @TEXI2HTML@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_aux_dir = @ac_aux_dir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = defs.in stdopts.def $(TESTS) +TESTS = \ + alias.test argument.test cfg-edit.test cond.test \ + config.test doc.test enums.test equiv.test \ + errors.test getopt.test handler.test immediate.test \ + keyword.test library.test main.test nested.test \ + nls.test rc.test shell.test stdopts.test \ + time.test usage.test vendor.test vers.test + +testsubdir = ./testdir +TESTS_ENVIRONMENT = TERM='' top_builddir="$(top_builddir)" +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu autoopts/test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu autoopts/test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +defs: $(top_builddir)/config.status $(srcdir)/defs.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: all all-am check check-TESTS check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distclean-local distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am + + +distclean-local: + -rm -rf $(testsubdir) FAILURES + +check : perm-stamp + +perm-stamp : + @-cd $(srcdir) ; chmod +x *.test 2>/dev/null + +verbose : + rm -rf FAILURES testdir ; VERBOSE=true ; export VERBOSE ; \ + $(MAKE) check TESTS="$(TESTS)" + +# Makefile.am ends here + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/autoopts/test/alias.test b/autoopts/test/alias.test new file mode 100755 index 0000000..1cde083 --- /dev/null +++ b/autoopts/test/alias.test @@ -0,0 +1,120 @@ +#! /bin/sh +# +# alias.test --- test option aliasing +# +# Time-stamp: "2012-05-12 19:56:13 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs +failure() { exit 1 ; } +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +testname="${testname}" test_main="YES" \ +argument="arg [...]" long_opts="YES" use_flags=true \ +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" +: add defs +cat >> ${testname}.def <<- \_EOF_ + + flag = { + name = a-opt; + value = a; + aliases = option; + }; + + flag = { + name = b-second; + value = b; + aliases = second; + }; + _EOF_ + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # FIRST TEST # # # # # # # # # + +echo creating ${testname}-1.help +clean_help > ${testname}-1.help <<'_EOF_' +test_alias - Test AutoOpts for alias +USAGE: alias [ -<flag> [<val>] | --<name>[{=| }<val>] ]... arg [...] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -a Str a-opt This is an alias for 'option' + -b Num b-second This is an alias for 'second' + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +_EOF_ + +cmp -s ${testname}-1.help ${testname}.help || \ + failure "`diff ${testname}-1.help ${testname}.help`" + +./${testname} -o foo -a bar && \ + failure "both -o and -a were accepted" + +./${testname} -a bar fumble > ${testname}.out +cat > ${testname}.base <<- \_EOF_ + OPTION_CT=2 + export OPTION_CT + TEST_ALIAS_OPTION='bar' + export TEST_ALIAS_OPTION + _EOF_ + +cmp -s ${testname}.out ${testname}.base || \ + failure "`diff ${testname}.out ${testname}.base`" + +run_ag als -T agtexi-cmd.tpl ${testname}.def +test -f invoke-test_${testname}.menu || \ + failure "no menu entry output" +rm -f invoke-test_${testname}.menu +test -f invoke-test_${testname}.texi || \ + failure "no texi output" +mv -f invoke-test_${testname}.texi ${testname}.texi + +run_ag als -T agmdoc-cmd.tpl ${testname}.def +test -f test_${testname}.1 || failure "no man page output" +mv test_${testname}.1 ${testname}.1 +lnct=` + ${EGREP} '^This is an alias for the (option|second) option[,.]$' \ + ${testname}.texi ${testname}.1 | \ + wc -l` +test $lnct -eq 4 || \ + failure "bad documentation output" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of cond.test diff --git a/autoopts/test/argument.test b/autoopts/test/argument.test new file mode 100755 index 0000000..ee7fa0d --- /dev/null +++ b/autoopts/test/argument.test @@ -0,0 +1,209 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# argument.test --- test argument program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2012-08-11 08:12:41 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +export testname test_main argument long_opts +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" + +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehlp=${testname}.hlp +echo creating ${basehlp} +clean_help > ${basehlp} <<'_EOF_' +test_argument - Test AutoOpts for argument +USAGE: argument [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${basehlp} ${testname}.help`" + +./${testname} mumble 2> /dev/null && \ + failure ${testname} should not accept non-options + +./${testname} -s mumble 2> /dev/null && \ + failure ${testname} should not accept bad options + +./${testname} -o string -s 99 > /dev/null || \ + failure ${testname} did not handle its options + +# # # # # # # # # # T E S T 2 # # # # # # # # # # # + +exec 3> ${testname}2.def +${SED} '/arg-type = number/q' ${testname}.def >&3 +cat >&3 <<- _EOF_ + arg-range = "-1"; + arg-range = "3->021"; + arg-range = "040->0x1FFF"; + scaled; + flag-code[0] = ' /* no-op zero */;'; + flag-code[1] = ' /* no-op one */;'; + }; + include = '#include <stdlib.h>'; + _EOF_ +exec 3>&- + +${AG_L} ${testname}2.def || \ + failure AutoGen could not process +{ + ${SED} '/^#if.*TEST MAIN PROCEDURE:/,/#endif.*defined TEST_/d + /^#/s/_ARGUMENT_/_ARGUMENT2_/' \ + ${testname}2.c + cat <<EOF +int main( int argc, char** argv ) { + optionProcess( &test_argumentOptions, argc, argv ); + return 0; } +EOF +} > XX +mv ${testname}2.c ${testname}2.c.save +mv -f XX ${testname}2.c + +Csrc=${testname}2 +compile "-?" + +clean_help > ${testname}2.hlp <<'_EOF_' +test_argument - Test AutoOpts for argument +USAGE: argument2 [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + - is scalable with a suffix: k/K/m/M/g/G/t/T + - It must lie in one of the ranges: + -1 exactly, or + 3 to 17, or + 32 to 8191 + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}2.hlp ${testname}2.help || \ + failure "`diff ${testname}2.hlp ${testname}2.help`" + +./${testname}2 -o string -s 037 > /dev/null && \ + failure ${testname} handled wrong sized option + +./${testname}2 -o string -s 0x37 > /dev/null || \ + failure ${testname} did not handle its options + +./${testname}2 -o string -s 8k > /dev/null || \ + failure ${testname} could not handle 8k + +./${testname}2 -o string -s 8K > ${testname}2-bad.out 2>&1 && \ + failure ${testname} did handle 8K + +${GREP} 'error:.* value .* is out of range\.$' ${testname}2-bad.out || \ + failure "missing 'is out of range' message" + +# # # # # # # # # # T E S T 3 # # # # # # # # # # # + +exec 3> ${testname}3.def +${SED} '/value = .s.;/q' ${testname}.def >&3 +cat >&3 <<- _EOF_ + arg-type = file; + file-exists = yes; + open-file = fopen; + file-mode = "r"; + }; + _EOF_ +exec 3>&- + +${AG_L} ${testname}3.def || \ + failure AutoGen could not process +{ + ${SED} '/^#if.*TEST MAIN PROCEDURE:/,/#endif.*defined TEST_/d + /^#/s/_ARGUMENT_/_ARGUMENT3_/' \ + ${testname}3.c + cat <<EOF +int main( int argc, char** argv ) { + optionProcess( &test_argumentOptions, argc, argv ); + for (;;) { int ch = getc(OPT_VALUE_SECOND); + if (ch == EOF) break; + putc(ch, stdout); } + return fclose(OPT_VALUE_SECOND); } +EOF +} > XX +mv ${testname}3.c ${testname}3.c.save +mv -f XX ${testname}3.c + +Csrc=${testname}3 +compile "-?" + +clean_help > ${testname}3.hlp <<'_EOF_' +test_argument - Test AutoOpts for argument +USAGE: argument3 [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Fil second The second option descrip + - file must pre-exist + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}3.hlp ${testname}3.help || \ + failure "`diff ${testname}3.hlp ${testname}3.help`" + +./${testname}3 -o string -s `pwd`/bogusfilename.c > /dev/null && \ + failure ${testname} handled non-existent file + +./${testname}3 -o string -s `pwd`/${testname}3.hlp > ${testname}3-a.hlp || \ + failure ${testname} could not handle existing file + +cmp -s ${testname}3.hlp ${testname}3-a.hlp || \ + failure "`diff ${testname}3.hlp ${testname}3-a.hlp`" +# # # # # # # # # # T E S T E N D # # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of argument.test diff --git a/autoopts/test/cfg-edit.test b/autoopts/test/cfg-edit.test new file mode 100755 index 0000000..506ca10 --- /dev/null +++ b/autoopts/test/cfg-edit.test @@ -0,0 +1,330 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# rc.test --- test loading and saving of rc files +# +# Time-stamp: "2012-03-31 13:10:38 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +test_name=`echo ${testname} | ${SED} 's/-/_/g'` +cfg_file=`basename ${TMPDIR}`/${testname}.cfg + +exec 5> ${testname}.def +cat >&5 <<- _EOF_ + + AutoGen definitions options; + + config-header = 'config.h'; + prog-name = "test_${testname}"; + prog-title = "Test AutoOpts for ${testname}"; + homerc = ${cfg_file}; + resettable; + argument = '[ <output-config-file> ]'; + + flag = { + name = struct; + value = s; + max = NOLIMIT; + descrip = 'structured argument val'; + arg-type = nested; + }; + + flag = { + name = members; + value = m; + descrip = 'membership set'; + keyword = one, two, three, four, five, six, seven, eight, nine, ten; + arg-default = five; + arg-type = set; + }; + + flag = { + name = enumerate; + value = e; + descrip = 'a test enumeration'; + keyword = uno, dos, tres, quatro, cinco, seis, siete, ocho; + arg-default = cinco; + arg-type = keyword; + }; + + flag = { + name = stacking; + value = k; + descrip = 'stack up a list'; + arg-default = initialized; + arg-type = string; + stack-arg; max = NOLIMIT; + }; + + flag = { + name = number; + value = n; + descrip = 'a range constrained int'; + arg-default = 32; + arg-type = number; + arg-range = '->-1', '1->31', '33', '64->'; + }; + + flag = { + name = boolean; + value = b; + descrip = 'a boolean value'; + arg-default = true; + arg-type = boolean; + }; + + flag = { + name = in-file; + value = I; + descrip = 'an input file'; + arg-type = file; + open-file = descriptor; + file-mode = O_RDONLY; + file-exists = yes; + }; + + flag = { + name = out-file; + value = O; + descrip = 'an output file'; + arg-type = file; + open-file = fopen; + file-mode = w; + file-exists = no; + }; + + flag = { + name = test-file; + value = T; + descrip = 'a test file'; + arg-type = file; + }; + + main = { + main-type = main; + _EOF_ + +asl='<''<' +cat >&5 <<- _EOF_ + main-text = ${asl}- _EOCode_ + { + tOptions * const pOpts = &test_${test_name}Options; + int svix = pOpts->specOptIdx.save_opts; + char const * pzFile = "${cfg_file}-default"; + + if (argc > 0) + pzFile = *argv; + if (svix == 0) exit(1); + SET_OPT_SAVE_OPTS(pzFile); + optionSaveFile(pOpts); + } + _EOF_ + +echo "_EOCode_; };" >&5 + +exec 5>&- + +# # # # # # # # # # CREATE PROGRAM # # # # # # # # # + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehelp=${testname}-base.help +echo creating ${basehelp} +clean_help > ${basehelp} <<_EOF_ +test_${testname} - Test AutoOpts for ${testname} +USAGE: ${testname} [ -<flag> [<val>] ]... [ <output-config-file> ] + Flg Arg Option-Name Description + -s Cpx struct structured argument val + - may appear multiple times + -m Mbr members membership set + - is a set membership option + -e KWd enumerate a test enumeration + -k Str stacking stack up a list + - may appear multiple times + -n Num number a range constrained int + - It must lie in one of the ranges: + less than or equal to -1, or + 1 to 31, or + 33 exactly, or + greater than or equal to 64 + -b T/F boolean a boolean value + -I Fil in-file an input file + - file must pre-exist + -O Fil out-file an output file + - file must not pre-exist + -T Fil test-file a test file + -R Str reset-option Reset an option's state + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + + +The following option preset mechanisms are supported: + - reading file ${testname}.cfg + +The valid "members" option keywords are: + one two three four five six seven eight nine ten + or an integer mask with any of the lower 10 bits set +or you may use a numeric representation. Preceding these with a '!' will +clear the bits, specifying 'none' will clear all bits, and 'all' will set them +all. Multiple entries may be passed as an option argument list. +The valid "enumerate" option keywords are: + uno dos tres quatro cinco seis siete ocho + or an integer from 0 through 7 +_EOF_ + +${SED} "/ - reading file/s/ file .*/ file ${testname}.cfg/" \ + ${testname}.help > X$$ +mv -f X$$ ${testname}.help +cmp -s ${basehelp} ${testname}.help || \ + failure "`diff ${basehelp} ${testname}.help`" + +./${testname} -m 'one + three + seven' '->' +members=`${SED} -n 's/^members *//p' ${cfg_file}` +case "${members}" in +'none + one + three + five + seven' ) : ;; +* ) failure "members not set to one, three, five and seven" ;; +esac + +./${testname} -R '*' '->' +members=`${SED} -n 's/^members *//p' ${cfg_file}` 2>/dev/null +case "${members}" in +'' ) : ;; +* ) failure "members entry not removed" +esac + +arg1="stumble, <foo>foo${ht}lish</foo>, <bar type=integer>1234</bar>, able" +arg2='foo, <bar type=integer>4321</bar> <gr type=nested>one, two=2, three</gr>' +dir=`echo ${TMPDIR} | ${SED} "s@^\`pwd\`//*@@"` +out_file=${dir}/${testname}-out-file +rm -f ${out_file} +./${testname} -m 'one + three' -b true -m 'seven' \ + -s "${arg1}" -n -200 -s "${arg2}" -e ocho \ + -I ${srcdir}/${testname}.test \ + -O ${out_file} \ + -T ${dir}/${testname}-test-file \ + '->' +${SED} '/^#/d' ${cfg_file} > ${testname}-X +mv -f ${testname}-X ${cfg_file} +cat > ${testname}.sample-cfg <<- \_EOF_ + <struct type=nested> + <able/> + <bar type=integer>0x4D2</bar> + <foo>foo	lish</foo> + <stumble/> + </struct> + <struct type=nested> + <bar type=integer>0x10E1</bar> + <foo/> + <gr type=nested> + <one/> + <three/> + <two>2</two> + </gr> + </struct> + members none + one + three + five + seven + enumerate ocho + number -200 + boolean true + _EOF_ + +cat >> ${testname}.sample-cfg <<- _EOF_ + in-file ${srcdir}/${testname}.test + out-file ${out_file} + test-file ${dir}/${testname}-test-file + _EOF_ +pair=${testname}.sample-cfg\ ${cfg_file} +cmp ${pair} || \ + failure "improperly saved state:${nl}`diff ${pair}`" + +rm -f ${out_file} +./${testname} ${cfg_file}-2 +${SED} '/^#/d' ${cfg_file}-2 > ${testname}-X +mv -f ${testname}-X ${cfg_file}-2 +cmp ${cfg_file} ${cfg_file}-2 || \ + failure "mismatched: re-saved config${nl}`diff ${cfg_file} ${cfg_file}-2`" + +rm -f ${cfg_file}-2 +rm -f ${out_file} +./${testname} -R struct ${cfg_file}-2 +test "X`egrep -v '^#' ${cfg_file}-2`" = "X`egrep '^[a-z]' ${cfg_file}`" || \ + failure "structure not erased${nl}`cat ${cfg_file}-2`" + +opt_ct=7 +mv -f ${cfg_file}-2 ${cfg_file} +ct=`egrep '^[a-z]' ${cfg_file} | wc -l` +test ${ct} -eq ${opt_ct} || failure "wrong line count${nl}`cat ${cfg_file}`" + +rm -f ${out_file} + +remove_opt() { + opt_ct=`expr $opt_ct - 1` + ./${testname} -R ${1} '->' + ct=`egrep '^[a-z]' ${cfg_file} | wc -l` + test ${ct} -eq ${opt_ct} || \ + failure "${1} is still there${nl}`cat ${cfg_file}`" +} + +for f in out-file in-file test-file boolean members enumerate number +do + remove_opt $f +done + +./${testname} -k alpha -k beta -k omega ${cfg_file}-XX +${SED} '/^#/d' ${cfg_file}-XX > ${cfg_file}-2 +cat > ${cfg_file}-3 <<- _EOF_ + stacking alpha + stacking beta + stacking omega + _EOF_ +cmp ${cfg_file}-[23] || \ + failure "missing stacking args:${nl}`diff -c ${cfg_file}-[23]`" +./${testname} -R k ${cfg_file}-2 +ct=`egrep '^[a-z]' ${cfg_file}-2 | wc -l` +test ${ct} -eq 0 || failure "arg values still stacked" + +# # # # # # # # # # TEST OPERATION # # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of cfg-edit.test diff --git a/autoopts/test/cond.test b/autoopts/test/cond.test new file mode 100755 index 0000000..8767eda --- /dev/null +++ b/autoopts/test/cond.test @@ -0,0 +1,194 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# cond.test --- test conditionally compiled option +# +# Time-stamp: "2012-03-31 13:09:15 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +testname="${testname}" test_main="${test_main}" \ +argument="${argument}" long_opts="${long_opts}" \ +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" +cat >> ${testname}.def <<EOF +flag = { + name = condition; + value = c; + ifdef = COND; + descrip = "cond test"; + arg-type = number; + doc = mumble; +}; + +flag = { + name = interfere; + value = I; + descrip = "cond interference test"; + arg-type = number; + doc = stumble; +}; +EOF +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +# # # # # # # # # # FIRST TEST # # # # # # # # # + +compile "-?" +mv ${testname} ${testname}-1 +echo creating ${testname}-1.help +clean_help > ${testname}-1.help <<'_EOF_' +test_cond - Test AutoOpts for cond +USAGE: cond [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -I Num interfere cond interference test + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}-1.help ${testname}.help || \ + failure "TEST 1 FAILED${nl}`diff ${testname}-1.help ${testname}.help`" + +./${testname}-1 -c 123 2>/dev/null && \ + failure "*DID* process -c option" + +# # # # # # # # # # SECOND TEST # # # # # # # # # + +INC="${INC} -DCOND=1" +compile "-?" +mv ${testname} ${testname}-2 +clean_help > ${testname}-2.help <<'_EOF_' +test_cond - Test AutoOpts for cond +USAGE: cond [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -c Num condition cond test + -I Num interfere cond interference test + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}-2.help ${testname}.help || \ + failure "TEST 2 FAILED${nl}`diff ${testname}-2.help ${testname}.help`" + +# # # # # # # # # # THIRD TEST # # # # # # # # # + +echo guard-option-names\; >> ${testname}.def +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || failure AutoGen could not process + +( cc_cmd=`echo ${cc_cmd} | \ + ${SED} "s/-DTEST_TEST/-DSECOND -DTEST_TEST/" ` + eval "$cc_cmd" 2>&1 ) \ + | ${SED} -n '/undefining SECOND due to option name conflict/p' \ + > ${testname}-cc.log + +test -s ${testname}-cc.log || \ + failure "warning diffs: 'undefining SECOND' not found" + +# # # # # # # # # # FOURTH TEST # # # # # # # # # + +${SED} '/value = c/s/$/ deprecated;/' ${testname}.def > ${testname}.def4 + +echo ${AG_L} ${testname}.def4 +${AG_L} ${testname}.def4 || \ + failure AutoGen could not process ${testname}.def4 + +compile "-?" +mv ${testname} ${testname}-4 +cmp -s ${testname}-1.help ${testname}.help || \ + failure "TEST 4 FAILED${nl}`diff ${testname}-1.help ${testname}.help`" + +./${testname}-4 -c 123 || \ + failure "could not process -c option" + +# # # # # # # # # # FIFTH TEST # # # # # # # # # + +${SED} '/deprecated/s/deprecated.*/arg-range = "0->1000";/' \ + ${testname}.def4 > ${testname}.def5 + +echo ${AG_L} ${testname}.def5 +${AG_L} ${testname}.def5 || \ + failure AutoGen could not process ${testname}.def5 + +compile "-?" +mv ${testname} ${testname}-5 +clean_help > ${testname}-5.help <<'_EOF_' +test_cond - Test AutoOpts for cond +USAGE: cond [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -c Num condition cond test + - It must be in the range: + 0 to 1000 + -I Num interfere cond interference test + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}-5.help ${testname}.help || \ + failure "TEST 5 FAILED${nl}`diff -u ${testname}-5.help ${testname}.help`" + +# # # # # # # # # # SIXTH TEST # # # # # # # # # + +INC=`echo ${INC} | sed 's/ -DCOND=1//'` +compile "-?" +mv ${testname} ${testname}-6 +clean_help > ${testname}-6.help <<'_EOF_' +test_cond - Test AutoOpts for cond +USAGE: cond [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -I Num interfere cond interference test + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}-6.help ${testname}.help || \ + failure "TEST 6 FAILED${nl}`diff -u ${testname}-6.help ${testname}.help`" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of cond.test diff --git a/autoopts/test/config.test b/autoopts/test/config.test new file mode 100755 index 0000000..d8b6280 --- /dev/null +++ b/autoopts/test/config.test @@ -0,0 +1,201 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# rc.test --- test loading and saving of rc files +# +# Time-stamp: "2011-02-02 12:10:27 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- +. ./defs + +# # # # # # # # # # PROGRAM FILE # # # # # # # # # + +cat > ${testname}.c <<- _EOTest_ + #include <stdio.h> + #include "config.h" + #include <autoopts/options.h> + + int print_entry( const tOptionValue* pGV ); + int print_entry( const tOptionValue* pGV ) { + if (pGV == NULL) { + fprintf( stderr, "ENTRY NOT FOUND\n" ); + return 1; + } + printf( "%-8s -- ", pGV->pzName ); + switch (pGV->valType) { + case OPARG_TYPE_NONE: + fputs( "no value\n", stdout ); break; + + case OPARG_TYPE_STRING: + printf( "string: %s\n", pGV->v.strVal ); break; + + case OPARG_TYPE_ENUMERATION: + printf( "enum: %d\n", pGV->v.enumVal ); break; + + case OPARG_TYPE_BOOLEAN: + printf( "bool: %s\n", + pGV->v.boolVal ? "TRUE" : "false" ); break; + + case OPARG_TYPE_MEMBERSHIP: + printf( "members: 0x%08lX\n", (unsigned long)pGV->v.setVal ); break; + + case OPARG_TYPE_NUMERIC: + printf( "integer: %ld\n", pGV->v.longVal ); break; + + case OPARG_TYPE_HIERARCHY: + printf( "nested: 0x%08lX\n", (unsigned long)pGV->v.nestVal ); break; + + default: + printf( "bad type: %d\n", pGV->valType ); + return 1; + } + return 0; + } + + int main( int argc, char** argv ) { + int res = 0; + const tOptionValue* pOV; + if ((argc < 3) || (argv[1][0] == '-')) { + fputs( "help\n", stdout ); + return 0; + } + pOV = configFileLoad( *++argv ); + if (pOV == NULL) { + fprintf( stderr, "Could not load: %s\n", *argv ); + return 1; + } + argc -= 2; + while (argc-- > 0) { + const tOptionValue* pGV = optionGetValue( pOV, *++argv ); + res |= print_entry( pGV ); + } + + { + const tOptionValue* pGV = optionGetValue( pOV, "n4_ty" ); + pGV = optionGetValue( pGV, "b4r" ); + if (pGV->valType != OPARG_TYPE_BOOLEAN) { + res = 1; + } else if (pGV->v.boolVal) { + fputs( "YES!!\n", stdout ); + } else { + fputs( "oops!!\n", stdout ); + res = 1; + } + } + + { + const tOptionValue* pGV = optionGetValue( pOV, NULL ); + while (pGV != NULL) { + res |= print_entry( pGV ); + pGV = optionNextValue( pOV, pGV ); + } + } + + print_entry( pOV ); + optionUnloadNested( pOV ); + return res; + } + _EOTest_ + +compile --help + +# # # # # # # # # # RUN TESTS # # # # # # # # # + +echo Constructing test ${testname} files +cat > ${testname}.cfg <<- \_EOConfig_ + mumble = grumble + grumble : rumble + + stumble "The\tquick\ + brown fox\tjumped\n\ + over everything." + + stumble2 The\ + quick\ + brown\ + \ + fix. + + <n4_ty type=nested> + foo : foolish + <b4r type=bool> YES!! </b4r> + </n4_ty> + alpha, beta ', gamma' + <beta cooked> "Carol\tTine\n" + </beta> + <zzyzx type=integer> 42 </zzyzx> + _EOConfig_ + +cat > ${testname}.res <<- \_EOResult_ + mumble -- string: grumble + grumble -- string: rumble + stumble -- string: The quickbrown fox jumped + over everything. + alpha -- no value + beta -- string: , gamma + zzyzx -- integer: 42 + YES!! + alpha -- no value + beta -- string: , gamma + beta -- string: Carol Tine + + grumble -- string: rumble + mumble -- string: grumble + n4_ty -- nested: 0xXXXXXXXX + stumble -- string: The quickbrown fox jumped + over everything. + stumble2 -- string: The + quick + brown + + fix. + zzyzx -- integer: 42 + ./config.cfg -- nested: 0xXXXXXXXX + _EOResult_ + +./${testname} ./${testname}.cfg mumble grumble stumble alpha beta zzyzx \ + > ${testname}.tmp-out || { + failure "Cannot run ${testname}" +} + +${SED} '/ -- nested:/s/0x.*/0xXXXXXXXX/' \ + ${testname}.tmp-out > ${testname}.out +cmp ${testname}.out ${testname}.res || { + failure "`diff -c ${testname}.out ${testname}.res`" +} + +./${testname} ${testname}.cfg gamma >/dev/null && \ + failure "found non-existent value" + +# # # # # # # # # # CLEANUP # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of config.test diff --git a/autoopts/test/defs.in b/autoopts/test/defs.in new file mode 100644 index 0000000..d7669ab --- /dev/null +++ b/autoopts/test/defs.in @@ -0,0 +1,351 @@ +#! /bin/echo this_file_should_be_sourced,_not_executed +# -*- Mode: Shell-script -*- +# +# defs --- define the environment for autogen tests. +# +# Time-stamp: "2012-05-13 16:02:07 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# +# C O N F I G U R E D V A L U E S +# +# Make sure srcdir is an absolute path. Supply the variable +# if it does not exist. We want to be able to run the tests +# stand-alone!! +# +cfg_vals() +{ + case `uname -s` in + SunOS ) + if test "X$BASH_VERSION" = X + then + # On Solaris, make certain we do not use /bin/sh + sh=`which bash` + test "X$sh" = X && sh=/usr/xpg4/bin/sh + BASH_VERSION=not-good-enough + export BASH_VERSION + exec $sh "$0" "$@" + fi + ;; + esac + + script_name=$1 + set -a + . ${top_builddir}/config/shdefs + progname=`echo "$script_name" | ${SED} 's,^.*/,,'` + testname=`echo "$progname" | ${SED} 's,\..*$,,'` + test_name=`echo ${testname} | ${SED} 's/-/_/g'` + PS4=">${testname}-\${FUNCNAME}> " + test -z "$srcdir" && exit 1 + srcdir=`cd $srcdir >/dev/null && pwd` + ( exec 2>/dev/null; ulimit -c unlimited ) && \ + ulimit -c unlimited + + test -z "${CFLAGS}" && CFLAGS='@CFLAGS@' + CFLAGS="${CFLAGS} @DEFS@" + test -z "${testsubdir}" && testsubdir=testdir + test -z "${PAGER}" && PAGER=more + nl=' +' ht=' ' + + stdopts=${top_srcdir}/autoopts/test/stdopts.def + test_main=yes + use_flags=true + sed_omit_license="/-\*- buffer-read-only:/,/^ \*\//d" + TERM='' + set +a + + ( + test_local() { + local local_works=yes + } + test_local + ) || eval 'local() { : ; }' + + vars=`set | ${SED} -n '/^\(LANG\|LC_[A-Z_]*\)=/s/=.*//p'` 2>/dev/null + test "X$vars" = X || unset $vars +} + +# If only the "rm(1)" command could be relied upon.... +# +purge() +{ + rm -rf ${*} 2>/dev/null + bad='' + for f + do test -f ${f} -o -d ${f} && bad="${bad} ${f}" + done + test -z "$bad" && return 0 + + set -- $bad + test "x${RANDOM}" = "x${RANDOM}" && RANDOM=`expr 0${RANDOM} + 1 2>/dev/null` + + f=ZZPURGE-${1}-${RANDOM}-$$ + if test $# -gt 1 + then mkdir ${f} + mv $* ${f}/. + else mv $1 ${f} + fi +} + +init_tests() +{ + logfile=`pwd`/testdir/${testname}.log + exec 8>&2 1>${logfile} 2>&1 + + TMPDIR=`pwd`/testdir/${testname}-tmpd + mkdir ${TMPDIR} + + f=`\cd ${LIBGUILE_PATH}/../bin && pwd` + PATH=${f}:${PATH} + echo PATH is ${PATH} >&2 + + builddir=`pwd` + testsubdir=testdir + CFLAGS=`echo ${CFLAGS} | \ + ${SED} "s/-Werror[^ ${ht}]*//g;s/-Wextra//g"` + + lo_dir=${top_builddir}/autoopts + test -d ${lo_dir}/.libs && lo_dir=${lo_dir}/.libs + test "X${LD_LIBRARY_PATH}" = X || LD_LIBRARY_PATH=:${LD_LIBRARY_PATH} + LD_LIBRARY_PATH=${lo_dir}:${LIBGUILE_PATH}${LD_LIBRARY_PATH} + + case ${AG_VERSION} in + *pre* ) GUILE_WARN_DEPRECATED=detailed ;; + * ) GUILE_WARN_DEPRECATED=no ;; + esac + + case "$LIB" in + *-lgen* ) : ;; + * ) + for f in /usr/lib*/libgen.so /lib*/libgen.so + do + test -f $f && { + LIB="${LIB} -lgen" + break + } + done + ;; + esac + lo_lib=`find ${lo_dir} -type f -name libopts*.${OBJEXT}` + LIB="${lo_lib} ${LIB}" + + AG_L=run_ag\ ao + agl_opts="-L${top_builddir}/autoopts/tpl -L${top_srcdir}/autoopts/tpl" + + export TMPDIR PATH LD_LIBRARY_PATH \ + GUILE_WARN_DEPRECATED LIB AG_L agl_opts \ + CC LIBGUILE AG_VERSION +} + +be_silent() +{ + setx=: + VERBOSE=false + purge testdir + + # Sometimes, MSDos FS cannot even rename the directory!! + # + if test -d testdir + then purge testdir/* testdir/.??* + else msg=echo + mkdir testdir || exit 1 + fi + + run_ag() + { + local opts='' + shift + + case " $* " in + *' -L'* ) : ;; + * ) opts="${agl_opts}" ;; + esac + + ${AGexe} ${opts} "$@" + } + + init_tests +} + +be_verbose() +{ + set -x + setx='set -x' + msg=: + VERBOSE=true + test -d testdir || mkdir testdir || exit 1 + + run_ag() + { + local tfile=${testname}-aglog-${1}-$$.log + shift + local opts='' + local tr="--trace=every --trace-out=>>${tfile}" + + case " $* " in + *' -L'* ) : ;; + * ) opts="${agl_opts}" ;; + esac + + MALLOC_CHECK_=2 \ + ${AGexe} ${opts} ${tr} "$@" + } + + init_tests +} + +cfg_inc() +{ + cd testdir || { + echo "Cannot make or change into testdir" >&8 + exit 1 + } + testsubdir=`pwd` + + dirs=` + for f in ${top_builddir} ${top_srcdir} + do + for d in . autoopts agen5 + do + cd $f/$d + pwd >&9 + cd - + done 9>&1 1>/dev/null + done | sort -u | ${SED} 's/^/-I/'` + + INC=`echo ${dirs} ${CPPFLAGS}` + + : "=== Running $progname for ${testname} using ${SHELL} ===" + chmod +w * > /dev/null 2>&1 || : + ${VERBOSE} && SHELLX="${SHELL} -x" || SHELLX="${SHELL}" +} + +clean_help() { + test -z "$sedcmd" && s= || s="${sedcmd}${nl}" + s="${s}/^Packaged by/d${nl}" + s="${s}/^Report .* bugs to/d${nl}" + s="${s}/[Pp]lease send bug reports/d${nl}" + s="${s}/^[ ${ht}]*\$/d" + + ${SED} "${s}" +} + +compile() +{ + ${setx} + test "X${Csrc}" = "X" && Csrc="${testname}" + test "X${Cexe}" = "X" && Cexe="${Csrc}" + test "X${Dnam}" = "X" && Dnam="${testname}" + + d=`echo TEST_TEST_${Dnam}_OPTS | /usr/bin/tr '[a-z]-' '[A-Z]_'` + cc_cmd="${CC} ${CFLAGS} -D$d ${INC} -o ${Cexe} ${Csrc}.c ${LIB}" + eval ${cc_cmd} || \ + failure cannot compile ${Csrc}.c + if test $# -gt 0 + then + ./${Cexe} ${*} ${dosed} || \ + failure cannot obtain help output for ${Csrc} + fi | clean_help > ${Csrc}.help + Csrc='' Cexe='' Dnam='' +} + +cleanup() +{ + trap '' 15 + ${setx} + ${VERBOSE} || { + cd ${builddir} + purge testdir + test -d testdir && mv testdir ZZJUNK-$$ + } + ${msg} ${testname} done +} + +# A standard failure function +# +failure() +{ + trap '' 15 + ${setx} + cd ${testsubdir} + if test -d ../FAILURES + then ( \cd ../FAILURES ; purge -rf ${testname}* .*${testname}* ) + else mkdir ../FAILURES ; fi + + exec > /dev/tty 2>&8 + cat ${logfile} >&2 + + { + mv -f ${testname}* .*${testname}* ../FAILURES || : + } 2>/dev/null + for f in core* + do test -f ${f} && mv -f ${f} ../FAILURES/${testname}-${f} ; done + + echo FAILURE: "$*" >&8 + exit 1 +} + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +cfg_vals $0 + +case "${VERBOSE}" in +'' | [Nn]* | 0 | [Ff]* ) + be_silent ;; + +[Yy]* | [0-9] | [Tt]* ) + be_verbose ;; + +* ) + case "$-" in + *x* ) be_verbose ;; + * ) be_silent ;; + esac +esac + +cfg_inc + +trap "failure 'test ${testname} killed on timeout'" 15 +( ( exec > /dev/null 2>&1 </dev/null + test -z "${kill_delay}" && kill_delay=3 + kill_delay=`expr $kill_delay '*' $AG_TIMEOUT` + sleep ${kill_delay} + ps -p $$ || exit + kill -15 $$ + sleep 1 + ps -p $$ || exit + mv -f `dirname $logfile` ${builddir}/FAILED-${testname} + kill -9 $$ +) & +) + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## sh-basic-offset: 2 +## End: + +# defs.in ends here diff --git a/autoopts/test/doc.test b/autoopts/test/doc.test new file mode 100755 index 0000000..d0c2989 --- /dev/null +++ b/autoopts/test/doc.test @@ -0,0 +1,848 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# +# doc.test --- test doc templates +# +# Time-stamp: "2012-08-11 08:54:27 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs + +test_src=${srcdir}/${testname}.test + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # +echo make defs from test file +sed "1,/^##* *BEGIN-DEFS/d + /^prog-name/s/=.*/= ${testname};/ + \\@^// *END-DEFS@q" \ + ${test_src} > ${testname}.def + +# # # # # # # # # # TEXI DOC CHECK # # # # # # # # # +${AGexe} ${agl_opts} -Tagtexi-cmd ${testname}.def +test -f invoke-${testname}.menu -a -f invoke-${testname}.texi || \ + failure "invoke-${testname}.{menu,texi} not built" +sed '/^@ignore/,/^@end ignore/d' \ + invoke-${testname}.texi > ${testname}-res.texi +rm -f invoke-${testname}.menu invoke-${testname}.texi + +sed "1,/^##* *BEGIN-TEXI/d + /^@ignore/,/^@end ignore/d + /^## END-TEXI/{;s/.*//;q;}" \ + ${test_src} > ${testname}-base.texi + +outfiles="${testname}-res.texi ${testname}-base.texi" +cmp -s ${outfiles} || \ + failure "Differences: ${outfiles}${nl}`diff ${outfiles}`" + +# # # # # # # # # # MAN DOC CHECK # # # # # # # # # +${AGexe} ${agl_opts} -Tagman-cmd ${testname}.def +test -f ${testname}.1 || \ + failure "${testname}.1 not built" + +{ + sed '/^\.\\"/d;/^\.TH/s/ *".*//' ${testname}.1 + rm -f ${testname}.1 + echo +} > ${testname}-res.1 + +sed "1,/^##* *BEGIN-MAN/d + /^## END-MAN/{;s/.*//;q;}" ${test_src} > ${testname}-base.1 + +outfiles="${testname}-base.1 ${testname}-res.1" +cmp -s ${outfiles} || \ + failure "Differences: ${outfiles}${nl}`diff ${outfiles}`" + +# # # # # # # # # # MDOC DOC CHECK # # # # # # # # # +${AGexe} ${agl_opts} -Tagmdoc-cmd ${testname}.def +test -f ${testname}.1 || \ + failure "${testname}.1 not built" + +{ + ${EGREP} -v '^\.(Dd |Os |\\")' ${testname}.1 + echo +} > ${testname}-mdoc-res.1 + +sed "1,/^##* *BEGIN-MDOC/d + /^## END-MDOC/{;s/.*//;q;}" ${test_src} > ${testname}-mdoc-base.1 + +outfiles="${testname}-mdoc-base.1 ${testname}-mdoc-res.1" +cmp -s ${outfiles} || \ + failure "Differences: ${outfiles}${nl}`diff ${outfiles}`" + +# # # # # # # # # # POT CHECK # # # # # # # # # +${AGexe} ${agl_opts} -Tdef2pot ${testname}.def +test -s ${testname}.pot || \ + failure "${testname}.pot not built" + +{ + sed -e '/^# *Copyright/s/).*/)/' \ + -e '/^$/d' \ + -e 's/>, 20[0-9][0-9]\./>./' \ + -e '/POT-Creation-Date:/s/ 2[0-9].*/\\n"/' \ + ${testname}.pot + echo +} > ${testname}-res.pot + +sed "1,/^##* *BEGIN-POT/d + /^$/d + /^## END-POT/{;s/.*//;q;}" ${test_src} > ${testname}-base.pot + +outfiles="${testname}-base.pot ${testname}-res.pot" +cmp -s ${outfiles} || \ + failure "Differences: ${outfiles}${nl}`diff ${outfiles}`" + +# # # # # # # # # # # FINISH # # # # # # # # # # # + +cleanup + +exit 0 + +# # # # # # # # # # # OPTION DEFS + +cat <<_End_Of_Definitions_ +## BEGIN-DEFS +AutoGen Definitions options; +prog-name = gnutls-cli; +prog-title = "GnuTLS client"; +prog-desc = "Simple client program to set up a TLS connection."; +short-usage = <<- _EOUsage_ + Usage: gnutls-cli [options] hostname + gnutls-cli --help for usage instructions. + _EOUsage_; +prog-group = "GnuTLS"; +detail = <<- _EODetail_ + Simple client program to set up a TLS connection to some other computer. + It sets up a TLS connection and forwards data from the standard input + to the secured socket and vice versa. + _EODetail_; + +gnu-usage; +no-misuse-usage; +disable-save; +reorder-args; +no-xlate = opt; +argument = "[hostname]"; +long-opts; + +copyright = { + date = "2000-2012"; + owner = "Free Software Foundation"; + author = "Nikos Mavrogiannopoulos, Simon Josefsson and others; " + "see /usr/share/doc/gnutls-bin/AUTHORS for a complete list."; + eaddr = "bug-gnutls@gnu.org"; + type = gpl; +}; +version = "3.0.12"; +help-value = h; +more-help-value = M; + +flag = { + name = debug; + value = d; + arg-type = number; + arg-range = "0->9999"; + descrip = "Enable @code{debugging}"; + doc = 'really enable debugging'; +}; + +flag = { + name = mtu; + arg-type = number; + arg-range = "0->17000"; + descrip = "Set MTU for datagram TLS"; + doc = "Really set MTU for datagram TLS"; +}; + +flag = { + name = group-2; + descrip = "second group of options"; + documentation; +}; + +flag = { + name = crlf; + descrip = "Send CR LF instead of LF"; + doc = "Really send CR LF instead of LF"; +}; + +flag = { + name = x509fmtder; + descrip = "Use DER format for certificates to read from"; + doc = "Really use DER format for certificates to read from"; +}; + +flag = { + name = group-3; + descrip = "third group of options"; + documentation; +}; + +flag = { + name = recordsize; + arg-type = number; + arg-range = "0->4096"; + descrip = "The maximum record size to advertize"; + doc = "Really the maximum record size to advertize"; +}; + +flag = { + name = priority; + arg-type = string; + descrip = "Priorities string"; + doc = <<- _EODoc_ + TLS algorithms and protocols to enable. You can + use predefined sets of ciphersuites such as PERFORMANCE, + NORMAL, SECURE128, SECURE256. + + Check the GnuTLS manual on section ``Priority strings'' for more + information on allowed keywords + _EODoc_; +}; + + +doc-section = { + ds-type = 'SEE ALSO'; + ds-format = texi; + omit-texi; + ds-text = 'gnutls-cli-debug(1), gnutls-serv(1)'; +}; + +doc-section = { + ds-type = EXAMPLES; + ds-format = texi; + ds-text = <<- _EOT_ + To connect to a server using PSK authentication, you need to enable + the choice of PSK by using a cipher priority parameter such as in the + example below. + @example + $ ./gnutls-cli -p 5556 localhost --pskusername psk_identity \\ + --pskkey 88f3824b3e5659f52d00e959bacab954b6540344 \\ + --priority NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK + Resolving 'localhost'... + Connecting to '127.0.0.1:5556'... + - PSK authentication. + - Version: TLS1.1 + - Key Exchange: PSK + - Cipher: AES-128-CBC + - MAC: SHA1 + - Compression: NULL + - Handshake was completed + + - Simple Client Mode: + @end example + By keeping the --pskusername parameter and removing the --pskkey + parameter, it will query only for the password during the handshake. + + To list the ciphersuites in a priority string: + @example + $ ./gnutls-cli --priority SECURE192 -l + Cipher suites for SECURE192 + TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 0xc0, 0x24 TLS1.2 + TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 0xc0, 0x2e TLS1.2 + TLS_ECDHE_RSA_AES_256_GCM_SHA384 0xc0, 0x30 TLS1.2 + TLS_DHE_RSA_AES_256_CBC_SHA256 0x00, 0x6b TLS1.2 + TLS_DHE_DSS_AES_256_CBC_SHA256 0x00, 0x6a TLS1.2 + TLS_RSA_AES_256_CBC_SHA256 0x00, 0x3d TLS1.2 + @end example + _EOT_; +}; +// END-DEFS +_End_Of_Definitions_ + +# # # # # # # # # # # TEXI TEXT + +cat <<_End_Of_TexInfo_ +## BEGIN-TEXI +@node doc Invocation +@section Invoking doc +@pindex doc +@cindex GnuTLS client +Simple client program to set up a TLS connection to some other computer. +It sets up a TLS connection and forwards data from the standard input +to the secured socket and vice versa. + +This section was generated by @strong{AutoGen}, +using the @code{agtexi-cmd} template and the option descriptions for the @code{doc} program. +This software is released under the GNU General Public License, version 3 or later. + +@menu +* doc usage:: doc help/usage (@option{--help}) +* doc base-options:: Base options +* doc group-2:: group-2 options +* doc group-3:: group-3 options +* doc exit status:: exit status +* doc Examples:: Examples +@end menu + +@node doc usage +@subsection doc help/usage (@option{--help}) +@cindex doc help + +This is the automatically generated usage text for doc. + +The text printed is the same whether selected with the @code{help} option +(@option{--help}) or the @code{more-help} option (@option{--more-help}). @code{more-help} will print +the usage text by passing it through a pager program. +@code{more-help} is disabled on platforms without a working +@code{fork(2)} function. The @code{PAGER} environment variable is +used to select the program, defaulting to @file{more}. Both will exit +with a status code of 0. + +@exampleindent 0 +@example +doc is unavailable - no --help +@end example +@exampleindent 4 + +@node doc +@subsection Base options +@subsubheading debug option (-d). +@anchor{doc debug} +@cindex doc-debug + +This is the ``enable @code{debugging}'' option. +This option takes an argument number. +really enable debugging +@subsubheading mtu option. +@anchor{doc mtu} +@cindex doc-mtu + +This is the ``set mtu for datagram tls'' option. +This option takes an argument number. +Really set MTU for datagram TLS +@node doc group-2 +@subsection group-2 options +second group of options. +@subsubheading crlf option. +@anchor{doc crlf} +@cindex doc-crlf + +This is the ``send cr lf instead of lf'' option. +Really send CR LF instead of LF +@subsubheading x509fmtder option. +@anchor{doc x509fmtder} +@cindex doc-x509fmtder + +This is the ``use der format for certificates to read from'' option. +Really use DER format for certificates to read from +@node doc group-3 +@subsection group-3 options +third group of options. +@subsubheading recordsize option. +@anchor{doc recordsize} +@cindex doc-recordsize + +This is the ``the maximum record size to advertize'' option. +This option takes an argument number. +Really the maximum record size to advertize +@subsubheading priority option. +@anchor{doc priority} +@cindex doc-priority + +This is the ``priorities string'' option. +This option takes an argument string. +TLS algorithms and protocols to enable. You can +use predefined sets of ciphersuites such as PERFORMANCE, +NORMAL, SECURE128, SECURE256. + +Check the GnuTLS manual on section ``Priority strings'' for more +information on allowed keywords +@node doc exit status +@subsection doc exit status + +One of the following exit values will be returned: +@table @samp +@item 0 (EXIT_SUCCESS) +Successful program execution. +@item 1 (EXIT_FAILURE) +The operation failed or the command syntax was not valid. +@end table +@node doc Examples +@subsection doc Examples +To connect to a server using PSK authentication, you need to enable +the choice of PSK by using a cipher priority parameter such as in the +example below. +@example +$ ./gnutls-cli -p 5556 localhost --pskusername psk_identity \\ + --pskkey 88f3824b3e5659f52d00e959bacab954b6540344 \\ + --priority NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK +Resolving 'localhost'... +Connecting to '127.0.0.1:5556'... +- PSK authentication. +- Version: TLS1.1 +- Key Exchange: PSK +- Cipher: AES-128-CBC +- MAC: SHA1 +- Compression: NULL +- Handshake was completed + +- Simple Client Mode: +@end example +By keeping the --pskusername parameter and removing the --pskkey +parameter, it will query only for the password during the handshake. + +To list the ciphersuites in a priority string: +@example +$ ./gnutls-cli --priority SECURE192 -l +Cipher suites for SECURE192 +TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 0xc0, 0x24 TLS1.2 +TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 0xc0, 0x2e TLS1.2 +TLS_ECDHE_RSA_AES_256_GCM_SHA384 0xc0, 0x30 TLS1.2 +TLS_DHE_RSA_AES_256_CBC_SHA256 0x00, 0x6b TLS1.2 +TLS_DHE_DSS_AES_256_CBC_SHA256 0x00, 0x6a TLS1.2 +TLS_RSA_AES_256_CBC_SHA256 0x00, 0x3d TLS1.2 +@end example +## END-TEXI +_End_Of_TexInfo_ + +# # # # # # # # # # # MAN PAGE + +cat <<_End_Of_ManPage_ +## BEGIN-MAN +.TH doc 1 +.SH NAME +doc \- GnuTLS client +.SH SYNOPSIS +.B doc +.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \-\-\fIopt\-name\fP " [[=| ]\fIvalue\fP]]..." [hostname] +.PP +Operands and options may be intermixed. They will be reordered. +.SH "DESCRIPTION" +Simple client program to set up a TLS connection to some other computer. +It sets up a TLS connection and forwards data from the standard input +to the secured socket and vice versa. +.SH "OPTIONS" +.TP +.BR \-d " \fInumber\fP, " \-\-debug "=" \fInumber\fP +Enable \fBdebugging\fP. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 9999 +.fi +.in -4 +.sp +really enable debugging +.TP +.BR \-\-mtu "=\fInumber\fP" +Set MTU for datagram TLS. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 17000 +.fi +.in -4 +.sp +Really set MTU for datagram TLS +.SS "second group of options" +.TP +.BR \-\-crlf +Send CR LF instead of LF. +.sp +Really send CR LF instead of LF +.TP +.BR \-\-x509fmtder +Use DER format for certificates to read from. +.sp +Really use DER format for certificates to read from +.SS "third group of options" +.TP +.BR \-\-recordsize "=\fInumber\fP" +The maximum record size to advertize. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 4096 +.fi +.in -4 +.sp +Really the maximum record size to advertize +.TP +.BR \-\-priority "=\fIstring\fP" +Priorities string. +.sp +TLS algorithms and protocols to enable. You can +use predefined sets of ciphersuites such as PERFORMANCE, +NORMAL, SECURE128, SECURE256. +Check the GnuTLS manual on section \(lqPriority strings\(rq for more +information on allowed keywords +.TP +.BR \-h , " \-\-help" +Display usage information and exit. +.TP +.BR \-M , " \-\-more-help" +Pass the extended usage information through a pager. +.TP +.BR \-v " [{\fIv|c|n\fP}]," " \-\-version" "[=\fI{v|c|n}\fP]" +Output version of program and exit. The default mode is `v', a simple +version. The `c' mode will print copyright information and `n' will +print the full copyright notice. +.SH EXAMPLES +To connect to a server using PSK authentication, you need to enable +the choice of PSK by using a cipher priority parameter such as in the +example below. +.br +.in +4 +.nf +$ ./gnutls\-cli \-p 5556 localhost \-\-pskusername psk_identity \\ + \-\-pskkey 88f3824b3e5659f52d00e959bacab954b6540344 \\ + \-\-priority NORMAL:\-KX\-ALL:+ECDHE\-PSK:+DHE\-PSK:+PSK +Resolving 'localhost'... +Connecting to '127.0.0.1:5556'... +- PSK authentication. +- Version: TLS1.1 +- Key Exchange: PSK +- Cipher: AES\-128\-CBC +- MAC: SHA1 +- Compression: NULL +- Handshake was completed +- Simple Client Mode: +.in -4 +.fi +By keeping the \-\-pskusername parameter and removing the \-\-pskkey +parameter, it will query only for the password during the handshake. +.sp +To list the ciphersuites in a priority string: +.br +.in +4 +.nf +$ ./gnutls\-cli \-\-priority SECURE192 \-l +Cipher suites for SECURE192 +TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 0xc0, 0x24 TLS1.2 +TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 0xc0, 0x2e TLS1.2 +TLS_ECDHE_RSA_AES_256_GCM_SHA384 0xc0, 0x30 TLS1.2 +TLS_DHE_RSA_AES_256_CBC_SHA256 0x00, 0x6b TLS1.2 +TLS_DHE_DSS_AES_256_CBC_SHA256 0x00, 0x6a TLS1.2 +TLS_RSA_AES_256_CBC_SHA256 0x00, 0x3d TLS1.2 +.in -4 +.fi +.SH "EXIT STATUS" +One of the following exit values will be returned: +.TP +.BR 0 " (EXIT_SUCCESS)" +Successful program execution. +.TP +.BR 1 " (EXIT_FAILURE)" +The operation failed or the command syntax was not valid. +.SH "SEE ALSO" +gnutls\-cli\-debug(1), gnutls\-serv(1) +.SH "AUTHORS" +Nikos Mavrogiannopoulos, Simon Josefsson and others; see /usr/share/doc/gnutls-bin/AUTHORS for a complete list. +.SH "COPYRIGHT" +Copyright (C) 2000-2012 Free Software Foundation all rights reserved. +This program is released under the terms of the GNU General Public License, version 3 or later. +.SH "BUGS" +Please send bug reports to: bug-gnutls@gnu.org +.SH "NOTES" +This manual page was \fIAutoGen\fP-erated from the \fBdoc\fP +option definitions. +## END-MAN +_End_Of_ManPage_ + +# # # # # # # # # # # MAN PAGE + +cat <<_End_Of_MdocPage_ +## BEGIN-MDOC +.Dt DOC 1 User Commands +.Sh NAME +.Nm doc +.Nd GnuTLS client +.Sh SYNOPSIS +.Nm +.Op Fl flags +.Op Fl flag Ar value +.Op Fl \-option-name Ar value +[hostname] +.Pp +Operands and options may be intermixed. They will be reordered. +.Pp +.Sh "DESCRIPTION" +Simple client program to set up a TLS connection to some other computer. +It sets up a TLS connection and forwards data from the standard input +to the secured socket and vice versa. +.Sh "OPTIONS" +.Bl -tag +.It \-d " \fInumber\fP, " \-\-debug "=" \fInumber\fP +Enable \fBdebugging\fP. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 9999 +.fi +.in -4 +.sp +really enable debugging +.It \-\-mtu "=\fInumber\fP" +Set MTU for datagram TLS. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 17000 +.fi +.in -4 +.sp +Really set MTU for datagram TLS +.Ss "second group of options" +.It \-\-crlf +Send CR LF instead of LF. +.sp +Really send CR LF instead of LF +.It \-\-x509fmtder +Use DER format for certificates to read from. +.sp +Really use DER format for certificates to read from +.Ss "third group of options" +.It \-\-recordsize "=\fInumber\fP" +The maximum record size to advertize. +This option takes an integer number as its argument. +The value of \fInumber\fP is constrained to being: +.in +4 +.nf +.na +in the range 0 through 4096 +.fi +.in -4 +.sp +Really the maximum record size to advertize +.It \-\-priority "=\fIstring\fP" +Priorities string. +.sp +TLS algorithms and protocols to enable. You can +use predefined sets of ciphersuites such as PERFORMANCE, +NORMAL, SECURE128, SECURE256. +.sp +Check the GnuTLS manual on section \(lqPriority strings\(rq for more +information on allowed keywords +.It \-h , " \-\-help" +Display usage information and exit. +.It \-M , " \-\-more-help" +Pass the extended usage information through a pager. +.It \-v " [{\fIv|c|n\fP}]," " \-\-version" "[=\fI{v|c|n}\fP]" +Output version of program and exit. The default mode is `v', a simple +version. The `c' mode will print copyright information and `n' will +print the full copyright notice. +.El +.Sh EXAMPLES +To connect to a server using PSK authentication, you need to enable +the choice of PSK by using a cipher priority parameter such as in the +example below. +.Bd -literal -offset indent +$ ./gnutls\-cli \-p 5556 localhost \-\-pskusername psk_identity \\ + \-\-pskkey 88f3824b3e5659f52d00e959bacab954b6540344 \\ + \-\-priority NORMAL:\-KX\-ALL:+ECDHE\-PSK:+DHE\-PSK:+PSK +Resolving 'localhost'... +Connecting to '127.0.0.1:5556'... +- PSK authentication. +- Version: TLS1.1 +- Key Exchange: PSK +- Cipher: AES\-128\-CBC +- MAC: SHA1 +- Compression: NULL +- Handshake was completed +- Simple Client Mode: +.Ed +By keeping the \-\-pskusername parameter and removing the \-\-pskkey +parameter, it will query only for the password during the handshake. +.sp +To list the ciphersuites in a priority string: +.Bd -literal -offset indent +$ ./gnutls\-cli \-\-priority SECURE192 \-l +Cipher suites for SECURE192 +TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 0xc0, 0x24 TLS1.2 +TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 0xc0, 0x2e TLS1.2 +TLS_ECDHE_RSA_AES_256_GCM_SHA384 0xc0, 0x30 TLS1.2 +TLS_DHE_RSA_AES_256_CBC_SHA256 0x00, 0x6b TLS1.2 +TLS_DHE_DSS_AES_256_CBC_SHA256 0x00, 0x6a TLS1.2 +TLS_RSA_AES_256_CBC_SHA256 0x00, 0x3d TLS1.2 +.Ed +.Sh "EXIT STATUS" +One of the following exit values will be returned: +.Bl -tag +.It 0 " (EXIT_SUCCESS)" +Successful program execution. +.It 1 " (EXIT_FAILURE)" +The operation failed or the command syntax was not valid. +.El +.Sh "SEE ALSO" +gnutls\-cli\-debug(1), gnutls\-serv(1) +.Sh "AUTHORS" +Nikos Mavrogiannopoulos, Simon Josefsson and others; see /usr/share/doc/gnutls-bin/AUTHORS for a complete list. +.Sh "COPYRIGHT" +Copyright (C) 2000-2012 Free Software Foundation all rights reserved. +This program is released under the terms of the GNU General Public License, version 3 or later. +.Sh "BUGS" +Please send bug reports to: bug-gnutls@gnu.org +.Sh "NOTES" +This manual page was \fIAutoGen\fP-erated from the \fBdoc\fP +option definitions. +## END-MDOC +_End_Of_MdocPage_ + +# # # # # # # # # # # POT PAGE + +cat <<_End_Of_PotPage_ +## BEGIN-POT +# localization template (.pot) for doc.def of doc, +# this file is used to generate localized manual for doc. +# Copyright (C) +# This file is distributed under the terms of the +# the GNU General Public License, version 3 or later +# The program owners may be reached via: +# Free Software Foundation <bug-gnutls@gnu.org>. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: doc 3.0.12\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date:\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: doc.def:3 +msgid "GnuTLS client" +msgstr "" + +#: doc.def:41 +msgid "Enable debugging" +msgstr "" + +#: doc.def:42 +msgid "really enable debugging" +msgstr "" + +#: doc.def:49 +msgid "Set MTU for datagram TLS" +msgstr "" + +#: doc.def:50 +msgid "Really set MTU for datagram TLS" +msgstr "" + +#: doc.def:55 +msgid "second group of options" +msgstr "" + +#: doc.def:61 +msgid "Send CR LF instead of LF" +msgstr "" + +#: doc.def:62 +msgid "Really send CR LF instead of LF" +msgstr "" + +#: doc.def:67 +msgid "Use DER format for certificates to read from" +msgstr "" + +#: doc.def:68 +msgid "Really use DER format for certificates to read from" +msgstr "" + +#: doc.def:73 +msgid "third group of options" +msgstr "" + +#: doc.def:81 +msgid "The maximum record size to advertize" +msgstr "" + +#: doc.def:82 +msgid "Really the maximum record size to advertize" +msgstr "" + +#: doc.def:88 +msgid "Priorities string" +msgstr "" + +#: doc.def:90 +msgid "TLS algorithms and protocols to enable. You can use predefined sets of\n" + "ciphersuites such as PERFORMANCE, NORMAL, SECURE128, SECURE256.\n\n" + "Check the GnuTLS manual on section ``Priority strings'' for more\n" + "information on allowed keywords" +msgstr "" + +#: doc.def:104 +msgid "gnutls-cli-debug(1), gnutls-serv(1)" +msgstr "" + +#: doc.def:111 +msgid "To connect to a server using PSK authentication, you need to enable the\n" + "choice of PSK by using a cipher priority parameter such as in the\n" + "example below. @example $ ./gnutls-cli -p 5556 localhost --pskusername\n" + "psk_identity \\\\ --pskkey 88f3824b3e5659f52d00e959bacab954b6540344 \\\\\n" + "--priority NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK Resolving\n" + "'localhost'... Connecting to '127.0.0.1:5556'... - PSK authentication.\n" + "- Version: TLS1.1 - Key Exchange: PSK - Cipher: AES-128-CBC - MAC: SHA1\n" + "- Compression: NULL - Handshake was completed\n\n" + "- Simple Client Mode: @end example By keeping the --pskusername\n" + "parameter and removing the --pskkey parameter, it will query only for\n" + "the password during the handshake.\n\n" + "To list the ciphersuites in a priority string: @example $ ./gnutls-cli\n" + "--priority SECURE192 -l Cipher suites for SECURE192\n" + "TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 0xc0, 0x24 TLS1.2\n" + "TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 0xc0, 0x2e TLS1.2\n" + "TLS_ECDHE_RSA_AES_256_GCM_SHA384 0xc0, 0x30 TLS1.2\n" + "TLS_DHE_RSA_AES_256_CBC_SHA256 0x00, 0x6b TLS1.2\n" + "TLS_DHE_DSS_AES_256_CBC_SHA256 0x00, 0x6a TLS1.2\n" + "TLS_RSA_AES_256_CBC_SHA256 0x00, 0x3d TLS1.2 @end example" +msgstr "" + +#: doc.def:11 +msgid "Simple client program to set up a TLS connection to some other computer.\n" + "It sets up a TLS connection and forwards data from the standard input to\n" + "the secured socket and vice versa." +msgstr "" + +#: +msgid "This program is released under the terms of the GNU General Public License, version 3 or later." +msgstr "" + +#: doc.def:21 +msgid "[hostname]" +msgstr "" +## END-POT +_End_Of_PotPage_ + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of doc.test diff --git a/autoopts/test/enums.test b/autoopts/test/enums.test new file mode 100755 index 0000000..d3edf55 --- /dev/null +++ b/autoopts/test/enums.test @@ -0,0 +1,309 @@ +#! /bin/sh +# -*- Mode: shell-script -*- +# ---------------------------------------------------------------------- +# enums.test --- test enums program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2012-08-11 08:31:49 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +cat > ${testname}.def <<- _EOF_ + autogen definitions options; + + prog-name = ${testname}-test; + prog-title = 'test complex main procedure'; + config-header = config.h; + + argument = '[ <node> ]'; + long-opts; + + flag = { + name = print; + value = p; + descrip = 'Print operational info'; + arg-type = keyword; + arg-name = type; + min = 1; + equivalence = print; + keyword = one, two, three, four, five, six, seven, eight, nine, ten; + }; + + flag = { + name = dump-log; + value = D; + descrip = 'Dump the program log'; + equivalence = print; + }; + + flag = { + name = all-dump; + value = A; + equivalence = print; + descrip = 'Dump everything we\'ve got'; + }; + + flag = { + name = set; + value = s; + descrip = 'set options'; + arg-type = set; + arg-name = 'opt[, ...]'; + arg-default = first,fifth,ninth,thirteenth; + equivalence = print; + keyword = first, second, third, fourth, fifth, sixth, seventh, + eighth, ninth, tenth, eleventh, twelfth, thirteenth, + fourteenth, fifteenth, sixteenth; + }; + + flag = { + name = unset; + value = u; + descrip = 'unset debug options'; + arg-type = string; + arg-name = 'opt[, ...]'; + equivalence = print; + flag-proc = set; + }; + + flag = { + name = msg-num; + value = m; + descrip = 'message number'; + no-preset; + arg-type = string; + arg-name = id; + max = NOLIMIT; + + flag-code = <<- _EndOfFlagCode_ + /* + * 'set' and 'unset' must be acted upon immediately + * -- we may get more of them. + */ + switch (WHICH_IDX_PRINT) { + case NO_EQUIVALENT: + case INDEX_OPT_PRINT: + case INDEX_OPT_DUMP_LOG: + case INDEX_OPT_ALL_DUMP: + if (COUNT_OPT( MSG_NUM ) > 1) { + fputs("Except for 'set' and 'unset' functions, " + "only one 'msg-num' is allowed\n", stderr); + USAGE(EXIT_FAILURE); + } + break; + case INDEX_OPT_SET: + set_options(1, pOptDesc->pzLastArg); + break; + case INDEX_OPT_UNSET: + set_options(0, pOptDesc->pzLastArg); + break; + }; + _EndOfFlagCode_; + }; + /* + cat <<_EOF_ + * for emacs */ + + export = "#include <sys/types.h>\n" + "#include <sys/stat.h>\n" + "#include <stdio.h>\n" + "#include <stdlib.h>\n" + "#include <fcntl.h>\n" + "#include \"config.h\"\n" + "#include \"compat/compat.h\""; + + include = 'void set_options(int mode, char const* pzArg);'; + + main = { + main-type = include; + tpl = ${testname}.tpl; + }; + _EOF_ + +# # # # # # # # # # TEMPLATE FILE # # # # # # # # # +# +# In one case we must not use built in echo. +# +cat > ${testname}.tpl <<- \__EOF + [= AutoGen5 Template -*- Mode: C -*- =] + [=(define proc-list "")=] + typedef int (do_proc_t)(void); + extern do_proc_t + [= (set! proc-list (string-append "do_print_undefined,\ndo_print_" + (join ",\ndo_print_" (stack "flag[0].keyword")) )) + (set! proc-list + (shell (string-append "${CLexe} -I4 --spread=1 <<_EOF_\n" + proc-list "\n_EOF_")) ) + proc-list =]; + do_proc_t* do_proc[] = { + [= (. proc-list) =] }; + + [=(shellf "procs='%s' ; ix=0 ; for p in ${procs} + do + p=`echo $p | sed s/,//` + echo int ${p}'(void) {' + printf ' fputs(\"'${p}'\\\\n\", stdout);\n' + echo \" return ${ix}; }\" + ix=`expr $ix + 1` + done" proc-list) =] + + int + do_dump_log(void) + { + return WHICH_IDX_PRINT != INDEX_OPT_DUMP_LOG; + } + + int + do_all_dump(void) + { + return WHICH_IDX_PRINT != INDEX_OPT_ALL_DUMP; + } + + int + do_set(int which_way) + { + printf("PRINT = 0x%lX\n", (unsigned long)DESC(PRINT).optCookie); + printf("SET = 0x%lX\n", (unsigned long)DESC(SET).optCookie); + if (which_way) + printf("0x%lX\n", OPT_VALUE_SET); + else + printf("0x%lX\n", (~ OPT_VALUE_SET) & SET_MEMBERSHIP_MASK); + return 0; + } + + void + set_options(int mode, char const* pzArg) + { + exit(atoi(pzArg)); + } + __EOF + +cat >> ${testname}.tpl <<- __EOF + int + main( int argc, char** argv ) + { + { + int ct = optionProcess(&${testname}_testOptions, argc, argv); + argc -= ct; + argv += ct; + } + + if (argc > 1) + return EXIT_FAILURE; + + /* + * Invoke the proper operational procedure. + */ + { + int res = 0; + switch (WHICH_IDX_PRINT) { + case INDEX_OPT_PRINT: res = do_proc[OPT_VALUE_PRINT](); break; + case INDEX_OPT_DUMP_LOG: res = do_dump_log(); break; + case INDEX_OPT_ALL_DUMP: res = do_all_dump(); break; + case INDEX_OPT_SET: res = do_set(1); break; + case INDEX_OPT_UNSET: res = do_set(0); break; + } + return res; + } + } + __EOF + +# # # # # # # # # # CREATE PROGRAM # # # # # # # # # + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehlp=${testname}.hlp +echo creating ${basehlp} +clean_help > ${basehlp} <<_EOF_ +${testname}-test - test complex main procedure +USAGE: ${testname} { -<flag> [<val>] | --<name>[{=| }<val>] }... [ <node> ] + Flg Arg Option-Name Req? Description + -p KWd print YES Print operational info + -D no dump-log opt Dump the program log + - an alternate for print + -A no all-dump opt Dump everything we've got + - an alternate for print + -s Mbr set opt set options + - an alternate for print + -u Str unset opt unset debug options + - an alternate for print + -m Str msg-num opt message number + - may not be preset + - may appear multiple times + -? no help opt Display extended usage information and exit + -! no more-help opt Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +The valid "print" option keywords are: + one two three four five six seven eight nine ten + or an integer from 1 through 10 +The valid "set" option keywords are: + first second third fourth fifth sixth seventh + eighth ninth tenth eleventh twelfth thirteenth fourteenth + fifteenth sixteenth + or an integer mask with any of the lower 16 bits set +or you may use a numeric representation. Preceding these with a '!' will +clear the bits, specifying 'none' will clear all bits, and 'all' will set them +all. Multiple entries may be passed as an option argument list. +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${basehlp} ${testname}.help`" + +# # # # # # # # # # TEST OPERATION # # # # # # # # # # + +ix=0 +for f in one two three four five six seven eight nine ten +do + ix=`expr $ix + 1` + txt=`./${testname} -p $f` + test $? -eq $ix || \ + failure "'./${testname} -p $f' did not yield $ix" + test "${txt}" = "do_print_${f}" || \ + failure "'./${testname} -p $f' did not print 'do_print_${f}'" +done + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## sh-basic-offset: 2 +## End: + +# end of enums.test diff --git a/autoopts/test/equiv.test b/autoopts/test/equiv.test new file mode 100755 index 0000000..2c4cc74 --- /dev/null +++ b/autoopts/test/equiv.test @@ -0,0 +1,274 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# +# equiv.test --- test option equivivalence classes +# +# Time-stamp: "2012-02-12 09:28:59 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +CFLAGS="-g -static" \ +testname="${testname}" test_main="${test_main}" \ +argument="${argument}" long_opts="${long_opts}" \ +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" +cat >> ${testname}.def <<'_EOF_' +long-opts; + +flag = { + name = alpha; + descrip = "alpha opt"; + equivalence = alpha; + doc = 'alpha mumbling'; + arg-type = str; + arg-optional; +}; + +flag = { + name = beta; + descrip = "beta opt"; + equivalence = alpha; + doc = 'beta mumbling'; + arg-type = num; +}; + +flag = { + name = gamma; + descrip = "gamma opt"; + equivalence = alpha; + doc = 'gamma mumbling'; + arg-type = bool; +}; + +flag = { + name = omega; + descrip = "omega opt"; + equivalence = alpha; + doc = 'omega mumbling'; + arg-type = key; + keyword = uno, dos, tres, mucho; + arg-optional; + arg-default = mucho; +}; +_EOF_ +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure "AutoGen could not process - exited $?" + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}-base.help +clean_help > ${testname}-base.help <<_EOF_ +test_${testname} - Test AutoOpts for ${testname} +USAGE: equiv [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + opt alpha alpha opt + Num beta beta opt + - an alternate for alpha + T/F gamma gamma opt + - an alternate for alpha + opt omega omega opt + - an alternate for alpha + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +The valid "omega" option keywords are: + uno dos tres mucho + or an integer from 0 through 3 +_EOF_ + +cmp -s ${testname}*.help || \ + failure "`diff ${testname}-base.help ${testname}.help`" + +cat > ${testname}-base.out <<_EOF_ +OPTION_CT=3 +export OPTION_CT +TEST_EQUIV_SECOND=2 # 0x2 +export TEST_EQUIV_SECOND +TEST_EQUIV_ALPHA=1 # 0x1 +export TEST_EQUIV_ALPHA +=== --beta 5 -o opt === +OPTION_CT=4 +export OPTION_CT +TEST_EQUIV_OPTION='opt' +export TEST_EQUIV_OPTION +TEST_EQUIV_ALPHA_MODE='BETA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_BETA=5 # 0x5 +export TEST_EQUIV_BETA +=== --gamma Yes! === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='GAMMA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_GAMMA='true' +export TEST_EQUIV_GAMMA +=== --gamma false === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='GAMMA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_GAMMA='false' +export TEST_EQUIV_GAMMA +=== --omega tres === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='OMEGA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_OMEGA='tres' +export TEST_EQUIV_OMEGA +_EOF_ + +( set -e +x + ./${testname} --alpha -s 2 + echo === --beta 5 -o opt === + ./${testname} --beta 5 -o opt + echo === --gamma Yes! === + ./${testname} --gamma Yes! + echo === --gamma false === + ./${testname} --gamma false + echo === --omega tres === + ./${testname} --omega tres ) > ${testname}.out + +cmp -s ${testname}-base.out ${testname}.out || \ + failure "` + diff -c ${testname}-base.out ${testname}.out`" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}-base2.help +clean_help > ${testname}-base2.help <<_EOF_ +test_${testname} - Test AutoOpts for ${testname} +USAGE: equiv [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + opt alpha alpha opt + Num beta beta opt + - an alternate for alpha + T/F gamma gamma opt + - an alternate for alpha + opt omega omega opt + - an alternate for alpha + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +The following option preset mechanisms are supported: + - reading file ..../testdir/.test_equivrc + +The valid "omega" option keywords are: + uno dos tres mucho + or an integer from 0 through 3 +_EOF_ + +echo 'homerc = "$$";' >> ${testname}.def + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" +${SED} '/^ - reading file/s, file .*/testdir/, file ..../testdir/,' \ + ${testname}.help > ${testname}-test2.help +cmp -s ${testname}-base2.help ${testname}-test2.help || \ + failure "`diff ${testname}-base2.help ${testname}-test2.help`" + +echo 'gamma Yes' > .test_equivrc + +cat > ${testname}-base.out2 <<_EOF_ +=== -o opt === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_OPTION='opt' +export TEST_EQUIV_OPTION +TEST_EQUIV_ALPHA_MODE='GAMMA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_GAMMA='true' +export TEST_EQUIV_GAMMA +=== --gamma Yes! === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='GAMMA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_GAMMA='true' +export TEST_EQUIV_GAMMA +=== --gamma false === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='GAMMA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_GAMMA='false' +export TEST_EQUIV_GAMMA +=== --omega tres === +OPTION_CT=2 +export OPTION_CT +TEST_EQUIV_ALPHA_MODE='OMEGA' +export TEST_EQUIV_ALPHA_MODE +TEST_EQUIV_OMEGA='tres' +export TEST_EQUIV_OMEGA +_EOF_ + +( set -e + echo === -o opt === + ./${testname} -o opt + echo === --gamma Yes! === + ./${testname} --gamma Yes! + echo === --gamma false === + ./${testname} --gamma false + echo === --omega tres === + ./${testname} --omega tres ) > ${testname}.out2 + +cmp -s ${testname}-base.out2 ${testname}.out2 || \ + failure "` + diff -c ${testname}-base.out2 ${testname}.out2`" + +./${testname} --omega tres --beta 12 2>/dev/null && \ + failure "${testname}-2 ERROR: conflicting options accepted" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of equiv.test diff --git a/autoopts/test/errors.test b/autoopts/test/errors.test new file mode 100755 index 0000000..89f508e --- /dev/null +++ b/autoopts/test/errors.test @@ -0,0 +1,232 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# errors.test --- test argument program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2011-08-07 17:37:02 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" + +testname="${testname}" \ +test_main="${test_main}" \ +argument="arg ..." \ +long_opts="yes" \ +${SHELLX} ${stdopts} option second:fumble ignored || \ + failure "Could not run stdopts.def" + +echo 'reorder-args;' >> ${testname}.def +${SED} -e '/"second"/a\ + must-set;' \ + -e '/"ignored"/a\ + omitted-usage = "we have dumped this"; ifdef = IGNORE_THIS;' \ + ${testname}.def > ${testname}.tmp +mv -f ${testname}.tmp ${testname}.def +echo "homerc = ${testname}RC;" >> ${testname}.def + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +mkdir ${testname}RC +compile "--help" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.res-help +clean_help > ${testname}.res-help <<'_EOF_' +test_errors - Test AutoOpts for errors +USAGE: errors [ -<flag> [<val>] | --<name>[{=| }<val>] ]... arg ... + Flg Arg Option-Name Description + -o no option The option option descrip + -s Str second The second option descrip + -i --- ignored we have dumped this + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +Operands and options may be intermixed. They will be reordered. + +The following option preset mechanisms are supported: + - reading file errorsRC/.test_errorsrc +_EOF_ + +clean_help > ${testname}.ignored-expected <<\_EOF_ +errors: The ``ignored'' option has been disabled -- we have dumped this +test_errors - Test AutoOpts for errors +USAGE: errors [ -<flag> [<val>] | --<name>[{=| }<val>] ]... arg ... + Flg Arg Option-Name Description + -o no option The option option descrip + -s Str second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +Operands and options may be intermixed. They will be reordered. +_EOF_ + +dir=`pwd -P` || dir=`pwd` +${SED} "s#${dir}/##" ${testname}.help > ${testname}.bas-help +cmp -s ${testname}.*-help || \ + failure "help output: `diff ${testname}.*-help`" + +./${testname} -s foo -o -s bar 2> /dev/null && \ + failure ${testname} should not accept multiple options + +./${testname} -o -s foo > /dev/null 2>&1 && \ + failure ${testname} must have arguments + +./${testname} -o -s foo mumble > /dev/null || \ + failure ${testname} stumbled somehow + +./${testname} -o > /dev/null 2>&1 && \ + failure ${testname} "'option'" must have argument + +./${testname} -o mumble > /dev/null 2>&1 && \ + failure ${testname} must have second argument + +echo "second bumble" > ${testname}RC/.test_errorsrc +./${testname} -o mumble > /dev/null || \ + failure ${testname} did not see errorsRC/.test_errorsrc + +./${testname} --ignored > ${testname}.ignored 2>&1 && \ + failure "${testname} accepted --ignored" + +clean_help < ${testname}.ignored > ${testname}.ignored-result +cmp -s ${testname}.ignored-* || \ + failure "${testname}.ignored error: `diff ${testname}.ignored-*`" + +mv ${testname}RC/.test_errorsrc ${testname}RC/test_errors.rc +./${testname} --load=${testname}RC/test_errors.rc -o mumble > /dev/null || \ + failure ${testname} did not see errorsRC/test_errors.rc + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "allow_errors;" >> ${testname}.def + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process allow-errors + +compile "--help" + +${SED} "s#${dir}/##" ${testname}.help > ${testname}.bas-help +cmp -s ${testname}.*-help || \ + failure "help output: `diff ${testname}.*-help`" + +# This time, having a duplicate should be ignored... +# +./${testname} -s foo -o -s bar mumble 2> /dev/null 1>&2 || \ + failure ${testname} should not object to multiple options + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +${SED} '/second option/a\ + max = "10";' ${testname}.def > XX +mv -f XX ${testname}.def +cat >> ${testname}.def << '_EOF_' +flag = { + name = "another"; + max = '5'; + descrip = "Another option descrip"; + value = 'X'; +}; + +_EOF_ + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process gnu-usage + +compile "--help" + +# # # # # # # # # # SORTED ARGS OUTPUT FILE # # # # # # # # # +test -n "${POSIXLY_CORRECT}" && { + POSIXLY_CORRECT='' + unset POSIXLY_CORRECT +} + +echo creating ${testname}-sh.samp +cat > ${testname}-sh.samp <<'_EOF_' +OPTION_CT=4 +export OPTION_CT +TEST_ERRORS_OPTION=1 # 0x1 +export TEST_ERRORS_OPTION +TEST_ERRORS_SECOND='foo' +export TEST_ERRORS_SECOND +TEST_ERRORS_ANOTHER=1 # 0x1 +export TEST_ERRORS_ANOTHER +set -- 'mum'\''ble' '-X' 'stumble' +OPTION_CT=0 +_EOF_ + +./${testname} "mum'ble" -os foo -X -- -X stumble > ${testname}-sh.out + +cmp -s ${testname}-sh.out ${testname}-sh.samp || \ + failure "`diff ${testname}-sh.samp ${testname}-sh.out`" + +cat >> ${testname}.def << '_EOF_' +flag = { + name = "still-another"; + ifdef = true ; ifndef = false; + descrip = "Another option descrip"; + value = 'Y'; +}; +_EOF_ + +case "${BASH_VERSION}" in +not-good-enough ) + echo "You are running Solaris without bash available." + echo "duplicate option flags cannot be tested." + ;; + +* ) + ${SED} '/ value /s/Y/X/;s/ ifndef =.*//' ${testname}.def > ${testname}-2.def + ${AG_L} ${testname}-2.def && \ + failure AutoGen processed conflicting flag values + ;; +esac + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of errors.test diff --git a/autoopts/test/getopt.test b/autoopts/test/getopt.test new file mode 100755 index 0000000..383c6fc --- /dev/null +++ b/autoopts/test/getopt.test @@ -0,0 +1,668 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# +# getopt.test --- test getopt_long argument processing +# +# Time-stamp: "2012-05-12 19:54:26 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs + +set -x +PS4='>${FUNCNAME:-go}> ' + +CC="${CC} ${CFLAGS} ${INC}" +CFLAGS='' +INC='' +export AUTOGEN_TEMPL_DIRS=${TMPDIR} + +compile_getopt() { + run_ag opts -b${testname}-bn ${testname}.def || \ + failure "AutoGen could not process ${testname}.def #${1}" + + # Remove the variable comments so we can test against the expected result + # + ${SED} '2,/and the template file/d + /\$''Id.*\$/d + /Last template edit:/d' getopt-test_${testname}.c \ + > ${testname}${1}-getopt.c + + # Finally, compile this thing: + # + ${CC} ${CFLAGS} -c ${testname}${1}-getopt.c || \ + failure "could not compile ${testname}1-getopt.c" + + ${SED} "${sed_omit_license}"' + /Packaged by /d + s@^Report .* bugs to.*"@\\n"@ + s@^please send bug.*"@\\n"@ + s@\\n\\n\\n\\$@\\n\\n\\@ + s@\(and the flag character\.\\n.\)n\\$@\1@' ${testname}${1}-getopt.c \ + > ${testname}${1}-res.c + cmp -s ${testname}${1}-base.c ${testname}${1}-res.c || { set +x ; \ + failure "`diff -c ${testname}${1}-base.c ${testname}${1}-res.c`" ; } +} + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# +# Fix up a test-specific include directory: +# +# The getopt template presumes that everything has been installed. +# However, we have to work with the local stuff. So, remove the +# "autoopts-config" probing and replace with local stuff: +# +go_init() +{ + mkdir -p ${TMPDIR}/autoopts + + CFLAGS="-I${TMPDIR}" + LDFLAGS="${LDFLAGS} ${LIB}" + export CFLAGS LDFLAGS TMPDIR + + aolib=`find ${top_builddir}/autoopts -type f -name libopts.a` + case " ${LDFLAGS} " in + *' -lgen '* ) aolib=${aolib}\ -lgen ;; + esac + + cd ${top_srcdir}/autoopts/tpl + cp *.* ${TMPDIR}/. + chmod u+w ${TMPDIR}/* + + cd ${top_builddir}/autoopts/tpl + cp *.* ${TMPDIR}/. + chmod u+w ${TMPDIR}/* + + cd ${builddir}/testdir + ${SED} -e "/^cflags=/s@=.*@='-I${TMPDIR}/autoopts -I${top_builddir}'@" \ + -e "/^ldflags=/s@=.*@='${aolib}'@" \ + ${TMPDIR}/usage.tlib > ${TMPDIR}/usage.tlib-XX + mv -f ${TMPDIR}/usage.tlib-XX ${TMPDIR}/usage.tlib + + # In order to compile correctly, we have to temporarily install the options.h + # header in our TMPDIR. We also must find that header first. Tweak CFLAGS: + # + DESTdestdir=${TMPDIR}/autoopts \ + top_builddir=${top_builddir} \ + CONFIG_SHELL="${SHELL}" \ + ${SHELLX} -x ${top_srcdir}/autoopts/install-hook.sh + AUTOGEN_TEMPL_DIRS=${TMPDIR} + export AUTOGEN_TEMPL_DIRS +} + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # +go_samples() { + +echo "creating ${testname}.def in `pwd`" + +cat >> ${testname}.def <<_EOF_ +AutoGen definitions getopt; + +prog-name = "test_${testname}"; +prog-title = "Test AutoOpts for ${testname}"; +test-main = 'yes'; +config-header = 'config.h'; + +settable; +version = '1.2.3'; +help-value = 'h'; +gnu-usage; +no-libopts; + +copyright = { + date = "2003-2012"; + owner = "Odyssey Computing Concepts, Inc."; + author= "Bruce Korb"; + eaddr = "bkorb@gnu.org"; + type = lgpl; +}; + +flag = { + name = "option"; + descrip = "The option option descrip"; + value = 'o'; + arg_type = string; arg_default = 'opt init'; +}; + +flag = { + name = "second"; + descrip = "The second option descrip"; + value = 's'; + arg_type = string; arg_default = '020'; +}; + +flag = { + name = no_val; + descrip = 'option with no flag'; + value = 'F'; /* REMOVE */ + flags-must = max_val; +}; + +flag = { + name = max_val; + descrip = 'option with max ct'; + value = 'X'; /* REMOVE */ + max = '5'; +}; + +flag = { + name = min2_val; + descrip = 'option with min ct'; + value = 'M'; /* REMOVE */ + max = '50'; + flags-cant = max_val; + min = '5'; +}; + +flag = { + name = min_val; + descrip = 'option with min ct'; + value = '2'; /* REMOVE */ + max = '50'; + min = '5'; +}; +_EOF_ + +# # # # # # # # # # BASE-1 OUTPUT FILE # # # # # # # # # + +echo creating ${testname}1-base.c + +cat > ${testname}1-base.c <<\_EndOfSample_ +#include "getopt-test_getopt.h" + +#include <sys/types.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "getopt-bn.h" + +#ifndef DIRCH +# if defined(_WIN32) && !defined(__CYGWIN__) +# define DIRCH '\\' +# else +# define DIRCH '/' +# endif +#endif +/* + * Option flag character list + */ +static char z_opts[] = "o:s:FXM2hv"; + +/* + * AutoOpts library replacement routines: + */ +void +optionUsage (tOptions* pOptions, int status) +{ + if (status != 0) + fprintf (stderr, _("Try `%s -h' for more information.\n"), + test_getoptOptions.pzProgName); + else + { + fputs (_("test_getopt - Test AutoOpts for getopt - Ver. 1.2.3\n\ +USAGE: test_getopt { -<flag> [<val>] }...\n\n\ + -o str The option option descrip\n\ + -s str The second option descrip\n\ + -F option with no flag\n\ + -X option with max ct\n\ + -M option with min ct\n\ + -2 option with min ct\n\ + -v Output version information and exit\n\ + -h Display extended usage information and exit\n\n\ +\n"), stdout); + } + + exit (status); +} + +void +optionPrintVersion( + tOptions* pOptions, + tOptDesc* pOptDesc ) +{ + char const * pz_by = + _("test_getopt 1.2.3\n\ +Written by Bruce Korb.\n\n\ +copyright (c) 2003-2012 Odyssey Computing Concepts, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + + fputs (pz_by, stdout); + exit (EXIT_SUCCESS); +} + +/* + * If an option appears more often than is allowed, ... + */ +static void +usage_too_many (tOptDesc* pOptDesc) +{ + char const * pz = + _("test_getopt error: the '%s' option appears more than %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMaxCt); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one option that must appear. + */ +static void +usage_too_few (tOptDesc* pOptDesc) +{ + char const * pz = + _("test_getopt error: the '%s' option must appear %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMinCt); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one pair of options that may not appear together + * on the command line. + */ +static void +usage_cannot (char const* pz_what, char const* pz_cant) +{ + char const * pz = + _("test_getopt error: the `%s' option conflicts with the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_cant); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one pair of options that are required to appear + * together on the command line. + */ +static void +usage_must (char const* pz_what, char const* pz_must) +{ + char const * pz = + _("test_getopt error: the `%s' option requires the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_must); + USAGE(EXIT_FAILURE); +} + +/* + * Process the options for the "test_getopt" program. + * This function was generated to use the getopt(3posix) function. + * There are 8 options for this program, + * including "help (usage)" and "version". + */ +int +process_test_getopt_opts (int argc, char** argv) +{ + { + char * pz_prog = strrchr (argv[0], DIRCH); + /* + * This violates the const-ness of the pzProgName field. + * The const-ness is to prevent accidents. This is not accidental. + */ + char ** pp = (char **)(void *)&(test_getoptOptions.pzProgName); + + if (pz_prog != NULL) + pz_prog++; + else + pz_prog = argv[0]; + *pp = pz_prog; + } + + for (;;) { + switch (getopt (argc, argv, z_opts)) { + case -1: goto leave_processing; + case 0: break; + + case VALUE_OPT_OPTION: + if (HAVE_OPT( OPTION )) + usage_too_many (&DESC(OPTION)); + SET_OPT_OPTION(optarg); + break; + + case VALUE_OPT_SECOND: + if (HAVE_OPT( SECOND )) + usage_too_many (&DESC(SECOND)); + SET_OPT_SECOND(optarg); + break; + + case VALUE_OPT_NO_VAL: + if (HAVE_OPT( NO_VAL )) + usage_too_many (&DESC(NO_VAL)); + SET_OPT_NO_VAL; + break; + + case VALUE_OPT_MAX_VAL: + if (DESC(MAX_VAL).optOccCt++ >= DESC(MAX_VAL).optMaxCt) + usage_too_many (&DESC(MAX_VAL)); + SET_OPT_MAX_VAL; + break; + + case VALUE_OPT_MIN2_VAL: + if (DESC(MIN2_VAL).optOccCt++ >= DESC(MIN2_VAL).optMaxCt) + usage_too_many (&DESC(MIN2_VAL)); + SET_OPT_MIN2_VAL; + break; + + case VALUE_OPT_MIN_VAL: + if (DESC(MIN_VAL).optOccCt++ >= DESC(MIN_VAL).optMaxCt) + usage_too_many (&DESC(MIN_VAL)); + SET_OPT_MIN_VAL; + break; + + case VALUE_OPT_HELP: + USAGE(EXIT_SUCCESS); + /* NOTREACHED */ + + case VALUE_OPT_VERSION: + optionPrintVersion (&test_getoptOptions, &DESC(VERSION)); + /* NOTREACHED */ + + default: + USAGE(EXIT_FAILURE); + } + } leave_processing:; + + if (HAVE_OPT( NO_VAL )) { + if (! HAVE_OPT( MAX_VAL )) + usage_must (DESC(NO_VAL).pz_Name, DESC(MAX_VAL).pz_Name); + } + + if (HAVE_OPT( MIN2_VAL )) { + if (HAVE_OPT( MAX_VAL )) + usage_cannot (DESC(MIN2_VAL).pz_Name, DESC(MAX_VAL).pz_Name); + if (DESC(MIN2_VAL).optOccCt < DESC(MIN2_VAL).optMinCt) + usage_too_few (&DESC(MIN2_VAL)); + } + else + usage_too_few (&DESC(MIN2_VAL)); + + if (DESC(MIN_VAL).optOccCt < DESC(MIN_VAL).optMinCt) + usage_too_few (&DESC(MIN_VAL)); + + return 0; +} +_EndOfSample_ + +# # # # # # # # # # BASE-2 OUTPUT FILE # # # # # # # # # + +echo creating ${testname}2-base.c + +cat > ${testname}2-base.c <<\_EndOfSample_ +#include "getopt-test_getopt.h" + +#include <sys/types.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include "getopt-bn.h" + +#ifndef DIRCH +# if defined(_WIN32) && !defined(__CYGWIN__) +# define DIRCH '\\' +# else +# define DIRCH '/' +# endif +#endif + +/* + * getopt_long option descriptor + */ +static struct option a_long_opts[] = { + { "option", 1, NULL, VALUE_OPT_OPTION }, + { "second", 1, NULL, VALUE_OPT_SECOND }, + { "no_val", 0, NULL, VALUE_OPT_NO_VAL }, + { "max_val", 0, NULL, VALUE_OPT_MAX_VAL }, + { "min2_val", 0, NULL, VALUE_OPT_MIN2_VAL }, + { "min_val", 0, NULL, VALUE_OPT_MIN_VAL }, + { "help", 0, NULL, VALUE_OPT_HELP }, + { "version", 0, NULL, VALUE_OPT_VERSION }, + { NULL, 0, NULL, 0 } +}; + +/* + * Option flag character list + */ +static char z_opts[] = "o:s:h"; + +/* + * AutoOpts library replacement routines: + */ +void +optionUsage (tOptions* pOptions, int status) +{ + if (status != 0) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + test_getoptOptions.pzProgName); + else + { + fputs (_("test_getopt - Test AutoOpts for getopt - Ver. 1.2.3\n\ +USAGE: test_getopt { -<flag> [<val>] | --<name>[{=| }<val>] }...\n\n\ + -o, --option=str The option option descrip\n\ + -s, --second=str The second option descrip\n\ + --no-val option with no flag\n\ + --max-val option with max ct\n\ + --min2-val option with min ct\n\ + --min-val option with min ct\n\ + --version Output version information and exit\n\ + -h, --help Display extended usage information and exit\n\n\ +Options are specified by doubled hyphens and their name or by a single\n\ +hyphen and the flag character.\n\ +\n"), stdout); + } + + exit (status); +} + +void +optionPrintVersion( + tOptions* pOptions, + tOptDesc* pOptDesc ) +{ + char const * pz_by = + _("test_getopt 1.2.3\n\ +Written by Bruce Korb.\n\n\ +copyright (c) 2003-2012 Odyssey Computing Concepts, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); + + fputs (pz_by, stdout); + exit (EXIT_SUCCESS); +} + +/* + * If an option appears more often than is allowed, ... + */ +static void +usage_too_many (tOptDesc* pOptDesc) +{ + char const * pz = + _("test_getopt error: the '%s' option appears more than %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMaxCt); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one option that must appear. + */ +static void +usage_too_few (tOptDesc* pOptDesc) +{ + char const * pz = + _("test_getopt error: the '%s' option must appear %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMinCt); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one pair of options that may not appear together + * on the command line. + */ +static void +usage_cannot (char const* pz_what, char const* pz_cant) +{ + char const * pz = + _("test_getopt error: the `%s' option conflicts with the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_cant); + USAGE(EXIT_FAILURE); +} + +/* + * There is at least one pair of options that are required to appear + * together on the command line. + */ +static void +usage_must (char const* pz_what, char const* pz_must) +{ + char const * pz = + _("test_getopt error: the `%s' option requires the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_must); + USAGE(EXIT_FAILURE); +} + +/* + * Process the options for the "test_getopt" program. + * This function was generated to use the getopt_long(3GNU) function. + * There are 8 options for this program, + * including "help (usage)" and "version". + */ +int +process_test_getopt_opts (int argc, char** argv) +{ + { + char * pz_prog = strrchr (argv[0], DIRCH); + /* + * This violates the const-ness of the pzProgName field. + * The const-ness is to prevent accidents. This is not accidental. + */ + char ** pp = (char **)(void *)&(test_getoptOptions.pzProgName); + + if (pz_prog != NULL) + pz_prog++; + else + pz_prog = argv[0]; + *pp = pz_prog; + } + + for (;;) { + switch (getopt_long (argc, argv, z_opts, a_long_opts, NULL)) { + case -1: goto leave_processing; + case 0: break; + + case VALUE_OPT_OPTION: + if (HAVE_OPT( OPTION )) + usage_too_many (&DESC(OPTION)); + SET_OPT_OPTION(optarg); + break; + + case VALUE_OPT_SECOND: + if (HAVE_OPT( SECOND )) + usage_too_many (&DESC(SECOND)); + SET_OPT_SECOND(optarg); + break; + + case VALUE_OPT_NO_VAL: + if (HAVE_OPT( NO_VAL )) + usage_too_many (&DESC(NO_VAL)); + SET_OPT_NO_VAL; + break; + + case VALUE_OPT_MAX_VAL: + if (DESC(MAX_VAL).optOccCt++ >= DESC(MAX_VAL).optMaxCt) + usage_too_many (&DESC(MAX_VAL)); + SET_OPT_MAX_VAL; + break; + + case VALUE_OPT_MIN2_VAL: + if (DESC(MIN2_VAL).optOccCt++ >= DESC(MIN2_VAL).optMaxCt) + usage_too_many (&DESC(MIN2_VAL)); + SET_OPT_MIN2_VAL; + break; + + case VALUE_OPT_MIN_VAL: + if (DESC(MIN_VAL).optOccCt++ >= DESC(MIN_VAL).optMaxCt) + usage_too_many (&DESC(MIN_VAL)); + SET_OPT_MIN_VAL; + break; + + case VALUE_OPT_HELP: + USAGE(EXIT_SUCCESS); + /* NOTREACHED */ + + case VALUE_OPT_VERSION: + optionPrintVersion (&test_getoptOptions, &DESC(VERSION)); + /* NOTREACHED */ + + default: + USAGE(EXIT_FAILURE); + } + } leave_processing:; + + if (HAVE_OPT( NO_VAL )) { + if (! HAVE_OPT( MAX_VAL )) + usage_must (DESC(NO_VAL).pz_Name, DESC(MAX_VAL).pz_Name); + } + + if (HAVE_OPT( MIN2_VAL )) { + if (HAVE_OPT( MAX_VAL )) + usage_cannot (DESC(MIN2_VAL).pz_Name, DESC(MAX_VAL).pz_Name); + if (DESC(MIN2_VAL).optOccCt < DESC(MIN2_VAL).optMinCt) + usage_too_few (&DESC(MIN2_VAL)); + } + else + usage_too_few (&DESC(MIN2_VAL)); + + if (DESC(MIN_VAL).optOccCt < DESC(MIN_VAL).optMinCt) + usage_too_few (&DESC(MIN_VAL)); + + return 0; +} +_EndOfSample_ +} + +# # # # # # # # # # RESULTS TESTING # # # # # # # # # + +go_init +go_samples +compile_getopt 1 + +${GREP} 'getopt_long' /usr/include/getopt.h >/dev/null && { + CFLAGS="${CFLAGS} -D_GNU_SOURCE=1" + ${SED} '/REMOVE/d;$a\ +long-opts;\ +version-value; +' ${testname}.def > ${testname}2.def + mv -f ${testname}2.def ${testname}.def + + compile_getopt 2 +} + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## sh-basic-offset: 2 +## End: + +# end of getopt.test diff --git a/autoopts/test/handler.test b/autoopts/test/handler.test new file mode 100755 index 0000000..ac7d4a4 --- /dev/null +++ b/autoopts/test/handler.test @@ -0,0 +1,254 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# handler.test --- test option handling +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2012-08-11 08:14:34 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +cat > ${testname}.def <<_EOF_ +AutoGen Definitions options; +prog-name = ${testname}; +prog-title = "Testing ${testname}"; + +flag = { + name = first; + descrip = "first description"; + extract_code; +}; + +flag = { + name = second; + descrip = "second description"; + arg-type = keyword; + keyword = alpha, beta, gamma, omega; +}; + +flag = { + name = third; + descrip = "third description"; + flag_code = " SomeCodeOrOther();"; +}; + +flag = { + name = fourth; + descrip = "fourth description"; + arg-type = keyword; + keyword = alpha, beta, gamma, omega; + arg-default = gamma; + arg-optional; +}; + +flag = { + name = fifth; + descrip = "fifth description"; + flag_proc = first; +}; + +flag = { + name = sixth; + descrip = "sixth description"; + arg-type = set-member; + keyword = alpha, beta, gamma, omega; + arg-default = gamma, beta; +}; +_EOF_ + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +${SED} '/START =/a\ +SampleCode();\ +XXX-REMOVE-XXX' ${testname}.c > ${testname}.tmp +chmod 644 ${testname}.c +${SED} -e '/^XXX-REMOVE-XXX$/d;s/XXX-REMOVE-XXX//' \ + ${testname}.tmp > ${testname}.c + +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +# We are testing to ensure the procedures are created correctly. +# The template line numbers and time stamps and all that cruft +# vary too much, so sed them away. +# +${SED} -e '1,/Create the static procedure(s) declared above/d' \ + -e '/extracted from.*near line/d' \ + -e '/^#line/d' \ + -e 's@handler_opt_strs+[0-9]*@handler_opt_strs+NNN@g' \ + -e 's@+NNN, *@+NNN, @g' \ + -e '/^#ifndef *PKGDATADIR/,$d' \ + ${testname}.c > ${testname}.test + +# # # # # # # # # # SAMPLE OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.sample +cat > ${testname}.sample <<\_EOF_ + */ +/** + * The callout function that invokes the optionUsage function. + * + * @param pOptions the AutoOpts option description structure + * @param pOptDesc the descriptor for the "help" (usage) option. + * @noreturn + */ +static void +doUsageOpt(tOptions * pOptions, tOptDesc * pOptDesc) +{ + optionUsage(&handlerOptions, HANDLER_EXIT_SUCCESS); + /* NOTREACHED */ + (void)pOptDesc; + (void)pOptions; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Code to handle the first option. + * + * @param pOptions the handler options data structure + * @param pOptDesc the option descriptor for this option. + */ +static void +doOptFirst(tOptions* pOptions, tOptDesc* pOptDesc) +{ +/* START =-= First Opt Code =-= DO NOT CHANGE THIS COMMENT */ +SampleCode(); +/* END =-= First Opt Code =-= DO NOT CHANGE THIS COMMENT */ + (void)pOptDesc; + (void)pOptions; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Code to handle the second option. + * + * @param pOptions the handler options data structure + * @param pOptDesc the option descriptor for this option. + */ +static void +doOptSecond(tOptions* pOptions, tOptDesc* pOptDesc) +{ + + static char const zDef[2] = { 0x7F, 0 }; + static char const * const azNames[5] = { zDef, + handler_opt_strs+NNN, handler_opt_strs+NNN, handler_opt_strs+NNN, + handler_opt_strs+NNN }; + + if (pOptions <= OPTPROC_EMIT_LIMIT) { + (void) optionEnumerationVal(pOptions, pOptDesc, azNames, 5); + return; /* protect AutoOpts client code from internal callbacks */ + } + + pOptDesc->optArg.argEnum = + optionEnumerationVal(pOptions, pOptDesc, azNames, 5); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Code to handle the third option. + * + * @param pOptions the handler options data structure + * @param pOptDesc the option descriptor for this option. + */ +static void +doOptThird(tOptions* pOptions, tOptDesc* pOptDesc) +{ + /* extracted from handler.def, line 21 */ + SomeCodeOrOther(); + (void)pOptDesc; + (void)pOptions; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Code to handle the fourth option. + * + * @param pOptions the handler options data structure + * @param pOptDesc the option descriptor for this option. + */ +static void +doOptFourth(tOptions* pOptions, tOptDesc* pOptDesc) +{ + + static char const * const azNames[4] = { + handler_opt_strs+NNN, handler_opt_strs+NNN, handler_opt_strs+NNN, + handler_opt_strs+NNN }; + + if (pOptions <= OPTPROC_EMIT_LIMIT) { + (void) optionEnumerationVal(pOptions, pOptDesc, azNames, 4); + return; /* protect AutoOpts client code from internal callbacks */ + } + + if (pOptDesc->optArg.argString == NULL) + pOptDesc->optArg.argEnum = FOURTH_GAMMA; + else + pOptDesc->optArg.argEnum = + optionEnumerationVal(pOptions, pOptDesc, azNames, 4); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Code to handle the sixth option. + * + * @param pOptions the handler options data structure + * @param pOptDesc the option descriptor for this option. + */ +static void +doOptSixth(tOptions* pOptions, tOptDesc* pOptDesc) +{ + + static char const * const azNames[4] = { + "alpha", "beta", "gamma", "omega" + }; + /* + * This function handles special invalid values for "pOptions" + */ + optionSetMembers(pOptions, pOptDesc, azNames, 4); +} + +/** + * The directory containing the data associated with handler. + */ +_EOF_ + +cmp -s ${testname}.test ${testname}.sample || { + failure "`diff -c ${testname}.test ${testname}.sample`" ; } + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of handler.test diff --git a/autoopts/test/immediate.test b/autoopts/test/immediate.test new file mode 100755 index 0000000..c7edbce --- /dev/null +++ b/autoopts/test/immediate.test @@ -0,0 +1,121 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# immediate.test --- test immediate option handling +# +# Time-stamp: "2012-01-29 13:33:03 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" + +cat > ${testname}.def << _EOF_ +AutoGen definitions options; + +prog-name = "test_${testname}"; +prog-title = "Test AutoOpts for ${testname}"; +include = "#include <stdio.h>\nint invocation_ct = 0;"; +config-header = 'config.h'; +version = '1.0'; +copyright = { + date = "1992-2012"; + owner = "Bruce Korb"; + eaddr = "autogen-users@lists.sourceforge.net"; + type = gpl; +}; + +flag = { + name = "second"; + descrip = "The second option descrip"; + immediate = also; + immed-disable = also; + disable = not; + arg-type = string; + flag-code = " invocation_ct++;"; +}; + +main = { + main-type = main; + main-text = ' printf( "invocation_ct = %d\\n", invocation_ct );'; +}; + +_EOF_ + +INC=`echo ${INC} | ${SED} 's/-lguile//;s/-lqthreads//'` +CFLAGS="-g`echo ' '${CFLAGS}' ' | \ + ${SED} 's, -O2 , ,;s/ -g[^ ]* / /'`" + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +sedcmd="/All arguments are named options./q" +compile "help" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.hlp +clean_help > ${testname}.hlp << '_EOF_' +test_immediate - Test AutoOpts for immediate - Ver. 1.0 +USAGE: immediate [ <option-name>[{=| }<val>] ]... + Arg Option-Name Description + Str second The second option descrip + - disabled as --not-second + opt version Output version information and exit + no help Display extended usage information and exit + no more-help Extended usage information passed thru pager + +All arguments are named options. +_EOF_ + +cmp -s ${testname}.help ${testname}.hlp || { set +x ; \ + failure "`diff -c ${testname}.hlp ${testname}.help`" ; } + +f=`./${testname} second=hand` +test "$f" = "invocation_ct = 2" || \ + failure "enabled option not processed twice" + +f=`./${testname} not-second` +test "$f" = "invocation_ct = 2" || \ + failure "DIS-abled option not processed twice" + +f=`./${testname} help version=c | ${FGREP} 'USAGE:'` +test -z "${f}" && failure "no USAGE: in help text" + +f=`./${testname} version=c help | ${FGREP} -i 'copyright (c)'` +test -z "${f}" && failure "no 'copyright (c)' in version text" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of immediate.test diff --git a/autoopts/test/keyword.test b/autoopts/test/keyword.test new file mode 100755 index 0000000..03b8720 --- /dev/null +++ b/autoopts/test/keyword.test @@ -0,0 +1,449 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# keyword.test --- keyword option processing +# +# Time-stamp: "2012-02-28 19:42:00 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +testname="${testname}" test_main="" \ +argument="${argument}" long_opts="yes" \ +${SHELLX} ${stdopts} option:'opt init' || failure "Could not run stdopts.def" +cat >> ${testname}.def <<- _EndOfDef_ + help_value = X; + homerc = '.'; + rcfile = ${testname}.cfg; + + flag = { + name = trace; + arg-type = keyword; + arg-default = nothing; + arg-name = level; + descrip = "tracing level of detail"; + keyword = nothing, templates, block-macros, expressions, + explanations; + }; + + flag = { + name = sets; + arg-type = set-members; + arg-default = second, fourth; + arg-name = member-list; + descrip = "set membership testing"; + keyword = first, second, third, fourth, fifth, + sixth, seventh, eighth, ninth, tenth, + eleventh, twelfth, thirteenth, fourteenth, fifteenth, + sixteenth, seventeenth, eighteenth; + }; + main = { main-type = shell-process; }; + _EndOfDef_ + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-X" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.res-help +clean_help > ${testname}.res-help <<\_EOF_ +test_keyword - Test AutoOpts for keyword +USAGE: keyword [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -o Str option The option option descrip + KWd trace tracing level of detail + Mbr sets set membership testing + - is a set membership option + -X no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +The following option preset mechanisms are supported: + - reading file ./keyword.cfg + +The valid "trace" option keywords are: + nothing templates block-macros expressions explanations + or an integer from 0 through 4 +The valid "sets" option keywords are: + first second third fourth fifth sixth + seventh eighth ninth tenth eleventh twelfth + thirteenth fourteenth fifteenth sixteenth seventeenth eighteenth + or an integer mask with any of the lower 18 bits set +or you may use a numeric representation. Preceding these with a '!' will +clear the bits, specifying 'none' will clear all bits, and 'all' will set them +all. Multiple entries may be passed as an option argument list. +_EOF_ + +dir=`pwd -P` || dir=`pwd` +${SED} "s#${dir}/##" ${testname}.help > ${testname}.bas-help +cmp -s ${testname}.*-help || \ + failure "help output: `diff ${testname}.*-help`" + +./${testname} --trace=exp > /dev/null 2>&1 && \ + failure "${testname} accepted ambiguous keyword" + +./${testname} --trace=999 > /dev/null 2>&1 && \ + failure "${testname} accepted too much tracing" + +./${testname} --trace=~0 > /dev/null 2>&1 || \ + failure "${testname} would not accept max tracing" + +./${testname} --trace=expr --set=thirteen,ninth,third > ${testname}.t1-s || \ + failure "${testname} did not handle its options" + +./${testname} --trace=expr --set=thirteen,ninth,third --save=${testname}.cfg || \ + failure "${testname} could not save its options" + +${EGREP} -v '^#' ${testname}.cfg > ${testname}res.cfg || \ + failure "${testname} could not create ${testname}.cfg" + +cat > ${testname}base.cfg <<- \_EndIni_ + trace expressions + sets none + second + third + fourth + ninth + thirteenth + _EndIni_ + +cmp -s ${testname}base.cfg ${testname}res.cfg || \ + failure "`diff ${testname}base.cfg ${testname}res.cfg`" + +cat > ${testname}.t1-b <<- \_EndTst_ + OPTION_CT=2 + export OPTION_CT + TEST_KEYWORD_TRACE='expressions' + export TEST_KEYWORD_TRACE + TEST_KEYWORD_SETS=4366 # 0x110E + export TEST_KEYWORD_SETS + typeset -x -i SETS_FIRST=1 # 0x1 + typeset -x -i SETS_SECOND=2 # 0x2 + typeset -x -i SETS_THIRD=4 # 0x4 + typeset -x -i SETS_FOURTH=8 # 0x8 + typeset -x -i SETS_FIFTH=16 # 0x10 + typeset -x -i SETS_SIXTH=32 # 0x20 + typeset -x -i SETS_SEVENTH=64 # 0x40 + typeset -x -i SETS_EIGHTH=128 # 0x80 + typeset -x -i SETS_NINTH=256 # 0x100 + typeset -x -i SETS_TENTH=512 # 0x200 + typeset -x -i SETS_ELEVENTH=1024 # 0x400 + typeset -x -i SETS_TWELFTH=2048 # 0x800 + typeset -x -i SETS_THIRTEENTH=4096 # 0x1000 + typeset -x -i SETS_FOURTEENTH=8192 # 0x2000 + typeset -x -i SETS_FIFTEENTH=16384 # 0x4000 + typeset -x -i SETS_SIXTEENTH=32768 # 0x8000 + typeset -x -i SETS_SEVENTEENTH=65536 # 0x10000 + typeset -x -i SETS_EIGHTEENTH=131072 # 0x20000 + _EndTst_ + +cmp -s ${testname}.t1-* || \ + failure "`diff ${testname}.t1-*`" + +${AG_L} -T agman-cmd.tpl ${testname}.def +test -f test_${testname}.1 || \ + failure "'test_${testname}.1' was not produced" +mv test_${testname}.1 ${testname}.1 + +cat > ${testname}-base.1 <<\_EOMan_ +test_keyword \- Test AutoOpts for keyword +.SH SYNOPSIS +.B test_keyword +.\" Mixture of short (flag) options and long options +.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \-\-\fIopt\-name\fP " [[=| ]\fIvalue\fP]]..." +.PP +All arguments must be options. +.SH "DESCRIPTION" +There is no description for this command. +.SH "OPTIONS" +.TP +.BR \-o " \fIstring\fP, " \-\-option "=" \fIstring\fP +The option option descrip. +The default \fIstring\fP for this option is: +.ti +4 + opt init +.sp +This option has not been fully documented. +.TP +.BR \-\-trace "=\fIlevel\fP" +tracing level of detail. +This option takes a keyword as its argument. The argument sets an enumeration value that can +be tested by comparing them against the option value macro. +The available keywords are: +.in +4 +.nf +.na +nothing templates block-macros +expressions explanations +.fi +or their numeric equivalent. +.in -4 +.sp +The default \fIlevel\fP for this option is: +.ti +4 + nothing +.sp +This option has not been fully documented. +.TP +.BR \-\-sets "=\fImember\-list\fP" +set membership testing. +This option takes a keyword as its argument list. Each entry turns on or off +membership bits. The bits are set by name or numeric value and cleared +by preceding the name or number with an exclamation character ('!'). +They can all be cleared with the magic name \fInone\fR and they can all be set +with +.IR all . +A single option will process a list of these values. +The available keywords are: +.in +4 +.nf +.na +first second third fourth +fifth sixth seventh eighth +ninth tenth eleventh twelfth +thirteenth fourteenth fifteenth sixteenth +seventeenth eighteenth +.fi +or their numeric equivalent. +.in -4 +.sp +The default \fImember\-list\fP for this option is: +.ti +4 + second + fourth +.sp +This option has not been fully documented. +.TP +.BR \-X , " \-\-help" +Display usage information and exit. +.TP +.BR \-! , " \-\-more-help" +Pass the extended usage information through a pager. +.TP +.BR \-> " [\fIrcfile\fP]," " \-\-save-opts" "[=\fIrcfile\fP]" +Save the option state to \fIrcfile\fP. The default is the \fIlast\fP +configuration file listed in the \fBOPTION PRESETS\fP section, below. +.TP +.BR \-< " \fIrcfile\fP," " \-\-load-opts" "=\fIrcfile\fP," " \-\-no-load-opts" +Load options from \fIrcfile\fP. +The \fIno-load-opts\fP form will disable the loading +of earlier RC/INI files. \fI\-\-no-load-opts\fP is handled early, +out of order. +.SH "OPTION PRESETS" +Any option that is not marked as \fInot presettable\fP may be preset +by loading values from configuration ("RC" or ".INI") file(s). +The file "\fI./keyword.cfg\fP" will be used, if present. +.SH "FILES" +See \fBOPTION PRESETS\fP for configuration files. +.SH "EXIT STATUS" +One of the following exit values will be returned: +.TP +.BR 0 " (EXIT_SUCCESS)" +Successful program execution. +.TP +.BR 1 " (EXIT_FAILURE)" +The operation failed or the command syntax was not valid. +.TP +.BR 66 " (EX_NOINPUT)" +A specified configuration file could not be loaded. +.TP +.BR 70 " (EX_SOFTWARE)" +libopts had an internal operational error. Please report +it to autogen-users@lists.sourceforge.net. Thank you. +.SH "NOTES" +This manual page was \fIAutoGen\fP-erated from the \fBtest_keyword\fP +option definitions. +_EOMan_ + +${SED} '1,/^\.SH NAME/d' ${testname}.1 > ${testname}-res.1 +cmp -s ${testname}-base.1 ${testname}-res.1 || \ + failure "`diff ${testname}-base.1 ${testname}-res.1`" + +# # # # # # # # # # CHECK OUT MDOC # # # # # # # # # # # + +${AG_L} -T agmdoc-cmd.tpl ${testname}.def +test -f test_${testname}.1 || \ + failure "'test_${testname}.1' was not produced" +mv test_${testname}.1 ${testname}.mdoc + +cat > ${testname}-base.mdoc <<\_EOMan_ +.Dt TEST_KEYWORD 1 User Commands +.Sh NAME +.Nm test_keyword +.Nd Test AutoOpts for keyword +.Sh SYNOPSIS +.Nm +.\" Mixture of short (flag) options and long options +.Op Fl flags +.Op Fl flag Ar value +.Op Fl \-option-name Ar value +.Pp +All arguments must be options. +.Pp +.Sh "DESCRIPTION" +There is no description for this command. +.Sh "OPTIONS" +.Bl -tag +.It \-o " \fIstring\fP, " \-\-option "=" \fIstring\fP +The option option descrip. +The default \fIstring\fP for this option is: +.ti +4 + opt init +.sp +This option has not been fully documented. +.It \-\-trace "=\fIlevel\fP" +tracing level of detail. +This option takes a keyword as its argument. The argument sets an enumeration value that can +be tested by comparing them against the option value macro. +The available keywords are: +.in +4 +.nf +.na +nothing templates block-macros +expressions explanations +.fi +or their numeric equivalent. +.in -4 +.sp +The default \fIlevel\fP for this option is: +.ti +4 + nothing +.sp +This option has not been fully documented. +.It \-\-sets "=\fImember\-list\fP" +set membership testing. +This option takes a keyword as its argument list. Each entry turns on or off +membership bits. The bits are set by name or numeric value and cleared +by preceding the name or number with an exclamation character ('!'). +They can all be cleared with the magic name \fInone\fR and they can all be set +with +.IR all . +A single option will process a list of these values. +The available keywords are: +.in +4 +.nf +.na +first second third fourth +fifth sixth seventh eighth +ninth tenth eleventh twelfth +thirteenth fourteenth fifteenth sixteenth +seventeenth eighteenth +.fi +or their numeric equivalent. +.in -4 +.sp +The default \fImember\-list\fP for this option is: +.ti +4 + second + fourth +.sp +This option has not been fully documented. +.It \-X , " \-\-help" +Display usage information and exit. +.It \-! , " \-\-more-help" +Pass the extended usage information through a pager. +.It \-> " [\fIrcfile\fP]," " \-\-save-opts" "[=\fIrcfile\fP]" +Save the option state to \fIrcfile\fP. The default is the \fIlast\fP +configuration file listed in the \fBOPTION PRESETS\fP section, below. +.It \-< " \fIrcfile\fP," " \-\-load-opts" "=\fIrcfile\fP," " \-\-no-load-opts" +Load options from \fIrcfile\fP. +The \fIno-load-opts\fP form will disable the loading +of earlier RC/INI files. \fI\-\-no-load-opts\fP is handled early, +out of order. +.El +.Sh "OPTION PRESETS" +Any option that is not marked as \fInot presettable\fP may be preset +by loading values from configuration ("RC" or ".INI") file(s). +The file "\fI./keyword.cfg\fP" will be used, if present. +.Sh "FILES" +See \fBOPTION PRESETS\fP for configuration files. +.Sh "EXIT STATUS" +One of the following exit values will be returned: +.Bl -tag +.It 0 " (EXIT_SUCCESS)" +Successful program execution. +.It 1 " (EXIT_FAILURE)" +The operation failed or the command syntax was not valid. +.It 66 " (EX_NOINPUT)" +A specified configuration file could not be loaded. +.It 70 " (EX_SOFTWARE)" +libopts had an internal operational error. Please report +it to autogen-users@lists.sourceforge.net. Thank you. +.El +.Sh "NOTES" +This manual page was \fIAutoGen\fP-erated from the \fBtest_keyword\fP +option definitions. +_EOMan_ + +${SED} '/DO NOT EDIT/,/and the template file/d;/^\.Os /d;/^\.Dd /d' \ + ${testname}.mdoc > ${testname}-res.mdoc +cmp -s ${testname}-base.mdoc ${testname}-res.mdoc || \ + failure "`diff ${testname}-base.mdoc ${testname}-res.mdoc`" + +# # # # # # # # # # CHECK OUT VAL2STR # # # # # # # # # # # + +exec 3> ${testname}_2.def +${SED} '/^prog-name/s/";/_2";/;/^main *=/,$d' ${testname}.def >&3 +cat >&3 <<- \_EOF_ + include = '#include <stdio.h>'; + main = { + main-type = main; + main-text = + ' printf( "%s\n", OPT_TRACE_VAL2STR( OPT_VALUE_TRACE ));'; + }; + _EOF_ +exec 3>&- + +echo ${AG_L} ${testname}_2.def +${AG_L} ${testname}_2.def || \ + failure AutoGen could not process + +Csrc=${testname}_2 +Dnam=${Csrc} +compile "-X" || failure "cannot compile ${testname}_2" + +val=`./${testname}_2 --trace=expr 2>&1` || \ + failure "cannot run ${testname}_2" + +case "${val}" in +expressions) : ;; +* ) failure "${testname}_2 returned '${val}', not 'expressions': + ${testname}_2 --trace=expr" ;; +esac + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of keyword.test diff --git a/autoopts/test/library.test b/autoopts/test/library.test new file mode 100755 index 0000000..f463e3e --- /dev/null +++ b/autoopts/test/library.test @@ -0,0 +1,170 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# library.test --- test library options +# +# Time-stamp: "2013-03-10 07:14:58 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +DEND=\<\<'- _DESC_END_' + +cat > ${testname}-libopts.def <<- _EODefs_ + flag = { name = zzyzx-opts; + documentation; + lib-name = zzyzx; + descrip = ${DEND} + This option introduces the options for the + zzyzx library + _DESC_END_; + }; + flag = { + name = library; + value = c; + ifdef = LIBOPTS; + descrip = "library test"; + doc = mumble; + }; + _EODefs_ + +cat > ${testname}-lib.def <<- _EODefs_ + + AutoGen definitions options; + + prog-name = ${testname}; + prog-title = lib-${testname}; + config-header = 'config.h'; + + library; + #include ${testname}-libopts.def + _EODefs_ + +cat > ${testname}-prog.def <<- _EOF_ + + AutoGen definitions options; + + prog-name = test-lib-prog; + prog-title = 'Test ${testname} Program'; + config-header = 'config.h'; + + flag = { + name = program; + value = p; + descrip = "${testname} program test"; + doc = stumble; + }; + + #include ${testname}-libopts.def + _EOF_ + +echo ${AG_L} ${testname}-lib.def +${AG_L} ${testname}-lib.def || \ + failure AutoGen could not process ${testname}-lib.def + +echo ${AG_L} ${testname}-prog.def +${AG_L} ${testname}-prog.def || \ + failure AutoGen could not process ${testname}-prog.def + +for f in lib prog +do + ${SED} -e '1,/include <autoopts\/options.h>/d' \ + -e '/endif .* AUTOOPTS_.*_H_GUARD/,$d' \ + -e 's/near line [0-9]*/near line XXX/' \ + ${testname}-${f}.h > ${testname}-${f}.h-res || \ + failure could not sed ${testname}-${f}.h +done + +# # # # # # # # # # TEST PROGRAM # # # # # # # # # # + +cat > ${testname}-lib.c <<- _EOCode_ + #include <stdlib.h> + #define LIBOPTS + #include "${testname}-lib.h" + void check_library_opt( void ); + void check_library_opt( void ) { + if (HAVE_OPT(LIBRARY)) return; + exit( EXIT_FAILURE ); } + _EOCode_ +test $? -eq 0 || failure cannot create ${testname}-lib.c + +${CC} ${CFLAGS} ${INC} -o ${testname}-lib.o -c ${testname}-lib.c +test $? -eq 0 || failure cannot compile ${testname}-lib.c + +cat > ${testname}-main.c <<- _EOCode_ + #include <stdio.h> + #include <stdlib.h> + #define LIBOPTS + #include "${testname}-prog.c" + extern void check_library_opt( void ); + int main( int argc, char** argv ) { + (void)optionProcess( &test_lib_progOptions, argc, argv ); + check_library_opt(); + return EXIT_SUCCESS; } + _EOCode_ + +${CC} ${CFLAGS} ${INC} -o ${testname} ${testname}-main.c ${testname}-lib.o ${LIB} +test $? -eq 0 || failure cannot compile ${testname}-main.c + +./${testname} -c || failure library option not detected + +# # # # # # # # # # HELP OUTPUT # # # # # # # # # # + +./${testname} -? | clean_help > ${testname}.help-sample + +clean_help > ${testname}.help-base <<- _EOHelp_ +test-lib-prog - Test library Program +USAGE: library [ -<flag> ]... + Flg Arg Option-Name Description + -p no program library program test + +This option introduces the options for the zzyzx library: + + Flg Arg Option-Name Description + -c no library library test + +version, usage and configuration options: + + Flg Arg Option-Name Description + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + + _EOHelp_ + +cmp ${testname}.help-* || \ + failure "help output mismatch: +`diff ${testname}.help-*`" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of library.test diff --git a/autoopts/test/main.test b/autoopts/test/main.test new file mode 100755 index 0000000..0c4b124 --- /dev/null +++ b/autoopts/test/main.test @@ -0,0 +1,127 @@ +#! /bin/sh +# -*- Mode: Shell-Script -*- +# ---------------------------------------------------------------------- +# main.test --- test main program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2011-08-07 17:33:19 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +testname="${testname}" \ +argument="${argument}" long_opts="${long_opts}" \ +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" + +exec 4> ${testname}.def2 +${SED} '/test_main=/d' ${testname}.def >&4 +unset test_main +cat >&4 <<- _EOF_ + explain = 'This is some explanatory text.'; + argument = '[ <argument> ... ]'; + main = { + handler-proc = fumble; + fumble-code = 'printf( "%s\n", pz_entry );'; + main-type = for-each; + }; + _EOF_ +exec 4>&- +mv -f ${testname}.def2 ${testname}.def + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehlp=${testname}.hlp +echo creating ${basehlp} +clean_help > ${basehlp} <<'_EOF_' +test_main - Test AutoOpts for main +USAGE: main [ -<flag> [<val>] ]... [ <argument> ... ] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s Num second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + + +This is some explanatory text. +If no arguments are provided, input arguments are read from stdin, +one per line; blank and '#'-prefixed lines are comments. +'stdin' may not be a terminal (tty). +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${basehlp} ${testname}.help`" + +# # # # # # # # # # TEST OPERATION # # # # # # # # # # + +./${testname} > ${testname}.out < ${testname}.hlp + +clean_help > ${testname}.base <<\_EOF_ +test_main - Test AutoOpts for main +USAGE: main [ -<flag> [<val>] ]... [ <argument> ... ] +Flg Arg Option-Name Description +-o Str option The option option descrip +-s Num second The second option descrip +-? no help Display extended usage information and exit +-! no more-help Extended usage information passed thru pager +This is some explanatory text. +If no arguments are provided, input arguments are read from stdin, +one per line; blank and '#'-prefixed lines are comments. +'stdin' may not be a terminal (tty). +_EOF_ + +cmp -s ${testname}.base ${testname}.out || \ + failure "`diff ${testname}.base ${testname}.out`" + +./${testname} -s 5 the quick 'brown fox' > ${testname}.out2 + +cat > ${testname}.base2 <<\_EOF_ +the +quick +brown fox +_EOF_ + +cmp -s ${testname}.base2 ${testname}.out2 || \ + failure "`diff ${testname}.base2 ${testname}.out2`" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of main.test diff --git a/autoopts/test/nested.test b/autoopts/test/nested.test new file mode 100755 index 0000000..34c9a55 --- /dev/null +++ b/autoopts/test/nested.test @@ -0,0 +1,266 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# nested.test --- test nested option values +# +# Time-stamp: "2012-03-31 13:10:48 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +exec 5> ${testname}.def +cat >&5 <<- _EOF_ + + AutoGen definitions options; + + config-header = 'config.h'; + prog-name = "test_${testname}"; + prog-title = "Test AutoOpts for ${testname}"; + homerc = ${testname}.d/${testname}.cfg; + + flag = { + name = struct; + value = s; + max = NOLIMIT; + descrip = 'structured argument val'; + arg-type = nested; + }; + main = { + main-type = main; + _EOF_ + +test -d ${testname}.d || mkdir -p ${testname}.d + +echo ' main-text = <''<- _EOCode_' >&5 +cat >&5 <<- _EOF_ + { + int ix = 0; + const tOptionValue* pOV = + optionFindValue(&DESC(STRUCT), NULL, NULL); + do { + printf("\nstruct opt #%d:\n", ++ix); + res |= print_entry( pOV ); + pOV = optionFindNextValue(&DESC(STRUCT), pOV, NULL, NULL); + } while (pOV != NULL); + } + _EOF_ + +echo "_EOCode_; };" >&5 + +echo 'include = <''<- _EOSubr_' >&5 +cat >&5 <<- _EOF_ + #include <stdio.h> + + int print_nested( const tOptionValue* pGV ); + int print_entry( const tOptionValue* pGV ); + int print_entry( const tOptionValue* pGV ) { + if (pGV == NULL) { + fprintf( stderr, "ENTRY NOT FOUND\n" ); + return 1; + } + printf( "%-8s -- ", pGV->pzName ); + switch (pGV->valType) { + case OPARG_TYPE_NONE: + fputs( "no value\n", stdout ); break; + + case OPARG_TYPE_STRING: + printf( "string: %s\n", pGV->v.strVal ); break; + + case OPARG_TYPE_ENUMERATION: + printf( "enum: %d\n", pGV->v.enumVal ); break; + + case OPARG_TYPE_BOOLEAN: + printf( "bool: %s\n", + pGV->v.boolVal ? "TRUE" : "false" ); break; + + case OPARG_TYPE_MEMBERSHIP: + printf("members: 0x%08lX\n", (unsigned long)pGV->v.setVal); break; + + case OPARG_TYPE_NUMERIC: + printf( "integer: %ld\n", pGV->v.longVal ); break; + + case OPARG_TYPE_HIERARCHY: + printf( "nested: 0x%08lX\n", (unsigned long)pGV->v.nestVal ); + return print_nested( pGV ); + break; + + default: + printf( "bad type: %d\n", pGV->valType ); + return 1; + } + return 0; + } + + int print_nested( const tOptionValue* pGV ) { + int res = 0; + const tOptionValue* pOV = optionGetValue( pGV, NULL ); + while (pOV != NULL) { + res |= print_entry( pOV ); + pOV = optionNextValue( pGV, pOV ); + } + return res; + } + _EOF_ +echo "_EOSubr_;" >&5 + +exec 5>&- + +# # # # # # # # # # CREATE PROGRAM # # # # # # # # # + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehelp=${testname}-base.help +echo creating ${basehelp} +clean_help > ${basehelp} <<_EOF_ +test_${testname} - Test AutoOpts for ${testname} +USAGE: ${testname} [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -s Cpx struct structured argument val + - may appear multiple times + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + + +The following option preset mechanisms are supported: + - reading file ${testname}.cfg +_EOF_ + +${SED} "/ - reading file/s/ file .*/ file ${testname}.cfg/" \ + ${testname}.help > X$$ +mv -f X$$ ${testname}.help + +cmp -s ${basehelp} ${testname}.help || \ + failure "`diff ${basehelp} ${testname}.help`" + +# # # # # # # # # # SINGLE ARG TEST # # # # # # # # # + +cat > ${testname}-res1.base <<- _EOF_ + + struct opt #1: + struct -- nested: 0xXXXXXXXX + able -- no value + bar -- integer: 1234 + foo -- no value + stumble -- no value + _EOF_ + +./${testname} -s 'stumble, foo, <bar type=integer>1234</bar> able' | \ +${SED} '/ nested:/s/ 0x.*/ 0xXXXXXXXX/' > ${testname}-res1.out || \ + failure "FAILED: \ +./${testname} -s 'stumble, foo, <bar type=integer>1234</bar> baz'" + +cmp -s ${testname}-res1.* || \ + failure "`diff ${testname}-res1.*`" + +# # # # # # # # # # DOUBLE ARG TEST # # # # # # # # # + +arg1="stumble, <foo>foo${ht}lish</foo>, <bar type=integer>1234</bar>, able" +arg2='foo, <bar type=integer>4321</bar> <gr type=nested>one, two=2, three</gr>' +(./${testname} -s "${arg1}" -s "${arg2}" \ + | ${SED} '/ nested:/s/ 0x.*/ 0xXXXXXXXX/' ) > ${testname}-res2.out || \ + failure "FAILED: ./${testname} ${arg1} ${arg2}" + +cat > ${testname}-res2.base <<- _EOF_ + + struct opt #1: + struct -- nested: 0xXXXXXXXX + able -- no value + bar -- integer: 1234 + foo -- string: foo lish + stumble -- no value + + struct opt #2: + struct -- nested: 0xXXXXXXXX + bar -- integer: 4321 + foo -- no value + gr -- nested: 0xXXXXXXXX + one -- no value + three -- no value + two -- string: 2 + _EOF_ + +cmp -s ${testname}-res2.* || \ + failure "`diff ${testname}-res2.*`" + +./${testname} -s "${arg1}" -s "${arg2}" '->' +${SED} -e '3s/.*/# ***DATE***/' ${testname}.d/${testname}.cfg > ${testname}.XX +mv -f ${testname}.XX ${testname}.d/${testname}.cfg +cat > ${testname}-res3.base <<- _EOF_ + # test_nested - Test AutoOpts for nested + # preset/initialization file + # ***DATE*** + # + <struct type=nested> + <able/> + <bar type=integer>0x4D2</bar> + <foo>foo	lish</foo> + <stumble/> + </struct> + <struct type=nested> + <bar type=integer>0x10E1</bar> + <foo/> + <gr type=nested> + <one/> + <three/> + <two>2</two> + </gr> + </struct> + _EOF_ +files=${testname}-res3.base\ ${testname}.d/${testname}.cfg +cmp -s ${files} || \ + failure "saved config${nl}`diff ${files}`" + +# Copy the config file and verify that the contents are the same. +# +./${testname} "->${testname}.d/${testname}.cfg2" +${SED} -e '3s/.*/# ***DATE***/' ${testname}.d/${testname}.cfg2 > ${testname}.XX +mv -f ${testname}.XX ${testname}.d/${testname}.cfg2 +files=${testname}.d/${testname}.cfg\ ${testname}.d/${testname}.cfg2 +cmp -s ${files} || \ + failure "re-saved config${nl}`diff ${files}`" + +# # # # # # # # # # TEST OPERATION # # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of nested.test diff --git a/autoopts/test/nls.test b/autoopts/test/nls.test new file mode 100755 index 0000000..1455515 --- /dev/null +++ b/autoopts/test/nls.test @@ -0,0 +1,156 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# nls.test --- test NLS, sort-of +# +# Time-stamp: "2011-08-07 17:36:29 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs +AUTOGEN_TEMPL_DIRS=`cd ${srcdir}/..;pwd` +export AUTOGEN_TEMPL_DIRS + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +testname="${testname}" test_main="YES" \ +argument="${argument}" long_opts="YES" \ +${SHELLX} ${stdopts} option:'opt init' second=020 || \ + failure "Could not run stdopts.def" + +echo 'export = "extern char* gettext( char const* );";' >> ${testname}.def +CC="${CC} ${CFLAGS} -DENABLE_NLS=1 ${INC}" +CFLAGS='' +INC='' + +compile_with_nls() { + + echo ${AG_L} ${testname}.def + ${AG_L} ${testname}.def || \ + failure AutoGen could not process + + chmod u+w ${testname}.[ch] + cat >> ${testname}.c <<'_EOF_' +#include <ctype.h> +char* +gettext( char const* pzS ) +{ + static char z[ 4096 ]; + char* pzD = z + sizeof(z) - 1; + int ct = 0; + int found_nl = 0; + if (pzS == NULL) + return NULL; + if (strchr(pzS, '%') != NULL) + return (void *)pzS; + *--pzD = '\0'; + while (*pzS == ' ') pzS++; + for (;;) { + char ch = *(pzS++); + if (ch == '\0') + break; + *(--pzD) = ch; + ct++; + if (ch != '\n') + continue; + found_nl = 1; + while (*pzS == ' ') pzS++; + } + if (found_nl) + strcpy(z + sizeof(z) - 2, "\n"); + while (*pzD == '\n') + pzD++; + return pzD; +} +_EOF_ + + sedcmd='/ot sgub .* tropeR$/d;/ yb degakcaP/d' + compile "--pleh" + mv ${testname}.help ${testname}-${1}.help + cmp -s ${testname}-${1}.help ${testname}-${1}.hlp || { set +x ; \ + failure "`diff -c ${testname}-${1}.hlp ${testname}-${1}.help`" ; } +} + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.hlp +clean_help > ${testname}-1.hlp <<'_EOF_' +test_nls - Test AutoOpts for nls +USAGE: nls [ -<flag> [<val>] | --<name>[{=| }<val>] ]... +noitpircseD emaN-noitpO grA glF + -o rtS noitpo pircsed noitpo noitpo ehT + -s muN dnoces pircsed noitpo dnoces ehT + -? on pleh tixe dna noitamrofni egasu dednetxe yalpsiD + -! on pleh-erom regap urht dessap noitamrofni egasu dednetxE + +.retcarahc galf eht dna nehpyh +elgnis a yb ro eman rieht dna snehpyh delbuod yb deificeps era snoitpO +_EOF_ + +compile_with_nls 1 + +mv ${testname}.def ${testname}-1.def + +exec 3> ${testname}.def +cat ${testname}-1.def >&3 +echo 'full-usage = <''<''- _EOF_' >&3 +clean_help >&3 <<'_EOF_' +test_nls - Test AutoOpts for nls +USAGE: nls [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -o Str option The option descrip + -s Num second The second descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +_EOF_ +echo '_EOF_;' >&3 +exec 3>&- + +clean_help > ${testname}-2.hlp <<'_EOF_' +.retcarahc galf eht dna nehpyh +elgnis a yb ro eman rieht dna snehpyh delbuod yb deificeps era snoitpO + +regap urht dessap noitamrofni egasu dednetxE pleh-erom on !- +tixe dna noitamrofni egasu dednetxe yalpsiD pleh on ?- +pircsed dnoces ehT dnoces muN s- +pircsed noitpo ehT noitpo rtS o- +noitpircseD emaN-noitpO grA glF +...] ]>lav<} |={[>eman<-- | ]>lav<[ >galf<- [ sln :EGASU +sln rof stpOotuA tseT - sln_tset +_EOF_ + +compile_with_nls 2 +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of nls.test diff --git a/autoopts/test/rc.test b/autoopts/test/rc.test new file mode 100755 index 0000000..18e005d --- /dev/null +++ b/autoopts/test/rc.test @@ -0,0 +1,240 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- + +# rc.test --- test loading and saving of rc files +# +# Time-stamp: "2012-05-13 13:21:58 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +. ./defs + +AUTOOPTS_TRACE=every +AUTOOPTS_TRACE_OUT=">>`pwd`/${testname}-ag-trace.txt" +export AUTOOPTS_TRACE AUTOOPTS_TRACE_OUT + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +: "creating ${testname}.def in `pwd`" + +TESTNAME=RC +export TESTNAME + +test_main="yes" \ +argument="mumble" long_opts="yes" \ +${SHELLX} ${stdopts} option second:init third: || \ + failure "Could not run stdopts.def" + +cat >> ${testname}.def <<_EOF_ +homerc = "\$\$/${testname}.rc"; +rcfile = ${testname}.file; +environrc; +_EOF_ + +${AG_L} ${testname}.def || \ + failure AutoGen could not process A + +# # # # # # # # # # VALIDATE HELP # # # # # # # # # + +clean_help > ${testname}-base1.help <<_EOF_ +test_rc - Test AutoOpts for rc +USAGE: rc [ -<flag> [<val>] | --<name>[{=| }<val>] ]... mumble + Flg Arg Option-Name Description + -o no option The option option descrip + -s Str second The second option descrip + -t Str third The third option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -> opt save-opts Save the option state to a config file + -< Str load-opts Load options from a config file + - disabled as --no-load-opts + - may appear multiple times + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +The following option preset mechanisms are supported: + - reading file ..../${testname}.rc/rc.file + - examining environment variables named TEST_RC_* +_EOF_ + +mkdir ${testname}.rc ${testname}.run +compile "--help" +${SED} 's@\( - reading file \).*\(/'${testname}.rc/rc.file'\)@\1....\2@' \ + ${testname}.help > ${testname}-res1.help +cmp ${testname}-*1.help || \ + failure "`diff ${testname}-*.help`" + +# # # # # # # # # # DO THE REAL TEST # # # # # # # # # + +# Install an initialization for the "second" option. +# That goes into the ${testname}.rc directory. +# We change into the ${testname}.run directory and run the program. +# It should pick up the value saved into the ${testname}.rc dir. +# +./${testname} --second=third '->'${testname}.rc/${testname}.file + +cd ${testname}.run +../${testname} -t xxx MUMBLE > ${testname}.cmds + +# This is what the output should be: +# +cat > ${testname}.test <<'_EOF_' +OPTION_CT=2 +export OPTION_CT +TEST_RC_SECOND='third' +export TEST_RC_SECOND +TEST_RC_THIRD='xxx' +export TEST_RC_THIRD +_EOF_ + + +cmp ${testname}.cmds ${testname}.test || { + df="`diff -c ${testname}.test ${testname}.cmds`" + cd .. + failure "${df}" +} + +# # # # # + +TEST_RC=--no-load ../${testname} -t xxx MUMBLE > ${testname}-2.cmds + +# This is what the output should be: +# +cat > ${testname}-2.test <<'_EOF_' +OPTION_CT=2 +export OPTION_CT +TEST_RC_THIRD='xxx' +export TEST_RC_THIRD +_EOF_ + +cmp ${testname}-2.cmds ${testname}-2.test || { + df="`diff -c ${testname}-2.test ${testname}-2.cmds`" + cd .. + failure "${df}" +} + +# # # # # # # # # # SECOND TEST OUTPUT FILE # # # # # # # # # + +cat >> ../${testname}.rc/${testname}.file <<_EOF_ +[TEST_MUMBLE] +second fourth +<!-- This is a comment + and it should have no effect --> +[TEST_${TESTNAME}] +second = fifth + +# this is another comment +# +[TEST_STUMBLE] +second : sixth +_EOF_ + +../${testname} -t yyy MUMBLE > ${testname}.cmds + +# This is what the output should be: +# +cat > ${testname}.test <<'_EOF_' +OPTION_CT=2 +export OPTION_CT +TEST_RC_SECOND='fifth' +export TEST_RC_SECOND +TEST_RC_THIRD='yyy' +export TEST_RC_THIRD +_EOF_ + +cmp ${testname}.cmds ${testname}.test || { + df="`diff -c ${testname}.test ${testname}.cmds`" + cd .. + failure "${df}" +} + +mv ../${testname}.rc/${testname}.file ../${testname}.rc/${testname}.save +( ${SED} '/^[TEST_MUMBLE]/,$d' ../${testname}.rc/${testname}.save + cat <<- _EOF_ + <?program test-mumble> + second fourth + <!-- This is a comment + and it should have no effect --> + <?program test-${testname}> + <second cooked> + fifth + </second> + # this is another comment + # + <?program test-stumble> + second : sixth + _EOF_ +) > ../${testname}.rc/${testname}.file + +../${testname} -t yyy MUMBLE > ${testname}.cmds + +cmp ${testname}.cmds ${testname}.test || { + df="USING <?program>: `diff -c ${testname}.test ${testname}.cmds`" + cd .. + failure "${df}" +} + +# # # # # # # # # # THIRD TEST OUTPUT FILE # # # # # # # # # + +cd ${testsubdir} + +echo 'disable-save;' >> ${testname}.def + +${AG_L} ${testname}.def || \ + failure AutoGen could not process B + +compile "--help" +${SED} 's@\( - reading file \).*\(/'${testname}.rc/rc.file'\)@\1....\2@' \ + ${testname}.help > ${testname}-res2.help +egrep -v ' save-opts +Save ' ${testname}-base1.help > ${testname}-base2.help + +cmp ${testname}-*2.help || \ + failure "`diff ${testname}-*2.help`" + +echo 'disable-load;' >> ${testname}.def + +${AG_L} ${testname}.def || \ + failure AutoGen could not process B + +compile "--help" +${SED} 's@\( - reading file \).*\(/'${testname}.rc/rc.file'\)@\1....\2@' \ + ${testname}.help > ${testname}-res3.help + +${SED} -e '/ load-opts *Load /,/multiple times$/d' \ + -e '/ save-opts *Save /d' \ + ${testname}-base1.help > ${testname}-base3.help + +cmp ${testname}-*3.help || \ + failure "`diff ${testname}-*3.help`" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of rc.test diff --git a/autoopts/test/shell.test b/autoopts/test/shell.test new file mode 100755 index 0000000..1a47b2f --- /dev/null +++ b/autoopts/test/shell.test @@ -0,0 +1,457 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# shell.test --- test shell program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2012-08-11 08:51:08 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" + + testname="${testname}" \ +test_main="${test_main}" \ + argument="reg-arg [ ... ]" \ +long_opts=true \ +${SHELLX} ${stdopts} option: second || failure "Could not run stdopts.def" + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.hlp +clean_help > ${testname}.hlp <<'_EOF_' +test_shell - Test AutoOpts for shell +USAGE: shell [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + reg-arg [ ... ] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s no second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${testname}.hlp ${testname}.help`" + +./${testname} -X 2> /dev/null && \ + failure ${testname} should not accept bogus options + +./${testname} -o 2> /dev/null && \ + failure ${testname} should not accept missing options argument + +./${testname} 2> /dev/null && \ + failure ${testname} must have an argument + +# # # # # # # # # # SHELL OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.out +cat > ${testname}.out <<_EOF_ +OPTION_CT=3 +export OPTION_CT +TEST_SHELL_OPTION='opt-arg' +export TEST_SHELL_OPTION +TEST_SHELL_SECOND=1 # 0x1 +export TEST_SHELL_SECOND +_EOF_ + +./${testname} -o opt-arg -s a1 a2 > ${testname}.test || \ + failure ${testname} did not handle its options + +cmp -s ${testname}.test ${testname}.out || \ + failure "`diff ${testname}.out ${testname}.test`" + +${SED} '/test-main/s/yes/optionParseShell/' ${testname}.def > XX +mv -f XX ${testname}.def + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +sedcmd='/Note that.*is only useful/,/will be regenerated/d' +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating second ${testname}.hlp +clean_help > ${testname}.hlp <<'_EOF_' +genshellopt - Generate Shell Option Processing Script - Ver. 1 +USAGE: shell [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -o Str script Output Script File + -s Str shell Shell name (follows "#!" magic) + - disabled as --no-shell + - enabled by default + -v opt version Output version information and exit + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. + +Note that ``shell'' is only useful if the output file does not already +exist. If it does, then the shell name and optional first argument will +be extracted from the script file. + +If the script file already exists and contains Automated Option Processing +text, the second line of the file through the ending tag will be replaced +by the newly generated text. The first ``#!'' line will be regenerated. + += = = = = = = = + +This incarnation of genshell will produce +a shell script to parse the options for test_shell: + +test_shell - Test AutoOpts for shell +USAGE: test_shell [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + reg-arg [ ... ] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s no second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character. +_EOF_ + +files=${testname}.hlp\ ${testname}.help +cmp -s ${files} || \ + failure "script generator help output mismatch: `diff -c ${files}`" + +# # # # # # # # # # SCRIPT OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.sht +exec 3> ${testname}.sht +echo "#! ${SHELL}" >&3 +cat >&3 <<'_EOF_' +# +TEST_SHELL_LONGUSAGE_TEXT='test_shell - Test AutoOpts for shell +USAGE: test_shell [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + reg-arg [ ... ] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s no second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character.' + +TEST_SHELL_USAGE_TEXT='test_shell - Test AutoOpts for shell +USAGE: test_shell [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + reg-arg [ ... ] + Flg Arg Option-Name Description + -o Str option The option option descrip + -s no second The second option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +Options are specified by doubled hyphens and their name or by a single +hyphen and the flag character.' + + +TEST_SHELL_OPTION=${TEST_SHELL_OPTION} +TEST_SHELL_OPTION_set=false +export TEST_SHELL_OPTION + +TEST_SHELL_SECOND=${TEST_SHELL_SECOND} +TEST_SHELL_SECOND_set=false +export TEST_SHELL_SECOND + +OPT_PROCESS=true +OPT_ARG=$1 +while ${OPT_PROCESS} && [ $# -gt 0 ] +do + OPT_ELEMENT='' + OPT_ARG_VAL='' + + case "${OPT_ARG}" in + -- ) + OPT_PROCESS=false + shift + ;; + --* ) + OPT_CODE=`echo "X${OPT_ARG}"|sed 's/^X-*//'` + shift + OPT_ARG=$1 + case "${OPT_CODE}" in *=* ) + OPT_ARG_VAL=`echo "${OPT_CODE}"|sed 's/^[^=]*=//'` + OPT_CODE=`echo "${OPT_CODE}"|sed 's/=.*$//'` ;; esac + case "${OPT_CODE}" in + 'op' | \ + 'opt' | \ + 'opti' | \ + 'optio' | \ + 'option' ) + if [ -n "${TEST_SHELL_OPTION}" ] && ${TEST_SHELL_OPTION_set} ; then + echo Error: duplicate OPTION option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 ; fi + TEST_SHELL_OPTION_set=true + OPT_NAME='OPTION' + OPT_ARG_NEEDED=YES + ;; + + 'se' | \ + 'sec' | \ + 'seco' | \ + 'secon' | \ + 'second' ) + if [ -n "${TEST_SHELL_SECOND}" ] && ${TEST_SHELL_SECOND_set} ; then + echo Error: duplicate SECOND option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 ; fi + TEST_SHELL_SECOND_set=true + OPT_NAME='SECOND' + eval TEST_SHELL_SECOND${OPT_ELEMENT}=true + export TEST_SHELL_SECOND${OPT_ELEMENT} + OPT_ARG_NEEDED=NO + ;; + + 'he' | \ + 'hel' | \ + 'help' ) + echo "$TEST_SHELL_LONGUSAGE_TEXT" + exit 0 + ;; + + 'mo' | \ + 'mor' | \ + 'more' | \ + 'more-' | \ + 'more-h' | \ + 'more-he' | \ + 'more-hel' | \ + 'more-help' ) + echo "$TEST_SHELL_LONGUSAGE_TEXT" | ${PAGER-more} + exit 0 + ;; + + * ) + echo Unknown option: "${OPT_CODE}" >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 + ;; + esac + + case "${OPT_ARG_NEEDED}" in + NO ) + OPT_ARG_VAL='' + ;; + YES ) + if [ -z "${OPT_ARG_VAL}" ] + then + if [ $# -eq 0 ] + then + echo No argument provided for ${OPT_NAME} option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 + fi + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 + fi + ;; + OK ) + if [ -z "${OPT_ARG_VAL}" ] && [ $# -gt 0 ] + then + case "${OPT_ARG}" in -* ) ;; * ) + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 ;; esac + fi + ;; + esac + ;; + + -* ) + OPT_CODE=`echo "X${OPT_ARG}" | sed 's/X-\(.\).*/\1/'` + OPT_ARG=` echo "X${OPT_ARG}" | sed 's/X-.//'` + case "${OPT_CODE}" in + 'o' ) + if [ -n "${TEST_SHELL_OPTION}" ] && ${TEST_SHELL_OPTION_set} ; then + echo Error: duplicate OPTION option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 ; fi + TEST_SHELL_OPTION_set=true + OPT_NAME='OPTION' + OPT_ARG_NEEDED=YES + ;; + + 's' ) + if [ -n "${TEST_SHELL_SECOND}" ] && ${TEST_SHELL_SECOND_set} ; then + echo Error: duplicate SECOND option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 ; fi + TEST_SHELL_SECOND_set=true + OPT_NAME='SECOND' + eval TEST_SHELL_SECOND${OPT_ELEMENT}=true + export TEST_SHELL_SECOND${OPT_ELEMENT} + OPT_ARG_NEEDED=NO + ;; + + '?' ) + echo "$TEST_SHELL_LONGUSAGE_TEXT" + exit 0 + ;; + + '!' ) + echo "$TEST_SHELL_LONGUSAGE_TEXT" | ${PAGER-more} + exit 0 + ;; + + * ) + echo Unknown flag: "${OPT_CODE}" >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 + ;; + esac + + case "${OPT_ARG_NEEDED}" in + NO ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG=-${OPT_ARG} + else + shift + OPT_ARG=$1 + fi + ;; + YES ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG_VAL=${OPT_ARG} + else + if [ $# -eq 0 ] + then + echo No argument provided for ${OPT_NAME} option >&2 + echo "$TEST_SHELL_USAGE_TEXT" + exit 1 + fi + shift + OPT_ARG_VAL=$1 + fi + shift + OPT_ARG=$1 + ;; + OK ) + if [ -n "${OPT_ARG}" ] + then + OPT_ARG_VAL=${OPT_ARG} + shift + OPT_ARG=$1 + else + shift + if [ $# -gt 0 ] + then + case "$1" in -* ) ;; * ) + OPT_ARG_VAL=$1 + shift ;; esac + OPT_ARG=$1 + fi + fi + ;; + esac + ;; + + * ) + OPT_PROCESS=false + ;; + esac + if [ -n "${OPT_ARG_VAL}" ] + then + eval TEST_SHELL_${OPT_NAME}${OPT_ELEMENT}="'${OPT_ARG_VAL}'" + export TEST_SHELL_${OPT_NAME}${OPT_ELEMENT} + fi +done +unset OPT_PROCESS || : +unset OPT_ELEMENT || : +unset OPT_ARG || : +unset OPT_ARG_NEEDED || : +unset OPT_NAME || : +unset OPT_CODE || : +unset OPT_ARG_VAL || : + +# # # # # # # # # # +# +# END OF AUTOMATED OPTION PROCESSING +# +# # # # # # # # # # -- do not modify this marker -- + +env | grep '^TEST_SHELL_' +_EOF_ +exec 3>&- + +# # # # # # # # # # SCRIPT OUTPUT TESTING # # # # # # # # # + +rm -f ${testname}.sh +./${testname} -o ${testname}.sh + +sedcmd='2,/From the.*option def/d' +${FGREP} 'Packaged by ' ${testname}.sh >/dev/null && { + sedcmd=${sedcmd}${nl}'/^Packaged by /d + /^Report .* bugs to /d + /and the flag character\.$/s/$/'"'/" +} + +${SED} "$sedcmd" ${testname}.sh > ${testname}.shx +cmp -s ${testname}.sh[tx] || \ + failure "`diff ${testname}.sh[tx]`" + +# # # # # # # # # # SCRIPT PROCESSING TEST # # # # # # # # # + +./${testname}.sh --opt opt-arg -s a1 a2 | sort > ${testname}.test || \ + failure ${testname} did not handle its options + +sort > ${testname}.out <<_EOF_ +TEST_SHELL_OPTION=opt-arg +TEST_SHELL_SECOND=true +_EOF_ + +cmp -s ${testname}.out ${testname}.test || \ + failure "`diff ${testname}.out ${testname}.test`" + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of shell.test diff --git a/autoopts/test/stdopts.def b/autoopts/test/stdopts.def new file mode 100644 index 0000000..e89745c --- /dev/null +++ b/autoopts/test/stdopts.def @@ -0,0 +1,109 @@ +#! /bin/sh + +## Time-stamp: "2012-05-13 12:44:49 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + +# This is the standard set of options for testing option processing +# It is expected to be dot + +exec 5> $testname.def +cat >&5 <<- _EOF_ + + AutoGen definitions options; + + config-header = 'config.h'; + prog-name = "test_${testname}"; + prog-title = "Test AutoOpts for ${testname}"; + _EOF_ + +echo test_main $test_main +echo argument $argument +echo long_opts $long_opts + +{ + test -n "${test_main}" && echo "test-main = '${test_main}';" + test -n "${argument}" && echo "argument = '${argument}';" + test -n "${long_opts}" && echo "long-opts;" +} >&5 + +for flag +do + fname=`echo "${flag}" | ${SED} 's/[^a-zA-Z0-9_-].*//'` + flag=`echo "${flag}" | ${SED} "s/^${fname}//"` + + case "${flag}" in + :* ) + aval=`echo $flag | ${SED} 's/^://'` + arg=" arg-type = string;" + test -n "${aval}" && arg="${arg} arg_default = '${aval}';" + ;; + + =* ) + aval=`echo $flag | ${SED} 's/=//'` + arg=" arg-type = number;" + test -n "${aval}" && arg="${arg} arg_default = '${aval}';" + ;; + + @* ) + arg=`echo $flag | ${SED} 's/@//'` + case "${arg}" in + *=* ) default=`echo $flag | ${SED} 's/.*=//'` + arg=`echo $arg | ${SED} 's/=.*//'` + arg=" arg-type = '${arg}'; arg-default='${default}';" + ;; + + * ) + arg=" arg-type = '${arg}';" + ;; + esac + ;; + + * ) + unset arg + ;; + esac + + cat <<-_EOF_ + flag = { + name = "${fname}"; + descrip = "The ${fname} option descrip"; + _EOF_ + + ${use_flags} && { + fname=`echo ${fname} | ${SED} 's/\(.\).*/\1/'` + echo " value = '${fname}';" + } + test -n "${arg}" && echo "${arg}" + echo "};" + echo +done >&5 + +exec 5>&- +ls -l ${testname}.def + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of stdopts.def diff --git a/autoopts/test/stdopts.test b/autoopts/test/stdopts.test new file mode 100755 index 0000000..21ba56c --- /dev/null +++ b/autoopts/test/stdopts.test @@ -0,0 +1,161 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# stdopts.test --- test standard options +# +# Time-stamp: "2013-03-10 07:14:45 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +cat > ${testname}.def <<- _EOF_ + + AutoGen Definitions options; + + prog-name = test_${testname}; + prog-title = "${testname} test"; + config-header = 'config.h'; + test-main; + long-opts; + + #define VERBOSE_ENUM + #define VERBOSE_FLAG + + #include stdoptions + _EOF_ + +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating ${testname}.hlp +clean_help > ${testname}.hbase <<- _EOF_ + test_stdopts - stdopts test + USAGE: stdopts [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + + The following options are commonly used and are provided and supported + by AutoOpts: + + Flg Arg Option-Name Description + -V KWd verbose run program with progress info + + version, usage and configuration options: + + Flg Arg Option-Name Description + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + + Options are specified by doubled hyphens and their name or by a single + hyphen and the flag character. + + The valid "verbose" option keywords are: + silent quiet brief informative verbose + or an integer from 0 through 4 + _EOF_ + +# When building with DEBUG set, we get an unanticipated option: +# +${GREP} -v 'run program with debugging info' ${testname}.help > ${testname}.hres + +cmp -s ${testname}.h[br]* || \ + failure "MISCOMPARE: `diff ${testname}.h[br]*`" + +./${testname} --verbose=exp > /dev/null 2>&1 && \ + failure ${testname} accepted ambiguous keyword + +./${testname} --verbose=inf > ${testname}.out || \ + failure ${testname} did not handle its options + +cat > ${testname}.oex <<_EOF_ +OPTION_CT=1 +export OPTION_CT +TEST_STDOPTS_VERBOSE='informative' +export TEST_STDOPTS_VERBOSE +_EOF_ + +cmp -s ${testname}.o* || \ + failure "`diff ${testname}.o??`" + +# # # # # # # # # # USAGE OPTION # # # # # # # # # # # + +( ${SED} "s/${testname}/${testname}-2/g" ${testname}.def + echo 'usage-opt;' +) > ${testname}-2.def + +testname=${testname}-2 + +${AG_L} ${testname}.def || { + testname=${testname%-2} + failure AutoGen could not process +} + +compile "--usage" + +clean_help > ${testname}.hbase <<- _EOF_ + test_stdopts-2 - stdopts-2 test + USAGE: stdopts-2 [ -<flag> [<val>] | --<name>[{=| }<val>] ]... + Flg Arg Option-Name Description + -V KWd verbose run program with progress info + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + -u no usage Abbreviated usage to stdout + + Options are specified by doubled hyphens and their name or by a single + hyphen and the flag character. + _EOF_ + +# When building with DEBUG set, we get an unanticipated option: +# +${GREP} -v 'run program with debugging info' ${testname}.help > ${testname}.hres + +cmp -s ${testname}.h[br]* || { + testname=${testname%-2} + failure "MISCOMPARE: `diff ${testname}-2.h[br]*`" +} + +use=` + set +x + exec 2>&1 + exec 1>/dev/null + ./${testname} --usage` +test $? -eq 0 || failure usage failure +test "X${use}" = X || failure misdirected usage + +testname=${testname%-2} +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of stdopts.test diff --git a/autoopts/test/time.test b/autoopts/test/time.test new file mode 100755 index 0000000..855ae88 --- /dev/null +++ b/autoopts/test/time.test @@ -0,0 +1,101 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# time.test --- test time duration argument +# +# Time-stamp: "2011-08-07 17:34:14 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating ${testname}.def in `pwd`" +unset test_main +export testname argument long_opts + +${SHELLX} ${stdopts} ${testname}@time='1d 2 h 15:10' +here='<<' +cat >> ${testname}.def <<- _EOF_ + main = { + main-type = main; + main-text = ${here}- CodeEnd + printf("arg %s represents %d seconds", argv[-1], + OPT_VALUE_TIME); + return 0; + CodeEnd; + }; + _EOF_ + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +compile "-?" + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +basehlp=${testname}.hlp +echo creating ${basehlp} +clean_help > ${basehlp} <<'_EOF_' +test_time - Test AutoOpts for time +USAGE: time [ -<flag> [<val>] ]... + Flg Arg Option-Name Description + -t Tim time The time option descrip + -? no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${basehlp} ${testname}.help`" + +time_val=213791 + +ck() { + tim=`./${testname} -t "$*" | \ + ${SED} -n 's/.* represents \([0-9]*\) seconds/\1/p'` + test -z "${tim}" && failure ${testname} could not parse "$*" + test ${tim} -eq ${time_val} || \ + failure ${testname} misevaluated "$*" +} + +ck 2 d 11h 23:11 +ck 2 d 11h 23m 11s + +tim=`./${testname} -t '2 d 10h 83:11'` && \ + failure ${testname} handled bad options + +# # # # # # # # # # T E S T E N D # # # # # # # # # # + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of argument.test diff --git a/autoopts/test/usage.test b/autoopts/test/usage.test new file mode 100755 index 0000000..33a21a5 --- /dev/null +++ b/autoopts/test/usage.test @@ -0,0 +1,656 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# usage.test --- test all the ways usage text can be printed. +# +## Time-stamp: "2011-08-07 17:20:27 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +${VERBOSE} && kill_delay=10 || kill_delay=5 +. ./defs + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +# ============= usage_LGFRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGFRA.hlp' +test_usage_LGFRA - Checkout usage_LGFRA Options +USAGE: usage_LGFRA { -<flag> [<val>] | --<name>[{=| }<val>] }... \ + cmd-arg ... +X +X -L, --check-dirs=str Checkout directory list +X --show-defs[=arg] Show the definition tree +X -?, --help Display extended usage information and exit +X -!, --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGFRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGFRp.hlp' +test_usage_LGFRp - Checkout usage_LGFRp Options +USAGE: usage_LGFRp { -<flag> | --<name> }... cmd-arg ... +X +X -L, --check-dirs Checkout directory list +X --show-defs Show the definition tree +X -?, --help Display extended usage information and exit +X -!, --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGFoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGFoA.hlp' +test_usage_LGFoA - Checkout usage_LGFoA Options +USAGE: usage_LGFoA [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + cmd-arg ... +X +X -L, --check-dirs=str Checkout directory list +X --show-defs[=arg] Show the definition tree +X -?, --help Display extended usage information and exit +X -!, --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGFop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGFop.hlp' +test_usage_LGFop - Checkout usage_LGFop Options +USAGE: usage_LGFop [ -<flag> | --<name> ]... cmd-arg ... +X +X -L, --check-dirs Checkout directory list +X --show-defs Show the definition tree +X -?, --help Display extended usage information and exit +X -!, --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGsRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGsRA.hlp' +test_usage_LGsRA - Checkout usage_LGsRA Options +USAGE: usage_LGsRA { --<name>[{=| }<val>] }... cmd-arg ... +X +X --check-dirs=str Checkout directory list +X --show-defs[=arg] Show the definition tree +X --help Display extended usage information and exit +X --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGsRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGsRp.hlp' +test_usage_LGsRp - Checkout usage_LGsRp Options +USAGE: usage_LGsRp { --<name> }... cmd-arg ... +X +X --check-dirs Checkout directory list +X --show-defs Show the definition tree +X --help Display extended usage information and exit +X --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGsoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGsoA.hlp' +test_usage_LGsoA - Checkout usage_LGsoA Options +USAGE: usage_LGsoA [ --<name>[{=| }<val>] ]... cmd-arg ... +X +X --check-dirs=str Checkout directory list +X --show-defs[=arg] Show the definition tree +X --help Display extended usage information and exit +X --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LGsop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LGsop.hlp' +test_usage_LGsop - Checkout usage_LGsop Options +USAGE: usage_LGsop [ --<name> ]... cmd-arg ... +X +X --check-dirs Checkout directory list +X --show-defs Show the definition tree +X --help Display extended usage information and exit +X --more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LaFRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LaFRA.hlp' +test_usage_LaFRA - Checkout usage_LaFRA Options +USAGE: usage_LaFRA { -<flag> [<val>] | --<name>[{=| }<val>] }... \ + cmd-arg ... +X Flg Arg Option-Name Req? Description +X -L Str check-dirs YES Checkout directory list +X opt show-defs opt Show the definition tree +X -? no help opt Display extended usage information and exit +X -! no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LaFRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LaFRp.hlp' +test_usage_LaFRp - Checkout usage_LaFRp Options +USAGE: usage_LaFRp { -<flag> | --<name> }... cmd-arg ... +X Flg Arg Option-Name Req? Description +X -L no check-dirs YES Checkout directory list +X no show-defs opt Show the definition tree +X -? no help opt Display extended usage information and exit +X -! no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LaFoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LaFoA.hlp' +test_usage_LaFoA - Checkout usage_LaFoA Options +USAGE: usage_LaFoA [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \ + cmd-arg ... +X Flg Arg Option-Name Description +X -L Str check-dirs Checkout directory list +X opt show-defs Show the definition tree +X -? no help Display extended usage information and exit +X -! no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LaFop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LaFop.hlp' +test_usage_LaFop - Checkout usage_LaFop Options +USAGE: usage_LaFop [ -<flag> | --<name> ]... cmd-arg ... +X Flg Arg Option-Name Description +X -L no check-dirs Checkout directory list +X no show-defs Show the definition tree +X -? no help Display extended usage information and exit +X -! no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LasRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LasRA.hlp' +test_usage_LasRA - Checkout usage_LasRA Options +USAGE: usage_LasRA { --<name>[{=| }<val>] }... cmd-arg ... +X Arg Option-Name Req? Description +X Str check-dirs YES Checkout directory list +X opt show-defs opt Show the definition tree +X no help opt Display extended usage information and exit +X no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LasRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LasRp.hlp' +test_usage_LasRp - Checkout usage_LasRp Options +USAGE: usage_LasRp { --<name> }... cmd-arg ... +X Arg Option-Name Req? Description +X no check-dirs YES Checkout directory list +X no show-defs opt Show the definition tree +X no help opt Display extended usage information and exit +X no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_LasoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_LasoA.hlp' +test_usage_LasoA - Checkout usage_LasoA Options +USAGE: usage_LasoA [ --<name>[{=| }<val>] ]... cmd-arg ... +X Arg Option-Name Description +X Str check-dirs Checkout directory list +X opt show-defs Show the definition tree +X no help Display extended usage information and exit +X no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_Lasop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_Lasop.hlp' +test_usage_Lasop - Checkout usage_Lasop Options +USAGE: usage_Lasop [ --<name> ]... cmd-arg ... +X Arg Option-Name Description +X no check-dirs Checkout directory list +X no show-defs Show the definition tree +X no help Display extended usage information and exit +X no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGFRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGFRA.hlp' +test_usage_sGFRA - Checkout usage_sGFRA Options +USAGE: usage_sGFRA { -<flag> [<val>] }... cmd-arg ... +X +X -L str Checkout directory list +X -s [arg] Show the definition tree +X -? Display extended usage information and exit +X -! Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGFRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGFRp.hlp' +test_usage_sGFRp - Checkout usage_sGFRp Options +USAGE: usage_sGFRp { -<flag> }... cmd-arg ... +X +X -L Checkout directory list +X -s Show the definition tree +X -? Display extended usage information and exit +X -! Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGFoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGFoA.hlp' +test_usage_sGFoA - Checkout usage_sGFoA Options +USAGE: usage_sGFoA [ -<flag> [<val>] ]... cmd-arg ... +X +X -L str Checkout directory list +X -s [arg] Show the definition tree +X -? Display extended usage information and exit +X -! Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGFop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGFop.hlp' +test_usage_sGFop - Checkout usage_sGFop Options +USAGE: usage_sGFop [ -<flag> ]... cmd-arg ... +X +X -L Checkout directory list +X -s Show the definition tree +X -? Display extended usage information and exit +X -! Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGsRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGsRA.hlp' +test_usage_sGsRA - Checkout usage_sGsRA Options +USAGE: usage_sGsRA { <option-name>[{=| }<val>] }... +X +X check-dirs=str Checkout directory list +X show-defs[=arg] Show the definition tree +X help Display extended usage information and exit +X more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGsRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGsRp.hlp' +test_usage_sGsRp - Checkout usage_sGsRp Options +USAGE: usage_sGsRp { <option-name> }... +X +X check-dirs Checkout directory list +X show-defs Show the definition tree +X help Display extended usage information and exit +X more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGsoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGsoA.hlp' +test_usage_sGsoA - Checkout usage_sGsoA Options +USAGE: usage_sGsoA [ <option-name>[{=| }<val>] ]... +X +X check-dirs=str Checkout directory list +X show-defs[=arg] Show the definition tree +X help Display extended usage information and exit +X more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sGsop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sGsop.hlp' +test_usage_sGsop - Checkout usage_sGsop Options +USAGE: usage_sGsop [ <option-name> ]... +X +X check-dirs Checkout directory list +X show-defs Show the definition tree +X help Display extended usage information and exit +X more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_saFRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_saFRA.hlp' +test_usage_saFRA - Checkout usage_saFRA Options +USAGE: usage_saFRA { -<flag> [<val>] }... cmd-arg ... +X Flg Arg Option-Name Req? Description +X -L Str check-dirs YES Checkout directory list +X -s opt show-defs opt Show the definition tree +X -? no help opt Display extended usage information and exit +X -! no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_saFRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_saFRp.hlp' +test_usage_saFRp - Checkout usage_saFRp Options +USAGE: usage_saFRp { -<flag> }... cmd-arg ... +X Flg Arg Option-Name Req? Description +X -L no check-dirs YES Checkout directory list +X -s no show-defs opt Show the definition tree +X -? no help opt Display extended usage information and exit +X -! no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_saFoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_saFoA.hlp' +test_usage_saFoA - Checkout usage_saFoA Options +USAGE: usage_saFoA [ -<flag> [<val>] ]... cmd-arg ... +X Flg Arg Option-Name Description +X -L Str check-dirs Checkout directory list +X -s opt show-defs Show the definition tree +X -? no help Display extended usage information and exit +X -! no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_saFop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_saFop.hlp' +test_usage_saFop - Checkout usage_saFop Options +USAGE: usage_saFop [ -<flag> ]... cmd-arg ... +X Flg Arg Option-Name Description +X -L no check-dirs Checkout directory list +X -s no show-defs Show the definition tree +X -? no help Display extended usage information and exit +X -! no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sasRA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sasRA.hlp' +test_usage_sasRA - Checkout usage_sasRA Options +USAGE: usage_sasRA { <option-name>[{=| }<val>] }... +X Arg Option-Name Req? Description +X Str check-dirs YES Checkout directory list +X opt show-defs opt Show the definition tree +X no help opt Display extended usage information and exit +X no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sasRp.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sasRp.hlp' +test_usage_sasRp - Checkout usage_sasRp Options +USAGE: usage_sasRp { <option-name> }... +X Arg Option-Name Req? Description +X no check-dirs YES Checkout directory list +X no show-defs opt Show the definition tree +X no help opt Display extended usage information and exit +X no more-help opt Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sasoA.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sasoA.hlp' +test_usage_sasoA - Checkout usage_sasoA Options +USAGE: usage_sasoA [ <option-name>[{=| }<val>] ]... +X Arg Option-Name Description +X Str check-dirs Checkout directory list +X opt show-defs Show the definition tree +X no help Display extended usage information and exit +X no more-help Extended usage information passed thru pager +SHAR_EOF + +# ============= usage_sasop.hlp ============== +${SED} 's/^X//;/^[ ]*$/d' << 'SHAR_EOF' > 'usage_sasop.hlp' +test_usage_sasop - Checkout usage_sasop Options +USAGE: usage_sasop [ <option-name> ]... +X Arg Option-Name Description +X no check-dirs Checkout directory list +X no show-defs Show the definition tree +X no help Display extended usage information and exit +X no more-help Extended usage information passed thru pager +SHAR_EOF + +# # # # # # # # # # DEFINITIONS FILES # # # # # # # # # + +emit_defs() +{ + exec 4> $1.def + cat >&4 <<- _EOF_ + AutoGen Definitions options; + prog-name = test_$1; + prog-title = "Checkout $1 Options"; + config-header = 'config.h'; + test-main; + _EOF_ + + cmd_arg="argument = 'cmd-arg ...';" + if ${long_opts} + then + echo "long-opts;" >&4 + if ${flag_opts} + then detail="Long and short (flag) options are accepted." + else detail="Only long options are accepted." ; fi + else + if ${flag_opts} + then detail="Only short (flag) options are accepted." + else detail="All command line arguments must be named options." + cmd_arg='' + fi + fi + + if ${gnu_usage} + then + echo "gnu-usage;" >&4 + detail="${detail}${nl}Usage should be in GNU style." + else + detail="${detail}${nl}Usage is in AutoOpts traditional style." + fi + + cat >&4 <<- _EOF_ + ${cmd_arg} + flag = { + name = check_dirs; + descrip = "Checkout directory list"; + _EOF_ + + if ${flag_opts} + then + echo " value = L;" >&4 + fi + + if ${req_opts} + then + echo " min = '1';" >&4 + detail="${detail}${nl}The check-dirs option is required." + else + detail="${detail}${nl}There are no required options." + fi + + if ${arg_opts} + then + echo " arg-type = string;" >&4 + echo " arg-name = dir;" >&4 + detail="${detail}${nl}Some options require arguments." + else + detail="${detail}${nl}No options require arguments." + fi + + cat >&4 <<- _EOF_ + }; + + flag = { + name = show_defs; + descrip = "Show the definition tree"; + _EOF_ + + if ${flag_opts} + then + ${long_opts} || echo " value = s;" >&4 + fi + + if ${arg_opts} + then + echo " arg-type = number;" >&4 + echo " arg-name = depth;" >&4 + echo " arg-optional;" >&4 + fi + + echo "};" >&4 + echo "detail = '${detail}';" >&4 + + exec 4>&- +} + +run_usage_test() { + ${arg_opts} && name="${rname}A" || name="${rname}p" + testname=${tname}_${name} + emit_defs ${testname} + test_list="${test_list} ${testname}" + echo firstline >> ${defnames_raw} + ${AG_L} ${testname}.def >> ${defnames_raw} || { + cat ${defnames_raw} + failure "AutoGen could not process $testname" + } + + ${SED} \ + -e '1,/definition names looked up/d' \ + -e '/end of looked up def/,$d' ${defnames_raw} \ + ${defnames_raw} >> ${defnames_file} + compile ${helpstr} + ${SED} -e '/Extended usage information passed thru pager/q' \ + ${testname}.help > XXX + mv XXX ${testname}.help + cmp -s ${testname}.help ${testname}.hlp || \ + failure "FAILED ${testname} hlp -> help +`diff ${testname}.hlp ${testname}.help`" +} + +test_list="" +tname=${testname} +defnames_raw=${TMPDIR}/defnames.raw +defnames_file=${TMPDIR}/defnames.uniq +AG_L=${AG_L}\ --used-defines + +case "$-" in +*x* ) setx='set -x' ;; +* ) setx='' ;; +esac + +stime=$(date +%s) + +for long_opts in true false +do + ${long_opts} && lname=L || lname=s + + for gnu_usage in true false + do + ${gnu_usage} && uname="${lname}G" || uname="${lname}a" + + for flag_opts in true false + do + ${flag_opts} && fname="${uname}F" || fname="${uname}s" + + if ${long_opts} + then helpstr=--help + + elif ${flag_opts} + then helpstr='-?' + + else helpstr=help + fi + + for req_opts in true false + do + ${req_opts} && rname="${fname}R" || rname="${fname}o" + + for arg_opts in true false + do + run_usage_test + done + done + done + done +done + +test -z "${DEBUG_USAGE}" && cleanup && exit 0 + +sort -u -o ${defnames_file} ${defnames_file} +cat > ${defnames_raw} <<- _EOF_ + aliases + allow_errors + arg_default + arg_optional + arg_range + arg_type + argument + call_proc + code + config_header + copyright + default + deprecated + descrip + detail + disable + documentation + eaddr + enable + enabled + environrc + equivalence + exit_name + explain + export + extract_code + field + file_fail_code + flag + flag_code + flag_proc + flags_cant + flags_must + full_usage + gnu_usage + guard_option_names + help_value + homerc + ifdef + ifndef + immed_disable + immediate + include + lib_name + library + long_opts + main + main_text + main_type + max + min + more_help_value + must_set + name + no_command + no_libopts + no_misuse_usage + no_preset + no_xlate + nomem_fail_code + omitted_usage + package + prefix + prefix_enum + preserve_case + prog_name + prog_title + reorder_args + resettable + scaled + settable + short_usage + stack_arg + std_value + test_main + translators + unstack_arg + usage + usage_message + usage_opt + usage_type + val_name + val_upname + value + version + _EOF_ + +cmp ${defnames_raw} ${defnames_file} || \ + failure "${defnames_raw} and ${defnames_file} do not compare${nl}` + diff ${defnames_raw} ${defnames_file}`" +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of usage.test diff --git a/autoopts/test/vendor.test b/autoopts/test/vendor.test new file mode 100755 index 0000000..a9d0ac8 --- /dev/null +++ b/autoopts/test/vendor.test @@ -0,0 +1,174 @@ +#! /bin/sh +# -*- Mode: shell-script -*- +# ---------------------------------------------------------------------- +# vendor.test --- test the vendor-opt option +# +# Time-stamp: "2012-03-31 13:11:19 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +# +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +{ + sedcmd=' +s/long-opts;/vendor-opt;/ +/#include "autogen.h"/d +/^prog-name/s/=.*/= '${testname}';/ +s/AutoGen/'${testname}'/g +/^include /s/= '${testname}'5 Temp/= AutoGen5 Temp/ +/^config-header/s/=.*/= '${testname}'-config.h;/ +/call-proc *=/d +/#ifndef XML/,/^#endif/ { + /^#else/,/^#endif/d + /^#/d +} +/flag-code =.*_EOCode_/,/_EOCode_;/d +/flag-code *=/d +' + + ${SED} "$sedcmd" ${top_srcdir}/agen5/opts.def + cat <<- _EOF_ + config-header = ${testname}-config.h; + help-value = h; + save-opts-value = S; + load-opts-value = P; + gnu-usage; + main = { main-type = shell-process; }; + include = '#undef DEBUG_ENABLED'; + _EOF_ +} > ${testname}.def + +{ + sed '/^#endif.*_CONFIG_H/d' ${top_builddir}/config.h + sed '1,/#define *COMPAT_H_GUARD/d + /^#endif .* COMPAT_H_GUARD/{ + s/COMPAT_H_GUARD/AUTOGEN_CONFIG_H/ + q + }' ${top_srcdir}/compat/compat.h +} > ./${testname}-config.h + +echo ${AG_L} ${testname}.def +${AG_L} ${testname}.def || \ + failure AutoGen could not process + +sedcmd='' +HOME=${TMPDIR} compile "-h" +${SED} 1d ${testname}.help > ${testname}.$$ +mv -f ${testname}.$$ ${testname}.help + +clean_help > ${testname}.hlp <<_EOF_ +USAGE: ${testname} [ -<flag> [<val>] ]... [ <def-file> ] +The following options select definitions, templates and scheme functions +to use: + -L str Template search directory list + - may appear multiple times + -T str Override template file + - may not be preset + -l str Library template file + - may appear multiple times + -S str Scheme code file to load + -F str Load scheme function library + -m Do not use in-mem streams +The following options modify how output is handled: + -b str Base name for output file(s) + - may not be preset +The following options are often useful while debugging new templates: + -t num Time limit for server shell + - It must be in the range: + 0 to 3600 + --- show-defs This option has been disabled + -C Leave a core dump on a failure exit +These options can be used to control what gets processed in the +definitions files and template files: + -s str Omit the file with this suffix + - prohibits these options: + select-suffix + - may not be preset + - may appear multiple times + -o str specify this output suffix + - may not be preset + - may appear multiple times + -D str name to add to definition list + - may appear multiple times + -U str definition list removal pattern + - an alternate for define +This option is used to automate dependency tracking: + -M [arg] emit make dependency file + - may not be preset + - may appear multiple times +version, usage and configuration options: + -R str Reset an option's state + -v [arg] Output version information and exit + -h Display extended usage information and exit + -! Extended usage information passed thru pager + -u Abbreviated usage to stdout + -S [arg] Save the option state to a config file + -P str Load options from a config file + - disabled as --no-load-opts + - may appear multiple times +The next option supports vendor supported extra options: + -W str vendor supported additional options + These additional options are: + definitions=str Definitions input file + - disabled as --no-definitions + - enabled by default + - may not be preset + shell=str name or path name of shell to use + equate=str characters considered equivalent + source-time set mod times to latest source + - disabled as --no-source-time + writable Allow output files to be writable + - disabled as --not-writable + loop-limit=num Limit on increment loops + - is scalable with a suffix: k/K/m/M/g/G/t/T + - It must lie in one of the ranges: + -1 exactly, or + 1 to 16777216 + trace=KWd tracing level of detail + trace-out=str tracing output file or filter + used-defines Show the definitions used + - may not be preset +${testname} creates text files from templates using external definitions. + +The following option preset mechanisms are supported: + - reading file \$HOME/.${testname}rc + - reading file ./.${testname}rc + - examining environment variables named ` + echo ${testname} | tr 'a-z' 'A-Z'`_* + +The valid "trace" option keywords are: + nothing debug-message server-shell templates block-macros + expressions everything + or an integer from 0 through 6 + +${testname} is a tool designed for generating program files that contain +repetitive text with varied substitutions. +_EOF_ + +cmp -s ${testname}.h*lp || \ + failure "`diff ${testname}.hlp ${testname}.help`" + +cleanup diff --git a/autoopts/test/vers.test b/autoopts/test/vers.test new file mode 100755 index 0000000..55fb435 --- /dev/null +++ b/autoopts/test/vers.test @@ -0,0 +1,107 @@ +#! /bin/sh +# -*- Mode: Shell-script -*- +# ---------------------------------------------------------------------- +# vers.test --- test vers program attribute +# make sure that when it is not specified +# then option processing consumes all args. +# +# Time-stamp: "2011-08-07 17:35:55 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd +## +# ---------------------------------------------------------------------- + +. ./defs + +# # # # # # # # # # DEFINITIONS FILE # # # # # # # # # + +echo "creating $testname.def in `pwd`" +testname="$testname" test_main="${test_main}" \ +argument="${argument}" long_opts="${long_opts}" \ +${SHELLX} ${stdopts} option second || failure "Could not construct stdopts" +echo 'help-value = h;' >> $testname.def +echo 'version-value = V;' >> $testname.def + +echo ${AG_L} $testname.def +${AG_L} $testname.def || \ + failure AutoGen could not process + +compile "-h" + + +# # # # # # # # # # HELP OUTPUT FILE # # # # # # # # # + +echo creating $testname.hlp +clean_help > $testname.hlp <<'_EOF_' +test_vers - Test AutoOpts for vers +USAGE: vers [ -<flag> ]... + Flg Arg Option-Name Description + -o no option The option option descrip + -s no second The second option descrip + -h no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s $testname.h*lp || \ + failure help output mismatch + +./$testname -v 2> /dev/null && \ + failure $testname should not accept version option + +ver="`echo '$Revision: 4.8 $'|${SED} 's/.*: *\([0-9.a-z]*\).*/\1/'`" +echo "version = '$ver';" >> $testname.def + +echo ${AG_L} $testname.def +${AG_L} $testname.def || \ + failure AutoGen could not process + +compile "-h" + +./$testname -V 2> /dev/null || \ + failure "$testname '*SHOULD*' accept version option" + +echo recreating $testname.hlp +clean_help > $testname.hlp <<_EOF_ +test_vers - Test AutoOpts for vers - Ver. ${ver} +USAGE: vers [ -<flag> ]... + Flg Arg Option-Name Description + -o no option The option option descrip + -s no second The second option descrip + -V opt version Output version information and exit + -h no help Display extended usage information and exit + -! no more-help Extended usage information passed thru pager + +_EOF_ + +cmp -s $testname.h*lp || \ + failure versioned help output mismatch + +cleanup + +## Local Variables: +## mode: shell-script +## indent-tabs-mode: nil +## sh-indentation: 2 +## End: + +# end of vers.test diff --git a/autoopts/text_mmap.c b/autoopts/text_mmap.c new file mode 100644 index 0000000..4a7aa1a --- /dev/null +++ b/autoopts/text_mmap.c @@ -0,0 +1,370 @@ +/** + * @file text_mmap.c + * + * Map a text file, ensuring the text always has an ending NUL byte. + * + * Time-stamp: "2012-01-29 09:40:21 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ +#if defined(HAVE_MMAP) +# ifndef MAP_ANONYMOUS +# ifdef MAP_ANON +# define MAP_ANONYMOUS MAP_ANON +# endif +# endif + +# if ! defined(MAP_ANONYMOUS) && ! defined(HAVE_DEV_ZERO) + /* + * We must have either /dev/zero or anonymous mapping for + * this to work. + */ +# undef HAVE_MMAP + +# else +# ifdef _SC_PAGESIZE +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# else +# define GETPAGESIZE() getpagesize() +# endif +# endif +#endif + +/* + * Some weird systems require that a specifically invalid FD number + * get passed in as an argument value. Which value is that? Well, + * as everybody knows, if open(2) fails, it returns -1, so that must + * be the value. :) + */ +#define AO_INVALID_FD -1 + +#define FILE_WRITABLE(_prt,_flg) \ + ( (_prt & PROT_WRITE) \ + && ((_flg & (MAP_SHARED|MAP_PRIVATE)) == MAP_SHARED)) +#define MAP_FAILED_PTR ((void*)MAP_FAILED) + +/** + * Load the contents of a text file. There are two separate implementations, + * depending up on whether mmap(3) is available. + * + * If not available, malloc the file length plus one byte. Read it in + * and NUL terminate. + * + * If available, first check to see if the text file size is a multiple of a + * page size. If it is, map the file size plus an extra page from either + * anonymous memory or from /dev/zero. Then map the file text on top of the + * first pages of the anonymous/zero pages. Otherwise, just map the file + * because there will be NUL bytes provided at the end. + * + * @param mapinfo a structure holding everything we need to know + * about the mapping. + * + * @param pzFile name of the file, for error reporting. + */ +static void +load_text_file(tmap_info_t * mapinfo, char const * pzFile) +{ +#if ! defined(HAVE_MMAP) + mapinfo->txt_data = AGALOC(mapinfo->txt_size+1, "file text"); + if (mapinfo->txt_data == NULL) { + mapinfo->txt_errno = ENOMEM; + return; + } + + { + size_t sz = mapinfo->txt_size; + char* pz = mapinfo->txt_data; + + while (sz > 0) { + ssize_t rdct = read(mapinfo->txt_fd, pz, sz); + if (rdct <= 0) { + mapinfo->txt_errno = errno; + fprintf(stderr, zFSErrReadFile, + errno, strerror(errno), pzFile); + free(mapinfo->txt_data); + return; + } + + pz += rdct; + sz -= rdct; + } + + *pz = NUL; + } + + mapinfo->txt_errno = 0; + +#else /* HAVE mmap */ + size_t const pgsz = GETPAGESIZE(); + void * map_addr = NULL; + + (void)pzFile; + + mapinfo->txt_full_size = (mapinfo->txt_size + pgsz) & ~(pgsz - 1); + if (mapinfo->txt_full_size == (mapinfo->txt_size + pgsz)) { + /* + * The text is a multiple of a page boundary. We must map an + * extra page so the text ends with a NUL. + */ +#if defined(MAP_ANONYMOUS) + map_addr = mmap(NULL, mapinfo->txt_full_size, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, AO_INVALID_FD, 0); +#else + mapinfo->txt_zero_fd = open("/dev/zero", O_RDONLY); + + if (mapinfo->txt_zero_fd == AO_INVALID_FD) { + mapinfo->txt_errno = errno; + return; + } + map_addr = mmap(NULL, mapinfo->txt_full_size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, mapinfo->txt_zero_fd, 0); +#endif + if (map_addr == MAP_FAILED_PTR) { + mapinfo->txt_errno = errno; + return; + } + mapinfo->txt_flags |= MAP_FIXED; + } + + mapinfo->txt_data = + mmap(map_addr, mapinfo->txt_size, mapinfo->txt_prot, + mapinfo->txt_flags, mapinfo->txt_fd, 0); + + if (mapinfo->txt_data == MAP_FAILED_PTR) + mapinfo->txt_errno = errno; +#endif /* HAVE_MMAP */ +} + +/** + * Make sure all the parameters are correct: we have a file name that + * is a text file that we can read. + * + * @param fname the text file to map + * @param prot the memory protections requested (read/write/etc.) + * @param flags mmap flags + * @param mapinfo a structure holding everything we need to know + * about the mapping. + */ +static void +validate_mmap(char const * fname, int prot, int flags, tmap_info_t * mapinfo) +{ + memset(mapinfo, 0, sizeof(*mapinfo)); +#if defined(HAVE_MMAP) && ! defined(MAP_ANONYMOUS) + mapinfo->txt_zero_fd = AO_INVALID_FD; +#endif + mapinfo->txt_fd = AO_INVALID_FD; + mapinfo->txt_prot = prot; + mapinfo->txt_flags = flags; + + /* + * Make sure we can stat the regular file. Save the file size. + */ + { + struct stat sb; + if (stat(fname, &sb) != 0) { + mapinfo->txt_errno = errno; + return; + } + + if (! S_ISREG(sb.st_mode)) { + mapinfo->txt_errno = errno = EINVAL; + return; + } + + mapinfo->txt_size = sb.st_size; + } + + /* + * Map mmap flags and protections into open flags and do the open. + */ + { + /* + * See if we will be updating the file. If we can alter the memory + * and if we share the data and we are *not* copy-on-writing the data, + * then our updates will show in the file, so we must open with + * write access. + */ + int o_flag = FILE_WRITABLE(prot, flags) ? O_RDWR : O_RDONLY; + + /* + * If you're not sharing the file and you are writing to it, + * then don't let anyone else have access to the file. + */ + if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE)) + o_flag |= O_EXCL; + + mapinfo->txt_fd = open(fname, o_flag); + } + + if (mapinfo->txt_fd == AO_INVALID_FD) + mapinfo->txt_errno = errno; +} + +/** + * Close any files opened by the mapping. + * + * @param mi a structure holding everything we need to know about the map. + */ +static void +close_mmap_files(tmap_info_t * mi) +{ + if (mi->txt_fd == AO_INVALID_FD) + return; + + close(mi->txt_fd); + mi->txt_fd = AO_INVALID_FD; + +#if ! defined(MAP_ANONYMOUS) + if (mi->txt_zero_fd == AO_INVALID_FD) + return; + + close(mi->txt_zero_fd); + mi->txt_zero_fd = AO_INVALID_FD; +#endif +} + +/*=export_func text_mmap + * private: + * + * what: map a text file with terminating NUL + * + * arg: char const*, pzFile, name of the file to map + * arg: int, prot, mmap protections (see mmap(2)) + * arg: int, flags, mmap flags (see mmap(2)) + * arg: tmap_info_t*, mapinfo, returned info about the mapping + * + * ret-type: void* + * ret-desc: The mmaped data address + * + * doc: + * + * This routine will mmap a file into memory ensuring that there is at least + * one @file{NUL} character following the file data. It will return the + * address where the file contents have been mapped into memory. If there is a + * problem, then it will return @code{MAP_FAILED} and set @code{errno} + * appropriately. + * + * The named file does not exist, @code{stat(2)} will set @code{errno} as it + * will. If the file is not a regular file, @code{errno} will be + * @code{EINVAL}. At that point, @code{open(2)} is attempted with the access + * bits set appropriately for the requested @code{mmap(2)} protections and flag + * bits. On failure, @code{errno} will be set according to the documentation + * for @code{open(2)}. If @code{mmap(2)} fails, @code{errno} will be set as + * that routine sets it. If @code{text_mmap} works to this point, a valid + * address will be returned, but there may still be ``issues''. + * + * If the file size is not an even multiple of the system page size, then + * @code{text_map} will return at this point and @code{errno} will be zero. + * Otherwise, an anonymous map is attempted. If not available, then an attempt + * is made to @code{mmap(2)} @file{/dev/zero}. If any of these fail, the + * address of the file's data is returned, bug @code{no} @file{NUL} characters + * are mapped after the end of the data. + * + * see: mmap(2), open(2), stat(2) + * + * err: Any error code issued by mmap(2), open(2), stat(2) is possible. + * Additionally, if the specified file is not a regular file, then + * errno will be set to @code{EINVAL}. + * + * example: + * #include <mylib.h> + * tmap_info_t mi; + * int no_nul; + * void* data = text_mmap("file", PROT_WRITE, MAP_PRIVATE, &mi); + * if (data == MAP_FAILED) return; + * no_nul = (mi.txt_size == mi.txt_full_size); + * << use the data >> + * text_munmap(&mi); +=*/ +void * +text_mmap(char const * pzFile, int prot, int flags, tmap_info_t * mi) +{ + validate_mmap(pzFile, prot, flags, mi); + if (mi->txt_errno != 0) + return MAP_FAILED_PTR; + + load_text_file(mi, pzFile); + + if (mi->txt_errno == 0) + return mi->txt_data; + + close_mmap_files(mi); + + errno = mi->txt_errno; + mi->txt_data = MAP_FAILED_PTR; + return mi->txt_data; +} + + +/*=export_func text_munmap + * private: + * + * what: unmap the data mapped in by text_mmap + * + * arg: tmap_info_t*, mapinfo, info about the mapping + * + * ret-type: int + * ret-desc: -1 or 0. @code{errno} will have the error code. + * + * doc: + * + * This routine will unmap the data mapped in with @code{text_mmap} and close + * the associated file descriptors opened by that function. + * + * see: munmap(2), close(2) + * + * err: Any error code issued by munmap(2) or close(2) is possible. +=*/ +int +text_munmap(tmap_info_t * mi) +{ + errno = 0; + +#ifdef HAVE_MMAP + (void)munmap(mi->txt_data, mi->txt_full_size); + +#else /* don't HAVE_MMAP */ + /* + * IF the memory is writable *AND* it is not private (copy-on-write) + * *AND* the memory is "sharable" (seen by other processes) + * THEN rewrite the data. Emulate mmap visibility. + */ + if ( FILE_WRITABLE(mi->txt_prot, mi->txt_flags) + && (lseek(mi->txt_fd, 0, SEEK_SET) >= 0) ) { + write(mi->txt_fd, mi->txt_data, mi->txt_size); + } + + free(mi->txt_data); +#endif /* HAVE_MMAP */ + + mi->txt_errno = errno; + close_mmap_files(mi); + + return mi->txt_errno; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/text_mmap.c */ diff --git a/autoopts/time.c b/autoopts/time.c new file mode 100644 index 0000000..e8e4f05 --- /dev/null +++ b/autoopts/time.c @@ -0,0 +1,143 @@ + +/** + * \file time.c + * + * Time-stamp: "2012-08-11 08:34:17 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionTimeVal + * private: + * + * what: process an option with a time duration. + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Decipher a time duration value. +=*/ +void +optionTimeVal(tOptions * pOpts, tOptDesc * pOD) +{ + time_t val; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + val = parse_duration(pOD->optArg.argString); + if (val == BAD_TIME) { + fprintf(stderr, zNotDuration, pOpts->pzProgName, pOD->optArg.argString); + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + } + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + + pOD->optArg.argInt = (unsigned long)val; +} + +/*=export_func optionTimeDate + * private: + * + * what: process an option with a time and date. + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + tOptDesc* + pOptDesc + the descriptor for this arg + + * + * doc: + * Decipher a time and date value. +=*/ +void +optionTimeDate(tOptions * pOpts, tOptDesc * pOD) +{ +#if defined(HAVE_GETDATE_R) && defined(HAVE_PUTENV) + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((! HAS_pzPkgDataDir(pOpts)) || (pOpts->pzPkgDataDir == NULL)) + goto default_action; + + /* + * Export the DATEMSK environment variable. getdate_r() uses it to + * find the file with the strptime formats. If we cannot find the file + * we need ($PKGDATADIR/datemsk), then fall back to just a time duration. + */ + { + static char * envptr = NULL; + + if (envptr == NULL) { + static char const fmt[] = "DATEMSK=%s/datemsk"; + envptr = AGALOC(sizeof(fmt) + strlen(pOpts->pzPkgDataDir), fmt); + sprintf(envptr, fmt, pOpts->pzPkgDataDir); + + putenv(envptr); + } + + if (access(envptr+8, R_OK) != 0) + goto default_action; + } + + /* + * Convert the date to a time since the epoch and stash it in a long int. + */ + { + struct tm stm; + time_t tm; + + if (getdate_r(pOD->optArg.argString, &stm) != 0) { + fprintf(stderr, zNotDate, pOpts->pzProgName, + pOD->optArg.argString); + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + return; + } + + tm = mktime(&stm); + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + } + + pOD->optArg.argInt = tm; + } + return; + +default_action: + +#endif + optionTimeVal(pOpts, pOD); + if (pOD->optArg.argInt != BAD_TIME) + pOD->optArg.argInt += (unsigned long)time(NULL); +} +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/time.c */ diff --git a/autoopts/tokenize.c b/autoopts/tokenize.c new file mode 100644 index 0000000..9563713 --- /dev/null +++ b/autoopts/tokenize.c @@ -0,0 +1,333 @@ +/* + * This file defines the string_tokenize interface + * Time-stamp: "2012-03-04 13:23:50 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +#include <errno.h> +#include <stdlib.h> + +#define cc_t const unsigned char +#define ch_t unsigned char + +/* = = = START-STATIC-FORWARD = = = */ +static void +copy_cooked(ch_t** ppDest, char const ** ppSrc); + +static void +copy_raw(ch_t** ppDest, char const ** ppSrc); + +static token_list_t * +alloc_token_list(char const * str); +/* = = = END-STATIC-FORWARD = = = */ + +static void +copy_cooked(ch_t** ppDest, char const ** ppSrc) +{ + ch_t* pDest = (ch_t*)*ppDest; + const ch_t* pSrc = (const ch_t*)(*ppSrc + 1); + + for (;;) { + ch_t ch = *(pSrc++); + switch (ch) { + case NUL: *ppSrc = NULL; return; + case '"': goto done; + case '\\': + pSrc += ao_string_cook_escape_char((char*)pSrc, (char*)&ch, 0x7F); + if (ch == 0x7F) + break; + /* FALLTHROUGH */ + + default: + *(pDest++) = ch; + } + } + + done: + *ppDest = (ch_t*)pDest; /* next spot for storing character */ + *ppSrc = (char const *)pSrc; /* char following closing quote */ +} + + +static void +copy_raw(ch_t** ppDest, char const ** ppSrc) +{ + ch_t* pDest = *ppDest; + cc_t* pSrc = (cc_t*) (*ppSrc + 1); + + for (;;) { + ch_t ch = *(pSrc++); + switch (ch) { + case NUL: *ppSrc = NULL; return; + case '\'': goto done; + case '\\': + /* + * *Four* escapes are handled: newline removal, escape char + * quoting and apostrophe quoting + */ + switch (*pSrc) { + case NUL: *ppSrc = NULL; return; + case '\r': + if (*(++pSrc) == NL) + ++pSrc; + continue; + + case NL: + ++pSrc; + continue; + + case '\'': + ch = '\''; + /* FALLTHROUGH */ + + case '\\': + ++pSrc; + break; + } + /* FALLTHROUGH */ + + default: + *(pDest++) = ch; + } + } + + done: + *ppDest = pDest; /* next spot for storing character */ + *ppSrc = (char const *) pSrc; /* char following closing quote */ +} + +static token_list_t * +alloc_token_list(char const * str) +{ + token_list_t * res; + + int max_token_ct = 2; /* allow for trailing NULL pointer & NUL on string */ + + if (str == NULL) goto enoent_res; + + /* + * Trim leading white space. Use "ENOENT" and a NULL return to indicate + * an empty string was passed. + */ + str = SPN_WHITESPACE_CHARS(str); + if (*str == NUL) goto enoent_res; + + /* + * Take an approximate count of tokens. If no quoted strings are used, + * it will be accurate. If quoted strings are used, it will be a little + * high and we'll squander the space for a few extra pointers. + */ + { + char const * pz = str; + + do { + max_token_ct++; + pz = BRK_WHITESPACE_CHARS(pz+1); + pz = SPN_WHITESPACE_CHARS(pz); + } while (*pz != NUL); + + res = malloc(sizeof(*res) + (pz - str) + + (max_token_ct * sizeof(ch_t*))); + } + + if (res == NULL) + errno = ENOMEM; + else res->tkn_list[0] = (ch_t*)(res->tkn_list + (max_token_ct - 1)); + + return res; + + enoent_res: + + errno = ENOENT; + return NULL; +} + +/*=export_func ao_string_tokenize + * + * what: tokenize an input string + * + * arg: + char const* + string + string to be tokenized + + * + * ret_type: token_list_t* + * ret_desc: pointer to a structure that lists each token + * + * doc: + * + * This function will convert one input string into a list of strings. + * The list of strings is derived by separating the input based on + * white space separation. However, if the input contains either single + * or double quote characters, then the text after that character up to + * a matching quote will become the string in the list. + * + * The returned pointer should be deallocated with @code{free(3C)} when + * are done using the data. The data are placed in a single block of + * allocated memory. Do not deallocate individual token/strings. + * + * The structure pointed to will contain at least these two fields: + * @table @samp + * @item tkn_ct + * The number of tokens found in the input string. + * @item tok_list + * An array of @code{tkn_ct + 1} pointers to substring tokens, with + * the last pointer set to NULL. + * @end table + * + * There are two types of quoted strings: single quoted (@code{'}) and + * double quoted (@code{"}). Singly quoted strings are fairly raw in that + * escape characters (@code{\\}) are simply another character, except when + * preceding the following characters: + * @example + * @code{\\} double backslashes reduce to one + * @code{'} incorporates the single quote into the string + * @code{\n} suppresses both the backslash and newline character + * @end example + * + * Double quote strings are formed according to the rules of string + * constants in ANSI-C programs. + * + * example: + * @example + * #include <stdlib.h> + * int ix; + * token_list_t* ptl = ao_string_tokenize(some_string) + * for (ix = 0; ix < ptl->tkn_ct; ix++) + * do_something_with_tkn(ptl->tkn_list[ix]); + * free(ptl); + * @end example + * Note that everything is freed with the one call to @code{free(3C)}. + * + * err: + * NULL is returned and @code{errno} will be set to indicate the problem: + * @itemize @bullet + * @item + * @code{EINVAL} - There was an unterminated quoted string. + * @item + * @code{ENOENT} - The input string was empty. + * @item + * @code{ENOMEM} - There is not enough memory. + * @end itemize +=*/ +token_list_t* +ao_string_tokenize(char const* str) +{ + token_list_t* res = alloc_token_list(str); + ch_t* pzDest; + + /* + * Now copy each token into the output buffer. + */ + if (res == NULL) + return res; + + pzDest = (ch_t*)(res->tkn_list[0]); + res->tkn_ct = 0; + + do { + res->tkn_list[ res->tkn_ct++ ] = pzDest; + for (;;) { + int ch = (ch_t)*str; + if (IS_WHITESPACE_CHAR(ch)) { + found_white_space: + str = SPN_WHITESPACE_CHARS(str+1); + break; + } + + switch (ch) { + case '"': + copy_cooked(&pzDest, &str); + if (str == NULL) { + free(res); + errno = EINVAL; + return NULL; + } + if (IS_WHITESPACE_CHAR(*str)) + goto found_white_space; + break; + + case '\'': + copy_raw(&pzDest, &str); + if (str == NULL) { + free(res); + errno = EINVAL; + return NULL; + } + if (IS_WHITESPACE_CHAR(*str)) + goto found_white_space; + break; + + case NUL: + goto copy_done; + + default: + str++; + *(pzDest++) = (unsigned char)ch; + } + } copy_done:; + + /* + * NUL terminate the last token and see if we have any more tokens. + */ + *(pzDest++) = NUL; + } while (*str != NUL); + + res->tkn_list[ res->tkn_ct ] = NULL; + + return res; +} + +#ifdef TEST +#include <stdio.h> +#include <string.h> + +int +main(int argc, char** argv) +{ + if (argc == 1) { + printf("USAGE: %s arg [ ... ]\n", *argv); + return 1; + } + while (--argc > 0) { + char* arg = *(++argv); + token_list_t* p = ao_string_tokenize(arg); + if (p == NULL) { + printf("Parsing string ``%s'' failed:\n\terrno %d (%s)\n", + arg, errno, strerror(errno)); + } else { + int ix = 0; + printf("Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct); + do { + printf(" %3d: ``%s''\n", ix+1, p->tkn_list[ix]); + } while (++ix < p->tkn_ct); + free(p); + } + } + return 0; +} +#endif + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/tokenize.c */ diff --git a/autoopts/tpl/aginfo.tpl b/autoopts/tpl/aginfo.tpl new file mode 100644 index 0000000..01e4e2f --- /dev/null +++ b/autoopts/tpl/aginfo.tpl @@ -0,0 +1,10 @@ +[= AutoGen5 template + +texi + +=] +[= `echo please note that this is obsolete >&2` =][= + +INCLUDE "agtexi-cmd.tpl" + +\=] diff --git a/autoopts/tpl/aginfo3.tpl b/autoopts/tpl/aginfo3.tpl new file mode 100644 index 0000000..6c79e22 --- /dev/null +++ b/autoopts/tpl/aginfo3.tpl @@ -0,0 +1,128 @@ +{+ AutoGen5 template -*- nroff -*- + +texi + +## --------------------------------------------------------------------- +## aginfo3.tpl -- Template for function texi doc +## +## Time-stamp: "2011-02-01 06:38:27 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + ++}{+ + +(out-push-new (sprintf "%s.menu" (base-name))) +(define lib-name (get "library")) +(if (< (string-length lib-name) 1) + (set! lib-name (base-name)) ) +(define node-name (sprintf "lib%s procedures" lib-name)) +(define sec-name (sprintf "lib%s External Procedures" lib-name)) + +(define doc-level (getenv "LEVEL")) +(if (not (string? doc-level)) + (set! doc-level "section")) +(sprintf "* %-28s %s\n" (string-append node-name "::") sec-name) +}{+ +(out-pop) ++}@node {+ (. node-name) +} +@{+ (. doc-level) +} {+ (. sec-name) +} + +{+ + +IF (not (exist? "lib-description")) + ++}These are the publicly exported procedures from the lib@i{{+(. lib-name)+}} +library. Any other functions mentioned in the @i{header} file are +for the private use of the library.{+ + +ELSE +}{+ lib-description +}{+ +ENDIF +} + +@menu{+ + +FOR export-func +}{+ + IF (not (exist? "private")) +} +* lib{+(sprintf "%-24s" (string-append + lib-name "-" (get "name") "::")) + +} {+name +}{+ + + ENDIF private +}{+ + +ENDFOR export-func +} +@end menu + +This {+(. doc-level)+} was automatically generated by AutoGen +using extracted information and the {+(tpl-file)+} template.{+ + +FOR export-func +}{+ + IF (not (exist? "private")) + ++} + +@node lib{+library+}-{+name+} +@{+CASE (. doc-level)+}{+ + = chapter +}{+ + = section +}sub{+ + = subsection +}subsub{+ + ESAC +}section {+name+} +@findex {+name+} + +{+what+} + +@noindent +Usage: +@example +{+ % ret-type "%s res = " ++}{+name+}({+ + IF (exist? "arg") +} {+ + FOR arg ", " +}{+arg-name+}{+ + ENDFOR +} {+ + ENDIF +}); +@end example{+ + IF (or (exist? "arg") (exist? "ret-type")) +} +@noindent +Where the arguments are: +@multitable @columnfractions .05 .15 .20 .55 +@item @tab Name @tab Type @tab Description +@item @tab ----- @tab ----- @tab -------------{+ + FOR arg "\n" +} +@item @tab {+arg-name+} @tab @code{{+arg-type+}} +@tab {+arg-desc+}{+ + ENDFOR+}{+ + IF (exist? "ret-type") +} +@item @tab returns @tab {+ret-type+} +@tab {+ ret-desc +}{+ + + ENDIF +} +@end multitable{+ + + ENDIF ++} + +{+doc+} +{+ % err "\n%s\n" +}{+ + + ENDIF private +}{+ + +ENDFOR export-func + + ++} diff --git a/autoopts/tpl/agman-cmd.tpl b/autoopts/tpl/agman-cmd.tpl new file mode 100644 index 0000000..1ba4908 --- /dev/null +++ b/autoopts/tpl/agman-cmd.tpl @@ -0,0 +1,123 @@ +[+: -*- Mode: nroff -*- + + AutoGen5 template man + +## agman-cmd.tpl -- Template for command line man pages +## +## Time-stamp: "2011-11-18 07:48:17 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +# Produce a man page for section 1, 5 or 8 commands. +# Which is selected via: -DMAN_SECTION=n +# passed to the autogen invocation. "n" may have a suffix, if desired. +# +:+][+: + +(define head-line (lambda() + (sprintf ".TH %s %s \"%s\" \"%s\" \"%s\"\n.\\\"\n" + (get "prog-name") man-sect + (shell "date '+%d %b %Y'") package-text section-name) )) + +(define man-page #t) + +:+][+: + +INCLUDE "cmd-doc.tlib" + +:+] +.\" +.SH NAME +[+: prog-name :+] \- [+: prog-title :+] +[+: + +(out-push-new) :+][+: + +INVOKE build-doc :+][+: + + (shell (string-append + "fn='" (find-file "mdoc2man") "'\n" + "test -f ${fn} || die mdoc2man not found from $PWD\n" + "${fn} <<\\_EndOfMdoc_ || die ${fn} failed in $PWD\n" + (out-pop #t) + "\n_EndOfMdoc_" )) + +:+][+: + +(out-move (string-append (get "prog-name") "." + man-sect)) :+][+: # + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" S Y N O P S I S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-synopsis :+][+: + (out-push-new file-name) \:+] +.SH SYNOPSIS +.B [+: prog-name :+][+: + + IF (. use-flags) :+][+: + IF (exist? "long-opts") :+] +.\" Mixture of short (flag) options and long options +.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \-\-\fIopt\-name\fP[+:# +:+] " [[=| ]\fIvalue\fP]]..."[+: + + ELSE no long options: :+] +.\" Short (flag) options only +.RB [ \-\fIflag\fP " [\fIvalue\fP]]..."[+: + ENDIF + :+][+: + ELIF (exist? "long-opts") + :+] +.\" Long options only +.RB [ \-\-\fIopt\-name\fP [ = "| ] \fIvalue\fP]]..."[+: + + ELIF (not (exist? "argument")) :+] +.RI [ opt\-name "[\fB=\fP" value ]]... +.PP +All arguments are named options.[+: + ENDIF :+][+: + + IF (exist? "argument") + :+] [+: argument :+][+: + + IF (exist? "reorder-args") :+] +.PP +Operands and options may be intermixed. They will be reordered. +[+: ENDIF :+][+: + + ELIF (or (exist? "long-opts") use-flags) + +:+] +.PP +All arguments must be options.[+: + + ENDIF :+][+: + +(if (exist? "explain") + (string-append "\n.PP\n" + (join "\n.PP\n" (stack "explain"))) ) :+][+: + +(out-pop) :+][+: + +ENDDEF mk-synopsis + +agman-cmd.tpl ends here :+] diff --git a/autoopts/tpl/agman.tlib b/autoopts/tpl/agman.tlib new file mode 100644 index 0000000..1a0a322 --- /dev/null +++ b/autoopts/tpl/agman.tlib @@ -0,0 +1,81 @@ +[+: AutoGen5 template -*- shell-script -*- + +null + +:+][+: + +## agman-lib.tpl -- Template for command line man pages +## +## Time-stamp: "2010-07-10 14:28:52 bkorb" +## Author: Jim Van Zandt <jrv@vanzandt.mv.com> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +## This "library" converts texi-isms into man-isms. It gets included +## by the man page template at the point where texi-isms might start appearing +## and then "emit-man-text" is invoked when all the text has been assembled. +## +## Display the command line prototype, +## based only on the argument processing type. +## +## And run the entire output through "sed" to convert texi-isms + +:+][+: + +(out-push-new) + +\:+] +sed \ + -e 's;@code{\([^}]*\)};\\fB\1\\fP;g' \ + -e 's;@var{\([^}]*\)};\\fB\1\\fP;g' \ + -e 's;@samp{\([^}]*\)};\\fB\1\\fP;g' \ + -e 's;@i{\([^}]*\)};\\fI\1\\fP;g' \ + -e 's;@file{\([^}]*\)};\\fI\1\\fP;g' \ + -e 's;@emph{\([^}]*\)};\\fI\1\\fP;g' \ + -e 's;@strong{\([^}]*\)};\\fB\1\\fP;g' \ + -e 's/@\([{}]\)/\1/g' \ + -e 's,^\$\*$,.br,' \ + -e '/@ *example/,/@ *end *example/s/^/ /' \ + -e 's/^ *@ *example/.nf/' \ + -e 's/^ *@ *end *example/.fi/' \ + -e '/^ *@ *noindent/d' \ + -e '/^ *@ *enumerate/d' \ + -e 's/^ *@ *end *enumerate/.br/' \ + -e '/^ *@ *table/d' \ + -e 's/^ *@ *end *table/.br/' \ + -e 's/^@item \(.*\)/.sp\ +.IR "\1"/' \ + -e 's/^@item/.sp 1/' \ + -e 's/\*\([a-zA-Z0-9:~=_ -]*\)\*/\\fB\1\\fP/g' \ + -e 's/``\([a-zA-Z0-9:~+=_ -]*\)'"''"'/\\(lq\1\\(rq/g' \ + -e "s/^'/\\'/" \ + -e 's/^@\*/.br/' \ + -e 's/ -/ \\-/g;s/^\.in \\-/.in -/' <<'_End_Of_Man_' +[+: + +DEFINE emit-man-text :+] +_End_Of_Man_[+: + +(shell (out-pop #t) ) :+][+: + +ENDDEF emit-man-text :+][+: # + +agman-lib.tpl ends here :+] diff --git a/autoopts/tpl/agman1.tpl b/autoopts/tpl/agman1.tpl new file mode 100644 index 0000000..95e2a9c --- /dev/null +++ b/autoopts/tpl/agman1.tpl @@ -0,0 +1,10 @@ +[+: -*- Mode: nroff -*- + +AutoGen5 template man=%s.1 + +:+] +[+: `echo please note that this is obsolete >&2` :+][+: + +INCLUDE "agman-cmd.tpl" + +\:+] diff --git a/autoopts/tpl/agman3.tpl b/autoopts/tpl/agman3.tpl new file mode 100644 index 0000000..6837c00 --- /dev/null +++ b/autoopts/tpl/agman3.tpl @@ -0,0 +1,142 @@ +{+ AutoGen5 template -*- nroff -*- + +null + +## agman3.tpl -- Template for command line man pages +## +## Time-stamp: "2011-02-24 10:39:17 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + ++}{+ + +(define see-also "") +(if (exist? "see-also") + (set! see-also (string-append (get "see-also") " ")) ) + ++}{+ + +FOR export-func +}{+ + (if (not (exist? "private")) + (set! see-also (string-append see-also + (get "name") "(3) " )) ) + +}{+ + +ENDFOR export-func +}{+ + + +FOR export-func +}{+ + IF (not (exist? "private")) +}{+ + + (out-push-new (string-append + (get "name") ".3" )) + ++}.TH {+name+} 3 {+ `date +%Y-%m-%d` +} "" "Programmer's Manual" +{+ + +;; The following "dne" argument is a string of 5 characters: +;; '.' '\\' '"' and two spaces. It _is_ hard to read. " +;; +(dne ".\\\" ") + ++} +.SH NAME +{+name+} - {+what+} +.sp 1 +.SH SYNOPSIS +{+IF (exist? "header") +} +#include <\fI{+header+}\fP> +.br{+ + ENDIF+} +cc [...] -o outfile infile.c -l\fB{+library+}\fP [...] +.sp 1 +{+ ?% ret-type "%s" void ++} \fB{+name+}\fP({+ + IF (not (exist? "arg")) +}void{+ + ELSE +}{+ + FOR arg ", " +}{+arg-type+} \fI{+arg-name+}\fP{+ + ENDFOR arg +}{+ + ENDIF +}); +.sp 1 +.SH DESCRIPTION +{+ + INCLUDE "agman.tlib" ++}{+ +(get "doc") +}{+ + IF (exist? "arg") +}{+ + FOR arg +} +.TP +.IR {+ arg-name +} +{+ arg-desc +}{+ + + ENDFOR arg +}{+ + ENDIF arg exists +}{+ + + IF (exist? "ret-type") +} +.sp 1 +.SH RETURN VALUE +{+ret-desc+}{+ + + ENDIF +}{+ + + IF (exist? "err") +} +.sp 1 +.SH ERRORS +{+ err +}{+ + + ENDIF +}{+ + + IF (exist? "example") +} +.sp 1 +.SH EXAMPLES +.nf +.in +5 +{+ example +} +.in -5 +.fi{+ + + ENDIF +}{+ + +emit-man-text + ++} +.SH SEE ALSO +The \fIinfo\fP documentation for the -l\fI{+library+}\fP library. +.br +{+ +(define tmp-txt (get "see")) +(if (> (string-length see-also) 0) + (set! tmp-txt (string-append see-also ", " tmp-txt)) ) + +(shellf "echo '%s' | \ +sed 's@%s(3) @@;s/3) $/3)/;s/(3) /(3), /g;s/, *,/,/g;s/^, *//'" + tmp-txt (get "name")) +} +{+ + + (out-pop) +}{+ + + ENDIF private +}{+ + +ENDFOR export-func + + ++} diff --git a/autoopts/tpl/agmdoc-cmd.tpl b/autoopts/tpl/agmdoc-cmd.tpl new file mode 100644 index 0000000..be8af95 --- /dev/null +++ b/autoopts/tpl/agmdoc-cmd.tpl @@ -0,0 +1,115 @@ +[+: -*- Mode: nroff -*- + + AutoGen5 template mdoc + +## agman-cmd.tpl -- Template for command line mdoc pages +## +## Time-stamp: "2011-11-18 07:48:29 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +# Produce a man page for section 1, 5 or 8 commands. +# Which is selected via: -DMAN_SECTION=n +# passed to the autogen invocation. "n" may have a suffix, if desired. +# +:+][+: + +(define head-line (lambda() (string-append + ".Dd " (shell "date '+%B %e %Y' | sed 's/ */ /g'") + "\n.Dt " UP-PROG-NAME " " man-sect " " section-name + "\n.Os " (shell "uname -sr") "\n") )) + +(define man-page #f) + +:+][+: + +INCLUDE "cmd-doc.tlib" + +:+] +.Sh NAME +.Nm [+: prog-name :+] +.Nd [+: prog-title :+] +[+: INVOKE build-doc :+][+: + +(out-move (string-append (get "prog-name") "." + man-sect)) :+][+:# + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" S Y N O P S I S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-synopsis :+][+: + (out-push-new file-name) \:+] +.Sh SYNOPSIS +.Nm[+: + + IF (. use-flags) :+][+: + IF (exist? "long-opts") :+] +.\" Mixture of short (flag) options and long options +.Op Fl flags +.Op Fl flag Ar value +.Op Fl \-option-name Ar value +[+: ELSE no long options: :+] +.Op Fl flags +.Op Fl flag Ar value +[+: ENDIF + :+][+: + ELIF (exist? "long-opts") + :+] +.Op Fl \-option-name +.Op Fl \-option-name Ar value +[+: + + ELIF (not (exist? "argument")) :+] +.Op Ar option\-name Ar value +.Pp +All arguments are named options. +[+: + ENDIF :+][+: + + IF (exist? "argument") :+][+: + argument :+][+: + + IF (exist? "reorder-args") :+] +.Pp +Operands and options may be intermixed. They will be reordered. +[+: ENDIF :+][+: + + ELIF (or (exist? "long-opts") use-flags) + +:+] +.Pp +All arguments must be options. +[+: + + ENDIF :+] +.Pp +[+: + +FOR explain "\n.Pp\n" :+][+: + explain :+][+: +ENDFOR :+][+: + +(out-pop) :+][+: + +ENDDEF mk-synopsis + +agmdoc-cmd.tpl ends here :+] diff --git a/autoopts/tpl/agpl.lic b/autoopts/tpl/agpl.lic new file mode 100644 index 0000000..99661e4 --- /dev/null +++ b/autoopts/tpl/agpl.lic @@ -0,0 +1,19 @@ +<PFX>Copyright (C) <years> <owner>, all rights reserved. +<PFX>This is free software. It is licensed for use, modification and +<PFX>redistribution under the terms of the +<PFX>GNU Affero GPL, version 3 or later <http://gnu.org/licenses/gpl.html> + +<PFX><program> is free software: you can redistribute it and/or modify it +<PFX>under the terms of the GNU General Public License as published by the +<PFX>Free Software Foundation, either version 3 of the License, or +<PFX>(at your option) any later version. +<PFX> +<PFX><program> is distributed in the hope that it will be useful, but +<PFX>WITHOUT ANY WARRANTY; without even the implied warranty of +<PFX>MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +<PFX>See the GNU Affero General Public License for more details. +<PFX> +<PFX>You should have received a copy of the GNU Affero General Public License +<PFX>along with this program. If not, see <http://www.gnu.org/licenses/>. + +GNU Affero GPL, version 3 or later diff --git a/autoopts/tpl/agtexi-cmd.tpl b/autoopts/tpl/agtexi-cmd.tpl new file mode 100644 index 0000000..75330a0 --- /dev/null +++ b/autoopts/tpl/agtexi-cmd.tpl @@ -0,0 +1,894 @@ +[= AutoGen5 template -*- Mode: texinfo -*- + +texi + +# Documentation template +# +# Time-stamp: "2012-08-11 08:33:08 bkorb" +# Author: Bruce Korb <bkorb@gnu.org> +# +# This file is part of AutoOpts, a companion to AutoGen. +# AutoOpts is free software. +# AutoOpts is Copyright (c) 1992-2012 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 md5sums: +# +# 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +# 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +# 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= + +INVOKE initialization =][= + +(out-push-new (string-substitute (out-name) ".texi" ".menu")) + +(ag-fprintf 0 "* %-32s Invoking %s\n" + (string-append program-name " Invocation::") + program-name ) + +(out-pop) +(if (exist? "explain") + (emit (string-append "\n" (get "explain") "\n")) ) +(set! tmp-str (get "option-doc-format" "texi")) +(divert-convert tmp-str) + +=][= + +IF (match-value? == "doc-section.ds-type" "DESCRIPTION") =][= + + FOR doc-section =][= + IF (== (get "ds-type") "DESCRIPTION") =][= + (define cvt-fn (get "ds-format" "texi")) + (if (not (== cvt-fn "texi")) + (divert-convert cvt-fn) ) =][= + (emit (string-append "\n" (get "ds-text") "\n")) + (convert-divert) =][= + BREAK =][= + + ENDIF =][= + ENDFOR =][= + +ELSE =][= + +(join "\n\n" + (if (exist? "prog-info-descrip") + (stack "prog-info-descrip") + (if (exist? "prog-man-descrip") + (stack "prog-man-descrip") + (if (exist? "prog-descrip") + (stack "prog-descrip") + (stack "detail") +) ) ) ) =][= + +ENDIF =][= + +(convert-divert) =] + +This [=(string-downcase doc-level)=] was generated by @strong{AutoGen}, +using the @code{agtexi-cmd} template and the option descriptions for the [=(. +coded-prog-name)=] program.[= (name-copyright) =] + +@menu +[= + (out-push-new) (out-suspend "menu") + (out-push-new) =][= + +INVOKE emit-usage-opt =][= + +;; FOR all options, ... +;; +(define opt-name "") +(define extra-ct 0) +(define extra-text "") +(define optname-from "A-Z_^") +(define optname-to "a-z--") +(define invalid-doc "* INVALID *") +(if (exist? "preserve-case") (begin + (set! optname-from "_^") + (set! optname-to "--") )) +(if (and have-doc-options (not (exist? "flag[].documentation"))) (begin + (ag-fprintf "menu" menu-entry-fmt + "base-options:: " "Base options") + (print-node opt-name "Base options") +) ) + +=][=# + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +FOR flag =][= + + (set! opt-name (string-tr! (get "name") optname-from optname-to)) + (if (exist? "documentation") + (begin + (set! label-str (string-append opt-name " options")) + (ag-fprintf "menu" menu-entry-fmt + (string-append opt-name ":: ") label-str) + (print-node opt-name label-str) + (ag-fprintf 0 "\n%s." (get "descrip")) + (set! tmp-str (get "documentation")) + (if (> (string-length tmp-str) 1) + (ag-fprintf 0 "\n%s" tmp-str)) + ) + (begin + (set! tmp-str (get "doc" invalid-doc)) + (if (< 0 (string-length tmp-str)) (begin + (set! label-str (string-append opt-name " option" + (if (exist? "value") + (string-append " (-" (get "value") ")") + "" ) )) + (if have-doc-options + (ag-fprintf 0 opt-node-fmt opt-name label-str) + (begin + (ag-fprintf "menu" menu-entry-fmt + (string-append opt-name ":: ") label-str) + (print-node opt-name label-str) + ) + ) + (ag-fprintf 0 "\n@cindex %s-%s" down-prog-name opt-name) + ) ) + ) + ) =][= + + IF (and (not (exist? "documentation")) + (< 0 (string-length tmp-str)) ) + =][= + IF (exist? "aliases") =][= + INVOKE emit-aliases =][= + ELSE =][= + INVOKE emit-opt-text =][= + ENDIF =][= + ENDIF =][= + +ENDFOR flag =][= + +IF + (define home-rc-files (exist? "homerc")) + (define environ-init (exist? "environrc")) + (or home-rc-files environ-init) + =][= + + INVOKE emit-presets =][= + +ENDIF =][= + +INVOKE emit-exit-status =][= +INVOKE emit-doc-sections =][= + +(out-suspend "opt-desc") +(out-resume "menu") +(emit (out-pop #t)) +(emit "@end menu\n") +(out-resume "opt-desc") +(out-pop #t) =][=# + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-doc-sections =][= + +FOR doc-section =][= + + IF (define opt-name (string-capitalize! (get "ds-type"))) + (or (== opt-name "Exit Status") + (== opt-name "Description") + (exist? "omit-texi")) =][= + CONTINUE =][= + ENDIF =][= + + (ag-fprintf "menu" menu-entry-fmt (string-append opt-name "::") opt-name) + (set! label-str (string-append + down-prog-name " " (string-capitalize opt-name))) + (print-node opt-name label-str) + (define cvt-fn (get "ds-format" "texi")) + (if (not (== cvt-fn "texi")) + (divert-convert cvt-fn) ) =][= + (emit (string-append "\n" (get "ds-text") "\n")) + (convert-divert) =][= + +ENDFOR doc-section =][= + +ENDDEF emit-doc-sections + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-exit-status =][= + (ag-fprintf "menu" menu-entry-fmt "exit status::" "exit status") + (print-node "exit status" (string-append program-name " exit status")) =] + +One of the following exit values will be returned: +@table @samp +@item 0 (EXIT_[= + (set! tmp-str (get "exit-name[0]" "SUCCESS")) + (string-upcase (string->c-name! tmp-str)) + =]) +[= + (define need-ex-noinput (exist? "homerc")) + (define need-ex-software #t) + (get "exit-desc[0]" "Successful program execution.")=] +@item 1 (EXIT_[= + + (set! tmp-str (get "exit-name[1]" "FAILURE")) + (string-upcase (string->c-name! tmp-str))=]) +[= (get "exit-desc[1]" + "The operation failed or the command syntax was not valid.") =][= + +FOR exit-desc (for-from 2) =][= + (if (= (for-index) 66) + (set! need-ex-noinput #f) + (if (= (for-index) 70) + (set! need-ex-software #f) )) + (set! tmp-str (get (sprintf "exit-name[%d]" (for-index)) "* unnamed *")) + (sprintf "\n@item %d (EXIT_%s)\n%s" (for-index) + (string-upcase (string->c-name! tmp-str)) + (get (sprintf "exit-desc[%d]" (for-index)))) + =][= +ENDFOR exit-desc =][= + +(if need-ex-noinput + (emit "\n@item 66 (EX_NOINPUT) +A specified configuration file could not be loaded.")) + +(if need-ex-noinput + (emit "\n@item 70 (EX_SOFTWARE) +libopts had an internal operational error. Please report +it to autogen-users@@lists.sourceforge.net. Thank you.")) +=] +@end table[= + +ENDDEF emit-exit-status + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-aliases =] + +This is an alias for the [= aliases =] option, +[= (sprintf "@pxref{%1$s %2$s, the %2$s option documentation}.\n" + down-prog-name (get "aliases")) =][= + +ENDDEF emit-aliases + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-opt-text =] + +This is the ``[=(string-downcase! (get "descrip"))=]'' option.[= + IF (exist? "arg-type") =] +This option takes an [= (if (exist? "arg-optional") "optional " "") + =]argument [= arg-type =][= +(if (exist? "arg-name") (string-append " @file{" + (string-substitute (get "arg-name") "@" "@@") "}")) + =].[= + ENDIF =][= + + (set! extra-ct 0) + (out-push-new) =][= + + IF (exist? "min") =]@item +is required to appear on the command line. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "max") =]@item +may appear [= + IF % max (== "%s" "NOLIMIT") + =]an unlimited number of times[= + ELSE + =]up to [=max=] times[= + ENDIF=]. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "enabled") =]@item +is enabled by default. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "ifdef") =]@item +must be compiled in by defining @code{[=(get "ifdef") + =]} during the compilation. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF =][= + + IF (exist? "ifndef") =]@item +must be compiled in by @strong{un}-defining @code{[=(get "ifndef") + =]} during the compilation. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "no_preset") =]@item +may not be preset with environment variables or configuration (rc/ini) files. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "equivalence") =]@item +is a member of the [=equivalence=] class of options. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "flags_must") =]@item +must appear in combination with the following options: +[= FOR flags_must ", " =][=flags_must=][= + ENDFOR=]. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (exist? "flags_cant") =]@item +must not appear in combination with any of the following options: +[= FOR flags_cant ", " =][=flags_cant=][= + ENDFOR=]. +[= (set! extra-ct (+ extra-ct 1)) =][= + ENDIF=][= + + IF (~* (get "arg-type") "key|set") =]@item +This option takes a keyword as its argument[= + + CASE arg-type =][= + =* key =][= (set! extra-ct (+ extra-ct 1)) =]. +The argument sets an enumeration value that can be tested by comparing[= + + =* set =][= (set! extra-ct (+ extra-ct 1)) =] list. +Each entry turns on or off membership bits. These bits can be tested +with bit tests against[= + ESAC arg-type =] the option value macro ([= +(string-upcase (string-append +(if (exist? "prefix") (string-append (get "prefix") "_") "") +"OPT_VALUE_" (get "name") )) =]). +The available keywords are: +@example +[= (shell (string-append + "${CLexe:-columns} -I4 --spread=1 -W50 <<\\" heredoc-marker + (join "\n" (stack "keyword") "\n") + heredoc-marker + ) ) =] +@end example +[= + + IF (=* (get "arg-type") "key") =] +or their numeric equivalent.[= + ENDIF =][= + + ENDIF key/set arg =][= + + IF (> extra-ct 0) =][= + (set! extra-text (out-pop #t)) =] + +@noindent +This option has some usage constraints. It: +@itemize @bullet +[=(. extra-text) +=]@end itemize +[= ELSE =][= + (out-pop) =][= + ENDIF =][= + +?% doc "\n%s" "\nThis option has no @samp{doc} documentation." =][= + IF (exist? "deprecated") =] + +@strong{NOTE: THIS OPTION IS DEPRECATED}[= + + ENDIF =][= + +ENDDEF emit-opt-text + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE set-home-rc-vars =][= + CASE homerc =][= + ==* '$@' =][= + (set! explain-pkgdatadir #t) + (set! cfg-file-name (string-substitute (get "homerc") + "$@" "$(pkgdatadir)")) =][= + + == '.' =][= + (set! cfg-file-name "$PWD") + (set! env-var-list (string-append env-var-list "PWD, ")) + =][= + + ==* './' =][= + (set! explain-pkgdatadir #t) + (set! env-var-list (string-append env-var-list "PWD, ")) + (set! cfg-file-name (string-append "$PWD" (substring (get "homerc") 1))) + =][= + + ~~* '\$[A-Za-z]' =][= + (set! cfg-file-name (get "homerc")) + (set! env-var-list (string-append env-var-list + (shellf "echo '%s' | sed 's/^.//;s#/.*##'" cfg-file-name) + ", " )) + =][= + + == "" =][= (set! cfg-file-name "") =][= + + * =][= + (set! cfg-file-name (get "homerc")) =][= + ESAC =][= + +ENDDEF set-home-rc-vars + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-multiple-rc \=] +[= + (define explain-pkgdatadir #f) + (define env-var-list "") + rc-count =] places for configuration files: +@itemize @bullet[= +FOR homerc =][= + INVOKE set-home-rc-vars =][= + (if (> (string-length cfg-file-name) 0) + (sprintf "\n@item\n%s" cfg-file-name )) + =][= + +ENDFOR homerc =] +@end itemize[= + (if explain-pkgdatadir (ag-fprintf 0 +"\nThe value for @code{$(pkgdatadir)} is recorded at package configure time +and replaced by @file{libopts} when @file{%s} runs." program-name)) + +(if (> (string-length env-var-list) 1) + (shell (string-append +"list='@code{'`echo '" env-var-list "' | \ + sed -e 's#, $##' \ + -e 's#, #}, @code{#g' \ + -e 's#, \\([^ ][^ ]*\\)$#, and \\1#'`\\} +echo +echo 'The environment variables' ${list} +echo 'are expanded and replaced when @file{" program-name "} runs.'" +)) ) =] +For any of these that are plain files, they are simply processed. +For any that are directories, then a file named @file{[= + (if (exist? "rcfile") (get "rcfile") + (string-append "." program-name "rc"))=]} is searched for +within that directory and processed. +[= + +ENDDEF emit-multiple-rc + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-one-rc-dir =][= + (define env-var-list "") + (define explain-pkgdatadir #f) =][= + INVOKE set-home-rc-vars + +=]@file{[=(. cfg-file-name) =]} for configuration (option) data.[= + IF (. explain-pkgdatadir) =] +The value for @code{$(pkgdatadir)} is recorded at package configure time +and replaced by @file{libopts} when @file{[=prog-name=]} runs. +[=ENDIF=][= +(if (> (string-length env-var-list) 1) + (sprintf +"\nThe environment variable @code{%s} is expanded and replaced when +the program runs" env-var-list)) =] +If this is a plain file, it is simply processed. +If it is a directory, then a file named @file{[= +(if (exist? "rcfile") (get "rcfile") + (string-append "." program-name "rc")) +=]} is searched for within that directory.[= + +ENDDEF emit-one-rc-dir + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-rc-file-info =] + +@noindent +@code{libopts} will search in [= + + IF (define rc-count (count "homerc")) + (define cfg-file-name "") + (> rc-count 1) =][= + + INVOKE emit-multiple-rc =][= + + ELSE =][= + INVOKE emit-one-rc-dir =][= + ENDIF (> rc-count 1) + +=] + +Configuration files may be in a wide variety of formats. +The basic format is an option name followed by a value (argument) on the +same line. Values may be separated from the option name with a colon, +equal sign or simply white space. Values may be continued across multiple +lines by escaping the newline with a backslash. + +Multiple programs may also share the same initialization file. +Common options are collected at the top, followed by program specific +segments. The segments are separated by lines like: +@example +[[=(. UP-PROG-NAME)=]] +@end example +@noindent +or by +@example +<?program [= prog-name =]> +@end example +@noindent +Do not mix these styles within one configuration file. + +Compound values and carefully constructed string values may also be +specified using XML syntax: +@example +<option-name> + <sub-opt>...<...>...</sub-opt> +</option-name> +@end example +@noindent +yielding an @code{option-name.sub-opt} string value of +@example +"...<...>..." +@end example +@code{AutoOpts} does not track suboptions. You simply note that it is a +hierarchicly valued option. @code{AutoOpts} does provide a means for searching +the associated name/value pair list (see: optionFindValue).[= + +ENDDEF emit-rc-file-info + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-presets =] + +[= + (ag-fprintf "menu" menu-entry-fmt "config::" + (string-append "presetting/configuring " down-prog-name) ) + + (print-node "config" + (string-append "presetting/configuring " program-name) ) =] + +Any option that is not marked as @i{not presettable} may be preset by +loading values from [= + +IF + + (if home-rc-files (emit + "configuration (\"rc\" or \"ini\") files")) + + environ-init + + =][= + (if home-rc-files (emit ", and values from ")) + =]environment variables named @code{[=(. UP-PROG-NAME)=]} and @code{[= +(. UP-PROG-NAME)=]_<OPTION_NAME>}. @code{<OPTION_NAME>} must be one of +the options listed above in upper case and segmented with underscores. +The @code{[=(. UP-PROG-NAME)=]} variable will be tokenized and parsed like +the command line. The remaining variables are tested for existence and their +values are treated like option arguments[= + ENDIF have environment inits =]. +[= + + IF (. home-rc-files) =][= + INVOKE emit-rc-file-info =][= + ENDIF home-rc-files =] + +The command line options relating to configuration and/or usage help are: +[= + +IF (exist? "version") =] +@[= (. head-level) =] version[= (flag-string "version-value" "v") =] + +Print the program version to standard out, optionally with licensing +information, then exit 0. The optional argument specifies how much licensing +detail to provide. The default is to print [= +(if (exist? "gnu-usage") "the license name with the version" "just the version") +=]. The licensing infomation may be selected with an option argument. Only the +first letter of the argument is examined: + +@table @samp +@item version +Only print the version.[= +(if (not (exist? "gnu-usage")) " This is the default.")=] +@item copyright +Name the copyright usage licensing terms.[= +(if (exist? "gnu-usage") " This is the default.")=] +@item verbose +Print the full copyright usage licensing terms. +@end table +[= +ENDIF version =][= + +IF (exist? "usage-opt") =] +@[= (. head-level) =] usage[= (flag-string "usage-value" "u") =] + +Print abbreviated usage to standard out, then exit 0. +[= +ENDIF usage-opt =][= + +IF (exist? "vendor-opt") =] +@[= (. head-level) =] vendor-option (-W) + +Options that do not have flag values specified must be specified with +@code{-W} and the long option name. That long name is the argument to +this option. Any options so named that require an argument must have +that argument attached to the option name either with quoting or an +equal sign. +[= +ENDIF vendor-opt =][= + +IF (exist? "resettable") =] +@[= (. head-level) =] reset-option[= (flag-string "reset-value" "R") =] + +Resets the specified option to the compiled-in initial state. +This will undo anything that may have been set by configuration files. +The option argument may be either the option flag character or its long name. +[= +ENDIF resettable =][= + +IF (exist? "home-rc") =][= + IF (exist? "disable-save") =] +@[= (. head-level) =] save-opts[= (flag-string "save-opts-value" ">") =] + +Saves the final, configured option state to the specified file (the optional +option argument). If no file is specified, then it will be saved to the +highest priority (last named) @file{rc-file} in the search list. +[= + ENDIF disable-save =][= + + IF (exist? "disable-load") =] +@[= (. head-level) =] load-opts[= (flag-string "load-opts-value" "<") =] + +Loads the named configuration file. +[= + ENDIF disable-load =][= +ENDIF home-rc =][= + +ENDDEF emit-presets + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE header \=] +\input texinfo +@c -*-texinfo-*- +@c %**start of header +@setfilename [= (string-append down-prog-name ".info") =] +@settitle [= (sprintf (if (exist? "package") "%2$s - %1$s" "%s") + (get "package") (get "prog-title")) =] +@c %**end of header +@setchapternewpage off +@titlepage +@sp 10 +@comment The title is printed in a large font. +@center @titlefont{Sample Title} + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +[= (name-copyright) =][= +IF (exist? "copyright.type") =] +[= (license-full (get "copyright.type") program-name "" + (get "copyright.owner" (get "copyright.author" "")) + (get "copyright.date") ) =][= +ENDIF =] +@end titlepage +@node Top, [= prog-name =] usage, , (dir) +@top [= prog-title =] +[= + +ENDDEF header + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-usage-opt =][= + + (define label-str (string-append + program-name " help/usage (@option{" help-opt "})")) + (ag-fprintf "menu" menu-entry-fmt "usage::" label-str) + (sprintf node-fmt "usage" label-str) =] +@cindex [=(. down-prog-name)=] help + +This is the automatically generated usage text for [= prog-name =]. + +The text printed is the same whether selected with the @code{help} option +(@option{[= (. help-opt) =]}) or the @code{more-help} option (@option{[= +(. more-help-opt) =]}). @code{more-help} will print +the usage text by passing it through a pager program. +@code{more-help} is disabled on platforms without a working +@code{fork(2)} function. The @code{PAGER} environment variable is +used to select the program, defaulting to @file{more}. Both will exit +with a status code of 0. + +@exampleindent 0 +@example +[= (out-push-new) =] +prog_name=[= (. program-name) =] +PROG=./${prog_name} +test -f ${PROG} || { + PROG=`echo $PROG | tr '[A-Z]' '[a-z]'` + test -f ${PROG} || PROG=`echo $PROG | tr x_ x-` +} +if [ ! -f ${PROG} ] +then + if [= (string-append program-name " " help-opt) =] > /dev/null 2>&1 + then PROG=`command -v ${prog_name}` + else PROG="echo ${prog_name} is unavailable - no " + fi +fi +${PROG} [=(. help-opt)=] 2>&1 | \ + sed -e "s/USAGE: lt-${prog_name} /USAGE: ${prog_name} /" \ + -e 's/@/@@/g;s/{/@{/g;s/}/@}/g' \ + -e 's/ / /g' +[= (shell (out-pop #t)) =] +@end example +@exampleindent 4 +[= + +ENDDEF emit-usage-opt + +@c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE initialization =][= + + ;;# START-BUILDTREE-ISMS + ;; + (shell "CLexe=${AGexe%/agen5/*}/columns/columns + test -x \"${CLexe}\" || { + CLexe=${AGexe%/autogen}/columns + test -x \"${CLexe}\" || die 'columns program is not findable' + }") + +=][= # END-BUILDTREE-ISMS + + (shell "CLexe=${AGexe%/autogen}/columns") + +# END-INSTALL-ONLY-CODE =][= + + ;; divert-convert divert text for conversion to .texi format + ;; convert-divert convert the diversion done with divert-convert + ;; + (define divert-convert (lambda (diversion-type) (begin + (set! was-diverted + (not (or (== diversion-type "texi") (== diversion-type "")))) + (if was-diverted (begin + (set! cvt-script + (find-file (string-append diversion-type "2texi"))) + (if (not (defined? 'cvt-script)) + (error (sprintf "unknown source format type: %s" diversion-type)) ) + (out-push-new) )) ))) + + (define heredoc-marker "_Unlikely_Here_Doc_Marker_\n") + (define convert-divert (lambda () + (if was-diverted (shell (string-append + cvt-script "<<\\" heredoc-marker (out-pop #t) "\n" heredoc-marker + )) ))) + + (define was-diverted #f) + (define diversion-type "") + (define cvt-script "") + (define tmp-str "") + + (define name-copyright (lambda () + (if (exist? "copyright") + (string-append "\nThis software is released under " + (license-name (get "copyright.type" "an unknown copyright")) + "." ) ) )) + + (make-tmp-dir) + (define program-name (get "prog-name")) + (define down-prog-name (string-downcase program-name)) + (define UP-PROG-NAME (string-upcase program-name)) + (shellf "export AG_DEF_PROG_NAME=%s" program-name) + (define doc-level (getenv "LEVEL")) + (if (not (string? doc-level)) + (set! doc-level "section")) + (define file-name (string-append down-prog-name ".texi")) + (define coded-prog-name (string-append "@code{" down-prog-name "}")) + + (define replace-prog-name (lambda (nm) + (string-substitute (get nm) down-prog-name coded-prog-name ) )) + + (define have-doc-options (exist? "flag.documentation")) + (define print-menu #t) + (define do-doc-nodes #f) + (define menu-entry-fmt (string-append + "* " down-prog-name " %-24s %s\n")) + (define emit-menu-entry (lambda (is-doc) (not is-doc))) + (if have-doc-options + (set! emit-menu-entry (lambda (is-doc) is-doc)) ) + (define chk-flag-val (exist? "flag.value")) + (define flag-string (lambda (v-nm v-df) (if (not chk-flag-val) "" + (string-append " (-" + (if (exist? v-nm) (get v-nm) v-df) + ")") ))) + + (define help-opt "") + (if (exist? "long-opts") + (set! help-opt "--help") + (if (not (exist? "flag.value")) + (set! help-opt "help") + (if (not (exist? "help-value")) + (set! help-opt "-?") + (begin + (set! tmp-str (get "help-value")) + (if (> (string-length tmp-str) 0) + (set! help-opt (string-append "-" tmp-str)) + (set! help-opt "--help") + ) ) + ))) + + (define more-help-opt "") + (if (exist? "long-opts") + (set! more-help-opt "--more-help") + (if (not (exist? "flag.value")) + (set! more-help-opt "more-help") + (if (not (exist? "more-help-value")) + (set! more-help-opt "-!") + (begin + (set! tmp-str (get "more-help-value")) + (if (> (string-length tmp-str) 0) + (set! help-opt (string-append "-" tmp-str)) + (set! help-opt "--more-help") + ) ) + ))) + + =][= + + CASE (. doc-level) =][= + == document =][= INVOKE header =][= + (define sub-level "chapter") + (define head-level "heading") =][= + == chapter =][= + (define sub-level "section") + (define head-level "subheading") =][= + == section =][= + (define sub-level "subsection") + (define head-level "subsubheading") =][= + == subsection =][= + (define sub-level "subsubsection") + (define head-level "subsubheading") =][= + + * =][=(error (sprintf "invalid doc level: %s\n" doc-level)) =][= + + ESAC doc level =][= + + (define node-fmt (string-append + "\n@node " down-prog-name " %s\n@" sub-level " %s")) + (define print-node (lambda (a b) (ag-fprintf 0 node-fmt a b) )) + + (define opt-node-fmt (if have-doc-options + (string-append "\n@" head-level + " %2$s.\n@anchor{" down-prog-name " %1$s}") + node-fmt + )) + + (define exit-sts-fmt "\n\n@node %1$s %2$s\n@%3$s %1$s %2$s\n") + =][= + + IF (not (== doc-level "document")) =][= + (set! file-name (string-append "invoke-" file-name)) + \=] +@node [= prog-name =] Invocation +@[=(. doc-level) =] Invoking [= prog-name =] +@pindex [= prog-name =] +@cindex [= prog-title =][= + +FOR concept =] +@cindex [= concept =][= +ENDFOR =][= + + ENDIF document component + +=] +@ignore +[= + +(out-move file-name) +(dne "# " "# ") + +=] +@end ignore +[= + +ENDDEF initialization + +@c agtexi-cmd.tpl ends here =] diff --git a/autoopts/tpl/bits.tpl b/autoopts/tpl/bits.tpl new file mode 100644 index 0000000..6de0458 --- /dev/null +++ b/autoopts/tpl/bits.tpl @@ -0,0 +1,721 @@ +[= AutoGen5 Template -*- Mode: C -*- + +h +c + +#!/bin/sh + +## Time-stamp: "2011-12-30 08:28:20 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + + (define base-name "") + (define BASE-NAME "") + (define element-type "") + (define init-done #f) + (define is-64-bit #f) + (define is-array #f) + (define name-width 0) + (define desc-width 0) + (define bit-list "") + (define bit-name "") + (define tmp-name "") + + (define id-name (lambda (sfx) + (string-append + prefix "_" (string-upcase! (string->c-name! (get "b-name"))) sfx + ) )) + + (define mask-name (lambda (sfx) + (string-append + prefix "_" (string-upcase! (string->c-name! (get "m-name"))) sfx + ) )) + +=][= + +INVOKE preamble + +=][= + +CASE (suffix) =][= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +== h + +=] +[= + (shell "sedcmd='s/$/_val} +/;s/^/${/'") + (make-header-guard "bit_mask") =] +#include [= (if (exist? "stdint-hdr") + (string-append "\"" (get "stdint-hdr") "\"") + "<stdint.h>" ) =] + +typedef [= + + (define type-name (string-append base-name "_bits_t")) + (define tmp + (if (< (high-lim "bit") 32) (begin + (set! element-type "uint32_t") + "uint32_t %s_bits_t") + (if (< (high-lim "bit") 64) (begin + (set! element-type "uint64_t") + (set! is-64-bit #t) + "uint64_t %s_bits_t" ) + (begin + (set! element-type "uint32_t") + (set! is-array #t) + (sprintf "uint32_t %%s_bits_t[%s]" + (shellf "mask_ct=`calc '( %d + 32 ) / 32'` ; echo $mask_ct" + (high-lim "bit")) ) )) )) + + (sprintf tmp base-name) + +=]; +typedef enum {[= + +FOR bit =][= + + (set! bit-name (string->c-name! (get "b-name"))) + (shellf + "%1$s_val=`calc '2 ^ %2$d'`\nmask_val=`calc \"${mask_val} + ${%1$s_val}\"`" + bit-name (for-index)) + + (set! tmp (string-length bit-name)) + (if (> tmp name-width) + (set! name-width tmp)) + (set! tmp (string-length (get "b-what"))) + (if (> tmp desc-width) + (set! desc-width tmp)) =][= + +ENDFOR bit =][= + + (define define-width (+ name-width 6 (string-length prefix))) + (define enum-fmt (sprintf "\n %%-%ds =%%4d%%s /* %%-%ds */" + define-width desc-width)) + +=][= + +FOR bit =][= + + (sprintf enum-fmt (id-name "_ID") (for-index) + (if (last-for?) " " ",") (get "b-what")) =][= +ENDFOR bit + += = = = = = = = = = = = = = = = =][= + +IF (ag-fprintf 0 "\n} %s_enum_t;\n" base-name) + (define def-fmt (sprintf "\n#define %%-%ds " define-width)) + + (< (high-lim "bit") 32) =][= + + INVOKE emit-word-macro one = 'U' mask-fmt = "%08XU" =][= + +ELIF (< (high-lim "bit") 64) =][= + + INVOKE emit-word-macro one = 'ULL' mask-fmt = "%016XULL" =][= + +ELSE more than 64 bits =][= + + INVOKE emit-multi-macros =][= + +ENDIF how many bits =][= + +IF (if (exist? "extra-defs") + (emit (string-append "\n\n" (get "extra-defs") "\n"))) + + (not (exist? "no-code")) =] +/* + * Return a string containing the names of the bits set. + */ +extern char * +[= (. base-name) =]_names([= (. type-name) =] bits); + +#define INV_[= (. BASE-NAME) =] -1 +#define DUP_[= (. BASE-NAME) =] -2 + +/* + * Set the bits in "bits" as specified by the input string "str". + * If any names are untranslatable (not in the name list or are + * ambiguous in that they match the initial portion of more than + * one entry), it will return -1 or -2, respectively. + * Otherwise, it returns the number of bits set in "bits". + */ +extern int +[= (. base-name) =]_bits( + [= (. type-name) =] * const bits, + char const * str); +[= ENDIF =] +#endif /* [= (. header-guard) =] */[= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +== c + + +=] +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +[= + + (if (exist? "no-code") (out-delete)) + (ag-fprintf 0 "#include \"%s\"\n" header-file) + (string-table-new "nm") + (string-table-add "nm" "* INVALID *") + (define ix 0) + (define offset-list "") + (define sorted-off "") =][= + +FOR bit (for-from 0) (for-by 1) =][= + + (if (exist? "b-name") + (begin + (set! tmp (string-downcase! (string->c-name! (get "b-name")))) + (set! ix (string-table-add "nm" tmp)) + (set! offset-list (string-append offset-list (sprintf "%d\n" ix))) + (set! sorted-off (string-append sorted-off + (sprintf "%-40s { %3d, %3d }\n" tmp ix (for-index)))) + ) + + (set! offset-list (string-append offset-list "0\n" )) + ) =][= + +ENDFOR bit =][= + + (emit-string-table "nm") + (sprintf "\nchar *\n%1$s_names(%1$s_bits_t bits)\n{" base-name) +=] + static int const nm_ixa[ [= (+ 1 (high-lim "bit")) =] ] = { +[= + + (define string-table-size (lambda (st-name) + (hash-ref (hash-ref stt-table st-name) "current-index") )) + + (emit (shellf "columns -I8 -S, --spread=1 <<_EOF_\n%s_EOF_" offset-list)) +=] }; + + static char buf[ [= (+ (string-table-size "nm") (count "bit")) =] ]; + char * buf_p = buf; + int ix = 0; +[= + +IF (< (high-lim "bit") 64) + +=] + while (bits != 0) { + if ((bits & 1) != 0) { + char const * p = nm + nm_ixa[ix]; + + if (buf_p > buf) { + *(buf_p++) = ','; + *(buf_p++) = ' '; + } + + if (p == nm) { + Oops: + strncpy(buf_p, nm, sizeof (buf) - (buf_p - buf)); + break; + } + + while ((*(buf_p++) = *(p++)) != '\0') ; + buf_p--; + } + bits >>= 1; + if (++ix > [= (high-lim "bit") =]) { + if (bits != 0) + goto Oops; + break; + } + }[= + +ELSE more than 64: + +=] + int bix = 0; + int bit_lim = 32; + do { + uint32_t bit_word = bits[bix]; + int ix = bix * 32; + + while (bit_word != 0) { + if ((bit_word & 1) != 0) { + char const * p = nm + nm_ixa[ix]; + + if (buf_p > buf) { + *(buf_p++) = ','; + *(buf_p++) = ' '; + } + + if (p == nm) { + Oops: + strncpy(buf_p, nm, sizeof (buf) - (buf_p - buf)); + break; + } + + while ((*(buf_p++) = *(p++)) != '\0') ; + buf_p--; + } + bit_word >>= 1; + if (++ix > [= (high-lim "bit") =]) { + if (bit_word != 0) + goto Oops; + return buf; + } + } + } while (++bix < [= `echo $mask_ct` =]);[= + +ENDIF + +=] + + return buf; +} + +static int +str_to_id(char const * str, char const ** p_str) +{ + static char nm_buf[ [= (+ 1 name-width) =] ]; + int res = -1; + int part = 1; + size_t len = 0; + + /* + * Extract the lower cased name with '-' replaced with '_' + */ + { + char * p = nm_buf; + + for (;;) { + char ch = *(str++); + switch (ch) { + case '-': + ch = '_'; + /* FALLTHROUGH */ + + case '_': + break; + + default: + if (isupper(ch)) + ch = _tolower(ch); + else if (! isalnum(ch)) { + str--; + goto have_name; + } + } + + if (++len > [= (. name-width) =]) + return -1; + + *(p++) = ch; + } have_name :; + + *p = '\0'; + len = p - nm_buf; + if (len == 0) + return INV_[= (. BASE-NAME) =]; + } + + /* + * Search the alphabetized table + */ + do { + static struct { + unsigned short const nm_off, val; + } nm_ixa[ [= (count "bit") =] ] = { +[= + (shellf (string-append + "(sort | sed 's/.*{/{/' | columns -I8 -S, --spread=1)<<_EOF_\n" + sorted-off "_EOF_" + )) +=] }; + + int av; + int lo = 0; + int hi = [= (- (count "bit") 1) =]; + + /* + * Binary search for first match + */ + do { + char const * p; + int df; + + av = (lo + hi) / 2; + p = nm + nm_ixa[av].nm_off; + df = strncmp(p, nm_buf, len); + + if (df == 0) { + res = nm_ixa[av].val; + if (p[len] == '\0') + part = 0; + + break; + } + + if (df > 0) + hi = av - 1; + else lo = av + 1; + + } while (lo <= hi); + + if (res < 0) + return INV_[= (. BASE-NAME) =]; + + if (part == 0) + break; + + /* + * Partial match. Look for an earlier match. One may be a full match. + */ + lo = av; + while (lo > 0) { + char const * p = nm + nm_ixa[--lo].nm_off; + int df = strncmp(p, nm_buf, len); + if (df != 0) + break; + if (p[len] == '\0') { + part = 0; + res = nm_ixa[lo].val; + break; + } + part++; + } + + if (part > 1) { + *p_str = nm_buf; + return DUP_[= (. BASE-NAME) =]; + } + + if ((part == 0) || (av == [= (- (count "bit") 1) =])) + break; + + /* + * Look for a successor match. No full match possible. + */ + { + char const * p = nm + nm_ixa[av+1].nm_off; + int df = strncmp(p, nm_buf, len); + if (df == 0) { + *p_str = nm_buf; + return DUP_[= (. BASE-NAME) =]; + } + } + } while (0); + + while (isspace(*str)) str++; + *p_str = str; + return res; +} + +int +[= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +(. base-name) =]_bits( + [= (. type-name) =] * const bits[= (if is-array "_p")=], + char const * str) +{[= + IF (. is-array) =] + [= (. element-type) =] * const bits = (void*)bits_p;[= + ENDIF =] + int ct = 0; + int res = 0; + + memset(bits, '\0', sizeof([= (. type-name) =])); + + another_bit: + + while (isspace(*str) || (*str == ',')) str++; + + for (;;) { + if (isdigit(*str)) { + [=(. element-type) =] num = + ([=(. element-type) =])strtoull(str, &str, 0); + *bits |= num; + ct += (num != 0); + + } else if (isalpha(*str)) { + res = str_to_id(str, &str); + if (res < 0) { + if (res == DUP_[= (. BASE-NAME) =]) + fprintf(stderr, "duplicate matches for '%s'\n", str); + goto fail_exit; + } + ct++; +[= + + IF (. is-array) =] + bits[res/32] |= 1 << (res & 0x1F);[= + ELIF (. is-64-bit) =] + *bits |= 1ULL << res;[= + ELSE =] + *bits |= 1 << res;[= + ENDIF + +=] + } else switch (*str) { + case ',': + goto another_bit; + + case '\0': + return ct; + + default: + res = INV_[= (. BASE-NAME) =]; + goto fail_exit; + } + } + + fail_exit: + memset(bits, '\0', sizeof(*bits)); + return res; +} + +#ifdef TEST_BITS + +static char const bit_names[] = +[= +(kr-string (string-append "The known " base-name " bit names are:\n" + (shellf (string-append + "(sort | columns -I2 --spread=1\n) <<_EOF_\n" + (string-downcase! (join "\n" (stack "bit.b-name"))) + "\n_EOF_")) + "\n" )) + =]; + +int +main(int argc, char** argv) +{ + static char const fmt_z[] = "'%s' yields: %s\n"; + [= (. type-name) =] bts; + if (argc != 2) { + fputs(bit_names, stderr); + return 1; + } + { + int ct = [= (. base-name) =]_bits(&bts, argv[1]); + if (ct <= 0) { + char const * pz; + switch (ct) { + case 0: pz = "no results"; break; + case INV_[= (. BASE-NAME) =]: pz = "invalid name"; break; + case DUP_[= (. BASE-NAME) =]: pz = "multiple match"; break; + } + fprintf(stderr, fmt_z, argv[1], pz); + fputs(bit_names, stderr); + return 1; + } + } + { + char * pz = [= (. base-name) =]_names(bts); + printf(fmt_z, argv[1], pz); + } + return 0; +} +#endif +[= + +ESAC =] +/* end of [= (out-name) =] */ +[=# + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE preamble =][= + + (if (not init-done) (begin + + (if (not (exist? "mask-name")) + (error "no defined bit mask name")) + + (shell "calc() { bc <<_EOF_ +$* +_EOF_ +} + mask_val=0") + (set! init-done #t) + (set! base-name (string-downcase! (string->c-name! (get "mask-name")))) + (set! BASE-NAME (string-upcase base-name)) + (set! prefix (string-upcase (string->c-name! + (if (exist? "prefix") (get "prefix") base-name) ))) + ) ) + + (dne " * " "/* ") =] + */ +[= + +ENDDEF preamble + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-bit-list =][= + + (if (exist? "b-name") + (set! bit-list (string-append (join "\n" (stack "b-name")) "\n")) + (set! bit-list "") + ) =][= + + FOR m-inc =][= + (set! tmp (string->c-name! (get "m-inc"))) + (set! bit-list (string-append bit-list + (shellf "echo \"${%s}\"" tmp) "\n")) + =][= + ENDFOR m-inc=][= + + (set! bit-list (string->c-name! bit-list)) + (shellf "%s='%s'" (string->c-name! (get "m-name")) bit-list) + + (emit (shell (string-append + + "(sort -u | columns -I8 --spread=1 -S' |' --format=" prefix "_%s_BIT " + "--line=' \\'\n) <<\\_EOF_\n" + (string-upcase bit-list) + "_EOF_" + + ))) + + (shell (string-append + "sum=`(sort -u | \ + sed -e \"${sedcmd}\"\n) <<\\_EOF_\n" + bit-list + "_EOF_\n`\n" + "sum=`eval calc ${sum} 0`\n" + "printf " + (if (>= (high-lim "bit") 32) + "' \\\\\\n /* 0x%016XULL */\\n'" + (if (>= (high-lim "bit") 16) + "' \\\\\\n /* 0x%08XU */\\n'" + "' \\\\\\n /* 0x%04XU */\\n'" )) + " ${sum}" + )) +=][= + +ENDDEF emit-bit-list + += = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-word-macro =][= + + (set! tmp-name (string-upcase! (string-append prefix "_" + (if (exist? "zero-name") (get "zero-name") "NO_BITS") ))) + (sprintf def-fmt tmp-name) =]0[= one =][= + + FOR bit =][= + + (sprintf def-fmt (id-name "_BIT")) =](1[=one=] << [= (id-name "_ID") =])[= + + ENDFOR =][= + + (ag-fprintf 0 def-fmt (string-append BASE-NAME "_MASK")) + (shellf "printf 0x%s ${mask_val}" (get "mask-fmt")) + + =][= + + FOR mask + + =] +[= (sprintf def-fmt (mask-name "_MASK")) =]( \ +[= INVOKE emit-bit-list =] )[= + + ENDFOR mask =][= + + FOR un-mask + + =] +[= (sprintf def-fmt (mask-name "_MASK")) =]([= + (string-append BASE-NAME "_MASK") =] & ~( \ +[= INVOKE emit-bit-list =]))[= + + ENDFOR un-mask=][= + + (if (exist? "defined") (string-append "\n\n" (get "defined"))) + +=][= IF (not (exist? "omit-test-n-set")) =] + +#define SET_[= (. BASE-NAME) =](_m, _b) \ + do { (_m) |= 1[= one =] << _b; } while (0) +#define CLEAR_[= (. BASE-NAME) =](_m, _b) \ + do { (_m) &= ~(1[= one =] << _b); } while (0) +#define TEST_[= (. BASE-NAME) =](_m, _b) (((_m) & (1[= one =] << _b)) != 0) +#define AND_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) & (_s2); } while (0) +#define OR_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) | (_s2); } while (0) +#define XOR_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) ^ (_s2); } while (0) +#define NOT_[= (. BASE-NAME) =](_d, _s) \ + do { (_d) = ~(_s); } while (0) +[= ENDIF omit-test-n-set =][= +ENDDEF emit-word-macro + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-loop-macro + +=][= + + (sprintf "#define %5s_%s" (get "mac-name") BASE-NAME) =][= + + CASE op-code =][= + == "~" =](_d, _s)[= (set! tmp one-arg-op)=][= + * =](_d, _s1, _s2)[= (set! tmp two-arg-op)=][= + ESAC op-code =] \ + [= (. iterate) =] \ + [= (sprintf tmp (get "op-code")) =][= + +ENDDEF emit-loop-macro + += = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-multi-macros + +=][= + +defined + +=][= IF (not (exist? "omit-test-n-set")) =] + +#define SET_[= +(define iterate (sprintf "do { int _ix_ = 0; for (;_ix_ < %s; _ix_++) {" + (shell "echo $mask_ct") )) +(define two-arg-op "(_d)[_ix_] = (_s1)[_ix_] %s (_s2)[_ix_]; } } while (0)") +(define one-arg-op "(_d)[_ix_] = %s(_s)[_ix_]; } } while (0)") + + BASE-NAME =](_m, _b) \ + do { (_m)[(_b)/32] |= 1U << ((_b) % 32); } while (0) +#define CLEAR_[= (. BASE-NAME) =](_m, _b) \ + do { (_m)[(_b)/32] &= ~(1U << ((_b) % 32)); } while (0) +#define TEST_[= (. BASE-NAME) =](_m, _b) \ + (((_m)[(_b)/32] & (1U << ((_b) % 32))) != 0) +[= INVOKE emit-loop-macro op-code = "&" mac-name = AND =] +[= INVOKE emit-loop-macro op-code = "|" mac-name = OR =] +[= INVOKE emit-loop-macro op-code = "^" mac-name = XOR =] +[= INVOKE emit-loop-macro op-code = "~" mac-name = NOT =] +[= ENDIF omit-test-n-set =][= + +ENDDEF emit-multi-macros =][= + +# End of bits.tpl \=] diff --git a/autoopts/tpl/cmd-doc.tlib b/autoopts/tpl/cmd-doc.tlib new file mode 100644 index 0000000..b59cef9 --- /dev/null +++ b/autoopts/tpl/cmd-doc.tlib @@ -0,0 +1,1001 @@ +[+: -*- Mode: nroff -*- + + AutoGen5 template man + +# cmd-doc.tlib -- Template for command line man/mdoc pages +# +# Time-stamp: "2012-05-12 20:52:33 bkorb" +# +# This file is part of AutoOpts, a companion to AutoGen. +# AutoOpts is free software. +# Copyright (c) 1992-2012 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 md5sums: +# +# 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +# 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +# 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +# Produce a man page for section 1, 5, 6 or 8 commands. Which is +# selected via: -DMAN_SECTION=n. "n" may have a suffix, if desired. +# These sections have default section names that may be overridden +# with -DSECTIN_NAME=XX, also passed to the autogen invocation. +# +:+][+: + + ;;# START-BUILDTREE-ISMS + ;; + (shell "CLexe=${AGexe%/agen5/*}/columns/columns + test -x \"${CLexe}\" || { + CLexe=${AGexe%/autogen}/columns + test -x \"${CLexe}\" || die 'columns program is not findable' + }") + +:+][+: # END-BUILDTREE-ISMS + + (shell "CLexe=${AGexe%/autogen}/columns") + +# END-INSTALL-ONLY-CODE :+][+: + +(define down-prog-name (string-downcase! (get "prog-name"))) +(define UP-PROG-NAME (get-up-name "prog-name")) + +(define tmp-val (getenv "MAN_SECTION")) +(define man-sect (if (exist? "cmd-section") (get "cmd-section") "1")) +(define file-name "") +(define sect-name "") +(define macro-name "") +(define tmp-str "") +(define fname-line "") +(define use-flags (exist? "flag.value")) +(define named-mode (not (or use-flags (exist? "long-opts") ))) + +(if (defined? 'tmp-val) + (if (string? tmp-val) + (set! man-sect tmp-val))) + +(define section-name + (if (=* man-sect "1") "User Commands" + (if (=* man-sect "5") "File Formats" + (if (=* man-sect "6") "Games" + (if (=* man-sect "8") "System Management" + (error + "the agman-cmd template only produces section 1, 5, 6 and 8 man pages") +))))) +(set! tmp-val (getenv "SECTION_NAME")) +(if (defined? 'tmp-val) (if (string? tmp-val) + (set! section-name tmp-val) )) + +(define package-text "") +(define package+version (and (exist? "package") (exist? "version"))) + +(if (or (exist? "package") (exist? "version")) (begin + (set! package-text (string-append + (get "package") + (if package+version " (" "") + (get "version") + (if package+version ")" "") )) +) ) + +(define name-to-fname (lambda (nm) + (string-tr (string-downcase nm) " " "-") )) + +(define sect-line-fname (lambda () (begin + (out-push-new file-name) + (emit (string-append ".Sh \"" sect-name "\"\n")) + (string-append "mk-" macro-name) ))) + +(make-tmp-dir) + +(define home-rc-files (exist? "homerc")) +(define home-rc-text + "\nSee \\fBOPTION PRESETS\\fP for configuration files.") + +(define environ-init (exist? "environrc")) +(define environ-text + "\nSee \\fBOPTION PRESETS\\fP for configuration environment variables.") + +(set! tmp-str (find-file (if man-page "texi2man" "texi2mdoc"))) +(if (not (defined? 'tmp-str)) + (error (string-append "cannot locate " + (if man-page "texi2man" "texi2mdoc")))) +(shell (string-append "cvt_prog='" tmp-str + "'\ntest -x \"$cvt_prog\" || die 'no conversion program'" )) + +(define get-cvt (lambda (nm alt-txt) + (shell (string-append + "{\n${cvt_prog} || die ${cvt_prog} failed in $PWD\n" + "} <<\\_EndOfTexiSection_\n" + (get nm alt-txt) + "\n_EndOfTexiSection_" + )) +)) + +(emit (head-line)) +(dne ".\\\" ") :+][+: + +INCLUDE "tpl-config.tlib" :+][+:# + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" B U I L D D O C +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE build-doc :+][+: + +INVOKE doc-sections :+][+: +INVOKE ao-sections :+][+: + +(out-push-new (string-append tmp-dir "/.assemble")) \:+] + +cat_n_rm() { + test -f ${tmp_dir}/$1 || return 0 + [+:(. egrep-prog):+] -v '^[ ]*$' ${tmp_dir}/$1 + rm -f ${tmp_dir}/$1 +} + +#.\" Insert these sections first, in the prescribed order +# +for f in synopsis description options option-presets +do cat_n_rm $f ; done +test -f ${tmp_dir}/name && rm -f ${tmp_dir}/name + +#.\" These sections go last, in the prescribed order +# +for f in implementation-notes environment files examples exit-status errors \ + compatibility see-also conforming-to history authors copyright bugs notes +do cat_n_rm $f ; done > ${tmp_dir}/.fini + +#.\" Insert the contents of all remaining files in alphabetic order, +#.\" except remove any blank lines. +# +set XX ${tmp_dir}/* ; shift +test -f "$1" && cat $* | [+:(. egrep-prog):+] -v '^[ ]*$' + +#.\" Now insert the sections we squirreled away for the end. +# +cat ${tmp_dir}/.fini +[+: (out-pop) + (shell ". ${tmp_dir}/.assemble") :+][+: + +ENDDEF build-doc + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" D O C S E C T I O N S +.\" +.\" Emit the files for each section that was provided. +.\" +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE doc-sections :+][+: + +FOR doc-section :+][+: + + CASE + (define sec-type (string-upcase (get "ds-type"))) + (define sec-name (name-to-fname sec-type)) + (out-push-new (string-append tmp-dir "/" sec-name)) + (define cvt-fn (find-file (string-append + (get "ds-format" "man") "2mdoc"))) + (if (not (defined? 'cvt-fn)) + (error (sprintf "Cannot locate converter for %s" + (get "ds-format" "man")))) + sec-type :+][+: + == "" :+][+: (error "unnamed doc-section") :+][+: + *==* " " :+].Sh "[+: (. sec-type) :+]"[+: + * :+].Sh [+: (. sec-type) :+][+: + ESAC :+] +[+: + (shell (string-append + "fn='" cvt-fn "'\n" + "test -f ${fn} || die ${fn} not found from $PWD\n" + "${fn} <<\\_EndOfDocSection_ || die ${fn} failed in $PWD\n" + (get "ds-text") + "\n_EndOfDocSection_" + )) :+][+: + + CASE (. sec-type) :+][+: + == FILES :+][+: + (if home-rc-files (emit home-rc-text)) + (set! home-rc-files #f) :+][+: + + == ENVIRONMENT :+][+: + (if environ-init (emit environ-text)) + (set! environ-init #f) :+][+: + ESAC :+][+: + + (out-pop) + :+][+: + +ENDFOR doc-section :+][+: + +ENDDEF doc-sections + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" A O S E C T I O N S +.\" +.\" Emit the files for the sections that these templates augment, +.\" replace or conditionally replace +.\" +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE ao-sections :+][+: + +INVOKE cond-section sec = "OPTIONS" mode = "replace" :+][+: +INVOKE cond-section sec = "SYNOPSIS" mode = "alt" :+][+: +INVOKE cond-section sec = "DESCRIPTION" mode = "append" :+][+: +INVOKE cond-section sec = "EXIT STATUS" mode = "insert" :+][+: +INVOKE cond-section sec = "AUTHORS" mode = "alt" :+][+: +INVOKE cond-section sec = "BUGS" mode = "append" :+][+: +INVOKE cond-section sec = "NOTES" mode = "append" :+][+: + +IF (exist? "copyright") :+][+: + INVOKE cond-section sec = "COPYRIGHT" mode = "alt" :+][+: +ENDIF :+][+: + +IF (or home-rc-files environ-init) :+][+: + INVOKE cond-section sec = "OPTION PRESETS" mode = "replace" :+][+: + + IF (. home-rc-files) :+][+: + INVOKE cond-section sec = "FILES" mode = "append" :+][+: + ENDIF :+][+: + + IF (. environ-init) :+][+: + INVOKE cond-section sec = "ENVIRONMENT" mode = "append" :+][+: + ENDIF :+][+: + +ENDIF :+][+: + +ENDDEF ao-sections + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" C O N D I T I O N A L S E C T I O N +.\" +.\" Figure out what to do for AutoOpts required sections, depending on "mode" +.\" In all cases, if the file does not exist, invoke the "mk" macro to create +.\" a new file. If it does exist, then: +.\" +.\" alt Alternate -- emit no text +.\" replace throw away any pre-existing file. +.\" append invoke the "append" macro to emit additional text +.\" insert save the current contents, replacing the .Sh line with .Pp. +.\" invoke the "mk" macro then emit the saved text +.\" +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE cond-section :+][+: + + IF + (set! sect-name (string-upcase! (string-substitute + (get "sec") "-" " " ))) + (set! macro-name (string-downcase! (string-substitute + sect-name " " "-" ))) + (set! file-name (string-append tmp-dir "/" macro-name)) + + (not (access? file-name R_OK)) :+][+: + + INVOKE (sect-line-fname) :+][+: + (out-pop) :+][+: + + ELSE file exists :+][+: + + CASE (get "mode") :+][+: + + == replace :+][+: + INVOKE (sect-line-fname) :+][+: + (out-pop) :+][+: + + == append :+][+: + (out-push-add file-name) :+][+: + INVOKE (string-append "append-" macro-name) :+][+: + (out-pop) :+][+: + + == insert :+][+: + (set! fname-line (shellf "sed '1s/.Sh .*/.Pp/' %s" file-name)) :+][+: + INVOKE (sect-line-fname) :+][+: + (emit fname-line) + (out-pop) :+][+: + + # * -- otherwise, do nothing :+][+: + + ESAC :+][+: + + ENDIF file existence/non-existence :+][+: +ENDDEF cond-section + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - D E S C R I P T I O N +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-description :+][+: + + (if (exist? "prog-man-descrip") + (stack-join "\n.Pp\n" "prog-man-descrip") + (if (exist? "detail") + (stack-join "\n.Pp\n" "detail") + "There is no description for this command." + ) ) :+] +[+: + INVOKE append-description :+][+: + +ENDDEF mk-description + +.\" = = = = = APPEND TO IT: :+][+: + +DEFINE append-description :+][+: + +IF (= (get "main.main-type") "for-each"):+][+: + + CASE main.handler-type :+][+: + ~* ^(name|file)|.*text \:+] +.Pp +This program will perform its function for every file named on the command +line or every file named in a list read from stdin. The arguments or input +names must be pre\-existing files. The input list may contain comments, +which[+: + + !E \:+] +.Pp +This program will perform its function for every command line argument +or every non\-comment line in a list read from stdin. +The input list comments[+: + + * :+][+: + (error "the 'for-each' main has in invalid handler-type.") :+][+: + ESAC \:+] + are blank lines or lines beginning with a '[+: + ?% comment-char "%s" "#" :+]' character. +[+: + +ENDIF - "main" exists :+][+: +ENDDEF append-description + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - O P T I O N S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-options + +:+][+: + +(define opt-arg "") +(define dis-name "") +(define opt-name "") +(define optname-from "A-Z_^") +(define optname-to "a-z--") +(define cvt-cmd "") +(define formatted-doc (exist? "option-doc-format")) + +(if formatted-doc (begin + (out-push-new) + (set! cvt-cmd (string-append (get "option-doc-format") "2mdoc")) +) ) + +(if (exist? "preserve-case") + (begin + (set! optname-from "_^") + (set! optname-to "--") +) ) + +(define fix-optname (lambda (o_nm) (begin + (set! o_nm (string-tr o_nm optname-from optname-to)) + (set! o_nm (string-substitute o_nm "-" "\\-" )) + o_nm ))) + +(if (exist? "option-info") + (string-append ".Pp\n" (get "option-info") "\n") ) +\:+] +.Bl -tag[+: + +FOR flag :+][+: + IF (not (exist? "documentation")) :+][+: + IF (exist? "aliases") :+][+: + INVOKE emit-alias-opt :+][+: + ELSE :+][+: + INVOKE emit-flag-text :+][+: + ENDIF :+][+: + + ELSE :+] +.Ss "[+: (get-cvt "descrip" "") :+]"[+: + + IF (set! tmp-str (get-cvt "documentation" "")) + (> (string-length tmp-str) 3) :+] +[+: (. tmp-str) :+] +[+: ENDIF :+][+: + + ENDIF :+][+: +ENDFOR flag + +.\" = = = = = = = = = = = = = = = = = +.\" help option +.\" = = = = = = = = = = = = = = = = = + +:+] +.It [+: + + IF (. use-flags) :+]\-[+: (get "help-value" "?") :+][+: + (if (exist? "long-opts") " , \" \\-\\-help\"") :+][+: + ELSE :+][+: + (if (exist? "long-opts") "\\-\\-") :+]help[+: + ENDIF :+] +Display usage information and exit.[+:# + +.\" = = = = = = = = = = = = = = = = = +.\" more-help option +.\" = = = = = = = = = = = = = = = = = :+][+: + + IF (not (exist? "no-libopts")) :+] +.It [+: + + IF (. use-flags) :+]\-[+: ?% more-help-value "%s" "!" :+][+: + IF (exist? "long-opts") :+] , " \-\-more-help"[+: ENDIF :+][+: + ELSE :+][+: + IF (exist? "long-opts") :+]\-\-[+: ENDIF :+]more-help[+: + ENDIF :+] +Pass the extended usage information through a pager.[+: + +ENDIF no no-libopts + +.\" = = = = = = = = = = = = = = = = = +.\" save and load configuration +.\" = = = = = = = = = = = = = = = = = :+][+: + +IF (exist? "homerc") :+] +.It [+: + + IF (. use-flags) :+]\-[+: ?% save-opts-value "%s" ">" + :+] " [\fIrcfile\fP][+: + IF (exist? "long-opts") :+]," " \-\-save-opts" "[=\fIrcfile\fP][+: + ENDIF :+]"[+: + ELSE :+][+: + IF (exist? "long-opts") :+]\-\-[+: + ENDIF :+]save-opts "[=\fIrcfile\fP]"[+: + ENDIF :+] +Save the option state to \fIrcfile\fP. The default is the \fIlast\fP +configuration file listed in the \fBOPTION PRESETS\fP section, below. +.It [+: + + IF (. use-flags) :+]\-[+: ?% load-opts-value "%s" "<" + :+] " \fIrcfile\fP[+: + IF (exist? "long-opts") + :+]," " \-\-load-opts" "=\fIrcfile\fP," " \-\-no-load-opts[+: + ENDIF :+]"[+: + ELSE :+][+: + IF (exist? "long-opts") :+]\-\-[+: + ENDIF :+]load-opts "=\fIrcfile\fP," " \-\-no-load-opts"[+: + ENDIF :+] +Load options from \fIrcfile\fP. +The \fIno-load-opts\fP form will disable the loading +of earlier RC/INI files. \fI\-\-no-load-opts\fP is handled early, +out of order.[+: +ENDIF (exist? "homerc") + +.\" = = = = = = = = = = = = = = = = = +.\" version +.\" = = = = = = = = = = = = = = = = = :+][+: + +IF (exist? "version") :+] +.It [+: + + IF (. use-flags) :+]\-[+: ?% version-value "%s" "v" + :+] " [{\fIv|c|n\fP}][+: + IF (exist? "long-opts") :+]," " \-\-version" "[=\fI{v|c|n}\fP][+: + ENDIF :+]"[+: + ELSE :+][+: + IF (exist? "long-opts") :+]\-\-[+: + ENDIF :+]version "[=\fI{v|c|n}\fP]"[+: + ENDIF :+] +Output version of program and exit. The default mode is `v', a simple +version. The `c' mode will print copyright information and `n' will +print the full copyright notice.[+: +ENDIF :+] +.El +[+: + +(if formatted-doc + (shell (string-append + "fn='" (find-file cvt-cmd) + "'\ntest -f ${fn} || die '" cvt-cmd " not found'\n" + "${fn} <<\\_EndOfMdoc_ || die ${fn} failed in $PWD\n" + (out-pop #t) + "\n_EndOfMdoc_" )) ) :+][+: + +ENDDEF mk-options + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - O P T I O N - P R E S E T S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-option-presets \:+] +Any option that is not marked as \fInot presettable\fP may be preset +by loading values from [+: + IF (. home-rc-files) + :+]configuration ("RC" or ".INI") file(s)[+: + IF (. environ-init) :+] and values from +[+: + ENDIF :+][+: + ENDIF :+][+: + IF (. environ-init) :+]environment variables named: +.nf + \fB[+: (. UP-PROG-NAME) :+]_<option-name>\fP or \fB[+: (. UP-PROG-NAME) :+]\fP +.fi +.ad[+: + IF (. home-rc-files) :+] +The environmental presets take precedence (are processed later than) +the configuration files.[+: + ENDIF :+][+: + ELSE :+].[+: + ENDIF :+][+: + + CASE + (define rc-file + (get "rcfile" (string-append "." (get "prog-name") "rc")) ) + (count "homerc") :+][+: + + == "0" :+][+: + == "1" :+][+: + + CASE homerc :+][+: + ~~ '\.|\$HOME' :+] +The file "\fI[+: (string-append (get "homerc") "/" rc-file) +:+]\fP" will be used, if present.[+: + * :+] +The \fIhomerc\fP file is "\fI[+:homerc:+]\fP", unless that is a directory. +In that case, the file "\fI[+: (. rc-file) :+]\fP" +is searched for within that directory.[+: + ESAC :+][+: + + * :+] +The \fIhomerc\fP files are [+: + FOR homerc ", " :+][+: + IF (last-for?) :+]and [+: + ENDIF :+]"\fI[+: homerc :+]\fP"[+: ENDFOR :+]. +If any of these are directories, then the file \fI[+: (. rc-file) :+]\fP +is searched for within those directories.[+: + ESAC :+][+: + +ENDDEF mk-option-presets + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - E X I T - S T A T U S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-exit-status \:+] +One of the following exit values will be returned: +.Bl -tag +[+: +(ag-fprintf 0 ".It 0 \" (EXIT_%s)\"\n%s\n" + (string->c-name! (string-upcase (get "exit-name[0]" "SUCCESS"))) + (get-cvt "exit-desc[0]" "Successful program execution.") ) + +(define need-ex-noinput (exist? "homerc")) +(define need-ex-software #t) + +(ag-fprintf 0 ".It 1 \" (EXIT_%s)\"\n%s\n" + (string->c-name! (string-upcase (get "exit-name[1]" "FAILURE"))) + (get-cvt "exit-desc[1]" + "The operation failed or the command syntax was not valid.")) :+][+: + +FOR exit-desc (for-from 2) :+][+: + (if (= (for-index) 66) + (set! need-ex-noinput #f) + (if (= (for-index) 70) + (set! need-ex-software #f) )) + + (set! tmp-str (get (sprintf "exit-name[%d]" (for-index)) "* unnamed *")) + (sprintf ".It %d \" (EXIT_%s)\"\n%s\n" + (for-index) + (string-upcase (string->c-name! tmp-str)) + (get-cvt "exit-desc" "")) :+][+: +ENDFOR exit-desc :+][+: +(if need-ex-noinput + (emit ".It 66 \" (EX_NOINPUT)\" +A specified configuration file could not be loaded.\n")) + +(if need-ex-noinput + (emit ".It 70 \" (EX_SOFTWARE)\" +libopts had an internal operational error. Please report +it to autogen-users@lists.sourceforge.net. Thank you.\n")) + +(if (> (string-length fname-line) 1) + (emit fname-line)) :+] +.El +[+: + +ENDDEF exit-status + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - A U T H O R S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-authors :+][+: + + (define remove-authors #t) + + (set! tmp-val + (if (exist? "copyright.author") + (stack-join ",\n" "copyright.author") + (stack-join ",\n" "copyright.owner") )) + + (if (> (string-length tmp-val) 1) + (string-append tmp-val "\n") + (delete-file file-name)) + + :+][+: + +ENDDEF mk-authors + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - B U G S +.\" +.\" This section is guaranteed to be the last section in the man page +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-bugs :+][+: + + (set! tmp-val (get "copyright.eaddr" (get "eaddr"))) + (if (> (string-length tmp-val) 1) + (string-append "Please send bug reports to: " tmp-val "\n") + (delete-file file-name) ) + :+][+: + +ENDDEF mk-bugs :+][+: + +DEFINE append-bugs :+][+: + + (set! tmp-val (get "copyright.eaddr" (get "eaddr"))) + (if (> (string-length tmp-val) 1) + (string-append "Please send bug reports to: " tmp-val "\n") ) + :+][+: + +ENDDEF append-bugs + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - C O P Y R I G H T (+ licensing) +.\" +.\" This section is guaranteed to be the last section in the man page +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-copyright \:+] +Copyright (C) [+: copyright.date :+] [+: + (get "copyright.owner" (get "copyright.author" (get "copyright.eaddr"))) + :+] all rights reserved. +[+: CASE (get "copyright.type") :+][+: + = note :+][+: (get "copyright.text") :+][+: + == '' :+]This program has an unspecified license.[+: + + * :+][+: + (string-append "This program is released under the terms of " + (license-name (get "copyright.type")) ".") :+][+: + + ESAC :+] +[+: +ENDDEF mk-copyright + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - N O T E S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-notes \:+] +This manual page was \fIAutoGen\fP-erated from the \fB[+: prog-name :+]\fP +option definitions. +[+: + +ENDDEF mk-notes + +.\" = = = = = APPEND TO IT: :+][+: + +DEFINE append-notes \:+] +.Pp +This manual page was \fIAutoGen\fP-erated from the \fB[+: prog-name :+]\fP +option definitions.[+: + +ENDDEF append-notes + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - E N V I R O N M E N T +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-environment :+][+: + INVOKE append-environment :+][+: +ENDDEF mk-environment + +.\" = = = = = APPEND TO IT: :+][+: + +DEFINE append-environment :+][+: + (. environ-text) :+][+: +ENDDEF append-environment + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" M K - F I L E S +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE mk-files :+][+: + INVOKE append-files :+][+: +ENDDEF mk-files + +.\" = = = = = APPEND TO IT: :+][+: + +DEFINE append-files :+][+: + (. home-rc-text) :+][+: +ENDDEF append-files + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" E M I T A L I A S O P T +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE emit-alias-opt :+] +.It [+: + IF (exist? "value") :+][+: + IF (exist? "long-opts") \:+] + \-[+:value:+] ", " -\-[+: name :+][+: + ELSE \:+] + \-[+:value:+][+: + ENDIF (exist? "long-opts") :+][+: + + ELSE value does not exist -- named option only :+][+: + + IF (not (exist? "long-opts")) \:+] + [+: name :+][+: + ELSE \:+] + \-\-[+: (. opt-name) :+][+: + ENDIF :+][+: + ENDIF :+] +This is an alias for the [+: aliases :+] option.[+: +ENDDEF emit-alias-opt + +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +.\" E M I T F L A G T E X T +.\" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = :+][+: + +DEFINE emit-flag-text :+][+: + + (if (exist? "enable") + (set! opt-name (string-append (get "enable") "-" (get "name"))) + (set! opt-name (get "name")) ) + (if (exist? "disable") + (set! dis-name (string-append (get "disable") "-" (get "name"))) + (set! dis-name "") ) + + (set! opt-name (fix-optname opt-name)) + (if (> (string-length dis-name) 0) + (set! dis-name (fix-optname dis-name)) ) + + (if (not (exist? "arg-type")) + (set! opt-arg "") + (set! opt-arg (string-append "\\fI" + (fix-optname (if (exist? "arg-name") + (get "arg-name") + (string-downcase! (get "arg-type")) )) + "\\fP" )) + ) + +:+] +.It [+: + IF (exist? "value") :+][+: + IF (exist? "long-opts") :+][+: + + # * * * * * * * * * * * * * * * * * * * * + * + * The option has a flag value (character) AND + * the program uses long options + * + \:+] + \-[+:value:+][+: + IF (not (exist? "arg-type")) :+] ", " -\-[+: + ELSE :+] " [+:(. opt-arg):+], " \-\-[+: + ENDIF :+][+: (. opt-name) :+][+: + IF (exist? "arg-type") :+][+: + ? arg-optional " [ =" ' "=" ' + :+][+: (. opt-arg) :+][+: + arg-optional " ]" :+][+: + ENDIF :+][+: + IF (exist? "disable") :+], " \fB\-\-[+:(. dis-name):+]\fP"[+: + ENDIF :+][+: + + ELSE :+][+: + + # * * * * * * * * * * * * * * * * * * * * + * + * The option has a flag value (character) BUT + * the program does _NOT_ use long options + * + \:+] + \-[+:value:+][+: + IF (exist? "arg-type") :+][+: + arg-optional "[" :+] "[+:(. opt-arg):+][+: + arg-optional '"]"' :+][+: + ENDIF " :+][+: + ENDIF (exist? "long-opts") :+][+: + + + ELSE value does not exist -- named option only :+][+: + + IF (not (exist? "long-opts")) :+][+: + + # * * * * * * * * * * * * * * * * * * * * + * + * The option does not have a flag value (character). + * The program does _NOT_ use long options either. + * Special magic: All arguments are named options. + * + \:+] + [+: (. opt-name) :+][+: + IF (exist? "arg-type") :+] [+: + ? arg-optional " [ =" ' "=" ' + :+][+:(. opt-arg) :+][+: + arg-optional "]" :+][+: + ENDIF:+][+: + IF (exist? "disable") :+], " \fB[+:(. dis-name):+]\fP"[+: + ENDIF :+][+: + + + ELSE :+][+: + # * * * * * * * * * * * * * * * * * * * * + * + * The option does not have a flag value (character). + * The program, instead, only accepts long options. + * + \:+] + \-\-[+: (. opt-name) :+][+: + + IF (exist? "arg-type") :+] "[+: #" :+][+: + arg-optional "[" :+]=[+:(. opt-arg):+][+: + arg-optional "]" :+]"[+: #" :+][+: + ENDIF :+][+: + + IF (exist? "disable") + :+], " \fB\-\-[+:(. dis-name):+]\fP"[+: + ENDIF :+][+: + ENDIF :+][+: + ENDIF :+] +[+: (get-cvt "descrip" "") :+].[+: + + IF (exist? "min") :+] +This option is required to appear.[+: + ENDIF :+][+: + + IF (exist? "max") :+] +This option may appear [+: + IF % max (= "%s" "NOLIMIT") + :+]an unlimited number of times[+:ELSE + :+]up to [+: max :+] times[+: + ENDIF:+].[+: + ENDIF:+][+: + + IF (exist? "disable") :+] +The \fI[+:(. dis-name):+]\fP form will [+: + IF (exist? "stack-arg") + :+]clear the list of option arguments[+: + ELSE :+]disable the option[+: + ENDIF :+].[+: + ENDIF:+][+: + + IF (exist? "enabled") :+] +This option is enabled by default.[+: + ENDIF :+][+: + + IF (exist? "no-preset") :+] +This option may not be preset with environment variables +or in initialization (rc) files.[+: + ENDIF :+][+: + + IF (and (exist? "default") named-mode) :+] +This option is the default option.[+: + ENDIF :+][+: + + IF (exist? "equivalence") :+] +This option is a member of the [+:equivalence:+] class of options.[+: + ENDIF :+][+: + + IF (exist? "flags-must") :+] +This option must appear in combination with the following options: +[+: FOR flags-must ", " :+][+:flags-must:+][+:ENDFOR:+].[+: + ENDIF :+][+: + + IF (exist? "flags-cant") :+] +This option must not appear in combination with any of the following options: +[+: FOR flags-cant ", " :+][+:flags-cant:+][+:ENDFOR:+].[+: + ENDIF :+][+: + + + IF (~* (get "arg-type") "key|set") :+] +This option takes a keyword as its argument[+: + + IF (=* (get "arg-type") "set") + +:+] list. Each entry turns on or off +membership bits. The bits are set by name or numeric value and cleared +by preceding the name or number with an exclamation character ('!'). +They can all be cleared with the magic name \fInone\fR and they can all be set +with +.IR all . +A single option will process a list of these values.[+: + + ELSE + +:+]. The argument sets an enumeration value that can +be tested by comparing them against the option value macro.[+: + + ENDIF + +:+] +The available keywords are: +.in +4 +.nf +.na +[+: (shellf "${CLexe} --indent='' --spread=1 -W50 <<_EOF_\n%s\n_EOF_" + (join "\n" (stack "keyword")) ) :+] +.fi +or their numeric equivalent. +.in -4[+: (if (exist? "arg-default") "\n.sp" ) :+][+: + + ELIF (=* (get "arg-type") "num") :+] +This option takes an integer number as its argument.[+: + + IF (exist? "arg-range") :+] +The value of [+:(. opt-arg):+] is constrained to being: +.in +4 +.nf +.na[+:FOR arg_range ", or" :+] +[+: (shellf " +range='%s' + +case \"X${range}\" in +X'->'?* ) + echo \"less than or equal to\" ` + echo $range | sed 's/->//' ` ;; + +X?*'->' ) + echo \"greater than or equal to\" ` + echo $range | sed 's/->.*//' ` ;; + +X?*'->'?* ) + echo \"in the range \" ` + echo $range | sed 's/->/ through /' ` ;; + +X?* ) + echo exactly $range ;; + +X* ) echo $range is indeterminate +esac" + +(get "arg-range") ) +:+][+: + ENDFOR arg-range :+] +.fi +.in -4[+: + + ENDIF arg-range exists :+][+: + + ENDIF arg-type key/set/num :+][+: + + IF (exist? "arg-default") :+] +The default [+: (. opt-arg) :+] for this option is: +.ti +4 + [+: (join " + " (stack "arg-default" )) :+][+: + ENDIF :+] +.sp +[+: + (if (exist? "doc") + (get-cvt "doc" "") + "This option has not been fully documented." ) :+][+: + IF (exist? "deprecated") :+] +.sp +.B +NOTE: THIS OPTION IS DEPRECATED +.R[+: + ENDIF :+][+: + +ENDDEF emit-flag-text + +.\" cmd-doc.tlib ends here \:+] diff --git a/autoopts/tpl/def2pot.tpl b/autoopts/tpl/def2pot.tpl new file mode 100644 index 0000000..d2c5cc4 --- /dev/null +++ b/autoopts/tpl/def2pot.tpl @@ -0,0 +1,131 @@ +[= AutoGen5 template pot =][= +# +# this template can be used to generate .pot file for the +# option definition files for these templates: +# aginfo.tpl, agman-cmd.tpl, agmdoc-cmd.tpl +# + +====================== FUNCTIONS BEGIN =======================][= +DEFINE genmsg =][= + + IF (set! msg-id (get "msgid")) + (set! msg-text (get-text msg-id)) + (< 0 (string-length msg-text)) =] +#: [=(def-file-line msg-id "%s:%d") =] +msgid [= (c-string msg-text) =] +msgstr "" +[=ENDIF =][= +ENDDEF =][= + +DEFINE genmsg2 =][= + IF (set! msg-text (get "msgid")) + (string-length msg-text) =] +#: [=(def-file-line msg-text "%s:%d") =] +msgid [= (c-string msg-text) =] +msgstr "" +[=ENDIF =][= +ENDDEF =][= + +(define get-text (lambda (nm) (shell (string-append + + "{ sed 's/@[a-z]*{\\([^}]*\\)}/\\1/g' | " + "${CLexe} --fill -I0 -W72\n" + "} <<\\_EODesc_\n" + (get nm) + "\n_EODesc_" +)))) +(define msg-text "") +(define msg-id "") + + ;;# START-BUILDTREE-ISMS + ;; + (shell "CLexe=${AGexe%/agen5/*}/columns/columns + test -x \"${CLexe}\" || { + CLexe=${AGexe%/autogen}/columns + test -x \"${CLexe}\" || die 'columns program is not findable' + }") + +=][= # END-BUILDTREE-ISMS + + (shell "CLexe=${AGexe%/autogen}/columns") + +# END-INSTALL-ONLY-CODE =][= # + +;; ==================== FUNCTIONS END =========================== + +;; pot file header and comment info \=] +# localization template (.pot) for [= (def-file) =] of [= prog-name =], +# this file is used to generate localized manual for [= prog-name =]. +# Copyright (C) [= (shell "date +%Y") =][= + + IF (exist? "copyright") =] +# This file is distributed under the terms of the +# [= (license-name (get "copyright.type")) \=] + +# The program owners may be reached via: +# [=(shellf + "author='%s' email='%s' date=`date +%%Y` + printf '%%s <%%s>, %%s.' \"$author\" \"$email\" \"${date}\"" + (get "copyright.owner" "FIRST AUTHOR") + (get "copyright.eaddr" "EMAIL@ADDRESS") +)=][= ENDIF =] +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: [= prog-name =] [= version =]\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: [= (shell "date +\"%F %R%z\"") =]\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +[= +genmsg msgid=prog-title =][= + +FOR flag =][= + genmsg msgid=descrip =][= + genmsg msgid=doc =][= +ENDFOR =][= + +FOR explain =][= + genmsg msgid=explain =][= +ENDFOR =][= + +FOR doc-section =][= + genmsg msgid=ds-text =][= +ENDFOR =][= + +FOR prog-man-descrip =][= + genmsg msgid=prog-man-descrip =][= +ENDFOR =][= + +FOR prog-info-descrip =][= + genmsg msgid=prog-info-descrip =][= +ENDFOR =][= + +FOR detail =][= + genmsg msgid=detail =][= +ENDFOR =][= + +FOR exit-desc =][= + genmsg msgid=exit-desc =][= +ENDFOR =][= + +CASE (get "copyright.type") =][= + = note =][= + == '' =][= + * =][= + genmsg2 msgid=(string-append + "This program is released under the terms of " + (license-name (get "copyright.type")) ".") + =][= +ESAC =][= + +genmsg msgid=option-info =][= +genmsg msgid=argument =][= +genmsg msgid=man-doc =][= +genmsg msgid=copyright.text =] diff --git a/autoopts/tpl/getopt.tpl b/autoopts/tpl/getopt.tpl new file mode 100644 index 0000000..374c8b6 --- /dev/null +++ b/autoopts/tpl/getopt.tpl @@ -0,0 +1,517 @@ +[+ AutoGen5 Template -*- Mode: C -*- + + h=%s-temp.h + c=%s-temp.c +][+ + +`stamp=\`sed 's,.*stamp: *",,;s,".*,,' <<\_EOF_ + Time-stamp: "2012-04-29 08:54:45 bkorb" +_EOF_ +\` ` +][+ + +;; This file is part of AutoOpts, a companion to AutoGen. +;; AutoOpts is free software. +;; AutoOpts is Copyright (c) 1992-2012 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 md5sums: +;; +;; 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +;; 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +;; 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + + (if (not (exist? "settable")) + (error "'settable' must be specified globally for getopt_long\n")) + (if (not (exist? "no-libopts")) + (error "'no-libopts' must be specified globally to use getopt\n")) + (define prog-name (string->c-name! (get "prog-name"))) + (define PROG-NAME (string-upcase prog-name)) + (out-move (string-append "getopt-" prog-name "." (suffix))) + (dne " * " "/* " ) +] + *[+ + + IF (exist? "copyright") +] + * +[+ + CASE copyright.type +][+ + == "" +] * licensing type not specified.[+ + = note +][+ (prefix " * " (get "copyright.text")) +][+ + * +][+ + (license-description (get "copyright.type") prog-name " * " + (get "copyright.owner")) +][+ + ESAC +][+ + ENDIF +] + * + * Last template edit: [+ `echo $stamp` +] + */[+ +CASE (suffix) +][+ +== h +][+ + (define header-file (out-name)) + (out-push-new) \+] +{ + test -x "${AGexe}" || die "AGexe not properly set: ${AGexe}" +[+ # START-BUILDTREE-ISMS: + +# The following code is sedded away in install-hook.sh. +# The goal is to ensure we use build tree templates in testing mode, and +# remove them when installing this file. + +\+] + aobdir=`echo ${AGexe} | sed 's@/[^/]*$@@'` + + if ! test -x ${aobdir}/autoopts-config + then + # Check for autoopts-config in build directory layout + # + aobdir=`echo ${aobdir} | sed 's@/[^/]*$@@'`/autoopts + test -x ${aobdir}/autoopts-config || { + aobdir=`echo ${aobdir} | sed 's@/[^/]*/autoopts$@@'`/autoopts + test -x ${aobdir}/autoopts-config || \ + die 'cannot locate autoopts-config' + } + fi + + agopts=`dirname [+ (tpl-file #t) +]` + agopts="-L${aobdir}/tpl -L$agopts " + tarfile=`set -- ${aobdir}/libopts*.tar.* + test -f $1 || { + cd ${aobdir} + ${MAKE:-make} libsrc + cd - + set -- ${aobdir}/libopts*.tar.* + test -f $1 || die 'libopts tarball not built' + } >&2 + echo $1`[+ + +# END-BUILDTREE-ISMS the following code is for installed version: + agopts= + aocfg=`echo ${AGexe} | sed 's@/[^/]*$@@'`/autoopts-config + tarfile=`${aocfg} libsrc` + +# END-INSTALL-ONLY-CODE +] + if test -n "${AG_Tracing}" + then + AG_Dep_File=`dirname "${AG_Tracing}"`/ao-[+ (base-name) +].dep + agopts="${agopts}-MF${AG_Dep_File} -MT${AG_Dep_File%.dep}.targ" + fi + + ${AGexe} -b[+ (base-name) +] ${agopts} -Toptions.tpl [+ (def-file) +] + def_hdr=[+ (base-name) +].h + sed 's@<autoopts/options.h>@"[+ (. header-file) + +]"@' $def_hdr > XXX-$$ + mv -f XXX-$$ $def_hdr + hdrfile=`gunzip -c $tarfile | tar tf - | fgrep /autoopts/options.h` + gunzip -c $tarfile | tar xf - $hdrfile + exec 3< $hdrfile + untardir=`echo $hdrfile | sed 's@/.*@@'` +} >&2 + +while : +do + IFS= read -r -u3 line || die "no header guard in $hdrfile" + case "$line" in + *AUTOOPTS_OPTIONS_H_GUARD ) break ;; + esac +done +echo + +echo "$line" +IFS= read -r -u3 line || die "short $hdrfile" +case "$line" in +'#define AUTOOPTS_OPTIONS_H_GUARD'* ) : ;; +*) die "invalid header guard in $hdrfile" ;; +esac +echo "$line" +echo '#include "[+ +(if (exist? "config-header") + (get "config-header") + (error "getopt template requires a \"config-header\" attribute") +) +]"' + +while : +do + IFS= read -r -u3 line || die "no CPLUSPLUS_CLOSER in $hdrfile" + case "$line" in + *'Versions where in various fields first appear'* ) break ;; + esac + echo "$line" +done + +cat <<- _EOF_ + * option loop function + */ + #ifdef __cplusplus + #define CPLUSPLUS_OPENER extern "C" { + CPLUSPLUS_OPENER + #define CPLUSPLUS_CLOSER } + #else + #define CPLUSPLUS_CLOSER + #endif + + extern int process_[+(. prog-name)+]_opts(int argc, char** argv); + extern void optionPrintVersion(tOptions* pOptions, tOptDesc* pOptDesc); + + CPLUSPLUS_CLOSER + _EOF_ + +sed '1,/^CPLUSPLUS_CLOSER/d' <&3 +exec 3<&- +rm -rf $untardir +[+ (shell (out-pop #t)) +] +[+ == c +] +#include "[+ (. header-file) +]" + +#include <sys/types.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <[+ (if (exist? "long-opts") "getopt" "unistd") +].h> +#include "[+ (base-name) +].h" + +#ifndef DIRCH +# if defined(_WIN32) && !defined(__CYGWIN__) +# define DIRCH '\\' +# else +# define DIRCH '/' +# endif +#endif[+ + +IF (exist? "long-opts") +] + +/* + * getopt_long option descriptor + */ +static struct option a_long_opts[] = {[+ + + FOR flag +][+ + (sprintf + + "\n { %-20s %d, NULL, VALUE_OPT_%s }," + (string-append (c-string (get "name")) ",") + (if (exist? "arg-type") 1 0) + (string-upcase (string->c-name! (get "name"))) + ) +][+ + + ENDFOR flag + ++] + { "help", 0, NULL, VALUE_OPT_HELP },[+ +IF (exist? "version") +] + { "version", 0, NULL, VALUE_OPT_VERSION },[+ +ENDIF +] + { NULL, 0, NULL, 0 } +}; +[+ ENDIF +] +/* + * Option flag character list + */ +static char z_opts[] = "[+ # close quote for emacs " +][+ + FOR flag +][+ + CASE value +][+ + ~ [!-~] +][+ value +][+ + + CASE arg-type +][+ + =* str +]:[+ + == "" +][+ + * +][+ (error (sprintf + "error in %s opt: The only allowed arg type is 'string'\n" + (get "name") )) +][+ + ESAC +][+ + + ESAC +][+ + + ENDFOR flag +][+ + + IF (not (exist? "help-value")) +]?[+ + ELSE +][+ + CASE help-value +][+ + == "" +][+ + == '"' +]\"[+ + * +][+ help-value +][+ + ESAC +][+ + ENDIF +][+ + + IF (exist? "version") +][+ + IF (not (exist? "version-value")) +]v[+ + ELSE +][+ + CASE version-value +][+ + == "" +][+ + == '"' +]\"[+ + * +][+ version-value +][+ + ESAC +][+ + ENDIF +][+ + ENDIF +][+ + + (define help-opt + (if (exist? "long-opts") "--help" + (if (not (exist? "flag.value")) "help" + (if (exist? "help-value") (string-append "-" (get "help-value")) + "-?" ))) ) + ;; open quote for emacs " +]"; + +/* + * AutoOpts library replacement routines: + */ +void +optionUsage (tOptions* pOptions, int status) +{ + if (status != 0) + fprintf (stderr, _("Try `%s [+(. help-opt)+]' for more information.\n"), + [+ (. prog-name) +]Options.pzProgName); + else + { + fputs (_([+ + INVOKE emit-usage-string usage-type = short +]), stdout); + } + + exit (status); +} + +void +optionPrintVersion( + tOptions* pOptions, + tOptDesc* pOptDesc ) +{ + char const * pz_by = + _("[+ # " +][+ + + (sprintf "%s%s %s" prog-name + (if (exist? "prog-group") + (sprintf " (%s)" (get "prog-group")) + "" ) + (get "version") ) +]\n\ +Written by [+(join ", " (stack "copyright.author"))+].\n\n\ +copyright (c) [+ copyright.date +] [+ copyright.owner +]\n[+ + +CASE copyright.type +][+ +*= gpl +]\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.[+ + +ESAC +][+ # " +]\n"); + + fputs (pz_by, stdout); + exit (EXIT_SUCCESS); +} + +/* + * If an option appears more often than is allowed, ... + */ +static void +usage_too_many (tOptDesc* pOptDesc) +{ + char const * pz = + _("[+(. prog-name) + +] error: the '%s' option appears more than %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMaxCt); + USAGE(EXIT_FAILURE); +} +[+ + IF (exist? "flag.min") ++] +/* + * There is at least one option that must appear. + */ +static void +usage_too_few (tOptDesc* pOptDesc) +{ + char const * pz = + _("[+(. prog-name) + +] error: the '%s' option must appear %d times\n"); + fprintf (stderr, pz, pOptDesc->pz_Name, pOptDesc->optMinCt); + USAGE(EXIT_FAILURE); +} +[+ + ENDIF ++][+ + IF (exist? "flag.flags-cant") ++] +/* + * There is at least one pair of options that may not appear together + * on the command line. + */ +static void +usage_cannot (char const* pz_what, char const* pz_cant) +{ + char const * pz = + _("[+(. prog-name) + +] error: the `%s' option conflicts with the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_cant); + USAGE(EXIT_FAILURE); +} +[+ + ENDIF ++][+ + IF (exist? "flag.flags-must") ++] +/* + * There is at least one pair of options that are required to appear + * together on the command line. + */ +static void +usage_must (char const* pz_what, char const* pz_must) +{ + char const * pz = + _("[+(. prog-name) + +] error: the `%s' option requires the `%s' option.\n"); + fprintf (stderr, pz, pz_what, pz_must); + USAGE(EXIT_FAILURE); +} +[+ + ENDIF ++] +/* + * Process the options for the "[+(. prog-name)+]" program. + * This function was generated to use the getopt[+ + (if (exist? "long-opts") "_long(3GNU)" "(3posix)") +] function. + * There are [+ (+ (count "flag") (if (exist? "version") 2 1)) + +] options for this program, + * including "help (usage)"[+ + IF (exist? "version") +] and "version"[+ ENDIF +]. + */ +int +process_[+(. prog-name)+]_opts (int argc, char** argv) +{ + { + char * pz_prog = strrchr (argv[0], DIRCH); + /* + * This violates the const-ness of the pzProgName field. + * The const-ness is to prevent accidents. This is not accidental. + */ + char ** pp = (char **)(void *)&([+ (. prog-name) +]Options.pzProgName); + + if (pz_prog != NULL) + pz_prog++; + else + pz_prog = argv[0]; + *pp = pz_prog; + } + + for (;;) { + switch ([+ + +IF (exist? "long-opts") + +]getopt_long (argc, argv, z_opts, a_long_opts, NULL)[+ +ELSE +]getopt (argc, argv, z_opts)[+ +ENDIF +]) { + case -1: goto leave_processing; + case 0: break;[+ + FOR flag +][+ + (define OPT-NAME (string-upcase! (string->c-name! (get "name")))) ++] + + case VALUE_OPT_[+ (. OPT-NAME) +]:[+ + + IF (not (exist? "max")) +] + if (HAVE_OPT( [+(. OPT-NAME)+] )) + usage_too_many (&DESC([+(. OPT-NAME) +]));[+ + + ELIF (not (= (get "max") "nolimit")) +] + if (DESC([+(. OPT-NAME)+]).optOccCt++ >= DESC([+(. OPT-NAME)+]).optMaxCt) + usage_too_many (&DESC([+(. OPT-NAME) +]));[+ + ENDIF ++] + SET_OPT_[+(. OPT-NAME)+][+ (if (exist? "arg-type") "(optarg)") +]; + break;[+ + + ENDFOR +] + + case VALUE_OPT_HELP: + USAGE(EXIT_SUCCESS); + /* NOTREACHED */ +[+ IF (exist? "version") +] + case VALUE_OPT_VERSION: + optionPrintVersion (&[+ (. prog-name) +]Options, &DESC(VERSION)); + /* NOTREACHED */ +[+ ENDIF +] + default: + USAGE(EXIT_FAILURE); + } + } leave_processing:; +[+ +FOR flag +][+ + IF + (set! OPT-NAME (string-upcase! (string->c-name! (get "name")))) + (define check-have-opt (or (exist? "flags-cant") (exist? "flags-must"))) + check-have-opt ++] + if (HAVE_OPT( [+ (. OPT-NAME) +] )) {[+ + + FOR flags-cant +] + if (HAVE_OPT( [+ (string-upcase! (string->c-name! (get "flags-cant"))) +] )) + usage_cannot (DESC([+ (. OPT-NAME) +]).pz_Name, DESC([+ + (string-upcase! (string->c-name! (get "flags-cant"))) +]).pz_Name);[+ + ENDFOR cant +][+ + + FOR flags-must +] + if (! HAVE_OPT( [+(string-upcase! (string->c-name! (get "flags-must")))+] )) + usage_must (DESC([+ (. OPT-NAME) +]).pz_Name, DESC([+ + (string-upcase! (string->c-name! (get "flags-must"))) +]).pz_Name);[+ + ENDFOR must +][+ + + IF (exist? "min") +][+ + IF (> (string->number (get "min" "0")) 1) +] + if (DESC([+(. OPT-NAME)+]).optOccCt < DESC([+(. OPT-NAME)+]).optMinCt) + usage_too_few (&DESC([+(. OPT-NAME) +]));[+ + + ENDIF +][+ + ENDIF +] + } +[+ + + ENDIF + ++][+ + + IF (exist? "min") +][+ + IF (. check-have-opt) ++] else[+ + + ELSE ++] + if ([+ # + We have a minimum count, but we have not checked for option existence + yet because there are no option interdependencies. We must therefore + now check to see if the option has appeared the required number of + times. In the absence of a max count, our limit must be one and we + only check for presence. If a max count exists, then we will also + have kept the occurrence count. Check that against the limit. +][+ + + IF (not (exist? "max")) + +]! HAVE_OPT( [+ (. OPT-NAME) +] )[+ + ELSE max ct exists + +]DESC([+(. OPT-NAME)+]).optOccCt < DESC([+(. OPT-NAME)+]).optMinCt[+ + ENDIF +])[+ + + ENDIF +] + usage_too_few (&DESC([+(. OPT-NAME) +])); +[+ + ENDIF +][+ +ENDFOR +] + return 0; +} +[+ ESAC +][+ + +DEFINE emit-usage-string +][+ + + (out-push-new) +][+ + INCLUDE "usage.tlib" +][+ + (kr-string (string-append (shell (string-append + "sed -e '/version information/s/ -v \\[arg\\]/ -v /' \ + -e '/: illegal option --/d' \ + -e 's/ --version\\[=arg\\]/ --version /' <<_EOF_\n" + (out-pop #t) "\n_EOF_" + )) "\n" )) +][+ + +ENDDEF + +# end of getopt.tpl \+] diff --git a/autoopts/tpl/gpl.lic b/autoopts/tpl/gpl.lic new file mode 100644 index 0000000..47cdf95 --- /dev/null +++ b/autoopts/tpl/gpl.lic @@ -0,0 +1,20 @@ +<PFX>Copyright (C) <years> <owner>, all rights reserved. +<PFX>This is free software. It is licensed for use, modification and +<PFX>redistribution under the terms of the +<PFX>GNU General Public License, version 3 or later +<PFX> <http://gnu.org/licenses/gpl.html> + +<PFX><program> is free software: you can redistribute it and/or modify it +<PFX>under the terms of the GNU General Public License as published by the +<PFX>Free Software Foundation, either version 3 of the License, or +<PFX>(at your option) any later version. +<PFX> +<PFX><program> is distributed in the hope that it will be useful, but +<PFX>WITHOUT ANY WARRANTY; without even the implied warranty of +<PFX>MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +<PFX>See the GNU General Public License for more details. +<PFX> +<PFX>You should have received a copy of the GNU General Public License along +<PFX>with this program. If not, see <http://www.gnu.org/licenses/>. + +the GNU General Public License, version 3 or later diff --git a/autoopts/tpl/gplv2.lic b/autoopts/tpl/gplv2.lic new file mode 100644 index 0000000..31965d3 --- /dev/null +++ b/autoopts/tpl/gplv2.lic @@ -0,0 +1,19 @@ +<PFX>Copyright (C) <years> <owner>, all rights reserved. +<PFX>This is free software. It is licensed for use, modification and +<PFX>redistribution under the terms of the +<PFX>GNU General Public License, version 2 <http://gnu.org/licenses/gpl.html> + +<PFX><program> is free software: you can redistribute it and/or modify it +<PFX>under the terms of version 2 of the GNU General Public License, +<PFX>as published by the Free Software Foundation. +<PFX> +<PFX><program> is distributed in the hope that it will be useful, but +<PFX>WITHOUT ANY WARRANTY; without even the implied warranty of +<PFX>MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +<PFX>See the GNU General Public License for more details. +<PFX> +<PFX>You should have received a copy of the GNU General Public License, +<PFX>version 2, along with this program. +<PFX>If not, see <http://www.gnu.org/licenses/>. + +the GNU General Public License, version 2 diff --git a/autoopts/tpl/lgpl.lic b/autoopts/tpl/lgpl.lic new file mode 100644 index 0000000..86c7cf6 --- /dev/null +++ b/autoopts/tpl/lgpl.lic @@ -0,0 +1,20 @@ +<PFX>Copyright (C) <years> <owner>, all rights reserved. +<PFX>This is free software. It is licensed for use, modification and +<PFX>redistribution under the terms of the +<PFX>GNU Lesser General Public License, version 3 or later +<PFX> <http://gnu.org/licenses/lgpl.html> + +<PFX><program> is free software: you can redistribute it and/or modify it +<PFX>under the terms of the GNU Lesser General Public License as published +<PFX>by the Free Software Foundation, either version 3 of the License, or +<PFX>(at your option) any later version. +<PFX> +<PFX><program> is distributed in the hope that it will be useful, but +<PFX>WITHOUT ANY WARRANTY; without even the implied warranty of +<PFX>MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +<PFX>See the GNU Lesser General Public License for more details. +<PFX> +<PFX>You should have received a copy of the GNU Lesser General Public License +<PFX>along with this program. If not, see <http://www.gnu.org/licenses/>."; + +the GNU Lesser General Public License, version 3 or later diff --git a/autoopts/tpl/man2mdoc.pl b/autoopts/tpl/man2mdoc.pl new file mode 100755 index 0000000..64d3570 --- /dev/null +++ b/autoopts/tpl/man2mdoc.pl @@ -0,0 +1,279 @@ +#!/usr/bin/perl + +use strict; + +my ($taglist , $optlistold, $paraold, $parafirstval,$List, + $indentation,$isindentated); + +my ($line); + +$isindentated = 0; #this variable is used check the indentation +$indentation = 0; #this variable is used to set the indentation if given +$List = 0; +$parafirstval = 0; +$paraold = 0; +$taglist = 0; ### 1 = taglist, 0 = other list types except taglist +$optlistold = 0; ## 1 = previous list entry was there, 0 = not + +while ($line = <STDIN>) +{ + if ($line !~ /^\./ ) { + if ($line =~ /[\\fB|\\fI]/) { + MakeMacro($line); + print "\n"; + next; + } + + print $line; + next; + } + + $line =~ s/^\.//; + + next + if ($line =~ /\\"/); + + $line = ParseMacro($line); + + print($line) + if (defined $line); +} + +sub ParseMacro +{ + my ($line) = @_; + + my (@words,$retval); + $retval = ''; + @words = split(/\s+/,$line); + + while($_ = shift (@words)) { + if (/^sp$/ || /^ne$/ || /^na$/|| /^rt$/|| /^mk$/|| /^ad$/) { + last; + } + + if (/^RS$/) { + $List = 1; + # this is to check whether that indentation value is given, + # if it is not given tha means we have to use default indentation, + # if it is given we need to check for that value + # + $isindentated = scalar(@words); + + if ($isindentated) { + if ($_ = shift (@words)) + { + $indentation = 1; + last; + } + $indentation = 0; + last; + } + $indentation = 1; + last; + } + + if (/^IP$/ && $List) { + if (!$optlistold) { + $optlistold = 1; + $taglist = 1; + + if ($indentation) { + $retval .= ".Bl -tag -offset indent -compact\n"; + } else { + $retval .= ".Bl -tab -offset 0n -compact\n"; + } + print $retval; + $words[0] =~ s/\\fB/ Nm /; + $words[0] =~ s/\\fI/ Ar /; + $words[0] =~ s/\\fR/ /g; + + print ".It ".$words[0]."\n"; + last; + + } + + if ($optlistold) { + $words[0] =~ s/\\fB/ Nm /; + $words[0] =~ s/\\fI/ Ar /; + $words[0] =~ s/\\fR/ /g; + print ".It ".$words[0]."\n"; + last; + } + } + + if (/^TP$/ && $List) { + if (!$optlistold) + { + $optlistold = 1; + $taglist = 1; + + if ($indentation) { + $retval .= ".Bl -tag -offset indent -compact\n"; + } else { + $retval .= ".Bl -tab -offset 0n -compact\n"; + } + print $retval; + $retval = <DATA>; + + $retval =~ s/\\fB/ Nm /; + $retval =~ s/\\fI/ Ar /; + $retval =~ s/\\fR/ /g; + + print ".It ".$retval."\n"; + last; + } + + if ($optlistold) { + $retval = <DATA>; + $retval =~ s/\\fB/ Nm /; + $retval =~ s/\\fI/ Ar /; + $retval =~ s/\\fR/ /g; + print ".It ".$retval."\n"; + last; + } + } + + if (/^RE$/) { + $indentation = 0; + $optlistold = 0; + $isindentated = 0; + + $optlistold = 0; + + } + + if (/^IP$/ && !$List) + { + if (!$optlistold && $words[0] =~ /^\\\(bu$/) { + $optlistold = 1; + $retval .= ".Bl -bullet"."\n"; + print $retval; + print ".It \n"; + last; + } + + + if (!$optlistold && $words[0] =~ /^-$/) { + $optlistold = 1; + $retval .= ".Bl -dash \n"; + print $retval; + print ".It \n"; + last; + } + + + if (!$optlistold && $words[0] =~ /^[1-9]\.$/) { + $optlistold = 1; + $retval .= ".Bl -enum \n"; + print $retval; + print ".It \n"; + last; + + } + + if (!$optlistold && $words[0] !~ /[0-9|-|(br]/) { + $optlistold = 1; + $taglist = 1; + $retval .= ".Bl -tag \n"; + print $retval; + print ".It ".$words[0]."\n"; + last; + } + + if (!$optlistold) { + $optlistold = 1; + $retval .= ".Bl -item \n"; + print $retval; + print ".It \n"; + last; + + } + + if ($optlistold) { + print ".It \n"; + last + } + } + + if ($optlistold && ! /^IP$/ ) { + $optlistold = 0; + print ".El \n"; + } + + if (/^TP$/) { + $parafirstval = 1; + + if (!$paraold) { + $retval .= ".Bl -tag \n"; + print $retval; + print ".It "; + $paraold = 1; + last; + } + + if ($paraold) { + print ".It "; + $paraold = 1; + last; + } + } + + #text bolding (mdoc : .Nm ntpq) (man : .B ntpq ) + if (/^RS$/) { + $List = 1; + } + + if (/^B$/) { + $retval .= ".Nm ".join(' ',@words)."\n"; + print $retval; + } + + #text bolding () + if (/\\fB/) { + $retval = $_; + $retval =~ s/[\\fB|\\fP]//g; + print ".Nm ".$retval."\n"; + } + + if (/\\fI/) { + $retval = $_; + $retval =~ s/[\\fI|\\fP]//g; + print ".Em ".$retval."\n"; + } + + if (/^I$/) { + $retval .= ".Em ".join(' ',@words)."\n"; + print $retval; + } + + if (/^PP$/) { + print "\n"; + } + + if (/^LP$/) { + print "\n"; + } + } +} + +sub MakeMacro +{ + my (@words); + @words = split(/\s+/,$line); + while($_ = shift (@words)) + { + if (/\\fB/ or /\\fI/) { + print "\n"; + $_ =~ s/\\fB/\.Nm /; + $_ =~ s/\\fI/\.Ar /; + $_ =~ s/\\fR//g; + + print $_; + print"\n"; + next; + } + + print $_." "; + } +} diff --git a/autoopts/tpl/man2texi.sh b/autoopts/tpl/man2texi.sh new file mode 100755 index 0000000..6578a51 --- /dev/null +++ b/autoopts/tpl/man2texi.sh @@ -0,0 +1,29 @@ +#! /bin/sh + +## man2texi.sh -- script to convert man page isms to texi-isms +## +## Time-stamp: "2012-02-12 09:25:29 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +sed \ + -e 's;\\fB\([^\\]*\)\\fP;@var{\1};' \ + -e 's;\\fI\([^\\]*\)\\fP;@i{\1};' diff --git a/autoopts/tpl/mbsd.lic b/autoopts/tpl/mbsd.lic new file mode 100644 index 0000000..2537463 --- /dev/null +++ b/autoopts/tpl/mbsd.lic @@ -0,0 +1,31 @@ +<PFX>Copyright (C) <years> <owner>, all rights reserved. +<PFX>This is free software. It is licensed for use, modification and +<PFX>redistribution under the terms of the +<PFX>Modified (3 clause) Berkeley Software Distribution License +<PFX> <http://www.xfree86.org/3.3.6/COPYRIGHT2.html> + +<PFX>Redistribution and use in source and binary forms, with or without +<PFX>modification, are permitted provided that the following conditions +<PFX>are met: +<PFX>1. Redistributions of source code must retain the above copyright +<PFX> notice, this list of conditions and the following disclaimer. +<PFX>2. Redistributions in binary form must reproduce the above copyright +<PFX> notice, this list of conditions and the following disclaimer in the +<PFX> documentation and/or other materials provided with the distribution. +<PFX>3. Neither the name ``<owner>'' nor the name of any other +<PFX> contributor may be used to endorse or promote products derived +<PFX> from this software without specific prior written permission. +<PFX> +<PFX><program> IS PROVIDED BY <owner> ``AS IS'' AND ANY EXPRESS +<PFX>OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +<PFX>WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +<PFX>ARE DISCLAIMED. IN NO EVENT SHALL <owner> OR ANY OTHER CONTRIBUTORS +<PFX>BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +<PFX>CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +<PFX>SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +<PFX>BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +<PFX>WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +<PFX>OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +<PFX>ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +the Modified Berkeley Software Distribution License diff --git a/autoopts/tpl/mdoc2man.sh b/autoopts/tpl/mdoc2man.sh new file mode 100755 index 0000000..815f716 --- /dev/null +++ b/autoopts/tpl/mdoc2man.sh @@ -0,0 +1,298 @@ +#! /bin/sh + +## mdoc2man.sh -- script to convert mdoc-isms to man-isms +## +## Time-stamp: "2012-04-15 07:38:27 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +## This "library" converts mdoc-isms into man-isms. It gets included +## by the man page template at the point where mdoc-isms might start appearing +## and then "emit-man-text" is invoked when all the text has been assembled. +## +## Display the command line prototype, +## based only on the argument processing type. +## +## And run the entire output through "sed" to convert mdoc-isms + +# /bin/sh on Solaris is too horrible for words +# +case "$0" in +/bin/sh ) test -x /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh ${1+"$@"} ;; +esac + +parent_pid=$$ +prog=`basename $0 .sh` +NmName= + +die() { + echo "$prog error: $*" >&2 + ps -p ${AG_pid:-999999999} >/dev/null 2>&1 && \ + kill -TERM ${AG_pid} + kill -TERM $parent_pid + sleep 1 + kill -9 $parent_pid + sleep 1 + exit 1 +} + +had_no_arg() { + die "'$1' command had no argument: <$line>" +} + +# One function for each mdoc structure. +# +do_nest_enum() { + do_enum +} + +do_enum() { + echo '.in +4' + local ix=1 + + while IFS='' read -r line + do + case "${line}" in + .It* ) printf '.ti -4\n%d\n\t' $ix + ix=`expr $ix + 1` + ;; + + .Bl' '*enum* ) do_nest_enum ;; + .Bl' '*tag* ) do_nest_tag ;; + .Bl' '*bullet* ) do_nest_bullet ;; + .Bd' '* ) do_nest_block ;; + .Op' '* ) do_nest_optional ;; + .Fl' '* ) do_nest_flag ;; + .Ar' '* ) do_nest_arg ;; + + .El* ) echo '.in -4' + return 0 ;; + + * ) echo "$line" ;; + esac + done + die "EOF reached processing '.Bl -enum'" +} + +do_nest_tag() { + echo '.in +4' + while IFS='' read -r line + do + case "${line}" in + .It* ) printf '.ti -4\n.IR ' + echo ${line#.It} ;; + + .Bl' '*enum* ) do_nest_enum ;; + .Bl' '*tag* ) do_nest_tag ;; + .Bl' '*bullet* ) do_nest_bullet ;; + .Bd' '* ) do_nest_block ;; + .Op' '* ) do_nest_optional ;; + .Fl' '* ) do_nest_flag ;; + .Ar' '* ) do_nest_arg ;; + + .El* ) echo '.in -4' + return 0 ;; + + * ) echo "$line" ;; + esac + done + die "EOF reached processing '.Bl -tag'" +} + +do_tag() { + while IFS='' read -r line + do + case "${line}" in + .It* ) printf '.TP\n.BR ' + echo ${line#.It} ;; + + .Bl' '*enum* ) do_nest_enum ;; + .Bl' '*tag* ) do_nest_tag ;; + .Bl' '*bullet* ) do_nest_bullet ;; + .Bd' '* ) do_nest_block ;; + .Op' '* ) do_nest_optional ;; + .Fl' '* ) do_nest_flag ;; + .Ar' '* ) do_nest_arg ;; + .El* ) return 0 ;; + * ) echo "$line" ;; + esac + done + die "EOF reached processing '.Bl -tag'" +} + +do_nest_bullet() { + do_bullet +} + +do_bullet() { + echo '.in +4' + while IFS='' read -r line + do + case "${line}" in + .It* ) printf '.ti -4\n\\fB*\\fP\n' + echo ${line#.It} + ;; + + .Bl' '*enum* ) do_nest_enum ;; + .Bl' '*tag* ) do_nest_tag ;; + .Bl' '*bullet* ) do_nest_bullet ;; + .Bd' '* ) do_nest_block ;; + .Op' '* ) do_nest_optional ;; + .Fl' '* ) do_nest_flag ;; + .Ar' '* ) do_nest_arg ;; + + .El* ) echo '.in -4' + return 0 ;; + + * ) echo "$line" ;; + esac + done + die "EOF reached processing '.Bl -bullet'" +} + +do_nest_block() { + do_block +} + +do_block() { + printf '.br\n.in +4\n.nf\n' + while IFS='' read -r line + do + case "${line}" in + .B* ) die ".Bx command nested within .Bd" ;; + + .Ed* ) echo .in -4 + echo .fi + return 0 ;; + + * ) echo "$line" ;; + esac + done + die "EOF reached processing '.Bd'" +} + +do_nest_optional() { + do_optional +} + +do_optional() { + set -- $line + shift + local text='[' + while test $# -gt 0 + do + m1="$1" + case "X$1" in + 'X...' | 'X\*' ) + text=${text}' "\fI'${1}'\fR"' + shift + ;; + XAr | XCm ) + text=${text}' "\fI'${2}'\fR"' + shift 2 || had_no_arg "$m1" + ;; + XFl ) + text=${text}' \fB-'${2}'\fR' + shift 2 || had_no_arg "$m1" + ;; + * ) text="${text} \"$2\"" + m1="$1" + shift 2 || had_no_arg "$m1" + ;; + esac + done + echo "${text} ]" +} + +do_nest_flag() { + do_flag +} + +do_flag() { + echo ${line#.Fl} +} + +do_nest_arg() { + do_arg +} + +do_arg() { + line=`echo ${line#.Ar}` + echo "\\fI${line}\\fR" +} + +do_NmName() { + # do we want to downcase the line first? Yes... + set -- `echo ${line#.Nm} | \ + sed -e 's/-/\\-/g' \ + -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + NmNameSfx= + + if test $# -gt 0 + then case "$1" in + [A-Za-z]* ) + NmName=$1 + shift + ;; + esac + + test $# -gt 0 && NmNameSfx=" $*" + fi + echo ".B $NmName$NmNameSfx" +} + +do_line() { + case "${line}" in + .Bl' '*enum* ) do_enum ;; + .Bl' '*tag* ) do_tag ;; + .Bl' '*bullet* ) do_bullet ;; + .Bd' '* ) do_block ;; + .Op' '* ) do_optional ;; + .Fl' '* ) do_flag ;; + .Ar' '* ) do_arg ;; + .Nm' '* ) do_NmName ;; + .Nm ) do_NmName ;; + * ) echo "$line" ;; + esac + return 0 +} + + + +easy_fixes=' +s/^\.Sh/.SH/ +s/^\.Ss/.SS/ +s/^\.Em/.I/ +s/^\.Pp/.PP/ +s/^.in *\\-/.in -/ +' + +readonly easy_fixes +set -f + +{ + while IFS='' read -r line + do + do_line + done +} | sed "${easy_fixes}" + +exit 0 diff --git a/autoopts/tpl/mdoc2texi.pl b/autoopts/tpl/mdoc2texi.pl new file mode 100755 index 0000000..859690e --- /dev/null +++ b/autoopts/tpl/mdoc2texi.pl @@ -0,0 +1,345 @@ +#! /usr/bin/perl + +use strict; + +my ($optlist,$oldoptlist); +my ($literal); +my ($line); +my ($count,$tableitemcount); +my ($progName); +my (@words, $retval,$columnline); + +$optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag, 4 = item +$oldoptlist = 0; + +while ($line = <STDIN>) +{ + if ($line !~ /^\./) + { + print $line; + print ".br\n" + if ($literal); + next; + } + + next + if ($line =~ /^\.\\"/); + + $line = ParseMacro($line); + print($line) + if (defined $line); +} + +sub Handle_Bl +{ + if ($words[0] eq '-bullet') + { + if (!$optlist) + { + $optlist = 1; #bullet + $retval .= "\@itemize \@bullet\n" ; + print "$retval"; + return 1; + } + else + { + $retval .= "\@itemize \@minus\n"; + print $retval; + $oldoptlist = 1; + return 1; + } + } + if ($words[0] eq '-enum') + { + if (!$optlist) + { + $optlist = 2; #enum + $retval .= "\@enumerate\n" ; + print "$retval"; + return 1; + } + else + { + $retval .= "\@enumerate\n"; + print $retval; + $oldoptlist = 2; + return 1; + } + } + if ($words[0] eq '-tag') + { + $optlist = 3; #tag + $retval .= "\@table \@samp\n"; + print "$retval"; + return 1; + } + if ($words[0] eq '-column') + { + $optlist = 4; #column + $retval = "\@multitable \@columnfractions ";#\.20 \.20 \.20\n"; + #print $retval; + $columnline = "\@headitem "; + #print $retval; + foreach(@words) + { + if (!/^"./ && !/-column/ && !/indent/ && !/-offset/) + { + $_ =~ s/\"//g; + + $retval .= "\.20 "; + if (!$count) + { + $columnline .= $_; + } + else + { + $columnline .= " \@tab ".$_; + } + $count++; + } + } + print $retval."\n"; + print $columnline; + return 1; + } + + return 0; +} + +sub Handle_It +{ + if ($optlist == 3) + { + $retval .= "\@item ".$words[0]."\n"; + print $retval; + return 1; + } + elsif ($optlist == 4 ) + { + if (!$tableitemcount) + { + $tableitemcount = 1; + return 1; + } + else + { + foreach(@words) + { + if (/^Li$/) + { + print "\n\@item "; + return 0; + } + elsif (/^Ta$/) + { + print "\n\@tab "; + return 0; + } + else + { + print $_; + return 0; + } + } + return 1; + } + } + else + { + print "\@item\n"; + } + return 0; +} + +sub Handle_El +{ + if ($oldoptlist) + { + if ($oldoptlist == 1) + { + $oldoptlist = 0; + $retval .= "\@end itemize\n"; + print $retval; + } + elsif ($oldoptlist == 2) + { + $oldoptlist = 0; + $retval .= "\@end enumerate\n"; + print $retval; + } + } + else + { + if ($optlist == 1) + { + $oldoptlist = 0; + $retval .= "\@end itemize\n"; + print $retval; + } + elsif ($optlist == 2) + { + $oldoptlist = 0; + $retval .= "\@end enumerate\n"; + print $retval; + } + elsif ($optlist = 4) + { + $count = 0; + $columnline = ''; + $oldoptlist = 0; + $optlist = 0; + $tableitemcount = 0; + $retval .= "\n\@end multitable\n"; + print $retval; + } + $optlist = 0; + } +} + +sub Handle_Fl +{ + # .Cm is .Fl but no '-'. + # Usage: .Fl <argument> ... + # + # .Fl - + # .Fl cfv -cfv + # .Fl cfv . -cfv. + # .Cm cfv . cfv. + # .Fl s v t -s -v -t + # .Fl - , --, + # .Fl xyz ) , -xyz), + # .Fl | - | + # + my ($dash, $didOne); + $dash = "-"; # or empty if .Cm + $didOne = 0; + + do { + if ($words[0] eq '' || $words[0] =~ /^[-\w]+$/) + { + print " " if $didOne; + print '@code{', $dash, $words[0], '}'; + } + elsif ($words[0] eq '|') + { + print " " if $didOne; + print '@code{', $dash, '}', " $words[0]"; + } + else + { + print "$words[0]"; + } + shift @words; + $didOne = 1; + } while scalar(@words); + print " "; +} + +sub Handle_Nm +{ + # Usage: .Nm [<argument>] ... + # + # .Nm groff_mdoc groff_mdoc + # .Nm \-mdoc -mdoc + # .Nm foo ) ) , foo)), + # .Nm : groff_mdoc: + # + if (!defined $progName) + { + if (defined $ENV{AG_DEF_PROG_NAME}) + { + $progName = $ENV{AG_DEF_PROG_NAME}; + } + else + { + $progName = "XXX Program Name"; + } + } + + if ($words[0] =~ /^[\\\w]/) + { + $progName = shift @words; + } + print '@code{', $progName, '}'; + + # Anything after this should be punctuation + + while ($_ = shift @words) + { + print; + } + print "\n"; +} + +sub Handle_Xr +{ + # Usage: .Xr <man page name> [<section>] ... + # .Xr mdoc mdoc + # .Xr mdoc , mdoc, + # .Xr mdoc 7 mdoc(7) + # .Xr xinit 1x ; xinit(1x); + # + # Emitting things like @uref{/man.cgi/1/ls,,ls} would be OK, + # but we'd have to allow for changing /man.cgi/ (at least). + # I'm OK with: + # @code{mdoc} + # @code{mdoc}, + # @code{mdoc(7)} + # @code{xinit(1x); + # + my ($xr_cmd, $xr_sec, $xr_punc); + if (@words == 1) + { + $xr_cmd = $words[0]; + } + elsif (@words == 2) + { + $xr_cmd = shift @words; + if ($words[0] =~ /[[:punct:]]/) + { + $xr_punc = shift @words; + } + else + { + $xr_sec = shift @words; + } + } + elsif (@words == 3) + { + $xr_cmd = shift @words; + $xr_sec = shift @words; + $xr_punc = shift @words; + } + else + { + } + + # HMS: do we really want 'defined' in the following tests? + print '@code{',"$xr_cmd" if (defined $xr_cmd); + print "($xr_sec)" if (defined $xr_sec); + print "}" if (defined $xr_cmd); + print "$xr_punc" if (defined $xr_punc); + print "\n"; +} + +sub ParseMacro #line +{ + my ($line) = @_; + + @words = split(/\s+/, $line); + $retval = ''; + + # print('@words = ', scalar(@words), ': ', join(' ', @words), "\n"); + + while ($_ = shift @words) + { + if (/^\.Bl$/) { last if (Handle_Bl()); } + elsif ($optlist && /^\.It$/) { last if (Handle_It()); } + elsif (/^\.El$/) { Handle_El(); } + elsif (/^\.Fl$/) { Handle_Fl(); } + elsif (/^\.Nm/) { Handle_Nm(); } + elsif (/^\.Pp$/) { print "\n"; } + elsif (/^\.Xr/) { Handle_Xr(); } + else { print $_,"\n"; } + } +} diff --git a/autoopts/tpl/optcode.tlib b/autoopts/tpl/optcode.tlib new file mode 100644 index 0000000..9f519ae --- /dev/null +++ b/autoopts/tpl/optcode.tlib @@ -0,0 +1,819 @@ +[= autogen5 template + +# Time-stamp: "2012-08-11 08:31:28 bkorb" +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= + +;;; +;;; Compute the usage line. It is complex because we are trying to +;;; encode as much information as we can and still be comprehensible. +;;; +;;; The rules are: If any options have a "value" attribute, then +;;; there are flags allowed, so include "-<flag>" on the usage line. +;;; If the program has the "long-opts" attribute set, then we must +;;; have "<option-name>" or "--<name>" on the line, depending on +;;; whether or not there are flag options. If any options take +;;; arguments, then append "[<val>]" to the flag description and +;;; "[{=| }<val>]" to the option-name/name descriptions. We will not +;;; worry about being correct if every option has a required argument. +;;; Finally, if there are no minimum occurrence counts (i.e. all +;;; options are optional), then we put square brackets around the +;;; syntax. +;;; +;;; Compute the option arguments +;;; +(define tmp-val "") +(if (exist? "flag.arg-type") + (set! tmp-val "[{=| }<val>]")) + +(define usage-line (string-append "USAGE: %s " + + ;; If at least one option has a minimum occurrence count + ;; we use curly brackets around the option syntax. + ;; + (if (not (exist? "flag.min")) "[ " "{ ") + + (if (exist? "flag.value") + (string-append "-<flag>" + (if (exist? "flag.arg-type") " [<val>]" "") + (if (exist? "long-opts") " | " "") ) + (if (not (exist? "long-opts")) + (string-append "<option-name>" tmp-val) "" ) ) + + (if (exist? "long-opts") + (string-append "--<name>" tmp-val) "" ) + + (if (not (exist? "flag.min")) " ]..." " }...") +) ) + +(if (exist? "argument") + (set! usage-line (string-append usage-line + + ;; the USAGE line plus the program name plus the argument goes + ;; past 80 columns, then break the line, else separate with space + ;; + (if (< 80 (+ (string-length usage-line) + (len "argument") + (string-length prog-name) )) + " \\\n\t\t" + " " + ) + + (get "argument") + )) +) + +(define usage-text (string-append prog-name + (if (exist? "package") + (string-append " (" (get "package") ")") + "" ) + " - " (get "prog-title") + (if (exist? "version") + (string-append " - Ver. " (get "version")) + "" ) + "\n" usage-line "\n" +)) + +=][= # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +INCLUDE "optmain.tlib" + +=][= + +IF (or (= "shell-process" (get "main.main-type")) + (= "shell-parser" (get "main.main-type")) + (exist? "main.code")) =] +#define [= (set! make-test-main #t) main-guard =] 1[= +ENDIF +=] +#ifndef __doxygen__ +#define OPTION_CODE_COMPILE 1 +#include "[= (define lib-externs "") header-file=]"[= + +IF (== (get "main.main-type" "") "for-each") + +=] +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h>[= + +ELSE + +=] +#include <sys/types.h> + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h>[= + + (if (exist? "flag.arg-range") + (emit "\n#include <errno.h>")) + + (if (and (exist? "resettable") (exist? "flag.open-file")) + (emit " +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h>" )) =][= + +ENDIF + +=] + +#ifdef __cplusplus +extern "C" { +#endif +extern FILE * option_usage_fp; + +/* TRANSLATORS: choose the translation for option names wisely because you + cannot ever change your mind. */[= + +IF (not (exist? "copyright")) + +=] +#define zCopyright NULL +#define zLicenseDescrip NULL[= +ELSE =][= + (define cright-owner (get "copyright.owner" (get "copyright.author"))) + =][= + CASE (get "copyright.type") =][= + = note =][= + (set! tmp-text (get "copyright.text")) + (define ext-text tmp-text) =][= + + ~~* . =][= + (define ext-text + (license-description (get "copyright.type") + prog-name "" cright-owner ) ) + + (set! tmp-text + (license-info (get "copyright.type") + prog-name "" cright-owner (get "copyright.date") ) ) + =][= + + * =][= + (set! tmp-text (sprintf + "Copyright (C) %s %s, all rights reserved" + (get "copyright.date") cright-owner )) + (define ext-text tmp-text) =][= + + ESAC =][= + +(set! tmp-text (string-append version-text "\n" tmp-text)) +(string-append "\n#define zCopyright (" + (string-table-add-ref opt-strs tmp-text) + ")\n#define zLicenseDescrip (" + + (if (= tmp-text ext-text) + "zCopyright" + (begin + (set! ext-text (string-append (shell (string-append + "${CLexe} --fill -I0 -W75 <<_EOF_\n" ext-text "\n_EOF_" )) "\n" )) + + (string-table-add-ref opt-strs ext-text) + ) ) + ")\n" ) =][= + +ENDIF "copyright" =][= + + (define usage-proc (get "usage")) + (if (< 1 (string-length usage-proc)) + (emit (string-append "\nextern tUsageProc " usage-proc ";")) + (set! usage-proc "optionUsage") + ) + +=] +[= INVOKE join-or-expand join-type = "include" =] +#ifndef NULL +# define NULL 0 +#endif + +/* + * [= prog-name =] option static const strings + */[= + (out-resume "home-list") \=][= + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +FOR flag "\n" =][= + (define flag-index (for-index)) =][= + INVOKE emit-opt-strs =][= + + (if (exist? "lib-name") (begin + (set! lib-opt-ptr (string->c-name! (string-append + (get "lib-name") "_" (get "name") "_optDesc_p"))) + (set! lib-externs (string-append lib-externs + (sprintf "tOptDesc * const %-16s = optDesc + %d;\n" + lib-opt-ptr (for-index) ) )) + ) ) =][= + +ENDFOR flag =][= + +INVOKE help-strs =][= +INVOKE decl-callbacks =][= + +IF (exist? "version") =][= + + IF (exist? "version-proc") =] +#define VER_PROC [= (get "version-proc") =][= + ELIF (. make-test-main) =] +#ifdef [=(. main-guard) =] +# define VER_PROC optionVersionStderr +#else +# define VER_PROC optionPrintVersion +#endif /* [=(. main-guard)=] */[= + ELSE =] +#define VER_PROC optionPrintVersion[= + ENDIF make-test-main =][= + +ENDIF there is a version + +=] +[= INVOKE emit-option-desc-table =] +[= (. lib-externs) =] +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Define the [= (. prog-name) =] Option Environment + */ +#define zPROGNAME ([= (string-table-add-ref opt-strs pname-up) =]) +#define zUsageTitle ([= + (define homerc-ct 0) + (define homerc-txt "") + (string-table-add-ref opt-strs usage-text) =]) +[= +FOR homerc =][= + (set! tmp-text (get "homerc")) + (if (> (string-length tmp-text)) (begin + (set! homerc-ct (+ 1 homerc-ct)) + (set! homerc-txt (string-append homerc-txt + "\n " (string-table-add-ref opt-strs tmp-text) "," )) + ) ) =][= +ENDFOR homerc =][= +IF (> homerc-ct 0) \=] +#define zRcName ([= + (set! tmp-text (if (exist? "rcfile") (get "rcfile") + (string-append "." pname-down "rc") )) + (string-table-add-ref opt-strs tmp-text) =]) +static char const * const apzHomeList[= + (sprintf "[%u] = {%s\n NULL };" (+ 1 homerc-ct) homerc-txt) =][= + +ELSE \=] +#define zRcName NULL +#define apzHomeList NULL[= +ENDIF =] +#define zBugsAddr ([= +(out-push-new) \=] +s/@[a-z]*{\([^{@}]*\)}/``\1''/g +s=@<prog-name>@=[= prog-name =]=g +/^@\(end *\)*example/d +s/^@item *$/\ +/[= + +(define patch-text-sed + (sprintf "sed %s <<\\_EODetail_ | ${CLexe} --fill -I0 -W75\n" + (raw-shell-str (out-pop #t)) ) ) + +(define patch-text (lambda (t-name) + (set! tmp-text (string-append "\n" + + (shell (string-append + patch-text-sed + (get t-name) + "\n_EODetail_" )) + "\n" )) )) + +(if (exist? "copyright.eaddr") + (string-table-add-ref opt-strs (get "copyright.eaddr")) + (if (exist? "eaddr") + (string-table-add-ref opt-strs (get "eaddr")) + "NULL" +) ) =]) +#define zExplain ([= + +(if (or (exist? "explain") (== (get "main.main-type") "for-each")) + (begin + (if (exist? "explain") + (patch-text "explain") + (set! tmp-text "") ) + + (if (== (get "main.main-type") "for-each") + (set! tmp-text (string-append tmp-text +"\nIf no arguments are provided, input arguments are read from stdin, +one per line; blank and '#'-prefixed lines are comments. +'stdin' may not be a terminal (tty).\n" )) ) + + (string-table-add-ref opt-strs tmp-text) + ) + "NULL" +) =]) +#define zDetail ([= + +(if (exist? "detail") + (begin + (patch-text "detail") + (string-table-add-ref opt-strs tmp-text) + ) + "NULL" +) =]) +#define zFullVersion ([= + +(if (exist? "version") + (string-table-add-ref opt-strs version-text) + "NULL") =])[= +(tpl-file-line extract-fmt) +=][= + + IF (. omit-nls-code) =] +#define OPTPROC_BASE OPTPROC_NONE +#define translate_option_strings NULL +[= ELSE =] +#if defined(ENABLE_NLS) +# define OPTPROC_BASE OPTPROC_TRANSLATE[= +CASE no-xlate =][= +!E =][= += opt-cfg =] | OPTPROC_NXLAT_OPT_CFG[= += opt =] | OPTPROC_NXLAT_OPT[= +* =][= (error "invalid value for 'no-xlate'") =][= +ESAC no-xlate =] + static tOptionXlateProc translate_option_strings; +#else +# define OPTPROC_BASE OPTPROC_NONE +# define translate_option_strings NULL +#endif /* ENABLE_NLS */ +[= ENDIF no-nls =][= + IF (exist? "resettable") =] +static optArgBucket_t const original_[=(. pname-down)=]_defaults[ [= +(. UP-prefix) =]OPTION_CT ] = { +[= (shell (string-append + "sed '$s@},@} @' <<\\_EOF_" default-text "\n_EOF_\n")) =] +}; +static void * const original_[=(. pname-down)=]_cookies[ [= +(. UP-prefix) =]OPTION_CT ] = { +[= + (shell (string-append "${CLexe} -I4 -S, <<\\_EOF_\n" default-cookie "_EOF_")) +=] +}; +[= ENDIF resettable=] +[= INVOKE usage-text usage-type = full \=] +[= INVOKE usage-text usage-type = short =] +#endif /* not defined __doxygen__ */ +[= INVOKE emit-option-callbacks =] +/** + * The directory containing the data associated with [= prog-name =]. + */ +#ifndef PKGDATADIR +# define PKGDATADIR "" +#endif + +/** + * Information about the person or institution that packaged [= prog-name =] + * for the current distribution. + */ +#ifndef WITH_PACKAGER +# define [=(. pname)=]_packager_info NULL +#else +static char const [=(. pname)=]_packager_info[] = + "Packaged by " WITH_PACKAGER + +# ifdef WITH_PACKAGER_VERSION + " ("WITH_PACKAGER_VERSION")" +# endif + +# ifdef WITH_PACKAGER_BUG_REPORTS + "\nReport [=(. pname)=] bugs to " WITH_PACKAGER_BUG_REPORTS +# endif + "\n"; +#endif +#ifndef __doxygen__ +[= + (out-suspend "home-list") =][= + (emit-string-table opt-strs) =][= + (out-resume "home-list") =][= + (out-pop #t) +=] +#endif /* __doxygen__ */ +/** + * The option definitions for [= prog-name =]. The one structure that + * binds them all. + */ +tOptions [=(. pname)=]Options = { + OPTIONS_STRUCT_VERSION, + 0, NULL, /* original argc + argv */ + ( OPTPROC_BASE[= IF (not (exist? "allow-errors")) =] + + OPTPROC_ERRSTOP[= ENDIF=][=IF (exist? "flag.value") =] + + OPTPROC_SHORTOPT[= ENDIF=][=IF (exist? "long-opts") =] + + OPTPROC_LONGOPT[= ENDIF=][=IF (not (exist? "flag.min")) =] + + OPTPROC_NO_REQ_OPT[= ENDIF=][=IF (exist? "flag.disable") =] + + OPTPROC_NEGATIONS[= ENDIF=][=IF (>= number-opt-index 0) =] + + OPTPROC_NUM_OPT[= ENDIF=][=IF (exist? "environrc") =] + + OPTPROC_ENVIRON[= ENDIF=][=IF (not (exist? "argument")) =] + + OPTPROC_NO_ARGS[= ELIF (not (==* (get "argument") "[" )) =] + + OPTPROC_ARGS_REQ[= ENDIF=][=IF (exist? "reorder-args") =] + + OPTPROC_REORDER[= ENDIF=][=IF (exist? "gnu-usage") =] + + OPTPROC_GNUUSAGE[= ENDIF=][=IF (exist? "no-misuse-usage") =] + + OPTPROC_MISUSE[= ENDIF=][=IF (exist? "vendor-opt") =] + + OPTPROC_VENDOR_OPT[= ENDIF=] ), + 0, NULL, /* current option index, current option */ + NULL, NULL, zPROGNAME, + zRcName, zCopyright, zLicenseDescrip, + zFullVersion, apzHomeList, zUsageTitle, + zExplain, zDetail, optDesc, + zBugsAddr, /* address to send bugs to */ + NULL, NULL, /* extensions/saved state */ + [= (. usage-proc) =], /* usage procedure */ + translate_option_strings, /* translation procedure */ + /* + * Indexes to special options + */ + { [= (if (exist? "no-libopts") "NO_EQUIVALENT" + (string-append INDEX-pfx "MORE_HELP")) + =], /* more-help option index */ + [=IF (and (exist? "homerc") (not (exist? "disable-save"))) + =][= (. INDEX-pfx) =]SAVE_OPTS[= + ELSE =]NO_EQUIVALENT[= + ENDIF=], /* save option index */ + [= (if (>= number-opt-index 0) number-opt-index "NO_EQUIVALENT") + =], /* '-#' option index */ + [= (if (>= default-opt-index 0) default-opt-index "NO_EQUIVALENT") + =] /* index of default opt */ + }, + [= (. option-ct) =] /* full option count */, [= + (count "flag")=] /* user option count */, + [= (. pname) =]_full_usage, [= (. pname) =]_short_usage, +[= IF (exist? "resettable") \=] + original_[=(. pname-down)=]_defaults, original_[=(. pname-down)=]_cookies, +[= ELSE \=] + NULL, NULL, +[= ENDIF \=] + PKGDATADIR, [=(. pname)=]_packager_info +}; +[= + +FOR lib-name + +=] +tOptDesc* [= (string->c-name! (get "lib-name")) =]_optDesc_p = NULL;[= + +ENDFOR =][= + +INVOKE emit-nls-code + +=] +#ifdef __cplusplus +} +#endif[= # + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-nls-code + +=][= IF (. omit-nls-code) =][= RETURN =][= ENDIF + +=] +#if ENABLE_NLS +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <autoopts/usage-txt.h> + +static char* AO_gettext(char const* pz); +static void coerce_it(void** s); + +/** + * AutoGen specific wrapper function for gettext. + * It relies on the macro _() to convert from English to the target + * language, then strdup-duplicates the result string. + * + * @param[in] pz the input text used as a lookup key. + * @returns the translated text (if there is one), + * or the original text (if not). + */ +static char * +AO_gettext(char const* pz) +{ + char* pzRes; + if (pz == NULL) + return NULL; + pzRes = _(pz); + if (pzRes == pz) + return pzRes; + pzRes = strdup(pzRes); + if (pzRes == NULL) { + fputs(_("No memory for duping translated strings\n"), stderr); + exit([=(. nomem-exit-code)=]); + } + return pzRes; +} + +static void coerce_it(void** s) { *s = AO_gettext(*s); +} + +/** + * Translate all the translatable strings in the [=(. pname)=]Options + * structure defined above. This is done only once. + */ +static void +translate_option_strings(void) +{ + tOptions * const pOpt = &[=(. pname)=]Options; + + /* + * Guard against re-translation. It won't work. The strings will have + * been changed by the first pass through this code. One shot only. + */ + if (option_usage_text.field_ct != 0) { + /* + * Do the translations. The first pointer follows the field count + * field. The field count field is the size of a pointer. + */ + tOptDesc * pOD = pOpt->pOptDesc; + char ** ppz = (char**)(void*)&(option_usage_text); + int ix = option_usage_text.field_ct; + + do { + ppz++; + *ppz = AO_gettext(*ppz); + } while (--ix > 0); +[= + FOR field IN pzCopyright pzCopyNotice pzFullVersion pzUsageTitle pzExplain + pzDetail pzPackager =] + coerce_it((void*)&(pOpt->[= field =]));[= + ENDFOR =][= + + IF (exist? "full-usage") =] + coerce_it((void*)&(pOpt->pzFullUsage));[= + ENDIF =][= + + IF (exist? "short-usage") =] + coerce_it((void*)&(pOpt->pzShortUsage));[= + ENDIF =] + option_usage_text.field_ct = 0; + + for (ix = pOpt->optCt; ix > 0; ix--, pOD++) + coerce_it((void*)&(pOD->pzText)); + } + + if ((pOpt->fOptSet & OPTPROC_NXLAT_OPT_CFG) == 0) { + tOptDesc * pOD = pOpt->pOptDesc; + int ix; + + for (ix = pOpt->optCt; ix > 0; ix--, pOD++) {[= + + FOR field IN pz_Name pz_DisableName pz_DisablePfx =][= + + (sprintf "\n coerce_it((void*)&(pOD->%1$s));" + (get "field")) =][= + + ENDFOR =] + } + /* prevent re-translation */ + [= (. pname) + =]Options.fOptSet |= OPTPROC_NXLAT_OPT_CFG | OPTPROC_NXLAT_OPT; + } +} + +#endif /* ENABLE_NLS */ +[= + +ENDDEF emit-nls-code + +=][= + +DEFINE emit-option-desc-table + +=] +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Define the [= prog-name =] Option Descriptions. + * This is an array of [=(. UP-prefix)=]OPTION_CT entries, one for each + * option that the [= prog-name =] program responds to. + */ +static tOptDesc optDesc[[= +(define default-text "") +(define default-cookie "") +UP-prefix +=]OPTION_CT] = {[= + +FOR flag "\n" =][= + (define flag-index (for-index)) =][= + + INVOKE emit-opt-desc =][= + +ENDFOR flag + +=][= + +IF (exist? "resettable") + +=] + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* resettable */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]RESET_OPTION, [= (. VALUE-pfx) =]RESET_OPTION, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]RESET_OPTION, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ RESET_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionResetOpt, + /* desc, NAME, name */ RESET_DESC, NULL, RESET_name, + /* disablement strs */ NULL, NULL },[= + +ENDIF + +=][= + +IF (exist? "version") =] + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* version */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]VERSION, [= (. VALUE-pfx) =]VERSION, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]VERSION, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ VER_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ VER_PROC, + /* desc, NAME, name */ VER_DESC, NULL, VER_name, + /* disablement strs */ NULL, NULL }, + +[= + +ENDIF =] + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* help */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]HELP, [= (. VALUE-pfx) =]HELP, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ doUsageOpt, + /* desc, NAME, name */ HELP_DESC, NULL, HELP_name, + /* disablement strs */ NULL, NULL }[= + +IF (not (exist? "no-libopts")) =], + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* more-help */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]MORE_HELP, [= (. VALUE-pfx) =]MORE_HELP, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]MORE_HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ MORE_HELP_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionPagedUsage, + /* desc, NAME, name */ MORE_HELP_DESC, NULL, MORE_HELP_name, + /* disablement strs */ NULL, NULL }[= + +ENDIF not have no-libopts =][= + +IF (exist? "usage-opt") =], + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* usage-opt */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]USAGE, [= (. VALUE-pfx) =]USAGE, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]USAGE, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ doUsageOpt, + /* desc, NAME, name */ USAGE_DESC, NULL, USAGE_name, + /* disablement strs */ NULL, NULL }[= + +ENDIF have usage-opt =][= + +IF (exist? "homerc") =][= + IF (not (exist? "disable-save")) =], + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* save-opts */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]SAVE_OPTS, [= + (if (not (exist? "disable-save")) + (string-append VALUE-pfx "SAVE_OPTS") + "0") =], + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]SAVE_OPTS, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) + | OPTST_ARG_OPTIONAL | OPTST_NO_INIT, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ NULL, + /* desc, NAME, name */ SAVE_OPTS_DESC, NULL, SAVE_OPTS_name, + /* disablement strs */ NULL, NULL }[= + + ENDIF disable-save does not exist =], + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* load-opts */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]LOAD_OPTS, [= + (if (not (exist? "disable-load")) + (string-append VALUE-pfx "LOAD_OPTS") + "0") =], + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]LOAD_OPTS, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, NOLIMIT, 0, + /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) + | OPTST_DISABLE_IMM[= + (if (exist? "disable-load") "| OPTST_NO_COMMAND") =], 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionLoadOpt, + /* desc, NAME, name */ [= + (if (exist? "disable-load") "NULL, NULL, NULL" + "LOAD_OPTS_DESC, LOAD_OPTS_NAME, LOAD_OPTS_name")=], + /* disablement strs */ [= + (if (exist? "disable-load") "NULL, NULL" + "NO_LOAD_OPTS_name, LOAD_OPTS_pfx")=] }[= + +ENDIF have homerc =][= + +IF (exist? "vendor-opt") =], + + { /* entry idx, value */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* vendor-opt */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + INDEX-pfx =]VENDOR_OPT, [= (. VALUE-pfx) =]VENDOR_OPT, + /* equiv idx value */ NO_EQUIVALENT, [= (. VALUE-pfx) =]VENDOR_OPT, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, NOLIMIT, 0, + /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) + | OPTST_IMM | OPTST_TWICE, 0, /* both directions */ + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionVendorOption, + /* desc, NAME, name */ VEND_DESC, NULL, VEND_name, + /* disablement strs */ NULL, NULL }[= + +ENDIF have vendor-opt =] +}; +[= + +ENDDEF emit-option-desc-table + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * opthead.tpl ends here */ \=] diff --git a/autoopts/tpl/opthead.tlib b/autoopts/tpl/opthead.tlib new file mode 100644 index 0000000..86e87bf --- /dev/null +++ b/autoopts/tpl/opthead.tlib @@ -0,0 +1,601 @@ +[= autogen5 template -*- Mode: C -*- + +# Time-stamp: "2012-08-11 08:56:26 bkorb" +# +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=] +/* + * This file contains the programmatic interface to the Automated + * Options generated for the [=prog-name=] program. + * These macros are documented in the AutoGen info file in the + * "AutoOpts" chapter. Please refer to that doc for usage help. + */ +[= (make-header-guard "autoopts") =][= +% config-header "\n#include \"%s\"" =] +#include <autoopts/options.h>[= +(if (or (exist? "usage-message") (exist? "die-code")) + "\n#include <stdarg.h>") =] +[= IF + + (define option-ct 0) + (define index-sep-str "") + + (set! max-name-len (+ max-name-len 2)) + (define index-fmt (sprintf "%%s\n %s%%-%ds=%%3d" INDEX-pfx max-name-len)) + + (define add-opt-index (lambda (opt-nm) (begin + (ag-fprintf 0 index-fmt index-sep-str opt-nm option-ct) + (set! option-ct (+ option-ct 1)) + (set! index-sep-str ",") + ) ) ) + + (not (exist? "library")) =] +/* + * Ensure that the library used for compiling this generated header is at + * least as new as the version current when the header template was released + * (not counting patch version increments). Also ensure that the oldest + * tolerable version is at least as old as what was current when the header + * template was released. + */ +#define AO_TEMPLATE_VERSION [=(. ao-template-ver)=] +#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \ + || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION) +# error option template version mismatches autoopts/options.h header + Choke Me. +#endif +[= ENDIF not a library =] +/* + * Enumeration of each option: + */ +typedef enum {[= +FOR flag =][= + (if (exist? "documentation") + (set! option-ct (+ option-ct 1)) + (add-opt-index (get-up-name "name")) + ) + =][= +ENDFOR flag =][= + +IF (exist? "library") =], + LIBRARY_OPTION_COUNT[= + +ELSE not exists library =][= + + (if (exist? "resettable") (add-opt-index "RESET_OPTION")) + (if (exist? "version") (add-opt-index "VERSION")) + (add-opt-index "HELP") + (if (not (exist? "no-libopts")) (add-opt-index "MORE_HELP")) + (if (exist? "usage-opt") (add-opt-index "USAGE")) + (if (exist? "vendor-opt") (add-opt-index "VENDOR_OPT")) + + (if (exist? "homerc") (begin + (if (not (exist? "disable-save")) (add-opt-index "SAVE_OPTS")) + (add-opt-index "LOAD_OPTS") + ) ) =][= +ENDIF not exist library =] +} te[=(. Cap-prefix)=]OptIndex; + +#define [=(. UP-prefix)=]OPTION_CT [= (. option-ct) =][= +IF (exist? "version") =] +#define [=(. pname-up)=]_VERSION [=(c-string (get "version"))=] +#define [=(. pname-up)=]_FULL_VERSION [=(c-string version-text) =][= +ENDIF (exist? version) =] + +/* + * Interface defines for all options. Replace "n" with the UPPER_CASED + * option name (as in the te[=(. Cap-prefix)=]OptIndex enumeration above). + * e.g. HAVE_[=(. UP-prefix)=]OPT([= (get-up-name "flag[].name") =]) + */[= + +IF (exist? "library") + +=] +extern tOptDesc * const [= (. lib-opt-ptr) =];[= + +ENDIF is a library =][= + +CASE guard-option-names =][= +!E =][= + (set! tmp-val (string-append "[" INDEX-pfx "## n]")) + =][= + += full-enum =][= + (set! tmp-val "[n]") =][= + +=* no-warn =][= + (set! tmp-val (string-append "[" INDEX-pfx "## n]")) + =][= + +* =][= + (set! tmp-val (string-append "[" INDEX-pfx "## n]")) + =][= + +ESAC =][= + +(if (exist? "library") + (set! tmp-val (string-append "(" lib-opt-ptr tmp-val ")")) + (set! tmp-val (string-append "(" pname "Options.pOptDesc" tmp-val ")")) ) + +(ag-fprintf 0 "\n#define %8sDESC(n) " UP-prefix) tmp-val + +=][= + +IF (> 1 (string-length UP-prefix)) + +=] +#define HAVE_OPT(n) (! UNUSED_OPT(& DESC(n))) +#define OPT_ARG(n) (DESC(n).optArg.argString) +#define STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK) +#define COUNT_OPT(n) (DESC(n).optOccCt) +#define ISSEL_OPT(n) (SELECTED_OPT(&DESC(n))) +#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n))) +#define ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n))) +#define STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt) +#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs) +#define CLEAR_OPT(n) STMTS( \ + DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \ + if ((DESC(n).fOptState & OPTST_INITENABLED) == 0) \ + DESC(n).fOptState |= OPTST_DISABLED; \ + DESC(n).optCookie = NULL )[= + +ELSE we have a prefix: + +=][= (sprintf " +#define HAVE_%1$sOPT(n) (! UNUSED_OPT(& %1$sDESC(n))) +#define %1$sOPT_ARG(n) (%1$sDESC(n).optArg.argString) +#define STATE_%1$sOPT(n) (%1$sDESC(n).fOptState & OPTST_SET_MASK) +#define COUNT_%1$sOPT(n) (%1$sDESC(n).optOccCt) +#define ISSEL_%1$sOPT(n) (SELECTED_OPT(&%1$sDESC(n))) +#define ISUNUSED_%1$sOPT(n) (UNUSED_OPT(& %1$sDESC(n))) +#define ENABLED_%1$sOPT(n) (! DISABLED_OPT(& %1$sDESC(n))) +#define STACKCT_%1$sOPT(n) (((tArgList*)(%1$sDESC(n).optCookie))->useCt) +#define STACKLST_%1$sOPT(n) (((tArgList*)(%1$sDESC(n).optCookie))->apzArgs) +#define CLEAR_%1$sOPT(n) STMTS( \\ + %1$sDESC(n).fOptState &= OPTST_PERSISTENT_MASK; \\ + if ((%1$sDESC(n).fOptState & OPTST_INITENABLED) == 0) \\ + %1$sDESC(n).fOptState |= OPTST_DISABLED; \\ + %1$sDESC(n).optCookie = NULL )" + + UP-prefix ) =][= + +ENDIF prefix/not =] + +/* * * * * * + * + * Enumeration of [= prog-name =] exit codes + */ +typedef enum {[= + #/* + ;; Assume no definitions for exit-name[0] and [1]. If not true, + ;; then change the strings associated with the ones defined to the + ;; specified name. If the assumption is correct, we'll need to + ;; emit the a default value into the enumeration.. + =][= ;; */ + (set! tmp-val "") + (define need-ex-noinput (exist? "homerc")) + (define need-ex-software #t) + + (define succ-exit-code (string-append pname-up "_EXIT_SUCCESS")) + (if (exist? "exit-name[0]") + (set! succ-exit-code (string-append + pname-up "_EXIT_" (get-up-name "exit-name[0]") )) + + (set! tmp-val (string-append + "\n " pname-up "_EXIT_SUCCESS = 0" )) + ) + + (define fail-exit-code (string-append pname-up "_EXIT_FAILURE")) + (if (exist? "exit-name[1]") + (set! fail-exit-code (string-append + pname-up "_EXIT_" (get-up-name "exit-name[1]") )) + + (set! tmp-val (string-append tmp-val + (if (> (string-length tmp-val) 1) "," "") + "\n " pname-up "_EXIT_FAILURE = 1" )) + ) + + (define nomem-exit-code + (if (exist? "nomem-fail-code") + (string-append pname-up "_EXIT_" (get-up-name "nomem-fail-code")) + fail-exit-code)) + + (define file-fail-exit-code + (if (exist? "file-fail-code") + (string-append pname-up "_EXIT_" (get-up-name "file-fail-code")) + fail-exit-code)) + + (if (and (exist? "exit-name") (> (string-length tmp-val) 1)) + (set! tmp-val (string-append tmp-val ",")) ) + + tmp-val =][= + + FOR exit-name "," =] + [= + (if (= (for-index) 66) + (set! need-ex-noinput #f) + (if (= (for-index) 70) + (set! need-ex-software #f) )) + + pname-up =]_EXIT_[= (get-up-name "exit-name") + =] = [= (for-index) =][= + ENDFOR =][= + (if need-ex-noinput + (ag-fprintf 0 ",\n %s_EXIT_NO_CONFIG_INPUT = 66" pname-up)) + (if need-ex-software + (ag-fprintf 0 ",\n %s_EXIT_LIBOPTS_FAILURE = 70" pname-up)) +=] +} [= (. pname-down) =]_exit_code_t;[= + +CASE guard-option-names =][= +!E =][= += full-enum =][= + + +=* no-warn =] +/* + * Make sure there are no #define name conflicts with the option names + */[= + FOR flag =] +#undef [= (get-up-name "name") =][= + ENDFOR flag =][= + +* =][= + + (define undef-list "\n#else /* NO_OPTION_NAME_WARNINGS */") + (define conf-warn-fmt (string-append + "\n# ifdef %1$s" + "\n# warning undefining %1$s due to option name conflict" + "\n# undef %1$s" + "\n# endif" )) + +=] +/* + * Make sure there are no #define name conflicts with the option names + */ +#ifndef NO_OPTION_NAME_WARNINGS[= + FOR flag =][= + + (set! opt-name (get-up-name "name")) + (set! undef-list (string-append undef-list "\n# undef " opt-name)) + (sprintf conf-warn-fmt opt-name) + =][= + + ENDFOR flag =][= + + (. undef-list)=] +#endif /* NO_OPTION_NAME_WARNINGS */ +[= + +ESAC on guard-option-names + +=] +/* * * * * * + * + * Interface defines for specific options. + */[= + +FOR flag =][= + (define flag-index (for-index)) =][= + + INVOKE save-name-morphs =][= + + IF (set! opt-name (string-append OPT-pfx UP-name)) + (set! descriptor (string-append UP-prefix "DESC(" UP-name ")" )) + + (exist? "documentation") + + =][= + IF (hash-ref have-cb-procs flg-name) +=] +#define SET_[= (string-append OPT-pfx UP-name) =] STMTS( \ + (*([=(. descriptor)=].pOptProc))(&[=(. pname)=]Options, \ + [=(. pname)=]Options.pOptDesc + [=(for-index)=])[= + + ENDIF =][= + ELSE =][= + INVOKE option-defines =][= + ENDIF =][= +ENDFOR flag + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Autoopts maintained option values. + +If *any* option flag value is specified, +then we provide flag characters for our options. +Otherwise, we will use the INDEX_* values for the option value. + +There are no documentation strings because these defines +are used identically to the user-generated VALUE defines. + +=][= + +DEFINE set-std-value =] +#define [= (sprintf "%-23s " (string-append VALUE-pfx (get "val-UPNAME"))) =][= + CASE (define tmp-val (get "val-name")) + (get tmp-val) =][= + == "" =][= + + (if (exist? tmp-val) + (if (not (exist? "long-opts")) + (error (sprintf "'%s' may not be empty" tmp-val)) + (string-append INDEX-pfx (get "val-UPNAME")) ) + (sprintf "'%s'" (get "std-value")) + ) =][= + + == "'" =]'\''[= + ~~ . =]'[=(get tmp-val)=]'[= + * =][=(error "value (flag) codes must be single characters") =][= + ESAC =][= +ENDDEF set-std-value =][= + +IF (exist? "flag.value") =][= + + INVOKE set-std-value + val-name = "help-value" + val-UPNAME = "HELP" + std-value = "?" =][= + + IF (not (exist? "no-libopts")) =][= + INVOKE set-std-value + val-name = "more-help-value" + val-UPNAME = "MORE_HELP" + std-value = "!" =][= + ENDIF don't have no-libopts ' =][= + + IF (exist? "resettable") =][= + INVOKE set-std-value + val-name = "reset-value" + val-UPNAME = "RESET_OPTION" + std-value = "R" =][= + ENDIF have "reset" =][= + + IF (exist? "version") =][= + INVOKE set-std-value + val-name = "version-value" + val-UPNAME = "VERSION" + std-value = "v" =][= + ENDIF have "version" =][= + + IF (exist? "usage-opt") =][= + INVOKE set-std-value + val-name = "usage-value" + val-UPNAME = "USAGE" + std-value = "u" =][= + ENDIF have "usage-opt" =][= + + IF (exist? "vendor-opt") =][= + INVOKE set-std-value + val-name = "vendor-value" + val-UPNAME = "VENDOR_OPT" + std-value = "W" =][= + ENDIF have "vendor-opt" =][= + + IF (exist? "homerc") =][= + + IF (not (exist? "disable-save")) =][= + INVOKE set-std-value + val-name = "save-opts-value" + val-UPNAME = "SAVE_OPTS" + std-value = ">" =][= + ELSE =] +#define [= (sprintf "%-23s 0" (string-append VALUE-pfx "SAVE_OPTS")) + =][= + ENDIF =][= + IF (not (exist? "disable-load")) =][= + INVOKE set-std-value + val-name = "load-opts-value" + val-UPNAME = "LOAD_OPTS" + std-value = "<" =][= + ELSE =] +#define [= (sprintf "%-23s 0" (string-append VALUE-pfx "LOAD_OPTS")) + =][= + ENDIF =][= + ENDIF have "homerc" =][= + +ELSE NO "flag.value" =] +[= +(set! index-fmt (string-append + "\n#define " VALUE-pfx "%1$-16s " INDEX-pfx "%1$s")) +(define std-vals (lambda (std-nm) + (ag-fprintf 0 index-fmt std-nm) )) + +(if (exist? "resettable") (std-vals "RESET_OPTION")) +(if (exist? "version") (std-vals "VERSION")) +(std-vals "HELP") +(if (not (exist? "no-libopts")) (std-vals "MORE_HELP")) +(if (exist? "usage-opt") (std-vals "USAGE")) +(if (exist? "homerc") (begin + (if (not (exist? "disable-save")) + (std-vals "SAVE_OPTS")) + (if (not (exist? "disable-load")) + (std-vals "LOAD_OPTS")) +) ) =][= + +ENDIF have flag.value/not =][= + +IF (and (exist? "homerc") (not (exist? "disable-save"))) + +=] +#define SET_[=(. OPT-pfx)=]SAVE_OPTS(a) STMTS( \ + [=(. UP-prefix)=]DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT_MASK; \ + [=(. UP-prefix)=]DESC(SAVE_OPTS).fOptState |= OPTST_SET; \ + [=(. UP-prefix)=]DESC(SAVE_OPTS).optArg.argString = (char const*)(a) )[= +ENDIF +=][= + +IF (not (exist? "library")) + +=] +/* + * Interface defines not associated with particular options + */ +#define ERRSKIP_[= + + IF (> 1 (string-length UP-prefix)) + +=][= (sprintf "OPTERR STMTS(%1$sOptions.fOptSet &= ~OPTPROC_ERRSTOP) +#define ERRSTOP_OPTERR STMTS(%1$sOptions.fOptSet |= OPTPROC_ERRSTOP) +#define RESTART_OPT(n) STMTS( \\ + %1$sOptions.curOptIdx = (n); \\ + %1$sOptions.pzCurOpt = NULL) +#define START_OPT RESTART_OPT(1) +#define USAGE(c) (*%1$sOptions.pUsageProc)(&%1$sOptions, c)" + pname ) =][= + + ELSE we have a prefix + +=][= (sprintf "%1$sOPTERR STMTS(%2$sOptions.fOptSet &= ~OPTPROC_ERRSTOP) +#define ERRSTOP_%1$sOPTERR STMTS(%2$sOptions.fOptSet |= OPTPROC_ERRSTOP) +#define RESTART_%1$sOPT(n) STMTS( \\ + %2$sOptions.curOptIdx = (n); \\ + %2$sOptions.pzCurOpt = NULL ) +#define START_%1$sOPT RESTART_%1$sOPT(1) +#define %1$sUSAGE(c) (*%2$sOptions.pUsageProc)(&%2$sOptions, c)" + + UP-prefix pname ) =][= + + ENDIF have/don't have prefix ' =][= + +ENDIF is not a library + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * + +=][= +(tpl-file-line extract-fmt) +=][= + +IF (not (exist? "library")) + +=] +#ifdef __cplusplus +extern "C" { +#endif +[=INVOKE join-or-expand join-type = "export" =][= + + IF (exist? "usage-message") =] +extern void [=(. lc-prefix)=]vusage_message(char const * fmt, va_list ap); +extern void [=(. lc-prefix)=]usage_message(char const * fmt, ...); +[=ENDIF have usage-message =] + +/* * * * * * + * + * Declare the [=prog-name=] option descriptor. + */ +extern tOptions [=(. pname)=]Options;[= + + (if (> (string-length added-hdr) 0) + (begin + (emit "\n") + (shellf "sort -u <<_EOF_\n%s_EOF_" added-hdr) + ) ) =][= + + IF (not omit-nls-code) =] + +#if defined(ENABLE_NLS) +# ifndef _ +# include <stdio.h> +# ifndef HAVE_GETTEXT + extern char * gettext(char const *); +# else +# include <libintl.h> +# endif + +static inline char* aoGetsText(char const* pz) { + if (pz == NULL) return NULL; + return (char*)gettext(pz); +} +# define _(s) aoGetsText(s) +# endif /* _() */ + +# define OPT_NO_XLAT_CFG_NAMES STMTS([=(. pname)=]Options.fOptSet |= \ + OPTPROC_NXLAT_OPT_CFG;) +# define OPT_NO_XLAT_OPT_NAMES STMTS([=(. pname)=]Options.fOptSet |= \ + OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG;) + +# define OPT_XLAT_CFG_NAMES STMTS([=(. pname)=]Options.fOptSet &= \ + ~(OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG);) +# define OPT_XLAT_OPT_NAMES STMTS([=(. pname)=]Options.fOptSet &= \ + ~OPTPROC_NXLAT_OPT;) + +#else /* ENABLE_NLS */[= + ENDIF no-nls-support =] +# define OPT_NO_XLAT_CFG_NAMES +# define OPT_NO_XLAT_OPT_NAMES + +# define OPT_XLAT_CFG_NAMES +# define OPT_XLAT_OPT_NAMES + +# ifndef _ +# define _(_s) _s +# endif[= + +(if (not omit-nls-code) (emit "\n#endif /* ENABLE_NLS */")) =][= + +IF (exist? "die-code") =] + +extern void [=(. lc-prefix)=]vdie( int exit_code, char const * fmt, va_list); +extern void [=(. lc-prefix)=]die( int exit_code, char const * fmt, ...); +extern void [=(. lc-prefix) +=]fserr(int exit_code, char const * op, char const * fname);[= + +ENDIF die-code exists =] + +#ifdef __cplusplus +} +#endif[= + +ENDIF this is not a lib + +=] +#endif /* [=(. header-guard)=] */[= +DEFINE join-or-expand =][= + IF (define join-type (get "join-type")) + (exist? join-type) \=] +/* + * global [=(string-append join-type (if (==* join-type "inc") "d" "ed")) + =] definitions + */ +[= + IF + (set! tmp-text (join "\n\n" (stack join-type))) + (~* (get join-type) "^[^a-z0-9_]{2,}[ \t]+autogen5[ \t]+template") + =][= + INCLUDE (begin + (set! tmp-val (string-append tmp-dir "/" join-type "-text")) + (out-push-new tmp-val) + (emit tmp-text) + (out-pop) + tmp-val + ) =][= + ELSE text is not template =][= + (. tmp-text) =][= + ENDIF text is template =] +[=ENDIF join-type =][= +ENDDEF join-or-expand +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * opthead.tpl ends here */=] diff --git a/autoopts/tpl/options.tpl b/autoopts/tpl/options.tpl new file mode 100644 index 0000000..41d6291 --- /dev/null +++ b/autoopts/tpl/options.tpl @@ -0,0 +1,57 @@ +[= Autogen5 Template -*- Mode: scheme -*- + +h +c + +# Time-stamp: "2011-01-28 10:30:50 bkorb" + +# This file contains the templates used to generate the +# option descriptions for client programs, and it declares +# the macros used in the templates. + +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= (dne " * " "/* ") =][= + +CASE (suffix) =][= + +== h =][= + + INCLUDE "optlib.tlib" =][= + INVOKE init-and-validate =][= + INVOKE option-copyright =][= + INCLUDE "opthead.tlib" =][= + +== c =][= + + (if (exist? "library") + (out-delete)) =][= + + INVOKE option-copyright =][= + INCLUDE "optcode.tlib" =][= + + (if (exist? "flag.extract-code") + (shellf "test -f %1$s.c && rm -f %1$s.c.save" (base-name))) =][= + +ESAC =] +/* [= (out-name) =] ends here */[= + +# options.tpl ends here =] diff --git a/autoopts/tpl/optlib.tlib b/autoopts/tpl/optlib.tlib new file mode 100644 index 0000000..9d72c15 --- /dev/null +++ b/autoopts/tpl/optlib.tlib @@ -0,0 +1,1260 @@ +[= AutoGen5 Template Library -*- Mode: scheme -*- + +# Time-stamp: "2012-08-11 08:14:10 bkorb" +# +# This file is part of AutoOpts, a companion to AutoGen. +# AutoOpts is free software. +# AutoOpts is Copyright (c) 1992-2012 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 md5sums: +# +# 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +# 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +# 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= + +INCLUDE "tpl-config.tlib" =][= + +DEFINE init-and-validate =][= + +(if (not (exist? "flag.name")) + (error "No options have been defined" )) + +(if (> (count "flag") 100) + (error (sprintf "%d options are too many - limit of 100" + (count "flag")) )) + +(if (not (and (exist? "prog-name") (exist? "prog-title"))) + (error "prog-name and prog-title are required")) +(define prog-name (get "prog-name")) +(if (> (string-length prog-name) 16) + (error (sprintf "prog-name limited to 16 characters: %s" + prog-name)) ) + + ;;# START-BUILDTREE-ISMS + ;; + (shell "CLexe=${AGexe%/agen5/*}/columns/columns + test -x \"${CLexe}\" || { + CLexe=${AGexe%/autogen}/columns + test -x \"${CLexe}\" || die 'columns program is not findable' + }") + +=][= # END-BUILDTREE-ISMS + + (shell "CLexe=${AGexe%/autogen}/columns") + +# END-INSTALL-ONLY-CODE =][= + +(make-tmp-dir) +(define get-opt-value (lambda (val) + (if (<= val 32) val (+ val 96)) )) + +(define have-proc #f) +(define proc-name "") +(define test-name "") +(define tmp-text "") +(define is-extern #t) +(define is-lib-cb #f) +(define have-cb-procs (make-hash-table 31)) +(define is-ext-cb-proc (make-hash-table 31)) +(define is-lib-cb-proc (make-hash-table 31)) +(define cb-proc-name (make-hash-table 31)) +(define test-proc-name (make-hash-table 31)) +(define disable-name (make-hash-table 31)) +(define disable-prefix (make-hash-table 31)) +(define ifdef-ed (make-hash-table 31)) +(define tmp-ct 0) +(define extract-fmt "\n/* extracted from %s near line %d */\n") +(define make-callback-procs #f) +(define omit-nls-code (~ (get "no-xlate") "(any|no)thing")) + +(define need-stacking (lambda() + (if (not (exist? "max")) + #f + (> (string->number (get "max")) 1) +) ) ) + +(define get-text (lambda (nm) (shell (string-append + "{ sed 's/@[a-z]*{\\([^}]*\\)}/\\1/g' | " + "${CLexe} --fill -I0 -W72\n}<<\\_EODesc_\n" + (get nm) "\n_EODesc_" )))) + +(define do-ifdefs (or (exist? "flag.ifdef") (exist? "flag.ifndef"))) + +;; IF long options are disallowed +;; AND at least one flag character (value) is supplied +;; THEN every option must have a 'value' attribute +;; +(define flag-options-only + (and (not (exist? "long-opts")) (exist? "flag.value"))) + +(if (exist? "vendor-opt") (begin + ;; except the 'vendor-opt' attribute allows long options that do + ;; not have flag values, but it conflicts with 'long-opts' and requires + ;; at least one 'flag.value' + ;; + (if (or (exist? "long-opts") (not (exist? "flag.value"))) + (error "'vendor-opt' conflicts with 'long-opts' and requires flag values") + (set! flag-options-only #f)) + (if (exist? "library") + (error "'vendor-opt' conflicts with 'library'")) +) ) + +(if (and (exist? "reorder-args") (not (exist? "argument")) ) + (error + "Reordering arguments requires operands (the 'argument' attribute)")) + +(if (and flag-options-only (exist? "flag.disable")) + (error "options can be disabled only with a long option name")) + +(if (exist? "flag.extract-code") + (shellf "f=%s.c ; test -s $f && mv -f $f $f.save" + (base-name))) + +(if (and (exist? "usage") (exist? "gnu-usage")) + (error "'usage' and 'gnu-usage' conflict." )) + +(if (> (count "flag.default") 1) + (error "Too many default options")) + +(if (exist? "library") (begin + (if (not (exist? "flag[0].documentation")) (error + "The first option of a library must be a documentation option")) + (if (not (exist? "flag[0].lib-name")) + (error "The first option of a library must specify 'lib-name'")) + (if (< 1 (count "flag.lib-name")) + (error "a library must only have one 'flag.lib-name'")) +) ) + +;; Establish a number of variations on the spelling of the +;; program name. Use these Scheme defined values throughout. +;; +(define pname (get-c-name "prog-name")) +(define pname-cap (string-capitalize pname)) +(define pname-up (string-upcase pname)) +(define pname-down (string-downcase pname)) +(define main-guard (string-append "TEST_" pname-up "_OPTS" )) +(define number-opt-index -1) +(define default-opt-index -1) +(define make-test-main (if (exist? "test-main") #t + (string? (getenv "TEST_MAIN")) )) + +(define descriptor "") +(define opt-name "") +(define tmp-val "") +(define added-hdr "") + +(define flg-name "") +(define UP-name "") +(define cap-name "") +(define low-name "") +(define enum-pfx "") + +(define set-flag-names (lambda () (begin + (set! flg-name (get "name")) + (set! UP-name (get-up-name "name")) + (set! cap-name (string-capitalize UP-name )) + (set! low-name (string-downcase UP-name )) + (set! enum-pfx (if (exist? ".prefix-enum") + (string-append (get-up-name "prefix-enum") "_") + (string-append UP-prefix UP-name "_") )) +) ) ) + +(define UP-prefix "") +(define lc-prefix "") +(define Cap-prefix "") +(define OPT-pfx "OPT_") +(define INDEX-pfx "INDEX_OPT_") +(define VALUE-pfx "VALUE_OPT_") + +(if (exist? "prefix") + (begin + (set! UP-prefix (string-append (get-up-name "prefix") "_")) + (set! lc-prefix (string-downcase UP-prefix)) + (set! Cap-prefix (string-capitalize UP-prefix)) + (set! OPT-pfx (string-append UP-prefix "OPT_")) + (set! INDEX-pfx (string-append "INDEX_" OPT-pfx)) + (set! VALUE-pfx (string-append "VALUE_" OPT-pfx)) + ) ) + +(define cap-c-name (lambda (ag-name) + (string-capitalize! (get-c-name ag-name)) )) + +(define index-name (lambda (i-name) + (string-append INDEX-pfx (get-up-name i-name)) )) + +(define optname-from "A-Z_^") +(define optname-to "a-z--") +(if (exist? "preserve-case") + (begin + (set! optname-from "_^") + (set! optname-to "--") +) ) + +(define version-text (string-append prog-name + (if (exist? "package") + (string-append " (" (get "package") ")") + "" ) + (if (exist? "version") + (string-append " " (get "version")) + "" ) )) + +(if (exist? "flag.value") + (shellf " + + list=`echo '%s' | sort` + ulst=`echo \"${list}\" | sort -u` + test `echo \"${ulst}\" | wc -l` -ne %d && { + echo \"${list}\" > ${tmp_dir}/sort + echo \"${ulst}\" > ${tmp_dir}/uniq + df=`diff ${tmp_dir}/sort ${tmp_dir}/uniq | sed -n 's/< *//p'` + die 'duplicate option value characters:' ${df} + }" + + (join "\n" (stack "flag.value")) + (count "flag.value") ) ) + +(define temp-idx 0) +(define no-flag-ct 0) +(define lib-opt-ptr "") +(define max-name-len 10) =][= + + +FOR flag =][= + + (set! tmp-ct (len "name")) + (if (> tmp-ct 32) + (error (sprintf "Option %d name exceeds 32 characters: %s" + (for-index) (get "name")) )) + (if (> tmp-ct max-name-len) + (set! max-name-len tmp-ct)) + + (if (exist? "value") + (if (< 1 (count "value")) + (error (sprintf "Option %s has too many `value's" (get "name")))) + (set! no-flag-ct (+ 1 no-flag-ct)) + ) + + (if (and flag-options-only + (not (exist? "documentation")) + (not (exist? "value"))) + (error (sprintf "Option %s needs a `value' attribute" (get "name")))) + + (set! tmp-val + (+ (if (exist? "call-proc") 1 0) + (if (exist? "extract-code") 1 0) + (if (exist? "flag-proc") 1 0) + (if (exist? "unstack-arg") 1 0) + (if (exist? "stack-arg") 1 0) )) + + ;; IF there is one of the above callback proc types AND there is an + ;; option argument of type non-string, THEN oops. Conflict. + ;; + (if (and (> tmp-val 0) (exist? "arg-type") + (not (=* (get "arg-type") "str")) ) + (error (sprintf + "Option %s has a %s argument and a callback procedure" + (get "name") (get "arg-type") ) + ) ) + + ;; Count up the ways a callback procedure was specified. Must be 0 or 1 + ;; + (if (< 1 (+ (if (exist? "arg-range") 1 0) + (if (~* (get "arg-type") "key|set") 1 0) tmp-val)) + (error (sprintf "Option %s has multiple callback specifications" + (get "name")) )) + + (if (< 1 (+ (count "ifdef") (count "ifndef") )) + (error (sprintf "Option %s has multiple 'ifdef-es'" (get "name") )) ) + + (if (and (exist? "stack-arg") (not (exist? "arg-type"))) + (error (sprintf "Option %s has stacked args, but no arg-type" + (get "name")))) + + (if (and (exist? "min") (exist? "must-set")) + (error (sprintf "Option %s has both 'min' and 'must-set' attributes" + (get "name")))) + + (if (and (exist? "omitted-usage") + (not (exist? "ifdef")) + (not (exist? "ifndef")) ) + (error (string-append "Option " (get "name") " has 'omitted-usage' " + "but neither 'ifdef' nor 'ifndef'" )) ) + + (if (and (exist? "equivalence") + (exist? "aliases")) + (error (string-append "Option " (get "name") " has both " + "'equivalence' and 'aliases'" )) ) + + (if (exist? "lib-name") + (set! lib-opt-ptr (string->c-name! (string-append + (get "lib-name") "_" (get "name") "_optDesc_p"))) ) +=][= + +ENDFOR flag + +=][= +(if (and (exist? "vendor-opt") (= no-flag-ct 0)) + (error "'vendor-opt' requires that there be options without flag values")) + +(define opt-strs (string-append pname "_opt_strs")) +(string-table-new opt-strs) +(out-push-new) (out-suspend "home-list") +=][= + +ENDDEF init-and-validate + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE save-name-morphs + + Save the various flag name morphs into hash tables + + Every option descriptor has a pointer to a handler procedure. That + pointer may be NULL. We generate a procedure for keyword, + set-membership and range checked options. "optionStackArg" is called + if "stack-arg" is specified. The specified procedure is called if + "call-proc" is specified. Finally, we insert the specified code for + options with "flag-code" or "extract-code" attributes. + + This all changes, however, if "make-test-main" is set. It is set if + either "test-main" is specified as a program/global attribute, or if + the TEST_MAIN environment variable is defined. This should be set + if either the program is intended to digest options for an incorporating + shell script, or else if the user wants a quick program to show off the + usage text and command line parsing. For that environment, all callbacks + are disabled except "optionStackArg" for stacked arguments and the + keyword set membership options. + + =][= + + IF + + (set-flag-names) + (hash-create-handle! ifdef-ed flg-name + (and do-ifdefs (or (exist? "ifdef") (exist? "ifndef"))) ) + (set! proc-name (string-append "doOpt" cap-name)) + (set! is-lib-cb #f) + + (exist? "call-proc") + + =][= # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + + (set! have-proc #t) + (set! is-extern #t) + (set! proc-name (get "call-proc")) + (set! test-name (if need-stacking "optionStackArg" "NULL")) + =][= + + ELIF (or (exist? "extract-code") + (exist? "flag-code") + (exist? "aliases") + (exist? "arg-range")) + =][= + + (set! have-proc #t) + (set! is-extern #f) + (set! test-name (if (or (exist? "arg-range") (exist? "aliases")) + proc-name + (if need-stacking "optionStackArg" "NULL") )) + =][= + + ELIF (exist? "flag-proc") =][= + + (set! have-proc #t) + (set! proc-name (string-append "doOpt" (cap-c-name "flag-proc"))) + (set! test-name (if need-stacking "optionStackArg" "NULL")) + (set! is-extern #f) + =][= + + ELIF (exist? "stack-arg") =][= + + (if (not (exist? "max")) + (error (string-append flg-name + " has a stacked arg, but can only appear once")) ) + + (set! have-proc #t) + (set! proc-name "optionStackArg") + (set! is-lib-cb #t) + (set! test-name (if need-stacking proc-name "NULL")) + (set! is-extern #t) + =][= + + ELIF (exist? "unstack-arg") =][= + + (set! have-proc #t) + (set! proc-name "optionUnstackArg") + (set! is-lib-cb #t) + (set! test-name (if need-stacking proc-name "NULL")) + (set! is-extern #t) + =][= + + ELSE =][= + + CASE arg-type =][= + =* bool =][= + (set! proc-name "optionBooleanVal") + (set! is-lib-cb #t) + (set! test-name proc-name) + (set! is-extern #t) + (set! have-proc #t) =][= + + =* num =][= + (set! proc-name "optionNumericVal") + (set! is-lib-cb #t) + (set! test-name proc-name) + (set! is-extern #t) + (set! have-proc #t) =][= + + = time-date =][= + (set! proc-name "optionTimeDate") + (set! is-lib-cb #t) + (set! test-name proc-name) + (set! is-extern #t) + (set! have-proc #t) =][= + + =* time =][= + (set! proc-name "optionTimeVal") + (set! is-lib-cb #t) + (set! test-name proc-name) + (set! is-extern #t) + (set! have-proc #t) =][= + + ~* key|set|fil =][= + (set! test-name proc-name) + (set! is-extern #f) + (set! have-proc #t) =][= + + ~* hier|nest =][= + (set! proc-name "optionNestedVal") + (set! is-lib-cb #t) + (set! test-name proc-name) + (set! is-extern #t) + (set! have-proc #t) =][= + + * =][= + (set! have-proc #f) =][= + ESAC =][= + + ENDIF =][= + + ;; If these are different, then a #define name is inserted into the + ;; option descriptor table. Never a need to mess with it if we are + ;; not building a "test main" procedure. + ;; + (if (not make-test-main) + (set! test-name proc-name)) + + (if have-proc + (begin + (hash-create-handle! have-cb-procs flg-name #t) + (hash-create-handle! cb-proc-name flg-name proc-name) + (hash-create-handle! test-proc-name flg-name test-name) + (hash-create-handle! is-ext-cb-proc flg-name is-extern) + (hash-create-handle! is-lib-cb-proc flg-name is-lib-cb) + (set! make-callback-procs #t) + ) + (begin + (hash-create-handle! have-cb-procs flg-name #f) + (hash-create-handle! cb-proc-name flg-name "NULL") + (hash-create-handle! test-proc-name flg-name "NULL") + ) + ) + + (if (exist? "default") + (set! default-opt-index (. flag-index)) ) + +=][= + +ENDDEF save-name-morphs + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Emit the "#define SET_OPT_NAME ..." and "#define DISABLE_OPT_NAME ..." =][= + +DEFINE set-defines + +=] +#define SET_[=(. opt-name)=][= (if (exist? "arg-type") "(a)") + =] STMTS( \ + [=set-desc=].optActualIndex = [=(. flag-index)=]; \ + [=set-desc=].optActualValue = VALUE_[=(. opt-name)=]; \ + [=set-desc=].fOptState &= OPTST_PERSISTENT_MASK; \ + [=set-desc=].fOptState |= [=opt-state=][= + CASE arg-type =][= + ~* str|fil =]; \ + [=set-desc=].optArg.argString = (a)[= + =* num =]; \ + [=set-desc=].optArg.argInt = (a)[= + =* time =]; \ + [=set-desc=].optArg.argInt = (a)[= + =* bool =]; \ + [=set-desc=].optArg.argBool = (a)[= + =* key =]; \ + [=set-desc=].optArg.argEnum = (a)[= + =* set =]; \ + [=set-desc=].optArg.argIntptr = (a)[= + ~* hier|nest =]; \ + [=set-desc=].optArg.argString = (a)[= + + ESAC arg-type =][= + + IF (hash-ref have-cb-procs flg-name) =]; \ + (*([=(. descriptor)=].pOptProc))(&[=(. pname)=]Options, \ + [=(. pname)=]Options.pOptDesc + [=set-index=]);[= + ENDIF "callout procedure exists" =] )[= + + IF (exist? "disable") =][= + IF (~* (get "arg-type") "hier|nest") =] +#define DISABLE_[=(. opt-name)=](a) STMTS( \ + [=set-desc=].fOptState &= OPTST_PERSISTENT_MASK; \ + [=set-desc=].fOptState |= OPTST_SET | OPTST_DISABLED; \ + [=set-desc=].optArg.argString = (a); \ + optionNestedVal(&[=(. pname)=]Options, \ + [=(. pname)=]Options.pOptDesc + [=set-index=]);)[= + + ELSE =] +#define DISABLE_[=(. opt-name)=] STMTS( \ + [=set-desc=].fOptState &= OPTST_PERSISTENT_MASK; \ + [=set-desc=].fOptState |= OPTST_SET | OPTST_DISABLED; \ + [=set-desc=].optArg.argString = NULL[= + IF (hash-ref have-cb-procs flg-name) =]; \ + (*([=(. descriptor)=].pOptProc))(&[=(. pname)=]Options, \ + [=(. pname)=]Options.pOptDesc + [=set-index=]);[= + ENDIF "callout procedure exists" =] )[= + ENDIF =][= + ENDIF disable exists =][= + +ENDDEF set-defines + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Emit the copyright comment =][= + +DEFINE option-copyright =] + * + * Generated from AutoOpts [=(. ao-version)=] templates. + * + * AutoOpts is a copyrighted work. This [= + (if (= "h" (suffix)) "header" "source") =] file is not encumbered + * by AutoOpts licensing, but is provided under the licensing terms chosen + * by the [= prog-name =] author or copyright holder. AutoOpts is + * licensed under the terms of the LGPL. The redistributable library + * (``libopts'') is licensed under the terms of either the LGPL or, at the + * users discretion, the BSD license. See the AutoOpts and/or libopts sources + * for details.[= + +IF (exist? "copyright") =] + * + * The [= prog-name =] program is copyrighted and licensed + * under the following terms: + * +[= + CASE copyright.type =][= + == "" =][= + (sprintf " * %s copyright (c) %s %s - all rights reserved\n * %s" + prog-name (get "copyright.date") (get "copyright.owner") + "licensing type not specified" ) =][= + + = note =][= (prefix " * " (get "copyright.text")) =][= + + * =][= (license-full (get "copyright.type") prog-name " * " + (get "copyright.owner") (get "copyright.date")) =][= + ESAC =][= +ENDIF "copyright exists" =] + */ +[= + +ENDDEF option-copyright + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Emit usage text =][= + +DEFINE usage-text =] +#define [= + (set! tmp-val (string-append (get "usage-type") "-usage")) + (define usage-text-name + (string->c-name! (string-append pname "_" tmp-val)) ) + usage-text-name + + =] ([= + + CASE (set! tmp-val (get tmp-val "<<<NOT-FOUND>>>")) + tmp-val =][= + + == "<<<NOT-FOUND>>>" =]NULL[= + + == "" =][= + + (out-push-new) =][= + INCLUDE "usage.tlib" =][= + (string-table-add-ref opt-strs (out-pop #t)) =][= + + ~ "[a-z][a-z0-9_]*" =][= (. tmp-val) =][= + + * anything else must be plain text =][= + (string-table-add-ref opt-strs tmp-val) =][= + ESAC flavor of usage text. =]) +[= + +ENDDEF usage-text + +;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE emit-keyword-enum =] +typedef enum {[= + (if (not (exist? "arg-default")) + (string-append " " enum-pfx "UNDEFINED = 0,")) =] +[=(shellf +"for f in %s ; do echo %s${f} ; done | \ + ${CLexe} -I4 --spread=3 --sep=, +test $? -eq 0 || die ${CLexe} failed" + (string-upcase! (string->c-name! (join " " (stack "keyword")))) + enum-pfx )=] +} te_[=(string-append Cap-prefix cap-name)=]; +#define [= (sprintf "%-24s" (string-append OPT-pfx UP-name "_VAL2STR(_v)")) + =] optionKeywordName(&[=(. value-desc)=], (_v)) +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argEnum)[= + +ENDDEF emit-keyword-enum + +;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE emit-member-mask =][= + + (define setmember-fmt (string-append "\n#define %-24s 0x%0" + (shellf "expr '(' %d + 4 ')' / 4" (count "keyword")) "XUL" + (if (> (count "keyword") 32) "L" "") )) + (define full-prefix (string-append UP-prefix UP-name) ) =][= + + FOR keyword =][= + + (sprintf setmember-fmt + (string->c-name! (string-append + full-prefix "_" (string-upcase! (get "keyword")) )) + (ash 1 (for-index)) ) =][= + + ENDFOR keyword =][= + + (ag-fprintf 0 setmember-fmt (string->c-name! (string-append + full-prefix "_MEMBERSHIP_MASK")) + (- (ash 1 (count "keyword")) 1) ) =] +#define [=(sprintf "%sVALUE_%-14s ((uintptr_t)%s.optCookie)" + OPT-pfx UP-name value-desc) + =][= + +ENDDEF emit-member-mask + +;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE emit-value-defines =][= + + CASE arg-type =][= + + =* num =] +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argInt)[= + + =* time =] +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argInt)[= + + =* key =][= + INVOKE emit-keyword-enum =][= + + =* set =][= + INVOKE emit-member-mask =][= + + =* bool =] +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argBool)[= + + =* fil =][= + CASE open-file =][= + == "" =][= + =* desc =] +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argFd)[= + * =] +#define [=(. OPT-pfx)=]VALUE_[=(sprintf "%-14s" UP-name) + =] ([=(. value-desc)=].optArg.argFp)[= + ESAC =][= + + ESAC =][= + +ENDDEF emit-value-defines + +;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE set-option-define =][= + + IF (exist? "unstack-arg") =][= + + set-defines + set-desc = (string-append UP-prefix "DESC(" + (get-up-name "unstack-arg") ")" ) + set-index = (index-name "unstack-arg") + opt-state = "OPTST_SET | OPTST_EQUIVALENCE" =][= + + ELIF (and (exist? "equivalence") + (not (== (get-up-name "equivalence") UP-name))) =][= + + set-defines + set-desc = (string-append UP-prefix "DESC(" + (get-up-name "equivalence") ")" ) + set-index = (index-name "equivalence") + opt-state = "OPTST_SET | OPTST_EQUIVALENCE" =][= + + ELSE "is equivalenced" =][= + + set-defines + set-desc = (string-append UP-prefix "DESC(" UP-name ")" ) + set-index = (. flag-index) + opt-state = OPTST_SET =][= + + ENDIF is/not equivalenced =][= + +ENDDEF set-option-define + +;; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +;; +;; #define's for a single option +;; +;; First, emit defines that are always required. Then start collecting +;; defines in a diverted output. If there is any output, there will +;; be well more than 2 bytes of it. If so, actually emit it, but first +;; see if it needs to be enclused in a #ifdef/#endif pair. +;; =][= +DEFINE option-defines =] +#define VALUE_[= + (define value-desc (string-append UP-prefix "DESC(" + (if (exist? "equivalence") + (get-up-name "equivalence") + UP-name) ")" )) + (sprintf "%-18s" opt-name)=] [= + + CASE value =][= + !E =][= (get-opt-value flag-index) =][= + == "'" =]'\''[= + == "\\" =]'\\'[= + ~~ "[ -~]" =]'[=value=]'[= + + =* num =][= + (if (>= number-opt-index 0) + (error "only one number option is allowed") ) + (set! number-opt-index flag-index) + (get-opt-value flag-index) =][= + + * =][=(error (sprintf + "Error: value for opt %s is `%s'\nmust be single char or 'NUMBER'" + (get "name") (get "value")))=][= + + ESAC =][= + (out-push-new) =][= + INVOKE emit-value-defines =][= + + IF (== (get-up-name "equivalence") UP-name) =] +#define WHICH_[=(sprintf "%-18s" opt-name) + =] ([=(. descriptor)=].optActualValue) +#define WHICH_[=(. UP-prefix)=]IDX_[=(sprintf "%-14s" UP-name) + =] ([=(. descriptor)=].optActualIndex)[= + ENDIF =][= + + IF (exist? "settable") =][= + INVOKE set-option-define =][= + ENDIF settable =][= + + IF (define tmp-val (out-pop #t)) + (if (defined? 'tmp-val) + (> (string-length tmp-val) 2) + #f ) =][= + + IF (hash-ref ifdef-ed flg-name) =] +#if[=ifndef "n"=]def [= ifdef =][= ifndef \=] +[= (. tmp-val) =] +#endif /* [= ifdef =][= ifndef =] */[= + + ELSE =] +[= (. tmp-val) =][= + ENDIF =][= + ENDIF =][= + +ENDDEF Option_Defines + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE emit-alias-option + +=] +#define [= (. UP-name) =]_DESC ([= + (string-table-add-ref opt-strs + (string-append "This is an alias for '" (get "aliases") "'")) =]) +#define [= (. UP-name) =]_NAME NULL +#define [= (. UP-name) =]_name ([= + (string-table-add-ref opt-strs (get "name")) =]) +#define [=(. UP-name)=]_FLAGS ([= + (get-up-name "aliases") =]_FLAGS | OPTST_ALIAS)[= + +ENDDEF emit-alias-option + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Define the arrays of values associated with an option (strings, etc.) =][= + +DEFINE emit-nondoc-option =][= + (if (exist? "translators") + (string-append "\n" (shellf +"${CLexe} -I16 --fill --first='/* TRANSLATORS:' <<\\_EOF_ +%s +_EOF_" (get "translators") ) " */" ) ) =] +#define [= (. UP-name) =]_DESC ([= + (string-table-add-ref opt-strs (get-text "descrip")) =]) +#define [= (. UP-name) =]_NAME ([= + (string-table-add-ref opt-strs UP-name) =])[= + + # IF this option can be disabled, + # THEN we must create the string for the disabled version + # =][= + IF (> (len "disable") 0) =] +#define NOT_[= (. UP-name) =]_name ([= + (hash-create-handle! disable-name flg-name (string-append + "NOT_" UP-name "_name" )) + (hash-create-handle! disable-prefix flg-name (string-append + "NOT_" UP-name "_PFX" )) + (string-table-add-ref opt-strs + (string-tr! (string-append (get "disable") "-" flg-name) + optname-from optname-to)) =]) +#define NOT_[= (. UP-name) =]_PFX ([= + (string-table-add-ref opt-strs (string-downcase! (get "disable"))) =]) +#define [= (. UP-name) =]_name ([= + (if (> (len "enable") 0) + (string-table-add-ref opt-strs + (string-tr! (string-append (get "enable") "-" flg-name) + optname-from optname-to) ) + (sprintf "NOT_%s_name + %d" + UP-name (+ (string-length (get "disable")) 1 )) + ) =])[= + + ELSE No disablement of this option: =][= + + (hash-create-handle! disable-name flg-name "NULL") + (hash-create-handle! disable-prefix flg-name "NULL") "" + =] +#define [= (. UP-name) =]_name ([= + (string-table-add-ref opt-strs + (string-tr! (string-append + (if (exist? "enable") (string-append (get "enable") "-") "") + (get "name")) + optname-from optname-to)) =])[= + + ENDIF (> (len "disable") 0) =][= + + # Check for special attributes: a default value + # and conflicting or required options + =][= + IF (define def-arg-name (sprintf "%-28s " + (string-append UP-name "_DFT_ARG" ))) + (exist? "arg-default") =] +#define [= (. UP-name) =]_DFT_ARG ([= + CASE arg-type =][= + =* num =](char const*)[= arg-default =][= + + =* time =](char const*)[= + (time-string->number (get "arg-default")) =][= + + =* bool =][= + CASE arg-default =][= + ~ n.*|f.*|0 =](char const*)false[= + * =](char const*)true[= + ESAC =][= + + =* key =](char const*)[= + (emit (if (=* (get "arg-default") enum-pfx) "" enum-pfx)) + (get-up-name "arg-default") =][= + + =* set =]NULL) +#define [=(sprintf "%-28s " (string-append cap-name "CookieBits"))=](void*)([= + IF (not (exist? "arg-default")) =]0[= + ELSE =][= + FOR arg-default | =][= + (string->c-name! (string-append UP-prefix UP-name "_" + (get-up-name "arg-default") )) =][= + ENDFOR arg-default =][= + ENDIF =][= + + =* str =][= + (string-table-add-ref opt-strs (get "arg-default")) =][= + + =* file =][= + (string-table-add-ref opt-strs (get "arg-default")) =][= + + * =][= + (error (string-append cap-name + " has arg-default, but no valid arg-type")) =][= + ESAC =])[= + ENDIF =][= + + + IF (exist? "flags-must") =] +static int const a[=(. cap-name)=]MustList[] = {[= + FOR flags-must =] + [= (index-name "flags-must") =],[= + ENDFOR flags_must =] NO_EQUIVALENT };[= + ENDIF =][= + + + IF (exist? "flags-cant") =] +static int const a[=(. cap-name)=]CantList[] = {[= + FOR flags-cant =] + [= (index-name "flags-cant") =],[= + ENDFOR flags-cant =] NO_EQUIVALENT };[= + ENDIF =] +#define [= (. UP-name) =]_FLAGS ([= + ? enabled "OPTST_INITENABLED" + "OPTST_DISABLED" =][= + stack-arg " | OPTST_STACKED" =][= + must-set " | OPTST_MUST_SET" =][= + no-preset " | OPTST_NO_INIT" =][= + no-command " | OPTST_NO_COMMAND" =][= + deprecated " | OPTST_DEPRECATED" =][= + + CASE immediate =][= + = also =] | OPTST_IMM | OPTST_TWICE[= + +E =] | OPTST_IMM[= + ESAC immediate =][= + + CASE immed-disable =][= + = also =] | OPTST_DISABLE_IMM | OPTST_DISABLE_TWICE[= + +E =] | OPTST_DISABLE_IMM[= + ESAC immed-disable =][= + + IF (exist? "arg-type") =][= + CASE arg-type =][= + + =* num =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC)[= + IF (exist? "scaled") =] \ + | OPTST_SCALED_NUM[= ENDIF =][= + + =* time =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_TIME)[= + + =* bool =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_BOOLEAN)[= + + =* key =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_ENUMERATION)[= + + =* set =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_MEMBERSHIP)[= + + ~* hier|nest =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_HIERARCHY)[= + + =* str =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)[= + + =* fil =] \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE)[= + + * =][= + (error (string-append "unknown arg type '" + (get "arg-type") "' for " flg-name)) =][= + ESAC arg-type =][= + (if (exist? "arg-optional") " | OPTST_ARG_OPTIONAL") =][= + ENDIF arg-type exists =])[= + +ENDDEF emit-nondoc-option + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Define the arrays of values associated with an option (strings, etc.) =][= + +DEFINE emit-opt-strs + +=] +/* + * [= (set-flag-names) flg-name =] option description[= + IF (or (exist? "flags_must") (exist? "flags_cant")) =] with + * "Must also have options" and "Incompatible options"[= + ENDIF =]: + */[= + IF (hash-ref ifdef-ed flg-name) =] +#if[=ifndef "n"=]def [= (define if-def-name (get "ifdef" (get "ifndef"))) + if-def-name =][= + ENDIF ifdef-ed =][= + + IF (exist? "documentation") =] +#define [= (. UP-name) =]_DESC ([= + (string-table-add-ref opt-strs + (string-append (get-text "descrip") ":")) =]) +#define [= (. UP-name) =]_FLAGS (OPTST_DOCUMENT | OPTST_NO_INIT)[= + ELIF (exist? "aliases") =][= + INVOKE emit-alias-option =][= + ELSE =][= + INVOKE emit-nondoc-option =][= + ENDIF (exist? "documentation") =][= + + IF (hash-ref ifdef-ed flg-name) =] + +#else /* disable [= (. flg-name)=] */ +#define [= (. UP-name) =]_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)[= + + IF (exist? "arg-default") =] +#define [= (. UP-name) =]_DFT_ARG NULL[= + ENDIF =][= + + IF (exist? "flags-must") =] +#define a[=(. cap-name)=]MustList NULL[= + ENDIF =][= + + IF (exist? "flags-cant") =] +#define a[=(. cap-name)=]CantList NULL[= + ENDIF =] +#define [= (. UP-name) =]_NAME NULL[= + + IF (exist? "omitted-usage") =] +#define [= (. UP-name) =]_DESC ([= + (set! tmp-text (get "omitted-usage")) + (if (> (string-length tmp-text) 1) + (string-table-add-ref opt-strs tmp-text) + "NULL") =]) +#define [= (. UP-name) =]_name ([= + (string-table-add-ref opt-strs (get "name")) =])[= + + ELSE =] +#define [= (. UP-name) =]_DESC NULL +#define [= (. UP-name) =]_name NULL[= + ENDIF =][= + + IF (> (len "disable") 0) =] +#define NOT_[= (. UP-name) =]_name NULL +#define NOT_[= (. UP-name) =]_PFX NULL[= + ENDIF =] +#endif /* [= (. if-def-name) =] */[= + ENDIF ifdef-ed =][= + +ENDDEF opt-strs + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Define the arrays of values associated with help/version/etc. =][= + +DEFINE help-strs + +=] + +/* + * Help[= (string-append + (if (exist? "no-libopts") "" "/More_Help") + (if (exist? "version") "/Version" "")) =] option descriptions: + */ +#define HELP_DESC ([= + (string-table-add-ref opt-strs + "Display extended usage information and exit")=]) +#define HELP_name ([= + (string-table-add-ref opt-strs "help")=])[= + + IF (not (exist? "no-libopts")) + +=] +#ifdef HAVE_WORKING_FORK +#define MORE_HELP_DESC ([= + (string-table-add-ref opt-strs + "Extended usage information passed thru pager")=]) +#define MORE_HELP_name ([= + (string-table-add-ref opt-strs "more-help")=]) +#define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +#define MORE_HELP_DESC NULL +#define MORE_HELP_name NULL +#define MORE_HELP_FLAGS (OPTST_OMITTED | OPTST_NO_INIT) +#endif[= + + ENDIF (not (exist? "no-libopts")) =][= + + IF (exist? "version") + +=] +#ifdef NO_OPTIONAL_OPT_ARGS +# define VER_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +# define VER_FLAGS (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \ + OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT) +#endif +#define VER_DESC ([= + (string-table-add-ref opt-strs "Output version information and exit")=]) +#define VER_name ([= + (string-table-add-ref opt-strs "version")=])[= + + ENDIF (exist? "version") =][= + + IF (exist? "resettable") + +=] +#define RESET_DESC ([= + (string-table-add-ref opt-strs "Reset an option's state")=]) +#define RESET_name ([= + (string-table-add-ref opt-strs "reset-option")=]) +#define RESET_FLAGS (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | OPTST_NO_INIT)[= + + ENDIF (exist? "resettable") =][= + + IF (exist? "usage-opt") + +=] +#define USAGE_DESC ([= + (string-table-add-ref opt-strs "Abbreviated usage to stdout")=]) +#define USAGE_name ([= + (string-table-add-ref opt-strs "usage")=])[= + + ENDIF (exist? "usage-opt") =][= + + IF (exist? "vendor-opt") + +=] +#define VEND_DESC ([= + (string-table-add-ref opt-strs "vendor supported additional options")=]) +#define VEND_name ([= + (string-table-add-ref opt-strs "vendor-option")=])[= + + ENDIF (exist? "vendor-opt") =][= + + IF (exist? "homerc") =][= + + IF (not (exist? "disable-save")) =] +#define SAVE_OPTS_DESC ([= + (string-table-add-ref opt-strs "Save the option state to a config file")=]) +#define SAVE_OPTS_name ([= + (string-table-add-ref opt-strs "save-opts")=])[= + + ENDIF no disable-save =][= + + IF (not (exist? "disable-load")) =] +#define LOAD_OPTS_DESC ([= + (string-table-add-ref opt-strs "Load options from a config file")=]) +#define LOAD_OPTS_NAME ([= + (string-table-add-ref opt-strs "LOAD_OPTS")=]) +#define NO_LOAD_OPTS_name ([= + (string-table-add-ref opt-strs "no-load-opts")=]) +#define LOAD_OPTS_pfx ([= + (string-table-add-ref opt-strs "no")=]) +#define LOAD_OPTS_name (NO_LOAD_OPTS_name + 3)[= + + ENDIF no disable-load =][= + + ENDIF (exist? "homerc") =][= + +ENDDEF help-strs + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + +Define the values for an option descriptor =][= + +DEFINE emit-opt-desc =][= + IF + (set-flag-names) + + (exist? "documentation") + +=] + { /* entry idx, value */ 0, 0, + /* equiv idx, value */ 0, 0, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 0, 0, + /* opt state flags */ [=(. UP-name)=]_FLAGS, 0, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ [= + IF (exist? "call-proc") =][=call-proc=][= + ELIF (or (exist? "extract-code") + (exist? "flag-code")) =]doOpt[=(. cap-name)=][= + ELSE =]NULL[= + ENDIF =], + /* desc, NAME, name */ [= + (set! default-text (string-append default-text + "\n { NULL }, /* doc opt */" )) + (set! default-cookie (string-append default-cookie "NULL\n" )) + UP-name =]_DESC, NULL, NULL, + /* disablement strs */ NULL, NULL },[= + + ELSE + +=] + { /* entry idx, value */ [=(. flag-index)=], [= + (string-append VALUE-pfx UP-name)=], + /* equiv idx, value */ [= + IF (== (get-up-name "equivalence") UP-name) + =]NO_EQUIVALENT, 0[= + ELIF (or (exist? "equivalence") (exist? "unstack-arg")) + =]NOLIMIT, NOLIMIT[= + ELSE + =][=(. flag-index)=], [=(string-append VALUE-pfx UP-name)=][= + ENDIF=], + /* equivalenced to */ [= + (if (exist? "unstack-arg") + (index-name "unstack-arg") + (if (and (exist? "equivalence") + (not (== (get-up-name "equivalence") UP-name)) ) + (index-name "equivalence") + "NO_EQUIVALENT" + ) ) =], + /* min, max, act ct */ [= + (if (exist? "min") (get "min") + (if (exist? "must-set") "1" "0" )) =], [= + (if (=* (get "arg-type") "set") "NOLIMIT" + (if (exist? "max") (get "max") "1") ) =], 0, + /* opt state flags */ [=(. UP-name)=]_FLAGS, 0, + /* last opt argumnt */ [= + (set! tmp-val (if (exist? "arg-default") + (string-append "{ " UP-name "_DFT_ARG },") + (string-append "{ NULL }, /* --" flg-name " */" ) )) + (set! default-text (string-append default-text "\n " tmp-val)) + tmp-val =] + /* arg list/cookie */ [= + (set! tmp-val (if (and (=* (get "arg-type") "set") (exist? "arg-default")) + (string-append cap-name "CookieBits") "NULL")) + (set! default-cookie (string-append default-cookie tmp-val "\n" )) + tmp-val =], + /* must/cannot opts */ [= + (if (exist? "flags-must") + (string-append "a" cap-name "MustList, ") + "NULL, " ) =][= + (if (exist? "flags-cant") + (string-append "a" cap-name "CantList") + "NULL" ) =], + /* option proc */ [= + + ;; If there is a difference between what gets invoked under test and + ;; what gets invoked "normally", then there must be a #define name + ;; for the procedure. There will only be such a difference if + ;; make-test-main is #t + ;; + (if (= (hash-ref cb-proc-name flg-name) + (hash-ref test-proc-name flg-name)) + + (hash-ref test-proc-name flg-name) + (string-append UP-name "_OPT_PROC") ) =], + /* desc, NAME, name */ [= + (sprintf "%1$s_DESC, %1$s_NAME, %1$s_name," UP-name) =] + /* disablement strs */ [=(hash-ref disable-name flg-name)=], [= + (hash-ref disable-prefix flg-name)=] },[= + ENDIF =][= + +ENDDEF opt-desc + +optlib.tlib ends here \=] diff --git a/autoopts/tpl/optmain.tlib b/autoopts/tpl/optmain.tlib new file mode 100644 index 0000000..13b01de --- /dev/null +++ b/autoopts/tpl/optmain.tlib @@ -0,0 +1,1255 @@ +[= AutoGen5 Template -*- Mode: text -*- + +# Time-stamp: "2012-08-11 08:13:56 bkorb" + +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f 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 + +=][= (tpl-file-line extract-fmt) \=] + +#if defined([=(. main-guard)=]) /* TEST MAIN PROCEDURE: */[= + + 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 argc argument count + * @param 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);[= + + ELIF (exist? "main-text") =][= + IF (not (exist? "option-code")) =] + { + int ct = optionProcess(&[=(. pname)=]Options, argc, argv); + argc -= ct; + argv += ct; + }[= + ELSE =][= + (def-file-line "option-code" extract-fmt) =][= + option-code =][= + ENDIF =][= + + (def-file-line "main-text" extract-fmt) =][= + main-text =][= + + ELSE test-main is not optionParseShell and main-text not exist + +=] + (void)optionProcess(&[=(. pname)=]Options, argc, argv); + [= (. option-emitter-proc) =](&[=(. pname)=]Options); + res = ferror(stdout); + if (res != 0) + fputs("output error writing to stdout\n", stderr);[= + ENDIF=] + return res; +} +#endif /* defined [= (. 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) + +=] +/** + * 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 pz_s source text pointer + * @returns pointer to the same text buffer, but after finding the + * first non-white space character. + */ +static char * +trim_input_line(char * pz_s) +{ + char* pz_e = pz_s + strlen(pz_s); + while ((pz_e > pz_s) && isspace((unsigned int)pz_e[-1])) pz_e--; + *pz_e = '\0'; + while ((unsigned int)isspace(*pz_s)) pz_s++; + + switch (*pz_s) { + case '\0': + case '[= ?% comment-char "%s" "#" =]': + return NULL; + default: + return pz_s; + } +}[= + +CASE handler-type =][= +=* name =][= (set! handler-arg-type "char const* pz_fname") + (define handler-proc "validate_fname") =][= +=* file =][= + (set! handler-arg-type "char const* pz_fname, FILE* entry_fp") + (define handler-proc "validate_fname") =][= +*=* text =][= + (set! handler-arg-type + "char const* pz_fname, char* pz_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 + +=][= (tpl-file-line extract-fmt) =][= + +IF (exist? "handler-type") =] +/** + * 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 pz_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* pz_fname) +{ + static char const * pz_fs_err = NULL;[= + + IF (*=* (get "handler-type") "text") =] + char* file_text; + size_t text_size; + int res;[= + ENDIF =] + + if (pz_fs_err == NULL) + pz_fs_err = _("fs error %d (%s) %s-ing %s\n"); + + { + struct stat sb; + if (stat(pz_fname, &sb) < 0) {[= + IF (. emit-failing-printf) =] + fprintf(stderr, pz_fs_err, errno, strerror(errno), "stat", + pz_fname);[= + ENDIF =] + return [= (. file-fail-exit-code) =]; + }[= + + IF (*=* (get "handler-type") "text") =] + + if (! S_ISREG(sb.st_mode)) {[= + IF (. emit-failing-printf) =] + fprintf(stderr, pz_fs_err, EINVAL, strerror(EINVAL), + "not regular file:", pz_fname);[= + ENDIF =] + return [= (. file-fail-exit-code) =]; + }[= + + IF (=* (get "handler-type") "some-text") =] + + if (sb.st_size == 0) {[= + IF (. emit-failing-printf) =] + fprintf(stderr, pz_fs_err, EINVAL, strerror(EINVAL), + "empty file:", pz_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 =](pz_fname);[= + +=* file =][= (tpl-file-line extract-fmt) =] + { + int res; + FILE* fp = fopen(pz_fname, "[= + (shellf "echo '%s' | sed 's/.*-//'" + (get "handler-type")) =]"); + if (fp == NULL) { + fprintf(stderr, pz_fs_err, errno, strerror(errno), "fopen", + pz_fname); + return [= (. file-fail-exit-code) =]; + } + res = [= handler-proc =](pz_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, pz_fname); + exit([=(. nomem-exit-code)=]); + } + + { + char* pz = file_text; + size_t sz = text_size; + int fd = open(pz_fname, O_RDONLY); + int try_ct = 0; + + if (fd < 0) { + fprintf(stderr, pz_fs_err, errno, strerror(errno), "open", + pz_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, pz_fs_err, errno, strerror(errno), "read", + pz_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 =](pz_fname, file_text, text_size); + free(file_text); + return res;[= +ESAC =] +}[= + +ENDIF handler-type exists =][= + +(tpl-file-line extract-fmt) + +=] +/** + * 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 argc argument count + * @param argv argument vector + * @returns program exit code + */ +int +main(int argc, char** argv) +{ + int res = 0; + { + int ct = optionProcess(&[=(. pname)=]Options, argc, argv); + argc -= ct; + argv += ct; + }[= + (if (exist? "main-init") (string-append + "\n " (def-file-line "main-init" extract-fmt) "\n" (get "main-init"))) + + =][= (tpl-file-line extract-fmt) =] + /* + * Input list from command line + */ + if (argc > 0) { + do { + res |= [= (. handler-proc) =](*(argv++)); + } while (--argc > 0); + } + + /* + * 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 { + int in_ct = 0; + size_t pg_size = getpagesize(); + char* buf = malloc(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) { + res |= [= (. handler-proc) =](pz); + in_ct++; + } + } + + if (in_ct == 0) + fputs(_("[=(. prog-name) + =] Warning: no input lines were read\n"), stderr); + free(buf); + }[= + (if (exist? "main-fini") (string-append + "\n " (def-file-line "main-fini" extract-fmt) "\n" (get "main-fini"))) + \=] + + return res; +}[= + +ENDDEF for-each-main + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + 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 make-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 (. make-test-main) =][= + (set! extern-proc-list (string-append extern-proc-list + "optionVersionStderr\n")) =][= + INVOKE emit-testing-defines =][= + ENDIF make-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 make-test-main + (ag-fprintf 0 "\n#endif /* defined(%s) */" main-guard) ) + + undef-proc-names =][= + +ENDDEF decl-callbacks =][= + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =][= + +DEFINE emit-testing-defines + +=] +#if defined([=(tpl-file-line extract-fmt) 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 + +=]. + * + * @param pOptions the [=(. prog-name)=] options data structure + * @param 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, (void *)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([=(. fail-exit-code)=]); +[= + +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 azNames[[= (. 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, azNames, [= + (. 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, azNames, [=(. tmp-ct)=]);[= + + ELSE + +=] + + pOptDesc->optArg.argEnum = + optionEnumerationVal(pOptions, pOptDesc, azNames, [=(. 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 azNames[%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, azNames, [= (. 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 make-test-main + (begin + (set! endif-test-main + (sprintf "\n#endif /* defined(%s) */" main-guard)) + (sprintf "\n\n#if ! defined(%s)" main-guard) +) ) =][= + +INVOKE callback-proc-header =][= + +IF (out-push-new (string-append tmp-dir "/flag-code")) + (exist? "flag-code") =][= + (def-file-line "flag-code" " /* extracted from %s, line %d */\n") + =][= + (join "\n" (stack "flag-code")) =][= + +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 pOptions the AutoOpts option description structure + * @param pOptDesc the descriptor for the "help" (usage) option. + * @noreturn + */ +static void +doUsageOpt(tOptions * pOptions, tOptDesc * pOptDesc) +{[= + IF (exist? "resettable") =] + if ((pOptDesc->fOptState & OPTST_RESET) != 0) + return; +[=ENDIF=][= + IF (exist? "usage-opt") =] + int ex_code = (pOptDesc->optIndex == [= (. INDEX-pfx) =]HELP) + ? [=(. succ-exit-code)=] : AO_EXIT_REQ_USAGE; + [= (string-append usage-proc "(&" pname "Options, ex_code);") =] + /* NOTREACHED */[= + + ELSE =] + [= (string-append usage-proc "(&" pname "Options, " succ-exit-code ");") =] + /* NOTREACHED */ + (void)pOptDesc;[= + ENDIF =] + (void)pOptions; +}[= + +INVOKE define-option-callbacks =][= + +IF (exist? "main") =][= + INVOKE build-main =][= + +ELIF (. make-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 + */ +void +[=(. lc-prefix)=]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, " fail-exit-code ");") =] + /* NOTREACHED */ +} + +/** + * 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 + */ +void +[=(. lc-prefix)=]usage_message(char const * fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + [=(. lc-prefix)=]vusage_message(fmt, ap); + /* NOTREACHED */ + va_end(ap); +} +[= + +ENDIF have usage-message =][= + +IF (exist? "die-code") + +=] +/** + * Print a fatal error message and die + * + * @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 + */ +void +[=(. lc-prefix)=]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); + /* NOTREACHED */ +} + +/** + * Print a fatal error message and die + * + * @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 + */ +void +[=(. lc-prefix)=]die(int exit_code, char const * fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vdie(exit_code, fmt, ap); + /* NOTREACHED */ + va_end(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 + */ +void +[=(. lc-prefix)=]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); + /* NOTREACHED */ +} +[= + +ENDIF die-code =][= + +ENDDEF emit-option-callbacks + +=] diff --git a/autoopts/tpl/rc-sample.tpl b/autoopts/tpl/rc-sample.tpl new file mode 100644 index 0000000..f01d506 --- /dev/null +++ b/autoopts/tpl/rc-sample.tpl @@ -0,0 +1,126 @@ +[= AutoGen5 Template rc + +# Time-stamp: "2011-11-21 04:52:41 bkorb" + +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=] +# [= (define prog-name (get "prog-name")) prog-name =] sample configuration file +#[= + +IF (if (not (exist? "homerc")) + (error "RC file samples only work for rc-optioned programs") ) + + (out-move (string-append "sample-" + (if (exist? "rcfile") (get "rcfile") + (string-append (get "prog-name") "rc") ) + ) ) + + (set-writable) + + (exist? "copyright") +\=] +# This source file is copyrighted and licensed under the following terms: +# +[= + CASE copyright.type =][= + == "" =][= + (sprintf "# %s copyright (c) %s %s - all rights reserved\n# %s" + prog-name (get "copyright.date") (get "copyright.owner") + "licensing type not specified" ) =][= + + = note =][= (prefix "# " (get "copyright.text")) =][= + + * =][= (license-full (get "copyright.type") prog-name "# " + (get "copyright.owner") (get "copyright.date")) =][= + ESAC =][= + +ENDIF "copyright exists" =][= + +FOR flag =][= + + IF (not (or (exist? "documentation") (exist? "no-preset"))) =] + +# [= name =] -- [= descrip =] +# +[= INVOKE emit-description =] +# Example: +# +#[= name =][= + IF (exist? "arg-type") + =] [= (if (exist? "arg-default") (get "arg-default") + (if (exist? "arg-name") (get "arg-name") + (get "arg-type") )) =][= + ENDIF (exist? "arg-type") =][= + + ENDIF (not (exist? "documentation")) =][= + +ENDFOR flag + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-description =][= +(out-push-new) =][= + + IF (~* (get "arg-type") "key|set") +=]This configuration value takes a keyword as its argument[= + + IF (=* (get "arg-type") "set") + +=] list. Each entry turns on or off membership bits. The bits are set by [=# +=]name or numeric value and cleared by preceding the name or number with an [=# +=]exclamation character ('!'). [= + + ELSE + +=]. [= + + ENDIF + +=]The available keywords are: [= + (join ", " (stack "keyword")) =]. [= + + ELIF (=* (get "arg-type") "num") + =]This configuration value takes an integer number as its argument. [= + IF (exist? "scaled") =]That number may be scaled with a single letter [=# +=]suffix: k/K/m/M/g/G/t/T These will multiply the value by powers of [=# +=]1000 (lower case) or 1024 (upper case). [= + ENDIF =][= + + ENDIF =][= + + (define fill-txt (out-pop #t)) + (if (defined? 'fill-txt) + (string-append + + (shell (string-append "while read line + do echo ${line} | fold -s -w76 | sed 's/^/# /' + echo '#' + done <<'__EndOfText__'\n" fill-txt "\n__EndOfText__" )) + + "\n#\n" + ) ) =][= + + (if (exist? "doc") (prefix "# " (get "doc"))) =][= + +ENDDEF emit-description + +=] diff --git a/autoopts/tpl/stdoptions.def b/autoopts/tpl/stdoptions.def new file mode 100644 index 0000000..f04fd5b --- /dev/null +++ b/autoopts/tpl/stdoptions.def @@ -0,0 +1,345 @@ + +/* -*- Mode: Text -*- + * + * Time-stamp: "2013-03-10 07:50:01 bkorb" + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + */ + +#ifndef NO_STD_OPT_DOC +# ifndef HAVE_STD_OPT_DOC +# define HAVE_STD_OPT_DOC 1 +flag = { + name = autoopts_std_options; + documentation; + descrip = <<- _EOF_ + The following options are commonly used and are + provided and supported by AutoOpts + _EOF_; +}; +# endif +#endif + +#ifdef ALL_STD_OPTS +#define BRIEF +#define DEBUG +#define DIRECTORY +#define DRY_RUN +#define INPUT +#define INTERACTIVE +#define OUTPUT +#define QUIET +#define SILENT +#define VERBOSE +#define WARN +#endif + +#ifdef ALL_FLAG_OPTS +#define BRIEF_FLAG +#define DEBUG_FLAG +#define DIRECTORY_FLAG +#define DRY_RUN_FLAG +#define INPUT_FLAG +#define INTERACTIVE_FLAG +#define OUTPUT_FLAG +#define QUIET_FLAG +#define SILENT_FLAG +#define VERBOSE_FLAG +#define WARN_FLAG +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Levels of user entertainment + * + * DEBUG output + */ +#ifdef DEBUG_FLAG +#define DEBUG +#endif + +#ifdef DEBUG +flag = { + name = DEBUG; +#ifdef DEBUG_FLAG + value = D; +#endif +#ifdef DEBUG_LEVEL + arg-type = number; +#endif + descrip = 'run program with debugging info'; + doc = + "Specifying this option will cause the program to display debugging\n" + "information. The information should be helpful to a developer in\n" + "debugging this program."; +}; +#endif + +/* * * * * * * * + * + * VERBOSE output + */ +#ifdef VERBOSE_FLAG +#define VERBOSE 1 +#endif + +#ifdef VERBOSE +flag = { + name = verbose; +#ifdef VERBOSE_FLAG + value = V; +#endif +#ifdef VERBOSE_LEVEL + arg-type = number; +#endif +#ifdef VERBOSE_ENUM + arg-type = keyword; + keyword = silent, quiet, brief, informative, verbose; + arg-default = brief; +#endif + descrip = 'run program with progress info'; + doc = + "Specifying this option will cause the program to display lots of\n" + "progress information. You will be able to see that the program\n" + "is working and it may help you debug your use of the tool."; +}; +#endif + +/* * * * * * * * + * + * WARNING output + */ +#ifdef WARN_LEVEL +#define WARN +#endif +#ifdef WARN_FLAG +#define WARN +#endif + +#ifdef WARN +flag = { + name = warn; +#ifdef WARN_FLAG + value = w; +#endif +#ifdef WARN_LEVEL + arg-type = number; + descrip = 'specify a warning-level threshhold'; + disable = no; + doc = + "Specifying this option will allow you to specify the warning level\n" + "for the messages you want to see. `--no-warn' will disable\n" + "warnings entirely."; +#else + descrip = 'disable warning output'; + doc = + "Specifying this option will cause the program to disable\n" + "warning messages."; +#endif +}; +#endif + +/* * * * * * * * + * + * BRIEF output + */ +#ifdef BRIEF_FLAG +#define BRIEF +#endif + +#ifdef BRIEF +flag = { + name = brief; +#ifdef BRIEF_FLAG + value = b; +#endif + descrip = 'run with minimal info output'; + doc = + "Specifying this option will cause the program to disable most progress\n" + "information."; +}; +#endif + +/* * * * * * * * + * + * QUIET/SILENT output + */ +#ifdef QUIET_FLAG +#define QUIET +#endif +#ifdef SILENT_FLAG +#define SILENT +#endif + +#ifdef QUIET_SILENT +#define QUIET +#define SILENT +#else + +#ifdef QUIET +#ifdef SILENT +#define QUIET_SILENT +#endif +#endif +#endif + +#ifdef QUIET +flag = { + name = quiet; +#ifdef QUIET_FLAG + value = q; +#endif +#ifdef QUIET_SILENT + equivalence = quiet; +#endif +#ifdef QUIET_LEVEL + arg-type = number; +#endif + descrip = 'run without unnecessary output'; + doc = + "Specifying this option will cause the program to disable progress\n" + "information."; +}; +#endif + +#ifdef SILENT +flag = { + name = silent; +#ifdef SILENT_FLAG + value = s; +#endif +#ifdef QUIET_SILENT + equivalence = quiet; +#endif +#ifdef SILENT_LEVEL + arg-type = number; +#endif + descrip = 'run without unnecessary output'; + doc = + "Specifying this option will cause the program to disable progress\n" + "information."; +}; +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Operational mode + * + * DRY_RUN + */ +#ifdef DRY_RUN_FLAG +#define DRY_RUN +#endif + +#ifdef DRY_RUN +flag = { + name = DRY_RUN; +#ifdef DRY_RUN_FLAG + value = R; +#endif + descrip = 'program will make no changes'; + doc = + "Specifying this option will cause the program to run without\n" + "altering any of the normal output files. Instead, it will\n" + "display what it would otherwise have done."; +}; +#endif + +/* * * * * * * * + * + * INTERACTIVE OPERATION + */ +#ifdef INTERACTIVE_FLAG +#define INTERACTIVE +#endif + +#ifdef INTERACTIVE +flag = { + name = interactive; + arg-type = string; +#ifdef INTERACTIVE_FLAG + value = I; /* flag style option character */ +#endif + descrip = "prompt for confirmation"; + doc = + "Specifying this option will cause the program to query you for\n" + "confirmation before doing anything destructive."; +}; +#endif + +/* * * * * * * * + * + * INPUT/OUTPUT files + */ +#ifdef INPUT_FLAG +#define INPUT +#endif + +#ifdef INPUT +flag = { + name = input; + arg-type = string; +#ifdef INPUT_FLAG + value = i; /* flag style option character */ +#endif + descrip = "redirect input from file"; + doc = + "This option specifies the file to use for program input."; +}; +#endif + +#ifdef OUTPUT_FLAG +#define OUTPUT +#endif + +#ifdef OUTPUT +flag = { + name = output; + arg-type = string; +#ifdef OUTPUT_FLAG + value = o; /* flag style option character */ +#endif + descrip = "redirect output to file"; + doc = + "This option specifies the file to use for program output."; +}; +#endif + +/* * * * * * * * + * + * INPUT/OUTPUT directory + */ +#ifdef DIRECTORY_FLAG +#define DIRECTORY +#endif + +#ifdef DIRECTORY +flag = { + name = directory; + arg-type = string; +#ifdef DIRECTORY_FLAG + value = d; /* flag style option character */ +#endif + descrip = "use specified dir for I/O"; + doc = + "This option specifies the directory to use for program input and output."; +}; +#endif diff --git a/autoopts/tpl/strings.tpl b/autoopts/tpl/strings.tpl new file mode 100644 index 0000000..725726e --- /dev/null +++ b/autoopts/tpl/strings.tpl @@ -0,0 +1,174 @@ +[= AutoGen5 Template c -*- Mode: scheme -*- + +## Time-stamp: "2012-08-11 08:20:07 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> + +## Copyright (C) 2011-2012 Bruce Korb, all rights reserved. +## This is free software. It is licensed for use, modification and +## redistribution under the terms of the +## Modified (3 clause) Berkeley Software Distribution License +## <http://www.xfree86.org/3.3.6/COPYRIGHT2.html> +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. Neither the name ``Bruce Korb'' nor the name of any other +## contributor may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## strings IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS +## OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +## ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS +## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +## BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +## WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +## ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=] +[= INCLUDE "tpl-config.tlib" =][= + +(define copy-years (shellf + "year=`sed -n '/Time-stamp[:]/ { + s/[^\"]*\"// + s/-.*// + p + q + }' %s` + test X$year = X2011 || year=2011-$year + echo $year" (tpl-file #t))) \=] +[= INVOKE leader guard = false \=] +[= (out-push-new (string-append (base-name) ".h")) \=] +[= INVOKE leader guard = true =] +[= (out-suspend "header") ;; resume defines + (define string-name (string->c-name! (string-append + (base-name) "-strtable"))) + (string-table-new string-name) + (define max-name-len 0) + (define tmp-str "") + (define tmp-len 0) \=] +#include "[= (. header-file) =]" +[= + +(define str-nm "") +(define str-val "") +(define str-ct 0) +(define name-ln 0) +(define find-ln "") +(define def-fmt "#define %%-%us (%%s)\n#define %%-%us %%d\n") +(out-push-new) ;; temp file for #defines +=][= +FOR string =][= + (set! find-ln (string-length (get "nm" ""))) + (if (> find-ln name-ln) + (set! name-ln find-ln)) =][= +ENDFOR string =][= + +(if (exist? "file-name-string") (begin + (set! str-nm (string-upcase (string-append string-name "_file"))) + (set! find-ln (string-length str-nm)) + (if (> find-ln name-ln) + (set! name-ln find-ln)) + (set! def-fmt (sprintf def-fmt (+ 1 name-ln) (+ 5 name-ln))) + (set! str-ct 1) + (set! str-val (string-append (base-name) ".c")) + (set! tmp-str (string-table-add-ref string-name str-val)) + (ag-fprintf 0 def-fmt str-nm tmp-str + (string-append str-nm "_LEN") (string-length str-val)) + ) + + (set! def-fmt (sprintf def-fmt (+ 1 name-ln) (+ 5 name-ln))) +) + +(set! find-ln "") =][= + +FOR string =][= + (set! str-nm (get "nm")) + (set! str-ct (+ str-ct 1)) + (set! str-val (get "str" str-nm)) + (set! tmp-str (string-table-add-ref string-name str-val)) + (if (exist? "define-line-no") + (set! find-ln (string-append find-ln str-nm " " tmp-str "\n")) ) + (sprintf def-fmt str-nm tmp-str + (string-append str-nm "_LEN") (string-length str-val)) =][= +ENDFOR string =][= + +(out-suspend "defines") +(out-resume "header") ;; real header file +(ag-fprintf 0 + "/*\n * %d strings in %s string table\n */\n" str-ct string-name) +(out-resume "defines") +(emit (shell (string-append "sort <<\\_EOF_\n" + (out-pop #t) "_EOF_"))) ;; #defines now in real header file +(emit "\n") +(out-push-new) +(emit-string-table string-name) +(define str-table (out-pop #t)) +(emit (shell (string-append + "sed -n '/static char const/ { + s/static char/extern char/ + s/ *=.*/;/ + p + q + }' <<\\_EOF_\n" + str-table + "\n_EOF_" +))) +(out-suspend "header") ;; resuming text output +(shell (string-append + "sed 's/^static char const/char const/' <<\\_EOF_\n" + str-table + "\n_EOF_" +)) =][= + +IF (out-resume "header") ;; real header file + (> (string-length find-ln) 0)=] + +[= (out-push-new) =] +while read nm ln +do + test -z "$nm" && break + ln='/\* *'${ln#*+}' \*/' + ln=`[=(. egrep-prog)=] -n "$ln" [= (base-name) =].c` + nm=`echo $nm | tr '[a-z]' '[A-Z]'`_LINENO + printf '#define %-31s %s\n' ${nm} ${ln%%:*} +done <<\_EOF_ +[= (. find-ln) =]_EOF_[= + +(shell (out-pop #t)) =][= +ENDIF find-ln not empty =][= +(if (exist? "header-trailer") + (emit (join "\n\n" "header-trailer")) ) \=] + + +#endif /* [= (. header-guard) =] */ +[= (out-pop) =][= + +DEFINE leader \=][= + (emit (dne " * " "/* ")) + (emit "\n *\n") + (emit (license-full "mbsd" "strings" " * " "Bruce Korb" copy-years)) + (emit "\n */\n") + (if (= (get "guard") "true") + (emit (string-append + (make-header-guard "strings") + (if (exist? "header-leader") (string-append "\n\n" + (join "\n\n" "header-leader") ) "" ) )) + (if (exist? "code-leader") + (emit (string-append "\n\n" (join "\n\n" "code-leader"))) ) + ) +=][= + +ENDDEF leader =][= +(if (exist? "code-trailer") + (emit (join "\n\n" "code-trailer")) ) =] + +/* end of [= (out-name) =] */ diff --git a/autoopts/tpl/texi2man.sh b/autoopts/tpl/texi2man.sh new file mode 100755 index 0000000..0c20cb5 --- /dev/null +++ b/autoopts/tpl/texi2man.sh @@ -0,0 +1,76 @@ +#! /bin/sh + +## texi2man.sh -- script to convert texi-isms to man page isms +## +## Time-stamp: "2012-05-05 08:13:04 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +## This "library" converts texi-isms into man-isms. It gets included +## by the man page template at the point where texi-isms might start appearing +## and then "emit-man-text" is invoked when all the text has been assembled. +## +## Display the command line prototype, +## based only on the argument processing type. +## +## And run the entire output through "sed" to convert texi-isms + +nl=' +' +sedcmd= +bracket='{\([^}]*\)}' +replB='%BACKSLASH%fB\1%BACKSLASH%fP' +replI='%BACKSLASH%fI\1%BACKSLASH%fP' + +for f in code command var env dvn samp option strong +do + sedcmd="${sedcmd}s;@${f}${bracket};${replB};g${nl}" +done + +for f in i file emph kbd key abbr acronym email +do + sedcmd="${sedcmd}s;@${f}${bracket};${replI};g${nl}" +done + +sed \ + -e "${sedcmd}" \ + -e 's;@pxref{\([^}]*\)};see: \1;g' \ + -e 's;@xref{\([^}]*\)};see: \1;g' \ + -e 's/@\([{}]\)/\1/g' \ + -e 's,^\$\*$,.br,' \ + -e '/@ *example/,/@ *end *example/s/^/ /' \ + -e 's/^ *@ *example/.nf/' \ + -e 's/^ *@ *end *example/.fi/' \ + -e '/^ *@ *noindent/d' \ + -e '/^ *@ *enumerate/d' \ + -e 's/^ *@ *end *enumerate/.br/' \ + -e '/^ *@ *table/d' \ + -e 's/^ *@ *end *table/.br/' \ + -e 's/^@item \(.*\)/.sp\ +.IR "\1"/' \ + -e 's/^@item/.sp 1/' \ + -e 's/\*\([a-zA-Z0-9:~=_ -]*\)\*/%BACKSLASH%fB\1%BACKSLASH%fP/g' \ + -e 's/``\([a-zA-Z0-9:~+=_ -]*\)'"''"'/\\(lq\1\\(rq/g' \ + -e "s/^'/\\'/" \ + -e 's/^@\*/.br/' \ + -e 's/ -/ \\-/g' \ + -e 's@^\.in \\-@.in -@' \ + -e 's#%BACKSLASH%#\\#g' diff --git a/autoopts/tpl/texi2mdoc.sh b/autoopts/tpl/texi2mdoc.sh new file mode 100755 index 0000000..6c1325e --- /dev/null +++ b/autoopts/tpl/texi2mdoc.sh @@ -0,0 +1,196 @@ +#! /bin/sh + +## texi2mdoc.sh -- script to convert texi-isms to mdoc-isms +## +## Time-stamp: "2012-05-13 15:45:06 bkorb" +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +## This "library" converts texi-isms into man-isms. It gets included +## by the man page template at the point where texi-isms might start appearing +## and then "emit-man-text" is invoked when all the text has been assembled. +## +## Display the command line prototype, +## based only on the argument processing type. +## +## And run the entire output through "sed" to convert texi-isms + +# /bin/sh on Solaris is too horrible for words +# +case "$0" in +/bin/sh ) test -x /usr/xpg4/bin/sh && exec /usr/xpg4/bin/sh ${1+"$@"} ;; +esac + +parent_pid=$$ +prog=`basename $0 .sh` + +die() { + echo "$prog error: $*" >&2 + kill -TERM $parent_pid + sleep 1 + kill -9 $parent_pid + sleep 1 + exit 1 +} + +do_example() { + echo '.Bd -literal -offset indent' + res=0 + + while : + do + IFS='' read -r line || die "incomplete example" + case "$line" in + '@end '*example ) break ;; + esac + + do_line + done + echo '.Ed' + return $res +} + +do_noindent() { + return 0 +} + +do_enumerate() { + echo '.Bl -enum -compact' + + while : + do + IFS='' read -r line || die "incomplete enumerate" + case "$line" in + '@end '*enumerate ) break ;; + esac + + do_line + done + echo '.El' + + return $res +} + +do_end() { + die "Improper ending: $line" +} + +do_table() { + echo '.Bl -tag -width 8n' + + while : + do + IFS='' read -r line || die "incomplete table" + case "$line" in + '@end '*table ) break ;; + esac + + do_line + done + echo '.El' + + return $res +} + +do_itemize() { + echo '.Bl -bullet -compact' + + while : + do + IFS='' read -r line || die "incomplete itemize" + case "$line" in + '@end '*itemize ) break ;; + esac + + do_line + done + echo '.El' + + return $res +} + +do_item() { + echo "$line" | sed 's/@item/.It/' +} + +do_line() { + case "${line}" in + '@subheading'* ) echo "$line" | sed 's/@subheading/.SS /' ;; + '@*' ) echo .br ;; + '' ) echo .sp ;; + '@'[{}]* ) echo "${line}" | sed 's/@\([{}]\)/\1/g' ;; + '@'* ) + typ=`echo "$line" | egrep '@[a-z]*\{'` + test ${#typ} -gt 0 && echo "$line" && return 0 + typ=`echo "$line" | sed 's/@ *//;s/[^a-z].*//'` + eval do_${typ} || die "do_${typ} failed" + ;; + + * ) + echo "$line" + ;; + esac + return 0 +} + + +nl=' +' +sedcmd= +bracket='{\([^}]*\)}' +replB='%BACKSLASH%fB\1%BACKSLASH%fP' +replI='%BACKSLASH%fI\1%BACKSLASH%fP' + +for f in code command var env dvn samp option strong +do + sedcmd="${sedcmd}s;@${f}${bracket};${replB};g${nl}" +done + +for f in i file emph kbd key abbr acronym email +do + sedcmd="${sedcmd}s;@${f}${bracket};${replI};g${nl}" +done + +fixfont="${sedcmd}"' + s;@pxref{\([^}]*\)};see: \1;g + s;@xref{\([^}]*\)};see: \1;g + s/@\([{@}]\)/\1/g + s,^[@$]\*$,.br, + s/\*\([a-zA-Z0-9:~=_ -]*\)\*/\\fB\1\\fP/g + s/``\([a-zA-Z0-9:~+=_ -]*\)'\'\''/\\(lq\1\\(rq/g + s/\([^\\]\)-/\1\\-/g + s/\([^\\]\)-/\1\\-/g + /^\.Bl /s/ \\-/ -/g + /^\.Bd /s/ \\-/ -/g + /^\.in /s/ \\-/ -/g + s#%BACKSLASH%#\\#g'" + s/^'/\\\\'/ + /^\$/d" +readonly fixfont + +{ + while IFS='' read -r line + do + do_line + done +} | sed "${fixfont}" + +exit 0 diff --git a/autoopts/tpl/tpl-config-tlib.in b/autoopts/tpl/tpl-config-tlib.in new file mode 100644 index 0000000..80006dc --- /dev/null +++ b/autoopts/tpl/tpl-config-tlib.in @@ -0,0 +1,84 @@ +[= Autogen5 Template configuration -*- Mode: scheme -*- =] +[= + +# Time-stamp: "2012-05-12 19:42:14 bkorb" + +# This file contains configure stuff used by various templates. + +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= + +(define ao-version "@AO_CURRENT@:@AO_REVISION@:@AO_AGE@") +(define ao-template-ver "@AO_TEMPLATE_VERSION@") + +(define inst-prefix + (shell "prefix=\"@prefix@\" + echo \"${prefix}\"")) + +(define exec-prefix + (shell "exec_prefix=\"@exec_prefix@\" + echo \"${exec_prefix}\"")) + +(define inst-bin-dir + (shell "bindir=\"@bindir@\" + echo \"${bindir}\"")) + +(define libs + (shell "LIBS=\"@LIBS@\" + echo \"${LIBS}\"")) + +(define inc-dir + (shell "includedir=\"@includedir@\" + echo \"${includedir}\"")) + +(define lib-dir + (shell "libdir=\"@libdir@\" + echo \"${libdir}\"")) + +(define package + (shell "PACKAGE_TARNAME=\"@PACKAGE_TARNAME@\" + echo \"${PACKAGE_TARNAME}\"")) + +(define data-root-dir + (shell "datarootdir=\"@datarootdir@\" + echo \"${datarootdir}\"")) + +(define data-dir + (shell "datadir=\"@datadir@\" + echo \"${datadir}\"")) + +(define grep-prog + (shell "GREP=\"@GREP@\" + echo \"${GREP}\"")) + +(define egrep-prog + (shell "EGREP=\"@EGREP@\" + echo \"${EGREP}\"")) + +(define fgrep-prog + (shell "FGREP=\"@FGREP@\" + echo \"${FGREP}\"")) + +(define top-build-dir (shell "\\cd .. >/dev/null ; pwd")) +(define pkgdatadir (shell "echo \"${datadir}/${package}\"")) +(setenv "SHELL" "@POSIX_SHELL@") +;;; \=] diff --git a/autoopts/tpl/usage-txt.tpl b/autoopts/tpl/usage-txt.tpl new file mode 100644 index 0000000..fad1a0d --- /dev/null +++ b/autoopts/tpl/usage-txt.tpl @@ -0,0 +1,199 @@ +[= AutoGen5 Template + + h pot + +(define time-stamp "2012-02-18 10:10:47") + +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 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 md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + +=][= CASE (suffix) =][= + +== h =][= + +(define ref-list "") +(define cch-ct 0) +(dne " * " "/* ") =] + * + * This file handles all the bookkeeping required for tracking all the little + * tiny strings used by the AutoOpts library. There are [= (count "utxt") =] + * of them. This is not versioned because it is entirely internal to the + * library and accessed by client code only in a very well-controlled way: + * they may substitute translated strings using a procedure that steps through + * all the string pointers. + * +[= (license-full "lgpl" "AutoOpts" " * " "Bruce Korb" (shell "date +1992-%Y")) + =] + */ +[= +(make-header-guard "autoopts") +=] + +#undef cch_t +#define cch_t char const + +/* + * One structure to hold all the pointers to all the stringlets. + */ +typedef struct { + int field_ct;[= +FOR utxt =][= + (if (exist? "ut-type") + (emit (sprintf "\n %-9s utpz_%s;" + (string-append (get "ut-type") "*") + (get "ut-name") )) + (set! cch-ct (+ cch-ct 1)) ) =][= + +ENDFOR utxt =] + cch_t* apz_str[ [= (. cch-ct) =] ]; +} usage_text_t; + +/* + * Declare the global structure with all the pointers to translated + * strings. This is then used by the usage generation procedure. + */ +extern usage_text_t option_usage_text; + +#if defined(AUTOOPTS_INTERNAL) /* DEFINE ALL THE STRINGS = = = = = */ +/* + * Provide a mapping from a short name to fields in this structure. + */[= + +(string-table-new "usage_txt") +(define str-ix 0) +(define const-list "") +(define typed-list "") +(set! cch-ct 0) =][= + +FOR utxt =] +#define z[= (sprintf "%-20s" (get "ut-name")) + =] (option_usage_text.[= + + IF (exist? "ut-type") =]utpz_[= ut-name =][= + (set! typed-list (string-append typed-list "\n" (get "ut-name"))) =][= + ELSE + =][= + (ag-fprintf 0 "apz_str[%3d]" cch-ct) + (set! cch-ct (+ 1 cch-ct)) + =][= + ENDIF =])[= +ENDFOR =] + + /* + * First, set up the strings. Some of these are writable. These are all in + * English. This gets compiled into libopts and is distributed here so that + * xgettext (or equivalents) can extract these strings for translation. + */ +[= +FOR utxt =][= + (if (exist? "ut-type") + (sprintf "\n static %-7s eng_z%s[] = %s;" + (get "ut-type") (get "ut-name") (kr-string (get "ut-text")) + ) + + (begin + (set! str-ix (string-table-add "usage_txt" (get "ut-text"))) + (set! const-list (string-append const-list + (sprintf "usage_txt +%4d\n" str-ix) )) + ) ) + =][= +ENDFOR utxt =][= + +(emit-string-table "usage_txt") + +=] + + /* + * Now, define (and initialize) the structure that contains + * the pointers to all these strings. + * Aren't you glad you don't maintain this by hand? + */ + usage_text_t option_usage_text = { + [= (count "utxt") =], +[= (shell (string-append + "CLexe=${AGexe%/agen5/*}/columns/columns + test -x \"${CLexe}\" || { + CLexe=${AGexe%/autogen}/columns + test -x \"${CLexe}\" || die 'columns program is not findable' + } + ${CLexe} -W84 -I4 --spread=1 -f'eng_z%s,' <<_EOF_" typed-list + "\n_EOF_ + echo ' {' + ${CLexe} -W84 -I6 --spread=1 -S, <<_EOF_\n" const-list + "_EOF_" )) =] + } + }; + +#endif /* DO_TRANSLATIONS */ +#endif /* [= (. header-guard) =] */ +[= + + +== pot + + +\=] +# Automated Option parsing usage text. +# copyright (c) [=`date +1999-%Y`=] by Bruce Korb - all rights reserved +# This file is distributed under the same license as the AutoOpts package. +# Bruce Korb <bkorb@gnu.org> [=`date +%Y`=] +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: autogen [=`echo ${AG_VERSION}`=]\n" +"Report-Msgid-Bugs-To: autogen-users@lists.sourceforge.net\n" +"POT-Creation-Date: [=`date '+%Y-%m-%d %H:%M%z'`=]\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +[= + +FOR utxt + =][= + (set! ref-list (shellf + "list=`grep -n -w z%s *.c [agpo]*.h tpl/opt*.t* | \\ + sed -n 's/\\([^:]*:[^:]*\\):.*/\\1/p'` + echo ${list}" (get "ut-name"))) + + (if (< (string-length ref-list) 2) + (error (sprintf "No references to z%s string" (get "ut-name"))) ) + + (sprintf "\n#: %s\nmsgid %s\n" ref-list (c-string (get "ut-text"))) + + =][= +ENDFOR utxt + +=] +[= + +ESAC + +# Local Variables: +# Mode: text +# time-stamp-format: "\"%:y-%02m-%02d %02H:%02M:%02S\"" +# time-stamp-pattern: "(define time-stamp " +# time-stamp-end: ")" +# End: + +\=] diff --git a/autoopts/tpl/usage.tlib b/autoopts/tpl/usage.tlib new file mode 100644 index 0000000..91bb239 --- /dev/null +++ b/autoopts/tpl/usage.tlib @@ -0,0 +1,207 @@ +[= AutoGen5 Template -*- Mode: shell-script -*- + + help-text + +# This file is part of AutoGen. +# AutoGen Copyright (c) 1992-2012 by Bruce Korb - all rights reserved +# +# AutoGen is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# AutoGen is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + +=][= INCLUDE "tpl-config.tlib" =][= + + ;; This template is designed to emit help text from the current set + ;; of option definitions. + ;; + (make-tmp-dir) + (out-push-new (shellf "echo ${tmp_dir}/%s.def" (get "prog-name"))) + (define emit-def (lambda (vname) + (if (exist? vname) + (sprintf "\n%s = %s;" vname (kr-string (get vname))) ) )) +=] +AutoGen Definitions options.tpl; +no-libopts; +[= + +FOR var IN prog-name prog-title argument + environrc export homerc include + long-opts rcfile version detail + explain package preserve-case prog-desc + opts-ptr gnu-usage reorder-args usage-opt + + version-value help-value more-help-value + save-opts-value usage-value load-opts-value + =][= + (emit-def (get "var")) =][= +ENDFOR var IN .... =][= + +IF (exist? "config-header") =] +config-header = '[= prog-name =]-config.h';[= +ENDIF =][= + +FOR copyright =] +copyright = {[= + + FOR var IN date owner type text author eaddr + =][= + (emit-def (get "var")) =][= + ENDFOR var IN .... =] +};[= +ENDFOR copyright =] + +main = { main-type = shell-process; }; +[= + +FOR flag + +=] +flag = {[= + + FOR var IN name descrip value max min must-set enable disable enabled + ifdef ifndef no-preset settable equivalence documentation + immediate immed-disable also + arg-type arg-optional arg-default default arg-range + stack-arg unstack-arg + =][= + (emit-def (get "var")) =][= + ENDFOR var IN .... =][= + + IF (exist? "keyword") =] + keyword = '[= (join "', '" (stack "keyword")) =]';[= + ENDIF keyword exists =][= + + IF (exist? "flags-must") =] + flags-must = '[= (join "', '" (stack "flags-must")) =]';[= + ENDIF flags-must exists =][= + + IF (exist? "flags-cant") =] + flags-cant = '[= (join "', '" (stack "flags-cant")) =]';[= + ENDIF flags-cant exists =] +};[= + +ENDFOR flag =][= + +(out-pop) +(out-push-new) \=] +# redirect stdout. We see this IFF there is a problem +# +redirect_log=${tmp_dir}/redirected.log +exec 8>&1 9>&2 1> ${redirect_log} 2>&1 +redirect_die() { + exec 2>&9 1>&9 9>&- 8>&- + cat ${redirect_log} + die "$@" +} + +inc_list="-I${PWD} -I[=(. inc-dir)=]" +cfg_ldflags="[=(. libs)=]" +cfg_cflags=${CFLAGS} +exe=${tmp_dir}/[= prog-name =] +[= # START-BUILDTREE-ISMS: + +# The following code is sedded away in install-hook.sh. +# The goal is to remove build tree-isms when installing this file. + +\=] +test -z "${top_builddir}" && ldflags='' || \ + ldflags=`exec 2>/dev/null + find ${top_builddir}/autoopts -name "libopts*.${OBJEXT}" | head -1` + +test -f "${ldflags}" || { + ldflags='[=(. lib-dir)=]/libopts.a' + test -f "${ldflags}" || redirect_die "Cannot locate libopts.a" +} +ldflags="$ldflags ${cfg_ldflags}" +test -d "${top_builddir}" && \ + inc_list="-I${top_builddir} -I${top_builddir}/autoopts ${inc_list}" +test -d "${top_srcdir}" && \ + inc_list="-I${top_srcdir}/autoopts ${inc_list}" + +[= # END-BUILDTREE-ISMS the following code is for installed version: + +test -x "${AGexe}" || redirect_die "AGexe is invalid: ${AGexe}" +aocfg=`dirname ${AGexe}`/autoopts-config +test -x "$aocfg" || redirect_die "missing $ag" +ldflags="${cfg_ldflags} `${aocfg} ldflags`" +cfg_cflags="${cfg_cflags} `${aocfg} cflags`" + +# END-INSTALL-ONLY-CODE \=] +[= IF (exist? "config-header") \=] +inc_list="-I${tmp_dir} ${inc_list}" +while : +do + h='[= config-header =]' + test -f "$h" && break + hdr=$h + h=`basename "${hdr}"` + test -f "$h" && break + g=$h + d=`pwd` + + while : + do + d=`dirname $d` + test "X$d" = X/ && \ + redirect_die "cannot locate [= config-header =]" + h="$d/$g" + test -f "$h" && break + h="$d/$hdr" + test -f "$h" && break + done + break +done +cp "${h}" ${exe}-config.h +[= ENDIF \=] +flags="-DTEST_[= (string-upcase! (string->c-name! (get "prog-name"))) + =]_OPTS=1 ${inc_list} ${cfg_cflags}" +cd ${tmp_dir} +${AGexe} -Toptions.tpl [= prog-name =].def || \ + redirect_die "Cannot gen [= prog-name =]" +cd - +${CC:-cc} ${flags} -g -o TMPexe$$ ${exe}.c ${ldflags} || \ + redirect_die cannot compile ${exe}.c +mv -f TMPexe$$ ${exe} +exec 1>&8 2>&9 9>&- 8>&- + +${exe} [= + + (if (== (get "usage-type") "short") + (if (exist? "usage-opt") + (if (exist? "long-opts") + "--usage" + (string-append "-" (get "usage-value" "u")) + ) + "--give-me-short-usage 2>&1 | sed -e '/: illegal option /d'" + ) + (if (exist? "long-opts") + "--help" + (string-append "-" (get "help-value" "?")) + ) ) =] || \ + die "cannot obtain ${exe} help in ${tmp_dir}"[= + +(shell (out-pop #t)) + +=] +[= + +## Local Variables: +## Mode: shell-script +## indent-tabs-mode: nil +## sh-basic-offset: 4 +## sh-indent-after-do: 4 +## sh-indentation: 4 +## sh-indent-for-case-label: 0 +## sh-indent-for-case-alt: 4 +## End: + +# end of usage.tlib \=] diff --git a/autoopts/usage.c b/autoopts/usage.c new file mode 100644 index 0000000..ebdc46a --- /dev/null +++ b/autoopts/usage.c @@ -0,0 +1,1053 @@ + +/* + * \file usage.c + * + * Time-stamp: "2012-03-31 19:19:26 bkorb" + * + * This module implements the default usage procedure for + * Automated Options. It may be overridden, of course. + * + * Sort options: + --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \ + --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \ + --spac=2 --input=usage.c + */ + +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +#define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT) + +/* = = = START-STATIC-FORWARD = = = */ +static inline bool +do_gnu_usage(tOptions * pOpts); + +static inline bool +skip_misuse_usage(tOptions * pOpts); + +static void +print_usage_details(tOptions * opts, int exit_code); + +static void +prt_conflicts(tOptions * pOptions, tOptDesc * pOD); + +static void +prt_one_vendor(tOptions * pOptions, tOptDesc * pOD, + arg_types_t * pAT, char const * usefmt); + +static void +prt_vendor_opts(tOptions * pOpts, char const * pOptTitle); + +static void +prt_extd_usage(tOptions * pOpts, tOptDesc * pOD, + char const * pOptTitle); + +static void +prt_ini_list(char const * const * papz, bool * pInitIntro, + char const * pzRc, char const * pzPN); + +static void +prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT); + +static void +prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT); + +static void +prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle); + +static void +prt_prog_detail(tOptions* pOptions); + +static int +setGnuOptFmts(tOptions* pOpts, tCC** ppT); + +static int +setStdOptFmts(tOptions* pOpts, tCC** ppT); +/* = = = END-STATIC-FORWARD = = = */ + +/* + * NB: no entry may be a prefix of another entry + */ +#define AOFLAG_TABLE \ + _aof_(gnu, OPTPROC_GNUUSAGE ) \ + _aof_(autoopts, ~OPTPROC_GNUUSAGE) \ + _aof_(no_misuse_usage, OPTPROC_MISUSE ) \ + _aof_(misuse_usage, ~OPTPROC_MISUSE ) + +LOCAL void +set_usage_flags(tOptions * opts, char const * flg_txt) +{ + typedef struct { + size_t fnm_len; + uint32_t fnm_mask; + char const * fnm_name; + } ao_flag_names_t; + +# define _aof_(_n, _f) AOUF_ ## _n ## _ID, + typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t; +# undef _aof_ + +# define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID), + typedef enum { AOFLAG_TABLE } ao_flags_t; +# undef _aof_ + +# define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n }, + static ao_flag_names_t const fn_table[AOUF_COUNT] = { + AOFLAG_TABLE + }; +# undef _aof_ + + unsigned int flg = (ao_flags_t)0; + + if (flg_txt == NULL) { + flg_txt = getenv("AUTOOPTS_USAGE"); + if (flg_txt == NULL) return; + } + + flg_txt = SPN_WHITESPACE_CHARS(flg_txt); + if (*flg_txt == NUL) + return; + + for (;;) { + int ix = 0; + ao_flag_names_t const * fnt = fn_table; + + for (;;) { + if (strneqvcmp(flg_txt, fnt->fnm_name, fnt->fnm_len) == 0) + break; + if (++ix >= AOUF_COUNT) + return; + fnt++; + } + + /* + * Make sure we have a full match. Look for whitespace, + * a comma, or a NUL byte. + */ + if (! IS_END_LIST_ENTRY_CHAR(flg_txt[fnt->fnm_len])) + return; + + flg |= 1 << ix; + flg_txt = SPN_WHITESPACE_CHARS(flg_txt + fnt->fnm_len); + + if (*flg_txt == NUL) + break; + + if (*flg_txt == ',') { + /* + * skip the comma and following white space + */ + flg_txt = SPN_WHITESPACE_CHARS(flg_txt + 1); + if (*flg_txt == NUL) + break; + } + } + + { + ao_flag_names_t const * fnm = fn_table; + + while (flg != 0) { + if ((flg & 1) != 0) { + if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0) + opts->fOptSet &= fnm->fnm_mask; + else opts->fOptSet |= fnm->fnm_mask; + } + flg >>= 1; + fnm++; + } + } +} + +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline bool +do_gnu_usage(tOptions * pOpts) +{ + return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? true : false; +} + +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline bool +skip_misuse_usage(tOptions * pOpts) +{ + return (pOpts->fOptSet & OPTPROC_MISUSE) ? true : false; +} + + +/*=export_func optionOnlyUsage + * + * what: Print usage text for just the options + * arg: + tOptions* + pOpts + program options descriptor + + * arg: + int + ex_code + exit code for calling exit(3) + + * + * doc: + * This routine will print only the usage for each option. + * This function may be used when the emitted usage must incorporate + * information not available to AutoOpts. +=*/ +void +optionOnlyUsage(tOptions * pOpts, int ex_code) +{ + char const * pOptTitle = NULL; + + set_usage_flags(pOpts, NULL); + if ((ex_code != EXIT_SUCCESS) && + skip_misuse_usage(pOpts)) + return; + + /* + * Determine which header and which option formatting strings to use + */ + if (do_gnu_usage(pOpts)) + (void)setGnuOptFmts(pOpts, &pOptTitle); + else + (void)setStdOptFmts(pOpts, &pOptTitle); + + prt_opt_usage(pOpts, ex_code, pOptTitle); + + fflush(option_usage_fp); + if (ferror(option_usage_fp) != 0) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } +} + +static void +print_usage_details(tOptions * opts, int exit_code) +{ + { + char const * pOptTitle = NULL; + + /* + * Determine which header and which option formatting strings to use + */ + if (do_gnu_usage(opts)) { + int flen = setGnuOptFmts(opts, &pOptTitle); + sprintf(line_fmt_buf, zFmtFmt, flen); + fputc(NL, option_usage_fp); + } + else { + int flen = setStdOptFmts(opts, &pOptTitle); + sprintf(line_fmt_buf, zFmtFmt, flen); + + /* + * When we exit with EXIT_SUCCESS and the first option is a doc + * option, we do *NOT* want to emit the column headers. + * Otherwise, we do. + */ + if ( (exit_code != EXIT_SUCCESS) + || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) ) + + fputs(pOptTitle, option_usage_fp); + } + + prt_opt_usage(opts, exit_code, pOptTitle); + } + + /* + * Describe the mechanics of denoting the options + */ + switch (opts->fOptSet & OPTPROC_L_N_S) { + case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break; + case OPTPROC_SHORTOPT: break; + case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break; + case 0: fputs(zOptsOnly, option_usage_fp); break; + } + + if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0) + fputs(zNumberOpt, option_usage_fp); + + if ((opts->fOptSet & OPTPROC_REORDER) != 0) + fputs(zReorder, option_usage_fp); + + if (opts->pzExplain != NULL) + fputs(opts->pzExplain, option_usage_fp); + + /* + * IF the user is asking for help (thus exiting with SUCCESS), + * THEN see what additional information we can provide. + */ + if (exit_code == EXIT_SUCCESS) + prt_prog_detail(opts); + + /* + * Give bug notification preference to the packager information + */ + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) + fputs(opts->pzPackager, option_usage_fp); + + else if (opts->pzBugAddr != NULL) + fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr); + + fflush(option_usage_fp); + + if (ferror(option_usage_fp) != 0) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } +} + + +/*=export_func optionUsage + * private: + * + * what: Print usage text + * arg: + tOptions* + pOptions + program options descriptor + + * arg: + int + exitCode + exit code for calling exit(3) + + * + * doc: + * This routine will print usage in both GNU-standard and AutoOpts-expanded + * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will + * over-ride this, providing the value of it is set to either "gnu" or + * "autoopts". This routine will @strong{not} return. + * + * If "exitCode" is "AO_EXIT_REQ_USAGE" (normally 64), then output will to + * to stdout and the actual exit code will be "EXIT_SUCCESS". +=*/ +void +optionUsage(tOptions * pOptions, int usage_exit_code) +{ + int exit_code = (usage_exit_code == AO_EXIT_REQ_USAGE) + ? EXIT_SUCCESS : usage_exit_code; + + displayEnum = false; + + /* + * Paged usage will preset option_usage_fp to an output file. + * If it hasn't already been set, then set it to standard output + * on successful exit (help was requested), otherwise error out. + * + * Test the version before obtaining pzFullUsage or pzShortUsage. + * These fields do not exist before revision 30. + */ + { + char const * pz; + + if (exit_code == EXIT_SUCCESS) { + pz = (pOptions->structVersion >= 30 * 4096) + ? pOptions->pzFullUsage : NULL; + + if (option_usage_fp == NULL) + option_usage_fp = stdout; + } else { + pz = (pOptions->structVersion >= 30 * 4096) + ? pOptions->pzShortUsage : NULL; + + if (option_usage_fp == NULL) + option_usage_fp = stderr; + } + + if (pz != NULL) { + fputs(pz, option_usage_fp); + exit(exit_code); + } + } + + fprintf(option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName); + set_usage_flags(pOptions, NULL); + + if ((exit_code == EXIT_SUCCESS) || + (! skip_misuse_usage(pOptions))) + + print_usage_details(pOptions, usage_exit_code); + + exit(exit_code); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * PER OPTION TYPE USAGE INFORMATION + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * print option conflicts. + * + * @param pOptions the program option descriptor + * @param pOD the option descriptor + * @param pAT names of the option argument types + */ +static void +prt_conflicts(tOptions * pOptions, tOptDesc * pOD) +{ + + fputs(zTabHyp, option_usage_fp); + + /* + * REQUIRED: + */ + if (pOD->pOptMust != NULL) { + const int* pOptNo = pOD->pOptMust; + + fputs(zReqThese, option_usage_fp); + for (;;) { + fprintf(option_usage_fp, zTabout, + pOptions->pOptDesc[*pOptNo].pz_Name); + if (*++pOptNo == NO_EQUIVALENT) + break; + } + + if (pOD->pOptCant != NULL) + fputs(zTabHypAnd, option_usage_fp); + } + + /* + * CONFLICTS: + */ + if (pOD->pOptCant != NULL) { + const int* pOptNo = pOD->pOptCant; + + fputs(zProhib, option_usage_fp); + for (;;) { + fprintf(option_usage_fp, zTabout, + pOptions->pOptDesc[*pOptNo].pz_Name); + if (*++pOptNo == NO_EQUIVALENT) + break; + } + } +} + +/** + * Print the usage information for a single vendor option. + * + * @param pOpts the program option descriptor + * @param pOD the option descriptor + * @param pAT names of the option argument types + */ +static void +prt_one_vendor(tOptions * pOptions, tOptDesc * pOD, + arg_types_t * pAT, char const * usefmt) +{ + prt_preamble(pOptions, pOD, pAT); + + { + char z[ 80 ]; + char const * pzArgType; + + /* + * Determine the argument type string first on its usage, then, + * when the option argument is required, base the type string on the + * argument type. + */ + if (pOD->fOptState & OPTST_ARG_OPTIONAL) { + pzArgType = pAT->pzOpt; + + } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break; + case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break; + case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break; + case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break; + case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break; + case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break; + case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break; + case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break; + case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break; + default: goto bogus_desc; + } + + pzArgType = SPN_WHITESPACE_CHARS(pzArgType); + if (*pzArgType == NUL) + snprintf(z, sizeof(z), "%s", pOD->pz_Name); + else + snprintf(z, sizeof(z), "%s=%s", pOD->pz_Name, pzArgType); + fprintf(option_usage_fp, usefmt, z, pOD->pzText); + + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + displayEnum = (pOD->pOptProc != NULL) ? true : displayEnum; + } + } + + return; + +bogus_desc: + fprintf(stderr, zInvalOptDesc, pOD->pz_Name); + exit(EX_SOFTWARE); +} + +/** + * Print the long options processed with "-W". These options will be the + * ones that do *not* have flag characters. + * + * @param pOptions the program option descriptor + * @param pOD the option descriptor + */ +static void +prt_vendor_opts(tOptions * pOpts, char const * pOptTitle) +{ + static unsigned int const not_vended_mask = + OPTST_NO_USAGE_MASK | OPTST_DOCUMENT; + + static char const vfmtfmt[] = "%%-%us %%s\n"; + char vfmt[sizeof(vfmtfmt)]; + + /* + * Only handle client specified options. The "vendor option" follows + * "presetOptCt", so we won't loop/recurse indefinitely. + */ + int ct = pOpts->presetOptCt; + tOptDesc * pOD = pOpts->pOptDesc; + size_t nmlen = 0; + + fprintf(option_usage_fp, zTabout, zVendOptsAre); + + do { + size_t l; + if ( ((pOD->fOptState & not_vended_mask) != 0) + || IS_GRAPHIC_CHAR(pOD->optValue)) + continue; + + l = strlen(pOD->pz_Name); + if (l > nmlen) nmlen = l; + } while (pOD++, (--ct > 0)); + + sprintf(vfmt, vfmtfmt, (unsigned int)nmlen + 4); + ct = pOpts->presetOptCt; + pOD = pOpts->pOptDesc; + + do { + if ( ((pOD->fOptState & not_vended_mask) != 0) + || IS_GRAPHIC_CHAR(pOD->optValue)) + continue; + + prt_one_vendor(pOpts, pOD, &argTypes, vfmt); + prt_extd_usage(pOpts, pOD, pOptTitle); + + } while (pOD++, (--ct > 0)); +} + +/** + * Print extended usage. Usage/help was requested. + * + * @param pOptions the program option descriptor + * @param pOD the option descriptor + * @param pAT names of the option argument types + */ +static void +prt_extd_usage(tOptions * pOpts, tOptDesc * pOD, + char const * pOptTitle) +{ + if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) != 0) + && (pOD->optActualValue == VENDOR_OPTION_VALUE)) { + prt_vendor_opts(pOpts, pOptTitle); + return; + } + + /* + * IF there are option conflicts or dependencies, + * THEN print them here. + */ + if ( (pOD->pOptMust != NULL) + || (pOD->pOptCant != NULL) ) + prt_conflicts(pOpts, pOD); + + /* + * IF there is a disablement string + * THEN print the disablement info + */ + if (pOD->pz_DisableName != NULL ) + fprintf(option_usage_fp, zDis, pOD->pz_DisableName); + + /* + * Check for argument types that have callbacks with magical properties + */ + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NUMERIC: + /* + * IF the numeric option has a special callback, + * THEN call it, requesting the range or other special info + */ + if ( (pOD->pOptProc != NULL) + && (pOD->pOptProc != optionNumericVal) ) { + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); + } + break; + + case OPARG_TYPE_FILE: + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); + break; + } + + /* + * IF the option defaults to being enabled, + * THEN print that out + */ + if (pOD->fOptState & OPTST_INITENABLED) + fputs(zEnab, option_usage_fp); + + /* + * IF the option is in an equivalence class + * AND not the designated lead + * THEN print equivalence and leave it at that. + */ + if ( (pOD->optEquivIndex != NO_EQUIVALENT) + && (pOD->optEquivIndex != pOD->optActualIndex ) ) { + fprintf(option_usage_fp, zAlt, + pOpts->pOptDesc[ pOD->optEquivIndex ].pz_Name); + return; + } + + /* + * IF this particular option can NOT be preset + * AND some form of presetting IS allowed, + * AND it is not an auto-managed option (e.g. --help, et al.) + * THEN advise that this option may not be preset. + */ + if ( ((pOD->fOptState & OPTST_NO_INIT) != 0) + && ( (pOpts->papzHomeList != NULL) + || (pOpts->pzPROGNAME != NULL) + ) + && (pOD->optIndex < pOpts->presetOptCt) + ) + + fputs(zNoPreset, option_usage_fp); + + /* + * Print the appearance requirements. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) + fputs(zMembers, option_usage_fp); + + else switch (pOD->optMinCt) { + case 1: + case 0: + switch (pOD->optMaxCt) { + case 0: fputs(zPreset, option_usage_fp); break; + case NOLIMIT: fputs(zNoLim, option_usage_fp); break; + case 1: break; + /* + * IF the max is more than one but limited, print "UP TO" message + */ + default: fprintf(option_usage_fp, zUpTo, pOD->optMaxCt); break; + } + break; + + default: + /* + * More than one is required. Print the range. + */ + fprintf(option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt); + } + + if ( NAMED_OPTS(pOpts) + && (pOpts->specOptIdx.default_opt == pOD->optIndex)) + fputs(zDefaultOpt, option_usage_fp); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Figure out where all the initialization files might live. + * This requires translating some environment variables and + * testing to see if a name is a directory or a file. It's + * squishy, but important to tell users how to find these files. + */ +static void +prt_ini_list(char const * const * papz, bool * pInitIntro, + char const * pzRc, char const * pzPN) +{ + char zPath[AG_PATH_MAX+1]; + + if (papz == NULL) + return; + + fputs(zPresetIntro, option_usage_fp); + *pInitIntro = false; + + for (;;) { + char const * pzPath = *(papz++); + char const * pzReal = zPath; + + if (pzPath == NULL) + break; + + /* + * Ignore any invalid paths + */ + if (! optionMakePath(zPath, (int)sizeof(zPath), pzPath, pzPN)) + pzReal = pzPath; + + /* + * Expand paths that are relative to the executable or installation + * directories. Leave alone paths that use environment variables. + */ + else if ((*pzPath == '$') + && ((pzPath[1] == '$') || (pzPath[1] == '@'))) + pzPath = pzReal; + + /* + * Print the name of the "homerc" file. If the "rcfile" name is + * not empty, we may or may not print that, too... + */ + fprintf(option_usage_fp, zPathFmt, pzPath); + if (*pzRc != NUL) { + struct stat sb; + + /* + * IF the "homerc" file is a directory, + * then append the "rcfile" name. + */ + if ((stat(pzReal, &sb) == 0) && S_ISDIR(sb.st_mode)) { + fputc(DIRCH, option_usage_fp); + fputs(pzRc, option_usage_fp); + } + } + + fputc(NL, option_usage_fp); + } +} + + +static void +prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT) +{ + /* + * Flag prefix: IF no flags at all, then omit it. If not printable + * (not allowed for this option), then blank, else print it. + * Follow it with a comma if we are doing GNU usage and long + * opts are to be printed too. + */ + if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0) + fputs(pAT->pzSpc, option_usage_fp); + + else if (! IS_GRAPHIC_CHAR(pOD->optValue)) { + if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + fputc(' ', option_usage_fp); + fputs(pAT->pzNoF, option_usage_fp); + + } else { + fprintf(option_usage_fp, " -%c", pOD->optValue); + if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + fputs(", ", option_usage_fp); + } +} + +/** + * Print the usage information for a single option. + * + * @param pOpts the program option descriptor + * @param pOD the option descriptor + * @param pAT names of the option argument types + */ +static void +prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT) +{ + prt_preamble(pOptions, pOD, pAT); + + { + char z[ 80 ]; + char const * pzArgType; + + /* + * Determine the argument type string first on its usage, then, + * when the option argument is required, base the type string on the + * argument type. + */ + if (pOD->fOptState & OPTST_ARG_OPTIONAL) { + pzArgType = pAT->pzOpt; + + } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break; + case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break; + case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break; + case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break; + case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break; + case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break; + case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break; + case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break; + case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break; + default: goto bogus_desc; + } + + snprintf(z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name, + (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt); + + fprintf(option_usage_fp, line_fmt_buf, z, pOD->pzText); + + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + displayEnum = (pOD->pOptProc != NULL) ? true : displayEnum; + } + } + + return; + +bogus_desc: + fprintf(stderr, zInvalOptDesc, pOD->pz_Name); + exit(EX_SOFTWARE); +} + +/* + * Print out the usage information for just the options. + */ +static void +prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle) +{ + int ct = pOpts->optCt; + int optNo = 0; + tOptDesc * pOD = pOpts->pOptDesc; + int docCt = 0; + + do { + /* + * no usage --> disallowed on command line (OPTST_NO_COMMAND), or + * deprecated -- strongly discouraged (OPTST_DEPRECATED), or + * compiled out of current object code (OPTST_OMITTED) + */ + if ((pOD->fOptState & OPTST_NO_USAGE_MASK) != 0) { + + /* + * IF this is a compiled-out option + * *AND* usage was requested with "omitted-usage" + * *AND* this is NOT abbreviated usage + * THEN display this option. + */ + if ( (pOD->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) + && (pOD->pz_Name != NULL) + && (ex_code == EXIT_SUCCESS)) { + + char const * why_pz = + (pOD->pzText == NULL) ? zDisabledWhy : pOD->pzText; + prt_preamble(pOpts, pOD, &argTypes); + fprintf(option_usage_fp, zDisabledOpt, pOD->pz_Name, why_pz); + } + + continue; + } + + if ((pOD->fOptState & OPTST_DOCUMENT) != 0) { + if (ex_code == EXIT_SUCCESS) { + fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText, + pOptTitle); + docCt++; + } + + continue; + } + + /* Skip name only options when we have a vendor option */ + if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) != 0) + && (! IS_GRAPHIC_CHAR(pOD->optValue))) + continue; + + /* + * IF this is the first auto-opt maintained option + * *AND* we are doing a full help + * *AND* there are documentation options + * *AND* the last one was not a doc option, + * THEN document that the remaining options are not user opts + */ + if ((docCt > 0) && (ex_code == EXIT_SUCCESS)) { + if (pOpts->presetOptCt == optNo) { + if ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) + fprintf(option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle); + + } else if ((ct == 1) && + (pOpts->fOptSet & OPTPROC_VENDOR_OPT)) + fprintf(option_usage_fp, argTypes.pzBrk, zVendIntro, pOptTitle); + } + + prt_one_usage(pOpts, pOD, &argTypes); + + /* + * IF we were invoked because of the --help option, + * THEN print all the extra info + */ + if (ex_code == EXIT_SUCCESS) + prt_extd_usage(pOpts, pOD, pOptTitle); + + } while (pOD++, optNo++, (--ct > 0)); + + fputc(NL, option_usage_fp); +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * PROGRAM DETAILS + */ +static void +prt_prog_detail(tOptions* pOptions) +{ + bool initIntro = true; + + /* + * Display all the places we look for config files + */ + prt_ini_list(pOptions->papzHomeList, &initIntro, + pOptions->pzRcName, pOptions->pzProgPath); + + /* + * Let the user know about environment variable settings + */ + if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) { + if (initIntro) + fputs(zPresetIntro, option_usage_fp); + + fprintf(option_usage_fp, zExamineFmt, pOptions->pzPROGNAME); + } + + /* + * IF we found an enumeration, + * THEN hunt for it again. Call the handler proc with a NULL + * option struct pointer. That tells it to display the keywords. + */ + if (displayEnum) { + int ct = pOptions->optCt; + int optNo = 0; + tOptDesc* pOD = pOptions->pOptDesc; + + fputc(NL, option_usage_fp); + fflush(option_usage_fp); + do { + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); + } + } while (pOD++, optNo++, (--ct > 0)); + } + + /* + * If there is a detail string, now is the time for that. + */ + if (pOptions->pzDetail != NULL) + fputs(pOptions->pzDetail, option_usage_fp); +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * OPTION LINE FORMATTING SETUP + * + * The "OptFmt" formats receive three arguments: + * 1. the type of the option's argument + * 2. the long name of the option + * 3. "YES" or "no ", depending on whether or not the option must appear + * on the command line. + * These formats are used immediately after the option flag (if used) has + * been printed. + * + * Set up the formatting for GNU-style output + */ +static int +setGnuOptFmts(tOptions* pOpts, tCC** ppT) +{ + static char const zOneSpace[] = " "; + int flen = 22; + *ppT = zNoRq_ShrtTtl; + + argTypes.pzStr = zGnuStrArg; + argTypes.pzReq = zOneSpace; + argTypes.pzNum = zGnuNumArg; + argTypes.pzKey = zGnuKeyArg; + argTypes.pzKeyL = zGnuKeyLArg; + argTypes.pzTime = zGnuTimeArg; + argTypes.pzFile = zGnuFileArg; + argTypes.pzBool = zGnuBoolArg; + argTypes.pzNest = zGnuNestArg; + argTypes.pzOpt = zGnuOptArg; + argTypes.pzNo = zOneSpace; + argTypes.pzBrk = zGnuBreak; + argTypes.pzNoF = zSixSpaces; + argTypes.pzSpc = zThreeSpaces; + + switch (pOpts->fOptSet & OPTPROC_L_N_S) { + case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break; + case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break; + case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break; + case OPTPROC_SHORTOPT: + argTypes.pzOptFmt = zShrtGnuOptFmt; + zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' '; + argTypes.pzOpt = " [arg]"; + flen = 8; + break; + } + + return flen; +} + + +/* + * Standard (AutoOpts normal) option line formatting + */ +static int +setStdOptFmts(tOptions* pOpts, tCC** ppT) +{ + int flen = 0; + + argTypes.pzStr = zStdStrArg; + argTypes.pzReq = zStdReqArg; + argTypes.pzNum = zStdNumArg; + argTypes.pzKey = zStdKeyArg; + argTypes.pzKeyL = zStdKeyLArg; + argTypes.pzTime = zStdTimeArg; + argTypes.pzFile = zStdFileArg; + argTypes.pzBool = zStdBoolArg; + argTypes.pzNest = zStdNestArg; + argTypes.pzOpt = zStdOptArg; + argTypes.pzNo = zStdNoArg; + argTypes.pzBrk = zStdBreak; + argTypes.pzNoF = zFiveSpaces; + argTypes.pzSpc = zTwoSpaces; + + switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) { + case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT): + *ppT = zNoRq_ShrtTtl; + argTypes.pzOptFmt = zNrmOptFmt; + flen = 19; + break; + + case OPTPROC_NO_REQ_OPT: + *ppT = zNoRq_NoShrtTtl; + argTypes.pzOptFmt = zNrmOptFmt; + flen = 19; + break; + + case OPTPROC_SHORTOPT: + *ppT = zReq_ShrtTtl; + argTypes.pzOptFmt = zReqOptFmt; + flen = 24; + break; + + case 0: + *ppT = zReq_NoShrtTtl; + argTypes.pzOptFmt = zReqOptFmt; + flen = 24; + } + + return flen; +} + + +/*: + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/usage.c */ diff --git a/autoopts/value-type.c b/autoopts/value-type.c new file mode 100644 index 0000000..ff98c0a --- /dev/null +++ b/autoopts/value-type.c @@ -0,0 +1,123 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ + + +#if 0 /* gperf build options: */ +// %struct-type +// %language=ANSI-C +// %includes +// %global-table +// %omit-struct-type +// %readonly-tables +// %compare-strncmp +// +// %define slot-name vtp_name +// %define hash-function-name value_type_hash +// %define lookup-function-name find_value_type_name +// %define word-array-name value_type_table +// %define initializer-suffix ,VTP_COUNT_KWD +#endif /* gperf build options: */ + +#include "value-type.h" + +typedef struct { + char const * vtp_name; + value_type_enum_t vtp_id; +} value_type_map_t; +#include <string.h> + +/* maximum key range = 20, duplicates = 0 */ + +#ifdef __GNUC__ +#else +#ifdef __cplusplus +#endif +#endif +inline static unsigned int +value_type_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 10, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 5, 23, 23, 5, 0, 0, 23, 15, 23, + 23, 10, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23 + }; + return len + asso_values[(unsigned char)str[2]]; +} + +static const value_type_map_t value_type_table[] = + { + {"",VTP_COUNT_KWD}, {"",VTP_COUNT_KWD}, + {"",VTP_COUNT_KWD}, + {"set", VTP_KWD_SET}, + {"",VTP_COUNT_KWD}, {"",VTP_COUNT_KWD}, + {"nested", VTP_KWD_NESTED}, + {"integer", VTP_KWD_INTEGER}, + {"",VTP_COUNT_KWD}, + {"bool", VTP_KWD_BOOL}, + {"",VTP_COUNT_KWD}, + {"string", VTP_KWD_STRING}, + {"boolean", VTP_KWD_BOOLEAN}, + {"",VTP_COUNT_KWD}, + {"set-membership", VTP_KWD_SET_MEMBERSHIP}, + {"",VTP_COUNT_KWD}, {"",VTP_COUNT_KWD}, + {"keyword", VTP_KWD_KEYWORD}, + {"",VTP_COUNT_KWD}, + {"hierarchy", VTP_KWD_HIERARCHY}, + {"",VTP_COUNT_KWD}, {"",VTP_COUNT_KWD}, + {"invalid", VTP_KWD_INVALID} + }; + +#ifdef __GNUC__ +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +static inline const value_type_map_t * +find_value_type_name (register const char *str, register unsigned int len) +{ + if (len <= 14 && len >= 3) + { + register int key = value_type_hash (str, len); + + if (key <= 22 && key >= 0) + { + register const char *s = value_type_table[key].vtp_name; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &value_type_table[key]; + } + } + return 0; +} + + +value_type_enum_t +find_value_type_id(char const * str, unsigned int len) +{ + const value_type_map_t * p = + find_value_type_name(str, len); + return (p == 0) ? VTP_KWD_INVALID : p->vtp_id; +} diff --git a/autoopts/value-type.h b/autoopts/value-type.h new file mode 100644 index 0000000..70ff91a --- /dev/null +++ b/autoopts/value-type.h @@ -0,0 +1,25 @@ +/* + * Generated header for gperf generated source Sat Aug 11 09:41:14 PDT 2012 + * This file enumerates the list of names and declares the + * procedure for mapping string names to the enum value. + */ +#ifndef AUTOOPTS_VALUE_TYPE_H_GUARD +#define AUTOOPTS_VALUE_TYPE_H_GUARD 1 + +typedef enum { + VTP_KWD_INVALID, + VTP_KWD_STRING, + VTP_KWD_INTEGER, + VTP_KWD_BOOLEAN, + VTP_KWD_BOOL, + VTP_KWD_KEYWORD, + VTP_KWD_SET, + VTP_KWD_SET_MEMBERSHIP, + VTP_KWD_NESTED, + VTP_KWD_HIERARCHY, + VTP_COUNT_KWD +} value_type_enum_t; + +extern value_type_enum_t +find_value_type_id(char const * str, unsigned int len); +#endif /* AUTOOPTS_VALUE_TYPE_H_GUARD */ diff --git a/autoopts/version.c b/autoopts/version.c new file mode 100644 index 0000000..e91d4ec --- /dev/null +++ b/autoopts/version.c @@ -0,0 +1,214 @@ + +/* + * Time-stamp: "2012-08-11 08:41:53 bkorb" + * + * This module implements the default usage procedure for + * Automated Options. It may be overridden, of course. + */ + +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2012 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 md5sums: + * + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd + */ + +/*=export_func optionVersion + * + * what: return the compiled AutoOpts version number + * ret_type: char const* + * ret_desc: the version string in constant memory + * doc: + * Returns the full version string compiled into the library. + * The returned string cannot be modified. +=*/ +char const* +optionVersion(void) +{ + static char const zVersion[] = + STR(AO_CURRENT.AO_REVISION); + + return zVersion; +} + +/** + * Select among various ways to emit version information. + * + * @param opts the option descriptor + * @param fp the output stream + */ +static void +emit_simple_ver(tOptions * opts, FILE * fp) +{ + /* + * Use the supplied string + */ + if (opts->pzFullVersion != NULL) + fputs(opts->pzFullVersion, fp); + + /* + * Extract the interesting part of the copyright string + */ + else if (opts->pzCopyright != NULL) { + char const * pe = strchr(opts->pzCopyright, NL); + if (pe == NULL) + pe = opts->pzCopyright + strlen(opts->pzCopyright); + fwrite(opts->pzCopyright, 1, pe - opts->pzCopyright, fp); + } + + /* + * Extract the interesting part of the usage title string + */ + else { + char const * pe = strchr(opts->pzUsageTitle, NL); + if (pe == NULL) + pe = opts->pzUsageTitle + strlen(opts->pzUsageTitle); + fwrite(opts->pzUsageTitle, 1, pe - opts->pzUsageTitle, fp); + } + fputc(NL, fp); +} + +static void +emit_copy_ver(tOptions * opts, FILE * fp) +{ + if (opts->pzCopyright != NULL) + fputs(opts->pzCopyright, fp); + + else if (opts->pzFullVersion != NULL) + fputs(opts->pzFullVersion, fp); + + else { + char const * pe = strchr(opts->pzUsageTitle, NL); + if (pe == NULL) + pe = opts->pzUsageTitle + strlen(opts->pzUsageTitle); + fwrite(opts->pzUsageTitle, 1, pe - opts->pzCopyright, fp); + } + + fputc(NL, fp); + + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) + fputs(opts->pzPackager, fp); + + else if (opts->pzBugAddr != NULL) + fprintf(fp, zPlsSendBugs, opts->pzBugAddr); +} + +static void +emit_copy_note(tOptions * opts, FILE * fp) +{ + if (opts->pzCopyright != NULL) { + fputs(opts->pzCopyright, fp); + fputc(NL, fp); + } + + if (opts->pzCopyNotice != NULL) { + fputs(opts->pzCopyNotice, fp); + fputc(NL, fp); + } + + fprintf(fp, zAO_Ver, optionVersion()); + + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) + fputs(opts->pzPackager, fp); + + else if (opts->pzBugAddr != NULL) + fprintf(fp, zPlsSendBugs, opts->pzBugAddr); +} + +static void +print_ver(tOptions * opts, tOptDesc * od, FILE * fp) +{ + char ch; + + if (opts <= OPTPROC_EMIT_LIMIT) + return; + + /* + * IF we have an argument for this option, use it + * Otherwise, default to version only or copyright note, + * depending on whether the layout is GNU standard form or not. + */ + if ( (od->fOptState & OPTST_ARG_OPTIONAL) + && (od->optArg.argString != NULL) + && (od->optArg.argString[0] != NUL)) + + ch = od->optArg.argString[0]; + + else { + set_usage_flags(opts, NULL); + ch = (opts->fOptSet & OPTPROC_GNUUSAGE) ? 'c' : 'v'; + } + + switch (ch) { + case NUL: /* arg provided, but empty */ + case 'v': case 'V': emit_simple_ver(opts, fp); break; + case 'c': case 'C': emit_copy_ver( opts, fp); break; + case 'n': case 'N': emit_copy_note( opts, fp); break; + + default: + fprintf(stderr, zBadVerArg, ch); + exit(EXIT_FAILURE); + } + + fflush(fp); + if (ferror(fp) != 0) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} + +/*=export_func optionPrintVersion + * private: + * + * what: Print the program version + * arg: + tOptions* + opts + program options descriptor + + * arg: + tOptDesc* + od + the descriptor for this arg + + * + * doc: + * This routine will print the version to stdout. +=*/ +void +optionPrintVersion(tOptions * opts, tOptDesc * od) +{ + print_ver(opts, od, stdout); +} + +/*=export_func optionVersionStderr + * private: + * + * what: Print the program version to stderr + * arg: + tOptions* + opts + program options descriptor + + * arg: + tOptDesc* + od + the descriptor for this arg + + * + * doc: + * This routine will print the version to stderr. +=*/ +void +optionVersionStderr(tOptions * opts, tOptDesc * od) +{ + print_ver(opts, od, stderr); +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/version.c */ diff --git a/autoopts/xat-attribute.c b/autoopts/xat-attribute.c new file mode 100644 index 0000000..db47531 --- /dev/null +++ b/autoopts/xat-attribute.c @@ -0,0 +1,114 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ + + +#if 0 /* gperf build options: */ +// %struct-type +// %language=ANSI-C +// %includes +// %global-table +// %omit-struct-type +// %readonly-tables +// %compare-strncmp +// +// %define slot-name xat_name +// %define hash-function-name xat_attribute_hash +// %define lookup-function-name find_xat_attribute_name +// %define word-array-name xat_attribute_table +// %define initializer-suffix ,XAT_COUNT_KWD +#endif /* gperf build options: */ + +#include "xat-attribute.h" + +typedef struct { + char const * xat_name; + xat_attribute_enum_t xat_id; +} xat_attribute_map_t; +#include <string.h> + +/* maximum key range = 9, duplicates = 0 */ + +#ifdef __GNUC__ +#else +#ifdef __cplusplus +#endif +#endif +inline static unsigned int +xat_attribute_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, + 13, 13, 13, 13, 13, 5, 13, 5, 13, 0, + 13, 13, 13, 13, 13, 13, 0, 0, 13, 0, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13 + }; + return len + asso_values[(unsigned char)str[0]]; +} + +static const xat_attribute_map_t xat_attribute_table[] = + { + {"",XAT_COUNT_KWD}, {"",XAT_COUNT_KWD}, + {"",XAT_COUNT_KWD}, {"",XAT_COUNT_KWD}, + {"type", XAT_KWD_TYPE}, + {"words", XAT_KWD_WORDS}, + {"cooked", XAT_KWD_COOKED}, + {"members", XAT_KWD_MEMBERS}, + {"uncooked", XAT_KWD_UNCOOKED}, + {"keep", XAT_KWD_KEEP}, + {"",XAT_COUNT_KWD}, {"",XAT_COUNT_KWD}, + {"invalid", XAT_KWD_INVALID} + }; + +#ifdef __GNUC__ +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +static inline const xat_attribute_map_t * +find_xat_attribute_name (register const char *str, register unsigned int len) +{ + if (len <= 8 && len >= 4) + { + register int key = xat_attribute_hash (str, len); + + if (key <= 12 && key >= 0) + { + register const char *s = xat_attribute_table[key].xat_name; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &xat_attribute_table[key]; + } + } + return 0; +} + + +xat_attribute_enum_t +find_xat_attribute_id(char const * str, unsigned int len) +{ + const xat_attribute_map_t * p = + find_xat_attribute_name(str, len); + return (p == 0) ? XAT_KWD_INVALID : p->xat_id; +} diff --git a/autoopts/xat-attribute.h b/autoopts/xat-attribute.h new file mode 100644 index 0000000..ac9b595 --- /dev/null +++ b/autoopts/xat-attribute.h @@ -0,0 +1,22 @@ +/* + * Generated header for gperf generated source Sat Aug 11 09:41:14 PDT 2012 + * This file enumerates the list of names and declares the + * procedure for mapping string names to the enum value. + */ +#ifndef AUTOOPTS_XAT_ATTRIBUTE_H_GUARD +#define AUTOOPTS_XAT_ATTRIBUTE_H_GUARD 1 + +typedef enum { + XAT_KWD_INVALID, + XAT_KWD_TYPE, + XAT_KWD_WORDS, + XAT_KWD_MEMBERS, + XAT_KWD_COOKED, + XAT_KWD_UNCOOKED, + XAT_KWD_KEEP, + XAT_COUNT_KWD +} xat_attribute_enum_t; + +extern xat_attribute_enum_t +find_xat_attribute_id(char const * str, unsigned int len); +#endif /* AUTOOPTS_XAT_ATTRIBUTE_H_GUARD */ |